Commit 1751aced by 程裕兵

feat:pay refund and settle

parent 7e63c19d
...@@ -26,6 +26,7 @@ import com.jiejing.fitness.finance.service.merchant.StudioMerchantService; ...@@ -26,6 +26,7 @@ import com.jiejing.fitness.finance.service.merchant.StudioMerchantService;
import com.jiejing.fitness.finance.service.merchant.params.ApplyStudioMerchantParams; import com.jiejing.fitness.finance.service.merchant.params.ApplyStudioMerchantParams;
import com.jiejing.fitness.finance.service.merchant.params.PageStudioMerchantApplyParams; import com.jiejing.fitness.finance.service.merchant.params.PageStudioMerchantApplyParams;
import com.jiejing.fitness.finance.service.pay.PayService; import com.jiejing.fitness.finance.service.pay.PayService;
import com.jiejing.fitness.finance.service.pay.RefundService;
import com.jiejing.fitness.finance.service.pay.params.StudioMerchantPayParams; import com.jiejing.fitness.finance.service.pay.params.StudioMerchantPayParams;
import com.jiejing.fitness.finance.service.pay.params.StudioMerchantRefundParams; import com.jiejing.fitness.finance.service.pay.params.StudioMerchantRefundParams;
import com.jiejing.paycenter.common.model.vo.PayVO; import com.jiejing.paycenter.common.model.vo.PayVO;
...@@ -51,6 +52,9 @@ public class StudioMerchantController implements StudioMerchantApi { ...@@ -51,6 +52,9 @@ public class StudioMerchantController implements StudioMerchantApi {
@Resource @Resource
private PayService payService; private PayService payService;
@Resource
private RefundService refundService;
@ApiOperation(value = "场馆入驻商户", tags = {TAG}) @ApiOperation(value = "场馆入驻商户", tags = {TAG})
@PostMapping(value = "/private/studioMerchant/getMerchant") @PostMapping(value = "/private/studioMerchant/getMerchant")
@Override @Override
...@@ -179,7 +183,7 @@ public class StudioMerchantController implements StudioMerchantApi { ...@@ -179,7 +183,7 @@ public class StudioMerchantController implements StudioMerchantApi {
@Override @Override
public JsonResult<RefundVO> refund(@RequestBody @Valid StudioMerchantRefundRequest request) { public JsonResult<RefundVO> refund(@RequestBody @Valid StudioMerchantRefundRequest request) {
StudioMerchantRefundParams params = BeanUtil.map(request, StudioMerchantRefundParams.class); StudioMerchantRefundParams params = BeanUtil.map(request, StudioMerchantRefundParams.class);
return JsonResult.success(payService.merchantRefund(params)); return JsonResult.success(refundService.merchantRefund(params));
} }
} }
package com.jiejing.fitness.finance.app.controller.task; package com.jiejing.fitness.finance.app.controller.task;
import com.jiejing.common.model.JsonResult; import com.jiejing.common.model.JsonResult;
import com.jiejing.common.utils.time.TimeUtil;
import com.jiejing.fitness.finance.api.task.FitFinanceTaskApi; import com.jiejing.fitness.finance.api.task.FitFinanceTaskApi;
import com.jiejing.fitness.finance.api.task.request.CheckSettleRequest; import com.jiejing.fitness.finance.api.task.request.CheckSettleRequest;
import com.jiejing.fitness.finance.service.pay.PayService; import com.jiejing.fitness.finance.service.pay.SettleService;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import java.util.Date;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.validation.Valid; import javax.validation.Valid;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
...@@ -18,14 +20,16 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -18,14 +20,16 @@ import org.springframework.web.bind.annotation.RestController;
@RestController @RestController
public class FitFinanceTaskController implements FitFinanceTaskApi { public class FitFinanceTaskController implements FitFinanceTaskApi {
@Resource @Resource
private PayService payService; private SettleService settleService;
@ApiOperation(value = "对账", tags = {TAG}) @ApiOperation(value = "对账", tags = {TAG})
@PostMapping(value = "/private/task/checkSettle") @PostMapping(value = "/private/task/checkSettle")
@Override @Override
public JsonResult<Void> checkSettle(@Valid @RequestBody CheckSettleRequest request) { public JsonResult<Void> checkSettle(@Valid @RequestBody CheckSettleRequest request) {
payService.checkSettle(request.getMerchantId(), request.getSettleDate()); settleService.checkSettle(request.getMerchantId(), request.getSettleDate());
return JsonResult.success(); return JsonResult.success();
} }
...@@ -33,7 +37,7 @@ public class FitFinanceTaskController implements FitFinanceTaskApi { ...@@ -33,7 +37,7 @@ public class FitFinanceTaskController implements FitFinanceTaskApi {
@PostMapping(value = "/private/task/syncSettle") @PostMapping(value = "/private/task/syncSettle")
@Override @Override
public JsonResult<Void> syncSettle(@Valid @RequestBody CheckSettleRequest request) { public JsonResult<Void> syncSettle(@Valid @RequestBody CheckSettleRequest request) {
payService.syncSettle(request.getMerchantId(), request.getSettleDate()); settleService.syncSettle(request.getMerchantId(), request.getSettleDate());
return JsonResult.success(); return JsonResult.success();
} }
......
...@@ -6,6 +6,7 @@ import com.alibaba.fastjson.JSON; ...@@ -6,6 +6,7 @@ import com.alibaba.fastjson.JSON;
import com.jiejing.fitness.enums.finance.PartyTypeEnum; import com.jiejing.fitness.enums.finance.PartyTypeEnum;
import com.jiejing.fitness.finance.service.merchant.StudioMerchantService; import com.jiejing.fitness.finance.service.merchant.StudioMerchantService;
import com.jiejing.fitness.finance.service.pay.PayService; import com.jiejing.fitness.finance.service.pay.PayService;
import com.jiejing.fitness.finance.service.pay.RefundService;
import com.jiejing.paycenter.common.event.MerchantEvent; import com.jiejing.paycenter.common.event.MerchantEvent;
import com.jiejing.paycenter.common.event.PayEvent; import com.jiejing.paycenter.common.event.PayEvent;
import com.jiejing.paycenter.common.event.RefundEvent; import com.jiejing.paycenter.common.event.RefundEvent;
...@@ -33,6 +34,8 @@ public class ListenerService { ...@@ -33,6 +34,8 @@ public class ListenerService {
@Resource @Resource
private PayService payService; private PayService payService;
@Resource
private RefundService refundService;
@EventHandler(value = MerchantEvent.class, binder = "biz-kafka", maxAttempts = MAX_RETRY) @EventHandler(value = MerchantEvent.class, binder = "biz-kafka", maxAttempts = MAX_RETRY)
public void handleMerchantEvent(MerchantEvent event, @Header(DELIVERY_ATTEMPT) int retryNum) { public void handleMerchantEvent(MerchantEvent event, @Header(DELIVERY_ATTEMPT) int retryNum) {
...@@ -69,7 +72,7 @@ public class ListenerService { ...@@ -69,7 +72,7 @@ public class ListenerService {
public void refundEventCallback(RefundEvent event, @Header(DELIVERY_ATTEMPT) int retryNum) { public void refundEventCallback(RefundEvent event, @Header(DELIVERY_ATTEMPT) int retryNum) {
try { try {
log.info("start process refund event {}", JSON.toJSONString(event)); log.info("start process refund event {}", JSON.toJSONString(event));
payService.refundCallback(event); refundService.refundCallback(event);
} catch (Exception e) { } catch (Exception e) {
log.info("process refund event fail {}", event.getTransNo(), e); log.info("process refund event fail {}", event.getTransNo(), e);
} }
......
...@@ -3,13 +3,9 @@ package com.jiejing.fitness.finance.service.pay; ...@@ -3,13 +3,9 @@ package com.jiejing.fitness.finance.service.pay;
import com.jiejing.fitness.finance.service.pay.params.AppPayParams; import com.jiejing.fitness.finance.service.pay.params.AppPayParams;
import com.jiejing.fitness.finance.service.pay.params.NativePayParams; import com.jiejing.fitness.finance.service.pay.params.NativePayParams;
import com.jiejing.fitness.finance.service.pay.params.StudioMerchantPayParams; import com.jiejing.fitness.finance.service.pay.params.StudioMerchantPayParams;
import com.jiejing.fitness.finance.service.pay.params.StudioMerchantRefundParams;
import com.jiejing.paycenter.common.enums.common.PayChannelEnums; import com.jiejing.paycenter.common.enums.common.PayChannelEnums;
import com.jiejing.paycenter.common.model.vo.PayVO; import com.jiejing.paycenter.common.model.vo.PayVO;
import com.jiejing.paycenter.common.event.PayEvent; import com.jiejing.paycenter.common.event.PayEvent;
import com.jiejing.paycenter.common.event.RefundEvent;
import com.jiejing.paycenter.common.model.vo.RefundVO;
import java.util.Date;
/** /**
* @author chengyubing * @author chengyubing
...@@ -44,7 +40,7 @@ public interface PayService { ...@@ -44,7 +40,7 @@ public interface PayService {
PayVO appPay(AppPayParams params); PayVO appPay(AppPayParams params);
/** /**
* 支付 * 商户版支付
* *
* @param params 请求参数 * @param params 请求参数
* @return 结果 * @return 结果
...@@ -58,35 +54,4 @@ public interface PayService { ...@@ -58,35 +54,4 @@ public interface PayService {
*/ */
void payCallback(PayEvent event); void payCallback(PayEvent event);
/**
* 商户退款
*
* @param params 参数
* @return 结果
*/
RefundVO merchantRefund(StudioMerchantRefundParams params);
/**
* 退款回调
*
* @param event 事件
*/
void refundCallback(RefundEvent event);
/**
* 对账
*
* @param merchantId 商户ID
* @param settleDate 结算日
*/
void checkSettle(Long merchantId, Date settleDate);
/**
* 同步结算状态
*
* @param merchantId 商户ID
* @param settleDate 结算日
*/
void syncSettle(Long merchantId, Date settleDate);
} }
package com.jiejing.fitness.finance.service.pay;
import com.jiejing.fitness.finance.service.pay.params.StudioMerchantRefundParams;
import com.jiejing.paycenter.common.event.RefundEvent;
import com.jiejing.paycenter.common.model.vo.RefundVO;
/**
* @author chengyubing
* @since 2024/5/7 16:37
*/
public interface RefundService {
/**
* 商户退款
*
* @param params 参数
* @return 结果
*/
RefundVO merchantRefund(StudioMerchantRefundParams params);
/**
* 退款回调
*
* @param event 事件
*/
void refundCallback(RefundEvent event);
}
package com.jiejing.fitness.finance.service.pay;
import java.util.Date;
/**
* @author chengyubing
* @since 2024/5/7 16:32
*/
public interface SettleService {
/**
* 对账
*
* @param merchantId 商户ID
* @param settleDate 结算日
*/
void checkSettle(Long merchantId, Date settleDate);
/**
* 同步结算状态
*
* @param merchantId 商户ID
* @param settleDate 结算日
*/
void syncSettle(Long merchantId, Date settleDate);
}
...@@ -2,6 +2,7 @@ package com.jiejing.fitness.finance.service.pay.convert; ...@@ -2,6 +2,7 @@ package com.jiejing.fitness.finance.service.pay.convert;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.baomidou.mybatisplus.core.toolkit.IdWorker; import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.jiejing.common.exception.BizException; import com.jiejing.common.exception.BizException;
...@@ -15,11 +16,16 @@ import com.jiejing.fitness.finance.repository.entity.StudioCashierRecord; ...@@ -15,11 +16,16 @@ import com.jiejing.fitness.finance.repository.entity.StudioCashierRecord;
import com.jiejing.fitness.finance.repository.entity.StudioCheckSettleRecord; import com.jiejing.fitness.finance.repository.entity.StudioCheckSettleRecord;
import com.jiejing.fitness.finance.repository.entity.StudioMerchantApply; import com.jiejing.fitness.finance.repository.entity.StudioMerchantApply;
import com.jiejing.fitness.finance.repository.entity.StudioSettleRecord; import com.jiejing.fitness.finance.repository.entity.StudioSettleRecord;
import com.jiejing.fitness.finance.service.config.PayChannelProperties;
import com.jiejing.fitness.finance.service.enums.FinanceErrorEnums; import com.jiejing.fitness.finance.service.enums.FinanceErrorEnums;
import com.jiejing.fitness.finance.service.pay.enums.PayFailMessageReplaceEnums;
import com.jiejing.fitness.finance.service.pay.params.AppPayParams;
import com.jiejing.fitness.finance.service.pay.params.NativePayParams;
import com.jiejing.fitness.finance.service.pay.params.StudioMerchantRefundParams; import com.jiejing.fitness.finance.service.pay.params.StudioMerchantRefundParams;
import com.jiejing.fitness.finance.service.pay.params.StudioMerchantPayParams; import com.jiejing.fitness.finance.service.pay.params.StudioMerchantPayParams;
import com.jiejing.fitness.finance.service.utils.FeeUtil; import com.jiejing.fitness.finance.service.utils.FeeUtil;
import com.jiejing.fitness.finance.service.utils.MoneyUtil; import com.jiejing.fitness.finance.service.utils.MoneyUtil;
import com.jiejing.paycenter.common.enums.common.PayChannelEnums;
import com.jiejing.paycenter.common.model.vo.MerchantVO; import com.jiejing.paycenter.common.model.vo.MerchantVO;
import com.jiejing.paycenter.common.model.vo.PayVO; import com.jiejing.paycenter.common.model.vo.PayVO;
import com.jiejing.paycenter.common.model.vo.RefundVO; import com.jiejing.paycenter.common.model.vo.RefundVO;
...@@ -184,45 +190,7 @@ public class PayConvert { ...@@ -184,45 +190,7 @@ public class PayConvert {
return convertTransState(PayStateEnums.getByCode(state)); return convertTransState(PayStateEnums.getByCode(state));
} }
public static StudioCashierRecord convertRefundInit(StudioMerchantRefundParams params, public static BrandCashierTransStateEnum convertTransState(TransStateEnums state) {
StudioCashierRecord pay, BigDecimal historyRefundActualAmount) {
StudioCashierRecord record = BeanUtil.map(pay, StudioCashierRecord.class);
record.setId(IdWorker.getId());
record.setTransNo(record.getId().toString());
record.setOrderNo(params.getOrderNo());
record.setRelatedTransNo(params.getPayTransNo());
record.setTransAmount(params.getTransAmount());
record.setFeeRate(pay.getFeeRate());
record.setFee(
FeeUtil.calculateRefundFee(params.getTransAmount(), pay.getTransAmount(), pay.getActualAmount(),
pay.getFee(), historyRefundActualAmount));
record.setActualAmount(MoneyUtil.subtract(record.getTransAmount(), record.getFee()));
record.setRemark(params.getRefundReason());
record.setStudioId(params.getStudioId());
record.setTransState(BrandCashierTransStateEnum.REFUND_INIT.getCode());
record.setTradingTime(new Date());
record.setCreateTime(new Date());
record.setUpdateTime(new Date());
return record;
}
public static RefundPayRequest convert(StudioMerchantRefundParams params, StudioCashierRecord record) {
RefundPayRequest request = BeanUtil.map(params, RefundPayRequest.class);
request.setTransNo(record.getTransNo());
return request;
}
public static StudioCashierRecord convertRefund(StudioCashierRecord record, RefundVO vo) {
return StudioCashierRecord.builder()
.id(record.getId())
.transState(convertTransState(TransStateEnums.getByCode(vo.getRefundState())).getCode())
.failMessage(vo.getFailMessage())
.successTime(vo.getSuccessTime())
.updateTime(new Date())
.build();
}
private static BrandCashierTransStateEnum convertTransState(TransStateEnums state) {
switch (state) { switch (state) {
case SUCCESS: case SUCCESS:
return BrandCashierTransStateEnum.REFUND_SUCCESS; return BrandCashierTransStateEnum.REFUND_SUCCESS;
...@@ -235,55 +203,6 @@ public class PayConvert { ...@@ -235,55 +203,6 @@ public class PayConvert {
} }
} }
public static StudioCashierRecord convertRefund(StudioCashierRecord record, RefundEvent event) {
return StudioCashierRecord.builder()
.id(record.getId())
.transState(convertTransState(TransStateEnums.getByCode(event.getRefundState())).getCode())
.failMessage(event.getFailMessage())
.successTime(event.getSuccessTime())
.updateTime(new Date())
.build();
}
public static List<StudioSettleRecord> convertStudioSettle(MerchantSettleRecord record,
Map<Long, BigDecimal> studioPayAmountMap, Map<Long, BigDecimal> studioRefundAmountMap,
Map<Long, StudioVO> studioMap) {
// A场馆支付了100,B场馆支付了0,B场馆发起退款-》成功。结算记录-》
// A场馆支付了0,B场馆支付了0,B场馆发起退款-》失败
// A场馆支付了100,B场馆支付了0,B场馆发起退款-》成功,A场馆发起退款100-》失败
return studioPayAmountMap.keySet().stream().map(studioId -> StudioSettleRecord.builder()
.id(IdWorker.getId())
.parentId(record.getId())
.studioId(studioId)
.studioName(Optional.ofNullable(studioMap.get(studioId)).map(StudioVO::getName).orElse("-"))
.merchantId(record.getMerchantId())
.merchantNo(record.getMerchantNo())
.transState(record.getTransState())
.transAmount(MoneyUtil.subtract(studioPayAmountMap.getOrDefault(studioId, BigDecimal.ZERO),
studioRefundAmountMap.getOrDefault(studioId, BigDecimal.ZERO)))
.settleDate(record.getSettleDate())
.cardNo(record.getCardNo())
.bankName(record.getBankName())
.failMsg(record.getFailMsg())
.salt(record.getSalt())
.createTime(record.getCreateTime())
.updateTime(record.getUpdateTime())
.build()).collect(Collectors.toList());
}
public static StudioCheckSettleRecord convertCheckSettle(StudioMerchantApply apply, SettleVO vo,
BigDecimal totalAmount) {
return StudioCheckSettleRecord.builder()
.id(IdWorker.getId())
.merchantId(apply.getMerchantId())
.merchantNo(apply.getMerchantNo())
.checkState(TransStateEnums.FAIL.getCode())
.failMsg("对账失败,乐动收银入账中金额【" + totalAmount + "】,汇付结算金额【" + vo.getTransAmount() + "】")
.settleDate(vo.getTransDate())
.createTime(new Date())
.updateTime(new Date())
.build();
}
public static PayEvent convertEvent(PayRequest request, PayVO vo) { public static PayEvent convertEvent(PayRequest request, PayVO vo) {
return PayEvent.builder() return PayEvent.builder()
...@@ -300,38 +219,56 @@ public class PayConvert { ...@@ -300,38 +219,56 @@ public class PayConvert {
.build(); .build();
} }
public static MerchantSettleRecord convertMerchantSettle(StudioMerchantApply apply, SettleVO vo) { public static PayRequest convertNativePay(NativePayParams params, PayChannelProperties config) {
String salt = AesUtil.getSalt(8); PayRequest req = new PayRequest();
Date now = new Date(); req.setChannelNo(getChannelNo(params.getChannel(), config));
return MerchantSettleRecord.builder() req.setTransNo(IdWorker.getIdStr());
.id(IdWorker.getId()) req.setAmount(params.getAmount());
.merchantId(apply.getMerchantId()) req.setPayType(PayTypeEnums.NATIVE);
.merchantNo(apply.getMerchantNo()) req.setGoods(params.getGoods());
.transState(vo.getTransState()) req.setOrderNo(params.getOrderNo());
.transAmount(vo.getTransAmount()) req.setOrderType(params.getOrderType().getCode());
.settleDate(vo.getTransDate()) req.setTimeExpire(params.getTimeExpire());
.cardNo(AesUtil.encrypt(salt, vo.getCardNo())) req.setTradingTime(new Date());
.bankName(vo.getBankName()) req.setExtra(params.getExtra());
.failMsg(vo.getFailMsg()) return req;
.salt(salt)
.createTime(now)
.updateTime(now).build();
} }
public static MerchantSettleRecord convertMerchantSettle(MerchantSettleRecord history, SettleVO vo) { public static PayRequest convertAppPay(AppPayParams params, PayChannelProperties config) {
return MerchantSettleRecord.builder() PayRequest req = new PayRequest();
.id(history.getId()) req.setChannelNo(getChannelNo(params.getChannel(), config));
.transState(vo.getTransState()) req.setTransNo(IdWorker.getIdStr());
.failMsg(vo.getFailMsg()) req.setAmount(params.getAmount());
.updateTime(new Date()).build(); req.setPayType(PayTypeEnums.APP);
req.setGoods(params.getGoods());
req.setOrderNo(params.getOrderNo());
req.setOrderType(params.getOrderType().getCode());
req.setTimeExpire(params.getTimeExpire());
req.setTradingTime(new Date());
req.setExtra(params.getExtra());
return req;
} }
public static StudioSettleRecord convertStudioSettle(MerchantSettleRecord history, SettleVO vo) { private static String getChannelNo(PayChannelEnums channel, PayChannelProperties config) {
return StudioSettleRecord.builder() switch (channel) {
.parentId(history.getId()) case WX:
.transState(vo.getTransState()) return config.getWxApp();
.failMsg(vo.getFailMsg()) case ALI:
.updateTime(new Date()).build(); return config.getAliApp();
default:
throw new BizException(FinanceErrorEnums.NOT_SUPPORT_TYPE);
}
}
public static AlipaySystemOauthTokenRequest convertAlipaySystemOauthTokenRequest(String authCode) {
AlipaySystemOauthTokenRequest aliRequest = new AlipaySystemOauthTokenRequest();
aliRequest.setCode(authCode);
aliRequest.setGrantType("authorization_code");
return aliRequest;
}
public static FinanceErrorEnums replaceFailMessage(String failMsg) {
return PayFailMessageReplaceEnums.convertBySource(failMsg);
} }
} }
package com.jiejing.fitness.finance.service.pay.convert;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.jiejing.common.utils.convert.BeanUtil;
import com.jiejing.fitness.enums.finance.BrandCashierTransStateEnum;
import com.jiejing.fitness.finance.repository.entity.StudioCashierRecord;
import com.jiejing.fitness.finance.service.pay.params.StudioMerchantRefundParams;
import com.jiejing.fitness.finance.service.utils.FeeUtil;
import com.jiejing.fitness.finance.service.utils.MoneyUtil;
import com.jiejing.paycenter.api.pay.request.RefundPayRequest;
import com.jiejing.paycenter.common.enums.common.TransStateEnums;
import com.jiejing.paycenter.common.event.RefundEvent;
import com.jiejing.paycenter.common.model.vo.RefundVO;
import java.math.BigDecimal;
import java.util.Date;
/**
* @author chengyubing
* @since 2024/5/7 16:48
*/
public class RefundConvert {
public static StudioCashierRecord convertRefundInit(StudioMerchantRefundParams params,
StudioCashierRecord pay, BigDecimal historyRefundActualAmount) {
StudioCashierRecord record = BeanUtil.map(pay, StudioCashierRecord.class);
record.setId(IdWorker.getId());
record.setTransNo(record.getId().toString());
record.setOrderNo(params.getOrderNo());
record.setRelatedTransNo(params.getPayTransNo());
record.setTransAmount(params.getTransAmount());
record.setFeeRate(pay.getFeeRate());
record.setFee(
FeeUtil.calculateRefundFee(params.getTransAmount(), pay.getTransAmount(), pay.getActualAmount(),
pay.getFee(), historyRefundActualAmount));
record.setActualAmount(MoneyUtil.subtract(record.getTransAmount(), record.getFee()));
record.setRemark(params.getRefundReason());
record.setStudioId(params.getStudioId());
record.setTransState(BrandCashierTransStateEnum.REFUND_INIT.getCode());
record.setTradingTime(new Date());
record.setCreateTime(new Date());
record.setUpdateTime(new Date());
return record;
}
public static RefundPayRequest convert(StudioMerchantRefundParams params, StudioCashierRecord record) {
RefundPayRequest request = BeanUtil.map(params, RefundPayRequest.class);
request.setTransNo(record.getTransNo());
return request;
}
public static StudioCashierRecord convertRefund(StudioCashierRecord record, RefundVO vo) {
return StudioCashierRecord.builder()
.id(record.getId())
.transState(PayConvert.convertTransState(TransStateEnums.getByCode(vo.getRefundState())).getCode())
.failMessage(vo.getFailMessage())
.successTime(vo.getSuccessTime())
.updateTime(new Date())
.build();
}
public static StudioCashierRecord convertRefund(StudioCashierRecord record, RefundEvent event) {
return StudioCashierRecord.builder()
.id(record.getId())
.transState(PayConvert.convertTransState(TransStateEnums.getByCode(event.getRefundState())).getCode())
.failMessage(event.getFailMessage())
.successTime(event.getSuccessTime())
.updateTime(new Date())
.build();
}
}
package com.jiejing.fitness.finance.service.pay.convert;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.jiejing.common.utils.crypt.AesUtil;
import com.jiejing.fitness.finance.repository.entity.MerchantSettleRecord;
import com.jiejing.fitness.finance.repository.entity.StudioCheckSettleRecord;
import com.jiejing.fitness.finance.repository.entity.StudioMerchantApply;
import com.jiejing.fitness.finance.repository.entity.StudioSettleRecord;
import com.jiejing.fitness.finance.service.utils.MoneyUtil;
import com.jiejing.paycenter.common.enums.common.TransStateEnums;
import com.jiejing.paycenter.common.model.vo.SettleVO;
import com.jiejing.studio.api.studio.vo.StudioVO;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* @author chengyubing
* @since 2024/5/7 16:48
*/
public class SettleConvert {
public static MerchantSettleRecord convertMerchantSettle(StudioMerchantApply apply, SettleVO vo) {
String salt = AesUtil.getSalt(8);
Date now = new Date();
return MerchantSettleRecord.builder()
.id(IdWorker.getId())
.merchantId(apply.getMerchantId())
.merchantNo(apply.getMerchantNo())
.transState(vo.getTransState())
.transAmount(vo.getTransAmount())
.settleDate(vo.getTransDate())
.cardNo(AesUtil.encrypt(salt, vo.getCardNo()))
.bankName(vo.getBankName())
.failMsg(vo.getFailMsg())
.salt(salt)
.createTime(now)
.updateTime(now).build();
}
public static MerchantSettleRecord convertMerchantSettle(MerchantSettleRecord history, SettleVO vo) {
return MerchantSettleRecord.builder()
.id(history.getId())
.transState(vo.getTransState())
.failMsg(vo.getFailMsg())
.updateTime(new Date()).build();
}
public static StudioSettleRecord convertStudioSettle(MerchantSettleRecord history, SettleVO vo) {
return StudioSettleRecord.builder()
.parentId(history.getId())
.transState(vo.getTransState())
.failMsg(vo.getFailMsg())
.updateTime(new Date()).build();
}
public static List<StudioSettleRecord> convertStudioSettle(MerchantSettleRecord record,
Map<Long, BigDecimal> studioPayAmountMap, Map<Long, BigDecimal> studioRefundAmountMap,
Map<Long, StudioVO> studioMap) {
// A场馆支付了100,B场馆支付了0,B场馆发起退款-》成功。结算记录-》
// A场馆支付了0,B场馆支付了0,B场馆发起退款-》失败
// A场馆支付了100,B场馆支付了0,B场馆发起退款-》成功,A场馆发起退款100-》失败
return studioPayAmountMap.keySet().stream().map(studioId -> StudioSettleRecord.builder()
.id(IdWorker.getId())
.parentId(record.getId())
.studioId(studioId)
.studioName(Optional.ofNullable(studioMap.get(studioId)).map(StudioVO::getName).orElse("-"))
.merchantId(record.getMerchantId())
.merchantNo(record.getMerchantNo())
.transState(record.getTransState())
.transAmount(MoneyUtil.subtract(studioPayAmountMap.getOrDefault(studioId, BigDecimal.ZERO),
studioRefundAmountMap.getOrDefault(studioId, BigDecimal.ZERO)))
.settleDate(record.getSettleDate())
.cardNo(record.getCardNo())
.bankName(record.getBankName())
.failMsg(record.getFailMsg())
.salt(record.getSalt())
.createTime(record.getCreateTime())
.updateTime(record.getUpdateTime())
.build()).collect(Collectors.toList());
}
public static StudioCheckSettleRecord convertCheckSettle(StudioMerchantApply apply, SettleVO vo,
BigDecimal totalAmount) {
return StudioCheckSettleRecord.builder()
.id(IdWorker.getId())
.merchantId(apply.getMerchantId())
.merchantNo(apply.getMerchantNo())
.checkState(TransStateEnums.FAIL.getCode())
.failMsg("对账失败,乐动收银入账中金额【" + totalAmount + "】,汇付结算金额【" + vo.getTransAmount() + "】")
.settleDate(vo.getTransDate())
.createTime(new Date())
.updateTime(new Date())
.build();
}
}
package com.jiejing.fitness.finance.service.pay.impl;
import com.jiejing.common.exception.BizException;
import com.jiejing.fitness.finance.repository.entity.StudioCashierRecord;
import com.jiejing.fitness.finance.repository.service.StudioCashierRecordRpService;
import com.jiejing.fitness.finance.service.enums.FinanceErrorEnums;
import com.jiejing.fitness.finance.service.pay.RefundService;
import com.jiejing.fitness.finance.service.pay.convert.RefundConvert;
import com.jiejing.fitness.finance.service.pay.params.StudioMerchantRefundParams;
import com.jiejing.fitness.finance.service.rpc.PayRpcService;
import com.jiejing.paycenter.api.pay.request.RefundPayRequest;
import com.jiejing.paycenter.common.event.RefundEvent;
import com.jiejing.paycenter.common.model.vo.RefundVO;
import java.math.BigDecimal;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
/**
* @author chengyubing
* @since 2024/5/7 16:37
*/
@Slf4j
@Service
public class RefundServiceImpl implements RefundService {
@Resource
private PayRpcService payRpcService;
@Resource
private StudioCashierRecordRpService studioCashierRecordRpService;
@Resource
private TransactionTemplate transactionTemplate;
@Override
public RefundVO merchantRefund(StudioMerchantRefundParams params) {
StudioCashierRecord refund = transactionTemplate.execute(action -> {
Long payId = Long.parseLong(params.getPayTransNo());
StudioCashierRecord pay = studioCashierRecordRpService.getById(payId)
.orElseThrow(() -> new BizException(FinanceErrorEnums.NOT_EXIST));
BigDecimal historyRefundActualAmount = studioCashierRecordRpService.sumRefundActualAmountByPayTransNo(
params.getPayTransNo());
StudioCashierRecord record = RefundConvert.convertRefundInit(params, pay, historyRefundActualAmount);
studioCashierRecordRpService.insert(record);
return record;
});
RefundPayRequest request = RefundConvert.convert(params, refund);
RefundVO vo = payRpcService.refund(request);
StudioCashierRecord toModify = RefundConvert.convertRefund(refund, vo);
studioCashierRecordRpService.updateById(toModify);
return vo;
}
@Override
public void refundCallback(RefundEvent event) {
StudioCashierRecord record = studioCashierRecordRpService.getById(Long.parseLong(event.getTransNo()))
.orElse(null);
if (null == record) {
return;
}
StudioCashierRecord toModify = RefundConvert.convertRefund(record, event);
studioCashierRecordRpService.updateById(toModify);
}
}
...@@ -57,8 +57,10 @@ public class PayRpcService { ...@@ -57,8 +57,10 @@ public class PayRpcService {
.settleDate(settleDate) .settleDate(settleDate)
.build()); .build());
result.assertSuccess(); result.assertSuccess();
return Optional.ofNullable(result.getResult()) SettleVO vo = Optional.ofNullable(result.getResult())
.orElse(SettleVO.builder().transAmount(BigDecimal.ZERO).build()); .orElse(SettleVO.builder().transAmount(BigDecimal.ZERO).build());
log.info("merchant {} settle vo is {}", merchantId, JSON.toJSONString(vo));
return vo;
} }
public BigDecimal getFeeRate(PayRequest request) { public BigDecimal getFeeRate(PayRequest request) {
......
Markdown is supported
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