feat(支持与O2系统进行数据同步):

main
zk 2 weeks ago
parent e6ee95f229
commit ad298e6cc2

@ -1,18 +1,26 @@
package com.currency.appengine.config;
import com.currency.appengine.handler.GlobalInterceptor;
import com.currency.appengine.filter.RepeatedlyReadFilter;
import com.currency.appengine.handler.CustomMethodArgumentResolver;
import com.currency.appengine.handler.GlobalInterceptor;
import com.currency.appengine.handler.SignInterceptor;
import com.currency.appengine.handler.magic.DevInterceptor;
import java.util.List;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.*;
import java.util.List;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
public class WebMvcConfig implements WebMvcConfigurer {
/**
* Interceptor verification token
*
@ -28,9 +36,15 @@ public class WebMvcConfig implements WebMvcConfigurer {
return new DevInterceptor();
}
@Bean
public SignInterceptor signInterceptor() {
return new SignInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(GlobalInterceptor()).addPathPatterns("/**");
registry.addInterceptor(signInterceptor()).addPathPatterns("/open/**");//只拦截open前缀的接口
registry.addInterceptor(DevInterceptor()).addPathPatterns("/swagger-ui.html").addPathPatterns("/magic/**");
}
@ -47,8 +61,9 @@ public class WebMvcConfig implements WebMvcConfigurer {
// .allowedOrigins("*")
.allowedOriginPatterns("*")
.allowCredentials(true)
.allowedMethods("GET","HEAD","POST","PUT","DELETE","OPTIONS")
.maxAge(3600);
.allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
.maxAge(3600)
;
}
/*
@ -69,4 +84,15 @@ public class WebMvcConfig implements WebMvcConfigurer {
registry.addResourceHandler("doc.html").addResourceLocations(
"classpath:knife4j/");
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public FilterRegistrationBean someFilterRegistration()
{
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new RepeatedlyReadFilter());
registration.addUrlPatterns("/*");
registration.setName("repeatableFilter");
registration.setOrder(Ordered.LOWEST_PRECEDENCE);
return registration;
}
}

@ -0,0 +1,46 @@
package com.currency.appengine.controller;
import com.currency.appengine.domain.CustomerReq;
import com.currency.appengine.service.common.CommonServices;
import com.currency.appengine.service.system.CustomerService;
import com.currency.appengine.utils.Result;
import java.util.Map;
import java.util.Objects;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
*
*
*/
@RestController
@RequestMapping("/open")
public class OpenController {
@Autowired
private CustomerService customerService;
@Autowired
private CommonServices commonServices;
@PostMapping("/add")
public Result add(@RequestBody Map<String, Object> obj) {
CustomerReq customerReq = new CustomerReq();
customerReq.setCustomerName(obj.get("name").toString());
if (Objects.nonNull(obj.get("remark"))) {
customerReq.setRemarks(obj.get("remark").toString());
}
if (Objects.nonNull(obj.get("phone"))) {
customerReq.setContactPhone(obj.get("phone").toString());
}
customerReq.setStatus(1);
customerReq.setIsAuto(true);
customerReq.setSettlementCurrency("CNY");
customerReq.setTax("text2");
customerReq.setIsTaxIncluded(1);
customerReq.setCreateBy("超级管理员");
return Result.suc(customerService.AsynCustomer(customerReq));
}
}

@ -3,7 +3,9 @@ package com.currency.appengine.controller;
import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.LineCaptcha;
import com.currency.appengine.annotation.CheckToken;
import com.currency.appengine.domain.CustomerReq;
import com.currency.appengine.domain.system.SysParam;
import com.currency.appengine.service.system.CustomerService;
import com.currency.appengine.service.system.SysMenuService;
import com.currency.appengine.service.system.SysParamService;
import com.currency.appengine.service.system.SysRoleService;
@ -12,16 +14,20 @@ import com.currency.appengine.utils.JsonUtil;
import com.currency.appengine.utils.ReqParamsUtil;
import com.currency.appengine.utils.Result;
import com.currency.appengine.utils.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @date 2021/07/25
@ -29,6 +35,7 @@ import java.util.Map;
@RestController
@RequestMapping("/sys/authority")
public class SystemController {
@Autowired
SysUserService sysUserService;
@Autowired
@ -37,10 +44,12 @@ public class SystemController {
SysRoleService sysRoleService;
@Autowired
SysParamService sysParamService;
@Autowired
CustomerService customerService;
/*
*
* */
*
* */
@RequestMapping("/kaptcha")
public void getKaptchaImage(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpSession session = request.getSession();
@ -64,6 +73,7 @@ public class SystemController {
/**
*
*
* @param params
* @return
*/
@ -82,10 +92,10 @@ public class SystemController {
if (StringUtil.notEmpty(session.getAttribute("KAPTCHA_SESSION_KEY"))) {
String vercode = String.valueOf(params.get("verifycode"));
if (!code.equals(vercode)) {
return Result.fail(-14,"验证码错误");
return Result.fail(-14, "验证码错误");
}
} else {
return Result.fail(-14,"验证码错误");
return Result.fail(-14, "验证码错误");
}
return sysUserService.userLogin(params);
}
@ -164,6 +174,7 @@ public class SystemController {
/**
*
*
* @return
*/
@GetMapping("/role/list/all")
@ -235,12 +246,13 @@ public class SystemController {
/**
*
*
* @return
*/
@GetMapping("/menu/list/all")
@CheckToken
public Result menuListAll() {
return sysMenuService.getRouterListAll();
return sysMenuService.getRouterListAll();
}
@PostMapping("/menu/add")
@ -320,4 +332,13 @@ public class SystemController {
public Result cacheUpdate() {
return sysParamService.cacheUpdate();
}
@PostMapping("/customer/add")
@CheckToken
public Result addCustomer(HttpServletRequest request, @RequestBody CustomerReq customerReq) {
String userId = StringUtil.objectToString(request.getAttribute("openid"));
customerReq.setUserId(userId);
return Result.suc(customerService.addCustomer(customerReq));
}
}

@ -0,0 +1,41 @@
package com.currency.appengine.domain;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
* o1
*
* @author zk
* @date 2024/9/30
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Builder
public class AysnCustomer {
/**
*
*/
private String name;
/**
*
*/
private String phone;
/**
*
*/
private String email;
/**
*
*/
private String remark;
/**
* ()
*/
// private Long createTime;
}

@ -0,0 +1,75 @@
package com.currency.appengine.domain;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
*
*
* @author zk
* @date 2024/10/23
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
public class CustomerReq {
private Long id;
/**
*
*/
private String address;
/**
*
*/
private String contactPerson;
/**
*
*/
private String contactPhone;
/**
*
*/
private String customerCode;
/**
*
*/
private String customerName;
/**
*
*/
private Boolean isAuto;
/**
*
*/
private Integer isTaxIncluded;
/**
*
*/
private String remarks;
/**
*
*/
private String settlementCurrency;
/**
*
*/
private Integer status;
/**
*
*/
private String tax;
/**
*
*/
private String createBy;
/**
* id
*/
private String userId;
}

@ -0,0 +1,21 @@
package com.currency.appengine.filter;//package cn.iocoder.yudao.module.open.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
public class RepeatedlyReadFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
ServletRequest requestWrapper = null;
if(servletRequest instanceof HttpServletRequest) {
requestWrapper = new RequestWrapper((HttpServletRequest) servletRequest);
}
if(requestWrapper == null) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
filterChain.doFilter(requestWrapper, servletResponse);
}
}
}

@ -0,0 +1,85 @@
package com.currency.appengine.filter;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
public class RequestWrapper extends HttpServletRequestWrapper {
private final String body;
public RequestWrapper(HttpServletRequest request) {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
InputStream inputStream = null;
try {
inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
body = stringBuilder.toString();
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() throws IOException {
return byteArrayInputStream.read();
}
};
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
public String getBody() {
return this.body;
}
}

@ -56,7 +56,7 @@ public class GlobalInterceptor implements HandlerInterceptor {
log.info(">>>>>>>Call before request processing (check token) ");
Map<String, String> headers = HttpUtil.getHeadersInfo(request);
String token = headers.get("authorization");;
String token = headers.get("authorization");
if (token == null || token.isEmpty()) {
HttpUtil.returnJson(response, JsonUtil.generate(Result.fail(-2, "result.not_token")));
log.info(">>>>>>>check token fail");

@ -0,0 +1,144 @@
package com.currency.appengine.handler;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.currency.appengine.filter.RequestWrapper;
import com.currency.appengine.utils.IpUtils;
import com.currency.appengine.utils.Result;
import com.currency.appengine.utils.SignUtil;
import java.io.BufferedReader;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
@Slf4j
public class SignInterceptor implements HandlerInterceptor {
private static final String FORMAT = "yyyy-MM-dd HH:mm:ss"; //
private static final String ACCESS_KEY = "access-key";//调用者身份唯一标识
private static final String TIMESTAMP = "time-stamp";//时间戳
private static final String SIGN = "sign";//签名
private static final String NONCE = "nonce";//随机值
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 是否开启
String enable = SpringUtil.getProperty("open.api.enable");
if (!Boolean.parseBoolean(enable)) {
return false;
}
if (checkSign(request, response)) {//签名认证
return HandlerInterceptor.super.preHandle(request, response, handler);
}
return false;
}
/**
*
*
* @param request
* @param response
* @return
* @throws Exception
*/
private boolean checkSign(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("application/json");
response.setCharacterEncoding("utf8");
String ip = IpUtils.getIpAddr(request);
log.info("开放接口 访问时间:{} ,IP:{} ,访问接口: {}", LocalDateTime.now().format(DateTimeFormatter.ofPattern(FORMAT)), ip, request.getRequestURL());
String accessKey = request.getHeader(ACCESS_KEY);
String timestamp = request.getHeader(TIMESTAMP);
String nonce = request.getHeader(NONCE);
String sign = request.getHeader(SIGN);
if (CharSequenceUtil.isBlank(accessKey)) {
response.getWriter().write(JSONUtil.toJsonStr(Result.fail(403, "accessKey无效")));
log.error(
"开放接口请求失败,时间:{} ,IP:{} ,访问接口:{} 错误信息:accessKey无效", LocalDateTime.now().format(DateTimeFormatter.ofPattern(FORMAT)), ip,
request.getRequestURL()
);
return false;
}
if (CharSequenceUtil.isBlank(sign)) {
response.getWriter().write(JSONUtil.toJsonStr(Result.fail(403, "签名无效")));
log.error(
"开放接口请求失败,时间:{},IP:{},访问接口:{}错误信息:签名无效", LocalDateTime.now().format(DateTimeFormatter.ofPattern(FORMAT)), ip,
request.getRequestURL()
);
return false;
}
if (CharSequenceUtil.isBlank(timestamp)) {
response.getWriter().write(JSONUtil.toJsonStr(Result.fail(403, "时间戳无效")));
log.error(
"开放接口请求失败,时间:{},IP:{},访问接口:{}错误信息:时间戳无效", LocalDateTime.now().format(DateTimeFormatter.ofPattern(FORMAT)), ip,
request.getRequestURL()
);
return false;
}
Map<String, Object> hashMap = new HashMap<>();
String queryStrings = request.getQueryString();//获取url后边拼接的参数
if (Objects.nonNull(queryStrings)) {
for (String queryString : queryStrings.split("&")) {
String[] param = queryString.split("=");
if (param.length == 2) {
hashMap.put(param[0], param[1]);
}
}
}
hashMap.put(ACCESS_KEY, accessKey);
hashMap.put(TIMESTAMP, timestamp);
if (CharSequenceUtil.isNotBlank(nonce)) {
hashMap.put(NONCE, nonce);
}
// 判断时间戳是否超时,单位毫秒
String timeOut = SpringUtil.getProperty("open.api.time-out");
String secretKey = SpringUtil.getProperty("open.api.secret-key");
if (CharSequenceUtil.isBlank(secretKey)) {
response.getWriter().write(JSONUtil.toJsonStr(Result.fail(403, "secretKey无效")));
log.error(
"开放接口请求失败,时间:{},IP:{},访问接口:{}错误信息:secretKey无效", LocalDateTime.now().format(DateTimeFormatter.ofPattern(FORMAT)), ip,
request.getRequestURL()
);
return false;
}
if (CharSequenceUtil.isNotBlank(timeOut)) {
long timeOutLong = Long.parseLong(timeOut);
long currentTimeMillis = System.currentTimeMillis();
long timestampLong = Long.parseLong(timestamp);
if (currentTimeMillis - timestampLong > timeOutLong) {
response.getWriter().write(JSONUtil.toJsonStr(Result.fail(403, "时间戳超时")));
log.error(
"开放接口请求失败,时间:{},IP:{},访问接口:{}错误信息:时间戳超时,", LocalDateTime.now().format(DateTimeFormatter.ofPattern(FORMAT)), ip,
request.getRequestURL()
);
return false;
}
}
// 验证签名获取request中的参数并生成签名
// String body = new RequestWrapper(request).getBody();
RequestWrapper wrapper = new RequestWrapper(request);
BufferedReader reader = wrapper.getReader();
String body = reader.lines().reduce("", (a, b) -> a + b);
if (CharSequenceUtil.isNotBlank(body)) {
Map<String, Object> map = JSONUtil.parseObj(body);
hashMap.putAll(map);
}
if (!SignUtil.signValidate(hashMap, secretKey, sign)) {//认证失败
response.getWriter().write(JSONUtil.toJsonStr(Result.fail(403, "认证失败")));
log.error(
"开放接口请求失败,时间:{},IP:{},访问接口:{}错误信息:认证失败", LocalDateTime.now().format(DateTimeFormatter.ofPattern(FORMAT)), ip,
request.getRequestURL()
);
return false;
}
return true;
}
}

@ -0,0 +1,30 @@
package com.currency.appengine.mapper.system;
import com.currency.appengine.domain.CustomerReq;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
/**
* @author zk
* @date 2024/10/23
*/
public interface CustomerMapper {
@Insert(
"insert into mini_customer_info(address,create_by, contact_person, contact_phone, customer_name, is_tax_included, remarks, settlement_currency, status, tax) values(#{address},#{createBy}, #{contactPerson}, #{contactPhone}, #{customerName}, #{isTaxIncluded}, #{remarks}, #{settlementCurrency}, #{status}, #{tax});"
)
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
int insertCustomer(CustomerReq customerReq);
@Select(
"SELECT user_name FROM sys_user WHERE user_id = #{userId}"
)
String selectUserById(String userId);
@Update(
"update mini_customer_info set customer_code = #{customerCode} where id = #{id}"
)
void updateCodeById(CustomerReq customerReq);
}

@ -0,0 +1,18 @@
package com.currency.appengine.service.system;
import com.currency.appengine.domain.CustomerReq;
/**
* @author zk
* @date 2024/10/23
*/
public interface CustomerService {
/**
*
*/
int addCustomer(CustomerReq customerReq);
/**
*
*/
int AsynCustomer(CustomerReq customerReq);
}

@ -0,0 +1,109 @@
package com.currency.appengine.service.system.imp;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.currency.appengine.domain.AysnCustomer;
import com.currency.appengine.domain.CustomerReq;
import com.currency.appengine.mapper.system.CustomerMapper;
import com.currency.appengine.service.common.CommonServices;
import com.currency.appengine.service.system.CustomerService;
import com.currency.appengine.utils.SecurityUtils;
import com.currency.appengine.utils.SignUtil;
import java.util.HashMap;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author zk
* @date 2024/10/23
*/
@Slf4j
@Service
public class CustomerServiceImpl implements CustomerService {
@Autowired
private CustomerMapper customerMapper;
@Autowired
private CommonServices commonServices;
/**
*
*
*/
@Override
public int addCustomer(CustomerReq customerReq) {
if (Boolean.TRUE.equals(customerReq.getIsAuto())){
customerReq.setCustomerCode(commonServices.getCode("CustomerCode", null));
}
String user = customerMapper.selectUserById(customerReq.getUserId());
customerReq.setCreateBy(user);
int i = customerMapper.insertCustomer(customerReq);
customerReq.setCustomerCode(String.valueOf(customerReq.getId()));
customerMapper.updateCodeById(customerReq);
try {
aysnO2(customerReq);
} catch (Exception e) {
log.warn("同步客户信息异常", e);
}
return i;
}
/**
*
*
* @param customerReq
*/
@Override
public int AsynCustomer(CustomerReq customerReq) {
int i = customerMapper.insertCustomer(customerReq);
customerReq.setCustomerCode(String.valueOf(customerReq.getId()));
customerMapper.updateCodeById(customerReq);
return i;
}
/**
* O2
*/
private static void aysnO2(CustomerReq req) {
String property = SpringUtil.getProperty("o2.sync.enabled");
Boolean res = Boolean.valueOf(property);
if (Boolean.TRUE.equals(res)) {
String accessKey = SpringUtil.getProperty("o2.sync.access-key");
String secretKey = SpringUtil.getProperty("o2.sync.secret-key");
String url = SpringUtil.getProperty("o2.sync.create-url");
Map<String, String> map = new HashMap<>();
AysnCustomer customer = new AysnCustomer();
customer.setName(req.getCustomerName());
customer.setPhone(req.getContactPhone());
customer.setRemark(req.getRemarks());
// customer.setCreateTime(crmCustomer.getCreateTime().getTime());
Map<String, Object> toMap = BeanUtil.beanToMap(customer, false, true);
long timestamp = System.currentTimeMillis();
map.put("time-stamp", String.valueOf(timestamp));
map.put("access-key", accessKey);
map.put("tenant-id", "1");
toMap.put("time-stamp", String.valueOf(timestamp));
toMap.put("access-key", accessKey);
String sign = SignUtil.getSign(toMap, secretKey);
map.put("sign", sign);
HttpResponse response = null;
try {
response = HttpRequest.post(url)
.addHeaders(map)
.body(JSONUtil.toJsonStr(customer))
.execute();
} catch (Exception e) {
log.warn("同步O2客户信息异常", e);
return;
}
String body = response.body();
if (response.isOk()) {
log.info("同步O2成功");
}
}
}
}

@ -0,0 +1,224 @@
package com.currency.appengine.utils;
import cn.hutool.core.util.StrUtil;
import java.util.Objects;
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* IP
*
* @author ruoyi
*/
public class IpUtils {
/**
* IP
*
* @param request
* @return IP
*/
public static String getIpAddr(HttpServletRequest request) {
if (request == null) {
return "unknown";
}
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Forwarded-For");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Real-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip);
}
/**
* IP
*
* @param ip IP
* @return
*/
public static boolean internalIp(String ip) {
byte[] addr = textToNumericFormatV4(ip);
return internalIp(addr) || "127.0.0.1".equals(ip);
}
/**
* IP
*
* @param addr byte
* @return
*/
private static boolean internalIp(byte[] addr) {
if (Objects.isNull(addr) || addr.length < 2) {
return true;
}
final byte b0 = addr[0];
final byte b1 = addr[1];
// 10.x.x.x/8
final byte SECTION_1 = 0x0A;
// 172.16.x.x/12
final byte SECTION_2 = (byte) 0xAC;
final byte SECTION_3 = (byte) 0x10;
final byte SECTION_4 = (byte) 0x1F;
// 192.168.x.x/16
final byte SECTION_5 = (byte) 0xC0;
final byte SECTION_6 = (byte) 0xA8;
switch (b0) {
case SECTION_1:
return true;
case SECTION_2:
if (b1 >= SECTION_3 && b1 <= SECTION_4) {
return true;
}
case SECTION_5:
switch (b1) {
case SECTION_6:
return true;
}
default:
return false;
}
}
/**
* IPv4
*
* @param text IPv4
* @return byte
*/
public static byte[] textToNumericFormatV4(String text) {
if (text.length() == 0) {
return null;
}
byte[] bytes = new byte[4];
String[] elements = text.split("\\.", -1);
try {
long l;
int i;
switch (elements.length) {
case 1:
l = Long.parseLong(elements[0]);
if ((l < 0L) || (l > 4294967295L)) {
return null;
}
bytes[0] = (byte) (int) (l >> 24 & 0xFF);
bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
bytes[3] = (byte) (int) (l & 0xFF);
break;
case 2:
l = Integer.parseInt(elements[0]);
if ((l < 0L) || (l > 255L)) {
return null;
}
bytes[0] = (byte) (int) (l & 0xFF);
l = Integer.parseInt(elements[1]);
if ((l < 0L) || (l > 16777215L)) {
return null;
}
bytes[1] = (byte) (int) (l >> 16 & 0xFF);
bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
bytes[3] = (byte) (int) (l & 0xFF);
break;
case 3:
for (i = 0; i < 2; ++i) {
l = Integer.parseInt(elements[i]);
if ((l < 0L) || (l > 255L)) {
return null;
}
bytes[i] = (byte) (int) (l & 0xFF);
}
l = Integer.parseInt(elements[2]);
if ((l < 0L) || (l > 65535L)) {
return null;
}
bytes[2] = (byte) (int) (l >> 8 & 0xFF);
bytes[3] = (byte) (int) (l & 0xFF);
break;
case 4:
for (i = 0; i < 4; ++i) {
l = Integer.parseInt(elements[i]);
if ((l < 0L) || (l > 255L)) {
return null;
}
bytes[i] = (byte) (int) (l & 0xFF);
}
break;
default:
return null;
}
} catch (NumberFormatException e) {
return null;
}
return bytes;
}
/**
* IP
*
* @return IP
*/
public static String getHostIp() {
try {
return InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
}
return "127.0.0.1";
}
/**
*
*
* @return
*/
public static String getHostName() {
try {
return InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
}
return "未知";
}
/**
* unknown IP
*
* @param ip IP
* @return unknown IP
*/
public static String getMultistageReverseProxyIp(String ip) {
// 多级反向代理检测
if (ip != null && ip.indexOf(",") > 0) {
final String[] ips = ip.trim().split(",");
for (String subIp : ips) {
if (!isUnknown(subIp)) {
ip = subIp;
break;
}
}
}
return ip;
}
/**
* HTTP
*
* @param checkString
* @return
*/
public static boolean isUnknown(String checkString) {
return StrUtil.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
}
}

@ -0,0 +1,66 @@
package com.currency.appengine.utils;
import cn.hutool.core.net.URLEncodeUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.crypto.digest.MD5;
import java.util.*;
/**
*
*
* @author zk
*/
public class SignUtil {
/**
*
* 1.
* 4
* <key, value>keyN
* NURLTkey1=value1&key2=value2URLvalueURLURL%E8%e8
* app_keyURLTSkey1=value1&key2=value2&app_key=)
* SMD5MD5
* 2.
* 使
*
* URLvalueURL
*
* @return
*/
public static String getSign(Map<String, Object> map, String secretKey) {
List<Map.Entry<String, Object>> infoIds = new ArrayList<>(map.entrySet());
infoIds.sort(Map.Entry.comparingByKey());
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, Object> m : infoIds) {
if (Objects.nonNull(m.getValue()) && CharSequenceUtil.isNotBlank(m.getValue().toString())) {
sb.append(m.getKey()).append("=").append(URLEncodeUtil.encodeAll(m.getValue().toString())).append("&");
}
}
sb.append("secret-key=").append(secretKey);
return MD5.create().digestHex(sb.toString()).toUpperCase();
}
//获取随机值,防止重复提交,由于使用了时间戳,暂时不使用
public static String getNonceStr(int length) {
//生成随机字符串
String str = "zxcvbnmlkjhgfdsaqwertyuiopQWERTYUIOPASDFGHJKLZXCVBNM1234567890";
Random random = new Random();
StringBuilder randomStr = new StringBuilder();
// 设置生成字符串的长度,用于循环
for (int i = 0; i < length; ++i) {
//从62个的数字或字母中选择
int number = random.nextInt(62);
//将产生的数字通过length次承载到sb中
randomStr.append(str.charAt(number));
}
return randomStr.toString();
}
//签名验证方法
public static boolean signValidate(Map<String, Object> map, String secretKey, String sign) {
String mySign = getSign(map, secretKey);
return mySign.equals(sign);
}
}

@ -1,8 +1,8 @@
spring:
profiles:
# active: local # test 本地
# active: dev # test 测试
active: pro # pro 生产
active: local # test 本地
# active: dev # test 测试
# active: pro # pro 生产
# 通用配置
servlet:
@ -52,3 +52,20 @@ knife4j:
deployfront:
aes-key: hdTQ5SPTs3mp5Xt7ULeaxw==
plaintext: '@mkxy'
# 开放接口超时时间(毫秒级)时间戳
open:
api:
enable: true
time-out: 10000000
secret-key: alLv8CPzZjM6EAgvKqvVjf4kOuTPSmoQTbgK25jz
# o2 同步配置
o2:
sync:
access-key: 8ceeH0H6w4ZIR5nHSDB7
# 密钥
secret-key: alLv8CPzZjM6EAgvKqvVjf4kOuTPSmoQTbgK25jz
# 是否启用同步
enabled: true
# 同步新增o2的客户api地址
create-url: http://127.0.0.1:8182/open/api/add

Loading…
Cancel
Save