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