|
|
@@ -1,10 +1,11 @@
|
|
|
package com.ydtech.modules.admin.components;
|
|
|
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
+import com.ydtech.config.properties.UnionPayApiConfigurationProperties;
|
|
|
import com.ydtech.exception.SystemException;
|
|
|
import com.ydtech.modules.admin.components.request.UnionPayRequest;
|
|
|
import com.ydtech.modules.admin.components.response.UnionPayResponse;
|
|
|
-import com.ydtech.utils.HMAC256Uitil;
|
|
|
+import com.ydtech.modules.admin.utils.UnionPayUtils;
|
|
|
import com.ydtech.utils.SM2Utils;
|
|
|
import com.ydtech.utils.StringUtils;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
@@ -12,8 +13,6 @@ import org.redisson.api.RLock;
|
|
|
import org.redisson.api.RedissonClient;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
-import org.springframework.beans.factory.annotation.Autowired;
|
|
|
-import org.springframework.core.env.Environment;
|
|
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
|
|
import org.springframework.http.HttpEntity;
|
|
|
import org.springframework.http.HttpHeaders;
|
|
|
@@ -26,7 +25,10 @@ import java.net.InetAddress;
|
|
|
import java.net.UnknownHostException;
|
|
|
import java.security.InvalidParameterException;
|
|
|
import java.text.SimpleDateFormat;
|
|
|
-import java.util.*;
|
|
|
+import java.util.Base64;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
/**
|
|
|
@@ -37,32 +39,38 @@ import java.util.concurrent.TimeUnit;
|
|
|
public class UnionPayRequestApiComponent {
|
|
|
|
|
|
private final static Logger LOGGER = LoggerFactory.getLogger(UnionPayRequestApiComponent.class);
|
|
|
- @Autowired
|
|
|
- Environment environment;
|
|
|
|
|
|
- @Autowired
|
|
|
- private RedissonClient redissonClient;
|
|
|
- @Autowired
|
|
|
- private StringRedisTemplate redisTemplate;
|
|
|
+ private final UnionPayApiConfigurationProperties unionPayApiConfigurationProperties;
|
|
|
+
|
|
|
+ private final RedissonClient redissonClient;
|
|
|
+
|
|
|
+ private final StringRedisTemplate redisTemplate;
|
|
|
|
|
|
private final RestTemplate restTemplate;
|
|
|
|
|
|
- private final String UNION_PAY_MAP = "unionPay";
|
|
|
- private final String UNION_PAY_ACCESS_TOKEN_KEY = "unionPayAccessToken";
|
|
|
- private final String UNION_PAY_ACCESS_TOKEN_LOCK = "unionPayAccessTokenLock";
|
|
|
- private final int UNION_PAY_LOCK_TIME = 10000;
|
|
|
- private final int UNION_PAY_SLEEP_TIME = 5000;
|
|
|
- private final int RANDOM_MAX = 999999999;
|
|
|
- private final int RANDOM_MIN = 100000000;
|
|
|
+ private final static String UNION_PAY_MAP = "unionPay";
|
|
|
+
|
|
|
+ private final static String UNION_PAY_ACCESS_TOKEN_KEY = "unionPayAccessToken";
|
|
|
+
|
|
|
+ private final static String UNION_PAY_ACCESS_TOKEN_LOCK = "unionPayAccessTokenLock";
|
|
|
+
|
|
|
+ private final static int UNION_PAY_LOCK_TIME = 10000;
|
|
|
+
|
|
|
+ private final static int UNION_PAY_SLEEP_TIME = 5000;
|
|
|
|
|
|
+ private final static int RANDOM_MAX = 999999999;
|
|
|
+
|
|
|
+ private final static int RANDOM_MIN = 100000000;
|
|
|
|
|
|
/**
|
|
|
* 运营商二要素验证接口
|
|
|
+ *
|
|
|
* @param request
|
|
|
*/
|
|
|
public UnionPayResponse twoFactorVerifyRequest(UnionPayRequest request) {
|
|
|
- String url = environment.getProperty("unionPay.2FactorVerifyUrl");
|
|
|
- JSONObject params=new JSONObject();
|
|
|
+ String url = unionPayApiConfigurationProperties.getFactorVerifyUrl();
|
|
|
+
|
|
|
+ JSONObject params = new JSONObject();
|
|
|
if (StringUtils.isBlank(request.getPhoneNo())) {
|
|
|
throw new InvalidParameterException("手机号不允许为空!");
|
|
|
}
|
|
|
@@ -84,11 +92,13 @@ public class UnionPayRequestApiComponent {
|
|
|
|
|
|
/**
|
|
|
* 银行卡验证接口
|
|
|
+ *
|
|
|
* @param request
|
|
|
*/
|
|
|
- public UnionPayResponse bankCardVerifyRequest(UnionPayRequest request) {
|
|
|
- String url = environment.getProperty("unionPay.2FactorVerifyUrl");
|
|
|
- JSONObject params=new JSONObject();
|
|
|
+ public UnionPayResponse bankCardVerifyRequest(UnionPayRequest request) {
|
|
|
+ String url = unionPayApiConfigurationProperties.getFactorVerifyUrl();
|
|
|
+
|
|
|
+ JSONObject params = new JSONObject();
|
|
|
if (StringUtils.isBlank(request.getCardNo())) {
|
|
|
throw new InvalidParameterException("卡号不允许为空!");
|
|
|
}
|
|
|
@@ -114,8 +124,8 @@ public class UnionPayRequestApiComponent {
|
|
|
try {
|
|
|
params.put("sourceIp", InetAddress.getLocalHost().getHostAddress()); // ip
|
|
|
} catch (UnknownHostException e) {
|
|
|
- LOGGER.error("获取ipv4地址异常",e);
|
|
|
- throw new RuntimeException("获取ipv4地址异常:",e);
|
|
|
+ LOGGER.error("获取ipv4地址异常", e);
|
|
|
+ throw new RuntimeException("获取ipv4地址异常:", e);
|
|
|
}
|
|
|
params.put("protocolVersion", ""); // 用户授权协议版本号 //TODO
|
|
|
params.put("protocolNo", ""); // 用户授权协议流水号
|
|
|
@@ -125,52 +135,56 @@ public class UnionPayRequestApiComponent {
|
|
|
|
|
|
/**
|
|
|
* 调用银联接口
|
|
|
- * @param url 地址
|
|
|
+ *
|
|
|
+ * @param url 地址
|
|
|
* @param params 入参
|
|
|
* @return 返参
|
|
|
*/
|
|
|
- private UnionPayResponse commonRequest(String url,JSONObject params) {
|
|
|
+ private UnionPayResponse commonRequest(String url, JSONObject params) {
|
|
|
try {
|
|
|
- String publicKey = environment.getProperty("unionPay.publicKey");
|
|
|
- JSONObject data=new JSONObject();
|
|
|
+ String publicKey = unionPayApiConfigurationProperties.getPublicKey();
|
|
|
+
|
|
|
+ JSONObject data = new JSONObject();
|
|
|
String dataValue = Base64.getEncoder().encodeToString(SM2Utils.encrypt(params.toString(),
|
|
|
publicKey).getBytes());
|
|
|
data.put("data", dataValue);
|
|
|
|
|
|
HttpHeaders httpHeaders = new HttpHeaders();
|
|
|
- httpHeaders.set("Content-Type","application/json;charset=UTF-8");
|
|
|
- httpHeaders.set("Accept","application/json");
|
|
|
- httpHeaders.set("Authorization",getAccessToken());
|
|
|
+ httpHeaders.set("Content-Type", "application/json;charset=UTF-8");
|
|
|
+ httpHeaders.set("Accept", "application/json");
|
|
|
+ httpHeaders.set("Authorization", getAccessToken());
|
|
|
// 请求
|
|
|
HttpEntity<String> httpEntity = new HttpEntity<>(params.toString(), httpHeaders);
|
|
|
ResponseEntity<String> response = restTemplate.postForEntity(url, httpEntity, String.class);
|
|
|
JSONObject resp = JSONObject.parseObject(response.getBody());
|
|
|
|
|
|
if ("20000000".equals(resp.getString("errCode"))) {
|
|
|
- String privateKey = environment.getProperty("unionPay.privateKey");
|
|
|
+ String privateKey = unionPayApiConfigurationProperties.getPrivateKey();
|
|
|
+
|
|
|
String respData = SM2Utils.decrypt(new String(Base64.getDecoder().decode(resp.getString("data"))),
|
|
|
privateKey);
|
|
|
return JSONObject.parseObject(respData, UnionPayResponse.class);
|
|
|
} else {
|
|
|
- throw new SystemException("银联信息验证异常["+resp.getString("errCode")+":"+
|
|
|
- resp.getString("errInfo")+"]");
|
|
|
+ throw new SystemException("银联信息验证异常[" + resp.getString("errCode") + ":" +
|
|
|
+ resp.getString("errInfo") + "]");
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
- LOGGER.error("银联接口调用异常",e);
|
|
|
- throw new RuntimeException("银联接口调用异常:",e);
|
|
|
+ LOGGER.error("银联接口调用异常", e);
|
|
|
+ throw new RuntimeException("银联接口调用异常:", e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取银联token
|
|
|
+ *
|
|
|
* @return
|
|
|
*/
|
|
|
private String getAccessToken() {
|
|
|
|
|
|
- Object token = redisTemplate.opsForHash().get(UNION_PAY_MAP,UNION_PAY_ACCESS_TOKEN_KEY);
|
|
|
+ Object token = redisTemplate.opsForHash().get(UNION_PAY_MAP, UNION_PAY_ACCESS_TOKEN_KEY);
|
|
|
// 缓存中不存在就去请求token
|
|
|
if (!ObjectUtils.isEmpty(token)) {
|
|
|
- return (String)token;
|
|
|
+ return (String) token;
|
|
|
}
|
|
|
|
|
|
// 使用分布式锁 只有一个人可以访问登录
|
|
|
@@ -186,7 +200,7 @@ public class UnionPayRequestApiComponent {
|
|
|
}
|
|
|
|
|
|
} catch (InterruptedException e) {
|
|
|
- LOGGER.error("getAccessToken InterruptedException",e);
|
|
|
+ LOGGER.error("getAccessToken InterruptedException", e);
|
|
|
lock.unlock();
|
|
|
Thread.currentThread().interrupt();
|
|
|
throw new RuntimeException("获取银联Token异常,请重试!");
|
|
|
@@ -196,7 +210,7 @@ public class UnionPayRequestApiComponent {
|
|
|
try {
|
|
|
Thread.sleep(UNION_PAY_SLEEP_TIME);
|
|
|
} catch (InterruptedException e) {
|
|
|
- LOGGER.error("getAccessToken InterruptedException",e);
|
|
|
+ LOGGER.error("getAccessToken InterruptedException", e);
|
|
|
Thread.currentThread().interrupt();
|
|
|
throw new RuntimeException("获取银联Token异常,请重试!");
|
|
|
}
|
|
|
@@ -205,49 +219,55 @@ public class UnionPayRequestApiComponent {
|
|
|
|
|
|
/**
|
|
|
* 调用银联接口获取token
|
|
|
+ *
|
|
|
* @return token
|
|
|
*/
|
|
|
- private String invokeToken() {
|
|
|
- String appId = environment.getProperty("unionPay.appId");
|
|
|
- String appKey = environment.getProperty("unionPay.appKey");
|
|
|
- String accessTokenUrl = environment.getProperty("unionPay.accessTokenUrl");
|
|
|
+ public String invokeToken() {
|
|
|
+ String appId = unionPayApiConfigurationProperties.getAppId();
|
|
|
+ String appKey = unionPayApiConfigurationProperties.getAppKey();
|
|
|
+ String accessTokenUrl = unionPayApiConfigurationProperties.getAccessTokenUrl();
|
|
|
+
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
|
|
|
String timestamp = sdf.format(new Date());
|
|
|
- Random rand = new Random();
|
|
|
- String randNumber = String.valueOf(rand.nextInt(RANDOM_MAX - RANDOM_MIN + 1) + RANDOM_MIN);
|
|
|
+ String randNumber = UnionPayUtils.createData(3);
|
|
|
|
|
|
- String signature = HMAC256Uitil.hmac256(appId+timestamp+randNumber,appKey);//TODO
|
|
|
+ String signature = UnionPayUtils.SHA256(appId + timestamp + randNumber + appKey);
|
|
|
|
|
|
- JSONObject params=new JSONObject();
|
|
|
+ JSONObject params = new JSONObject();
|
|
|
params.put("appId", appId);
|
|
|
params.put("timestamp", timestamp);
|
|
|
params.put("nonce", randNumber);
|
|
|
params.put("signMethod", "SHA256");
|
|
|
params.put("signature", signature);
|
|
|
- try{
|
|
|
- HttpHeaders httpHeaders = new HttpHeaders();
|
|
|
- httpHeaders.set("Content-Type","application/json;charset=UTF-8");
|
|
|
- httpHeaders.set("Accept","application/json");
|
|
|
|
|
|
+ try {
|
|
|
+ HttpHeaders httpHeaders = new HttpHeaders();
|
|
|
+ httpHeaders.set("Content-Type", "application/json;charset=UTF-8");
|
|
|
+ httpHeaders.set("Accept", "application/json");
|
|
|
// 请求
|
|
|
- HttpEntity<String> httpEntity = new HttpEntity<>(params.toString(), httpHeaders);
|
|
|
+ HttpEntity<JSONObject> httpEntity = new HttpEntity<>(params, httpHeaders);
|
|
|
ResponseEntity<String> response = restTemplate.postForEntity(accessTokenUrl, httpEntity, String.class);
|
|
|
JSONObject resp = JSONObject.parseObject(response.getBody());
|
|
|
- if ("20000000".equals(resp.getString("errCode"))) {
|
|
|
+
|
|
|
+ if ("0000".equals(resp.getString("errCode"))) {
|
|
|
String token = resp.getString("accessToken");
|
|
|
int expiresIn = resp.getIntValue("expiresIn"); //失效时间
|
|
|
Map<String, String> map = new HashMap<>();
|
|
|
- map.put(UNION_PAY_MAP, "OPEN-ACCESS-TOKEN AccessToken=\""+token+"\", appId=\""+appId+"\"");
|
|
|
+ map.put(UNION_PAY_MAP, "OPEN-ACCESS-TOKEN AccessToken=\"" + token + "\", appId=\"" + appId + "\"");
|
|
|
redisTemplate.opsForHash().putAll(UNION_PAY_ACCESS_TOKEN_KEY, map);
|
|
|
- redisTemplate.expire(UNION_PAY_ACCESS_TOKEN_KEY, expiresIn-30, TimeUnit.SECONDS);
|
|
|
+ redisTemplate.expire(UNION_PAY_ACCESS_TOKEN_KEY, expiresIn - 30, TimeUnit.SECONDS);
|
|
|
return token;
|
|
|
} else {
|
|
|
- throw new SystemException("获取银联Token异常["+resp.getString("errCode")+":"+
|
|
|
- resp.getString("errInfo")+"]");
|
|
|
+ throw new SystemException("获取银联Token异常[" + resp.getString("errCode") + ":" +
|
|
|
+ resp.getString("errInfo") + "]");
|
|
|
}
|
|
|
- }catch(Exception e){
|
|
|
- LOGGER.error("获取银联Token异常",e);
|
|
|
- throw new RuntimeException("获取银联Token异常,请重试!",e);
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ LOGGER.error("获取银联Token异常", e);
|
|
|
+ throw new SystemException("获取银联Token异常,请重试!");
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
}
|