撤销支付接口

This commit is contained in:
HH 2022-06-01 16:29:52 +08:00
parent 6400095500
commit 2423fd9fe2
19 changed files with 233 additions and 34 deletions

View File

@ -6,7 +6,6 @@ import com.ghy.common.utils.StringUtils;
import com.ghy.customer.domain.Customer;
import com.ghy.customer.service.CustomerService;
import com.ghy.goods.domain.DeptGoodsCategory;
import com.ghy.goods.domain.Goods;
import com.ghy.goods.domain.GoodsStandard;
import com.ghy.goods.request.AppGoodsRequest;
import com.ghy.goods.service.DeptGoodsCategoryService;
@ -109,7 +108,7 @@ public class OrderController extends BaseController {
orderDetailService.insertOrderDetail(od);
// 批量生成订单商品
request.getGoodsList().forEach(goods->{
request.getGoodsList().forEach(goods -> {
OrderGoods orderGoods = new OrderGoods();
orderGoods.setGoodsId(goods.getGoodsStandardId());
orderGoods.setGoodsNum(goods.getNum());
@ -229,10 +228,10 @@ public class OrderController extends BaseController {
* 生成财务子单
*
* @param deptGoodsCategoryId 商品类目id
* @param deptId 商户ID
* @param customer 消费者
* @param payMoney 实付金额
* @param financialMaster 财务主单
* @param deptId 商户ID
* @param customer 消费者
* @param payMoney 实付金额
* @param financialMaster 财务主单
*/
private void createFinancialDetail(Long deptGoodsCategoryId, Long deptId, Customer customer, BigDecimal payMoney, FinancialMaster financialMaster) {
// 是否为0元购 是的话下面就不用多级分销了
@ -247,8 +246,8 @@ public class OrderController extends BaseController {
BigDecimal deptTotal = payMoney.multiply(deptRate).add(deptMoney);
FinancialDetail deptDetail = new FinancialDetail(financialDetailService.createCode(), deptId,
financialMaster.getId(), financialMaster.getCode(), deptTotal, 3, null);
FinancialDetail deptDetail = new FinancialDetail(deptId, financialDetailService.createCode(),
financialMaster.getId(), financialMaster.getCode(), deptTotal, 3, null);
financialDetailService.insertFinancialDetail(deptDetail);
/* 2 截留扣点 */
@ -257,8 +256,8 @@ public class OrderController extends BaseController {
BigDecimal retainTotal = payMoney.multiply(retainRate).add(retainMoney);
FinancialDetail retainDetail = new FinancialDetail(financialDetailService.createCode(), deptId,
financialMaster.getId(), financialMaster.getCode(), retainTotal, 2, null);
FinancialDetail retainDetail = new FinancialDetail(deptId, financialDetailService.createCode(),
financialMaster.getId(), financialMaster.getCode(), retainTotal, 2, null);
financialDetailService.insertFinancialDetail(retainDetail);
/* 3 分销扣点 */
@ -271,26 +270,26 @@ public class OrderController extends BaseController {
// 一级分销
if (customerPlaceId != null) {
FinancialDetail financialDetail = new FinancialDetail(financialDetailService.createCode(), deptId,
FinancialDetail financialDetail = new FinancialDetail(deptId, financialDetailService.createCode(),
financialMaster.getId(), financialMaster.getCode(), onePlaceMoney, 2, customerPlaceId);
financialDetailService.insertFinancialDetail(financialDetail);
}else {
} else {
deptPlaceTotal = deptPlaceTotal.add(onePlaceMoney);
}
// 二级分销
Long parentCustomerPlaceId = customer.getParentCustomerPlace();
if (parentCustomerPlaceId != null) {
FinancialDetail financialDetail = new FinancialDetail(financialDetailService.createCode(), deptId,
FinancialDetail financialDetail = new FinancialDetail(deptId, financialDetailService.createCode(),
financialMaster.getId(), financialMaster.getCode(), twoPlaceMoney, 2, parentCustomerPlaceId);
financialDetailService.insertFinancialDetail(financialDetail);
}else {
} else {
deptPlaceTotal = deptPlaceTotal.add(twoPlaceMoney);
}
// 平台分销
deptPlaceTotal = deptPlaceTotal.add(threePlaceMoney);
FinancialDetail financialDetail = new FinancialDetail(financialDetailService.createCode(), deptId,
FinancialDetail financialDetail = new FinancialDetail(deptId, financialDetailService.createCode(),
financialMaster.getId(), financialMaster.getCode(), deptPlaceTotal, 2, null);
financialDetailService.insertFinancialDetail(financialDetail);
}

View File

@ -0,0 +1,60 @@
package com.ghy.web.controller.pay;
import com.alibaba.fastjson.JSONObject;
import com.ghy.common.adapay.model.AdapayStatusEnum;
import com.ghy.common.core.domain.AjaxResult;
import com.ghy.order.domain.OrderMaster;
import com.ghy.order.service.OrderMasterService;
import com.ghy.payment.domain.FinancialMaster;
import com.ghy.payment.service.AdapayService;
import com.ghy.payment.service.FinancialMasterService;
import com.huifu.adapay.core.exception.BaseAdaPayException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
/**
* @author HH 2022/6/1
*/
@Controller
@RequestMapping("pay")
public class PayController {
private static final Logger logger = LoggerFactory.getLogger(PayController.class);
@Resource
private AdapayService adapayService;
@Resource
private OrderMasterService orderMasterService;
@Resource
private FinancialMasterService financialMasterService;
/**
* 撤销支付
*
* @param orderMasterId 主订单ID
* @param reverseAmt 撤销金额 保留两位小数
*/
@PostMapping("reverse")
@ResponseBody
public AjaxResult reverse(Long orderMasterId, String reverseAmt) throws BaseAdaPayException {
OrderMaster orderMaster = orderMasterService.selectById(orderMasterId);
Assert.notNull(orderMaster, "找不到对应的订单");
FinancialMaster financialMaster = financialMasterService.selectByOrderMasterId(orderMasterId);
Assert.notNull(financialMaster, "找不到订单");
Assert.isTrue(financialMaster.getPayStatus() == 1, "订单未支付");
Assert.hasText(financialMaster.getPaymentId(), "找不到订单的支付记录,请联系管理员");
JSONObject response = adapayService.payReverse(orderMaster.getDeptId(), financialMaster.getPaymentId(), reverseAmt);
if (AdapayStatusEnum.succeeded.code.equals(response.getString("status"))) {
return AjaxResult.success();
} else {
return AjaxResult.error(response.getString("error_msg"));
}
}
}

View File

@ -3,6 +3,8 @@ package com.ghy.common.adapay;
import com.ghy.common.adapay.model.Merchant;
import com.huifu.adapay.Adapay;
import com.huifu.adapay.model.MerConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.Assert;
@ -21,6 +23,8 @@ import java.util.stream.Collectors;
@EnableConfigurationProperties(AdapayProperties.class)
public class AdapayConfig {
private static final Logger logger = LoggerFactory.getLogger(AdapayConfig.class);
/**
* 商户配置
*/
@ -38,6 +42,7 @@ public class AdapayConfig {
Assert.notEmpty(merchants, "Merchants is empty!");
Map<String, MerConfig> configPathMap = new HashMap<>(merchants.size());
for (Merchant merchant : merchants) {
logger.info("Adapay load merchant : {}", merchant.getDeptId());
check(merchant);
MerConfig merConfig = new MerConfig();
merConfig.setApiKey(merchant.getApiKey());

View File

@ -9,7 +9,7 @@ import lombok.Data;
* @author HH 2022/4/1
*/
@Data
public class DrawCashReply {
public class DrawCashCallback {
/**
* 订单号

View File

@ -9,7 +9,7 @@ import lombok.Data;
* @author HH 2022/3/29
*/
@Data
public class PayReply {
public class PayCallback {
/**
* 返参必填由AdaPay生成的支付对象 ID

View File

@ -0,0 +1,43 @@
package com.ghy.common.adapay.model;
import com.alibaba.fastjson.annotation.JSONField;
import lombok.Data;
/**
* 撤销支付后Adapay回调接口传过来的数据
*
* @author HH 2022/5/31
*/
@Data
public class PayReverseCallback {
private String id;
private String status;
@JSONField(name = "error_code")
private String errorCode;
@JSONField(name = "error_msg")
private String errorMsg;
@JSONField(name = "error_type")
private String errorType;
@JSONField(name = "prod_mode")
private String prodMode;
@JSONField(name = "order_no")
private String orderNo;
@JSONField(name = "payment_id")
private String paymentId;
@JSONField(name = "reverse_amt")
private String reverseAmt;
@JSONField(name = "reversed_amt")
private String reversedAmt;
@JSONField(name = "confirmed_amt")
private String confirmedAmt;
@JSONField(name = "refunded_amt")
private String refundedAmt;
@JSONField(name = "createdTime")
private String created_time;
@JSONField(name = "succeed_time")
private String succeedTime;
@JSONField(name = "channel_no")
private String channelNo;
private String reason;
}

View File

@ -9,7 +9,7 @@ import lombok.Data;
* @author HH 2022/3/29
*/
@Data
public class RefundReply {
public class RefundCallback {
/**
* 退款目标支付对象 id
*/

View File

@ -46,18 +46,24 @@ public class FinancialDetail extends BaseEntity {
@Excel(name = "实付金额", cellType = Excel.ColumnType.STRING)
private BigDecimal payMoney;
@Excel(name = "财务子单类型,1师傅转派/2多级分销/3平台抽成", cellType = Excel.ColumnType.NUMERIC)
@Excel(name = "财务子单类型,1师傅转派/2多级分销/3平台抽成/4撤销支付或退款", cellType = Excel.ColumnType.NUMERIC)
private Integer financialDetailType;
/**
* 收款人ID
* 当财务子单类型是师傅转派时 收款人ID是师傅或徒弟的workerId
* 当财务子单类型是多级分销时 收款人ID是分销者的customerId
* 当财务子单类型是平台抽成 无需填写收款人ID
* 当财务子单类型是平台抽成和退款时 无需填写收款人ID
*/
@Excel(name = "收款人ID", cellType = Excel.ColumnType.NUMERIC)
private Long payeeId;
/**
* Adapay撤销支付或退款ID
*/
@Excel(name = "Adapay撤销支付或退款ID", cellType = Excel.ColumnType.STRING)
private String reverseId;
@Excel(name = "支付方式,微信/支付宝/线下", cellType = Excel.ColumnType.NUMERIC)
private Integer payType;
@ -74,7 +80,8 @@ public class FinancialDetail extends BaseEntity {
this.financialMasterId = financialMasterId;
}
public FinancialDetail(String code, Long deptId, Long financialMasterId, String financialMasterCode, BigDecimal payMoney, Integer financialDetailType, Long payeeId) {
public FinancialDetail(Long deptId, String code, Long financialMasterId, String financialMasterCode,
BigDecimal payMoney, Integer financialDetailType, Long payeeId) {
this.deptId = deptId;
this.code = code;
this.financialMasterId = financialMasterId;
@ -84,7 +91,9 @@ public class FinancialDetail extends BaseEntity {
this.payeeId = payeeId;
}
public FinancialDetail(Long deptId, String code, Long financialMasterId, String financialMasterCode, Long orderDetailId, String orderDetailCode, BigDecimal payMoney, Integer financialDetailType, Long payeeId, Integer payType, Integer payStatus, Date payTime) {
public FinancialDetail(Long deptId, String code, Long financialMasterId, String financialMasterCode,
Long orderDetailId, String orderDetailCode, BigDecimal payMoney, Integer financialDetailType,
Long payeeId, Integer payType, Integer payStatus, Date payTime) {
this.deptId = deptId;
this.code = code;
this.financialMasterId = financialMasterId;

View File

@ -48,4 +48,11 @@ public interface FinancialDetailMapper {
* @return 财务细单信息
*/
FinancialDetail checkFinancialDetailCodeUnique(String financialDetailCode);
/**
* 撤销支付成功
*
* @param reverseId 撤销支付ID
*/
void payReverseSucceeded(String reverseId);
}

View File

@ -57,4 +57,11 @@ public interface FinancialMasterMapper {
* @param orderMasterId 主订单ID
*/
FinancialMaster selectByOrderMasterId(Long orderMasterId);
/**
* 用支付ID查询主财务单
*
* @param paymentId 支付ID
*/
FinancialMaster selectByPaymentId(String paymentId);
}

View File

@ -28,10 +28,10 @@ import java.util.List;
@Service
public class AdapayService {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
private static final Logger logger = LoggerFactory.getLogger(AdapayService.class);
@Resource
private PayCallbackService payCallBackService;
private PayCallbackService payCallbackService;
@Resource
private RefundCallbackService refundCallbackService;
@Resource
@ -292,7 +292,7 @@ public class AdapayService {
paymentParams.put("expend", expend);
logger.debug("paymentParams: {}", paymentParams.toJSONString());
JSONObject response = (JSONObject) Payment.create(paymentParams, deptId.toString());
payCallBackService.onResponse(response);
payCallbackService.onResponse(response);
return response;
}
@ -382,7 +382,7 @@ public class AdapayService {
reverseParams.put("reverse_amt", reverseAmt);
reverseParams.put("notify_url", adapayProperties.getNotifyUrl());
reverseParams.put("order_no", "PAYMENT_REVERSE" + System.currentTimeMillis());
JSONObject response = (JSONObject) PaymentReverse.create(reverseParams);
JSONObject response = (JSONObject) PaymentReverse.create(reverseParams, deptId.toString());
payReverseCallbackService.onResponse(response);
return response;
}

View File

@ -55,4 +55,10 @@ public interface FinancialDetailService {
*/
String createCode();
/**
* 撤销支付成功
*
* @param reverseId 撤销支付ID
*/
void payReverseSucceeded(String reverseId);
}

View File

@ -83,4 +83,11 @@ public interface FinancialMasterService {
* @param id 交易ID
*/
PaymentDTO selectPaymentById(String id);
/**
* 用支付ID查询主财务单
*
* @param paymentId 支付ID
*/
FinancialMaster selectByPaymentId(String paymentId);
}

View File

@ -15,7 +15,6 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import static java.time.temporal.ChronoField.*;
import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
@Service
public class FinancialDetailServiceImpl implements FinancialDetailService {
@ -73,4 +72,9 @@ public class FinancialDetailServiceImpl implements FinancialDetailService {
LocalDateTime now = LocalDateTime.now();
return "fd" + now.format(MINI_FORMATTER) + INDEX.getAndIncrement();
}
@Override
public void payReverseSucceeded(String reverseId) {
financialDetailMapper.payReverseSucceeded(reverseId);
}
}

View File

@ -108,4 +108,9 @@ public class FinancialMasterServiceImpl implements FinancialMasterService {
return paymentMapper.selectById(id);
}
@Override
public FinancialMaster selectByPaymentId(String paymentId) {
return financialMasterMapper.selectByPaymentId(paymentId);
}
}

View File

@ -2,9 +2,9 @@ package com.ghy.payment.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ghy.common.adapay.model.Event;
import com.ghy.common.adapay.model.AdapayStatusEnum;
import com.ghy.common.adapay.model.PayReply;
import com.ghy.common.adapay.model.Event;
import com.ghy.common.adapay.model.PayCallback;
import com.ghy.common.adapay.model.PaymentDTO;
import com.ghy.payment.domain.FinancialMaster;
import com.ghy.payment.service.CallBackService;
@ -37,7 +37,7 @@ public class PayCallbackService implements CallBackService {
public void onCallback(Event event) {
logger.debug("pay callback is {}", event);
String data = event.getData();
PayReply payment = JSON.parseObject(data, PayReply.class);
PayCallback payment = JSON.parseObject(data, PayCallback.class);
Assert.hasText(payment.getOrderNo(), "orderNo is blank !!!");
// 校验是否是本系统发出去的回调请求
boolean ours = orderNoSet.remove(payment.getOrderNo());

View File

@ -1,12 +1,22 @@
package com.ghy.payment.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ghy.common.adapay.model.AdapayStatusEnum;
import com.ghy.common.adapay.model.Event;
import com.ghy.common.adapay.model.PayReverseCallback;
import com.ghy.payment.domain.FinancialDetail;
import com.ghy.payment.domain.FinancialMaster;
import com.ghy.payment.service.CallBackService;
import com.ghy.payment.service.FinancialDetailService;
import com.ghy.payment.service.FinancialMasterService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
/**
* 撤销支付回调
*
@ -17,13 +27,37 @@ public class PayReverseCallbackService implements CallBackService {
private static final Logger logger = LoggerFactory.getLogger(PayReverseCallbackService.class);
@Resource
private FinancialMasterService financialMasterService;
@Resource
private FinancialDetailService financialDetailService;
@Override
public void onCallback(Event event) {
logger.debug("撤销支付 callback: {}", event.toString());
logger.debug("撤销支付 callback: {}", event);
PayReverseCallback callback = JSON.parseObject(event.getData(), PayReverseCallback.class);
if (AdapayStatusEnum.succeeded.code.equals(callback.getStatus())) {
// 将子财务单支付状态设置为1 表示退款成功
financialDetailService.payReverseSucceeded(callback.getId());
}
}
@Override
public void onResponse(JSONObject response) {
logger.debug("撤销支付 Response: {}", response.toString());
if (AdapayStatusEnum.succeeded.code.equals(response.getString("status"))) {
String reverseId = response.getString("id");
String paymentId = response.getString("payment_id");
String reverseAmt = response.getString("reverse_amt");
FinancialMaster fm = financialMasterService.selectByPaymentId(paymentId);
// 创建并保存一条子财务单(type=撤销支付)
FinancialDetail fd = new FinancialDetail(fm.getDeptId(), financialDetailService.createCode(), fm.getId(),
fm.getCode(), new BigDecimal(reverseAmt), 4, null);
// 子财务单关联撤销支付ID
fd.setReverseId(reverseId);
financialDetailService.insertFinancialDetail(fd);
} else {
logger.warn("撤销失败: {}", response.toJSONString());
}
}
}

View File

@ -17,6 +17,7 @@
<result property="payMoney" column="pay_money"/>
<result property="financialDetailType" column="financial_detail_type"/>
<result property="payeeId" column="payee_id"/>
<result property="reverseId" column="reverse_id"/>
<result property="payType" column="pay_type"/>
<result property="payStatus" column="pay_status"/>
<result property="payTime" column="pay_time"/>
@ -28,9 +29,9 @@
</resultMap>
<sql id="selectFinancialDetail">
SELECT id, dept_id, code, financial_master_id, financial_master_code, order_detail_id,
order_detail_code, total_money, discount_money, pay_money, financial_detail_type,
payee_id, pay_type, pay_status, pay_time, create_by, create_time, update_by, update_time, remark
SELECT id, dept_id, code, financial_master_id, financial_master_code, order_detail_id, order_detail_code,
total_money, discount_money, pay_money, financial_detail_type,payee_id, reverse_id, pay_type,
pay_status, pay_time, create_by, create_time, update_by, update_time, remark
FROM financial_detail
</sql>
@ -89,6 +90,12 @@
WHERE id = #{id}
</update>
<update id="payReverseSucceeded">
UPDATE financial_detail SET
pay_status = 1
WHERE reverse_id = #{reverseId}
</update>
<insert id="insertFinancialDetail" parameterType="com.ghy.payment.domain.FinancialDetail" useGeneratedKeys="true"
keyProperty="id">
INSERT INTO financial_detail(
@ -103,6 +110,7 @@
<if test="payMoney != null">pay_money,</if>
<if test="financialDetailType != null">financial_detail_type,</if>
<if test="payeeId != null and payeeId != 0">payee_id,</if>
<if test="reverseId != null and reverseId != 0">reverse_id,</if>
<if test="payType != null">pay_type,</if>
<if test="payStatus != null">pay_status,</if>
<if test="payTime != null">pay_time,</if>
@ -120,6 +128,7 @@
<if test="payMoney != null">#{payMoney},</if>
<if test="financialDetailType != null">#{financialDetailType},</if>
<if test="payeeId != null and payeeId != 0">#{payeeId},</if>
<if test="reverseId != null and reverseId != 0">#{reverseId},</if>
<if test="payType != null">#{payType},</if>
<if test="payStatus != null">#{payStatus},</if>
<if test="payTime != null">#{payTime},</if>

View File

@ -56,6 +56,10 @@
<include refid="selectFinancialMaster"/> WHERE order_master_id = #{orderMasterId}
</select>
<select id="selectByPaymentId" parameterType="String" resultMap="FinancialMasterResult">
<include refid="selectFinancialMaster"/> WHERE payment_id = #{paymentId}
</select>
<delete id="deleteFinancialMasterByIds" parameterType="Long">
DELETE FROM financial_master WHERE id IN
<foreach collection="array" item="financialMasterId" open="(" separator="," close=")">