From c037c4b5356f3a2b0cc0dc18a46b8ed05af2e72e Mon Sep 17 00:00:00 2001
From: sangelxiu1 <15781802@163.com>
Date: Tue, 1 Jul 2025 14:57:00 +0800
Subject: [PATCH] =?UTF-8?q?##=20Feat=20-=20=E4=BA=AC=E4=B8=9C=E6=94=AF?=
=?UTF-8?q?=E4=BB=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../third/pay/TOnlinePaymentSepAcc.java | 72 ++++++
.../third/pay/TOnlinePaymentSepAccD.java | 56 +++++
.../hzs/third/pay/config/JdPayProperties.java | 17 ++
.../config/JdPaySeparateAccountConfig.java | 14 ++
.../controller/api/JdRefundController.java | 91 ++++++++
.../pay/controller/api/PayController.java | 14 +-
.../notify/JdPayNotifyController.java | 210 ++++++++++++++++++
.../notify/JdRefundNotifyController.java | 148 ++++++++++++
.../jdpay/dto/JdPayRefundSuccessNotify.java | 66 ++++++
.../jdpay/dto/JdPayTradeSuccessNotify.java | 98 ++++++++
.../mapper/TOnlinePaymentSepAccDMapper.java | 16 ++
.../mapper/TOnlinePaymentSepAccMapper.java | 16 ++
.../hzs/third/pay/service/IRefundService.java | 19 ++
.../ITOnlinePaymentSepAccDService.java | 16 ++
.../service/ITOnlinePaymentSepAccService.java | 16 ++
.../pay/service/impl/JdPayServiceImpl.java | 37 ++-
.../pay/service/impl/RefundServiceImpl.java | 146 ++++++++++++
.../TOnlinePaymentSepAccDServiceImpl.java | 20 ++
.../impl/TOnlinePaymentSepAccServiceImpl.java | 59 +++++
bd-third/src/main/resources/bootstrap.yml | 15 +-
.../third/pay/TOnlinePaymentSepAccDMapper.xml | 29 +++
.../third/pay/TOnlinePaymentSepAccMapper.xml | 31 +++
sql/2025年7月1日_京东支付_分账.sql | 89 ++++++++
文档/支付/支付回调/京东 | 5 +
24 files changed, 1286 insertions(+), 14 deletions(-)
create mode 100644 bd-common/bd-common-domain/src/main/java/com/hzs/common/domain/third/pay/TOnlinePaymentSepAcc.java
create mode 100644 bd-common/bd-common-domain/src/main/java/com/hzs/common/domain/third/pay/TOnlinePaymentSepAccD.java
create mode 100644 bd-third/src/main/java/com/hzs/third/pay/config/JdPayProperties.java
create mode 100644 bd-third/src/main/java/com/hzs/third/pay/config/JdPaySeparateAccountConfig.java
create mode 100644 bd-third/src/main/java/com/hzs/third/pay/controller/api/JdRefundController.java
create mode 100644 bd-third/src/main/java/com/hzs/third/pay/controller/notify/JdPayNotifyController.java
create mode 100644 bd-third/src/main/java/com/hzs/third/pay/controller/notify/JdRefundNotifyController.java
create mode 100644 bd-third/src/main/java/com/hzs/third/pay/jdpay/dto/JdPayRefundSuccessNotify.java
create mode 100644 bd-third/src/main/java/com/hzs/third/pay/jdpay/dto/JdPayTradeSuccessNotify.java
create mode 100644 bd-third/src/main/java/com/hzs/third/pay/mapper/TOnlinePaymentSepAccDMapper.java
create mode 100644 bd-third/src/main/java/com/hzs/third/pay/mapper/TOnlinePaymentSepAccMapper.java
create mode 100644 bd-third/src/main/java/com/hzs/third/pay/service/ITOnlinePaymentSepAccDService.java
create mode 100644 bd-third/src/main/java/com/hzs/third/pay/service/ITOnlinePaymentSepAccService.java
create mode 100644 bd-third/src/main/java/com/hzs/third/pay/service/impl/TOnlinePaymentSepAccDServiceImpl.java
create mode 100644 bd-third/src/main/java/com/hzs/third/pay/service/impl/TOnlinePaymentSepAccServiceImpl.java
create mode 100644 bd-third/src/main/resources/mapper/third/pay/TOnlinePaymentSepAccDMapper.xml
create mode 100644 bd-third/src/main/resources/mapper/third/pay/TOnlinePaymentSepAccMapper.xml
create mode 100644 sql/2025年7月1日_京东支付_分账.sql
create mode 100644 文档/支付/支付回调/京东
diff --git a/bd-common/bd-common-domain/src/main/java/com/hzs/common/domain/third/pay/TOnlinePaymentSepAcc.java b/bd-common/bd-common-domain/src/main/java/com/hzs/common/domain/third/pay/TOnlinePaymentSepAcc.java
new file mode 100644
index 00000000..3d8d0a1d
--- /dev/null
+++ b/bd-common/bd-common-domain/src/main/java/com/hzs/common/domain/third/pay/TOnlinePaymentSepAcc.java
@@ -0,0 +1,72 @@
+package com.hzs.common.domain.third.pay;
+
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.hzs.common.core.web.domain.BaseEntity;
+import lombok.*;
+import lombok.experimental.Accessors;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ *
+ * 支付请求主表
+ *
+ *
+ * @author bd
+ * @since 2025-07-01
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Accessors(chain = true)
+@TableName("T_ONLINE_PAYMENT_SEP_ACC")
+@KeySequence("T_ONLINE_PAYMENT_SEP_ACC_SEQ")
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TOnlinePaymentSepAcc extends BaseEntity {
+
+ private static final long serialVersionUID = 1L;
+
+ @TableId("PK_ID")
+ private Long pkId;
+
+ /**
+ * 在线支付信息ID
+ */
+ @TableField("PK_PAYMENT")
+ private Long pkPayment;
+
+ /**
+ * 版本号
+ */
+ @TableField("VERSION")
+ private String version;
+
+ /**
+ * 支付请求信息
+ */
+ @TableField("REQ_CONTENT")
+ private String reqContent;
+
+ /**
+ * 分账请求信息
+ */
+ @TableField("REQ_CONTENT_SEP_ACC")
+ private String reqContentSepAcc;
+
+ /**
+ * 支付响应信息
+ */
+ @TableField("RESP_CONTENT")
+ private String respContent;
+
+ @TableField("TRADE_AMOUNT")
+ private BigDecimal tradeAmount;
+
+ @TableField(exist = false)
+ private List sepAccDList;
+}
diff --git a/bd-common/bd-common-domain/src/main/java/com/hzs/common/domain/third/pay/TOnlinePaymentSepAccD.java b/bd-common/bd-common-domain/src/main/java/com/hzs/common/domain/third/pay/TOnlinePaymentSepAccD.java
new file mode 100644
index 00000000..8cdcb72e
--- /dev/null
+++ b/bd-common/bd-common-domain/src/main/java/com/hzs/common/domain/third/pay/TOnlinePaymentSepAccD.java
@@ -0,0 +1,56 @@
+package com.hzs.common.domain.third.pay;
+
+import java.math.BigDecimal;
+
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.hzs.common.core.web.domain.BaseEntity;
+import lombok.*;
+import lombok.experimental.Accessors;
+
+/**
+ *
+ * 支付请求子表(分账)
+ *
+ *
+ * @author bd
+ * @since 2025-07-01
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Accessors(chain = true)
+@TableName("T_ONLINE_PAYMENT_SEP_ACC_D")
+@KeySequence("T_ONLINE_PAYMENT_SEP_ACC_D_SEQ")
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TOnlinePaymentSepAccD extends BaseEntity {
+
+ private static final long serialVersionUID = 1L;
+
+ @TableId("PK_ID")
+ private Long pkId;
+
+ /**
+ * 支付请求主表ID
+ */
+ @TableField("PK_SEP_ACC")
+ private Long pkSepAcc;
+
+ /**
+ * 分账账号
+ */
+ @TableField("ACCOUNT")
+ private String account;
+
+ /**
+ * 分账比例
+ */
+ @TableField("PROPORTION")
+ private BigDecimal proportion;
+
+ @TableField("TRADE_AMOUNT")
+ private BigDecimal tradeAmount;
+}
diff --git a/bd-third/src/main/java/com/hzs/third/pay/config/JdPayProperties.java b/bd-third/src/main/java/com/hzs/third/pay/config/JdPayProperties.java
new file mode 100644
index 00000000..0da66bcc
--- /dev/null
+++ b/bd-third/src/main/java/com/hzs/third/pay/config/JdPayProperties.java
@@ -0,0 +1,17 @@
+package com.hzs.third.pay.config;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+@Setter
+@Getter
+@Component
+@ConfigurationProperties(prefix = "jd.pay") // 绑定jd.pay前缀的配置
+public class JdPayProperties {
+ private List separateAccounts;
+
+}
diff --git a/bd-third/src/main/java/com/hzs/third/pay/config/JdPaySeparateAccountConfig.java b/bd-third/src/main/java/com/hzs/third/pay/config/JdPaySeparateAccountConfig.java
new file mode 100644
index 00000000..d4d05f2f
--- /dev/null
+++ b/bd-third/src/main/java/com/hzs/third/pay/config/JdPaySeparateAccountConfig.java
@@ -0,0 +1,14 @@
+package com.hzs.third.pay.config;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+public class JdPaySeparateAccountConfig implements Serializable {
+ private String account;
+ @JsonFormat(shape = JsonFormat.Shape.STRING)
+ private BigDecimal proportion;
+}
diff --git a/bd-third/src/main/java/com/hzs/third/pay/controller/api/JdRefundController.java b/bd-third/src/main/java/com/hzs/third/pay/controller/api/JdRefundController.java
new file mode 100644
index 00000000..7bb9788f
--- /dev/null
+++ b/bd-third/src/main/java/com/hzs/third/pay/controller/api/JdRefundController.java
@@ -0,0 +1,91 @@
+package com.hzs.third.pay.controller.api;
+
+import com.hzs.common.core.enums.EPayChannel;
+import com.hzs.common.core.enums.EPayStatus;
+import com.hzs.common.core.utils.StringUtils;
+import com.hzs.common.core.web.domain.AjaxResult;
+import com.hzs.common.domain.third.pay.TOnlinePayment;
+import com.hzs.common.security.utils.SecurityUtils;
+import com.hzs.third.pay.controller.base.PayBaseController;
+import com.hzs.third.pay.dto.RefundDTO;
+import com.hzs.third.pay.param.PayParam;
+import com.hzs.third.pay.service.IRefundService;
+import com.hzs.third.pay.service.ITOnlinePaymentService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @Description: 京东退款控制器
+ * @Author: jiang chao
+ * @Time: 2023/8/17 15:11
+ * @Classname: JdRefundController
+ * @PackageName: com.hzs.third.pay.controller.api
+ */
+@Slf4j
+@RestController
+@RequestMapping("/jd-refund")
+public class JdRefundController extends PayBaseController {
+
+ @Autowired
+ private IRefundService iRefundService;
+ @Autowired
+ private ITOnlinePaymentService itOnlinePaymentService;
+
+ /**
+ * 京东退款接口
+ *
+ * @param param
+ * @return
+ */
+ @PostMapping("/refund")
+ public AjaxResult refund(@RequestBody PayParam param) {
+ if (null == param.getBusinessType() || StringUtils.isEmpty(param.getBusinessCode())) {
+ // 缺少参数
+ return AjaxResult.error("缺少参数");
+ }
+ // 查询在线支付明细
+ TOnlinePayment tOnlinePayment = itOnlinePaymentService.queryByBusiness(param.getBusinessType(), param.getBusinessCode(), SecurityUtils.getPkCountry());
+ if (null == tOnlinePayment || EPayStatus.UNPAID.getValue() == tOnlinePayment.getPayStatus()) {
+ // 在线支付明细为空 或者 未支付成功,则不能进行退款
+ return AjaxResult.error("订单不存在或未支付成功,不能进行退款");
+ }
+ // 获取支付渠道
+ EPayChannel ePayChannel = EPayChannel.getEnumByValue(tOnlinePayment.getPayChannel());
+ if (null == ePayChannel) {
+ return AjaxResult.error("订单支付信息有误,不能进行退款");
+ }
+
+ try {
+ // 京东收银台退款处理
+ String str = iRefundService.jdCashRefundHandle(RefundDTO.builder()
+ .businessType(param.getBusinessType())
+ .businessCode(param.getBusinessCode())
+ .refundAmount(tOnlinePayment.getPayMoney())
+ .userId(SecurityUtils.getUserId())
+ .pkCountry(SecurityUtils.getPkCountry())
+ .build(),
+ tOnlinePayment);
+ // 京东银行卡退款处理 -- 旧
+// String str = iRefundService.jdRefundHandle(RefundDTO.builder()
+// .businessType(param.getBusinessType())
+// .businessCode(param.getBusinessCode())
+// .refundAmount(tOnlinePayment.getPayMoney())
+// .userId(SecurityUtils.getUserId())
+// .pkCountry(SecurityUtils.getPkCountry())
+// .build(),
+// tOnlinePayment);
+ if (null == str) {
+ return AjaxResult.success();
+ }
+ return AjaxResult.error("退款失败:" + str);
+ } catch (Exception e) {
+ log.error("调用京东退款处理返回异常!", e);
+ return AjaxResult.error("退款异常,请刷新后重试");
+ }
+ }
+
+}
diff --git a/bd-third/src/main/java/com/hzs/third/pay/controller/api/PayController.java b/bd-third/src/main/java/com/hzs/third/pay/controller/api/PayController.java
index 46471d4c..e45f8a8f 100644
--- a/bd-third/src/main/java/com/hzs/third/pay/controller/api/PayController.java
+++ b/bd-third/src/main/java/com/hzs/third/pay/controller/api/PayController.java
@@ -252,8 +252,8 @@ public class PayController {
if (null != payResult) {
if (payResult.isSuccess()) {
// 实际支付金额在支付之前不需要入库,实际以取支付回调为准
- onlinePayment.setPayMoney(null);
- itOnlinePaymentService.saveOrUpdate(onlinePayment);
+// onlinePayment.setPayMoney(null);
+// itOnlinePaymentService.saveOrUpdate(onlinePayment);
return AjaxResult.success(payResult.getData());
}
@@ -275,13 +275,13 @@ public class PayController {
}
// 业务类型(校验业务类型)
- EPayBusinessType ePayBusinessType = EPayBusinessType.getEnumByValue(param.getBusinessType());
- if (null == ePayBusinessType) {
- return AjaxResult.success("支付业务类型错误", 0);
- }
+// EPayBusinessType ePayBusinessType = EPayBusinessType.getEnumByValue(param.getBusinessType());
+// if (null == ePayBusinessType) {
+// return AjaxResult.success("支付业务类型错误", 0);
+// }
QueryWrapper queryWrapper = new QueryWrapper<>();
- queryWrapper.eq("BUSINESS_TYPE", param.getBusinessType());
+// queryWrapper.eq("BUSINESS_TYPE", param.getBusinessType());
queryWrapper.eq("BUSINESS_CODE", param.getBusinessCode());
TOnlinePayment onlinePayment = itOnlinePaymentService.getOne(queryWrapper);
if (null == onlinePayment) {
diff --git a/bd-third/src/main/java/com/hzs/third/pay/controller/notify/JdPayNotifyController.java b/bd-third/src/main/java/com/hzs/third/pay/controller/notify/JdPayNotifyController.java
new file mode 100644
index 00000000..c8222d48
--- /dev/null
+++ b/bd-third/src/main/java/com/hzs/third/pay/controller/notify/JdPayNotifyController.java
@@ -0,0 +1,210 @@
+package com.hzs.third.pay.controller.notify;
+
+import cn.hutool.json.JSONUtil;
+import com.hzs.common.core.enums.EPayChannel;
+import com.hzs.common.core.utils.DateUtils;
+import com.hzs.third.pay.config.JdPayConfig;
+import com.hzs.third.pay.constants.JdPayConstants;
+import com.hzs.third.pay.controller.base.JdBaseController;
+import com.hzs.third.pay.dto.jd.JdPayNotifyBody;
+import com.hzs.third.pay.jdpay.dto.JdPayTradeSuccessNotify;
+import com.hzs.third.pay.jdpay.sdk.JdPay;
+import com.hzs.third.pay.jdpay.util.GsonUtil;
+import com.hzs.third.pay.service.IPayService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 京东支付回调控制器
+ */
+@Slf4j
+@RestController
+@RequestMapping("/jd")
+public class JdPayNotifyController extends JdBaseController {
+
+ @Autowired
+ private JdPayConfig jdPayConfig;
+ @Autowired
+ private IPayService iPayService;
+
+ /**
+ * 京东支付回调
+ *
+ * @param request
+ */
+ @PostMapping("/notify")
+ public String notify(HttpServletRequest request) {
+ try {
+ String reqBody = this.getRequestBody(request);
+ log.info("京东支付回调! body: {}", reqBody);
+
+ if (this.checkToken(request, reqBody, jdPayConfig.getSecretKey())) {
+ // 签名校验通过
+ JdPayNotifyBody notifyBody = JSONUtil.toBean(reqBody, JdPayNotifyBody.class);
+
+ // 支付流水号
+ String payNumber = notifyBody.getOrderNum();
+ // 支付时间
+ Date payTime = DateUtils.parseDate(notifyBody.getCompleteTime(), DateUtils.YYYY_MM_DD_HH_MM_SS);
+ // 支付金额
+ BigDecimal payMoney = new BigDecimal(notifyBody.getOrderAmount());
+
+ // 支付扩展类型
+ String type = notifyBody.getExtraInfo();
+
+ // 回调订单编号
+ String thirdOrderCode = notifyBody.getRequestNum();
+ // 支付信息编号
+ String orderCode = thirdOrderCode;
+ // 处理订单号以及扩展类型
+ if (orderCode.indexOf("-") > 0) {
+ // 带有分隔,需要处理
+ orderCode = orderCode.split("-")[0];
+ }
+
+ // 支付后续业务处理
+ if (iPayService.notifyHandle(type, orderCode, thirdOrderCode, payNumber, payTime, payMoney, EPayChannel.JD, "")) {
+ return JdPayConstants.RETURN_SUCCESS;
+ }
+ } else {
+ log.error("京东支付回调签名校验失败!");
+ }
+ } catch (Exception e) {
+ log.error("京东支付回调处理异常", e);
+ }
+ return JdPayConstants.RETURN_FAIL;
+ }
+
+
+ @Resource
+ private JdPay jdPay;
+
+ /**
+ * 京东收银台处理成功返回
+ */
+ private static final String SUCCESS = "SUCCESS";
+ /**
+ * 京东收银台处理失败返回
+ */
+ private static final String ERROR = "ERROR";
+
+ /**
+ * 京东收银台异步支付回调
+ *
+ * @param reqText
+ * @return 成功返回"SUCCESS", 失败返回"ERROR",京东支付会再次发起通知,通知频次见接口文档。
+ */
+ @PostMapping("/trade-notify")
+ public String tradeNotify(@RequestBody String reqText) {
+ log.info("京东收银台支付异步回调! reqText: {}", reqText);
+ try {
+ // 验证签名与解密
+ String interData = jdPay.verifyResponse(reqText);
+ JdPayTradeSuccessNotify successNotify = GsonUtil.fromJson(interData, JdPayTradeSuccessNotify.class);
+ if (null != successNotify) {
+ if ("FINI".equals(successNotify.getTradeStatus())) {
+ // 支付成功处理
+
+ // 商户订单号
+ String payNumber = successNotify.getTradeNo();
+ // 渠道流水号
+ String channelNumber = "";
+ // 支付完成时间
+ Date payTime = DateUtils.parseDateOne(successNotify.getFinishDate(), DateUtils.YAMMERERS);
+ // 支付扩展类型
+ String type = successNotify.getReturnParams();
+
+ // 回调订单编号
+ String thirdOrderCode = successNotify.getOutTradeNo();
+ // 订单编号
+ String orderCode = thirdOrderCode;
+
+ // 订单金额
+ int tradeAmount = Integer.parseInt(successNotify.getTradeAmount());
+ BigDecimal payMoney = new BigDecimal(tradeAmount).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP);
+
+ // 支付后续业务处理
+ if (iPayService.notifyHandle(type, orderCode, thirdOrderCode, payNumber, payTime, payMoney, EPayChannel.JD, channelNumber)) {
+ return SUCCESS;
+ }
+ } else {
+ log.error("京东收银台支付异步回调失败,resultDesc: {}", successNotify.getResultDesc());
+ }
+ } else {
+ log.error("京东收银台支付异步回调解密为空");
+ }
+ } catch (Exception e) {
+ log.error("京东收银台支付异步回调异常", e);
+ }
+ return ERROR;
+ }
+
+
+ /**
+ * 京东收银台页面回调
+ *
+ * @param request
+ * @return
+ */
+ @PostMapping("/sync-notify")
+ public String syncNotify(HttpServletRequest request) {
+ // 签名验证逻辑,需要支持添加通知字段不影响结果
+ Map respMap = getAllRequestParam(request);
+ log.info("京东收银台支付页面回调! request: {}", respMap);
+
+ try {
+ if (jdPay.verifyPageCallBack(respMap)) {
+ if ("FINI".equals(respMap.get("status"))) {
+ // todo 支付成功
+
+ return SUCCESS;
+ } else if ("WPAR".equals(respMap.get("status"))) {
+ // todo 支付处理中
+ log.error("京东支付页面回调,支付处理中");
+ } else {
+ // todo 支付失败
+ log.error("京东支付页面回调,支付失败");
+ }
+ } else {
+ // 签名异常,报错
+ log.error("京东收银台支付页面回调!签名异常!");
+ }
+ } catch (Exception e) {
+ log.error("京东支付页面回调参数", e);
+ }
+ return ERROR;
+ }
+
+ /**
+ * 获取客户端请求参数中所有的信息
+ */
+ private Map getAllRequestParam(final HttpServletRequest request) {
+ Map respMap = new HashMap<>();
+ Enumeration> temp = request.getParameterNames();
+ if (null != temp) {
+ while (temp.hasMoreElements()) {
+ String en = (String) temp.nextElement();
+ String value = request.getParameter(en);
+ respMap.put(en, value);
+ //如果字段的值为空,判断若值为空,则删除这个字段>
+ if (null == respMap.get(en) || "".equals(respMap.get(en))) {
+ respMap.remove(en);
+ }
+ }
+ }
+ return respMap;
+ }
+
+}
diff --git a/bd-third/src/main/java/com/hzs/third/pay/controller/notify/JdRefundNotifyController.java b/bd-third/src/main/java/com/hzs/third/pay/controller/notify/JdRefundNotifyController.java
new file mode 100644
index 00000000..f6ff3ea0
--- /dev/null
+++ b/bd-third/src/main/java/com/hzs/third/pay/controller/notify/JdRefundNotifyController.java
@@ -0,0 +1,148 @@
+package com.hzs.third.pay.controller.notify;
+
+import cn.hutool.json.JSONUtil;
+import com.hzs.common.core.enums.EPayChannel;
+import com.hzs.common.core.utils.DateUtils;
+import com.hzs.third.pay.config.JdPayConfig;
+import com.hzs.third.pay.constants.JdPayConstants;
+import com.hzs.third.pay.controller.base.JdBaseController;
+import com.hzs.third.pay.jdpay.dto.JdPayRefundSuccessNotify;
+import com.hzs.third.pay.jdpay.sdk.JdPay;
+import com.hzs.third.pay.jdpay.util.GsonUtil;
+import com.hzs.third.pay.service.IRefundService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Description: 京东退填回调控制器
+ * @Author: jiang chao
+ * @Time: 2023/8/17 15:50
+ * @Classname: JdRefundNotifyController
+ * @PackageName: com.hzs.third.pay.controller.notify
+ */
+@Slf4j
+@RestController
+@RequestMapping("/jd-refund")
+public class JdRefundNotifyController extends JdBaseController {
+
+ @Autowired
+ private JdPayConfig jdPayConfig;
+ @Autowired
+ private IRefundService iRefundService;
+
+ /**
+ * 京东退款回调
+ *
+ * @param request
+ * @return
+ * @throws Exception
+ */
+ @PostMapping("/notify")
+ public String refundNotify(HttpServletRequest request) {
+ try {
+ String reqBody = this.getRequestBody(request);
+ log.info("京东退款回调! body: {}", reqBody);
+
+ if (this.checkToken(request, reqBody, jdPayConfig.getSecretKey())) {
+ // 签名校验通过
+ Map dataMap = JSONUtil.toBean(reqBody, HashMap.class);
+
+ // 退款编号
+ String refundCode = dataMap.get("refundRequestNum");
+ // 京东交易流水号
+ String refundNumber = dataMap.get("orderNum");
+ // 退款完成时间
+ Date finishTime = DateUtils.parseDate(dataMap.get("refundSuccessTime"), DateUtils.YYYY_MM_DD_HH_MM_SS);
+ // 退款金额
+ BigDecimal finishMoney = new BigDecimal(dataMap.get("refundAmount"));
+
+ if (JdPayConstants.ORDER_SUCCESS.equals(dataMap.get("refundStatus"))) {
+ // 退款成功
+ // 退款后续业务处理
+ if (iRefundService.notifyHandle(EPayChannel.JD, refundCode, refundNumber, finishTime, finishMoney)) {
+ return JdPayConstants.RETURN_SUCCESS;
+ }
+ } else {
+ // 退款失败
+ log.error("京东退款失败: {}", dataMap.get("failReason"));
+
+ if (iRefundService.notifyErrorHandle(EPayChannel.JD, refundCode, refundNumber, dataMap.get("failReason"))) {
+ return JdPayConstants.RETURN_SUCCESS;
+ }
+ }
+ } else {
+ log.error("京东支付回调签名校验失败!");
+ }
+ } catch (Exception e) {
+ log.error("京东支付回调处理异常", e);
+ }
+ return JdPayConstants.RETURN_FAIL;
+ }
+
+
+ @Resource
+ private JdPay jdPay;
+
+ /**
+ * 京东收银台处理成功返回
+ */
+ private static final String SUCCESS = "SUCCESS";
+ /**
+ * 京东收银台处理失败返回
+ */
+ private static final String ERROR = "ERROR";
+
+ /**
+ * 京东收银台退款异步支付回调
+ *
+ * @param reqText
+ * @return 成功返回"SUCCESS", 失败返回"ERROR",退款通知会再次发起通知,通知频次见接口文档。
+ */
+ @PostMapping("/trade-notify")
+ public String tradeNotify(@RequestBody String reqText) {
+ log.info("京东收银台退款异步回调! reqText: {}", reqText);
+ try {
+ // 验证签名与解密
+ String interData = jdPay.verifyResponse(reqText);
+ JdPayRefundSuccessNotify successNotify = GsonUtil.fromJson(interData, JdPayRefundSuccessNotify.class);
+ if (null != successNotify) {
+ if ("FINI".equals(successNotify.getTradeStatus())) {
+
+ // 退款编号
+ String refundCode = successNotify.getOutTradeNo();
+ // 京东交易流水号
+ String refundNumber = successNotify.getTradeNo();
+ // 退款完成时间
+ Date finishTime = DateUtils.parseDate(successNotify.getFinishDate(), DateUtils.YAMMERERS);
+ // 退款金额
+ int tradeAmount = Integer.parseInt(successNotify.getTradeAmount());
+ BigDecimal finishMoney = new BigDecimal(tradeAmount).divide(new BigDecimal("100"), 2, BigDecimal.ROUND_HALF_UP);
+
+ // 退款后续业务处理
+ if (iRefundService.notifyHandle(EPayChannel.JD, refundCode, refundNumber, finishTime, finishMoney)) {
+ return SUCCESS;
+ }
+ } else {
+ log.error("京东收银台退款异步回调失败,resultDesc: {}", successNotify.getResultDesc());
+ }
+ } else {
+ log.error("京东收银台退款异步回调解密为空");
+ }
+ } catch (Exception e) {
+ log.error("京东收银台退款异步回调异常", e);
+ }
+ return ERROR;
+ }
+
+}
diff --git a/bd-third/src/main/java/com/hzs/third/pay/jdpay/dto/JdPayRefundSuccessNotify.java b/bd-third/src/main/java/com/hzs/third/pay/jdpay/dto/JdPayRefundSuccessNotify.java
new file mode 100644
index 00000000..e3b25444
--- /dev/null
+++ b/bd-third/src/main/java/com/hzs/third/pay/jdpay/dto/JdPayRefundSuccessNotify.java
@@ -0,0 +1,66 @@
+package com.hzs.third.pay.jdpay.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 退款成功通知
+ * @Author: jiang chao
+ * @Time: 2025/3/21 10:24
+ * @Classname: JdPayRefundSuccessNotify
+ * @PackageName: com.hzs.third.pay.jdpay.dto
+ */
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class JdPayRefundSuccessNotify implements Serializable {
+
+ /**
+ * 业务结果
+ */
+ private String resultCode;
+ /**
+ * 响应描述
+ */
+ private String resultDesc;
+
+ /**
+ * 京东退款订单号
+ */
+ private String tradeNo;
+
+ /**
+ * 商户退款订单号
+ */
+ private String outTradeNo;
+ /**
+ * 商户原正单订单号
+ */
+ private String originalOutTradeNo;
+ /**
+ * 订单总金额
+ */
+ private String tradeAmount;
+ /**
+ * 退款完成时间
+ */
+ private String finishDate;
+ /**
+ * 交易状态
+ */
+ private String tradeStatus;
+ /**
+ * 回传字段
+ */
+ private String returnParams;
+ /**
+ * 币种
+ */
+ private String currency;
+
+}
diff --git a/bd-third/src/main/java/com/hzs/third/pay/jdpay/dto/JdPayTradeSuccessNotify.java b/bd-third/src/main/java/com/hzs/third/pay/jdpay/dto/JdPayTradeSuccessNotify.java
new file mode 100644
index 00000000..a42ba4fb
--- /dev/null
+++ b/bd-third/src/main/java/com/hzs/third/pay/jdpay/dto/JdPayTradeSuccessNotify.java
@@ -0,0 +1,98 @@
+package com.hzs.third.pay.jdpay.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 交易成功通知
+ * @Author: jiang chao
+ * @Time: 2025/3/21 10:24
+ * @Classname: JdPayRefundSuccessNotify
+ * @PackageName: com.hzs.third.pay.jdpay.dto
+ */
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@Data
+public class JdPayTradeSuccessNotify implements Serializable {
+
+ /**
+ * 业务结果
+ */
+ private String resultCode;
+ /**
+ * 响应描述
+ */
+ private String resultDesc;
+
+ /**
+ * 京东交易订单号
+ */
+ private String tradeNo;
+
+ /**
+ * 商户订单号
+ */
+ private String outTradeNo;
+ /**
+ * 订单总金额
+ */
+ private String tradeAmount;
+ /**
+ * 币种
+ */
+ private String currency;
+ /**
+ * 支付完成时间
+ */
+ private String finishDate;
+ /**
+ * 交易类型
+ */
+ private String tradeType;
+ /**
+ * 交易状态
+ */
+ private String tradeStatus;
+ /**
+ * 回传字段
+ */
+ private String returnParams;
+ /**
+ * 请求的端
+ */
+ private String clientType;
+ /**
+ * 商户用户标识
+ */
+ private String userId;
+ /**
+ * 优惠金额
+ */
+ private String discountAmount;
+ /**
+ * 支付工具
+ */
+ private String payTool;
+ /**
+ * 掩码卡号
+ */
+ private String maskCardNo;
+ /**
+ * 卡类型
+ */
+ private String cardType;
+ /**
+ * 银行编码
+ */
+ private String bankCode;
+ /**
+ * 白条分期数
+ */
+ private String installmentNum;
+
+}
diff --git a/bd-third/src/main/java/com/hzs/third/pay/mapper/TOnlinePaymentSepAccDMapper.java b/bd-third/src/main/java/com/hzs/third/pay/mapper/TOnlinePaymentSepAccDMapper.java
new file mode 100644
index 00000000..2d355e24
--- /dev/null
+++ b/bd-third/src/main/java/com/hzs/third/pay/mapper/TOnlinePaymentSepAccDMapper.java
@@ -0,0 +1,16 @@
+package com.hzs.third.pay.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.hzs.common.domain.third.pay.TOnlinePaymentSepAccD;
+
+/**
+ *
+ * 支付请求子表(分账) Mapper 接口
+ *
+ *
+ * @author bd
+ * @since 2025-07-01
+ */
+public interface TOnlinePaymentSepAccDMapper extends BaseMapper {
+
+}
diff --git a/bd-third/src/main/java/com/hzs/third/pay/mapper/TOnlinePaymentSepAccMapper.java b/bd-third/src/main/java/com/hzs/third/pay/mapper/TOnlinePaymentSepAccMapper.java
new file mode 100644
index 00000000..64655522
--- /dev/null
+++ b/bd-third/src/main/java/com/hzs/third/pay/mapper/TOnlinePaymentSepAccMapper.java
@@ -0,0 +1,16 @@
+package com.hzs.third.pay.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.hzs.common.domain.third.pay.TOnlinePaymentSepAcc;
+
+/**
+ *
+ * 支付请求主表 Mapper 接口
+ *
+ *
+ * @author bd
+ * @since 2025-07-01
+ */
+public interface TOnlinePaymentSepAccMapper extends BaseMapper {
+
+}
diff --git a/bd-third/src/main/java/com/hzs/third/pay/service/IRefundService.java b/bd-third/src/main/java/com/hzs/third/pay/service/IRefundService.java
index d1405669..68f5cafa 100644
--- a/bd-third/src/main/java/com/hzs/third/pay/service/IRefundService.java
+++ b/bd-third/src/main/java/com/hzs/third/pay/service/IRefundService.java
@@ -44,4 +44,23 @@ public interface IRefundService {
*/
boolean notifyErrorHandle(EPayChannel ePayChannel, String refundCode, String refundNumber, String errorMsg);
+
+ /**
+ * 京东退款处理
+ *
+ * @param refundDTO 业务类型
+ * @param tOnlinePayment 退款对应支付信息
+ * @return
+ */
+ String jdRefundHandle(RefundDTO refundDTO, TOnlinePayment tOnlinePayment);
+
+ /**
+ * 京东收银台退款处理
+ *
+ * @param refundDTO 业务类型
+ * @param tOnlinePayment 退款对应支付信息
+ * @return
+ */
+ String jdCashRefundHandle(RefundDTO refundDTO, TOnlinePayment tOnlinePayment);
+
}
diff --git a/bd-third/src/main/java/com/hzs/third/pay/service/ITOnlinePaymentSepAccDService.java b/bd-third/src/main/java/com/hzs/third/pay/service/ITOnlinePaymentSepAccDService.java
new file mode 100644
index 00000000..4cf631ee
--- /dev/null
+++ b/bd-third/src/main/java/com/hzs/third/pay/service/ITOnlinePaymentSepAccDService.java
@@ -0,0 +1,16 @@
+package com.hzs.third.pay.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.hzs.common.domain.third.pay.TOnlinePaymentSepAccD;
+
+/**
+ *
+ * 支付请求子表(分账) 服务类
+ *
+ *
+ * @author bd
+ * @since 2025-07-01
+ */
+public interface ITOnlinePaymentSepAccDService extends IService {
+
+}
diff --git a/bd-third/src/main/java/com/hzs/third/pay/service/ITOnlinePaymentSepAccService.java b/bd-third/src/main/java/com/hzs/third/pay/service/ITOnlinePaymentSepAccService.java
new file mode 100644
index 00000000..dd382d26
--- /dev/null
+++ b/bd-third/src/main/java/com/hzs/third/pay/service/ITOnlinePaymentSepAccService.java
@@ -0,0 +1,16 @@
+package com.hzs.third.pay.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.hzs.common.domain.third.pay.TOnlinePaymentSepAcc;
+
+/**
+ *
+ * 支付请求主表 服务类
+ *
+ *
+ * @author bd
+ * @since 2025-07-01
+ */
+public interface ITOnlinePaymentSepAccService extends IService {
+ void saveOrUpdateReq(TOnlinePaymentSepAcc tOnlinePaymentSepAcc);
+}
diff --git a/bd-third/src/main/java/com/hzs/third/pay/service/impl/JdPayServiceImpl.java b/bd-third/src/main/java/com/hzs/third/pay/service/impl/JdPayServiceImpl.java
index b6e58684..d3a17d31 100644
--- a/bd-third/src/main/java/com/hzs/third/pay/service/impl/JdPayServiceImpl.java
+++ b/bd-third/src/main/java/com/hzs/third/pay/service/impl/JdPayServiceImpl.java
@@ -1,5 +1,6 @@
package com.hzs.third.pay.service.impl;
+import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.hzs.common.core.config.BdConfig;
import com.hzs.common.core.domain.R;
@@ -9,7 +10,11 @@ import com.hzs.common.core.enums.EEnv;
import com.hzs.common.core.utils.DateUtils;
import com.hzs.common.domain.third.pay.TOnlineCard;
import com.hzs.common.domain.third.pay.TOnlinePayment;
+import com.hzs.common.domain.third.pay.TOnlinePaymentSepAcc;
+import com.hzs.common.domain.third.pay.TOnlinePaymentSepAccD;
import com.hzs.third.pay.config.JdPayConfig;
+import com.hzs.third.pay.config.JdPayProperties;
+import com.hzs.third.pay.config.JdPaySeparateAccountConfig;
import com.hzs.third.pay.constants.JdPayConstants;
import com.hzs.third.pay.constants.PayRedisConstants;
import com.hzs.third.pay.dto.jd.JdFastDTO;
@@ -20,9 +25,14 @@ import com.hzs.third.pay.enums.EJdAppType;
import com.hzs.third.pay.enums.EJdTerminalType;
import com.hzs.third.pay.jdpay.dto.JdPayAggregateCreateOrderRequest;
import com.hzs.third.pay.jdpay.dto.JdPayAggregateCreateOrderResponse;
+import com.hzs.third.pay.jdpay.dto.JdPayDivisionAccount;
+import com.hzs.third.pay.jdpay.dto.JdPayDivisionAccountTradeInfo;
import com.hzs.third.pay.jdpay.sdk.JdPay;
+import com.hzs.third.pay.jdpay.util.GsonUtil;
import com.hzs.third.pay.service.IJdPayService;
import com.hzs.third.pay.service.ITOnlineCardService;
+import com.hzs.third.pay.service.ITOnlinePaymentSepAccService;
+import com.hzs.third.pay.service.ITOnlinePaymentService;
import com.hzs.third.pay.util.JdPayUtil;
import com.hzs.third.pay.util.PayUtil;
import lombok.extern.slf4j.Slf4j;
@@ -34,6 +44,8 @@ import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.TimeUnit;
/**
@@ -49,9 +61,15 @@ public class JdPayServiceImpl implements IJdPayService {
private ITOnlineCardService itOnlineCardService;
@Resource
private JdPay jdPay;
-
+ @Autowired
+ private JdPayProperties jdPayProperties;
@Autowired
private RedisTemplate redisTemplate;
+ @Autowired
+ private ITOnlinePaymentSepAccService itOnlinePaymentSepAccService;
+
+ @Autowired
+ private ITOnlinePaymentService itOnlinePaymentService;
/**
* 页面回调地址
@@ -241,12 +259,24 @@ public class JdPayServiceImpl implements IJdPayService {
// 请求京东支付接口
JdPayAggregateCreateOrderResponse response = jdPay.aggregateCreateOrder(request);
-
+ TOnlinePaymentSepAcc sepAcc = TOnlinePaymentSepAcc.builder()
+ .sepAccDList(sepAccDList)
+ .reqContent(request.getDivisionAccount())
+ .reqContentSepAcc(JSONUtil.toJsonStr(divisionAccountTradeInfoList))
+ .version(divisionAccount.getVersion())
+ .respContent(JSONUtil.toJsonStr(response))
+ .tradeAmount(onlinePayment.getPayMoney())
+ .build();
if ("0000".equals(response.getResultCode())) {
// 请求响应成功
// 京东唯一订单号
onlinePayment.setPayNumber(response.getTradeNo());
-
+ // 将controller内入库逻辑移至此为止
+ onlinePayment.setPayMoney(null);
+ itOnlinePaymentService.saveOrUpdate(onlinePayment);
+ // 2025年7月1日 保存分账主表&子表
+ sepAcc.setPkPayment(onlinePayment.getPkId());
+ itOnlinePaymentSepAccService.saveOrUpdateReq(sepAcc);
if ("AGGRE_QR".equals(tradeType)) {
return R.ok(response.getQrCode());
}
@@ -261,4 +291,5 @@ public class JdPayServiceImpl implements IJdPayService {
}
}
+
}
diff --git a/bd-third/src/main/java/com/hzs/third/pay/service/impl/RefundServiceImpl.java b/bd-third/src/main/java/com/hzs/third/pay/service/impl/RefundServiceImpl.java
index 9d747ee8..8d93de4c 100644
--- a/bd-third/src/main/java/com/hzs/third/pay/service/impl/RefundServiceImpl.java
+++ b/bd-third/src/main/java/com/hzs/third/pay/service/impl/RefundServiceImpl.java
@@ -1,5 +1,6 @@
package com.hzs.third.pay.service.impl;
+import cn.hutool.json.JSONUtil;
import com.hzs.common.core.domain.R;
import com.hzs.common.core.enums.*;
import com.hzs.common.core.utils.*;
@@ -10,14 +11,20 @@ import com.hzs.sale.refund.ISaRefundServiceApi;
import com.hzs.third.pay.config.*;
import com.hzs.third.pay.constants.*;
import com.hzs.third.pay.dto.RefundDTO;
+import com.hzs.third.pay.jdpay.dto.JdPayRefundRequest;
+import com.hzs.third.pay.jdpay.dto.JdPayRefundResponse;
+import com.hzs.third.pay.jdpay.sdk.JdPay;
import com.hzs.third.pay.service.IAllInPayService;
import com.hzs.third.pay.service.IRefundService;
import com.hzs.third.pay.service.ITOnlineRefundService;
+import com.hzs.third.pay.util.JdPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
+import javax.annotation.Resource;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.util.*;
@@ -35,9 +42,17 @@ public class RefundServiceImpl implements IRefundService {
private IAllInPayService iAllInPayService;
@Autowired
private ITOnlineRefundService itOnlineRefundService;
+ @Autowired
+ private JdPayConfig jdPayConfig;
@DubboReference
ISaRefundServiceApi iSaRefundServiceApi;
+ @Value("${jd.pay.refundNotifyUrl}")
+ private String refundNotifyUrl;
+
+ @Resource
+ private JdPay jdPay;
+
@Override
public String allInRefundHandle(RefundDTO refundDTO, TOnlinePayment tOnlinePayment) {
@@ -251,4 +266,135 @@ public class RefundServiceImpl implements IRefundService {
return false;
}
+
+ @Override
+ public String jdRefundHandle(RefundDTO refundDTO, TOnlinePayment tOnlinePayment) {
+ try {
+ // 退款金额(默认按全款退)
+ BigDecimal amount = tOnlinePayment.getPayMoney();
+ if (null != refundDTO.getRefundAmount()) {
+ // 如果传入实际退款金额,则按实际退款金额处理
+ amount = refundDTO.getRefundAmount();
+ }
+
+ // 退款编号
+ String refundCode = CommonUtil.createSerialNumber(EOrderPrefix.REFUND_CODE);
+
+ Map requestMap = new HashMap<>();
+ requestMap.put("version", JdPayConstants.PAY_VERSION);
+ // 商户编号
+ requestMap.put("customerNum", jdPayConfig.getCustomerNum());
+ // 店铺编号
+ requestMap.put("shopNum", jdPayConfig.getShopNum());
+
+ // 商户订单号
+ requestMap.put("requestNum", tOnlinePayment.getOriginalOrder());
+ // 商户退款订单号
+ requestMap.put("refundRequestNum", refundCode);
+ // 退款金额
+ requestMap.put("refundPartAmount", amount.toString());
+ // 退款回调地址
+ requestMap.put("callbackUrl", jdPayConfig.getRefundCallbackUrl());
+
+ String body = JSONUtil.toJsonStr(requestMap);
+
+ log.info("京东退款请求参数: {}", body);
+
+ String postResult = JdPayUtil.requestOrder(JdPayConstants.REFUND_ORDER, body, jdPayConfig.getSecretKey(), jdPayConfig.getAccessKey());
+
+ log.info("京东退款返回数据: {}", postResult);
+
+ Map resultMap = JSONUtil.toBean(postResult, HashMap.class);
+
+ if (JdPayConstants.RESULT_SUCCESS.equals(resultMap.get("result").toString())) {
+ // 返回成功
+
+ // 返回业务数据
+ cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(resultMap.get("data"));
+
+ // 申请退款成功,保存退款
+ TOnlineRefund tOnlineRefund = new TOnlineRefund();
+ tOnlineRefund.setRefundCode(refundCode);
+ tOnlineRefund.setPkOnlinePayment(tOnlinePayment.getPkId());
+ tOnlineRefund.setBusinessCode(refundDTO.getRefundBusinessCode());
+ tOnlineRefund.setRefundMoney(amount);
+ tOnlineRefund.setRefundChannel(tOnlinePayment.getPayChannel());
+ tOnlineRefund.setRefundNumber(jsonObject.getStr("orderNum"));
+ tOnlineRefund.setPkCountry(refundDTO.getPkCountry());
+ tOnlineRefund.setPkCreator(refundDTO.getUserId());
+ if (itOnlineRefundService.save(tOnlineRefund)) {
+ return null;
+ }
+ log.error("调用京东退款入库失败, tOnlineRefund: {}", tOnlineRefund);
+ } else {
+ log.error("调用京东退款返回失败:{}", resultMap.get("errorMsg"));
+ }
+ return "退款失败,请重试";
+ } catch (Exception e) {
+ log.error("调用京东退款处理返回异常!", e);
+ return "退款异常,请重试";
+ }
+ }
+
+ @Override
+ public String jdCashRefundHandle(RefundDTO refundDTO, TOnlinePayment tOnlinePayment) {
+ try {
+ // 退款金额(默认按全款退)
+ BigDecimal amount = tOnlinePayment.getPayMoney();
+ if (null != refundDTO.getRefundAmount()) {
+ // 如果传入实际退款金额,则按实际退款金额处理
+ amount = refundDTO.getRefundAmount();
+ }
+
+ // 退款编号
+ String refundCode = CommonUtil.createSerialNumber(EOrderPrefix.REFUND_CODE);
+ // 当前时间
+ Date nowDate = new Date();
+
+ JdPayRefundRequest request = JdPayRefundRequest.builder()
+ // 退款订单号
+ .outTradeNo(refundCode)
+ // 原订单号(需要退款的订单号)
+ .originalOutTradeNo(tOnlinePayment.getBusinessCode())
+ // 退款时间
+ .tradeDate(DateUtils.parseDateToFormat(DateUtils.YAMMERERS, nowDate))
+ // 退款金额
+ .tradeAmount(amount.multiply(new BigDecimal("100")).intValue() + "")
+ // 货币种类
+ .currency("CNY")
+ // 退款回调地址
+ .notifyUrl(this.refundNotifyUrl)
+ // 回传信息
+// .returnParams("")
+ .build();
+
+ // 请求京东退款接口
+ JdPayRefundResponse response = jdPay.refund(request);
+
+ if ("0000".equals(response.getResultCode())) {
+ // 请求响应成功
+ // 申请退款成功,保存退款
+ TOnlineRefund tOnlineRefund = new TOnlineRefund();
+ tOnlineRefund.setRefundCode(refundCode);
+ tOnlineRefund.setPkOnlinePayment(tOnlinePayment.getPkId());
+ tOnlineRefund.setBusinessCode(refundDTO.getRefundBusinessCode());
+ tOnlineRefund.setRefundMoney(amount);
+ tOnlineRefund.setRefundChannel(tOnlinePayment.getPayChannel());
+ tOnlineRefund.setRefundNumber(response.getTradeNo());
+ tOnlineRefund.setPkCountry(refundDTO.getPkCountry());
+ tOnlineRefund.setPkCreator(refundDTO.getUserId());
+ if (itOnlineRefundService.save(tOnlineRefund)) {
+ return null;
+ } else {
+ log.error("调用京东收银台退款入库处理失败,desc: {}", response.getResultDesc());
+ return "退款失败,请联系系统管理员处理";
+ }
+ }
+ log.error("调用京东收银台退款处理失败,desc: {}", response.getResultDesc());
+ return "退款失败,请重试";
+ } catch (Exception e) {
+ log.error("调用京东收银台退款处理返回异常!", e);
+ return "退款异常,请重试";
+ }
+ }
}
diff --git a/bd-third/src/main/java/com/hzs/third/pay/service/impl/TOnlinePaymentSepAccDServiceImpl.java b/bd-third/src/main/java/com/hzs/third/pay/service/impl/TOnlinePaymentSepAccDServiceImpl.java
new file mode 100644
index 00000000..58929229
--- /dev/null
+++ b/bd-third/src/main/java/com/hzs/third/pay/service/impl/TOnlinePaymentSepAccDServiceImpl.java
@@ -0,0 +1,20 @@
+package com.hzs.third.pay.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.hzs.common.domain.third.pay.TOnlinePaymentSepAccD;
+import com.hzs.third.pay.mapper.TOnlinePaymentSepAccDMapper;
+import com.hzs.third.pay.service.ITOnlinePaymentSepAccDService;
+import org.springframework.stereotype.Service;
+
+/**
+ *
+ * 支付请求子表(分账) 服务实现类
+ *
+ *
+ * @author bd
+ * @since 2025-07-01
+ */
+@Service
+public class TOnlinePaymentSepAccDServiceImpl extends ServiceImpl implements ITOnlinePaymentSepAccDService {
+
+}
diff --git a/bd-third/src/main/java/com/hzs/third/pay/service/impl/TOnlinePaymentSepAccServiceImpl.java b/bd-third/src/main/java/com/hzs/third/pay/service/impl/TOnlinePaymentSepAccServiceImpl.java
new file mode 100644
index 00000000..aadf5ac3
--- /dev/null
+++ b/bd-third/src/main/java/com/hzs/third/pay/service/impl/TOnlinePaymentSepAccServiceImpl.java
@@ -0,0 +1,59 @@
+package com.hzs.third.pay.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.hzs.common.core.utils.DateUtils;
+import com.hzs.common.domain.third.pay.TOnlinePaymentSepAcc;
+import com.hzs.common.domain.third.pay.TOnlinePaymentSepAccD;
+import com.hzs.common.security.utils.SecurityUtils;
+import com.hzs.third.pay.mapper.TOnlinePaymentSepAccMapper;
+import com.hzs.third.pay.service.ITOnlinePaymentSepAccDService;
+import com.hzs.third.pay.service.ITOnlinePaymentSepAccService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ *
+ * 支付请求主表 服务实现类
+ *
+ *
+ * @author bd
+ * @since 2025-07-01
+ */
+@Service
+public class TOnlinePaymentSepAccServiceImpl extends ServiceImpl implements ITOnlinePaymentSepAccService {
+
+ @Autowired
+ private ITOnlinePaymentSepAccDService itOnlinePaymentSepAccDService;
+ @Override
+ public void saveOrUpdateReq(TOnlinePaymentSepAcc tOnlinePaymentSepAcc) {
+ LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
+ wrapper.eq(TOnlinePaymentSepAcc::getPkPayment, tOnlinePaymentSepAcc.getPkPayment());
+ TOnlinePaymentSepAcc source = this.getOne(wrapper, false);
+ if(ObjectUtil.isNotEmpty(source)){
+ tOnlinePaymentSepAcc.setPkId(source.getPkId());
+ }else{
+ tOnlinePaymentSepAcc.setCreationTime(DateUtils.currentDateTime());
+ tOnlinePaymentSepAcc.setPkCreator(SecurityUtils.getUserId());
+ }
+ tOnlinePaymentSepAcc.setModifiedTime(DateUtils.currentDateTime());
+ tOnlinePaymentSepAcc.setPkModified(SecurityUtils.getUserId());
+ this.save(tOnlinePaymentSepAcc);
+ LambdaQueryWrapper wrapperD = new LambdaQueryWrapper<>();
+ wrapperD.eq(TOnlinePaymentSepAccD::getPkSepAcc, tOnlinePaymentSepAcc.getPkId());
+ itOnlinePaymentSepAccDService.remove(wrapperD);
+ if(CollUtil.isNotEmpty(tOnlinePaymentSepAcc.getSepAccDList())){
+ for (TOnlinePaymentSepAccD tOnlinePaymentSepAccD : tOnlinePaymentSepAcc.getSepAccDList()) {
+ tOnlinePaymentSepAccD.setPkSepAcc(tOnlinePaymentSepAcc.getPkId());
+ tOnlinePaymentSepAccD.setCreationTime(DateUtils.currentDateTime());
+ tOnlinePaymentSepAccD.setPkCreator(SecurityUtils.getUserId());
+ tOnlinePaymentSepAccD.setModifiedTime(DateUtils.currentDateTime());
+ tOnlinePaymentSepAccD.setPkModified(SecurityUtils.getUserId());
+ }
+ itOnlinePaymentSepAccDService.saveBatch(tOnlinePaymentSepAcc.getSepAccDList());
+ }
+
+ }
+}
diff --git a/bd-third/src/main/resources/bootstrap.yml b/bd-third/src/main/resources/bootstrap.yml
index cb1ee881..ad31f194 100644
--- a/bd-third/src/main/resources/bootstrap.yml
+++ b/bd-third/src/main/resources/bootstrap.yml
@@ -101,12 +101,19 @@ jd:
## 生产环境api接口域名
apiDomain: http://wapi.jd.com
## 页面回调地址
- pageBackUrl: https://t-app.beida666.com/prod-api/pay/jd/sync-notify
+# pageBackUrl: https://t-app.beida666.com/prod-api/pay/jd/sync-notify
+ pageBackUrl: https://t-app.beida666.com/#/pages/pay/index
## 支付回调地址
- notifyUrl: https://t-app.beida666.com/prod-api/pay/jd/trade-notify
+# notifyUrl: https://t-app.beida666.com/prod-api/pay/jd/trade-notify
+ notifyUrl: https://b747-218-57-66-5.ngrok-free.app/pay/jd/trade-notify
## 退款回调地下
- refundNotifyUrl: https://t-app.beida666.com/prod-api/pay/jd-refund/trade-notify
-
+# refundNotifyUrl: https://t-app.beida666.com/prod-api/pay/jd-refund/trade-notify
+ refundNotifyUrl: https://b747-218-57-66-5.ngrok-free.app/pay/jd-refund/trade-notify
+ separateAccounts:
+ - account: 153428607007
+ proportion: 0.5
+ - account: 153428607005
+ proportion: 0.5
## 通联支付配置
allinpay:
# #################### 基础支付相关(正式) ####################
diff --git a/bd-third/src/main/resources/mapper/third/pay/TOnlinePaymentSepAccDMapper.xml b/bd-third/src/main/resources/mapper/third/pay/TOnlinePaymentSepAccDMapper.xml
new file mode 100644
index 00000000..0eaa9269
--- /dev/null
+++ b/bd-third/src/main/resources/mapper/third/pay/TOnlinePaymentSepAccDMapper.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DEL_FLAG,
+ CREATION_TIME,
+ MODIFIED_TIME,
+ PK_CREATOR,
+ PK_MODIFIED,
+ PK_ID, PK_SEP_ACC, ACCOUNT, PROPORTION
+
+
+
diff --git a/bd-third/src/main/resources/mapper/third/pay/TOnlinePaymentSepAccMapper.xml b/bd-third/src/main/resources/mapper/third/pay/TOnlinePaymentSepAccMapper.xml
new file mode 100644
index 00000000..a7a28bfe
--- /dev/null
+++ b/bd-third/src/main/resources/mapper/third/pay/TOnlinePaymentSepAccMapper.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DEL_FLAG,
+ CREATION_TIME,
+ MODIFIED_TIME,
+ PK_CREATOR,
+ PK_MODIFIED,
+ PK_ID, PK_PAYMENT, VERSION, REQ_CONTENT, REQ_CONTENT_SEP_ACC, RESP_CONTENT
+
+
+
diff --git a/sql/2025年7月1日_京东支付_分账.sql b/sql/2025年7月1日_京东支付_分账.sql
new file mode 100644
index 00000000..9e5e94d5
--- /dev/null
+++ b/sql/2025年7月1日_京东支付_分账.sql
@@ -0,0 +1,89 @@
+CREATE TABLE "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC" (
+ "PK_ID" NUMBER(20,0),
+ "PK_PAYMENT" NUMBER(20,0),
+ "VERSION" VARCHAR2(255),
+ "REQ_CONTENT" VARCHAR2(1024),
+ "REQ_CONTENT_SEP_ACC" VARCHAR2(1024),
+ "RESP_CONTENT" VARCHAR2(2048),
+ "DEL_FLAG" NUMBER(1),
+ "PK_COUNTRY" NUMBER(4,0) DEFAULT 1 NOT NULL ENABLE,
+ "CREATION_TIME" DATE,
+ "MODIFIED_TIME" DATE,
+ "PK_CREATOR" NUMBER(20,0),
+ "PK_MODIFIED" NUMBER(20,0),
+ PRIMARY KEY ("PK_ID")
+)
+;
+
+COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."PK_PAYMENT" IS '在线支付信息ID';
+
+COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."VERSION" IS '版本号';
+
+COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."REQ_CONTENT" IS '支付请求信息';
+
+COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."REQ_CONTENT_SEP_ACC" IS '分账请求信息';
+
+COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."RESP_CONTENT" IS '支付响应信息';
+
+COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."DEL_FLAG" IS '逻辑删除 (0=未删除,1已删除)';
+
+COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."CREATION_TIME" IS '创建时间';
+
+COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."MODIFIED_TIME" IS '修改时间';
+
+COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."PK_CREATOR" IS '创建者';
+
+COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."PK_MODIFIED" IS '更新者';
+
+COMMENT ON TABLE "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC" IS '支付请求主表';
+
+CREATE SEQUENCE T_ONLINE_PAYMENT_SEP_ACC_SEQ
+ START WITH 1
+ INCREMENT BY 1;
+
+CREATE TABLE "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D" (
+ "PK_ID" NUMBER(20,0),
+ "PK_SEP_ACC" NUMBER(20,0),
+ "ACCOUNT" VARCHAR2(255),
+ "PROPORTION" NUMBER(10, 2),
+ "DEL_FLAG" NUMBER(1),
+ "PK_COUNTRY" NUMBER(4,0) DEFAULT 1 NOT NULL ENABLE,
+ "CREATION_TIME" DATE,
+ "MODIFIED_TIME" DATE,
+ "PK_CREATOR" NUMBER(20,0),
+ "PK_MODIFIED" NUMBER(20,0),
+ PRIMARY KEY ("PK_ID")
+)
+;
+
+COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D"."PK_SEP_ACC" IS '支付请求主表ID';
+
+COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D"."ACCOUNT" IS '分账账号';
+
+COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D"."PROPORTION" IS '分账比例';
+
+COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D"."DEL_FLAG" IS '逻辑删除 (0=未删除,1已删除)';
+
+COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D"."CREATION_TIME" IS '创建时间';
+
+COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D"."MODIFIED_TIME" IS '修改时间';
+
+COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D"."PK_CREATOR" IS '创建者';
+
+COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D"."PK_MODIFIED" IS '更新者';
+
+COMMENT ON TABLE "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D" IS '支付请求子表(分账)';
+
+CREATE SEQUENCE T_ONLINE_PAYMENT_SEP_ACC_D_SEQ
+ START WITH 1
+ INCREMENT BY 1;
+
+
+ALTER TABLE "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"
+ ADD ("TRADE_AMOUNT" NUMBER(16,2));
+COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC"."TRADE_AMOUNT" IS '总金额';
+
+
+ALTER TABLE "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D"
+ ADD ("TRADE_AMOUNT" NUMBER(16,2));
+COMMENT ON COLUMN "CLOUD_2"."T_ONLINE_PAYMENT_SEP_ACC_D"."TRADE_AMOUNT" IS '分账金额';
diff --git a/文档/支付/支付回调/京东 b/文档/支付/支付回调/京东
new file mode 100644
index 00000000..8598f156
--- /dev/null
+++ b/文档/支付/支付回调/京东
@@ -0,0 +1,5 @@
+正常支付回调:
+ {"signData":"CFC402DAEBC319048859760C3C1076E252A0AA8E06480D33ABE8E9E4F6F64942","charset":"UTF-8","encType":"AP7","code":"00000","signType":"SHA-256","respData":"eyJiYW5rQ29kZSI6IkNDQiIsInRyYWRlTm8iOiIyMDI1MDcwMTE0MDI0MzIwMTE4MzAyNzYyOTk0MTkiLCJyZXN1bHRDb2RlIjoiMDAwMCIsImNhcmRUeXBlIjoiREUiLCJtYXNrQ2FyZE5vIjoiMDMwNSIsInJlc3VsdERlc2MiOiLmiJDlip8iLCJiYW5rU3VibWl0Tm8iOiIwNzAxNjU5MDI3NDk2MTUzIiwidXNlcklkIjoiVF8xMDkiLCJleHRJbmZvIjoie30iLCJwYXlUb29sIjoiRVhQUiIsInRyYWRlQW1vdW50IjoiMiIsInJldHVyblBhcmFtcyI6IjEiLCJvdXRUcmFkZU5vIjoiQkRTTzE3NTEzNDk3NTE0MDk2MDgiLCJ0cmFkZVN0YXR1cyI6IkZJTkkiLCJmaW5pc2hEYXRlIjoiMjAyNTA3MDExNDAzMTciLCJjdXJyZW5jeSI6IkNOWSIsInRyYWRlVHlwZSI6IkFHR1JFIn0=","formatType":"JSON","desc":"成功","merchantNo":"153428607005"}
+退款回调: 入口(my-order/self-revoke-order)
+
+