diff --git a/_doc/Task.md b/_doc/Task.md index 894536e8a..14af9d638 100644 --- a/_doc/Task.md +++ b/_doc/Task.md @@ -11,7 +11,8 @@ - [x] 微信通道添加单独的认证跳转地址, 处理它的特殊情况 ## bugs -- [ ] 修复 BigDecimal 类型数据序列化和签名异常问题 +- [x] 修复 BigDecimal 类型数据序列化和签名异常问题 +- [x] 获取是否订阅消息通知类型查询范围错误问题 ## 任务池 diff --git a/daxpay-single-channel/daxpay-single-alipay/src/main/java/org/dromara/daxpay/channel/alipay/service/pay/AliPayService.java b/daxpay-single-channel/daxpay-single-alipay/src/main/java/org/dromara/daxpay/channel/alipay/service/pay/AliPayService.java index f3a4b4e19..62f0c4b04 100644 --- a/daxpay-single-channel/daxpay-single-alipay/src/main/java/org/dromara/daxpay/channel/alipay/service/pay/AliPayService.java +++ b/daxpay-single-channel/daxpay-single-alipay/src/main/java/org/dromara/daxpay/channel/alipay/service/pay/AliPayService.java @@ -66,7 +66,7 @@ public class AliPayService { if (Objects.equals(payOrder.getMethod(), PayMethodEnum.WAP.getCode())) { payBody = this.wapPay(amount, payOrder); } - // 程序支付 + // APP支付 else if (Objects.equals(payOrder.getMethod(), PayMethodEnum.APP.getCode())) { payBody = this.appPay(amount, payOrder); } diff --git a/daxpay-single-channel/daxpay-single-wechat/src/main/java/org/dromara/daxpay/channel/wechat/service/pay/WechatPayV3Service.java b/daxpay-single-channel/daxpay-single-wechat/src/main/java/org/dromara/daxpay/channel/wechat/service/pay/WechatPayV3Service.java index ec2ab8498..5f00cf75f 100644 --- a/daxpay-single-channel/daxpay-single-wechat/src/main/java/org/dromara/daxpay/channel/wechat/service/pay/WechatPayV3Service.java +++ b/daxpay-single-channel/daxpay-single-wechat/src/main/java/org/dromara/daxpay/channel/wechat/service/pay/WechatPayV3Service.java @@ -184,7 +184,7 @@ public class WechatPayV3Service { packageParams.put("package", result.getPackageValue()); String signType = result.getSignType(); if (result.getSignType() == null) { - signType = "MD5"; + signType = "RSA"; } packageParams.put("signType", signType); packageParams.put("paySign", result.getPaySign()); diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/report/IndexTradeReportController.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/report/IndexTradeReportController.java new file mode 100644 index 000000000..96dfbe640 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/controller/report/IndexTradeReportController.java @@ -0,0 +1,66 @@ +package org.dromara.daxpay.service.controller.report; + +import cn.bootx.platform.core.annotation.RequestPath; +import cn.bootx.platform.core.rest.Res; +import cn.bootx.platform.core.rest.result.Result; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.dromara.daxpay.service.param.report.TradeReportQuery; +import org.dromara.daxpay.service.result.report.TradeReportResult; +import org.dromara.daxpay.service.service.report.IndexTradeReportService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * 首页交易报表 + * @author xxm + * @since 2024/11/17 + */ +@Tag(name = "首页交易报表") +@RestController +@RequestMapping("/report/index") +@RequiredArgsConstructor +public class IndexTradeReportController { + + private final IndexTradeReportService tradeReportService; + + + @RequestPath("支付交易信息统计") + @Operation(summary = "支付交易信息统计") + @GetMapping("/pay") + public Result pryTradeReport(TradeReportQuery query){ + return Res.ok(tradeReportService.pryTradeReport(query)); + } + + @RequestPath("退款交易信息统计") + @Operation(summary = "退款交易信息统计") + @GetMapping("/refund") + public Result refundTradeReport(TradeReportQuery query){ + return Res.ok(tradeReportService.refundTradeReport(query)); + } + + @RequestPath("支付交易通道统计") + @Operation(summary = "支付交易通道统计") + @GetMapping("/payChannel") + public Result> payChannelReport(TradeReportQuery query){ + return Res.ok(tradeReportService.payChannelReport(query)); + } + + @RequestPath("退款交易通道统计") + @Operation(summary = "退款交易通道统计") + @GetMapping("/refundChannel") + public Result> refundChannelReport(TradeReportQuery query){ + return Res.ok(tradeReportService.refundChannelReport(query)); + } + + @RequestPath("支付交易方式统计") + @Operation(summary = "支付交易方式统计") + @GetMapping("/payMethod") + public Result> payMethodReport(TradeReportQuery query){ + return Res.ok(tradeReportService.payMethodReport(query)); + } +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/report/IndexTradeReportMapper.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/report/IndexTradeReportMapper.java new file mode 100644 index 000000000..9ba163e71 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/dao/report/IndexTradeReportMapper.java @@ -0,0 +1,96 @@ +package org.dromara.daxpay.service.dao.report; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Constants; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; +import org.dromara.daxpay.service.param.report.TradeReportQuery; +import org.dromara.daxpay.service.result.report.TradeReportResult; + +import java.util.List; + +/** + * 首页报表数据库查询接口 + * @author xxm + * @since 2024/11/17 + */ +@Mapper +public interface IndexTradeReportMapper { + + /** + * 支付订单 + */ + @Select(""" + select + sum(amount) as tradeAmount, + count(amount) as tradeCount, + max(amount) as maxAmount, + avg(amount) as avgAmount + from pay_order + ${ew.customSqlSegment} + """) + TradeReportResult payTradeReport(@Param(Constants.WRAPPER) QueryWrapper param); + + /** + * 退款订单 + */ + @Select(""" + select + sum(amount) as tradeAmount, + count(amount) as tradeCount, + max(amount) as maxAmount, + avg(amount) as avgAmount + from pay_refund_order + ${ew.customSqlSegment} + """) + TradeReportResult refundTradeReport(@Param(Constants.WRAPPER) QueryWrapper param); + + /** + * 支付通道 + */ + @Select(""" + select + channel as title, + sum(amount) as tradeAmount, + count(amount) as tradeCount, + max(amount) as maxAmount, + avg(amount) as avgAmount + from pay_order + ${ew.customSqlSegment} + """) + List payChannelReport(@Param(Constants.WRAPPER) QueryWrapper param); + + /** + * 退款通道 + */ + @Select(""" + select + channel as title, + sum(amount) as tradeAmount, + count(amount) as tradeCount, + max(amount) as maxAmount, + avg(amount) as avgAmount + from pay_refund_order + ${ew.customSqlSegment} + """) + List refundChannelReport(@Param(Constants.WRAPPER) QueryWrapper param); + + /** + * 支付方式统计 + */ + @Select(""" + select + method as title, + sum(amount) as tradeAmount, + count(amount) as tradeCount, + max(amount) as maxAmount, + avg(amount) as avgAmount + from pay_order + ${ew.customSqlSegment} + """) + List payMethodReport(@Param(Constants.WRAPPER) QueryWrapper param); + + + +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/param/report/TradeReportQuery.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/param/report/TradeReportQuery.java new file mode 100644 index 000000000..646387c49 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/param/report/TradeReportQuery.java @@ -0,0 +1,26 @@ +package org.dromara.daxpay.service.param.report; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.time.LocalDate; + +/** + * 交易报表查询参数 + * @author xxm + * @since 2024/11/17 + */ +@Data +@Accessors(chain = true) +@Schema(title = "交易报表查询参数") +public class TradeReportQuery { + + /** 开始日期 */ + @Schema(title = "开始日期") + private LocalDate startDate; + + /** 结束日期 */ + @Schema(title = "结束日期") + private LocalDate endDate; +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/result/report/TradeReportResult.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/result/report/TradeReportResult.java new file mode 100644 index 000000000..7e5c5f4ec --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/result/report/TradeReportResult.java @@ -0,0 +1,35 @@ +package org.dromara.daxpay.service.result.report; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; + +/** + * 交易报表结果 + * @author xxm + * @since 2024/11/17 + */ +@Data +@Accessors(chain = true) +@Schema(title = "交易报表结果") +public class TradeReportResult { + + @Schema(title = "标题") + private String title; + + @Schema(title = "交易金额") + private BigDecimal tradeAmount; + + @Schema(title = "交易笔数") + private Integer tradeCount; + + @Schema(title = "最大单笔金额") + private BigDecimal maxAmount; + + @Schema(title = "平均单笔金额") + private BigDecimal avgAmount; + + +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/report/IndexTradeReportService.java b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/report/IndexTradeReportService.java new file mode 100644 index 000000000..759373dca --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/org/dromara/daxpay/service/service/report/IndexTradeReportService.java @@ -0,0 +1,102 @@ +package org.dromara.daxpay.service.service.report; + +import cn.bootx.platform.common.mybatisplus.util.MpUtil; +import cn.hutool.core.date.LocalDateTimeUtil; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.dromara.daxpay.core.enums.PayStatusEnum; +import org.dromara.daxpay.core.enums.RefundStatusEnum; +import org.dromara.daxpay.service.dao.report.IndexTradeReportMapper; +import org.dromara.daxpay.service.entity.order.pay.PayOrder; +import org.dromara.daxpay.service.entity.order.refund.RefundOrder; +import org.dromara.daxpay.service.param.report.TradeReportQuery; +import org.dromara.daxpay.service.result.report.TradeReportResult; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 交易类报表 + * @author xxm + * @since 2024/11/16 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class IndexTradeReportService { + private final IndexTradeReportMapper tradeReportMapper; + + /** + * 支付交易统计: 笔数, 金额 + */ + public TradeReportResult pryTradeReport(TradeReportQuery query){ + QueryWrapper param = new QueryWrapper<>(); + // 获取开始时间和结束时间 + var startTime = LocalDateTimeUtil.beginOfDay(query.getStartDate()); + var endTime = LocalDateTimeUtil.endOfDay(query.getEndDate()); + + param.between(MpUtil.getColumnName(PayOrder::getPayTime), startTime, endTime) + .eq(MpUtil.getColumnName(PayOrder::getStatus), PayStatusEnum.SUCCESS); + return tradeReportMapper.payTradeReport(param); + } + + /** + * 退款交易统计: 笔数, 金额 + */ + public TradeReportResult refundTradeReport(TradeReportQuery query){ + QueryWrapper param = new QueryWrapper<>(); + // 获取开始时间和结束时间 + var startTime = LocalDateTimeUtil.beginOfDay(query.getStartDate()); + var endTime = LocalDateTimeUtil.endOfDay(query.getEndDate()); + + param.between(MpUtil.getColumnName(RefundOrder::getFinishTime),startTime, endTime) + .eq(MpUtil.getColumnName(RefundOrder::getStatus), RefundStatusEnum.SUCCESS); + return tradeReportMapper.refundTradeReport(param); + } + + /** + * 支付通道统计 + */ + public List payChannelReport(TradeReportQuery query){ + QueryWrapper param = new QueryWrapper<>(); + // 获取开始时间和结束时间 + var startTime = LocalDateTimeUtil.beginOfDay(query.getStartDate()); + var endTime = LocalDateTimeUtil.endOfDay(query.getEndDate()); + + param.between(MpUtil.getColumnName(PayOrder::getPayTime),startTime, endTime) + .eq(MpUtil.getColumnName(PayOrder::getStatus), PayStatusEnum.SUCCESS) + .groupBy(MpUtil.getColumnName(PayOrder::getChannel)); + return tradeReportMapper.payChannelReport(param); + } + + /** + * 退款通道统计 + */ + public List refundChannelReport(TradeReportQuery query){ + QueryWrapper param = new QueryWrapper<>(); + // 获取开始时间和结束时间 + var startTime = LocalDateTimeUtil.beginOfDay(query.getStartDate()); + var endTime = LocalDateTimeUtil.endOfDay(query.getEndDate()); + + param.between(MpUtil.getColumnName(RefundOrder::getFinishTime),startTime, endTime) + .groupBy(MpUtil.getColumnName(RefundOrder::getChannel)) + .eq(MpUtil.getColumnName(RefundOrder::getStatus), RefundStatusEnum.SUCCESS); + return tradeReportMapper.refundChannelReport(param); + } + + /** + * 支付方式统计 + */ + public List payMethodReport(TradeReportQuery query){ + QueryWrapper param = new QueryWrapper<>(); + // 获取开始时间和结束时间 + var startTime = LocalDateTimeUtil.beginOfDay(query.getStartDate()); + var endTime = LocalDateTimeUtil.endOfDay(query.getEndDate()); + + param.between(MpUtil.getColumnName(PayOrder::getPayTime),startTime, endTime) + .eq(MpUtil.getColumnName(PayOrder::getStatus), PayStatusEnum.SUCCESS) + .groupBy(MpUtil.getColumnName(PayOrder::getMethod)); + return tradeReportMapper.payMethodReport(param); + } +}