wks 2 éve
szülő
commit
d9c5b106e5

+ 2 - 0
src/main/java/com/ydtech/components/TokenInterceptor.java

@@ -89,6 +89,8 @@ public class TokenInterceptor {
 
         notMatchList.add("/sysSys/sysList");//登录2  去除验证
 
+        notMatchList.add("/alipay/test");//登录2  去除验证
+
         return new SaInterceptor(handler -> {
             // 指定一条 match 规则
             SaRouter

+ 32 - 0
src/main/java/com/ydtech/config/properties/UnionPayApiConfigurationProperties.java

@@ -0,0 +1,32 @@
+package com.ydtech.config.properties;
+
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @description: 银联支付 配置文件
+ * @author: wenks
+ * @date: 2024/8/8 16:33
+ **/
+@Data
+@Component
+@ConfigurationProperties(prefix = "unionpay.api")
+public class UnionPayApiConfigurationProperties {
+
+    private String appId;
+
+    private String appKey;
+
+    private String accessTokenUrl;
+
+    private String factorVerifyUrl;
+
+    private String bankCardVerifyUrl;
+
+    private String publicKey;
+
+    private String privateKey;
+
+}

+ 1 - 0
src/main/java/com/ydtech/config/resttemplate/CustomResponseErrorHandler.java

@@ -6,6 +6,7 @@ import org.springframework.http.client.ClientHttpResponse;
 import org.springframework.web.client.ResponseErrorHandler;
 
 import java.io.IOException;
+import java.io.InputStream;
 
 public class CustomResponseErrorHandler implements ResponseErrorHandler {
 

+ 81 - 61
src/main/java/com/ydtech/modules/admin/components/UnionPayRequestApiComponent.java

@@ -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异常,请重试!");
         }
+
     }
+
+
 }

+ 13 - 0
src/main/java/com/ydtech/modules/admin/controller/AlipayController.java

@@ -3,6 +3,7 @@ package com.ydtech.modules.admin.controller;
 import com.alipay.api.AlipayApiException;
 import com.ydtech.core.page.HttpResult;
 import com.ydtech.exception.SystemException;
+import com.ydtech.modules.admin.components.UnionPayRequestApiComponent;
 import com.ydtech.modules.admin.model.SysUser;
 import com.ydtech.modules.admin.model.vo.*;
 import com.ydtech.modules.admin.service.AlipayService;
@@ -15,6 +16,7 @@ import io.swagger.annotations.ApiOperation;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
 @Api(tags = "支付宝业务")
@@ -60,4 +62,15 @@ public class AlipayController extends BaseController {
         AssertionUtils.isStringEmpty(alipayId, "未绑定支付宝");
         return HttpResult.ok();
     }
+
+    @Autowired
+    private UnionPayRequestApiComponent unionPayRequestApiComponent;
+
+    @GetMapping(value = "/test")
+    public HttpResult<Object> test() {
+        unionPayRequestApiComponent.invokeToken();
+        return HttpResult.ok();
+    }
+
+
 }

+ 60 - 0
src/main/java/com/ydtech/modules/admin/utils/UnionPayUtils.java

@@ -0,0 +1,60 @@
+package com.ydtech.modules.admin.utils;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Random;
+
+public class UnionPayUtils {
+
+
+    /**
+     * 生成定长的随机数
+     *
+     * @param length
+     * @return
+     */
+    public static String createData(int length) {
+        StringBuilder sb = new StringBuilder();
+        Random rand = new Random();
+        for (int i = 0; i < length; i++) {
+            sb.append(rand.nextInt(10));
+        }
+        return sb.toString();
+    }
+
+    /**
+     * SHA256算法
+     *
+     * @param value 需要加密的值
+     * @return 加密后的字符
+     */
+    public static String SHA256(String value) {
+        try {
+            // 创建SHA-256哈希算法的MessageDigest对象
+            MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
+
+            // 使用SHA-256计算字符串的哈希值
+            byte[] hash = sha256.digest(value.getBytes(StandardCharsets.UTF_8));
+
+            // 将哈希值转换为十六进制字符串
+            StringBuilder hexString = new StringBuilder();
+            for (byte b : hash) {
+                String hex = Integer.toHexString(0xff & b);
+                if (hex.length() == 1) {
+                    hexString.append('0');
+                }
+                hexString.append(hex);
+            }
+            return hexString.toString();
+        } catch (NoSuchAlgorithmException e) {
+            e.printStackTrace();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return "ERROR";
+    }
+
+
+}

+ 8 - 8
src/main/resources/application-pre.yml

@@ -22,14 +22,14 @@ baidu:
 
 #银联API参数配置
 unionPay:
-  appId: 111
-  appKey: 1111
-  accessTokenUrl: https://test-api-open.chinaums.com/v2/token/acces
-  2FactorVerifyUrl: https://test-api-open.chinaums.com/v1/datacenter/smartverification/encrypted/mobile/2factor/verify
-  bankCardVerifyUrl: https://test-api-open.chinaums.com/v1/datacenter/smartverification/encrypted/bankcard/verify
-  publicKey: 0414bb7e9c3914bb65b85079b1dc6e1ca2a0ee04dd9bb55b2f8d31704a6dec0cca695739e128f9c931330e1c0f493be4d56244236434c9d344c4716ba64a4470ba
-  privateKey:
-
+  api:
+    appId: 111
+    appKey: 1111
+    accessTokenUrl: https://test-api-open.chinaums.com/v2/token/acces
+    factorVerifyUrl: https://test-api-open.chinaums.com/v1/datacenter/smartverification/encrypted/mobile/2factor/verify
+    bankCardVerifyUrl: https://test-api-open.chinaums.com/v1/datacenter/smartverification/encrypted/bankcard/verify
+    publicKey: 0414bb7e9c3914bb65b85079b1dc6e1ca2a0ee04dd9bb55b2f8d31704a6dec0cca695739e128f9c931330e1c0f493be4d56244236434c9d344c4716ba64a4470ba
+    privateKey:
 aly:
   cbit:
     url_pre: http://223.70.186.115:80/CBIT/API/insCBIT

+ 8 - 7
src/main/resources/application-prod.yml

@@ -22,13 +22,14 @@ baidu:
 
 #银联API参数配置
 unionPay:
-  appId: 111
-  appKey: 1111
-  accessTokenUrl: https://test-api-open.chinaums.com/v2/token/acces
-  2FactorVerifyUrl: https://test-api-open.chinaums.com/v1/datacenter/smartverification/encrypted/mobile/2factor/verify
-  bankCardVerifyUrl: https://test-api-open.chinaums.com/v1/datacenter/smartverification/encrypted/bankcard/verify
-  publicKey: 0414bb7e9c3914bb65b85079b1dc6e1ca2a0ee04dd9bb55b2f8d31704a6dec0cca695739e128f9c931330e1c0f493be4d56244236434c9d344c4716ba64a4470ba
-  privateKey:
+  api:
+    appId: 111
+    appKey: 1111
+    accessTokenUrl: https://test-api-open.chinaums.com/v2/token/acces
+    factorVerifyUrl: https://test-api-open.chinaums.com/v1/datacenter/smartverification/encrypted/mobile/2factor/verify
+    bankCardVerifyUrl: https://test-api-open.chinaums.com/v1/datacenter/smartverification/encrypted/bankcard/verify
+    publicKey: 0414bb7e9c3914bb65b85079b1dc6e1ca2a0ee04dd9bb55b2f8d31704a6dec0cca695739e128f9c931330e1c0f493be4d56244236434c9d344c4716ba64a4470ba
+    privateKey:
 
 aly:
   cbit:

+ 8 - 7
src/main/resources/application-test.yml

@@ -24,13 +24,14 @@ baidu:
 
 #银联API参数配置
 unionPay:
-  appId: 111
-  appKey: 1111
-  accessTokenUrl: https://test-api-open.chinaums.com/v2/token/acces
-  2FactorVerifyUrl: https://test-api-open.chinaums.com/v1/datacenter/smartverification/encrypted/mobile/2factor/verify
-  bankCardVerifyUrl: https://test-api-open.chinaums.com/v1/datacenter/smartverification/encrypted/bankcard/verify
-  publicKey: 0414bb7e9c3914bb65b85079b1dc6e1ca2a0ee04dd9bb55b2f8d31704a6dec0cca695739e128f9c931330e1c0f493be4d56244236434c9d344c4716ba64a4470ba
-  privateKey:
+  api:
+    appId: 111
+    appKey: 1111
+    accessTokenUrl: https://test-api-open.chinaums.com/v2/token/acces
+    factorVerifyUrl: https://test-api-open.chinaums.com/v1/datacenter/smartverification/encrypted/mobile/2factor/verify
+    bankCardVerifyUrl: https://test-api-open.chinaums.com/v1/datacenter/smartverification/encrypted/bankcard/verify
+    publicKey: 0414bb7e9c3914bb65b85079b1dc6e1ca2a0ee04dd9bb55b2f8d31704a6dec0cca695739e128f9c931330e1c0f493be4d56244236434c9d344c4716ba64a4470ba
+    privateKey:
 
 aly:
   cbit: