mirror of
https://gitee.com/dromara/dax-pay.git
synced 2025-10-14 13:50:25 +00:00
ref 删除对账功能
This commit is contained in:
@@ -1,64 +0,0 @@
|
||||
package org.dromara.daxpay.channel.alipay.bo;
|
||||
|
||||
import cn.hutool.core.annotation.Alias;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 支付宝业务明细对账单解析类
|
||||
* @author xxm
|
||||
* @since 2024/1/18
|
||||
*/
|
||||
@Data
|
||||
public class AlipayReconcileBillDetail {
|
||||
@Alias("支付宝交易号")
|
||||
private String tradeNo;
|
||||
@Alias("商户订单号")
|
||||
private String outTradeNo;
|
||||
@Alias("业务类型")
|
||||
private String tradeType;
|
||||
@Alias("商品名称")
|
||||
private String subject;
|
||||
@Alias("创建时间")
|
||||
private String createTime;
|
||||
/** yyyy-MM-dd HH:mm:ss */
|
||||
@Alias("完成时间")
|
||||
private String endTime;
|
||||
@Alias("门店编号")
|
||||
private String storeId;
|
||||
@Alias("门店名称")
|
||||
private String storeName;
|
||||
@Alias("操作员")
|
||||
private String operator;
|
||||
@Alias("终端号")
|
||||
private String terminalId;
|
||||
@Alias("对方账户")
|
||||
private String otherAccount;
|
||||
@Alias("订单金额(元)")
|
||||
private String orderAmount;
|
||||
@Alias("商家实收(元)")
|
||||
private String realAmount;
|
||||
@Alias("支付宝红包(元)")
|
||||
private String alipayAmount;
|
||||
@Alias("集分宝(元)")
|
||||
private String jfbAmount;
|
||||
@Alias("支付宝优惠(元)")
|
||||
private String alipayDiscountAmount;
|
||||
@Alias("商家优惠(元)")
|
||||
private String discountAmount;
|
||||
@Alias("券核销金额(元)")
|
||||
private String couponDiscountAmount;
|
||||
@Alias("券名称")
|
||||
private String couponName;
|
||||
@Alias("商家红包消费金额(元)")
|
||||
private String couponAmount;
|
||||
@Alias("卡消费金额(元)")
|
||||
private String cardAmount;
|
||||
@Alias("退款批次号/请求号")
|
||||
private String batchNo;
|
||||
@Alias("服务费(元)")
|
||||
private String serviceAmount;
|
||||
@Alias("分润(元)")
|
||||
private String splitAmount;
|
||||
@Alias("备注")
|
||||
private String remark;
|
||||
}
|
@@ -1,43 +0,0 @@
|
||||
package org.dromara.daxpay.channel.alipay.bo;
|
||||
|
||||
import cn.bootx.platform.common.mybatisplus.base.MpIdEntity;
|
||||
import cn.hutool.core.annotation.Alias;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
/**
|
||||
* 支付宝业务汇总对账单解析类
|
||||
* @author xxm
|
||||
* @since 2024/1/17
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@TableName("pay_alipay_reconcile_bill_total")
|
||||
public class AlipayReconcileBillTotal extends MpIdEntity {
|
||||
@Alias("门店编号")
|
||||
private String storeId;
|
||||
@Alias("门店名称")
|
||||
private String storeName;
|
||||
@Alias("交易订单总笔数")
|
||||
private String totalNum;
|
||||
@Alias("退款订单总笔数")
|
||||
private String totalRefundNum;
|
||||
@Alias("订单金额(元)")
|
||||
private String totalOrderAmount;
|
||||
@Alias("商家实收(元)")
|
||||
private String totalAmount;
|
||||
@Alias("支付宝优惠(元)")
|
||||
private String totalDiscountAmount;
|
||||
@Alias("商家优惠(元)")
|
||||
private String totalCouponAmount;
|
||||
// 卡消费金额(元) 服务费(元) 分润(元) 实收净额(元)
|
||||
@Alias("卡消费金额(元)")
|
||||
private String totalConsumeAmount;
|
||||
@Alias("服务费(元)")
|
||||
private String totalServiceAmount;
|
||||
@Alias("分润(元)")
|
||||
private String totalShareAmount;
|
||||
@Alias("实收净额(元)")
|
||||
private String totalNetAmount;
|
||||
}
|
@@ -1,223 +0,0 @@
|
||||
package org.dromara.daxpay.channel.alipay.service.payment.reconcile;
|
||||
|
||||
import org.dromara.daxpay.channel.alipay.bo.AlipayReconcileBillDetail;
|
||||
import org.dromara.daxpay.channel.alipay.bo.AlipayReconcileBillTotal;
|
||||
import org.dromara.daxpay.channel.alipay.entity.config.AliPayConfig;
|
||||
import org.dromara.daxpay.channel.alipay.service.payment.config.AlipayConfigService;
|
||||
import org.dromara.daxpay.core.enums.TradeStatusEnum;
|
||||
import org.dromara.daxpay.core.enums.TradeTypeEnum;
|
||||
import org.dromara.daxpay.core.exception.OperationFailException;
|
||||
import org.dromara.daxpay.core.exception.ReconciliationFailException;
|
||||
import org.dromara.daxpay.service.bo.reconcile.ChannelReconcileTradeBo;
|
||||
import org.dromara.daxpay.service.bo.reconcile.ReconcileResolveResultBo;
|
||||
import org.dromara.daxpay.service.entity.reconcile.ReconcileStatement;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
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.StrUtil;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.AlipayConstants;
|
||||
import com.alipay.api.domain.AlipayDataDataserviceBillDownloadurlQueryModel;
|
||||
import com.alipay.api.request.AlipayDataDataserviceBillDownloadurlQueryRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
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.upload.UploadPretreatment;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 支付宝对账服务
|
||||
* @author xxm
|
||||
* @since 2024/1/17
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AlipayReconcileService {
|
||||
|
||||
private final AlipayConfigService aliPayConfigService;
|
||||
|
||||
private final FileStorageService fileStorageService;
|
||||
|
||||
|
||||
/**
|
||||
* 下载对账单, 并进行解析
|
||||
*
|
||||
* @param date 对账日期 yyyy-MM-dd 格式
|
||||
* @param statement 对账单对象
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ReconcileResolveResultBo downAndResolve(String date, ReconcileStatement statement, AliPayConfig aliPayConfig){
|
||||
try {
|
||||
var model = new AlipayDataDataserviceBillDownloadurlQueryModel();
|
||||
model.setBillDate(date);
|
||||
// 下载交易类型
|
||||
model.setBillType("trade");
|
||||
var request = new AlipayDataDataserviceBillDownloadurlQueryRequest();
|
||||
// 特约商户调用
|
||||
if (aliPayConfig.isIsv()){
|
||||
request.putOtherTextParam(AlipayConstants.APP_AUTH_TOKEN, aliPayConfig.getAppAuthToken());
|
||||
}
|
||||
request.setBizModel(model);
|
||||
var response = aliPayConfigService.execute(request,aliPayConfig);
|
||||
// 判断返回结果
|
||||
if (!response.isSuccess()) {
|
||||
log.error("获取支付宝对账单失败: {}", response.getSubMsg());
|
||||
throw new ReconciliationFailException(response.getSubMsg());
|
||||
}
|
||||
|
||||
// 获取对账单下载地址并下载
|
||||
String url = response.getBillDownloadUrl();
|
||||
byte[] zipBytes = HttpUtil.downloadBytes(url);
|
||||
// 使用 Apache commons-compress 包装流, 读取返回的对账CSV文件
|
||||
ZipArchiveInputStream zipArchiveInputStream = new ZipArchiveInputStream(new ByteArrayInputStream(zipBytes), "GBK");
|
||||
ZipArchiveEntry entry;
|
||||
List<AlipayReconcileBillDetail> billDetails = new ArrayList<>();
|
||||
byte[] bytes = null;
|
||||
while ((entry = zipArchiveInputStream.getNextZipEntry()) != null) {
|
||||
String name = entry.getName();
|
||||
// 只处理明细
|
||||
if (!StrUtil.endWith(name, "_业务明细(汇总).csv")) {
|
||||
bytes = IoUtil.readBytes(zipArchiveInputStream);
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes), "GBK"));
|
||||
List<String> strings = IoUtil.readLines(bufferedReader, new ArrayList<>());
|
||||
billDetails = this.parseDetail(strings);
|
||||
}
|
||||
}
|
||||
// 保存原始对账文件
|
||||
String originalFile = this.saveOriginalFile(statement, bytes);
|
||||
|
||||
// 将原始交易明细对账记录转换通用结构
|
||||
var reconcileTradeBos = this.convertReconcileTrade(billDetails);
|
||||
return new ReconcileResolveResultBo()
|
||||
.setChannelTrades(reconcileTradeBos)
|
||||
.setOriginalFileUrl(originalFile);
|
||||
|
||||
} catch (AlipayApiException e) {
|
||||
log.error("下载对账单失败",e);
|
||||
throw new OperationFailException("下载对账单失败: "+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传对账单解析并保存
|
||||
*/
|
||||
@SneakyThrows
|
||||
public ReconcileResolveResultBo upload(ReconcileStatement statement, byte[] bytes) {
|
||||
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes),"GBK"));
|
||||
List<String> strings = IoUtil.readLines(bufferedReader, new ArrayList<>());
|
||||
List<AlipayReconcileBillDetail> billDetails = this.parseDetail(strings);
|
||||
// 保存原始对账文件
|
||||
String originalFile = this.saveOriginalFile(statement, bytes);
|
||||
// 将原始交易明细对账记录转换通用结构
|
||||
var reconcileTradeBos = this.convertReconcileTrade(billDetails);
|
||||
return new ReconcileResolveResultBo()
|
||||
.setChannelTrades(reconcileTradeBos)
|
||||
.setOriginalFileUrl(originalFile);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为通用对账记录对象
|
||||
*/
|
||||
private List<ChannelReconcileTradeBo> convertReconcileTrade(List<AlipayReconcileBillDetail> billDetails){
|
||||
return billDetails.stream()
|
||||
.map(this::convert)
|
||||
.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为通用对账记录对象
|
||||
*/
|
||||
private ChannelReconcileTradeBo convert(AlipayReconcileBillDetail billDetail){
|
||||
// 金额
|
||||
var amount = new BigDecimal(billDetail.getOrderAmount());
|
||||
// 默认为支付对账记录
|
||||
ChannelReconcileTradeBo reconcileTradeBo = new ChannelReconcileTradeBo()
|
||||
.setPlatformTradeNo(billDetail.getOutTradeNo())
|
||||
.setTradeType(TradeTypeEnum.PAY.getCode())
|
||||
.setAmount(amount)
|
||||
.setTradeStatus(TradeStatusEnum.SUCCESS.getCode())
|
||||
.setChannelTradeNo(billDetail.getTradeNo());
|
||||
// 时间
|
||||
String endTime = billDetail.getEndTime();
|
||||
if (StrUtil.isNotBlank(endTime)) {
|
||||
LocalDateTime time = LocalDateTimeUtil.parse(endTime, DatePattern.NORM_DATETIME_PATTERN);
|
||||
reconcileTradeBo.setTradeTime(time);
|
||||
}
|
||||
|
||||
// 退款覆盖更新对应的字段
|
||||
if (Objects.equals(billDetail.getTradeType(), "退款")){
|
||||
reconcileTradeBo.setPlatformTradeNo(billDetail.getBatchNo())
|
||||
.setTradeType(TradeTypeEnum.REFUND.getCode());
|
||||
}
|
||||
return reconcileTradeBo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 解析明细
|
||||
*/
|
||||
private List<AlipayReconcileBillDetail> parseDetail(List<String> list){
|
||||
// 截取需要进行解析的文本内容
|
||||
String billDetail = list.stream()
|
||||
.collect(Collectors.joining(System.lineSeparator()));
|
||||
billDetail = StrUtil.subBetween(billDetail,
|
||||
"#-----------------------------------------业务明细列表----------------------------------------"+System.lineSeparator(),
|
||||
"#-----------------------------------------业务明细列表结束------------------------------------");
|
||||
billDetail = billDetail.replaceAll("\t", "");
|
||||
CsvReader reader = CsvUtil.getReader();
|
||||
return reader.read(billDetail, AlipayReconcileBillDetail.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析汇总
|
||||
*/
|
||||
private List<AlipayReconcileBillTotal> parseTotal(List<String> list){
|
||||
// 去除前 4 行和后 2 行 然后合并是个一个字符串
|
||||
String billTotal = list.stream()
|
||||
.collect(Collectors.joining(System.lineSeparator()));
|
||||
billTotal = StrUtil.subBetween(billTotal,
|
||||
"#-----------------------------------------业务汇总列表----------------------------------------"+System.lineSeparator(),
|
||||
"#----------------------------------------业务汇总列表结束-------------------------------------");
|
||||
|
||||
billTotal = billTotal.replaceAll("\t", "");
|
||||
CsvReader reader = CsvUtil.getReader();
|
||||
return reader.read(billTotal, AlipayReconcileBillTotal.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存下载的原始对账文件
|
||||
*/
|
||||
private String saveOriginalFile(ReconcileStatement statement, byte[] bytes) {
|
||||
// 将原始文件进行保存
|
||||
String date = LocalDateTimeUtil.format(statement.getDate(), DatePattern.PURE_DATE_PATTERN);
|
||||
// 将原始文件进行保存 通道-日期
|
||||
String fileName = StrUtil.format("交易对账单-支付宝-{}.csv",date);
|
||||
UploadPretreatment uploadPretreatment = fileStorageService.of(bytes);
|
||||
if (StrUtil.isNotBlank(fileName)) {
|
||||
uploadPretreatment.setOriginalFilename(fileName);
|
||||
}
|
||||
FileInfo upload = uploadPretreatment.upload();
|
||||
return upload.getUrl();
|
||||
}
|
||||
}
|
@@ -1,65 +0,0 @@
|
||||
package org.dromara.daxpay.channel.alipay.strategy.merchant;
|
||||
|
||||
import org.dromara.daxpay.channel.alipay.entity.config.AliPayConfig;
|
||||
import org.dromara.daxpay.channel.alipay.service.payment.config.AlipayConfigService;
|
||||
import org.dromara.daxpay.channel.alipay.service.payment.reconcile.AlipayReconcileService;
|
||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||
import org.dromara.daxpay.service.bo.reconcile.ReconcileResolveResultBo;
|
||||
import org.dromara.daxpay.service.enums.ReconcileFileTypeEnum;
|
||||
import org.dromara.daxpay.service.strategy.AbsReconcileStrategy;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
|
||||
|
||||
/**
|
||||
* 支付宝对账策略
|
||||
* @author xxm
|
||||
* @since 2024/1/17
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@Scope(SCOPE_PROTOTYPE)
|
||||
@RequiredArgsConstructor
|
||||
public class AlipayReconcileStrategy extends AbsReconcileStrategy {
|
||||
|
||||
private final AlipayReconcileService reconcileService;
|
||||
private final AlipayConfigService aliPayConfigService;
|
||||
|
||||
|
||||
/**
|
||||
* 策略标识, 可以自行进行扩展
|
||||
*
|
||||
* @see ChannelEnum
|
||||
*/
|
||||
@Override
|
||||
public String getChannel() {
|
||||
return ChannelEnum.ALIPAY.getCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传对账单解析并保存
|
||||
*
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public ReconcileResolveResultBo uploadAndResolve(MultipartFile file, ReconcileFileTypeEnum fileType) {
|
||||
return reconcileService.upload(this.getStatement(), file.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载对账单到本地进行保存
|
||||
*/
|
||||
@Override
|
||||
public ReconcileResolveResultBo downAndResolve() {
|
||||
AliPayConfig aliPayConfig = aliPayConfigService.getAliPayConfig(false);
|
||||
String date = LocalDateTimeUtil.format(this.getStatement().getDate(), DatePattern.NORM_DATE_PATTERN);
|
||||
return reconcileService.downAndResolve(date, this.getStatement(),aliPayConfig);
|
||||
}
|
||||
}
|
@@ -1,64 +0,0 @@
|
||||
package org.dromara.daxpay.channel.alipay.strategy.sub;
|
||||
|
||||
import org.dromara.daxpay.channel.alipay.entity.config.AliPayConfig;
|
||||
import org.dromara.daxpay.channel.alipay.service.payment.config.AlipayConfigService;
|
||||
import org.dromara.daxpay.channel.alipay.service.payment.reconcile.AlipayReconcileService;
|
||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||
import org.dromara.daxpay.service.bo.reconcile.ReconcileResolveResultBo;
|
||||
import org.dromara.daxpay.service.enums.ReconcileFileTypeEnum;
|
||||
import org.dromara.daxpay.service.strategy.AbsReconcileStrategy;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
|
||||
|
||||
/**
|
||||
* 支付宝对账策略
|
||||
* @author xxm
|
||||
* @since 2024/1/17
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@Scope(SCOPE_PROTOTYPE)
|
||||
@RequiredArgsConstructor
|
||||
public class AlipaySubReconcileStrategy extends AbsReconcileStrategy {
|
||||
|
||||
private final AlipayReconcileService reconcileService;
|
||||
private final AlipayConfigService aliPayConfigService;
|
||||
|
||||
/**
|
||||
* 策略标识, 可以自行进行扩展
|
||||
*
|
||||
* @see ChannelEnum
|
||||
*/
|
||||
@Override
|
||||
public String getChannel() {
|
||||
return ChannelEnum.ALIPAY_ISV.getCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传对账单解析并保存
|
||||
*
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public ReconcileResolveResultBo uploadAndResolve(MultipartFile file, ReconcileFileTypeEnum fileType) {
|
||||
return reconcileService.upload(this.getStatement(), file.getBytes());
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载对账单到本地进行保存
|
||||
*/
|
||||
@Override
|
||||
public ReconcileResolveResultBo downAndResolve() {
|
||||
AliPayConfig aliPayConfig = aliPayConfigService.getAliPayConfig(true);
|
||||
String date = LocalDateTimeUtil.format(this.getStatement().getDate(), DatePattern.NORM_DATE_PATTERN);
|
||||
return reconcileService.downAndResolve(date, this.getStatement(),aliPayConfig);
|
||||
}
|
||||
}
|
@@ -1,151 +0,0 @@
|
||||
package org.dromara.daxpay.channel.wechat.entity.reconcile;
|
||||
|
||||
import cn.hutool.core.annotation.Alias;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* 微信交易对账解析文件
|
||||
* @author xxm
|
||||
* @since 2024/8/11
|
||||
*/
|
||||
@Slf4j
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class WechatReconcileBillDetail {
|
||||
|
||||
// 交易时间
|
||||
@Alias("交易时间")
|
||||
private String transactionTime;
|
||||
// 公众账号ID
|
||||
@Alias("公众账号ID")
|
||||
private String appid;
|
||||
|
||||
// 商户号
|
||||
@Alias("商户号")
|
||||
private String mchid;
|
||||
|
||||
// 特约商户号
|
||||
@Alias("特约商户号")
|
||||
private String subMchid;
|
||||
|
||||
// 设备号
|
||||
@Alias("设备号")
|
||||
private String deviceInfo;
|
||||
|
||||
// 微信订单号
|
||||
@Alias("微信订单号")
|
||||
private String transactionId;
|
||||
|
||||
// 商户订单号
|
||||
@Alias("商户订单号")
|
||||
private String outTradeNo;
|
||||
|
||||
// 用户标识
|
||||
@Alias("用户标识")
|
||||
private String openid;
|
||||
|
||||
// 交易类型 JSAPI/NATIVE
|
||||
@Alias("交易类型")
|
||||
private String tradeType;
|
||||
|
||||
// 交易状态
|
||||
@Alias("交易状态")
|
||||
private String tradeState;
|
||||
|
||||
// 付款银行
|
||||
@Alias("付款银行")
|
||||
private String bankType;
|
||||
|
||||
// 货币种类
|
||||
@Alias("货币种类")
|
||||
private String feeType;
|
||||
|
||||
// 应结订单金额
|
||||
@Alias("应结订单金额")
|
||||
private String settlementTotalFee;
|
||||
|
||||
// 代金券金额
|
||||
@Alias("代金券金额")
|
||||
private String couponFee;
|
||||
|
||||
// 微信退款单号
|
||||
@Alias("微信退款单号")
|
||||
private String refundId;
|
||||
|
||||
// 商户退款单号
|
||||
@Alias("商户退款单号")
|
||||
private String outRefundNo;
|
||||
|
||||
/**
|
||||
* 退款金额
|
||||
* 该笔退款单参与计费的应结算金额(申请退款金额-免充值券退款金额),
|
||||
* 如果该行数据为订单则展示为0.00,非负数、单位元,保留到小数点后2位
|
||||
*/
|
||||
@Alias("退款金额")
|
||||
private String refundFee;
|
||||
|
||||
// 充值券退款金额
|
||||
@Alias("充值券退款金额")
|
||||
private String couponRefundFee;
|
||||
|
||||
// 退款类型
|
||||
@Alias("退款类型")
|
||||
private String refundType;
|
||||
|
||||
// 退款状态
|
||||
@Alias("退款状态")
|
||||
private String refundStatus;
|
||||
|
||||
// 商品名称
|
||||
@Alias("商品名称")
|
||||
private String body;
|
||||
|
||||
// 商户数据包
|
||||
@Alias("商户数据包")
|
||||
private String attach;
|
||||
|
||||
// 手续费
|
||||
@Alias("手续费")
|
||||
private String fee;
|
||||
|
||||
// 费率
|
||||
@Alias("费率")
|
||||
private String feeRate;
|
||||
|
||||
// 订单金额
|
||||
@Alias("订单金额")
|
||||
private String totalFee;
|
||||
|
||||
// 申请退款金额
|
||||
@Alias("申请退款金额")
|
||||
private String applyRefundFee;
|
||||
|
||||
// 费率备注
|
||||
@Alias("费率备注")
|
||||
private String feeRemark;
|
||||
|
||||
/**
|
||||
* 去除前缀的 ` 符号
|
||||
*/
|
||||
public void removeStartSymbol() {
|
||||
Field[] fields = this.getClass().getDeclaredFields();
|
||||
for (Field field : fields) {
|
||||
if (field.getType() == String.class) {
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
String value = (String) field.get(this);
|
||||
if (StrUtil.startWith(value, "`")) {
|
||||
field.set(this, StrUtil.replaceFirst(value, "`", ""));
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
log.warn("去除前缀错误错误", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,169 +0,0 @@
|
||||
package org.dromara.daxpay.channel.wechat.service.payment.reconcile;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
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.StrUtil;
|
||||
import com.github.binarywang.wxpay.bean.request.WxPayApplyTradeBillV3Request;
|
||||
import com.github.binarywang.wxpay.bean.result.WxPayApplyBillV3Result;
|
||||
import com.github.binarywang.wxpay.constant.WxPayConstants;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.channel.wechat.entity.config.WechatPayConfig;
|
||||
import org.dromara.daxpay.channel.wechat.entity.reconcile.WechatReconcileBillDetail;
|
||||
import org.dromara.daxpay.channel.wechat.service.payment.config.WechatPayConfigService;
|
||||
import org.dromara.daxpay.core.enums.TradeStatusEnum;
|
||||
import org.dromara.daxpay.core.enums.TradeTypeEnum;
|
||||
import org.dromara.daxpay.core.exception.OperationFailException;
|
||||
import org.dromara.daxpay.service.bo.reconcile.ChannelReconcileTradeBo;
|
||||
import org.dromara.daxpay.service.bo.reconcile.ReconcileResolveResultBo;
|
||||
import org.dromara.daxpay.service.entity.reconcile.ReconcileStatement;
|
||||
import org.dromara.x.file.storage.core.FileInfo;
|
||||
import org.dromara.x.file.storage.core.FileStorageService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 微信支付对账
|
||||
* @author xxm
|
||||
* @since 2024/1/17
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class WechatReconcileService {
|
||||
private final FileStorageService fileStorageService;
|
||||
private final WechatPayConfigService wechatPayConfigService;
|
||||
|
||||
/**
|
||||
* 下载对账单并保存
|
||||
*
|
||||
* @param statement 对账订单
|
||||
* @param date 对账日期 yyyyMMdd 格式
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ReconcileResolveResultBo downAndResolve(ReconcileStatement statement, String date) {
|
||||
WechatPayConfig config = wechatPayConfigService.getAndCheckConfig(false);
|
||||
WxPayService wxPayService = wechatPayConfigService.wxJavaSdk(config);
|
||||
var request = new WxPayApplyTradeBillV3Request();
|
||||
request.setBillDate(date);
|
||||
request.setBillType("ALL");
|
||||
try {
|
||||
WxPayApplyBillV3Result wxPayApplyBillV3Result = wxPayService.applyTradeBill(request);
|
||||
String downloadUrl = wxPayApplyBillV3Result.getDownloadUrl();
|
||||
byte[] bytes;
|
||||
try (InputStream inputStream = wxPayService.downloadBill(downloadUrl)) {
|
||||
bytes = IoUtil.readBytes(inputStream);
|
||||
}
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes)));
|
||||
String result = IoUtil.read(reader);
|
||||
// 过滤特殊字符
|
||||
result = result.replaceAll("`", "").replaceAll("\uFEFF", "");
|
||||
CsvReader csvRows = CsvUtil.getReader();
|
||||
// 获取交易记录并保存 同时过滤出当前应用的交易记录
|
||||
String billDetail = StrUtil.subBefore(result, "总交易单数", false);
|
||||
var billDetails = csvRows.read(billDetail, WechatReconcileBillDetail.class).stream()
|
||||
// 只读取当前商户的订单
|
||||
.filter(o->Objects.equals(o.getAppid(), config.getWxAppId()))
|
||||
// 只读取对账日的记录
|
||||
.filter(o->{
|
||||
String transactionTime = o.getTransactionTime();
|
||||
LocalDateTime time = LocalDateTimeUtil.parse(transactionTime, DatePattern.NORM_DATETIME_PATTERN);
|
||||
return Objects.equals(statement.getDate(), LocalDate.from(time));
|
||||
})
|
||||
.toList();
|
||||
|
||||
// 保存原始对账文件
|
||||
String originalFile = this.saveOriginalFile(statement, bytes);
|
||||
// 解析账单文件
|
||||
var tradeBos = this.convertReconcileTrade(billDetails);
|
||||
return new ReconcileResolveResultBo()
|
||||
.setOriginalFileUrl(originalFile)
|
||||
.setChannelTrades(tradeBos);
|
||||
} catch (WxPayException | IOException e) {
|
||||
log.error("下载对账单失败", e);
|
||||
throw new OperationFailException("下载对账单失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为通用对账记录对象
|
||||
*/
|
||||
private List<ChannelReconcileTradeBo> convertReconcileTrade(List<WechatReconcileBillDetail> billDetails){
|
||||
return billDetails.stream()
|
||||
.map(this::convert)
|
||||
.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为通用对账记录对象
|
||||
*/
|
||||
private ChannelReconcileTradeBo convert(WechatReconcileBillDetail billDetail){
|
||||
// 交易时间时间 指该笔交易的支付成功时间或发起退款成功时间(注:不是退款成功时间)
|
||||
LocalDateTime time = LocalDateTimeUtil.parse(billDetail.getTransactionTime(), DatePattern.NORM_DATETIME_PATTERN);
|
||||
// 默认为支付对账记录
|
||||
ChannelReconcileTradeBo tradeBo = new ChannelReconcileTradeBo()
|
||||
.setPlatformTradeNo(billDetail.getOutTradeNo())
|
||||
.setTradeType(TradeTypeEnum.PAY.getCode())
|
||||
.setTradeTime(time)
|
||||
.setChannelTradeNo(billDetail.getTransactionId());
|
||||
if (Objects.equals(billDetail.getTradeState(), WxPayConstants.WxpayTradeStatus.SUCCESS)) {
|
||||
tradeBo.setTradeType(TradeTypeEnum.PAY.getCode())
|
||||
.setAmount(new BigDecimal(billDetail.getTotalFee()))
|
||||
.setTradeStatus(TradeStatusEnum.SUCCESS.getCode());
|
||||
}
|
||||
|
||||
// 退款覆盖更新对应的字段
|
||||
if (Objects.equals(billDetail.getTradeState(), WxPayConstants.WxpayTradeStatus.REFUND)) {
|
||||
tradeBo.setPlatformTradeNo(billDetail.getOutRefundNo())
|
||||
.setChannelTradeNo(billDetail.getRefundId())
|
||||
.setAmount(new BigDecimal(billDetail.getRefundFee()))
|
||||
.setTradeType(TradeTypeEnum.REFUND.getCode());
|
||||
tradeBo.setTradeType(TradeTypeEnum.REFUND.getCode());
|
||||
// 状态
|
||||
switch (billDetail.getRefundStatus()) {
|
||||
case WxPayConstants.RefundStatus.SUCCESS -> tradeBo.setTradeStatus(TradeStatusEnum.SUCCESS.getCode());
|
||||
case WxPayConstants.RefundStatus.PROCESSING -> tradeBo.setTradeStatus(TradeStatusEnum.CLOSED.getCode());
|
||||
case WxPayConstants.ResultCode.FAIL -> tradeBo.setTradeStatus(TradeStatusEnum.FAIL.getCode());
|
||||
case WxPayConstants.RefundStatus.CHANGE -> tradeBo.setTradeStatus(TradeStatusEnum.EXCEPTION.getCode());
|
||||
}
|
||||
tradeBo.setTradeStatus(TradeStatusEnum.SUCCESS.getCode());
|
||||
}
|
||||
// 撤销状态
|
||||
if (Objects.equals(billDetail.getTradeState(), WxPayConstants.WxpayTradeStatus.REVOKED)) {
|
||||
tradeBo.setTradeType(TradeTypeEnum.PAY.getCode());
|
||||
tradeBo.setTradeStatus(TradeStatusEnum.REVOKED.getCode());
|
||||
}
|
||||
|
||||
return tradeBo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存下载的原始对账文件
|
||||
*/
|
||||
private String saveOriginalFile(ReconcileStatement reconcileOrder, byte[] bytes) {
|
||||
String date = LocalDateTimeUtil.format(reconcileOrder.getDate(), DatePattern.PURE_DATE_PATTERN);
|
||||
// 将原始文件进行保存 通道-日期
|
||||
String fileName = StrUtil.format("交易对账单-微信-{}.csv",date);
|
||||
var uploadPretreatment = fileStorageService.of(bytes);
|
||||
if (StrUtil.isNotBlank(fileName)) {
|
||||
uploadPretreatment.setOriginalFilename(fileName);
|
||||
}
|
||||
FileInfo upload = uploadPretreatment.upload();
|
||||
return upload.getUrl();
|
||||
}
|
||||
}
|
@@ -1,169 +0,0 @@
|
||||
package org.dromara.daxpay.channel.wechat.service.payment.reconcile;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
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.StrUtil;
|
||||
import com.github.binarywang.wxpay.bean.request.WxPayApplyTradeBillV3Request;
|
||||
import com.github.binarywang.wxpay.bean.result.WxPayApplyBillV3Result;
|
||||
import com.github.binarywang.wxpay.constant.WxPayConstants;
|
||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||
import com.github.binarywang.wxpay.service.WxPayService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.channel.wechat.entity.config.WechatPayConfig;
|
||||
import org.dromara.daxpay.channel.wechat.entity.reconcile.WechatReconcileBillDetail;
|
||||
import org.dromara.daxpay.channel.wechat.service.payment.config.WechatPayConfigService;
|
||||
import org.dromara.daxpay.core.enums.TradeStatusEnum;
|
||||
import org.dromara.daxpay.core.enums.TradeTypeEnum;
|
||||
import org.dromara.daxpay.core.exception.OperationFailException;
|
||||
import org.dromara.daxpay.service.bo.reconcile.ChannelReconcileTradeBo;
|
||||
import org.dromara.daxpay.service.bo.reconcile.ReconcileResolveResultBo;
|
||||
import org.dromara.daxpay.service.entity.reconcile.ReconcileStatement;
|
||||
import org.dromara.x.file.storage.core.FileInfo;
|
||||
import org.dromara.x.file.storage.core.FileStorageService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 微信支付对账
|
||||
* @author xxm
|
||||
* @since 2024/1/17
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class WechatSubReconcileService {
|
||||
private final FileStorageService fileStorageService;
|
||||
private final WechatPayConfigService wechatPayConfigService;
|
||||
|
||||
/**
|
||||
* 下载对账单并保存
|
||||
*
|
||||
* @param statement 对账订单
|
||||
* @param date 对账日期 yyyyMMdd 格式
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ReconcileResolveResultBo downAndResolve(ReconcileStatement statement, String date) {
|
||||
WechatPayConfig config = wechatPayConfigService.getAndCheckConfig(true);
|
||||
WxPayService wxPayService = wechatPayConfigService.wxJavaSdk(config);
|
||||
var request = new WxPayApplyTradeBillV3Request();
|
||||
request.setBillDate(date);
|
||||
request.setBillType("ALL");
|
||||
try {
|
||||
WxPayApplyBillV3Result wxPayApplyBillV3Result = wxPayService.applyTradeBill(request);
|
||||
String downloadUrl = wxPayApplyBillV3Result.getDownloadUrl();
|
||||
byte[] bytes;
|
||||
try (InputStream inputStream = wxPayService.downloadBill(downloadUrl)) {
|
||||
bytes = IoUtil.readBytes(inputStream);
|
||||
}
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes)));
|
||||
String result = IoUtil.read(reader);
|
||||
// 过滤特殊字符
|
||||
result = result.replaceAll("`", "").replaceAll("\uFEFF", "");
|
||||
CsvReader csvRows = CsvUtil.getReader();
|
||||
// 获取交易记录并保存 同时过滤出当前应用的交易记录
|
||||
String billDetail = StrUtil.subBefore(result, "总交易单数", false);
|
||||
var billDetails = csvRows.read(billDetail, WechatReconcileBillDetail.class).stream()
|
||||
// 只读取当前商户的订单
|
||||
.filter(o->Objects.equals(o.getAppid(), config.getSubAppId()))
|
||||
// 只读取对账日的记录
|
||||
.filter(o->{
|
||||
String transactionTime = o.getTransactionTime();
|
||||
LocalDateTime time = LocalDateTimeUtil.parse(transactionTime, DatePattern.NORM_DATETIME_PATTERN);
|
||||
return Objects.equals(statement.getDate(), LocalDate.from(time));
|
||||
})
|
||||
.toList();
|
||||
|
||||
// 保存原始对账文件
|
||||
String originalFile = this.saveOriginalFile(statement, bytes);
|
||||
// 解析账单文件
|
||||
var tradeBos = this.convertReconcileTrade(billDetails);
|
||||
return new ReconcileResolveResultBo()
|
||||
.setOriginalFileUrl(originalFile)
|
||||
.setChannelTrades(tradeBos);
|
||||
} catch (WxPayException | IOException e) {
|
||||
log.error("下载对账单失败", e);
|
||||
throw new OperationFailException("下载对账单失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为通用对账记录对象
|
||||
*/
|
||||
private List<ChannelReconcileTradeBo> convertReconcileTrade(List<WechatReconcileBillDetail> billDetails){
|
||||
return billDetails.stream()
|
||||
.map(this::convert)
|
||||
.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为通用对账记录对象
|
||||
*/
|
||||
private ChannelReconcileTradeBo convert(WechatReconcileBillDetail billDetail){
|
||||
// 交易时间时间 指该笔交易的支付成功时间或发起退款成功时间(注:不是退款成功时间)
|
||||
LocalDateTime time = LocalDateTimeUtil.parse(billDetail.getTransactionTime(), DatePattern.NORM_DATETIME_PATTERN);
|
||||
// 默认为支付对账记录
|
||||
ChannelReconcileTradeBo tradeBo = new ChannelReconcileTradeBo()
|
||||
.setPlatformTradeNo(billDetail.getOutTradeNo())
|
||||
.setTradeType(TradeTypeEnum.PAY.getCode())
|
||||
.setTradeTime(time)
|
||||
.setChannelTradeNo(billDetail.getTransactionId());
|
||||
if (Objects.equals(billDetail.getTradeState(), WxPayConstants.WxpayTradeStatus.SUCCESS)) {
|
||||
tradeBo.setTradeType(TradeTypeEnum.PAY.getCode())
|
||||
.setAmount(new BigDecimal(billDetail.getTotalFee()))
|
||||
.setTradeStatus(TradeStatusEnum.SUCCESS.getCode());
|
||||
}
|
||||
|
||||
// 退款覆盖更新对应的字段
|
||||
if (Objects.equals(billDetail.getTradeState(), WxPayConstants.WxpayTradeStatus.REFUND)) {
|
||||
tradeBo.setPlatformTradeNo(billDetail.getOutRefundNo())
|
||||
.setChannelTradeNo(billDetail.getRefundId())
|
||||
.setAmount(new BigDecimal(billDetail.getRefundFee()))
|
||||
.setTradeType(TradeTypeEnum.REFUND.getCode());
|
||||
tradeBo.setTradeType(TradeTypeEnum.REFUND.getCode());
|
||||
// 状态
|
||||
switch (billDetail.getRefundStatus()) {
|
||||
case WxPayConstants.RefundStatus.SUCCESS -> tradeBo.setTradeStatus(TradeStatusEnum.SUCCESS.getCode());
|
||||
case WxPayConstants.RefundStatus.PROCESSING -> tradeBo.setTradeStatus(TradeStatusEnum.CLOSED.getCode());
|
||||
case WxPayConstants.ResultCode.FAIL -> tradeBo.setTradeStatus(TradeStatusEnum.FAIL.getCode());
|
||||
case WxPayConstants.RefundStatus.CHANGE -> tradeBo.setTradeStatus(TradeStatusEnum.EXCEPTION.getCode());
|
||||
}
|
||||
tradeBo.setTradeStatus(TradeStatusEnum.SUCCESS.getCode());
|
||||
}
|
||||
// 撤销状态
|
||||
if (Objects.equals(billDetail.getTradeState(), WxPayConstants.WxpayTradeStatus.REVOKED)) {
|
||||
tradeBo.setTradeType(TradeTypeEnum.PAY.getCode());
|
||||
tradeBo.setTradeStatus(TradeStatusEnum.REVOKED.getCode());
|
||||
}
|
||||
|
||||
return tradeBo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存下载的原始对账文件
|
||||
*/
|
||||
private String saveOriginalFile(ReconcileStatement reconcileOrder, byte[] bytes) {
|
||||
String date = LocalDateTimeUtil.format(reconcileOrder.getDate(), DatePattern.PURE_DATE_PATTERN);
|
||||
// 将原始文件进行保存 通道-日期
|
||||
String fileName = StrUtil.format("交易对账单-微信-{}.csv",date);
|
||||
var uploadPretreatment = fileStorageService.of(bytes);
|
||||
if (StrUtil.isNotBlank(fileName)) {
|
||||
uploadPretreatment.setOriginalFilename(fileName);
|
||||
}
|
||||
FileInfo upload = uploadPretreatment.upload();
|
||||
return upload.getUrl();
|
||||
}
|
||||
}
|
@@ -1,65 +0,0 @@
|
||||
package org.dromara.daxpay.channel.wechat.strategy.merchant;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.channel.wechat.service.payment.config.WechatPayConfigService;
|
||||
import org.dromara.daxpay.channel.wechat.service.payment.reconcile.WechatReconcileService;
|
||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||
import org.dromara.daxpay.service.bo.reconcile.ReconcileResolveResultBo;
|
||||
import org.dromara.daxpay.service.enums.ReconcileFileTypeEnum;
|
||||
import org.dromara.daxpay.service.strategy.AbsReconcileStrategy;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
|
||||
|
||||
/**
|
||||
* 微信支付对账策略
|
||||
* @author xxm
|
||||
* @since 2024/1/17
|
||||
*/
|
||||
@Slf4j
|
||||
@Scope(SCOPE_PROTOTYPE)
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class WechatReconcileStrategy extends AbsReconcileStrategy {
|
||||
|
||||
private final WechatReconcileService reconcileService;
|
||||
|
||||
private final WechatPayConfigService wechatPayConfigService;
|
||||
|
||||
/**
|
||||
* 策略标识
|
||||
*
|
||||
* @see ChannelEnum
|
||||
*/
|
||||
@Override
|
||||
public String getChannel() {
|
||||
return ChannelEnum.WECHAT.getCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传对账单解析并保存
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public ReconcileResolveResultBo uploadAndResolve(MultipartFile file, ReconcileFileTypeEnum fileType) {
|
||||
// WechatPayConfig wechatPayConfig = wechatPayConfigService.getAndCheckConfig();
|
||||
// return reconcileService.uploadBill(file.getBytes(),wechatPayConfig);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载对账单
|
||||
*/
|
||||
@Override
|
||||
public ReconcileResolveResultBo downAndResolve() {
|
||||
String date = LocalDateTimeUtil.format(this.getStatement().getDate(), DatePattern.NORM_DATE_PATTERN);
|
||||
return reconcileService.downAndResolve(this.getStatement(), date);
|
||||
}
|
||||
|
||||
}
|
@@ -1,62 +0,0 @@
|
||||
package org.dromara.daxpay.channel.wechat.strategy.sub;
|
||||
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.dromara.daxpay.channel.wechat.service.payment.reconcile.WechatSubReconcileService;
|
||||
import org.dromara.daxpay.core.enums.ChannelEnum;
|
||||
import org.dromara.daxpay.service.bo.reconcile.ReconcileResolveResultBo;
|
||||
import org.dromara.daxpay.service.enums.ReconcileFileTypeEnum;
|
||||
import org.dromara.daxpay.service.strategy.AbsReconcileStrategy;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
|
||||
|
||||
/**
|
||||
* 微信支付对账策略
|
||||
* @author xxm
|
||||
* @since 2024/1/17
|
||||
*/
|
||||
@Slf4j
|
||||
@Scope(SCOPE_PROTOTYPE)
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class WechatSubReconcileStrategy extends AbsReconcileStrategy {
|
||||
|
||||
private final WechatSubReconcileService reconcileService;
|
||||
|
||||
/**
|
||||
* 策略标识
|
||||
*
|
||||
* @see ChannelEnum
|
||||
*/
|
||||
@Override
|
||||
public String getChannel() {
|
||||
return ChannelEnum.WECHAT_ISV.getCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传对账单解析并保存
|
||||
*/
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public ReconcileResolveResultBo uploadAndResolve(MultipartFile file, ReconcileFileTypeEnum fileType) {
|
||||
// WechatPayConfig wechatPayConfig = wechatPayConfigService.getAndCheckConfig();
|
||||
// return reconcileService.uploadBill(file.getBytes(),wechatPayConfig);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载对账单
|
||||
*/
|
||||
@Override
|
||||
public ReconcileResolveResultBo downAndResolve() {
|
||||
String date = LocalDateTimeUtil.format(this.getStatement().getDate(), DatePattern.NORM_DATE_PATTERN);
|
||||
return reconcileService.downAndResolve(this.getStatement(), date);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user