From 7fd3525256b0e4a0dbb6f08405368990619adf36 Mon Sep 17 00:00:00 2001 From: puzhibing <393733352@qq.com> Date: 星期五, 20 十月 2023 14:08:26 +0800 Subject: [PATCH] 对接第三方分账接口 --- ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/order/OrderServiceImpl.java | 270 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 236 insertions(+), 34 deletions(-) diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/order/OrderServiceImpl.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/order/OrderServiceImpl.java index 130aa93..1fc14f8 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/order/OrderServiceImpl.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/order/OrderServiceImpl.java @@ -1,5 +1,7 @@ package com.ruoyi.order.service.impl.order; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; @@ -39,6 +41,7 @@ import com.ruoyi.order.service.account.PaymentMessageService; import com.ruoyi.order.service.account.ProfitSharingService; import com.ruoyi.order.service.order.*; +import com.ruoyi.order.util.HuiFuTianXiaUtil; import com.ruoyi.system.api.constant.AppErrorConstant; import com.ruoyi.system.api.constant.DelayTaskEnum; import com.ruoyi.system.api.constant.SecurityConstant; @@ -60,12 +63,14 @@ import lombok.extern.log4j.Log4j2; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.math.BigDecimal; import java.math.RoundingMode; +import java.text.NumberFormat; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.format.DateTimeFormatter; @@ -145,6 +150,9 @@ @Resource private OrderRefundService orderRefundService; + + @Value("${wx.pay.callbackPath}") + private String callbackPath; /** @@ -781,8 +789,13 @@ if (null != goodsNameList) { goodsName = String.join(",", goodsNameList); } - // 小程序微信下单支付 - createWxPayInfo(appPlaceOrderVo, userId, order.getShopId(), goodsName, outTradeNo, +// // 小程序微信下单支付 +// createWxPayInfo(appPlaceOrderVo, userId, order.getShopId(), goodsName, outTradeNo, +// orderId, order.getPayMoney(), appPlaceOrderDto.getOpenid(), +// appPlaceOrderDto.getSpbillCreateIp()); + + // 小程序微信下单支付 TODO 更换支付渠道(汇付天下) + createWxPayInfo1(appPlaceOrderVo, userId, order.getShopId(), goodsName, outTradeNo, orderId, order.getPayMoney(), appPlaceOrderDto.getOpenid(), appPlaceOrderDto.getSpbillCreateIp()); //生成自动取消订单延时任务 @@ -921,36 +934,47 @@ * @param payerClientIp */ -// private void createWxPayInfo(AppPlaceOrderVo appPlaceOrderVo, Long userId, Long shopId, -// String goodsName, String outTradeNo, -// String orderId, BigDecimal payMoney, -// String openid, String payerClientIp){ -// try { -// -// -// -// // 支付相关信息返回 -// appPlaceOrderVo.setAppId(result.getAppId()); -// appPlaceOrderVo.setMchId(config.getMchId()); -// appPlaceOrderVo.setTimeStamp(result.getTimeStamp()); -// appPlaceOrderVo.setNonceStr(result.getNonceStr()); -// appPlaceOrderVo.setPackageStr(result.getPackageValue()); -// appPlaceOrderVo.setSignType(result.getSignType()); -// appPlaceOrderVo.setPaySign(result.getPaySign()); -// appPlaceOrderVo.setPrepayId(result.getPackageValue()); -// -// // 保存支付订单统一下单日志 -// paymentMessageService.savePaymentMessage("1", orderId, payRequestJson, payResponseJson); -// -// // 保存支付订单统一下单支付记录 -// orderPaymentService.saveOrderPayment(userId, shopId, mainMchId, orderId, outTradeNo, payMoney, -// appPlaceOrderVo.getEndTime(), "Y", openid, -// goodsName, result.getPackageValue()); -// }catch (Exception e){ -// e.printStackTrace(); -// } -// -// } + private void createWxPayInfo1(AppPlaceOrderVo appPlaceOrderVo, Long userId, Long shopId, + String goodsName, String outTradeNo, + String orderId, BigDecimal payMoney, + String openid, String payerClientIp){ + try { + WxPayConfig config = wxService.getConfig(); + PartnerTransactionsRequest request = new PartnerTransactionsRequest(); + request.setSpAppid(config.getAppId()); + request.setSpMchid(config.getMchId()); + request.setSubMchid(config.getSubMchId()); + // 商品描述 body + String description = goodsName + "-商品购买"; + + request.setDescription(description); + request.setOutTradeNo(outTradeNo); + request.setNotifyUrl(callbackPath + "/order/app/notify/wechatPaymentCallback"); + + R<com.alibaba.fastjson.JSONObject> r = HuiFuTianXiaUtil.weixinPayment(outTradeNo, description, payMoney.doubleValue(), openid, request.getNotifyUrl()); + com.alibaba.fastjson.JSONObject data = r.getData(); + String mainMchId = WxPayConfiguration.getPlatformTyMacId(); + // 支付相关信息返回 + appPlaceOrderVo.setAppId(data.getString("appId")); + appPlaceOrderVo.setMchId(config.getMchId()); + appPlaceOrderVo.setTimeStamp(data.getString("timeStamp")); + appPlaceOrderVo.setNonceStr(data.getString("nonceStr")); + appPlaceOrderVo.setPackageStr(data.getString("package")); + appPlaceOrderVo.setSignType(data.getString("signType")); + appPlaceOrderVo.setPaySign(data.getString("paySign")); + + // 保存支付订单统一下单日志 + paymentMessageService.savePaymentMessage("1", orderId, JSON.toJSONString(request), data.toJSONString()); + + // 保存支付订单统一下单支付记录 + orderPaymentService.saveOrderPayment(userId, shopId, mainMchId, orderId, outTradeNo, payMoney, + appPlaceOrderVo.getEndTime(), "Y", openid, + goodsName, appPlaceOrderVo.getPackageStr()); + }catch (Exception e){ + e.printStackTrace(); + } + + } @@ -1871,7 +1895,9 @@ this.saveOrUpdate(order); // 订单金额大于0时进行分账 if (order.getOnlinePayMoney().compareTo(BigDecimal.ZERO)>0) { - submitProfitSharing(orderId, order.getOrderNo(), order.getShopId(), order.getOnlinePayMoney(),order.getOrderFrom()); + // TODO: 2023/10/17 更换分账渠道(汇付天下) +// submitProfitSharing(orderId, order.getOrderNo(), order.getShopId(), order.getOnlinePayMoney(),order.getOrderFrom()); + submitProfitSharing1(orderId, order.getOrderNo(), order.getShopId(), order.getOnlinePayMoney(),order.getOrderFrom()); } //创建支付记录 if(merVerifyOrderDto.getRelPayMoney().compareTo(BigDecimal.ZERO)>0){ @@ -1994,6 +2020,120 @@ // 保存分账信息 paymentMessageService.savePaymentMessage("4", orderId, sendMessage, resultMessage); } + + + + + /** + * @description 分账实现 + * @author jqs + * @date 2023/9/8 11:56 + * @param orderId + * @param orderNo + * @param shopId + * @param orderMoney + * @param orderFrom + * @return void + */ + private void submitProfitSharing1(String orderId, String orderNo, Long shopId, BigDecimal orderMoney, Integer orderFrom) { + String sendMessage = ""; + String resultMessage = ""; + try { + // 核销完成 开始分账(平台收取服务费) + OrderPayment payment = orderPaymentService.getByOrderId(orderId); + String transactionId = payment.getTransactionId(); + String outTradeNo = payment.getOutTradeNo(); + R<ShopAuthenticationHftxVo> resultMch = remoteShopService.getShopHFTXSubMchId(shopId); + ShopAuthenticationHftxVo vo = resultMch.getData(); + if (StringUtils.isEmpty(vo.getHuifuId())) { + throw new ServiceException("获取商户号失败"); + } + // 平台特约商户号,用户平台收取服务费 2023-09-05改变分账方式 + String platformTyMacId = WxPayConfiguration.getPlatformTyMacId(); + if (!StringUtils.isEmpty(platformTyMacId)) { + WxPayConfig config = wxService.getConfig(); + ShopProportionVo shopProportion = null; + BigDecimal proportionPercent = null; + //商户订单获取统一分成 活动订单获取活动分成 + if(orderFrom==1){ + proportionPercent = new BigDecimal(vo.getShareRatio()); + }else{ + R<ShopProportionVo> resultShopProportion = remoteShopService.getShopProportion(shopId); + shopProportion = resultShopProportion.getData(); + proportionPercent = shopProportion.getProportionPercent(); + } + if (null != proportionPercent) { + ProfitSharingRequest request = new ProfitSharingRequest(); + request.setAppid(config.getAppId()); + request.setSubMchid(platformTyMacId); + request.setTransactionId(transactionId); + request.setOutOrderNo(IdUtils.simpleUUID()); + List<ProfitSharingRequest.Receiver> receiverList = new ArrayList<>(); + String description = "订单:" + orderNo + " 平台分账"; + //商户分成 + if(proportionPercent.compareTo(BigDecimal.ZERO)>0){ + PaymentDelaytransHFTXVo result = new PaymentDelaytransHFTXVo(); + // 计算分成金额 + int amount = orderMoney.multiply(proportionPercent).setScale(0, RoundingMode.UP).intValue(); + BigDecimal multiply = orderMoney.multiply(proportionPercent.divide(new BigDecimal(100))).setScale(2, RoundingMode.HALF_EVEN); + log.info("订单分账:{} 分账金额: {}", orderNo, amount); + if (amount > 0) { + // 分账创建 + ProfitSharingRequest.Receiver receiver = new ProfitSharingRequest.Receiver(); + receiver.setType("MERCHANT_ID"); + receiver.setReceiverAccount(vo.getHuifuId()); + receiver.setAmount(amount); + receiver.setDescription(description); + receiverList.add(receiver); + request.setReceivers(receiverList); + // 分账完成 + request.setFinish(true); + + NumberFormat numberFormat = NumberFormat.getInstance(); + numberFormat.setMaximumFractionDigits(2); + //分账对象 + JSONArray acctInfos = new JSONArray(); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("div_amt", numberFormat.format(multiply.doubleValue())); + jsonObject.put("huifu_id", vo.getHuifuId()); + //平台商户 + double pt_amount = orderMoney.subtract(multiply).setScale(2, RoundingMode.HALF_EVEN).doubleValue(); + JSONObject jsonObject1 = new JSONObject(); + jsonObject1.put("div_amt", numberFormat.format(pt_amount)); + jsonObject1.put("huifu_id", HuiFuTianXiaUtil.huifu_id); + acctInfos.add(jsonObject1); + R<PaymentDelaytransHFTXVo> hftxVoR = HuiFuTianXiaUtil.paymentDelaytrans(request.getOutOrderNo(), outTradeNo, acctInfos); + if(hftxVoR.getCode() != 200){ + throw new ServiceException(hftxVoR.getMsg()); + } + result = hftxVoR.getData(); + // 创建分账记录 + profitSharingService.saveProfitSharing1(shopId, orderId, orderMoney, vo.getHuifuId(), multiply.doubleValue(), result); + } + // 保存请求信息 + sendMessage = JSONObject.toJSONString(request); + resultMessage = JSONObject.toJSONString(result); + } + } else { + resultMessage = String.format("订单分账:%s 获取商户分成失败", orderNo); + log.info(resultMessage); + } + } else { + resultMessage = String.format("订单分账:%s 获取微信商户号失败", orderNo); + log.info(resultMessage); + } + } catch (Exception e) { + resultMessage = String.format("订单分账:%s 分账失败:%s", orderNo, e.getMessage()); + log.info(resultMessage); + throw new ServiceException(resultMessage); + } + + // 保存分账信息 + paymentMessageService.savePaymentMessage("4", orderId, sendMessage, resultMessage); + } + + + /** * @param merVerifyCouponDto @@ -5307,7 +5447,9 @@ if(BigDecimal.ZERO.compareTo(onlinePayMoney) < 0){ log.info("订单支付金额大于0,可发起退款"); // 订单支付金额大于0,可发起退款 - orderWxApplyRefund(orderId, refundId, onlinePayMoney, orderRefund); +// orderWxApplyRefund(orderId, refundId, onlinePayMoney, orderRefund); + // 订单支付金额大于0,可发起退款 todo 修改渠道(汇付天下) + orderWxApplyRefund1(orderId, refundId, onlinePayMoney, orderRefund); } orderRefund.setRefundStatus(1); @@ -5364,6 +5506,66 @@ } } + + + /** + * 申请退款API + */ + private void orderWxApplyRefund1(String orderId, String outRefundNo, BigDecimal payMoney, OrderRefund orderRefund){ + try { + // 创建支付订单 + OrderPayment orderPayment = orderPaymentService.getByOrderId(orderId); + if (null == orderPayment) { + return; + } + + log.info("调用微信退款---发起退款"); + + String subMchId = orderPayment.getSubMchId(); + WxPayConfig config = wxService.getConfig(); + + RefundsRequest request = new RefundsRequest(); + request.setSpAppid(config.getAppId()); + request.setSubMchid(subMchId); + request.setTransactionId(orderPayment.getTransactionId()); + request.setOutRefundNo(outRefundNo); + request.setReason("用户取消订单"); + // 订单金额 + int total = orderPayment.getPayMoney().multiply(new BigDecimal(100)).intValue(); + + RefundsRequest.Amount amount = RefundsRequest.Amount.builder().refund(total).total(total).currency("CNY").build(); + request.setAmount(amount); + request.setNotifyUrl(callbackPath + "/order/app/notify/wechatPaymentRefundCallback"); + + RefundsResult result = wxService.getEcommerceService().refunds(request); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); + String org_req_date = sdf.format(orderPayment.getCreateTime()); + String outTradeNo = orderPayment.getOutTradeNo(); + R<String> r = HuiFuTianXiaUtil.weixinPaymentRefund(outRefundNo, orderPayment.getPayMoney().doubleValue(), org_req_date, outTradeNo, request.getNotifyUrl()); + if(r.getCode() != 200){ + throw new ServiceException(r.getMsg()); + } + + // 微信退款id + orderRefund.setWxRefundId(r.getData()); + + // 请求参数 + Gson gson = new Gson(); + String refundRequestJson = gson.toJson(request); + // 返回参数 + String refundResponseJson = gson.toJson(result); + + log.info("调用微信退款返回参数---{}", refundResponseJson); + + // 保存支付订单统一下单日志 + paymentMessageService.savePaymentMessage("3", orderId, refundRequestJson, refundResponseJson); + + } catch (WxPayException e) { + throw new ServiceException(e.getMessage()); + } + } + /** * @param staffTotalDto * @return StaffActivityOrderTotalVo -- Gitblit v1.7.1