From 30f13db308bb6c050a4aa44e10ae993dc4fb3bb4 Mon Sep 17 00:00:00 2001
From: xiaoyong931011 <15274802129@163.com>
Date: Fri, 02 Sep 2022 16:09:45 +0800
Subject: [PATCH] 20220822

---
 src/main/java/cc/mrbird/febs/pay/service/impl/UnipayServiceImpl.java           |  130 +++++++++++++++++++++++++
 src/test/java/cc/mrbird/febs/ProfitTest.java                                   |   28 ++++
 src/main/java/cc/mrbird/febs/pay/model/SinglePayDto.java                       |   32 ++++++
 src/main/java/cc/mrbird/febs/pay/util/Md5_Sign.java                            |   27 +++++
 src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallMemberServiceImpl.java |   27 +++++
 5 files changed, 238 insertions(+), 6 deletions(-)

diff --git a/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallMemberServiceImpl.java b/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallMemberServiceImpl.java
index 71684cc..d7d88f3 100644
--- a/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallMemberServiceImpl.java
+++ b/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallMemberServiceImpl.java
@@ -16,6 +16,8 @@
 import cc.mrbird.febs.mall.service.IApiMallMemberWalletService;
 import cc.mrbird.febs.mall.service.IMallMoneyFlowService;
 import cc.mrbird.febs.mall.vo.*;
+import cc.mrbird.febs.pay.model.SinglePayDto;
+import cc.mrbird.febs.pay.service.UnipayService;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
@@ -64,6 +66,8 @@
     private final MallShopApplyMapper mallShopApplyMapper;
 
     private final IMallMoneyFlowService mallMoneyFlowService;
+    private final UnipayService unipayService;
+    private final MallMemberBankMapper mallMemberBankMapper;
 
     @Override
     public IPage<MallMember> getMallMemberList(MallMember mallMember, QueryRequest request) {
@@ -152,6 +156,28 @@
         if(1 != mallMemberWithdraw.getStatus()){
             return new FebsResponse().fail().message("当前状态不是提现中");
         }
+
+        Long wtihdrawTypeId = mallMemberWithdraw.getWtihdrawTypeId();
+        MallMemberBank mallMemberBank = mallMemberBankMapper.selectById(wtihdrawTypeId);
+        /**
+         * 调用汇聚代付
+         */
+        SinglePayDto singlePayDto = new SinglePayDto();
+        singlePayDto.setMerchantOrderNo(mallMemberWithdraw.getWithdrawNo());
+        singlePayDto.setReceiverAccountNoEncBankNo(mallMemberBank.getBankNo());
+        singlePayDto.setReceiverAccountNoEncName(mallMemberBank.getName());
+        singlePayDto.setReceiverAccountType("201");
+        BigDecimal paidAmount = mallMemberWithdraw.getAmount().subtract(mallMemberWithdraw.getAmountFee()).setScale(2, BigDecimal.ROUND_DOWN);
+        singlePayDto.setPaidAmount(paidAmount);
+        singlePayDto.setCurrency("201");
+        singlePayDto.setIsChecked("202");
+        singlePayDto.setPaidDesc("用户提现");
+        singlePayDto.setPaidUse("202");
+        String singlePayRep = unipayService.singlePay(singlePayDto);
+        if(!mallMemberWithdraw.getWithdrawNo().equals(singlePayRep)){
+            return new FebsResponse().fail().message("提现失败,请联系技术人员");
+        }
+
         mallMemberWithdraw.setStatus(2);
         mallMemberWithdrawMapper.updateById(mallMemberWithdraw);
 
@@ -175,7 +201,6 @@
         if(1 != mallMemberWithdraw.getStatus()){
             return new FebsResponse().fail().message("当前状态不是提现中");
         }
-
 
         mallMemberWithdraw.setStatus(3);
         mallMemberWithdrawMapper.updateById(mallMemberWithdraw);
diff --git a/src/main/java/cc/mrbird/febs/pay/model/SinglePayDto.java b/src/main/java/cc/mrbird/febs/pay/model/SinglePayDto.java
index e3de02f..232ee38 100644
--- a/src/main/java/cc/mrbird/febs/pay/model/SinglePayDto.java
+++ b/src/main/java/cc/mrbird/febs/pay/model/SinglePayDto.java
@@ -3,7 +3,39 @@
 import io.swagger.annotations.ApiModel;
 import lombok.Data;
 
+import java.math.BigDecimal;
+
 @Data
 @ApiModel(value = "SinglePayDto", description = "汇聚支付代付接收参数类")
 public class SinglePayDto {
+
+    //商户订单号(全局唯一,由数字或字母组成,长度
+    //须控制在 12 到 25 之间,可包含边界
+    //值)
+    private String merchantOrderNo;
+    //收款账户号(收款人银行卡卡号)
+    private String receiverAccountNoEncBankNo;
+    // 收款人(收款人银行卡持卡人名称)
+    private String receiverAccountNoEncName;
+    // 账户类型(对私账户:201
+    //对公账户:204)
+    private String receiverAccountType;
+    // 收款账户联行号,对公账户必须填写此字段
+//    private String receiverBankChannelNo;
+    // 交易金额,单位:元,精确到分,保留两位小数
+    private BigDecimal paidAmount;
+    // 人民币币种填写:201
+    private String currency;
+    // 是否复核:复核:201,不复核:202 (见注释
+    //一)是否审核→填写为 201 时,需到商户后台进行审核,审核通过汇聚才会进行打款,审核不通过,则订
+    //单状态为订单已取消(没有异步);填写为 202 时,不需要到商户后台进行审核,订单提交汇聚成功则开
+    //始打款。
+    private String isChecked;
+    //(代付说明填写此次单笔代付的代付说明(长度
+    //为 30 个字符以内)
+    private String paidDesc;
+    //代付用途 如其他 209
+    private String paidUse;
+    //代付用途 如其他 209
+//    private String callbackUrl;
 }
diff --git a/src/main/java/cc/mrbird/febs/pay/service/impl/UnipayServiceImpl.java b/src/main/java/cc/mrbird/febs/pay/service/impl/UnipayServiceImpl.java
index 1112631..d2a4e29 100644
--- a/src/main/java/cc/mrbird/febs/pay/service/impl/UnipayServiceImpl.java
+++ b/src/main/java/cc/mrbird/febs/pay/service/impl/UnipayServiceImpl.java
@@ -6,6 +6,7 @@
 import cc.mrbird.febs.pay.service.UnipayService;
 import cc.mrbird.febs.pay.util.*;
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
@@ -44,6 +45,7 @@
                     "MXm0GwJAZd4Bk8ZYJopIOUyRLibRQIFnI78Q7HAuAUW7QtSX4yh5bMcu+Nt8zIkNAuvBC8Ju7hAmmo1V7n" +
                     "cNgAAtydXYWQJALLOFCjCkRgeRVL8YE8bVi4U16b8ltAN1DlbWEzui6VFy2vIga3IryesNVAOOdornyAwf" +
                     "1huqB2lYfuQwtrIBKg==";
+    public static final String MD5KEY = "2e95f6a3e11e47fa8a4386d6aefe1735";
     public static final String notifyUrl = "http://47.111.90.145:8800/api/unipay/unipayCallBack";
     public static final String agreementPayNotifyUrl = "http://47.111.90.145:8800/api/unipay/agreeMentPayCallBack";
     public static final String p1MerchantNo = "888118000001971";/** 商户编号 */
@@ -233,8 +235,134 @@
     }
 
     @Override
+    @Transactional
     public String singlePay(SinglePayDto singlePayDto) {
-        return null;
+        String singlePay = null;
+        String key = MD5KEY;
+
+        Map<String, Object> map = new HashMap<>();
+        map.put("userNo", p1MerchantNo);// 商户编号
+        map.put("productCode", "BANK_PAY_DAILY_ORDER");//产品类型
+        map.put("requestTime", DateUtil.now()); // 交易请求时间
+        map.put("merchantOrderNo", singlePayDto.getMerchantOrderNo());//商户订单号
+        map.put("receiverAccountNoEnc", singlePayDto.getReceiverAccountNoEncBankNo()); // 收款账户号
+        map.put("receiverNameEnc", singlePayDto.getReceiverAccountNoEncName()); // 收款人
+        map.put("receiverAccountType", singlePayDto.getReceiverAccountType());//账户类型
+        map.put("paidAmount", singlePayDto.getPaidAmount()); //交易金额
+        map.put("currency", singlePayDto.getCurrency());//币种
+        map.put("isChecked", singlePayDto.getIsChecked());//是否复核
+        map.put("paidDesc", singlePayDto.getPaidDesc());//代付说明
+        map.put("paidUse", singlePayDto.getPaidUse());//代付用途
+//        map.put("callbackUrl", singlePayDto.getCallbackUrl());//商户通知地址
+
+        String reqSign = getRequestSign(map);
+        // 签名
+        String hmac = Md5_Sign.SignByMD5(reqSign, key);
+        map.put("hmac", hmac);/** 签名数据 */
+
+        // Map转json字符串
+        String reqBodyJson = JSON.toJSONString(map);
+        System.out.println("reqBodyJson:" + reqBodyJson);
+        String httpResponseJson = null;
+        try {
+            httpResponseJson = HttpClientUtil
+                    .sendHttpPost("https://www.joinpay.com/payment/pay/singlePay",reqBodyJson);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        System.out.println(httpResponseJson);
+        if(StrUtil.isNotBlank(httpResponseJson)){
+            try {
+                singlePay = doResponseInfo(httpResponseJson, key);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            return singlePay;
+        }else{
+            return "fail";
+        }
+    }
+
+    /**
+     * 对单笔代付响应信息的处理
+     *
+     * @param httpResponseJson 响应信息json字符串
+     * @param key 商户秘钥
+     * @throws Exception 异常实体类
+     */
+    @SuppressWarnings("unchecked")
+    private static String doResponseInfo(String httpResponseJson, String key) throws Exception {
+        // 响应信息map集合
+        Map<String, Object> httpResponseMap = (Map<String, Object>) JSONObject.parse(httpResponseJson);
+        // 业务数据map集合
+        Map<String, Object> dataMap = (Map<String, Object>) httpResponseMap.get("data");
+        dataMap.put("statusCode", httpResponseMap.get("statusCode"));
+        dataMap.put("message", httpResponseMap.get("message"));
+
+        // 请求签名串
+        String reqSign = getRequestSign(httpResponseMap);
+        // 响应签名串
+        String respSign = getResponseSign(dataMap);
+        // 请求数据的加密签名
+        String reqHmac = Md5_Sign.SignByMD5(respSign, key);
+        // 请求数据的加密签名
+        String respHmac = (String) dataMap.get("hmac");
+        System.out.println("reqHmac:" + reqHmac);
+        System.out.println("respSign:" + respHmac);
+
+        reqHmac=reqHmac.toUpperCase();
+        respHmac=respHmac.toUpperCase();
+        boolean isMatch = reqHmac.equals(respHmac);
+        if (isMatch) {
+            if("2001".equals(httpResponseMap.get("statusCode").toString())
+                    && ObjectUtil.isEmpty(dataMap.get("errorCode"))){
+                System.out.println("验签成功");
+                return dataMap.get("merchantOrderNo").toString();
+            }
+        }
+        return "fail";
+    }
+
+    /**
+     * 获取响应数据签名串信息
+     * 必须按新代付接口文档应答参数信息顺序来进行字符串的拼接,详情请参考新代付接口文档的应答报文
+     *
+     * @param params 响应数据参数
+     * @return 返回响应签名串
+     */
+    public static String getResponseSign(Map<String, Object> params) {
+
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append(params.get("statusCode")).append(params.get("message")).append(params.get("errorCode"))
+                .append(params.get("errorDesc")).append(params.get("userNo")).append(params.get("merchantOrderNo"));
+
+        return stringBuilder.toString();
+    }
+
+    /**
+     * 获取请求数据签名串信息
+     * 必须按新代付接口文档请求参数信息顺序来进行字符串的拼接,详情请参考新代付接口文档请求报文
+     *
+     * @param params 请求数据参数
+     * @return 返回请求签名串
+     */
+    public static String getRequestSign(Map<String, Object> params) {
+
+        StringBuilder stringBuilder = new StringBuilder();
+        stringBuilder.append(params.get("userNo"))
+                .append(params.get("productCode"))
+                .append(params.get("requestTime"))
+                .append(params.get("merchantOrderNo"))
+                .append(params.get("receiverAccountNoEnc"))
+                .append(params.get("receiverNameEnc"))
+                .append(params.get("receiverAccountType"))
+                .append(params.get("paidAmount"))
+                .append(params.get("currency"))
+                .append(params.get("isChecked"))
+                .append(params.get("paidDesc"))
+                .append(params.get("paidUse"));
+        System.out.println("reqSign:" + stringBuilder.toString());
+        return stringBuilder.toString();
     }
 
     public static void main(String[] args) {
diff --git a/src/main/java/cc/mrbird/febs/pay/util/Md5_Sign.java b/src/main/java/cc/mrbird/febs/pay/util/Md5_Sign.java
new file mode 100644
index 0000000..49e205a
--- /dev/null
+++ b/src/main/java/cc/mrbird/febs/pay/util/Md5_Sign.java
@@ -0,0 +1,27 @@
+package cc.mrbird.febs.pay.util;
+
+import org.apache.commons.codec.digest.DigestUtils;
+
+/**
+ * 类MD5_Sign:MD5签名和验签
+ * 
+ * @author Lori 2018年6月04日 下午16:10:04
+ */
+public class Md5_Sign {
+
+	/**
+	 * MD5签名
+	 * 
+	 * @param requestSign 请求签名串
+	 * @param merchantKey 商户秘钥
+	 */
+	public static String SignByMD5(String requestSign, String merchantKey) {
+		
+		String reqHmac = "";
+		try {
+			reqHmac = DigestUtils.md5Hex(requestSign + merchantKey).toUpperCase();
+		} catch (Exception e) {}
+		
+		return reqHmac;
+	}
+}
diff --git a/src/test/java/cc/mrbird/febs/ProfitTest.java b/src/test/java/cc/mrbird/febs/ProfitTest.java
index 4bd99ef..c9d6132 100644
--- a/src/test/java/cc/mrbird/febs/ProfitTest.java
+++ b/src/test/java/cc/mrbird/febs/ProfitTest.java
@@ -1,6 +1,7 @@
 package cc.mrbird.febs;
 
 import cc.mrbird.febs.common.entity.FebsResponse;
+import cc.mrbird.febs.common.utils.MallUtils;
 import cc.mrbird.febs.mall.entity.MallOrderItem;
 import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper;
 import cc.mrbird.febs.mall.mapper.MallOrderItemMapper;
@@ -8,10 +9,7 @@
 import cc.mrbird.febs.mall.service.IAgentService;
 import cc.mrbird.febs.mall.service.IMallAchieveService;
 import cc.mrbird.febs.mall.service.IMemberProfitService;
-import cc.mrbird.febs.pay.model.AgreeMentPaySmsDto;
-import cc.mrbird.febs.pay.model.AgreementPayDto;
-import cc.mrbird.febs.pay.model.AgreementSignDto;
-import cc.mrbird.febs.pay.model.UnipayDto;
+import cc.mrbird.febs.pay.model.*;
 import cc.mrbird.febs.pay.service.UnipayService;
 import cc.mrbird.febs.rabbit.consumer.AgentConsumer;
 import cn.hutool.core.date.DateUtil;
@@ -181,4 +179,26 @@
         agreementPayDto.setBankNo("6222031901002389639");
         unipayService.agreementPay(agreementPayDto);
     }
+
+    @Test
+    public void singlePay(){
+        /**
+         * 调用汇聚代付
+         */
+        String orderNo = MallUtils.getOrderNum("W");
+        SinglePayDto singlePayDto = new SinglePayDto();
+        singlePayDto.setMerchantOrderNo(orderNo);
+        singlePayDto.setReceiverAccountNoEncBankNo("6222031901002389639");
+        singlePayDto.setReceiverAccountNoEncName("肖永");
+        singlePayDto.setReceiverAccountType("201");
+        BigDecimal paidAmount = new BigDecimal(1.00);
+        singlePayDto.setPaidAmount(paidAmount);
+        singlePayDto.setCurrency("201");
+        singlePayDto.setIsChecked("202");
+        singlePayDto.setPaidDesc("用户提现");
+        singlePayDto.setPaidUse("202");
+        String singlePayRep = unipayService.singlePay(singlePayDto);
+
+        System.out.println(singlePayRep);
+    }
 }

--
Gitblit v1.9.1