mirror of
https://gitee.com/dromara/dax-pay.git
synced 2025-09-02 18:46:29 +00:00
ref 对账改造
This commit is contained in:
14
_doc/Task.md
14
_doc/Task.md
@@ -13,11 +13,9 @@
|
||||
- [x] 支付和退款回调
|
||||
- [x] 去除现金支付和储值卡支付方式
|
||||
- [x] 三方支付外部订单号规则优化: 支付P、退款R、分账A,根据环境加前缀:DEV_、DEMO_、PRE_
|
||||
- [ ] 金额显示统一使用元
|
||||
- [x] 金额显示统一使用元
|
||||
- [x] 使用切面统一处理API调用异常, 做统一包装返回
|
||||
- [x] 支付接口优化
|
||||
- [] 前端增加对应的枚举
|
||||
- [ ] 优化自动分账逻辑
|
||||
- [x] 前端查询条件适配
|
||||
- [x] paymentId替换
|
||||
- [ ] 对账单改造
|
||||
@@ -25,8 +23,16 @@
|
||||
- [x] 增加对账结果计算和显示
|
||||
- [ ] 增加下载原始对账单功能
|
||||
- [ ] 保存原始的文件
|
||||
- [ ] 微信
|
||||
- [x] 支付宝
|
||||
- [x] 云闪付
|
||||
- [ ] 解析原有文件, 可以转换为指定格式进行下载
|
||||
- [ ] 增加下载系统对账单功能
|
||||
- [ ] 自动分账改造
|
||||
- [ ] SDK新增对账接收放添加接口
|
||||
- [ ] 创建定时任务, 自动对待分账订单进行分账
|
||||
- [ ] 增加定时同步分账状态任务
|
||||
- [ ] 增加自动完结功能
|
||||
2.0.7: 分账完善和基础架构优化
|
||||
- [ ] 资金流水优化
|
||||
- [ ] 数据加密方式改为类型处理器模式
|
||||
@@ -37,7 +43,7 @@
|
||||
- [ ] 分账回调处理
|
||||
- [ ] 分账组管理提供接口调用
|
||||
- [ ] 分账通知
|
||||
- [ ] 增加收银台
|
||||
- [ ] 增加收银台功能
|
||||
|
||||
2.0.x 版本内容
|
||||
- [ ] 对账回退及退款
|
||||
|
@@ -17,10 +17,10 @@ import java.util.Objects;
|
||||
@RequiredArgsConstructor
|
||||
public enum PayChannelEnum {
|
||||
|
||||
ALI("ali_pay", "支付宝", "ali"),
|
||||
WECHAT("wechat_pay", "微信支付", "wx"),
|
||||
UNION_PAY("union_pay", "云闪付", "uni"),
|
||||
WALLET("wallet_pay", "钱包支付",null),
|
||||
ALI("ali_pay", "支付宝"),
|
||||
WECHAT("wechat_pay", "微信支付"),
|
||||
UNION_PAY("union_pay", "云闪付"),
|
||||
WALLET("wallet_pay", "钱包支付"),
|
||||
;
|
||||
|
||||
/** 支付通道编码 */
|
||||
@@ -29,9 +29,6 @@ public enum PayChannelEnum {
|
||||
/** 支付通道名称 */
|
||||
private final String name;
|
||||
|
||||
/** 对账前缀 */
|
||||
private final String reconcilePrefix;
|
||||
|
||||
/**
|
||||
* 根据字符编码获取
|
||||
*/
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package cn.bootx.platform.daxpay.service.core.channel.alipay.service;
|
||||
|
||||
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
|
||||
import cn.bootx.platform.daxpay.code.PayChannelEnum;
|
||||
import cn.bootx.platform.daxpay.code.ReconcileTradeEnum;
|
||||
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
|
||||
import cn.bootx.platform.daxpay.service.code.AliPayCode;
|
||||
@@ -104,10 +105,10 @@ public class AliPayReconcileService {
|
||||
billDetails = this.parseDetail(strings);
|
||||
}
|
||||
}
|
||||
// 保存原始对账文件
|
||||
this.saveOriginalFile(recordOrder, bytes);
|
||||
// 保存原始对账记录
|
||||
this.save(billDetails, billTotals);
|
||||
// 保存文件
|
||||
this.saveOriginalFile(recordOrder, bytes);
|
||||
|
||||
// 将原始交易明细对账记录转换通用结构并保存到上下文中
|
||||
this.convertAndSave(billDetails);
|
||||
@@ -239,7 +240,10 @@ public class AliPayReconcileService {
|
||||
*/
|
||||
private void saveOriginalFile(ReconcileOrder reconcileOrder, byte[] bytes) {
|
||||
// 将原始文件进行保存
|
||||
String fileName = "";
|
||||
PayChannelEnum channelEnum = PayChannelEnum.findByCode(reconcileOrder.getChannel());
|
||||
String date = LocalDateTimeUtil.format(reconcileOrder.getDate(), DatePattern.PURE_DATE_PATTERN);
|
||||
// 将原始文件进行保存 通道-日期
|
||||
String fileName = StrUtil.format("{}-{}.zip", channelEnum.getName(),date);
|
||||
UploadPretreatment uploadPretreatment = fileStorageService.of(bytes);
|
||||
if (StrUtil.isNotBlank(fileName)) {
|
||||
uploadPretreatment.setOriginalFilename(fileName);
|
||||
|
@@ -1,14 +1,18 @@
|
||||
package cn.bootx.platform.daxpay.service.core.channel.union.service;
|
||||
|
||||
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
|
||||
import cn.bootx.platform.daxpay.code.PayChannelEnum;
|
||||
import cn.bootx.platform.daxpay.code.ReconcileTradeEnum;
|
||||
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
|
||||
import cn.bootx.platform.daxpay.service.code.ReconcileFileTypeEnum;
|
||||
import cn.bootx.platform.daxpay.service.code.UnionPayCode;
|
||||
import cn.bootx.platform.daxpay.service.code.UnionReconcileFieldEnum;
|
||||
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.union.dao.UnionReconcileBillDetailManager;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.union.entity.UnionReconcileBillDetail;
|
||||
import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.ReconcileFileManager;
|
||||
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileDetail;
|
||||
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileFile;
|
||||
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileOrder;
|
||||
import cn.bootx.platform.daxpay.service.sdk.union.api.UnionPayKit;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
@@ -23,6 +27,9 @@ import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
|
||||
import org.dromara.x.file.storage.core.FileInfo;
|
||||
import org.dromara.x.file.storage.core.FileStorageService;
|
||||
import org.dromara.x.file.storage.core.UploadPretreatment;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.*;
|
||||
@@ -44,11 +51,13 @@ import static cn.bootx.platform.daxpay.service.code.UnionPayCode.*;
|
||||
public class UnionPayReconcileService {
|
||||
|
||||
private final UnionReconcileBillDetailManager unionReconcileBillDetailManager;
|
||||
private final FileStorageService fileStorageService;
|
||||
private final ReconcileFileManager reconcileFileManager;
|
||||
|
||||
/**
|
||||
* 下载对账单
|
||||
*/
|
||||
public void downAndSave(Date date, UnionPayKit unionPayKit){
|
||||
public void downAndSave(ReconcileOrder reconcileOrder, Date date, UnionPayKit unionPayKit){
|
||||
// 下载对账单
|
||||
Map<String, Object> map = unionPayKit.downloadBill(date, RECONCILE_BILL_TYPE);
|
||||
String fileContent = map.get(FILE_CONTENT).toString();
|
||||
@@ -81,6 +90,8 @@ public class UnionPayReconcileService {
|
||||
// 汇总目前不进行处理
|
||||
}
|
||||
}
|
||||
// 保存原始对账记录文件
|
||||
this.saveOriginalFile(reconcileOrder,zipBytes);
|
||||
// 保存原始对账记录
|
||||
this.save(billDetails);
|
||||
// 转换为通用对账记录对象
|
||||
@@ -194,4 +205,24 @@ public class UnionPayReconcileService {
|
||||
billDetails.forEach(o->o.setReconcileId(recordOrderId));
|
||||
unionReconcileBillDetailManager.saveAll(billDetails);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存下载的原始对账文件
|
||||
*/
|
||||
private void saveOriginalFile(ReconcileOrder reconcileOrder, byte[] bytes) {
|
||||
PayChannelEnum channelEnum = PayChannelEnum.findByCode(reconcileOrder.getChannel());
|
||||
String date = LocalDateTimeUtil.format(reconcileOrder.getDate(), DatePattern.PURE_DATE_PATTERN);
|
||||
// 将原始文件进行保存 通道-日期
|
||||
String fileName = StrUtil.format("{}-{}.zip", channelEnum.getName(),date);
|
||||
UploadPretreatment uploadPretreatment = fileStorageService.of(bytes);
|
||||
if (StrUtil.isNotBlank(fileName)) {
|
||||
uploadPretreatment.setOriginalFilename(fileName);
|
||||
}
|
||||
FileInfo upload = uploadPretreatment.upload();
|
||||
String fileId = upload.getId();
|
||||
ReconcileFile reconcileFile = new ReconcileFile().setFileId(Long.valueOf(fileId))
|
||||
.setReconcileId(reconcileOrder.getId())
|
||||
.setType(ReconcileFileTypeEnum.ZIP.getCode());
|
||||
reconcileFileManager.save(reconcileFile);
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,10 @@
|
||||
package cn.bootx.platform.daxpay.service.core.channel.wechat.service;
|
||||
|
||||
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
|
||||
import cn.bootx.platform.daxpay.code.PayChannelEnum;
|
||||
import cn.bootx.platform.daxpay.code.ReconcileTradeEnum;
|
||||
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
|
||||
import cn.bootx.platform.daxpay.service.code.ReconcileFileTypeEnum;
|
||||
import cn.bootx.platform.daxpay.service.code.WeChatPayCode;
|
||||
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.wechat.dao.WxReconcileBillDetailManager;
|
||||
@@ -11,13 +13,16 @@ import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayConf
|
||||
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WxReconcileBillDetail;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WxReconcileBillTotal;
|
||||
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WxReconcileFundFlowDetail;
|
||||
import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.ReconcileFileManager;
|
||||
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileDetail;
|
||||
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileFile;
|
||||
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileOrder;
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.text.csv.CsvReader;
|
||||
import cn.hutool.core.text.csv.CsvUtil;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.ijpay.core.enums.SignType;
|
||||
import com.ijpay.core.kit.WxPayKit;
|
||||
@@ -27,6 +32,9 @@ import com.ijpay.wxpay.model.DownloadFundFlowModel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.x.file.storage.core.FileInfo;
|
||||
import org.dromara.x.file.storage.core.FileStorageService;
|
||||
import org.dromara.x.file.storage.core.UploadPretreatment;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -53,16 +61,20 @@ import static cn.bootx.platform.daxpay.service.code.WeChatPayCode.ACCOUNT_TYPE_B
|
||||
public class WechatPayReconcileService{
|
||||
private final WxReconcileBillTotalManger reconcileBillTotalManger;
|
||||
private final WxReconcileBillDetailManager reconcileBillDetailManager;
|
||||
private final FileStorageService fileStorageService;
|
||||
private final ReconcileFileManager reconcileFileManager;
|
||||
|
||||
/**
|
||||
* 下载对账单并保存
|
||||
* @param date 对账日期 yyyyMMdd 格式
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void downAndSave(String date, WeChatPayConfig config) {
|
||||
public void downAndSave(String date, WeChatPayConfig config) {
|
||||
// TODO 修改为现将对账单全部下载下来, 然后再进行保存和解析
|
||||
|
||||
this.downBill(date, config);
|
||||
// 资金对账单先不启用
|
||||
// this.downFundFlow(date, recordOrderId, config);
|
||||
this.downFundFlow(date, config);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -111,7 +123,8 @@ public class WechatPayReconcileService{
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传对账单
|
||||
* 上传对账单明细
|
||||
* todo 增加校验, 增加类型识别
|
||||
*/
|
||||
@SneakyThrows
|
||||
public void uploadBill(byte[] bytes, WeChatPayConfig config){
|
||||
@@ -140,6 +153,7 @@ public class WechatPayReconcileService{
|
||||
.collect(Collectors.toList());
|
||||
|
||||
billDetails.forEach(o->o.setRecordOrderId(reconcileOrder.getId()));
|
||||
// 保存原始对账单明细
|
||||
reconcileBillDetailManager.saveAll(billDetails);
|
||||
|
||||
// 将原始交易明细对账记录转换通用结构并保存到上下文中
|
||||
@@ -207,9 +221,8 @@ public class WechatPayReconcileService{
|
||||
* 更换一下最新的JDK即可, 例如 corretto Jdk
|
||||
*
|
||||
* @param date 对账日期 yyyyMMdd 格式
|
||||
* @param recordOrderId 对账订单ID
|
||||
*/
|
||||
public void downFundFlow(String date, Long recordOrderId, WeChatPayConfig config){
|
||||
public void downFundFlow(String date, WeChatPayConfig config){
|
||||
if (StrUtil.isBlank(config.getP12())){
|
||||
return;
|
||||
}
|
||||
@@ -297,4 +310,26 @@ public class WechatPayReconcileService{
|
||||
throw new PayFailureException("微信资金对账失败: " + errorMsg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 保存下载的原始对账文件
|
||||
*/
|
||||
private void saveOriginalFile(ReconcileOrder reconcileOrder,String text, ReconcileFileTypeEnum fileType) {
|
||||
// 微信接收结果转换为 byte[]
|
||||
PayChannelEnum channelEnum = PayChannelEnum.findByCode(reconcileOrder.getChannel());
|
||||
String date = LocalDateTimeUtil.format(reconcileOrder.getDate(), DatePattern.PURE_DATE_PATTERN);
|
||||
// 将原始文件进行保存 通道-日期
|
||||
String fileName = StrUtil.format("{}-{}-{}.text", channelEnum.getName(),date,fileType.getName());
|
||||
byte[] bytes = StrUtil.bytes(text, CharsetUtil.CHARSET_UTF_8);
|
||||
UploadPretreatment uploadPretreatment = fileStorageService.of(bytes);
|
||||
if (StrUtil.isNotBlank(fileName)) {
|
||||
uploadPretreatment.setOriginalFilename(fileName);
|
||||
}
|
||||
FileInfo upload = uploadPretreatment.upload();
|
||||
String fileId = upload.getId();
|
||||
ReconcileFile reconcileFile = new ReconcileFile().setFileId(Long.valueOf(fileId))
|
||||
.setReconcileId(reconcileOrder.getId())
|
||||
.setType(fileType.getCode());
|
||||
reconcileFileManager.save(reconcileFile);
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@ package cn.bootx.platform.daxpay.service.core.order.reconcile.entity;
|
||||
|
||||
import cn.bootx.platform.common.core.function.EntityBaseFunction;
|
||||
import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity;
|
||||
import cn.bootx.platform.daxpay.code.PayChannelEnum;
|
||||
import cn.bootx.platform.daxpay.service.code.ReconcileResultEnum;
|
||||
import cn.bootx.platform.daxpay.service.core.order.reconcile.conver.ReconcileConvert;
|
||||
import cn.bootx.platform.daxpay.service.dto.order.reconcile.ReconcileOrderDto;
|
||||
@@ -36,17 +37,28 @@ public class ReconcileOrder extends MpCreateEntity implements EntityBaseFunction
|
||||
@DbColumn(comment = "日期")
|
||||
private LocalDate date;
|
||||
|
||||
/** 通道 */
|
||||
/**
|
||||
* 通道
|
||||
* @see PayChannelEnum
|
||||
*/
|
||||
@DbColumn(comment = "通道")
|
||||
private String channel;
|
||||
|
||||
/** 是否下载成功 */
|
||||
@DbColumn(comment = "是否下载或上传")
|
||||
private boolean downOrUpload;
|
||||
/** 明细对账文件是否下载成功 */
|
||||
@DbColumn(comment = "明细对账单下载")
|
||||
private boolean detailDown;
|
||||
|
||||
/** 是否比对完成 */
|
||||
@DbColumn(comment = "是否比对完成")
|
||||
private boolean compare;
|
||||
/** 明细是否比对完成 */
|
||||
@DbColumn(comment = "明细对账单比对")
|
||||
private boolean detailCompare;
|
||||
|
||||
/** 汇总对账文件是否下载成功 */
|
||||
@DbColumn(comment = "汇总对账单下载")
|
||||
private boolean totalDown;
|
||||
|
||||
/** 汇总是否比对完成 */
|
||||
@DbColumn(comment = "汇总对账单比对")
|
||||
private boolean totalCompare;
|
||||
|
||||
/**
|
||||
* 对账结果
|
||||
|
@@ -92,7 +92,7 @@ public class ReconcileService {
|
||||
*/
|
||||
public void downAndSave(ReconcileOrder reconcileOrder) {
|
||||
// 如果对账单已经存在
|
||||
if (reconcileOrder.isDownOrUpload()){
|
||||
if (reconcileOrder.isDetailDown() && reconcileOrder.isTotalDown()){
|
||||
throw new PayFailureException("对账单文件已经下载或上传");
|
||||
}
|
||||
// 将对账订单写入到上下文中
|
||||
@@ -103,7 +103,8 @@ public class ReconcileService {
|
||||
reconcileStrategy.doBeforeHandler();
|
||||
try {
|
||||
reconcileStrategy.downAndSave();
|
||||
reconcileOrder.setDownOrUpload(true)
|
||||
reconcileOrder.setDetailDown(true)
|
||||
.setTotalDown(true)
|
||||
.setErrorMsg(null);
|
||||
reconcileOrderService.update(reconcileOrder);
|
||||
} catch (Exception e) {
|
||||
@@ -154,16 +155,16 @@ public class ReconcileService {
|
||||
* 对账单比对
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void compare(Long reconcileOrderId){
|
||||
public void compareDetail(Long reconcileOrderId){
|
||||
ReconcileOrder reconcileOrder = reconcileOrderService.findById(reconcileOrderId)
|
||||
.orElseThrow(() -> new DataNotExistException("未找到对账订单"));
|
||||
this.compare(reconcileOrder);
|
||||
this.compareDetail(reconcileOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
* 对账单比对
|
||||
*/
|
||||
public void compare(ReconcileOrder reconcileOrder){
|
||||
public void compareDetail(ReconcileOrder reconcileOrder){
|
||||
// 判断是否已经下载了对账单明细
|
||||
if (!reconcileOrder.isDownOrUpload()){
|
||||
throw new PayFailureException("请先下载对账单");
|
||||
|
@@ -71,8 +71,6 @@ public class UnionPayReconcileStrategy extends AbsReconcileStrategy {
|
||||
@Override
|
||||
public void downAndSave() {
|
||||
Date date = DateUtil.date(this.getRecordOrder().getDate());
|
||||
reconcileService.downAndSave(date, this.unionPayKit);
|
||||
reconcileService.downAndSave(this.getRecordOrder(),date, this.unionPayKit);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user