TRX 1 jaar geleden
bovenliggende
commit
62e88391ce

+ 41 - 0
PaymentClient/src/main/java/com/zhongshu/payment/client/payModel/unionFrictionlessPay/model/SignParam.java

@@ -0,0 +1,41 @@
+package com.zhongshu.payment.client.payModel.unionFrictionlessPay.model;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * 签约参数
+ *
+ * @author TRX
+ * @date 2024/8/27
+ */
+@Data
+public class SignParam extends UnionSuperParam {
+
+    @Schema(description = "报文请求时间, 格式yyyy-MM-dd HH:mm:ss")
+    private String requestTimestamp;
+
+    @Schema(description = "商户代码 银商商户号")
+    private String mid;
+
+    @Schema(description = "商户签约协议号, 商户生成。在该商户号下唯一")
+    private String contractNo;
+
+    @Schema(description = "协议模板id, 无感(免密极速)产品模板ID,与接入产品对应。")
+    private String planId;
+
+    @Schema(description = "签约结果通知地址, 后台返回商户结果时使用")
+    private String notifyUrl;
+
+    @Schema(description = "过期时间, 交易过期时间,为空则使用系统默认过期时间(30分钟),格式yyyy-MM-ddHH:mm:ss")
+    private String expireTime;
+
+    @Schema(description = "交易发起场景, 01:APP 03:小程序  缺省值:01:APP")
+    private String invokeScene = "03";
+
+    @Schema(description = "商户微信小程序id, 交易发起场景03:小程序,必传用于签约完成/失败/取消后跳转")
+    private String mchntWxMpAppId;
+
+    @Schema(description = "商户微信小程序path, 交易发起场景03:小程序,必传用于签约完成/失败/取消后跳转")
+    private String mchntWxMpPath;
+}

+ 23 - 0
PaymentClient/src/main/java/com/zhongshu/payment/client/payModel/unionFrictionlessPay/model/UnionSuperParam.java

@@ -0,0 +1,23 @@
+package com.zhongshu.payment.client.payModel.unionFrictionlessPay.model;
+
+import lombok.Data;
+
+/**
+ * @author TRX
+ * @date 2024/8/27
+ */
+@Data
+public class UnionSuperParam {
+
+    /**
+     * 签名算法
+     */
+    private final String signType = "SHA256";
+
+
+    /**
+     * 签名
+     */
+    private String sign;
+
+}

+ 39 - 0
PaymentServer/src/main/java/com/zhongshu/payment/server/core/controller/unionFrictionlessPay/FrictionlessController.java

@@ -0,0 +1,39 @@
+package com.zhongshu.payment.server.core.controller.unionFrictionlessPay;
+
+import com.github.microservice.net.ResultContent;
+import com.zhongshu.payment.client.payModel.unionFrictionlessPay.model.SignParam;
+import com.zhongshu.payment.server.core.service.pay.impl.unionFrictionlessPay.UnionFrictionlessPayMainService;
+import com.zhongshu.payment.server.core.service.pay.impl.unionFrictionlessPay.UnionNotifyService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.servlet.http.HttpServletRequest;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+
+/**
+ * 无感支付
+ *
+ * @author TRX
+ * @date 2024/8/26
+ */
+@Slf4j
+@RestController
+@RequestMapping("/unionFrictionless")
+@Tag(name = "无感支付-业务API")
+public class FrictionlessController {
+
+    @Autowired
+    UnionFrictionlessPayMainService unionFrictionlessPayMainService;
+
+    //---------------------------通知 start-----------------------------
+    @Operation(summary = "无感支付开始签约")
+    @PostMapping(value = "sign", consumes = MediaType.APPLICATION_JSON_VALUE)
+    public ResultContent payNotify(@RequestBody @Valid SignParam param) {
+        return unionFrictionlessPayMainService.sign(param);
+    }
+
+}

+ 3 - 1
PaymentServer/src/main/java/com/zhongshu/payment/server/core/controller/unionFrictionlessPay/FrictionlessNotifyController.java

@@ -21,12 +21,14 @@ import org.springframework.web.bind.annotation.RestController;
 @Slf4j
 @RestController
 @RequestMapping("/frictionless/notify")
-@Tag(name = "无感支付-签约通知回调")
+@Tag(name = "无感支付-通知回调")
 public class FrictionlessNotifyController {
 
     @Autowired
     UnionNotifyService unionNotifyService;
 
+
+    //---------------------------通知 start-----------------------------
     @Operation(summary = "商户签约通知回调")
     @PostMapping(value = "payNotify/{outTradeNo}", consumes = MediaType.APPLICATION_JSON_VALUE)
     public void payNotify(HttpServletRequest request, @PathVariable(name = "outTradeNo") String outTradeNo) {

+ 7 - 0
PaymentServer/src/main/java/com/zhongshu/payment/server/core/domain/unionFrictionlessPay/UnionUserOpenInfo.java

@@ -46,5 +46,12 @@ public class UnionUserOpenInfo extends SuperMain {
     @Schema(description = "协议到期时间,格式:yyyy-MM-dd HH:mm:ss")
     private String contractExpiredTime;
 
+    @Schema(description = "签约订单过期时间")
     private Long expiredTime;
+
+    @Schema(description = "签约参数")
+    private Object param;
+
+    @Schema(description = "签约返回参数")
+    private Object result;
 }

+ 19 - 0
PaymentServer/src/main/java/com/zhongshu/payment/server/core/service/pay/impl/unionFrictionlessPay/UnionFrictionlessPayMainService.java

@@ -10,9 +10,12 @@ import com.zhongshu.payment.client.payModel.commn.ClosePayOrderParam;
 import com.zhongshu.payment.client.payModel.commn.CreateOrderParam;
 import com.zhongshu.payment.client.payModel.commn.PayNotifyParam;
 import com.zhongshu.payment.client.payModel.commn.PayOrderParam;
+import com.zhongshu.payment.client.payModel.unionFrictionlessPay.model.SignParam;
 import com.zhongshu.payment.server.core.service.pay.SuperPayService;
 import jakarta.servlet.http.HttpServletRequest;
 import lombok.extern.slf4j.Slf4j;
+import org.checkerframework.checker.units.qual.A;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 /**
@@ -26,6 +29,22 @@ import org.springframework.stereotype.Service;
 @PayAnnotationService(paymentType = PaymentType.UnionFrictionlessPay, remark = "银联无感支付")
 public class UnionFrictionlessPayMainService extends SuperPayService {
 
+    @Autowired
+    UnionRequestService unionRequestService;
+
+    /**
+     * 发起签约
+     *
+     * @param param
+     * @return
+     */
+    public ResultContent sign(SignParam param) {
+        String sign = unionRequestService.signParam(param);
+        log.info("sign: {}", sign);
+
+        return ResultContent.buildSuccess();
+    }
+
     /**
      * 创建支付渠道订单
      *

+ 51 - 0
PaymentServer/src/main/java/com/zhongshu/payment/server/core/service/pay/impl/unionFrictionlessPay/UnionRequestService.java

@@ -1,6 +1,9 @@
 package com.zhongshu.payment.server.core.service.pay.impl.unionFrictionlessPay;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
 import com.github.microservice.core.util.net.apache.HttpClientUtil;
 import com.github.microservice.core.util.net.apache.HttpModel;
 import com.github.microservice.core.util.net.apache.MethodType;
@@ -10,12 +13,20 @@ import com.zhongshu.card.client.model.payment.RequestInfoSaveParam;
 import com.zhongshu.card.client.service.feign.RequestInfoFeignService;
 import com.zhongshu.card.client.type.payment.RequestType;
 import com.zhongshu.payment.client.payModel.unionFrictionlessPay.model.ApiConfParam;
+import com.zhongshu.payment.client.payModel.unionFrictionlessPay.model.UnionSuperParam;
 import com.zhongshu.payment.server.core.service.base.SuperService;
+import com.zhongshu.payment.server.core.service.pay.impl.unionFrictionlessPay.config.UnionPaymentConfig;
+import com.zhongshu.payment.server.core.utils.AesUtils;
+import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.StopWatch;
 
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.TreeMap;
+
 /**
  * 银联无感支付的请求
  *
@@ -74,5 +85,45 @@ public class UnionRequestService extends SuperService {
         return responseModel;
     }
 
+    @SneakyThrows
+    public String signParam(UnionSuperParam param) {
+        JSONObject entries = JSONUtil.parseObj(param);
+        return signByJSONObject(entries);
+    }
+
+    @SneakyThrows
+    public String signByJSONObject(JSONObject entries) {
+        TreeMap<String, Object> map = new TreeMap<>();
+
+        for (String key : entries.keySet()) {
+            if (!ObjectUtil.isEmpty(entries.get(key)) && !"sign".equals(key)) {
+                map.put(key, String.valueOf(entries.get(key)));
+            }
+        }
+
+        StringBuffer signPara = new StringBuffer();//代签名的字符串
+        StringBuffer reqPara = new StringBuffer();// 组织请求参数
+
+        for (String key : map.keySet()) {
+            if (signPara.length() == 0) {
+                signPara.append(key + "=" + map.get(key));
+                reqPara.append(key + "=" + URLEncoder.encode(String.valueOf(map.get(key)), "UTF-8"));
+            } else {
+                Object o = map.get(key);
+                if (o instanceof ArrayList) {
+                    String jsonStr = JSONUtil.toJsonStr(o);
+                    signPara.append("&" + key + "=" + jsonStr);
+                    reqPara.append("&" + key + "=" + URLEncoder.encode(jsonStr, "UTF-8"));
+                } else {
+                    signPara.append("&" + key + "=" + map.get(key));
+                    reqPara.append("&" + key + "=" + URLEncoder.encode(String.valueOf(map.get(key)), "UTF-8"));
+                }
+            }
+        }
+        String sign = AesUtils.signData(signPara.toString() + UnionPaymentConfig.payKey);
+        StringBuffer append = reqPara.append("&sign=" + URLEncoder.encode(sign, "UTF-8"));
+        return append.toString();
+    }
+
 }
 

+ 11 - 0
PaymentServer/src/main/java/com/zhongshu/payment/server/core/service/pay/impl/unionFrictionlessPay/config/UnionPaymentConfig.java

@@ -0,0 +1,11 @@
+package com.zhongshu.payment.server.core.service.pay.impl.unionFrictionlessPay.config;
+
+/**
+ * @author TRX
+ * @date 2024/8/27
+ */
+public class UnionPaymentConfig {
+
+    public static final String payKey = "fcAmtnx7MwismjWWhVKad";
+
+}

+ 21 - 0
PaymentServer/src/main/java/com/zhongshu/payment/server/core/utils/AesUtils.java

@@ -0,0 +1,21 @@
+package com.zhongshu.payment.server.core.utils;
+
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+
+import java.security.MessageDigest;
+
+import static org.apache.tomcat.util.buf.HexUtils.toHexString;
+
+@Slf4j
+public class AesUtils {
+
+    @SneakyThrows
+    public static String signData(String json_data) {
+        MessageDigest md = MessageDigest.getInstance("SHA-256");
+        md.reset();
+        md.update(json_data.getBytes("utf-8"));
+        return toHexString(md.digest());
+    }
+
+}