From 20f7fde7cd833734c565c43a96f88c8b9c8fe346 Mon Sep 17 00:00:00 2001
From: gaoqr <13665037151@163.com>
Date: Fri, 22 Aug 2025 15:52:41 +0800
Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E5=8F=91=E7=A5=A8=E6=8A=AC=E5=A4=B4?=
=?UTF-8?q?=E7=AE=A1=E7=90=86=E3=80=81=E5=8F=AF=E5=BC=80=E7=A5=A8=E5=88=97?=
=?UTF-8?q?=E8=A1=A8=E9=83=A8=E5=88=86=E6=8E=A5=E5=8F=A3=E5=AE=8C=E5=96=84?=
=?UTF-8?q?=EF=BC=9B2=E3=80=81=E5=BE=AE=E4=BF=A1=E6=94=AF=E4=BB=98?=
=?UTF-8?q?=E5=8F=91=E8=B5=B7=E5=92=8C=E5=9B=9E=E8=B0=83=E6=B5=8B=E8=AF=95?=
=?UTF-8?q?=EF=BC=9B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
cf-dependencies/pom.xml | 3 +-
.../pay/config/ChenfengWechatPayConfig.java | 58 +++++++++++-
.../system/enums/ErrorCodeConstants.java | 1 +
.../funds/invoice/InvoiceController.java | 14 ++-
.../InvoiceAmountAndAvailablePageReqVO.java | 29 ++++++
.../InvoiceAmountAndAvailablePageRespVO.java | 20 ++++
.../funds/invoice/vo/InvoiceAmountRespVO.java | 23 +++++
.../invoice/vo/InvoiceDetailsPageReqVO.java | 61 +++++++++++++
.../invoice/vo/InvoiceDetailsRespVO.java | 28 ++++++
.../invoice/vo/InvoicePurchaseRecord.java | 38 ++++++++
.../funds/invoice/vo/InvoiceTitleInfo.java | 55 +++++++++++
.../funds/invoice/vo/InvoiceTitleReqVO.java | 15 +++
.../controller/admin/pay/PayController.java | 8 +-
.../funds/purchase/PurchaseRecordMapper.java | 30 ++++++
.../enums/pay/InvoiceIssueTypeEnum.java | 25 +++++
.../system/enums/pay/InvoiceTypeEnum.java | 28 ++++++
.../module/system/enums/pay/PayConstants.java | 2 +-
.../service/funds/invoice/InvoiceService.java | 26 ++++++
.../funds/invoice/InvoiceServiceImpl.java | 80 +++++++++++++++-
.../system/service/pay/PayOrderService.java | 2 +-
.../service/pay/PayOrderServiceImpl.java | 10 +-
.../pay/factory/impl/AbstractPayHandler.java | 2 +-
.../impl/alipay/AlipayPcPayHandler.java | 2 +-
.../impl/wechat/WechatNativePayHandler.java | 91 ++++++++++++++-----
.../invoice/InvoiceIssueTypeValid.java | 32 +++++++
.../invoice/InvoiceIssueTypeValidtor.java | 27 ++++++
.../validation/invoice/InvoiceTypeValid.java | 32 +++++++
.../invoice/InvoiceTypeValidtor.java | 27 ++++++
.../src/main/resources/application-dev.yaml | 11 +++
.../src/main/resources/application-local.yaml | 17 ++--
.../mapper/funds/purchase/PurchaseMapper.xml | 10 ++
31 files changed, 748 insertions(+), 59 deletions(-)
create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceAmountAndAvailablePageReqVO.java
create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceAmountAndAvailablePageRespVO.java
create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceAmountRespVO.java
create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceDetailsPageReqVO.java
create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceDetailsRespVO.java
create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoicePurchaseRecord.java
create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceTitleInfo.java
create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/enums/pay/InvoiceIssueTypeEnum.java
create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/enums/pay/InvoiceTypeEnum.java
create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/invoice/InvoiceIssueTypeValid.java
create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/invoice/InvoiceIssueTypeValidtor.java
create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/invoice/InvoiceTypeValid.java
create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/invoice/InvoiceTypeValidtor.java
diff --git a/cf-dependencies/pom.xml b/cf-dependencies/pom.xml
index 3a92dec32..bcbc9bb72 100644
--- a/cf-dependencies/pom.xml
+++ b/cf-dependencies/pom.xml
@@ -78,6 +78,7 @@
1.9.4
2.12.2
4.7.5.B
+ 4.7.6.B
2.5.1
@@ -608,7 +609,7 @@
com.github.binarywang
weixin-java-pay
- ${weixin-java.version}
+ ${weixin-pay-java.version}
com.github.binarywang
diff --git a/cf-framework/cf-spring-boot-starter-biz-pay/src/main/java/com/cf/imes/framework/pay/config/ChenfengWechatPayConfig.java b/cf-framework/cf-spring-boot-starter-biz-pay/src/main/java/com/cf/imes/framework/pay/config/ChenfengWechatPayConfig.java
index 01df2fbab..90cd7062f 100644
--- a/cf-framework/cf-spring-boot-starter-biz-pay/src/main/java/com/cf/imes/framework/pay/config/ChenfengWechatPayConfig.java
+++ b/cf-framework/cf-spring-boot-starter-biz-pay/src/main/java/com/cf/imes/framework/pay/config/ChenfengWechatPayConfig.java
@@ -19,6 +19,11 @@ public class ChenfengWechatPayConfig extends WxPayConfig {
@Value("${chenfeng.encrypt.publicKey:}")
private String publicKey;
+ /**
+ * 给微信支付的回调地址
+ */
+ private String notifyUrl;
+
@Override
public void setAppId(String appId) {
if (StringUtils.isNotEmpty(publicKey)) {
@@ -47,13 +52,56 @@ public class ChenfengWechatPayConfig extends WxPayConfig {
}
@Override
- public void setKeyContent(byte[] keyContent) {
+ public void setApiV3Key(String apiV3Key) {
if (StringUtils.isNotEmpty(publicKey)) {
- String encrypted = new String(keyContent, StandardCharsets.UTF_8);
- String decrypted = AesUtils.decrypt(encrypted, publicKey);
- super.setKeyContent(decrypted.getBytes(StandardCharsets.UTF_8));
+ super.setApiV3Key(AesUtils.decrypt(apiV3Key, publicKey));
} else {
- super.setKeyContent(keyContent);
+ super.setApiV3Key(apiV3Key);
+ }
+ }
+
+ @Override
+ public void setCertSerialNo(String certSerialNo) {
+ if (StringUtils.isNotEmpty(publicKey)) {
+ super.setCertSerialNo(AesUtils.decrypt(certSerialNo, publicKey));
+ } else {
+ super.setCertSerialNo(certSerialNo);
+ }
+ }
+
+ @Override
+ public void setPublicKeyId(String publicKeyId) {
+ if (StringUtils.isNotEmpty(publicKey)) {
+ super.setPublicKeyId(AesUtils.decrypt(publicKeyId, publicKey));
+ } else {
+ super.setPublicKeyId(publicKeyId);
+ }
+ }
+
+ @Override
+ public void setNotifyUrl(String notifyUrl) {
+ if (StringUtils.isNotEmpty(publicKey)) {
+ super.setNotifyUrl(AesUtils.decrypt(notifyUrl, publicKey));
+ } else {
+ super.setNotifyUrl(notifyUrl);
+ }
+ }
+
+ @Override
+ public void setPublicKeyString(String publicKeyString) {
+ if (StringUtils.isNotEmpty(publicKey)) {
+ super.setPublicKeyContent(AesUtils.decrypt(publicKeyString, publicKey).getBytes(StandardCharsets.UTF_8));
+ } else {
+ super.setPublicKeyContent(publicKeyString.getBytes(StandardCharsets.UTF_8));
+ }
+ }
+
+ @Override
+ public void setPrivateKeyString(String privateKeyString) {
+ if (StringUtils.isNotEmpty(publicKey)) {
+ super.setPrivateKeyContent(AesUtils.decrypt(privateKeyString, publicKey).getBytes(StandardCharsets.UTF_8));
+ } else {
+ super.setPrivateKeyContent(privateKeyString.getBytes(StandardCharsets.UTF_8));
}
}
}
diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java
index 78efd8ff1..99b72d520 100644
--- a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java
+++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java
@@ -437,6 +437,7 @@ public class ErrorCodeConstants {
public static final ErrorCode ORGAN_PRODUCT_PAY_AMOUNT_CHANGE_ERROR = new ErrorCode(1_002_043_025, "发起产品支付失败,组织资金已发生改变,请刷新或稍后再发起支付");
public static final ErrorCode PAY_RECHARGE_ACTIVITY_CHANNEL_MISMATCH_ERROR = new ErrorCode(1_002_043_026, "充值活动类型和支付渠道不匹配,请选择其他充值活动!");
public static final ErrorCode PAY_RECHARGE_ACTIVITY_EXPIRE_ERROR = new ErrorCode(1_002_043_027, "充值活动已结束,请选择其他充值活动!");
+ public static final ErrorCode INVOICE_TITLE_NOT_EXISTS_ERROR = new ErrorCode(1_002_043_028, "发票抬头不存在,请先创建发票抬头");
//=========== 支付相关 1-002-048-000 ============
public static final ErrorCode PAY_CHANNEL_NOT_SUPPORT = new ErrorCode(1_002_048_000, "暂不支持的支付渠道,请使用其他支付渠道");
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/InvoiceController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/InvoiceController.java
index 12ab5129c..f8bdbaecd 100644
--- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/InvoiceController.java
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/InvoiceController.java
@@ -2,11 +2,14 @@ package com.cf.imes.module.system.controller.admin.funds.invoice;
import com.cf.imes.framework.common.pojo.CommonResult;
+import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountAndAvailablePageReqVO;
+import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountAndAvailablePageRespVO;
import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceTitleReqVO;
import com.cf.imes.module.system.service.funds.invoice.InvoiceService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -32,15 +35,16 @@ public class InvoiceController {
private InvoiceService invoiceService;
- @PostMapping("")
+ @PostMapping("/title")
@Operation(summary = "新增/修改发票抬头信息")
public CommonResult insetInvoiceTitle(@Valid @RequestBody InvoiceTitleReqVO reqVO) {
-
invoiceService.insetInvoiceTitle(reqVO);
-
return success(Boolean.TRUE);
-
}
-
+ @GetMapping("/available/info")
+ @Operation(summary = "获取组织的开票金额信息")
+ public CommonResult getInvoiceAmountAndAvailablePage(@Valid InvoiceAmountAndAvailablePageReqVO pageReqVO) {
+ return success(invoiceService.getInvoiceAmount(pageReqVO));
+ }
}
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceAmountAndAvailablePageReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceAmountAndAvailablePageReqVO.java
new file mode 100644
index 000000000..4f6e3efb4
--- /dev/null
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceAmountAndAvailablePageReqVO.java
@@ -0,0 +1,29 @@
+package com.cf.imes.module.system.controller.admin.funds.invoice.vo;
+
+import com.cf.imes.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.time.LocalDateTime;
+
+import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+/**
+ * @author Gqr
+ * @since 2025/8/21 16:11
+ */
+@Data
+@Schema(description = "管理后台 - 组织开票金额和可开票列表 Req VO")
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class InvoiceAmountAndAvailablePageReqVO extends PageParam {
+ @Schema(description = "费用账期", example = "[2022-07-01 01:01:01 ,2022-07-01 01:01:01]")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] createTime;
+
+ @Schema(description = "开票金额", example = "[0,100]")
+ private Integer[] invoiceAmount;
+}
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceAmountAndAvailablePageRespVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceAmountAndAvailablePageRespVO.java
new file mode 100644
index 000000000..acf0a710a
--- /dev/null
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceAmountAndAvailablePageRespVO.java
@@ -0,0 +1,20 @@
+package com.cf.imes.module.system.controller.admin.funds.invoice.vo;
+
+import com.cf.imes.framework.common.pojo.PageResult;
+import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * @author Gqr
+ * @since 2025/8/21 16:11
+ */
+@Data
+@Schema(description = "管理后台 - 组织开票金额和可开票列表 Response VO")
+public class InvoiceAmountAndAvailablePageRespVO {
+ @Schema(description = "发票金额信息")
+ private InvoiceAmountRespVO invoiceAmountRespVO;
+
+ @Schema(description = "可开票记录")
+ private PageResult availableInvoicePurchaseRecords;
+}
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceAmountRespVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceAmountRespVO.java
new file mode 100644
index 000000000..856689072
--- /dev/null
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceAmountRespVO.java
@@ -0,0 +1,23 @@
+package com.cf.imes.module.system.controller.admin.funds.invoice.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class InvoiceAmountRespVO {
+
+
+ @Schema(description = "可开票")
+ private BigDecimal invocable;
+
+
+ @Schema(description = "开票中")
+ private BigDecimal inTheInvoice;
+
+
+ @Schema(description = "已开票")
+ private BigDecimal invoiced;
+
+}
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceDetailsPageReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceDetailsPageReqVO.java
new file mode 100644
index 000000000..3f368e5c9
--- /dev/null
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceDetailsPageReqVO.java
@@ -0,0 +1,61 @@
+package com.cf.imes.module.system.controller.admin.funds.invoice.vo;
+
+
+import com.cf.imes.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Builder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
+
+@Schema(description = "管理后台 - 组织可开票的数据明细 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Builder
+public class InvoiceDetailsPageReqVO extends PageParam {
+
+
+ @Schema(description = "组织ID")
+ private Long organId;
+
+
+ @Schema(description = "发票号")
+ private String invoiceNo;
+
+
+ @Schema(description = "发票状态,1待开票 2已开票 3开票失败")
+ private Integer status;
+
+
+ @Schema(description = "申请人")
+ private String creator;
+
+
+ @Schema(description = "开票人")
+ private String invoicePerson;
+
+
+ @Schema(description = "发票金额")
+ private BigDecimal[] invoiceAmount;
+
+
+ @Schema(description = "开票时间", example = "[2022-07-01 01:01:01 ,2022-07-01 01:01:01]")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] invoiceTime;
+
+
+ @Schema(description = "交易时间", example = "[2022-07-01 01:01:01 ,2022-07-01 01:01:01]")
+ @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
+ private LocalDateTime[] createTime;
+
+
+ @Schema(description = "交易金额")
+ private BigDecimal[] amount;
+
+
+}
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceDetailsRespVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceDetailsRespVO.java
new file mode 100644
index 000000000..9a34be0e1
--- /dev/null
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceDetailsRespVO.java
@@ -0,0 +1,28 @@
+package com.cf.imes.module.system.controller.admin.funds.invoice.vo;
+
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class InvoiceDetailsRespVO {
+
+
+ @Schema(description = "发票对应的购买记录")
+ private List invoicePurchaseRecords;
+
+
+ @Schema(description = "发票抬头信息")
+ private InvoiceTitleInfo invoiceTitleInfo;
+
+
+}
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoicePurchaseRecord.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoicePurchaseRecord.java
new file mode 100644
index 000000000..1ac449833
--- /dev/null
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoicePurchaseRecord.java
@@ -0,0 +1,38 @@
+package com.cf.imes.module.system.controller.admin.funds.invoice.vo;
+
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+
+@Data
+public class InvoicePurchaseRecord {
+
+
+ @Schema(description = "流水号")
+ private Long businessNo;
+
+
+ @Schema(description = "购买记录ID")
+ private Long purchaseRecordId;
+
+
+ @Schema(description = "产品名称")
+ private String productName;
+
+
+ @Schema(description = "交易类型")
+ private Integer tradeType;
+
+
+ @Schema(description = "可开票金额")
+ private BigDecimal rechargeAmount;
+
+
+ @Schema(description = "交易时间")
+ private LocalDateTime createTime;
+
+}
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceTitleInfo.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceTitleInfo.java
new file mode 100644
index 000000000..f3f9bf3fa
--- /dev/null
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceTitleInfo.java
@@ -0,0 +1,55 @@
+package com.cf.imes.module.system.controller.admin.funds.invoice.vo;
+
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+@Data
+public class InvoiceTitleInfo {
+
+
+ @Schema(description = "发票抬头ID")
+ private Long id;
+
+
+ @Schema(description = "组织ID")
+ private Long organId;
+
+
+ @Schema(description = "发票抬头")
+ private String invoiceTitle;
+
+
+ @Schema(description = "开具类型,0企业 1个人")
+ private Integer issueType;
+
+
+ @Schema(description = "发票类型,0增值税普通发票 1增值税专用发票")
+ private Integer invoiceType;
+
+
+ @Schema(description = "纳税人识别号")
+ private String taxpayerId;
+
+
+ @Schema(description = "开户银行名称")
+ private String bankName;
+
+
+ @Schema(description = "开户银行账号")
+ private String bankAccount;
+
+
+ @Schema(description = "注册场所地址")
+ private String registeredAddress;
+
+
+ @Schema(description = "注册固定电话")
+ private String fixedPhone;
+
+
+ @Schema(description = "邮箱")
+ private String email;
+
+
+}
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceTitleReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceTitleReqVO.java
index ec5424ea4..75dd93718 100644
--- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceTitleReqVO.java
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/invoice/vo/InvoiceTitleReqVO.java
@@ -1,7 +1,11 @@
package com.cf.imes.module.system.controller.admin.funds.invoice.vo;
+import com.cf.imes.module.system.validation.invoice.InvoiceIssueTypeValid;
+import com.cf.imes.module.system.validation.invoice.InvoiceTypeValid;
import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.Size;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
@@ -16,47 +20,58 @@ public class InvoiceTitleReqVO {
@Schema(description = "组织ID")
+ @NotNull(message = "组织ID不能为空")
private Long organId;
@Schema(description = "发票抬头")
@NotBlank(message = "发票抬头不能为空")
+ @Size(max = 64, message = "发票抬头长度不能超过64个字符")
private String invoiceTitle;
@Schema(description = "开具类型,0企业 1个人")
@NotNull(message = "开具类型不能为空")
+ @InvoiceIssueTypeValid
private Integer issueType;
@Schema(description = "发票类型,0增值税普通发票 1增值税专用发票")
@NotNull(message = "发票类型不能为空")
+ @InvoiceTypeValid
private Integer invoiceType;
@Schema(description = "纳税人识别号")
@NotNull(message = "纳税人识别号不能为空")
+ @Size(max = 20, message = "纳税人识别号长度不能超过20个字符")
private String taxpayerId;
@Schema(description = "开户银行名称")
+ @Size(max = 64, message = "开户银行名称长度不能超过64个字符")
private String bankName;
@Schema(description = "开户银行账号")
+ @Size(max = 40, message = "开户银行账号长度不能超过40个字符")
private String bankAccount;
@Schema(description = "注册场所地址")
+ @Size(max = 64, message = "注册场所地址长度不能超过64个字符")
private String registeredAddress;
@Schema(description = "注册固定电话")
+ @Size(max = 20, message = "注册固定电话长度不能超过20个字符")
private String fixedPhone;
@Schema(description = "邮箱")
@NotNull(message = "邮箱不能为空")
+ @Size(max = 64, message = "邮箱长度不能超过64个字符")
+ @Email(message = "邮箱格式不正确")
private String email;
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/pay/PayController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/pay/PayController.java
index a6eeba716..0d88990fb 100644
--- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/pay/PayController.java
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/pay/PayController.java
@@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@@ -67,9 +68,10 @@ public class PayController {
@PermitAll
public String notifyOrder(@PathVariable("channelCode") Integer channelCode,
@RequestParam(required = false) Map params,
- @RequestBody(required = false) String body) {
- log.info("[notifyOrder][channelCode({}) 回调数据({}/{})]", channelCode, params, body);
- payOrderService.doOrderNotify(channelCode, params, body);
+ @RequestBody(required = false) String body,
+ @RequestHeader Map headers) {
+ log.info("[notifyOrder][channelCode({}) 回调数据({}/{}/{})]", channelCode, params, body, headers);
+ payOrderService.doOrderNotify(channelCode, params, body, headers);
// 支付接口回调相应必须是"success"
return "success";
}
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/funds/purchase/PurchaseRecordMapper.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/funds/purchase/PurchaseRecordMapper.java
index cfb5e770f..7cd1488b9 100644
--- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/funds/purchase/PurchaseRecordMapper.java
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/funds/purchase/PurchaseRecordMapper.java
@@ -1,10 +1,15 @@
package com.cf.imes.module.system.dal.mysql.funds.purchase;
+import cn.hutool.core.util.ObjectUtil;
import com.cf.imes.framework.common.pojo.PageResult;
import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX;
import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX;
+import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
+import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountAndAvailablePageReqVO;
+import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountRespVO;
import com.cf.imes.module.system.controller.admin.funds.purchase.vo.PurchaseRecordPageReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO;
+import com.cf.imes.module.system.enums.pay.InvoiceStatusEnum;
import org.apache.ibatis.annotations.Mapper;
import java.math.BigDecimal;
@@ -38,4 +43,29 @@ public interface PurchaseRecordMapper extends BaseMapperX {
.likeIfPresent(PurchaseRecordDO::getCreator, pageReqVO.getCreator()));
}
+
+ /**
+ * 分页查询可开票记录
+ *
+ * @param pageReqVO
+ * @return
+ */
+ default PageResult selectPage(InvoiceAmountAndAvailablePageReqVO pageReqVO) {
+ return selectPage(pageReqVO, new LambdaQueryWrapperX()
+ .betweenIfPresent(PurchaseRecordDO::getCreateTime, pageReqVO.getCreateTime())
+ .geIfPresent(PurchaseRecordDO::getTotalAmount, ObjectUtil.isNotNull(pageReqVO.getInvoiceAmount()) ? pageReqVO.getInvoiceAmount()[0] : null)
+ .leIfPresent(PurchaseRecordDO::getTotalAmount, ObjectUtil.isNotNull(pageReqVO.getInvoiceAmount()) ? pageReqVO.getInvoiceAmount()[1] : null)
+ .eq(PurchaseRecordDO::getOrganId, SecurityFrameworkUtils.getUserOrganId())
+ .eq(PurchaseRecordDO::getDeleted, false)
+ .in(PurchaseRecordDO::getIsInvocing, InvoiceStatusEnum.INVOICABLE.getStatus(), InvoiceStatusEnum.INVOICINGFAILED.getStatus())
+ );
+
+ }
+
+ /**
+ * 查询机构下开票金额统计:可开票、开票中、已开票
+ * @param organId
+ * @return
+ */
+ InvoiceAmountRespVO getOrgInvoiceAmountStatistics(Long organId);
}
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/enums/pay/InvoiceIssueTypeEnum.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/enums/pay/InvoiceIssueTypeEnum.java
new file mode 100644
index 000000000..ac1aaf036
--- /dev/null
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/enums/pay/InvoiceIssueTypeEnum.java
@@ -0,0 +1,25 @@
+package com.cf.imes.module.system.enums.pay;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 发票开具类型枚举
+ * @author Gqr
+ * @since 2025/8/21 12:00
+ */
+@Getter
+@AllArgsConstructor
+public enum InvoiceIssueTypeEnum {
+ /**
+ * 企业
+ */
+ ENTERPRISE(0),
+
+ /**
+ * 个人
+ */
+ PERSONAL(1);
+
+ private final Integer value;
+}
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/enums/pay/InvoiceTypeEnum.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/enums/pay/InvoiceTypeEnum.java
new file mode 100644
index 000000000..976a28886
--- /dev/null
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/enums/pay/InvoiceTypeEnum.java
@@ -0,0 +1,28 @@
+package com.cf.imes.module.system.enums.pay;
+
+/**
+ * 发票类型枚举
+ * @author Gqr
+ * @since 2025/8/21 12:03
+ */
+public enum InvoiceTypeEnum {
+ /**
+ * 增值税普通发票
+ */
+ VAT_GENERAL(0),
+
+ /**
+ * 增值税专用发票
+ */
+ VAT_SPECIAL(1);
+
+ private final Integer value;
+
+ InvoiceTypeEnum(Integer value) {
+ this.value = value;
+ }
+
+ public Integer getValue() {
+ return value;
+ }
+}
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/enums/pay/PayConstants.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/enums/pay/PayConstants.java
index 7aadead3b..00659f363 100644
--- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/enums/pay/PayConstants.java
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/enums/pay/PayConstants.java
@@ -11,7 +11,7 @@ public class PayConstants {
public static final String PAY_PASSBACK_PARAMS_KEY = "passback_params";// 回调参数passback key
- public static final String PAY_ORDER_PREFIX_FORMAT = "P%dO%s%s";
+ public static final String PAY_ORDER_PREFIX_FORMAT = "P%dO%s";
public static final String PAY_PASSBACK_PARAMS_PURCHASE_RECORD_ID_KEY = "purchaseRecordId"; //支付passback 购买记录key
}
\ No newline at end of file
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/invoice/InvoiceService.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/invoice/InvoiceService.java
index 839b5a0b1..e6ceb8067 100644
--- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/invoice/InvoiceService.java
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/invoice/InvoiceService.java
@@ -1,6 +1,11 @@
package com.cf.imes.module.system.service.funds.invoice;
+import com.cf.imes.framework.common.pojo.PageResult;
+import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountAndAvailablePageReqVO;
+import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountAndAvailablePageRespVO;
+import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceDetailsPageReqVO;
+import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceDetailsRespVO;
import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceTitleReqVO;
/**
@@ -8,5 +13,26 @@ import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceTitleR
*/
public interface InvoiceService {
+ /**
+ * 新增/修改抬头信息
+ *
+ * @param reqVO
+ */
void insetInvoiceTitle(InvoiceTitleReqVO reqVO);
+
+ /**
+ * 查询组织开票金额和可开票列表
+ *
+ * @param invoiceAmountAndAvailablePageReqVO
+ * @return
+ */
+ InvoiceAmountAndAvailablePageRespVO getInvoiceAmount(InvoiceAmountAndAvailablePageReqVO invoiceAmountAndAvailablePageReqVO);
+
+ /**
+ * 查询开票分页
+ *
+ * @param pageReqVO
+ * @return
+ */
+ PageResult getInvoiceDetails(InvoiceDetailsPageReqVO pageReqVO);
}
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/invoice/InvoiceServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/invoice/InvoiceServiceImpl.java
index 89fbddc2a..b954af8b8 100644
--- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/invoice/InvoiceServiceImpl.java
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/invoice/InvoiceServiceImpl.java
@@ -1,40 +1,55 @@
package com.cf.imes.module.system.service.funds.invoice;
+import com.cf.imes.framework.common.pojo.PageResult;
+import com.cf.imes.framework.common.util.Assert.AssertUtils;
import com.cf.imes.framework.common.util.object.BeanUtils;
+import com.cf.imes.framework.security.core.util.SecurityFrameworkUtils;
+import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountAndAvailablePageReqVO;
+import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceAmountAndAvailablePageRespVO;
+import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceDetailsPageReqVO;
+import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceDetailsRespVO;
import com.cf.imes.module.system.controller.admin.funds.invoice.vo.InvoiceTitleReqVO;
import com.cf.imes.module.system.dal.dataobject.funds.invoice.InvoiceTitleInfoDO;
import com.cf.imes.module.system.dal.mysql.funds.invoice.InvoiceTitleInfoMapper;
+import com.cf.imes.module.system.dal.mysql.funds.purchase.PurchaseRecordMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
+import static com.cf.imes.module.system.enums.ErrorCodeConstants.INVOICE_TITLE_NOT_EXISTS_ERROR;
+
/**
* @author 发票管理接口 实现类
*/
@Slf4j
@Service
-public class InvoiceServiceImpl implements InvoiceService{
+public class InvoiceServiceImpl implements InvoiceService {
@Resource
private InvoiceTitleInfoMapper invoiceTitleInfoMapper;
+ @Resource
+ private PurchaseRecordMapper purchaseRecordMapper;
+
@Override
public void insetInvoiceTitle(InvoiceTitleReqVO reqVO) {
-
- if(reqVO.getId() != null){
+ if (reqVO.getId() != null) {
+ validTitleOrg(reqVO.getId(), reqVO.getOrganId());
+ // 更新抬头
InvoiceTitleInfoDO titleInfoDO = BeanUtils.toBean(reqVO, InvoiceTitleInfoDO.class);
invoiceTitleInfoMapper.updateById(titleInfoDO);
return;
}
-
+ // 新增抬头
invoiceTitleInfoMapper.insert(InvoiceTitleInfoDO.builder()
+ .organId(reqVO.getOrganId())
.invoiceTitle(reqVO.getInvoiceTitle())
.invoiceType(reqVO.getInvoiceType())
.issueType(reqVO.getIssueType())
@@ -45,6 +60,63 @@ public class InvoiceServiceImpl implements InvoiceService{
.fixedPhone(reqVO.getFixedPhone())
.email(reqVO.getEmail())
.build());
+ }
+
+ /**
+ * 校验抬头组织
+ *
+ * @param id
+ * @param organId
+ */
+ private void validTitleOrg(Long id, Long organId) {
+ InvoiceTitleInfoDO titleInfoDO = invoiceTitleInfoMapper.selectById(id);
+ // 抬头不存在
+ AssertUtils.notEmpty(titleInfoDO, INVOICE_TITLE_NOT_EXISTS_ERROR);
+ // 抬头组织不匹配
+ AssertUtils.notEquals(titleInfoDO.getOrganId(), organId, INVOICE_TITLE_NOT_EXISTS_ERROR);
+ }
+
+ @Override
+ public InvoiceAmountAndAvailablePageRespVO getInvoiceAmount(InvoiceAmountAndAvailablePageReqVO invoiceAmountAndAvailablePageReqVO) {
+ InvoiceAmountAndAvailablePageRespVO invoiceAmountAndAvailablePageRespVO = new InvoiceAmountAndAvailablePageRespVO();
+ // 开票金额
+ invoiceAmountAndAvailablePageRespVO.setInvoiceAmountRespVO(purchaseRecordMapper.getOrgInvoiceAmountStatistics(SecurityFrameworkUtils.getUserOrganId()));
+
+ // 可开票记录查询
+ invoiceAmountAndAvailablePageRespVO.setAvailableInvoicePurchaseRecords(purchaseRecordMapper.selectPage(invoiceAmountAndAvailablePageReqVO));
+
+ return invoiceAmountAndAvailablePageRespVO;
+ }
+
+ @Override
+ public PageResult getInvoiceDetails(InvoiceDetailsPageReqVO pageReqVO) {
+//
+// PageDTO page = new PageDTO<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
+//
+// List invoiceStatus = new ArrayList<>();
+// invoiceStatus.add(InvoiceStatusEnum.INVOICABLE.getStatus());
+// invoiceStatus.add(InvoiceStatusEnum.INVOICINGFAILED.getStatus());
+//
+// QueryWrapperX queryWrapperX = new QueryWrapperX<>();
+//
+// pageReqVO.setCreateTime(LocalDateTimeUtils.generateTimeSection(pageReqVO.getCreateTime()));
+// queryWrapperX
+// .eq("ied.organId",getUserOrganId())
+// .eq("ied.deleted",false)
+// .eq("ied.trade_type", TradeTypeEnum.PRODUCT.getCode())
+// .in("pr.is_invocing", invoiceStatus)
+// .betweenIfPresent("ied.create_time",pageReqVO.getCreateTime())
+// .betweenIfPresent("ied.cash_amount_change",pageReqVO.getAmount());
+//
+// IPage respVOIPage = incomeExpenseDetailsMapper.selectOrganInvoicable(page, queryWrapperX);
+//
+// List records = respVOIPage.getRecords();
+// if (CollUtil.isEmpty(records)) {
+// return new PageResult<>();
+// }
+//
+// return new PageResult<>(records, respVOIPage.getTotal());
+ return null;
}
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/PayOrderService.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/PayOrderService.java
index 166e821ac..68840fefa 100644
--- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/PayOrderService.java
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/PayOrderService.java
@@ -43,7 +43,7 @@ public interface PayOrderService {
* @param body
* @return
*/
- void doOrderNotify(Integer channelCode, Map params, String body);
+ void doOrderNotify(Integer channelCode, Map params, String body, Map headers);
/**
* 处理过期订单
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/PayOrderServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/PayOrderServiceImpl.java
index a1144c497..a1c40b82e 100644
--- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/PayOrderServiceImpl.java
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/PayOrderServiceImpl.java
@@ -1,7 +1,5 @@
package com.cf.imes.module.system.service.pay;
-import cn.hutool.core.date.DatePattern;
-import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
@@ -320,7 +318,7 @@ public class PayOrderServiceImpl implements PayOrderService {
Long organId = SecurityFrameworkUtils.getUserOrganId();
payOrderDO.setId(payOrderId);
- payOrderDO.setPayNo(String.format(PayConstants.PAY_ORDER_PREFIX_FORMAT, organId, payOrderId, DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_PATTERN)));
+ payOrderDO.setPayNo(String.format(PayConstants.PAY_ORDER_PREFIX_FORMAT, organId, payOrderId));
payOrderDO.setStatus(PayOrderStatusEnum.WAITING);
payOrderDO.setExpireTime(LocalDateTime.now().plus(payConfig.getPayExpireTime()));
payOrderDO.setPrice(price);
@@ -385,18 +383,18 @@ public class PayOrderServiceImpl implements PayOrderService {
@Override
@Transactional(rollbackFor = Exception.class)
- public void doOrderNotify(Integer channelCode, Map params, String body) {
+ public void doOrderNotify(Integer channelCode, Map params, String body, Map headers) {
// 获取渠道方处理器
AbstractPayHandler payHandler = payHandlerFactory.getPayHandler(channelCode);
try {
// 解析回调数据
- PayOrderRespDTO payOrderRespDTO = payHandler.doParseOrderNotify(params, body);
+ PayOrderRespDTO payOrderRespDTO = payHandler.doParseOrderNotify(params, body, headers);
// 处理支付回调数据
this.notifyOrder(payOrderRespDTO);
} catch (Throwable e) {
- log.error("[parseOrderNotify][客户端({}) params({}) body({}) headers({}) 解析失败]", channelCode, params, body, e);
+ log.error("[parseOrderNotify][客户端({}) params({}) body({}) headers({}) 解析失败]", channelCode, params, body, headers, e);
throw new PayException(PAY_ORDER_NOTIFY_DATA_PARSE_ERROR);
}
}
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/factory/impl/AbstractPayHandler.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/factory/impl/AbstractPayHandler.java
index 6eb3c0d53..499ad77a9 100644
--- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/factory/impl/AbstractPayHandler.java
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/factory/impl/AbstractPayHandler.java
@@ -36,5 +36,5 @@ public abstract class AbstractPayHandler {
* @param body
* @return
*/
- public abstract PayOrderRespDTO doParseOrderNotify(Map params, String body) throws Throwable;
+ public abstract PayOrderRespDTO doParseOrderNotify(Map params, String body, Map headers) throws Throwable;
}
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/factory/impl/alipay/AlipayPcPayHandler.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/factory/impl/alipay/AlipayPcPayHandler.java
index 04b8f4eaa..6de1fa781 100644
--- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/factory/impl/alipay/AlipayPcPayHandler.java
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/factory/impl/alipay/AlipayPcPayHandler.java
@@ -108,7 +108,7 @@ public class AlipayPcPayHandler extends AbstractPayHandler {
}
@Override
- public PayOrderRespDTO doParseOrderNotify(Map params, String body) throws Throwable {
+ public PayOrderRespDTO doParseOrderNotify(Map params, String body, Map headers) throws Throwable {
// 1. 校验回调数据
verifyNotifyData(params);
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/factory/impl/wechat/WechatNativePayHandler.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/factory/impl/wechat/WechatNativePayHandler.java
index f0ea7f8ba..037913d74 100644
--- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/factory/impl/wechat/WechatNativePayHandler.java
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/factory/impl/wechat/WechatNativePayHandler.java
@@ -2,6 +2,7 @@ package com.cf.imes.module.system.service.pay.factory.impl.wechat;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.date.TemporalAccessorUtil;
+import cn.hutool.core.text.CharSequenceUtil;
import com.alibaba.fastjson.JSON;
import com.cf.imes.framework.common.util.json.JsonUtils;
import com.cf.imes.framework.pay.config.ChenfengWechatPayConfig;
@@ -10,9 +11,10 @@ import com.cf.imes.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
import com.cf.imes.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
import com.cf.imes.module.system.enums.pay.PayOrderStatusEnum;
import com.cf.imes.module.system.service.pay.factory.impl.AbstractPayHandler;
-import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
-import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult;
-import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
+import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
+import com.github.binarywang.wxpay.bean.notify.WxPayNotifyV3Result;
+import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
+import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
@@ -23,9 +25,9 @@ import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Map;
-import java.util.Objects;
-import static cn.hutool.core.date.DatePattern.PURE_DATETIME_PATTERN;
+import static cn.hutool.core.date.DatePattern.UTC_WITH_XXX_OFFSET_PATTERN;
+import static com.cf.imes.framework.common.util.servlet.ServletUtils.getClientIP;
/**
* 微信native支付处理器
@@ -43,22 +45,21 @@ public class WechatNativePayHandler extends AbstractPayHandler {
@Override
public PayOrderRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
// 构建 WxPayUnifiedOrderRequest 对象
- WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder()
- .outTradeNo(reqDTO.getOutTradeNo())
- .body(reqDTO.getSubject())
- .detail(reqDTO.getBody())
- .totalFee(reqDTO.getPrice()) // 单位分
- .timeExpire(TemporalAccessorUtil.format(reqDTO.getExpireTime().atZone(ZoneId.systemDefault()), PURE_DATETIME_PATTERN))
- .spbillCreateIp(reqDTO.getUserIp())
- .notifyUrl(reqDTO.getNotifyUrl())
- .attach(JSON.toJSONString(reqDTO.getPassbackParams()))
- .build();
+ WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
+ request.setOutTradeNo(reqDTO.getOutTradeNo());
+ request.setDescription(reqDTO.getSubject());
+ request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getPrice())); // 单位分
+ request.setTimeExpire(formatDateV3(reqDTO.getExpireTime()));
+ request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(getClientIP()));
+ request.setNotifyUrl(reqDTO.getNotifyUrl());
+ request.setAttach(JSON.toJSONString(reqDTO.getPassbackParams()));
+ // 加载配置,创建client
WxPayService client = new WxPayServiceImpl();
client.setConfig(chenfengWechatPayConfig);
// 执行请求
- WxPayAppOrderResult response = client.createOrder(request);
+ String response = client.createOrderV3(TradeTypeEnum.NATIVE, request);
// 转换结果
return PayOrderRespDTO.waitingOf(PayOrderDisplayModeEnum.APP.getMode(), JsonUtils.toJsonString(response),
@@ -71,20 +72,60 @@ public class WechatNativePayHandler extends AbstractPayHandler {
}
@Override
- public PayOrderRespDTO doParseOrderNotify(Map params, String body) throws WxPayException {
+ public PayOrderRespDTO doParseOrderNotify(Map params, String body, Map headers) throws WxPayException {
// 1. 解析回调
+ SignatureHeader signatureHeader = getRequestHeader(headers);
+ // 加载配置,创建client
WxPayService client = new WxPayServiceImpl();
client.setConfig(chenfengWechatPayConfig);
- WxPayOrderNotifyResult response = client.parseOrderNotifyResult(body);
+
+ WxPayNotifyV3Result response = client.parseOrderNotifyV3Result(body, signatureHeader);
+ WxPayNotifyV3Result.DecryptNotifyResult result = response.getResult();
// 2. 构建结果
- // V2 微信支付的回调,只有 SUCCESS 支付成功、CLOSED 支付失败两种情况,无需像支付宝一样解析的比较复杂
- Integer status = Objects.equals(response.getResultCode(), "SUCCESS") ?
- PayOrderStatusEnum.SUCCESS.getStatus() : PayOrderStatusEnum.FAIL.getStatus();
- return PayOrderRespDTO.of(status, response.getTransactionId(), response.getOpenid(), parseDateV2(response.getTimeEnd()),
- response.getOutTradeNo(), body);
+ Integer status = parseStatus(result.getTradeState());
+ String openid = result.getPayer() != null ? result.getPayer().getOpenid() : null;
+ return PayOrderRespDTO.of(status, result.getTransactionId(), openid, parseDateV3(result.getSuccessTime()),
+ result.getOutTradeNo(), body);
}
- static LocalDateTime parseDateV2(String time) {
- return LocalDateTimeUtil.parse(time, PURE_DATETIME_PATTERN);
+ static String formatDateV3(LocalDateTime time) {
+ return TemporalAccessorUtil.format(time.atZone(ZoneId.systemDefault()), UTC_WITH_XXX_OFFSET_PATTERN);
}
+
+ /**
+ * 组装请求头重的签名信息
+ *
+ * @see 官方示例
+ */
+ private SignatureHeader getRequestHeader(Map headers) {
+ return SignatureHeader.builder()
+ .signature(headers.get("wechatpay-signature"))
+ .nonce(headers.get("wechatpay-nonce"))
+ .serial(headers.get("wechatpay-serial"))
+ .timeStamp(headers.get("wechatpay-timestamp"))
+ .build();
+ }
+
+ private static Integer parseStatus(String tradeState) {
+ switch (tradeState) {
+ case "NOTPAY":
+ case "USERPAYING": // 支付中,等待用户输入密码(条码支付独有)
+ return PayOrderStatusEnum.WAITING.getStatus();
+ case "SUCCESS":
+ return PayOrderStatusEnum.SUCCESS.getStatus();
+// case "REFUND":
+// return PayOrderStatusEnum.REFUND.getStatus();
+ case "CLOSED":
+ case "REVOKED": // 已撤销(刷卡支付独有)
+ case "PAYERROR": // 支付失败(其它原因,如银行返回失败)
+ return PayOrderStatusEnum.FAIL.getStatus();
+ default:
+ throw new IllegalArgumentException(CharSequenceUtil.format("未知的支付状态({})", tradeState));
+ }
+ }
+
+ static LocalDateTime parseDateV3(String time) {
+ return LocalDateTimeUtil.parse(time, UTC_WITH_XXX_OFFSET_PATTERN);
+ }
+
}
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/invoice/InvoiceIssueTypeValid.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/invoice/InvoiceIssueTypeValid.java
new file mode 100644
index 000000000..13bf962a3
--- /dev/null
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/invoice/InvoiceIssueTypeValid.java
@@ -0,0 +1,32 @@
+package com.cf.imes.module.system.validation.invoice;
+
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 发票开具类型校验注解
+ *
+ * @author Gqr
+ * @since 2025/8/21 14:36
+ */
+@Target({
+ ElementType.FIELD,
+})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Constraint(
+ validatedBy = {InvoiceIssueTypeValidtor.class}
+)
+public @interface InvoiceIssueTypeValid {
+ String message() default "不支持的发票开具类型";
+
+ Class>[] groups() default {};
+
+ Class extends Payload>[] payload() default {};
+}
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/invoice/InvoiceIssueTypeValidtor.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/invoice/InvoiceIssueTypeValidtor.java
new file mode 100644
index 000000000..545a66833
--- /dev/null
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/invoice/InvoiceIssueTypeValidtor.java
@@ -0,0 +1,27 @@
+package com.cf.imes.module.system.validation.invoice;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.cf.imes.module.system.enums.pay.InvoiceIssueTypeEnum;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+
+/**
+ * 发票开具类型校验器
+ *
+ * @author Gqr
+ * @since 2025/8/21 14:37
+ */
+public class InvoiceIssueTypeValidtor implements ConstraintValidator {
+ @Override
+ public boolean isValid(Integer integer, ConstraintValidatorContext constraintValidatorContext) {
+ if (ObjectUtil.isNull(integer)) {
+ return true;
+ }
+ for (InvoiceIssueTypeEnum issueTypeEnum : InvoiceIssueTypeEnum.values()) {
+ if (issueTypeEnum.getValue().equals(integer)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/invoice/InvoiceTypeValid.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/invoice/InvoiceTypeValid.java
new file mode 100644
index 000000000..a77c4117b
--- /dev/null
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/invoice/InvoiceTypeValid.java
@@ -0,0 +1,32 @@
+package com.cf.imes.module.system.validation.invoice;
+
+import jakarta.validation.Constraint;
+import jakarta.validation.Payload;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 发票类型校验注解
+ *
+ * @author Gqr
+ * @since 2025/8/21 14:36
+ */
+@Target({
+ ElementType.FIELD,
+})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Constraint(
+ validatedBy = {InvoiceTypeValidtor.class}
+)
+public @interface InvoiceTypeValid {
+ String message() default "不支持的发票类型";
+
+ Class>[] groups() default {};
+
+ Class extends Payload>[] payload() default {};
+}
diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/invoice/InvoiceTypeValidtor.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/invoice/InvoiceTypeValidtor.java
new file mode 100644
index 000000000..72eedcbc8
--- /dev/null
+++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/invoice/InvoiceTypeValidtor.java
@@ -0,0 +1,27 @@
+package com.cf.imes.module.system.validation.invoice;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.cf.imes.module.system.enums.pay.InvoiceTypeEnum;
+import jakarta.validation.ConstraintValidator;
+import jakarta.validation.ConstraintValidatorContext;
+
+/**
+ * 发票类型校验器
+ *
+ * @author Gqr
+ * @since 2025/8/21 14:37
+ */
+public class InvoiceTypeValidtor implements ConstraintValidator {
+ @Override
+ public boolean isValid(Integer integer, ConstraintValidatorContext constraintValidatorContext) {
+ if (ObjectUtil.isNull(integer)) {
+ return true;
+ }
+ for (InvoiceTypeEnum invoiceTypeEnum : InvoiceTypeEnum.values()) {
+ if (invoiceTypeEnum.getValue().equals(integer)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/cf-module-system/cf-module-system-biz/src/main/resources/application-dev.yaml b/cf-module-system/cf-module-system-biz/src/main/resources/application-dev.yaml
index 0b3c60744..7e15ddb7b 100644
--- a/cf-module-system/cf-module-system-biz/src/main/resources/application-dev.yaml
+++ b/cf-module-system/cf-module-system-biz/src/main/resources/application-dev.yaml
@@ -266,6 +266,17 @@ chenfeng:
privateKey: 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
alipayPublicKey: KbUGE7zsPBKWPx0/zMcAdLRldKrcgy2LRiOrqOBm7y4iPJLXTYtXFJT15p2JMQiyOM8mqiYQR0OEDwfrKxDgHXLtIut/e0EAk9bZwZoLrqVe0pN1huseRC38zEglbWil3yz+tZfHZuAaEq2EzvWJltX/tRKOzNBqAT9l+UvnqNedgCFB9MY2EErqJjbn/at3gYCkV2idt31ghF0z8SEQ5h9ztNYtmTvk8c8ipi0/hIjX8XryN6mlOvGQfyZ4rWrBWBuZ6iD/SyuThwxKmFYU4dhHbHVpBrva5nJWU43CP7RVaJm649nNJnce+Ppj2Tv8+ugSLe5poZWo2zmGe3Xn5WmN6OTZyRI1pnmn2/hGxtOMmTZJX7Gh0pI4v3wmU0gOd/gbRlqlvN+u12T92nyH8MQrHdA7UXuttAtolYUa/Rli/20qHX69QtOtvfZk8mNvDSj9dDvODseGcrFHm07jyfxpaIkQDeN75cQ3NwNgDQEW8urQszaU1IJ7hc+20tt0Z3td4+7MfiVPpGfVxsGE66gwLgpB8wsxEhyBTaBr7osMLqOv
notifyUrl: VvJ5DOVuGOBw39j7tyrvsEEtLSseVM8T3u9kqsWKago+iI5ao8JzoggmeSe+N9LrsYxutK4fkGpmr4jOGJ3JTQFZ7YBXLxf2oLIXOZH9O27EnDtm
+ wechat:
+ appId: vTVnNGeOPD8AeiTIS5cnUzq8q3EiOW0HZ18QtxFE/UxTYwV1DSwxrbYDbBGjoA==
+ mchId: p/zqgyb9tAG9n9DKROHdHuIv0FNQGfbQ0AH7uTsglakv9J4ZHGA=
+ mchKey: tdnmIOPmmqq0ST47xYWg61chgI2ycJGhjeApSjnraW103upgR/EMx/qfbFMVKA59BISqzbSukjQPV5pR
+ apiV3Key: tdnmIOPmmqq0ST47xYWg61chgI2ycJGhjeApSjnraW103upgR/EMx/qfbFMVKA59BISqzbSukjQPV5pR
+ publicKeyId: 9NU9NFR9WWUaN2xfCujfPhcOToJop6M0G4JGbpZDlkrfCQVK3KYDOEeinJwEuxvJGcoO2hKUVkapHmeUngH3VxPu+qBcf+gN8Q==
+ certSerialNo: zzAFIJnTSEhme+K37z/ciNI04S//eHxBR/VCKLdGRGTrWAlvHYU2LSw9YPl07OEBGOpIBHG3oep77cr5g8wpGXGRvJQ=
+ tradeType: eaQet/V56gw8fTCVKypLG8cAjgheMpxKo6Y6wQab1P5b9w==
+ publicKeyString: F+bPjhy/AwNvl16dMdqHCgKYIfA9c8Tho+g+fAeNOb7GjQf0NCX36B2ZH7yngpN6v82Q10/PfblVrPGrvMbDZcU4gxomhXN22L2hfaijPESgodEuoAd89Z31WYFuRRCKxAWWzjhXa+E5bBSUpMkuToLlgZgqiLmAmjfTJO9NOIM0i0+D/2foka4ALixhyklznefk8Dz2RwFb60luZSUE03NFoqp1/uifn6LB4r/Lery1wH8b1EN5rgjvJXDIRGsyaHWbtdQr0sB0NW6LoR5PzZPeq4X4DE6iBDzG7u55kFCFwVQXmxCgHN4bdniVHcu28m9piCTuvyGQHXZ2J6prsytv/N24ef/xBVTHMMx+bcj+AIB0z44/OfgK4DF2U4JURNsCmD9h6dY60Hi6kFHOe8Y9GcR8T9V2LrfOJdm2mX19U+ziCE7jo0zllxo6vzLCMwjfm61gWhxU30fOaZgXbhGHps3z/TS5LlYiLgZcv3LE+Ttvl3fl0Cm3SitvNqxwQTnLxxKjcr2+ZE523Azr6/6JF1t8wSBKz4MAH9FrNvHVbziu7QrrWOFpCUL22sbBXtglQvQ1fjHqQ84qcGh6fDJC9k3f+lWVX1jAQiJT6h2MjfwaSIbhUGFS1BG6mQ==
+ privateKeyString: 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
+ notifyUrl: RIEeHCoPHaAryuVN6mEYskBSl+EPvhsxRpjIbuIE7f7jABVxm46bLc01WQUe4Fn9NPYyNTv0xCxM68iRrmFDjAUjQ/hkIVNG+yD/kNsjcYCWa2gtOQPrvWZzDA==
justauth:
enabled: true
diff --git a/cf-module-system/cf-module-system-biz/src/main/resources/application-local.yaml b/cf-module-system/cf-module-system-biz/src/main/resources/application-local.yaml
index fa79e5dd7..a0a55646e 100644
--- a/cf-module-system/cf-module-system-biz/src/main/resources/application-local.yaml
+++ b/cf-module-system/cf-module-system-biz/src/main/resources/application-local.yaml
@@ -291,12 +291,17 @@ chenfeng:
privateKey: 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
alipayPublicKey: KbUGE7zsPBKWPx0/zMcAdLRldKrcgy2LRiOrqOBm7y4iPJLXTYtXFJT15p2JMQiyOM8mqiYQR0OEDwfrKxDgHXLtIut/e0EAk9bZwZoLrqVe0pN1huseRC38zEglbWil3yz+tZfHZuAaEq2EzvWJltX/tRKOzNBqAT9l+UvnqNedgCFB9MY2EErqJjbn/at3gYCkV2idt31ghF0z8SEQ5h9ztNYtmTvk8c8ipi0/hIjX8XryN6mlOvGQfyZ4rWrBWBuZ6iD/SyuThwxKmFYU4dhHbHVpBrva5nJWU43CP7RVaJm649nNJnce+Ppj2Tv8+ugSLe5poZWo2zmGe3Xn5WmN6OTZyRI1pnmn2/hGxtOMmTZJX7Gh0pI4v3wmU0gOd/gbRlqlvN+u12T92nyH8MQrHdA7UXuttAtolYUa/Rli/20qHX69QtOtvfZk8mNvDSj9dDvODseGcrFHm07jyfxpaIkQDeN75cQ3NwNgDQEW8urQszaU1IJ7hc+20tt0Z3td4+7MfiVPpGfVxsGE66gwLgpB8wsxEhyBTaBr7osMLqOv
notifyUrl: RIEeHCoPHaAryuVN6mEYskBSl+EPvhsxRpjIbuIE7f7jABVxm46bLc01WQUe4Fn9NPYyNTv0xCxM68iRrmFDjAUjQ/hkIVNG+yD/kNsjcYCWa2gtOQPrvWZzDA==
-# wechat:
-# payBaseUrl: https://api.mch.weixin.qq.com/xdc/apiv2sandbox
-# appId: wxd0b9c0b5d0b9c0b5
-# mchId: 1725093395
-# mchKey: Cf100261028910026102891002610289
-
+ wechat:
+ appId: vTVnNGeOPD8AeiTIS5cnUzq8q3EiOW0HZ18QtxFE/UxTYwV1DSwxrbYDbBGjoA==
+ mchId: p/zqgyb9tAG9n9DKROHdHuIv0FNQGfbQ0AH7uTsglakv9J4ZHGA=
+ mchKey: tdnmIOPmmqq0ST47xYWg61chgI2ycJGhjeApSjnraW103upgR/EMx/qfbFMVKA59BISqzbSukjQPV5pR
+ apiV3Key: tdnmIOPmmqq0ST47xYWg61chgI2ycJGhjeApSjnraW103upgR/EMx/qfbFMVKA59BISqzbSukjQPV5pR
+ publicKeyId: 9NU9NFR9WWUaN2xfCujfPhcOToJop6M0G4JGbpZDlkrfCQVK3KYDOEeinJwEuxvJGcoO2hKUVkapHmeUngH3VxPu+qBcf+gN8Q==
+ certSerialNo: zzAFIJnTSEhme+K37z/ciNI04S//eHxBR/VCKLdGRGTrWAlvHYU2LSw9YPl07OEBGOpIBHG3oep77cr5g8wpGXGRvJQ=
+ tradeType: eaQet/V56gw8fTCVKypLG8cAjgheMpxKo6Y6wQab1P5b9w==
+ publicKeyString: F+bPjhy/AwNvl16dMdqHCgKYIfA9c8Tho+g+fAeNOb7GjQf0NCX36B2ZH7yngpN6v82Q10/PfblVrPGrvMbDZcU4gxomhXN22L2hfaijPESgodEuoAd89Z31WYFuRRCKxAWWzjhXa+E5bBSUpMkuToLlgZgqiLmAmjfTJO9NOIM0i0+D/2foka4ALixhyklznefk8Dz2RwFb60luZSUE03NFoqp1/uifn6LB4r/Lery1wH8b1EN5rgjvJXDIRGsyaHWbtdQr0sB0NW6LoR5PzZPeq4X4DE6iBDzG7u55kFCFwVQXmxCgHN4bdniVHcu28m9piCTuvyGQHXZ2J6prsytv/N24ef/xBVTHMMx+bcj+AIB0z44/OfgK4DF2U4JURNsCmD9h6dY60Hi6kFHOe8Y9GcR8T9V2LrfOJdm2mX19U+ziCE7jo0zllxo6vzLCMwjfm61gWhxU30fOaZgXbhGHps3z/TS5LlYiLgZcv3LE+Ttvl3fl0Cm3SitvNqxwQTnLxxKjcr2+ZE523Azr6/6JF1t8wSBKz4MAH9FrNvHVbziu7QrrWOFpCUL22sbBXtglQvQ1fjHqQ84qcGh6fDJC9k3f+lWVX1jAQiJT6h2MjfwaSIbhUGFS1BG6mQ==
+ privateKeyString: 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
+ notifyUrl: RIEeHCoPHaAryuVN6mEYskBSl+EPvhsxRpjIbuIE7f7jABVxm46bLc01WQUe4Fn9NPYyNTv0xCxM68iRrmFDjAUjQ/hkIVNG+yD/kNsjcYCWa2gtOQPrvWZzDA==
justauth:
enabled: true
diff --git a/cf-module-system/cf-module-system-biz/src/main/resources/mapper/funds/purchase/PurchaseMapper.xml b/cf-module-system/cf-module-system-biz/src/main/resources/mapper/funds/purchase/PurchaseMapper.xml
index cb17f577c..9879dd996 100644
--- a/cf-module-system/cf-module-system-biz/src/main/resources/mapper/funds/purchase/PurchaseMapper.xml
+++ b/cf-module-system/cf-module-system-biz/src/main/resources/mapper/funds/purchase/PurchaseMapper.xml
@@ -5,4 +5,14 @@
select sum(account_balance_spent) from purchase_record
where organ_id = #{organId} and is_invocing = '${@com.cf.imes.module.system.enums.pay.InvoiceStatusEnum@INVOICABLE.status}';
+
+
+
\ No newline at end of file