Commit ad2afc15 authored by terrfly's avatar terrfly
Browse files

分账第一卷: 分账表结构设计; 分账MQ, 入库操作。

parent 07212404
...@@ -21,6 +21,7 @@ import com.jeequan.jeepay.pay.rqrs.AbstractMchAppRQ; ...@@ -21,6 +21,7 @@ import com.jeequan.jeepay.pay.rqrs.AbstractMchAppRQ;
import com.jeequan.jeepay.pay.rqrs.payorder.payway.*; import com.jeequan.jeepay.pay.rqrs.payorder.payway.*;
import lombok.Data; import lombok.Data;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.hibernate.validator.constraints.Range;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import javax.validation.constraints.Min; import javax.validation.constraints.Min;
...@@ -84,6 +85,9 @@ public class UnifiedOrderRQ extends AbstractMchAppRQ { ...@@ -84,6 +85,9 @@ public class UnifiedOrderRQ extends AbstractMchAppRQ {
/** 商户扩展参数 **/ /** 商户扩展参数 **/
private String extParam; private String extParam;
/** 分账模式: 0-该笔订单不允许分账, 1-支付成功按配置自动完成分账, 2-商户手动分账(解冻商户金额) **/
@Range(min = 0, max = 2, message = "分账模式设置值有误")
private Byte divisionMode;
/** 返回真实的bizRQ **/ /** 返回真实的bizRQ **/
public UnifiedOrderRQ buildBizRQ(){ public UnifiedOrderRQ buildBizRQ(){
......
...@@ -44,6 +44,7 @@ public class ChannelOrderReissueService { ...@@ -44,6 +44,7 @@ public class ChannelOrderReissueService {
@Autowired private ConfigContextService configContextService; @Autowired private ConfigContextService configContextService;
@Autowired private PayOrderService payOrderService; @Autowired private PayOrderService payOrderService;
@Autowired private RefundOrderService refundOrderService; @Autowired private RefundOrderService refundOrderService;
@Autowired private PayOrderProcessService payOrderProcessService;
@Autowired private PayMchNotifyService payMchNotifyService; @Autowired private PayMchNotifyService payMchNotifyService;
...@@ -78,11 +79,8 @@ public class ChannelOrderReissueService { ...@@ -78,11 +79,8 @@ public class ChannelOrderReissueService {
if(channelRetMsg.getChannelState() == ChannelRetMsg.ChannelState.CONFIRM_SUCCESS) { if(channelRetMsg.getChannelState() == ChannelRetMsg.ChannelState.CONFIRM_SUCCESS) {
if (payOrderService.updateIng2Success(payOrderId, channelRetMsg.getChannelOrderId())) { if (payOrderService.updateIng2Success(payOrderId, channelRetMsg.getChannelOrderId())) {
// 通知商户系统 //订单支付成功,其他业务逻辑
if(StringUtils.isNotEmpty(payOrder.getNotifyUrl())){ payOrderProcessService.confirmSuccess(payOrder);
payMchNotifyService.payOrderNotify(payOrderService.getById(payOrderId));
}
} }
}else if(channelRetMsg.getChannelState() == ChannelRetMsg.ChannelState.CONFIRM_FAIL){ //确认失败 }else if(channelRetMsg.getChannelState() == ChannelRetMsg.ChannelState.CONFIRM_FAIL){ //确认失败
......
/*
* Copyright (c) 2021-2031, 河北计全科技有限公司 (https://www.jeequan.com & jeequan@126.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jeequan.jeepay.pay.service;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.jeequan.jeepay.components.mq.model.PayOrderDivisionMQ;
import com.jeequan.jeepay.components.mq.vender.IMQSender;
import com.jeequan.jeepay.core.entity.PayOrder;
import com.jeequan.jeepay.service.impl.PayOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/***
* 订单处理通用逻辑
*
* @author terrfly
* @site https://www.jeepay.vip
* @date 2021/8/22 16:50
*/
@Service
@Slf4j
public class PayOrderProcessService {
@Autowired private PayOrderService payOrderService;
@Autowired private PayMchNotifyService payMchNotifyService;
@Autowired private IMQSender mqSender;
/** 明确成功的处理逻辑(除更新订单其他业务) **/
public void confirmSuccess(PayOrder payOrder){
//设置订单状态
payOrder.setState(PayOrder.STATE_SUCCESS);
//自动分账 处理逻辑, 不影响主订单任务
this.updatePayOrderAutoDivision(payOrder);
//发送商户通知
payMchNotifyService.payOrderNotify(payOrder);
}
/** 更新订单自动分账业务 **/
private void updatePayOrderAutoDivision(PayOrder payOrder){
try {
//默认不分账 || 其他非【自动分账】逻辑时, 不处理
if(payOrder == null || payOrder.getDivisionMode() == null || payOrder.getDivisionMode() != PayOrder.DIVISION_MODE_AUTO){
return ;
}
//更新订单表分账状态为: 等待分账任务处理
boolean updDivisionState = payOrderService.update(new LambdaUpdateWrapper<PayOrder>()
.set(PayOrder::getDivisionState, PayOrder.DIVISION_STATE_WAIT_TASK)
.eq(PayOrder::getPayOrderId, payOrder.getPayOrderId())
.eq(PayOrder::getDivisionState, PayOrder.DIVISION_STATE_UNHAPPEN)
);
if(updDivisionState){
//推送到分账MQ
mqSender.send(PayOrderDivisionMQ.build(payOrder.getPayOrderId(), null), 1); //1分钟后执行
}
} catch (Exception e) {
log.error("订单[{}]自动分账逻辑异常:", payOrder.getPayOrderId(), e);
}
}
}
package com.jeequan.jeepay.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeequan.jeepay.core.entity.MchDivisionReceiver;
import com.jeequan.jeepay.service.mapper.MchDivisionReceiverMapper;
import org.springframework.stereotype.Service;
/**
* <p>
* 商户分账接收者账号绑定关系表 服务实现类
* </p>
*
* @author [mybatis plus generator]
* @since 2021-08-19
*/
@Service
public class MchDivisionReceiverService extends ServiceImpl<MchDivisionReceiverMapper, MchDivisionReceiver> {
}
package com.jeequan.jeepay.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeequan.jeepay.core.entity.PayOrderDivisionRecord;
import com.jeequan.jeepay.service.mapper.PayOrderDivisionRecordMapper;
import org.springframework.stereotype.Service;
/**
* <p>
* 分账记录表 服务实现类
* </p>
*
* @author [mybatis plus generator]
* @since 2021-08-19
*/
@Service
public class PayOrderDivisionRecordService extends ServiceImpl<PayOrderDivisionRecordMapper, PayOrderDivisionRecord> {
}
...@@ -55,12 +55,17 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> { ...@@ -55,12 +55,17 @@ public class PayOrderService extends ServiceImpl<PayOrderMapper, PayOrder> {
@Autowired private PayWayMapper payWayMapper; @Autowired private PayWayMapper payWayMapper;
/** 更新订单状态 【订单生成】 --》 【支付中】 **/ /** 更新订单状态 【订单生成】 --》 【支付中】 **/
public boolean updateInit2Ing(String payOrderId, String ifCode, String wayCode){ public boolean updateInit2Ing(String payOrderId, PayOrder payOrder){
PayOrder updateRecord = new PayOrder(); PayOrder updateRecord = new PayOrder();
updateRecord.setState(PayOrder.STATE_ING); updateRecord.setState(PayOrder.STATE_ING);
updateRecord.setIfCode(ifCode);
updateRecord.setWayCode(wayCode); //同时更新, 未确定 --》 已确定的其他信息。 如支付接口的确认、 费率的计算。
updateRecord.setIfCode(payOrder.getIfCode());
updateRecord.setWayCode(payOrder.getWayCode());
updateRecord.setMchFeeRate(payOrder.getMchFeeRate());
updateRecord.setMchFeeAmount(payOrder.getMchFeeAmount());
updateRecord.setMchIncomeAmount(payOrder.getMchIncomeAmount());
return update(updateRecord, new LambdaUpdateWrapper<PayOrder>() return update(updateRecord, new LambdaUpdateWrapper<PayOrder>()
.eq(PayOrder::getPayOrderId, payOrderId).eq(PayOrder::getState, PayOrder.STATE_INIT)); .eq(PayOrder::getPayOrderId, payOrderId).eq(PayOrder::getState, PayOrder.STATE_INIT));
......
package com.jeequan.jeepay.service.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jeequan.jeepay.core.entity.MchDivisionReceiver;
/**
* <p>
* 商户分账接收者账号绑定关系表 Mapper 接口
* </p>
*
* @author [mybatis plus generator]
* @since 2021-08-19
*/
public interface MchDivisionReceiverMapper extends BaseMapper<MchDivisionReceiver> {
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jeequan.jeepay.service.mapper.MchDivisionReceiverMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.jeequan.jeepay.core.entity.MchDivisionReceiver">
<id column="receiver_id" property="receiverId" />
<result column="receiver_group_id" property="receiverGroupId" />
<result column="receiver_name" property="receiverName" />
<result column="mch_no" property="mchNo" />
<result column="isv_no" property="isvNo" />
<result column="app_id" property="appId" />
<result column="if_code" property="ifCode" />
<result column="acc_type" property="accType" />
<result column="acc_no" property="accNo" />
<result column="acc_name" property="accName" />
<result column="relation_type" property="relationType" />
<result column="relation_type_name" property="relationTypeName" />
<result column="division_profit" property="divisionProfit" />
<result column="state" property="state" />
<result column="channel_bind_state" property="channelBindState" />
<result column="channel_bind_result" property="channelBindResult" />
<result column="channel_ext_info" property="channelExtInfo" />
<result column="bind_success_time" property="bindSuccessTime" />
<result column="created_at" property="createdAt" />
<result column="updated_at" property="updatedAt" />
</resultMap>
</mapper>
package com.jeequan.jeepay.service.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jeequan.jeepay.core.entity.PayOrderDivisionRecord;
/**
* <p>
* 分账记录表 Mapper 接口
* </p>
*
* @author [mybatis plus generator]
* @since 2021-08-19
*/
public interface PayOrderDivisionRecordMapper extends BaseMapper<PayOrderDivisionRecord> {
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jeequan.jeepay.service.mapper.PayOrderDivisionRecordMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.jeequan.jeepay.core.entity.PayOrderDivisionRecord">
<id column="record_id" property="recordId" />
<result column="mch_no" property="mchNo" />
<result column="isv_no" property="isvNo" />
<result column="app_id" property="appId" />
<result column="mch_name" property="mchName" />
<result column="mch_type" property="mchType" />
<result column="if_code" property="ifCode" />
<result column="pay_order_id" property="payOrderId" />
<result column="pay_order_channel_order_no" property="payOrderChannelOrderNo" />
<result column="pay_order_amount" property="payOrderAmount" />
<result column="pay_order_division_amount" property="payOrderDivisionAmount" />
<result column="batch_order_id" property="batchOrderId" />
<result column="channel_batch_order_id" property="channelBatchOrderId" />
<result column="state" property="state" />
<result column="channel_resp_result" property="channelRespResult" />
<result column="receiver_id" property="receiverId" />
<result column="receiver_group_id" property="receiverGroupId" />
<result column="acc_type" property="accType" />
<result column="acc_no" property="accNo" />
<result column="acc_name" property="accName" />
<result column="relation_type" property="relationType" />
<result column="relation_type_name" property="relationTypeName" />
<result column="division_profit" property="divisionProfit" />
<result column="cal_division_amount" property="calDivisionAmount" />
<result column="created_at" property="createdAt" />
<result column="updated_at" property="updatedAt" />
</resultMap>
</mapper>
...@@ -14,6 +14,9 @@ ...@@ -14,6 +14,9 @@
<result column="if_code" property="ifCode" /> <result column="if_code" property="ifCode" />
<result column="way_code" property="wayCode" /> <result column="way_code" property="wayCode" />
<result column="amount" property="amount" /> <result column="amount" property="amount" />
<result column="mch_fee_rate" property="mchFeeRate" />
<result column="mch_fee_amount" property="mchFeeAmount" />
<result column="mch_income_amount" property="mchIncomeAmount" />
<result column="currency" property="currency" /> <result column="currency" property="currency" />
<result column="state" property="state" /> <result column="state" property="state" />
<result column="notify_state" property="notifyState" /> <result column="notify_state" property="notifyState" />
...@@ -26,8 +29,9 @@ ...@@ -26,8 +29,9 @@
<result column="refund_state" property="refundState" /> <result column="refund_state" property="refundState" />
<result column="refund_times" property="refundTimes" /> <result column="refund_times" property="refundTimes" />
<result column="refund_amount" property="refundAmount" /> <result column="refund_amount" property="refundAmount" />
<result column="division_flag" property="divisionFlag" /> <result column="division_mode" property="divisionMode" />
<result column="division_time" property="divisionTime" /> <result column="division_state" property="divisionState" />
<result column="division_last_time" property="divisionLastTime" />
<result column="err_code" property="errCode" /> <result column="err_code" property="errCode" />
<result column="err_msg" property="errMsg" /> <result column="err_msg" property="errMsg" />
<result column="ext_param" property="extParam" /> <result column="ext_param" property="extParam" />
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment