TRX 1 rok pred
rodič
commit
f6874d9d40

+ 35 - 0
PaymentClient/src/main/java/com/zhongshu/payment/client/model/payChannel/SuperPayChannel.java

@@ -0,0 +1,35 @@
+package com.zhongshu.payment.client.model.payChannel;
+
+
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.zhongshu.payment.client.types.PayChannelType;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Map;
+
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "_type")
+@JsonSubTypes({
+        @JsonSubTypes.Type(value = WxPayChannel.class, name = "WxPayChannel"),  // 微信
+        @JsonSubTypes.Type(value = UnionFrictionlessPayChannel.class, name = "UnionFrictionlessPayChannel"), // 银联无感支付
+})
+public abstract class SuperPayChannel {
+
+    //扩展字段
+    @Getter
+    @Setter
+    private Map<String, Object> _other;
+
+    // 支付过期时间 毫秒
+    @Getter
+    private Long payExpireTime = 15 * 60 * 1000L;
+
+    /**
+     * 类型
+     *
+     * @return
+     */
+    public abstract PayChannelType payType();
+
+}

+ 24 - 0
PaymentClient/src/main/java/com/zhongshu/payment/client/model/payChannel/UnionFrictionlessPayChannel.java

@@ -0,0 +1,24 @@
+package com.zhongshu.payment.client.model.payChannel;
+
+import com.zhongshu.payment.client.types.PayChannelType;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+/**
+ * 银联无感支付渠道
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class UnionFrictionlessPayChannel extends SuperPayChannel {
+
+    @Getter
+    private Long payExpireTime = 10 * 60 * 1000L;
+
+    @Override
+    public PayChannelType payType() {
+        return PayChannelType.UnionFrictionlessPay;
+    }
+}

+ 24 - 0
PaymentClient/src/main/java/com/zhongshu/payment/client/model/payChannel/WxPayChannel.java

@@ -0,0 +1,24 @@
+package com.zhongshu.payment.client.model.payChannel;
+
+import com.zhongshu.payment.client.types.PayChannelType;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+/**
+ * 微信支付渠道
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class WxPayChannel extends SuperPayChannel {
+
+    @Getter
+    private Long payExpireTime = 15 * 60 * 1000L;
+
+    @Override
+    public PayChannelType payType() {
+        return PayChannelType.WeChat;
+    }
+}

+ 29 - 0
PaymentClient/src/main/java/com/zhongshu/payment/client/types/PayChannelType.java

@@ -0,0 +1,29 @@
+package com.zhongshu.payment.client.types;
+
+import com.zhongshu.payment.client.model.payChannel.SuperPayChannel;
+import com.zhongshu.payment.client.model.payChannel.UnionFrictionlessPayChannel;
+import com.zhongshu.payment.client.model.payChannel.WxPayChannel;
+import lombok.Getter;
+
+/**
+ *
+ */
+public enum PayChannelType {
+
+    WeChat("微信支付", WxPayChannel.class),// 微信支付
+    UnionFrictionlessPay("银联无感支付", UnionFrictionlessPayChannel.class),// 银联
+    ;
+
+    // 名称
+    private String name;
+
+    // 支付对象
+    @Getter
+    private Class<? extends SuperPayChannel> payChannelConfigClass;
+
+
+    PayChannelType(String name, Class<? extends SuperPayChannel> payChannelConfigClass) {
+        this.name = name;
+        this.payChannelConfigClass = payChannelConfigClass;
+    }
+}

+ 1 - 1
PaymentClient/src/main/java/com/zhongshu/payment/client/types/PaymentType.java

@@ -4,7 +4,7 @@ import lombok.Getter;
 
 public enum PaymentType {
     WeChat("微信"),
-    UnionPay("银联"),
+    UnionFrictionlessPay("银联无感支付"),
 
     ;
 

+ 17 - 0
PaymentServer/src/main/java/com/zhongshu/payment/server/core/service/pay/SuperPayService.java

@@ -0,0 +1,17 @@
+package com.zhongshu.payment.server.core.service.pay;
+
+import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
+import com.zhongshu.card.client.model.payment.paySetting.WxPayConfigModel;
+import com.zhongshu.payment.client.model.PrePayModel;
+import com.zhongshu.payment.client.ret.ResultContent;
+
+/**
+ * @author TRX
+ * @date 2024/8/15
+ */
+public abstract class SuperPayService {
+
+    // 渠道支付下单
+    public abstract ResultContent<PrePayModel> createOrder(PrepayRequest request, WxPayConfigModel configModel);
+
+}

+ 119 - 0
PaymentServer/src/main/java/com/zhongshu/payment/server/core/service/pay/impl/WeChatPayService.java

@@ -0,0 +1,119 @@
+package com.zhongshu.payment.server.core.service.pay.impl;
+
+import com.wechat.pay.java.core.Config;
+import com.wechat.pay.java.core.RSAAutoCertificateConfig;
+import com.wechat.pay.java.core.exception.HttpException;
+import com.wechat.pay.java.core.exception.MalformedMessageException;
+import com.wechat.pay.java.core.exception.ServiceException;
+import com.wechat.pay.java.core.util.NonceUtil;
+import com.wechat.pay.java.core.util.PemUtil;
+import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
+import com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse;
+import com.zhongshu.card.client.model.payment.paySetting.WxPayConfigModel;
+import com.zhongshu.payment.client.model.PrePayModel;
+import com.zhongshu.payment.client.ret.ResultContent;
+import com.zhongshu.payment.server.core.service.pay.SuperPayService;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.io.UnsupportedEncodingException;
+import java.security.PrivateKey;
+import java.security.Signature;
+import java.util.Base64;
+
+/**
+ * @author TRX
+ * @date 2024/8/21
+ */
+@Slf4j
+@Component
+public class WeChatPayService extends SuperPayService {
+
+    public static com.wechat.pay.java.service.payments.jsapi.JsapiService service;
+
+    // 初始化商户配置
+    public static Config RSAAutoCertificateConfig(String mchId, String privateKeyPath, String mchSerialNo, String apiV3Key) {
+        return new RSAAutoCertificateConfig.Builder()
+                .merchantId(mchId)
+                // 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
+                .privateKeyFromPath(privateKeyPath)
+                .merchantSerialNumber(mchSerialNo)
+                .apiV3Key(apiV3Key)
+                .build();
+    }
+
+    /**
+     * 支付下单
+     *
+     * @param request
+     * @param configModel
+     * @return
+     */
+    @Override
+    public ResultContent<PrePayModel> createOrder(PrepayRequest request, WxPayConfigModel configModel) {
+        String privateKeyPath = configModel.getPrivateKeyPath();
+        if (configModel.getPrivateKeyType().equals("local")) {
+            privateKeyPath = Thread.currentThread().getContextClassLoader().getResource("").getPath() + configModel.getPrivateKeyPath();
+        }
+
+        // 初始化商户配置
+        Config config = RSAAutoCertificateConfig(configModel.getMchId(), privateKeyPath, configModel.getMchSerialNo(), configModel.getApiV3Key());
+        // 初始化服务
+        service = new com.wechat.pay.java.service.payments.jsapi.JsapiService.Builder().config(config).build();
+        // ... 调用接口
+        try {
+            // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
+            request.setAppid(configModel.getAppId());
+            request.setMchid(configModel.getMchId());
+            request.setNotifyUrl("https://api.dev.qk.zonelife.cn/paymentserver/wechat/v3/notify/payNotify/" + request.getOutTradeNo());
+//            request.setNotifyUrl(configModel.getNotifyUrl());
+            // 调用接口
+            PrepayResponse response = service.prepay(request);
+
+            PrePayModel prePayModel = new PrePayModel();
+            prePayModel.setNonceStr(NonceUtil.createNonce(10));
+            prePayModel.setPackAge("prepay_id=" + response.getPrepayId());
+            prePayModel.setSignType("RSA");
+            long timeStamp = System.currentTimeMillis() / 1000;
+            prePayModel.setTimeStamp(Long.toString(timeStamp));
+
+            String sign = buildMessage(configModel.getAppId(), timeStamp, prePayModel.getNonceStr(), prePayModel.getPackAge());
+            String signature = sign(privateKeyPath, sign.getBytes("utf-8"));
+            prePayModel.setPaySign(signature);
+            return ResultContent.buildContent(prePayModel);
+        } catch (HttpException e) { // 发送HTTP请求失败
+            // 调用e.getHttpRequest()获取请求打印日志或上报监控,更多方法见HttpException定义
+            log.info("请求失败1:{}", e.getHttpRequest());
+            return ResultContent.buildFail("发送HTTP请求失败");
+        } catch (ServiceException e) { // 服务返回状态小于200或大于等于300,例如500
+            // 调用e.getResponseBody()获取返回体打印日志或上报监控,更多方法见ServiceException定义
+            log.info("请求失败2:{}", e.getResponseBody());
+            return ResultContent.buildFail(e.getErrorMessage());
+        } catch (MalformedMessageException e) { // 服务返回成功,返回体类型不合法,或者解析返回体失败
+            // 调用e.getMessage()获取信息打印日志或上报监控,更多方法见MalformedMessageException定义
+            log.info("请求失败3:{}", e.getMessage());
+            return ResultContent.buildFail("服务返回成功,返回体类型不合法,或者解析返回体失败");
+        } catch (UnsupportedEncodingException e) {
+            log.info("请求失败4:{}", e.getMessage());
+            return ResultContent.buildFail("编码错误");
+        }
+    }
+
+    @SneakyThrows
+    public String sign(String privateKeyPath, byte[] message) {
+        Signature sign = Signature.getInstance("SHA256withRSA");
+        PrivateKey privateKey = PemUtil.loadPrivateKeyFromPath(privateKeyPath);
+        sign.initSign(privateKey);
+        sign.update(message);
+        return Base64.getEncoder().encodeToString(sign.sign());
+    }
+
+    private String buildMessage(String appid, long timestamp, String nonceStr, String prepayId) {
+        return appid + "\n"
+                + timestamp + "\n"
+                + nonceStr + "\n"
+                + prepayId + "\n";
+    }
+
+}

+ 0 - 31
PaymentServer/src/main/java/com/zhongshu/payment/server/core/service/wxPaymentV3/WxPayConfigService.java

@@ -1,31 +0,0 @@
-package com.zhongshu.payment.server.core.service.wxPaymentV3;
-
-import com.zhongshu.payment.client.model.param.WxPayConfigParam;
-import com.zhongshu.payment.server.core.dao.WxPayConfigDao;
-import com.zhongshu.payment.server.core.domain.wechatPay.WxPayConfig;
-import com.zhongshu.payment.server.core.utils.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-/**
- * 微信支付配置服务
- * @author wjf
- * @date 2024/7/25
- */
-@Service
-public class WxPayConfigService {
-
-    @Autowired
-    WxPayConfigDao wxPayConfigDao;
-
-    /** 创建/修改项目微信支付配置 */
-    public Object update(WxPayConfigParam param){
-        WxPayConfig wxPayConfig = wxPayConfigDao.findByOid(param.getOid());
-        if (wxPayConfig==null){
-            wxPayConfig = new WxPayConfig();
-        }
-        BeanUtils.copyPropertiesWithoutNull(param, wxPayConfig);
-        wxPayConfigDao.save(wxPayConfig);
-        return null;
-    }
-}