zhanglin
2023-07-20 cde69bd6e9ce00b22df3690d85ea295459e3b168
微信支付封装
1个文件已修改
93个文件已添加
12736 ■■■■■ 已修改文件
ruoyi-modules/ruoyi-order/pom.xml 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/auth/AutoUpdateInCloudCertificatesVerifier.java 242 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/auth/CacheService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/auth/CloudCertificatesVerifier.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/config/ProfitsSharingConfig.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/constant/AccountType.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/GetPath.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/amount/AmountDayEndOfPlatformRequest.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/amount/AmountDayEndOfSubMchRequest.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/amount/AmountOnlineOfPlatformRequest.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/amount/AmountOnlineOfSubMchRequest.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/applyments/ApplymentsModifySettlementRequest.java 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/applyments/ApplymentsRequest.java 806 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/applyments/ApplymentsSettlementStatusRequest.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/applyments/ApplymentsStatusRequest.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/applyments/ApplymentsStatusRequest1.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/fund/WithdrawExceptionLogRequest.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/fund/WithdrawForPlatformRequest.java 91 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/fund/WithdrawForSubMchRequest.java 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/fund/WithdrawStatusForPlatformRequest.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/fund/WithdrawStatusForPlatformRequest1.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/fund/WithdrawStatusForSubMchRequest.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/fund/WithdrawStatusForSubMchRequest1.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/profitsharing/ProfitSharingAddReceiverRequest.java 117 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/profitsharing/ProfitSharingApplyRequest.java 188 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/profitsharing/ProfitSharingFinishRequest.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/profitsharing/ProfitSharingNotifyRequest.java 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/profitsharing/ProfitSharingNotifyRequest1.java 200 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/profitsharing/ProfitSharingQueryApplyRequest.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/profitsharing/ProfitSharingQueryRefundRequest.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/profitsharing/ProfitSharingRefundRequest.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/profitsharing/ProfitSharingRemoveReceiverRequest.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/refunds/RefundApplyRequest.java 189 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/refunds/RefundNotifyRequest.java 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/refunds/RefundNotifyRequest1.java 226 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/refunds/RefundQueryStatusRequest.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/refunds/RefundQueryStatusRequest1.java 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/subsidies/SubsidiesCancelRequest.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/subsidies/SubsidiesCreateRequest.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/subsidies/SubsidiesRefundRequest.java 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/pay/bill/BillOfFundFlowRequest.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/pay/bill/BillOfTradeRequest.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/pay/combine/CombineTransactionsAppRequest.java 356 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/pay/combine/CombineTransactionsCloseRequest.java 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/pay/combine/CombineTransactionsDetailRequest.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/pay/combine/CombineTransactionsJsRequest.java 356 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/pay/combine/CombineTransactionsNotifyRequest.java 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/pay/combine/CombineTransactionsNotifyRequest1.java 592 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/pay/combine/CombineTransactionsStatusRequest.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/tool/ImageUploadRequest.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/AbstractResponse.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/amount/AmountDayEndOfPlatformResponse.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/amount/AmountDayEndOfSubMchResponse.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/amount/AmountOnlineOfPlatformResponse.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/amount/AmountOnlineOfSubMchResponse.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/applyments/ApplymentsDownCertificatesResponse.java 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/applyments/ApplymentsModifySettlementResponse.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/applyments/ApplymentsResponse.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/applyments/ApplymentsSettlementStatusResponse.java 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/applyments/ApplymentsStatusResponse.java 343 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/fund/WithdrawExceptionLogResponse.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/fund/WithdrawForPlatformResponse.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/fund/WithdrawForSubMchResponse.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/fund/WithdrawStatusForPlatformResponse.java 194 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/fund/WithdrawStatusForSubMchResponse.java 192 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/profitsharing/ProfitSharingAddReceiverResponse.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/profitsharing/ProfitSharingApplyResponse.java 261 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/profitsharing/ProfitSharingFinishResponse.java 83 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/profitsharing/ProfitSharingNotifyResponse.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/profitsharing/ProfitSharingQueryApplyResponse.java 283 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/profitsharing/ProfitSharingQueryRefundResponse.java 172 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/profitsharing/ProfitSharingRefundResponse.java 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/profitsharing/ProfitSharingRemoveReceiverResponse.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/refunds/RefundApplyResponse.java 243 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/refunds/RefundNotifyResponse.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/refunds/RefundQueryStatusResponse.java 335 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/subsidies/SubsidiesCancelResponse.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/subsidies/SubsidiesCreateResponse.java 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/subsidies/SubsidiesRefundResponse.java 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/pay/bill/BillOfFundFlowResponse.java 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/pay/bill/BillOfTradeResponse.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/pay/combine/CombineTransactionsAppResponse.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/pay/combine/CombineTransactionsCloseResponse.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/pay/combine/CombineTransactionsJsResponse.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/pay/combine/CombineTransactionsNotifyResponse.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/pay/combine/CombineTransactionsStatusResponse.java 379 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/tool/ImageUploadResponse.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/service/ProfitsSharingService.java 1024 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/service/ProfitsSharingServiceEmptyImpl.java 274 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/service/ProfitsSharingServiceImpl.java 636 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/utils/BuilderDTOUtils.java 362 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/utils/DateFormatUtils.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/utils/HttpUtils.java 156 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/utils/JsonUtils.java 123 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-modules/ruoyi-order/pom.xml
@@ -107,6 +107,26 @@
            <version>0.2.8</version>
        </dependency>
        <!--  微信支付分提供的工具包,用于生成公用的http-client客户端 -->
        <dependency>
            <groupId>com.github.wechatpay-apiv3</groupId>
            <artifactId>wechatpay-apache-httpclient</artifactId>
            <version>0.4.9</version>
        </dependency>
        <!-- 爬虫工具,抓取和解析html https://mvnrepository.com/artifact/org.jsoup/jsoup -->
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.14.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpmime</artifactId>
            <version>4.5.12</version>
        </dependency>
    </dependencies>
    <build>
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/auth/AutoUpdateInCloudCertificatesVerifier.java
New file
@@ -0,0 +1,242 @@
package com.ruoyi.order.tools.auth;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wechat.pay.contrib.apache.httpclient.Credentials;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.CertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
/**
 * 在原有CertificatesVerifier基础上,增加自动更新证书功能
 */
@Slf4j
public class AutoUpdateInCloudCertificatesVerifier implements Verifier {
    private boolean cloud;
    private final String UPDATE_TIME_CACHE_KEY = "UPDATE_TIME_CACHE_KEY";
    private final String NEW_CREDENTIALS_CACHE_KEY = "NEW_CREDENTIALS_CACHE_KEY";
    private CacheService cacheService;
    //证书下载地址
    private static final String CertDownloadPath = "https://api.mch.weixin.qq.com/v3/certificates";
    //上次更新时间
    private volatile Instant instant;
    //证书更新间隔时间,单位为分钟
    private final int minutesInterval;
    private Verifier verifier;
    private final Credentials credentials;
    private final byte[] apiV3Key;
    private final ReentrantLock lock = new ReentrantLock();
    private List<X509Certificate> certificateList;
    public List<X509Certificate> getLastCertificateList() {
        List<X509Certificate> certificateList = getCertificateList();
        if (certificateList.isEmpty()) {
            //构造时更新证书
            try {
                autoUpdateCert();
                setInstant(Instant.now());
            } catch (IOException | GeneralSecurityException e) {
                throw new RuntimeException(e);
            }
        }
        return getCertificateList();
    }
    private List<X509Certificate> getCertificateList() {
        if (cloud) return cacheService.getList(NEW_CREDENTIALS_CACHE_KEY);
        else {
            return certificateList;
        }
    }
    //时间间隔枚举,支持一小时、六小时以及十二小时
    public enum TimeInterval {
        OneHour(60),
//        SixHours(60 * 6),
//        TwelveHours(60 * 12)
        ;
        private final int minutes;
        TimeInterval(int minutes) {
            this.minutes = minutes;
        }
        public int getMinutes() {
            return minutes;
        }
    }
    public AutoUpdateInCloudCertificatesVerifier(Credentials credentials, byte[] apiV3Key, CacheService cacheService) {
        this(credentials, apiV3Key, TimeInterval.OneHour.getMinutes(), cacheService);
    }
    public AutoUpdateInCloudCertificatesVerifier(Credentials credentials, byte[] apiV3Key, int minutesInterval, CacheService cacheService) {
        this.credentials = credentials;
        this.apiV3Key = apiV3Key;
        this.minutesInterval = minutesInterval;
        if (cacheService != null) {
            setCacheService(cacheService);
        }
        //构造时更新证书
        try {
            autoUpdateCert();
            setInstant(Instant.now());
        } catch (IOException | GeneralSecurityException e) {
            throw new RuntimeException(e);
        }
    }
    public Instant getInstant() {
        if (!cloud) {
            return instant;
        }
        return cacheService.get(UPDATE_TIME_CACHE_KEY, Instant.class);
    }
    public void setInstant(Instant instant) {
        if (cloud) {
            cacheService.cache(UPDATE_TIME_CACHE_KEY, instant);
        } else {
            this.instant = instant;
        }
    }
    public void setCacheService(CacheService cacheService) {
        this.cacheService = cacheService;
        cloud = true;
        verifier = new CloudCertificatesVerifier(cacheService);
    }
    @Override
    public boolean verify(String serialNumber, byte[] message, String signature) {
        if (invalidInstant()) {
            if (lock.tryLock()) {
                try {
                    autoUpdateCert();
                    //更新时间
                    setInstant(Instant.now());
                } catch (GeneralSecurityException | IOException e) {
                    log.warn("Auto update cert failed, exception = " + e);
                } finally {
                    lock.unlock();
                }
            }
        }
        return verifier.verify(serialNumber, message, signature);
    }
    @Override
    public X509Certificate getValidCertificate() {
        return null;
    }
    private boolean invalidInstant() {
        Instant instant = getInstant();
        return instant == null || Duration.between(instant, Instant.now()).toMinutes() >= minutesInterval;
    }
    private void autoUpdateCert() throws IOException, GeneralSecurityException {
        CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
                .withCredentials(credentials)
                // 先只校验更新时间,更新时间不符合条件的时候,当做首次下载证书
                .withValidator(invalidInstant() ? (response) -> true : new WechatPay2Validator(verifier))
                .build();
        HttpGet httpGet = new HttpGet(CertDownloadPath);
        httpGet.addHeader("Accept", "application/json");
        CloseableHttpResponse response = httpClient.execute(httpGet);
        int statusCode = response.getStatusLine().getStatusCode();
        String body = EntityUtils.toString(response.getEntity());
        if (statusCode == 200) {
            List<X509Certificate> newCertList = deserializeToCerts(apiV3Key, body);
            if (newCertList.isEmpty()) {
                log.warn("Cert list is empty");
                return;
            }
            if (cloud) {
                cacheService.cache(NEW_CREDENTIALS_CACHE_KEY, newCertList);
                Map<BigInteger, X509Certificate> certificateMap = new HashMap<>();
                for (X509Certificate x509Certificate : newCertList) {
                    certificateMap.put(x509Certificate.getSerialNumber(), x509Certificate);
                }
                cacheService.cache(CloudCertificatesVerifier.CACHE_KEY, certificateMap);
            } else {
                certificateList = newCertList;
                this.verifier = new CertificatesVerifier(newCertList);
            }
        } else {
            log.warn("Auto update cert failed, statusCode = " + statusCode + ",body = " + body);
        }
    }
    /**
     * 反序列化证书并解密
     */
    private List<X509Certificate> deserializeToCerts(byte[] apiV3Key, String body)
            throws GeneralSecurityException, IOException {
        AesUtil decryptor = new AesUtil(apiV3Key);
        ObjectMapper mapper = new ObjectMapper();
        JsonNode dataNode = mapper.readTree(body).get("data");
        List<X509Certificate> newCertList = new ArrayList<>();
        if (dataNode != null) {
            for (int i = 0, count = dataNode.size(); i < count; i++) {
                JsonNode encryptCertificateNode = dataNode.get(i).get("encrypt_certificate");
                //解密
                String cert = decryptor.decryptToString(
                        encryptCertificateNode.get("associated_data").toString().replaceAll("\"", "")
                                .getBytes(StandardCharsets.UTF_8),
                        encryptCertificateNode.get("nonce").toString().replaceAll("\"", "")
                                .getBytes(StandardCharsets.UTF_8),
                        encryptCertificateNode.get("ciphertext").toString().replaceAll("\"", ""));
                X509Certificate x509Cert = PemUtil
                        .loadCertificate(new ByteArrayInputStream(cert.getBytes(StandardCharsets.UTF_8)));
                try {
                    x509Cert.checkValidity();
                } catch (CertificateExpiredException | CertificateNotYetValidException e) {
                    continue;
                }
                newCertList.add(x509Cert);
            }
        }
        return newCertList;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/auth/CacheService.java
New file
@@ -0,0 +1,11 @@
package com.ruoyi.order.tools.auth;
import java.util.List;
import java.util.Map;
public interface CacheService {
    <T> void cache(String cacheKey, T cacheData);
    <T> T get(String cacheKey, Class<T> cacheType);
    <Key, Val> Map<Key, Val> getMap(String cacheKey);
    <T> List<T> getList(String cacheKey);
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/auth/CloudCertificatesVerifier.java
New file
@@ -0,0 +1,51 @@
package com.ruoyi.order.tools.auth;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.Map;
public class CloudCertificatesVerifier implements Verifier {
    public static final String CACHE_KEY = "CLOUD_CERTIFICATES_CACHE";
    private final CacheService cacheService;
    public CloudCertificatesVerifier(CacheService cacheService) {
        this.cacheService = cacheService;
    }
    private boolean verify(X509Certificate certificate, byte[] message, String signature) {
        try {
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initVerify(certificate);
            sign.update(message);
            return sign.verify(Base64.getDecoder().decode(signature));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持SHA256withRSA", e);
        } catch (SignatureException e) {
            throw new RuntimeException("签名验证过程发生了错误", e);
        } catch (InvalidKeyException e) {
            throw new RuntimeException("无效的证书", e);
        }
    }
    @Override
    public boolean verify(String serialNumber, byte[] message, String signature) {
        BigInteger val = new BigInteger(serialNumber, 16);
        Map<BigInteger, X509Certificate> certificates = cacheService.getMap(CACHE_KEY);
        return certificates.containsKey(val) && verify(certificates.get(val), message, signature);
    }
    @Override
    public X509Certificate getValidCertificate() {
        return null;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/config/ProfitsSharingConfig.java
New file
@@ -0,0 +1,15 @@
package com.ruoyi.order.tools.config;
import lombok.Data;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
@Data
public class ProfitsSharingConfig {
    private String apiKey;
    private String mchId;                   // 商户号
    private String mchSerialNo;             // 商户证书序列号
    private PrivateKey privateKey;          // 你的商户私钥
    private X509Certificate certificate;    // 商户证书,在这里几乎没用,证书基本上都是用下载的
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/constant/AccountType.java
New file
@@ -0,0 +1,7 @@
package com.ruoyi.order.tools.constant;
public enum AccountType {
    BASIC, //:基本账户
    OPERATION, //:运营账户
    FEES //:手续费账户
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/GetPath.java
New file
@@ -0,0 +1,5 @@
package top.gabin.tools.request;
public interface GetPath {
    String getPath();
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/amount/AmountDayEndOfPlatformRequest.java
New file
@@ -0,0 +1,51 @@
package com.ruoyi.order.tools.amount;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 通过此接口可以查询本商户号指定日期当天24点的账户余额。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/amount/chapter3_4.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties("accountType")
public class AmountDayEndOfPlatformRequest {
    /**
     * <pre>
     * 字段名:账户类型
     * 变量名:account_type
     * 是否必填:是
     * 类型:string [1,16]
     * 描述:
     *  path 枚举值:
     *  BASIC:基本账户
     *  OPERATION:运营账户
     *  FEES:手续费账户
     *  示例值:BASIC
     * </pre>
     */
    @JsonIgnore
    @JsonProperty(value = "account_type")
    private String accountType;
    /**
     * <pre>
     * 字段名:日期
     * 变量名:date
     * 是否必填:是
     * 类型:string[1,10]
     * 描述:
     *   指定查询商户日终余额的日期
     *  示例值:2019-08-17
     * </pre>
     */
    @JsonProperty(value = "date")
    private String date;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/amount/AmountDayEndOfSubMchRequest.java
New file
@@ -0,0 +1,48 @@
package com.ruoyi.order.tools.amount;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商服务商通过该接口可以查询二级商户指定日期当天24点的账户余额。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/amount/chapter3_2.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties("subMchid")
public class AmountDayEndOfSubMchRequest {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  path 电商平台二级商户号,由微信支付生成并下发。
     *  示例值:1222212222
     * </pre>
     */
    @JsonIgnore
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:日期
     * 变量名:date
     * 是否必填:是
     * 类型:string[1,10]
     * 描述:
     *   指定查询商户日终余额的日期
     *  示例值:2019-08-17
     * </pre>
     */
    @JsonProperty(value = "date")
    private String date;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/amount/AmountOnlineOfPlatformRequest.java
New file
@@ -0,0 +1,37 @@
package com.ruoyi.order.tools.amount;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商平台可通过此接口可以查询本商户号的账号余额情况。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/amount/chapter3_3.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties("accountType")
public class AmountOnlineOfPlatformRequest {
    /**
     * <pre>
     * 字段名:账户类型
     * 变量名:account_type
     * 是否必填:是
     * 类型:string[1,16]
     * 描述:
     *  path 枚举值:
     *  BASIC:基本账户
     *  OPERATION:运营账户
     *  FEES:手续费账户
     *  示例值:BASIC
     * </pre>
     */
    @JsonIgnore
    @JsonProperty(value = "account_type")
    private String accountType;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/amount/AmountOnlineOfSubMchRequest.java
New file
@@ -0,0 +1,51 @@
package com.ruoyi.order.tools.amount;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商服务商通过此接口可以查询二级商户账户余额信息。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/amount/chapter3_1.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties("subMchid")
public class AmountOnlineOfSubMchRequest {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  path电商平台二级商户号,由微信支付生成并下发。
     *  示例值: 1900000109
     * </pre>
     */
    @JsonIgnore
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:账户类型
     * 变量名:account_type
     * 是否必填:否
     * 类型:string[1,16]
     * 描述:
     *  枚举值:
     *  BASIC:基本账户
     *  OPERATION:运营账户
     *  FEES:手续费账户
     *  示例值: BASIC
     * </pre>
     */
    @JsonProperty(value = "account_type")
    private String accountType;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/applyments/ApplymentsModifySettlementRequest.java
New file
@@ -0,0 +1,119 @@
package com.ruoyi.order.tools.applyments;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 服务商/电商平台(不包括支付机构、银行),可使用本接口,修改其进件且已签约特约商户/二级商户的结算银行账户。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_4.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties("subMchid")
public class ApplymentsModifySettlementRequest {
    /**
     * <pre>
     * 字段名:特约商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[8,10]
     * 描述:
     *  path请填写本服务商负责进件的特约商户号。
     *  特殊规则:长度最小8个字节。
     *  示例值:1511101111
     * </pre>
     */
    @JsonIgnore
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:账户类型
     * 变量名:account_type
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 根据特约商户号的主体类型,可选择的账户类型如下:
     *  1、小微主体:经营者个人银行卡 2、个体工商户主体:经营者个人银行卡/ 对公银行账户 3、企业主体:对公银行账户 4、党政、机关及事业单位主体:对公银行账户 5、其他组织主体:对公银行账户 枚举值: ACCOUNT_TYPE_BUSINESS:对公银行账户 ACCOUNT_TYPE_PRIVATE:经营者个人银行卡 示例值:ACCOUNT_TYPE_BUSINESS
     * </pre>
     */
    @JsonProperty(value = "account_type")
    private String accountType;
    /**
     * <pre>
     * 字段名:开户银行
     * 变量名:account_bank
     * 是否必填:是
     * 类型:string[1,128]
     * 描述:
     *  body 请填写开户银行名称,详细参见开户银行对照表。
     *  注:
     *  17家直连银行,请根据开户银行对照表直接填写银行名 ;
     *  非17家直连银行,该参数请填写为“其他银行”
     *  示例值:工商银行
     * </pre>
     */
    @JsonProperty(value = "account_bank")
    private String accountBank;
    /**
     * <pre>
     * 字段名:开户银行省市编码
     * 变量名:bank_address_code
     * 是否必填:是
     * 类型:string[1,128]
     * 描述:
     *  body 需至少精确到市,详细参见省市区编号对照表。
     *  示例值:110000
     * </pre>
     */
    @JsonProperty(value = "bank_address_code")
    private String bankAddressCode;
    /**
     * <pre>
     * 字段名:开户银行全称(含支行)
     * 变量名:bank_name
     * 是否必填:否
     * 类型:string[1,128]
     * 描述:body 若开户银行为“其他银行”,则需二选一填写“开户银行全称(含支行)”或“开户银行联行号”。 填写银行全称,如"深圳农村商业银行XXX支行" ,详细参见开户银行全称(含支行)对照表。 示例值:施秉县农村信用合作联社城关信用社
     * </pre>
     */
    @JsonProperty(value = "bank_name")
    private String bankName;
    /**
     * <pre>
     * 字段名:开户银行联行号
     * 变量名:bank_branch_id
     * 是否必填:否
     * 类型:string[1,128]
     * 描述:body 若开户银行为“其他银行”,则需二选一填写“开户银行全称(含支行)”或“开户银行联行号”。 填写银行联行号,详细参见开户银行全称(含支行)对照表。 示例值:402713354941
     * </pre>
     */
    @JsonProperty(value = "bank_branch_id")
    private String bankBranchId;
    /**
     * <pre>
     * 字段名:银行账号
     * 变量名:account_number
     * 是否必填:是
     * 类型:string[1,1024]
     * 描述:
     *  body 1、数字,长度遵循系统支持的开户银行对照表中对公/对私卡号长度要求
     *  2、该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
     *  示例值:d+xT+MQCvrLHUVDWv/8MR/dB7TkXM2YYZlokmXzFsWs35NXUot7C0NcxIrUF5FnxqCJHkNgKtxa6RxEYyba1+VBRLnqKG2fSy/Y5qDN08Ej9zHCwJjq52Wg1VG8MRugli9YMI1fI83KGBxhuXyemgS/hqFKsfYGiOkJqjTUpgY5VqjtL2N4l4z11T0ECB/aSyVXUysOFGLVfSrUxMPZy6jWWYGvT1+4P633f+R+ki1gT4WF/2KxZOYmli385ZgVhcR30mr4/G3HBcxi13zp7FnEeOsLlvBmI1PHN4C7Rsu3WL8sPndjXTd75kPkyjqnoMRrEEaYQE8ZRGYoeorwC+w==
     * </pre>
     */
    @JsonProperty(value = "account_number")
    private String accountNumber;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/applyments/ApplymentsRequest.java
New file
@@ -0,0 +1,806 @@
package com.ruoyi.order.tools.applyments;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商平台,可使用该接口,帮助其二级商户进件成为微信支付商户。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_1.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ApplymentsRequest {
    /**
     * <pre>
     * 字段名:业务申请编号
     * 变量名:out_request_no
     * 是否必填:是
     * 类型:string[1,124]
     * 描述:
     *  body 1、服务商自定义的商户唯一编号。
     *  2、每个编号对应一个申请单,每个申请单审核通过后会生成一个微信支付商户号。
     *  3、若申请单被驳回,可填写相同的“业务申请编号”,即可覆盖修改原申请单信息 。
     *  示例值:APPLYMENT_00000000001
     * </pre>
     */
    @JsonProperty(value = "out_request_no")
    private String outRequestNo;
    /**
     * <pre>
     * 字段名:主体类型
     * 变量名:organization_type
     * 是否必填:是
     * 类型:string[1,4]
     * 描述:
     *  body 非小微的主体类型需与营业执照/登记证书上一致,可参考选择主体指引,枚举值如下。
     *  2401:小微商户,指无营业执照的个人商家。
     *  2500:个人卖家,指无营业执照,已持续从事电子商务经营活动满6个月,且期间经营收入累计超过20万元的个人商家。(若选择该主体,请在“补充说明”填写相关描述)
     *  4:个体工商户,营业执照上的主体类型一般为个体户、个体工商户、个体经营。
     *  2:企业,营业执照上的主体类型一般为有限公司、有限责任公司。
     *  3:党政、机关及事业单位,包括国内各级、各类政府机构、事业单位等(如:公安、党 团、司法、交通、旅游、工商税务、市政、医疗、教育、学校等机构)。
     *  1708:其他组织,不属于企业、政府/事业单位的组织机构(如社会团体、民办非企业、基 金会),要求机构已办理组织机构代码证。
     *  示例值:2401
     * </pre>
     */
    @JsonProperty(value = "organization_type")
    private String organizationType;
    /**
     * <pre>
     * 字段名:+营业执照/登记证书信息
     * 变量名:business_license_info
     * 是否必填:条件选填
     * 类型:object
     * 描述:
     *  body 1、主体为“小微/个人卖家”时,不填。
     *  2、主体为“个体工商户/企业”时,请上传营业执照。
     *  3、主体为“党政、机关及事业单位/其他组织”时,请上传登记证书。
     * </pre>
     */
    @JsonProperty(value = "business_license_info")
    private BusinessLicenseInfo businessLicenseInfo;
    /**
     * <pre>
     * 字段名:+组织机构代码证信息
     * 变量名:organization_cert_info
     * 是否必填:条件选填
     * 类型:object
     * 描述:body 主体为“企业/党政、机关及事业单位/其他组织”,且营业执照/登记证书号码不是18位时必填。
     * </pre>
     */
    @JsonProperty(value = "organization_cert_info")
    private OrganizationCertInfo organizationCertInfo;
    /**
     * <pre>
     * 字段名:经营者/法人证件类型
     * 变量名:id_doc_type
     * 是否必填:否
     * 类型:string[1,64]
     * 描述:
     *  body 1、主体为“小微/个人卖家”,可选择:身份证。
     *  2、主体为“个体户/企业/党政、机关及事业单位/其他组织”,可选择:以下任一证件类型。
     *  3、若没有填写,系统默认选择:身份证。
     *  枚举值:
     *  IDENTIFICATION_TYPE_MAINLAND_IDCARD:中国大陆居民-身份证
     *  IDENTIFICATION_TYPE_OVERSEA_PASSPORT:其他国家或地区居民-护照
     *  IDENTIFICATION_TYPE_HONGKONG:中国香港居民–来往内地通行证
     *  IDENTIFICATION_TYPE_MACAO:中国澳门居民–来往内地通行证
     *  IDENTIFICATION_TYPE_TAIWAN:中国台湾居民–来往大陆通行证
     *  示例值:IDENTIFICATION_TYPE_MACAO
     * </pre>
     */
    @JsonProperty(value = "id_doc_type")
    private String idDocType;
    /**
     * <pre>
     * 字段名:+经营者/法人身份证信息
     * 变量名:id_card_info
     * 是否必填:条件选填
     * 类型:object
     * 描述:
     *  body 请填写经营者/法人的身份证信息
     *  证件类型为“身份证”时填写。
     *
     * </pre>
     */
    @JsonProperty(value = "id_card_info")
    private IdCardInfo idCardInfo;
    /**
     * <pre>
     * 字段名:+经营者/法人其他类型证件信息
     * 变量名:id_doc_info
     * 是否必填:条件选填
     * 类型:object
     * 描述:body 证件类型为“来往内地通行证、来往大陆通行证、护照”时填写。
     * </pre>
     */
    @JsonProperty(value = "id_doc_info")
    private IdDocInfo idDocInfo;
    /**
     * <pre>
     * 字段名:是否填写结算银行账户
     * 变量名:need_account_info
     * 是否必填:是
     * 类型:bool
     * 描述:
     *  body 1、可根据实际情况,填写“true”或“false”。
     *  1)若为“true”,则需填写结算银行账户。
     *  2)若为“false”,则无需填写结算银行账户。
     *  2、若入驻时未填写结算银行账户,则需入驻后调用修改结算账户API补充信息,才能发起提现。
     *  示例值:true
     * </pre>
     */
    @JsonProperty(value = "need_account_info")
    private Boolean needAccountInfo;
    /**
     * <pre>
     * 字段名:+结算银行账户
     * 变量名:account_info
     * 是否必填:条件选填
     * 类型:object
     * 描述:body 若"是否填写结算账户信息"填写为“true”, 则必填,填写为“false”不填 。
     * </pre>
     */
    @JsonProperty(value = "account_info")
    private AccountInfo accountInfo;
    /**
     * <pre>
     * 字段名:+超级管理员信息
     * 变量名:contact_info
     * 是否必填:是
     * 类型:object
     * 描述:
     *  body 请填写店铺的超级管理员信息。
     *  超级管理员需在开户后进行签约,并可接收日常重要管理信息和进行资金操作,请确定其为商户法定代表人或负责人。
     * </pre>
     */
    @JsonProperty(value = "contact_info")
    private ContactInfo contactInfo;
    /**
     * <pre>
     * 字段名:+店铺信息
     * 变量名:sales_scene_info
     * 是否必填:是
     * 类型:object
     * 描述:body 请填写店铺信息
     * </pre>
     */
    @JsonProperty(value = "sales_scene_info")
    private SalesSceneInfo salesSceneInfo;
    /**
     * <pre>
     * 字段名:商户简称
     * 变量名:merchant_shortname
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  body UTF-8格式,中文占3个字节,即最多16个汉字长度。将在支付完成页向买家展示,需与商家的实际售卖商品相符 。
     *  示例值:腾讯
     * </pre>
     */
    @JsonProperty(value = "merchant_shortname")
    private String merchantShortname;
    /**
     * <pre>
     * 字段名:特殊资质
     * 变量名:qualifications
     * 是否必填:否
     * 类型:string[1,1024]
     * 描述:
     *  body 1、若从事互联网售药,则需提供 《互联网药品交易服务证》;
     *  2、最多可上传5张照片,请填写通过图片上传接口预先上传图片生成好的MediaID 。
     *  示例值:[\"jTpGmxUX3FBWVQ5NJInE4d2I6_H7I4\"]
     * </pre>
     */
    @JsonProperty(value = "qualifications")
    private String qualifications;
    /**
     * <pre>
     * 字段名:补充材料
     * 变量名:business_addition_pics
     * 是否必填:否
     * 类型:string[1,1024]
     * 描述:
     *  body 最多可上传5张照片,请填写通过图片上传接口预先上传图片生成好的MediaID 。
     *  示例值:[\"jTpGmg05InE4d2I6_H7I4\"]
     * </pre>
     */
    @JsonProperty(value = "business_addition_pics")
    private String businessAdditionPics;
    /**
     * <pre>
     * 字段名:补充说明
     * 变量名:business_addition_desc
     * 是否必填:否
     * 类型:string[1,256]
     * 描述:
     *  body 1、可填写512字以内 。
     *  2、若主体为“个人卖家”,则需填写描述“ 该商户已持续从事电子商务经营活动满6个月,且期间经营收入累计超过20万元。”。
     *  示例值:特殊情况,说明原因
     * </pre>
     */
    @JsonProperty(value = "business_addition_desc")
    private String businessAdditionDesc;
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class BusinessLicenseInfo {
        /**
         * <pre>
         * 字段名:证件扫描件
         * 变量名:business_license_copy
         * 是否必填:是
         * 类型:string[1,256]
         * 描述:
         *  1、主体为“个体工商户/企业”时,请上传营业执照的证件图片。
         *  2、主体为“党政、机关及事业单位/其他组织”时,请上传登记证书的证件图片。
         *  3、可上传1张图片,请填写通过图片上传接口预先上传图片生成好的MediaID 。
         *  4、图片要求:
         *  (1)请上传证件的彩色扫描件或彩色数码拍摄件,黑白复印件需加盖公章(公章信息需完整) 。
         *  (2)不得添加无关水印(非微信支付商户申请用途的其他水印)。
         *  (3)需提供证件的正面拍摄件,完整、照面信息清晰可见。信息不清晰、扭曲、压缩变形、反光、不完整均不接受。
         *  (4)不接受二次剪裁、翻拍、PS的证件照片。
         *  示例值: 47ZC6GC-vnrbEny__Ie_An5-tCpqxucuxi-vByf3Gjm7KE53JXvGy9tqZm2XAUf-4KGprrKhpVBDIUv0OF4wFNIO4kqg05InE4d2I6_H7I4
         * </pre>
         */
        @JsonProperty(value = "business_license_copy")
        private String businessLicenseCopy;
        /**
         * <pre>
         * 字段名:证件注册号
         * 变量名:business_license_number
         * 是否必填:是
         * 类型:string[15,18]
         * 描述:
         *  1、主体为“个体工商户/企业”时,请填写营业执照上的注册号/统一社会信用代码,须为15位数字或 18位数字|大写字母。
         *  2、主体为“党政、机关及事业单位/其他组织”时,请填写登记证书的证书编号。
         *  示例值:123456789012345678
         * </pre>
         */
        @JsonProperty(value = "business_license_number")
        private String businessLicenseNumber;
        /**
         * <pre>
         * 字段名:商户名称
         * 变量名:merchant_name
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  1、请填写营业执照/登记证书的商家名称,2~110个字符,支持括号 。
         *  2、个体工商户/党政、机关及事业单位,不能以“公司”结尾。
         *  3、个体工商户,若营业执照上商户名称为空或为“无”,请填写"个体户+经营者姓名",如“个体户张三” 。
         *  示例值:腾讯科技有限公司
         * </pre>
         */
        @JsonProperty(value = "merchant_name")
        private String merchantName;
        /**
         * <pre>
         * 字段名:经营者/法定代表人姓名
         * 变量名:legal_person
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  请填写证件的经营者/法定代表人姓名
         *  示例值:张三
         * </pre>
         */
        @JsonProperty(value = "legal_person")
        private String legalPerson;
        /**
         * <pre>
         * 字段名:注册地址
         * 变量名:company_address
         * 是否必填:条件选填
         * 类型:string[1,128]
         * 描述:
         *  主体为“党政、机关及事业单位/其他组织”时必填,请填写登记证书的注册地址。
         *  示例值:深圳南山区科苑路
         * </pre>
         */
        @JsonProperty(value = "company_address")
        private String companyAddress;
        /**
         * <pre>
         * 字段名:营业期限
         * 变量名:business_time
         * 是否必填:条件选填
         * 类型:string[1,256]
         * 描述:
         *  1、主体为“党政、机关及事业单位/其他组织”时必填,请填写证件有效期。
         *  2、若证件有效期为长期,请填写:长期。
         *  3、结束时间需大于开始时间。
         *  4、有效期必须大于60天,即结束时间距当前时间需超过60天。
         *  示例值:[\"2014-01-01\",\"长期\"]
         * </pre>
         */
        @JsonProperty(value = "business_time")
        private String businessTime;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class OrganizationCertInfo {
        /**
         * <pre>
         * 字段名:组织机构代码证照片
         * 变量名:organization_copy
         * 是否必填:是
         * 类型:string[1,256]
         * 描述:
         *  可上传1张图片,请填写通过图片上传接口预先上传图片生成好的MediaID。
         *  示例值:vByf3Gjm7KE53JXv\prrKhpVBDIUv0OF4wFNIO4kqg05InE4d2I6_H7I4
         * </pre>
         */
        @JsonProperty(value = "organization_copy")
        private String organizationCopy;
        /**
         * <pre>
         * 字段名:组织机构代码
         * 变量名:organization_number
         * 是否必填:是
         * 类型:string[1,256]
         * 描述:
         *  1、请填写组织机构代码证上的组织机构代码。
         *  2、可填写9或10位 数字|字母|连字符。
         *  示例值:12345679-A
         * </pre>
         */
        @JsonProperty(value = "organization_number")
        private String organizationNumber;
        /**
         * <pre>
         * 字段名:组织机构代码有效期限
         * 变量名:organization_time
         * 是否必填:是
         * 类型:string[1,256]
         * 描述:
         *  1、请填写组织机构代码证的有效期限,注意参照示例中的格式。
         *  2、若证件有效期为长期,请填写:长期。
         *  3、结束时间需大于开始时间。
         *  4、有效期必须大于60天,即结束时间距当前时间需超过60天。
         *  示例值:[\"2014-01-01\",\"长期\"]
         * </pre>
         */
        @JsonProperty(value = "organization_time")
        private String organizationTime;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class IdCardInfo {
        /**
         * <pre>
         * 字段名:身份证人像面照片
         * 变量名:id_card_copy
         * 是否必填:是
         * 类型:string[1,256]
         * 描述:
         *  1、请上传经营者/法定代表人的身份证人像面照片。
         *  2、可上传1张图片,请填写通过图片上传接口预先上传图片生成好的MediaID。
         *  示例值:xpnFuAxhBTEO_PvWkfSCJ3zVIn001D8daLC-ehEuo0BJqRTvDujqhThn4ReFxikqJ5YW6zFQ
         * </pre>
         */
        @JsonProperty(value = "id_card_copy")
        private String idCardCopy;
        /**
         * <pre>
         * 字段名:身份证国徽面照片
         * 变量名:id_card_national
         * 是否必填:是
         * 类型:string[1,256]
         * 描述:
         *  1、请上传经营者/法定代表人的身份证国徽面照片。
         *  2、可上传1张图片,请填写通过图片上传接口预先上传图片生成好的MediaID 。
         *  示例值:vByf3Gjm7KE53JXvGy9tqZm2XAUf-4KGprrKhpVBDIUv0OF4wFNIO4kqg05InE4d2I6_H7I4
         * </pre>
         */
        @JsonProperty(value = "id_card_national")
        private String idCardNational;
        /**
         * <pre>
         * 字段名:身份证姓名
         * 变量名:id_card_name
         * 是否必填:是
         * 类型:string[1,256]
         * 描述:
         *  1、请填写经营者/法定代表人对应身份证的姓名,2~30个中文字符、英文字符、符号。
         *  2、该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
         *  示例值:pVd1HJ6v/69bDnuC4EL5Kz4jBHLiCa8MRtelw/wDa4SzfeespQO/0kjiwfqdfg==
         * </pre>
         */
        @JsonProperty(value = "id_card_name")
        private String idCardName;
        /**
         * <pre>
         * 字段名:身份证号码
         * 变量名:id_card_number
         * 是否必填:是
         * 类型:string[15,18]
         * 描述:
         *  1、请填写经营者/法定代表人对应身份证的号码。
         *  2、15位数字或17位数字+1位数字|X ,该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
         *  示例值:zV+BEmytMNQCqQ8juwEc4P4TG5xzchG/5IL9DBd+Z0zZXkw==4
         * </pre>
         */
        @JsonProperty(value = "id_card_number")
        private String idCardNumber;
        /**
         * <pre>
         * 字段名:身份证有效期限
         * 变量名:id_card_valid_time
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  1、请填写身份证有效期的结束时间,注意参照示例中的格式。
         *  2、若证件有效期为长期,请填写:长期。
         *  3、证件有效期需大于60天。
         *  示例值:2026-06-06,长期
         * </pre>
         */
        @JsonProperty(value = "id_card_valid_time")
        private String idCardValidTime;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class IdDocInfo {
        /**
         * <pre>
         * 字段名:证件姓名
         * 变量名:id_doc_name
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  请填写经营者/法人姓名。
         *  示例值:jTpGmxUX3FBWVQ5NJTZvlKX_gdU4LC-ehEuo0BJqRTvDujqhThn4ReFxikqJ5YW6zFQ
         * </pre>
         */
        @JsonProperty(value = "id_doc_name")
        private String idDocName;
        /**
         * <pre>
         * 字段名:证件号码
         * 变量名:id_doc_number
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  7~11位 数字|字母|连字符 。
         *  示例值:jTpGmxUX3FBWVQ5NJTZvlKX_go0BJqRTvDujqhThn4ReFxikqJ5YW6zFQ
         * </pre>
         */
        @JsonProperty(value = "id_doc_number")
        private String idDocNumber;
        /**
         * <pre>
         * 字段名:证件照片
         * 变量名:id_doc_copy
         * 是否必填:是
         * 类型:string[1,256]
         * 描述:
         *  1、可上传1张图片,请填写通过图片上传接口预先上传图片生成好的MediaID。
         *  2、2M内的彩色图片,格式可为bmp、png、jpeg、jpg或gif 。
         *  示例值:xi-vByf3Gjm7KE53JXvGy9tqZm2XAUf-4KGprrKhpVBDIUv0OF4wFNIO4kqg05InE4d2I6_H7I4
         * </pre>
         */
        @JsonProperty(value = "id_doc_copy")
        private String idDocCopy;
        /**
         * <pre>
         * 字段名:证件结束日期
         * 变量名:doc_period_end
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  1、请按照示例值填写。
         *  2、若证件有效期为长期,请填写:长期。
         *  3、证件有效期需大于60天 。
         *  示例值:2020-01-02
         * </pre>
         */
        @JsonProperty(value = "doc_period_end")
        private String docPeriodEnd;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class AccountInfo {
        /**
         * <pre>
         * 字段名:账户类型
         * 变量名:bank_account_type
         * 是否必填:是
         * 类型:string[1,2]
         * 描述:
         *  1、若主体为企业/党政、机关及事业单位/其他组织,可填写:74-对公账户。
         *  2、主体为“小微/个人卖家”,可选择:75-对私账户。
         *  3、若主体为个体工商户,可填写:74-对公账户、75-对私账户。
         *  示例值:75
         * </pre>
         */
        @JsonProperty(value = "bank_account_type")
        private String bankAccountType;
        /**
         * <pre>
         * 字段名:开户银行
         * 变量名:account_bank
         * 是否必填:是
         * 类型:string[1,10]
         * 描述:
         *  详细参见开户银行对照表。
         *  示例值:工商银行
         * </pre>
         */
        @JsonProperty(value = "account_bank")
        private String accountBank;
        /**
         * <pre>
         * 字段名:开户名称
         * 变量名:account_name
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  1、选择经营者个人银行卡时,开户名称必须与身份证姓名一致。
         *  2、选择对公账户时,开户名称必须与营业执照上的“商户名称”一致。
         *  3、该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
         *  示例值:AOZdYGISxo4yw96uY1Pk7Rq79Jtt7+I8juwEc4P4TG5xzchG/5IL9DBd+Z0zZXkw==
         * </pre>
         */
        @JsonProperty(value = "account_name")
        private String accountName;
        /**
         * <pre>
         * 字段名:开户银行省市编码
         * 变量名:bank_address_code
         * 是否必填:是
         * 类型:string[1,12]
         * 描述:
         *  至少精确到市,详细参见省市区编号对照表。
         *  示例值:110000
         * </pre>
         */
        @JsonProperty(value = "bank_address_code")
        private String bankAddressCode;
        /**
         * <pre>
         * 字段名:开户银行联行号
         * 变量名:bank_branch_id
         * 是否必填:条件选填
         * 类型:string[1,64]
         * 描述:
         *  1、17家直连银行无需填写,如为其他银行,开户银行全称(含支行)和开户银行联行号二选一。
         *  2、详细参见开户银行全称(含支行)对照表。
         *  示例值:402713354941
         * </pre>
         */
        @JsonProperty(value = "bank_branch_id")
        private String bankBranchId;
        /**
         * <pre>
         * 字段名:开户银行全称 (含支行]
         * 变量名:bank_name
         * 是否必填:条件选填
         * 类型:string[1,128]
         * 描述:
         *  1、17家直连银行无需填写,如为其他银行,开户银行全称(含支行)和开户银行联行号二选一。
         *  2、需填写银行全称,如"深圳农村商业银行XXX支行" 。
         *  3、详细参见开户银行全称(含支行)对照表。
         *  示例值:施秉县农村信用合作联社城关信用社
         * </pre>
         */
        @JsonProperty(value = "bank_name")
        private String bankName;
        /**
         * <pre>
         * 字段名:银行帐号
         * 变量名:account_number
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  1、数字,长度遵循系统支持的对公/对私卡号长度要求表。
         *  2、该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
         *  示例值: d+xT+MQCvrLHUVDWv/8MR/dB7TkXLVfSrUxMPZy6jWWYzpRrEEaYQE8ZRGYoeorwC+w==
         * </pre>
         */
        @JsonProperty(value = "account_number")
        private String accountNumber;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class ContactInfo {
        /**
         * <pre>
         * 字段名:超级管理员类型
         * 变量名:contact_type
         * 是否必填:是
         * 类型:string[1,2]
         * 描述:
         *  1、主体为“小微/个人卖家 ”,可选择:65-经营者/法人。
         *  2、主体为“个体工商户/企业/党政、机关及事业单位/其他组织”,可选择:65-经营者/法人、66- 负责人。 (负责人:经商户授权办理微信支付业务的人员,授权范围包括但不限于签约,入驻过程需完成账户验证)。
         *  示例值:65
         * </pre>
         */
        @JsonProperty(value = "contact_type")
        private String contactType;
        /**
         * <pre>
         * 字段名:超级管理员姓名
         * 变量名:contact_name
         * 是否必填:是
         * 类型:string[1,256]
         * 描述:
         *  1、若管理员类型为“法人”,则该姓名需与法人身份证姓名一致。
         *  2、若管理员类型为“经办人”,则可填写实际经办人的姓名。
         *  3、该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
         *  (后续该管理员需使用实名微信号完成签约)
         *  示例值: pVd1HJ6zyvPedzGaV+X3IdGdbDnuC4Eelw/wDa4SzfeespQO/0kjiwfqdfg==
         * </pre>
         */
        @JsonProperty(value = "contact_name")
        private String contactName;
        /**
         * <pre>
         * 字段名:超级管理员身份证件号码
         * 变量名:contact_id_card_number
         * 是否必填:是
         * 类型:string[1,256]
         * 描述:
         *  1、若管理员类型为法人,则该身份证号码需与法人身份证号码一致。若管理员类型为经办人,则可填写实际经办人的身份证号码。
         *  2、可传身份证、来往内地通行证、来往大陆通行证、护照等证件号码。
         *  3、超级管理员签约时,校验微信号绑定的银行卡实名信息,是否与该证件号码一致。
         *  4、该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
         *  示例值:pVd1HJ6zmty7/mYNxLMpRSvMRtelw/wDa4SzfeespQO/0kjiwfqdfg==
         * </pre>
         */
        @JsonProperty(value = "contact_id_card_number")
        private String contactIdCardNumber;
        /**
         * <pre>
         * 字段名:超级管理员手机
         * 变量名:mobile_phone
         * 是否必填:是
         * 类型:string[1,256]
         * 描述:
         *  1、请填写管理员的手机号,11位数字, 用于接收微信支付的重要管理信息及日常操作验证码 。
         *  2、该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
         *  示例值:pVd1HJ6zyvPedzGaV+X3qtmrq9bb9tPROvwia4ibL+F6mfjbzQIzfb3HHLEjZ4YiNWWNeespQO/0kjiwfqdfg==
         * </pre>
         */
        @JsonProperty(value = "mobile_phone")
        private String mobilePhone;
        /**
         * <pre>
         * 字段名:超级管理员邮箱
         * 变量名:contact_email
         * 是否必填:条件选填
         * 类型:string[1,256]
         * 描述:
         *  1、主体类型为“小微商户/个人卖家”可选填,其他主体需必填。
         *  2、用于接收微信支付的开户邮件及日常业务通知。
         *  3、需要带@,遵循邮箱格式校验 。
         *  4、该字段需进行加密处理,加密方法详见敏感信息加密说明。(提醒:必须在HTTP头中上送Wechatpay-Serial)
         *  示例值:pVd1HJ6zyvPedzGaV+X3qtmrq9bb9tPROvwia4ibL+FWWNUlw/wDa4SzfeespQO/0kjiwfqdfg==
         * </pre>
         */
        @JsonProperty(value = "contact_email")
        private String contactEmail;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class SalesSceneInfo {
        /**
         * <pre>
         * 字段名:店铺名称
         * 变量名:store_name
         * 是否必填:是
         * 类型:string[1,256]
         * 描述:
         *  请填写店铺全称。
         *  示例值:爱烧烤
         * </pre>
         */
        @JsonProperty(value = "store_name")
        private String storeName;
        /**
         * <pre>
         * 字段名:店铺链接
         * 变量名:store_url
         * 是否必填:二选一
         * 类型:string[1,1024]
         * 描述:
         *  1、店铺二维码or店铺链接二选一必填。
         *  2、请填写店铺主页链接,需符合网站规范。
         *  示例值:http://www.qq.com
         * </pre>
         */
        @JsonProperty(value = "store_url")
        private String storeUrl;
        /**
         * <pre>
         * 字段名:店铺二维码
         * 变量名:store_qr_code
         * 是否必填:1、店铺二维码 or 店铺链接二选一必填。 2、若为电商小程序,可上传店铺页面的小程序二维码。 3、请填写通过图片上传接口预先上传图片生成好的MediaID,仅能上传1张图片 。 示例值:jTpGmxUX3FBWVQ5NJTZvlKX_gdU4cRz7z5NxpnFuAxhBTEO1D8daLC-ehEuo0BJqRTvDujqhThn4ReFxikqJ5YW6zFQ
         * 类型:string[1,256]
         * 描述:
         * </pre>
         */
        @JsonProperty(value = "store_qr_code")
        private String storeQrCode;
        /**
         * <pre>
         * 字段名:小程序AppID
         * 变量名:mini_program_sub_appid
         * 是否必填:否
         * 类型:string[1,256]
         * 描述:
         *  body 1、可填写已认证的小程序AppID,认证主体需与二级商户主体一致;
         *  2、完成入驻后, 系统发起二级商户号与该AppID的绑定(即配置为sub_appid,可在发起支付时传入)
         *  示例值:wxd678efh567hg6787
         * </pre>
         */
        @JsonProperty(value = "mini_program_sub_appid")
        private String miniProgramSubAppid;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/applyments/ApplymentsSettlementStatusRequest.java
New file
@@ -0,0 +1,34 @@
package com.ruoyi.order.tools.applyments;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 服务商/电商平台(不包括支付机构、银行),可使用本接口,查询其进件且已签约特约商户/二级商户的结算账户信息(敏感信息掩码)。 该接口可用于核实是否成功修改结算账户信息、及查询系统汇款验证结果。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_5.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties("subMchid")
public class ApplymentsSettlementStatusRequest {
    /**
     * <pre>
     * 字段名:特约商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[8,10]
     * 描述:
     *  path 请输入本服务商进件、已签约的特约商户号。
     *  示例值:1900006491
     * </pre>
     */
    @JsonIgnore
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/applyments/ApplymentsStatusRequest.java
New file
@@ -0,0 +1,34 @@
package com.ruoyi.order.tools.applyments;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商平台通过查询申请状态API查询二级商户入驻申请结果。该查询服务提供两种查询方式(两种查询方式返回结果一致): 方式1:业务申请编号查询申请状态; 方式2:申请单号查询申请状态。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_2.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties("applymentId")
public class ApplymentsStatusRequest {
    /**
     * <pre>
     * 字段名:微信支付申请单号
     * 变量名:applyment_id
     * 是否必填:是
     * 类型:uint64
     * 描述:
     *  path申请单的主键,唯一定义此资源的标识。
     *  示例值:2000002124775691
     * </pre>
     */
    @JsonIgnore
    @JsonProperty(value = "applyment_id")
    private String applymentId;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/applyments/ApplymentsStatusRequest1.java
New file
@@ -0,0 +1,35 @@
package com.ruoyi.order.tools.applyments;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商平台通过查询申请状态API查询二级商户入驻申请结果。该查询服务提供两种查询方式(两种查询方式返回结果一致): 方式1:业务申请编号查询申请状态; 方式2:申请单号查询申请状态。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_2.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties("outRequestNo")
public class ApplymentsStatusRequest1 {
    /**
     * <pre>
     * 字段名:业务申请编号
     * 变量名:out_request_no
     * 是否必填:是
     * 类型:string[1,124]
     * 描述:
     *  path1、服务商自定义的商户唯一编号。
     *  2、每个编号对应一个申请单,每个申请单审核通过后会生成一个微信支付商户号。
     *  示例值:APPLYMENT_00000000001
     * </pre>
     */
    @JsonIgnore
    @JsonProperty(value = "out_request_no")
    private String outRequestNo;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/fund/WithdrawExceptionLogRequest.java
New file
@@ -0,0 +1,65 @@
package com.ruoyi.order.tools.request.ecommerce.fund;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商服务商按日查询并下载提现状态为异常的提现单,提现异常包括提现失败和银行退票。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_4.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties("billType")
public class WithdrawExceptionLogRequest {
    /**
     * <pre>
     * 字段名:账单类型
     * 变量名:bill_type
     * 是否必填:是
     * 类型:string[1,8]
     * 描述:
     *  path NO_SUCC:提现异常账单,包括提现失败和提现退票账单。
     *  示例值:NO_SUCC
     * </pre>
     */
    @JsonIgnore
    @JsonProperty(value = "bill_type")
    private String billType;
    /**
     * <pre>
     * 字段名:账单日期
     * 变量名:bill_date
     * 是否必填:是
     * 类型:string[1,10]
     * 描述:
     *   表示所在日期的提现账单,格式为YYYY-MM-DD。
     *  例如:2008-01-01日发起的提现,2008-01-03日银行返回提现失败,则该提现数据将出现在bill_date为2008-01-03日的账单中。
     *  示例值:2019-08-17
     * </pre>
     */
    @JsonProperty(value = "bill_date")
    private String billDate;
    /**
     * <pre>
     * 字段名:压缩格式
     * 变量名:tar_type
     * 是否必填:否
     * 类型:string[1,10]
     * 描述:
     *   不填则默认是数据流
     *  枚举值:
     *  GZIP:返回格式为.gzip的压缩包账单
     *  示例值:GZIP
     * </pre>
     */
    @JsonProperty(value = "tar_type")
    private String tarType;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/fund/WithdrawForPlatformRequest.java
New file
@@ -0,0 +1,91 @@
package com.ruoyi.order.tools.request.ecommerce.fund;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商平台通过该接口可将其平台的收入进行提现
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_5.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class WithdrawForPlatformRequest {
    /**
     * <pre>
     * 字段名:商户提现单号
     * 变量名:out_request_no
     * 是否必填:是
     * 类型:string[1, 32]
     * 描述:
     *  body商户提现单号,由商户自定义生成。
     *  示例值:20190611222222222200002122
     * </pre>
     */
    @JsonProperty(value = "out_request_no")
    private String outRequestNo;
    /**
     * <pre>
     * 字段名:提现金额
     * 变量名:amount
     * 是否必填:是
     * 类型:int64
     * 描述:
     *  body单位:分,金额不能超过8亿元
     *  示例值:1
     * </pre>
     */
    @JsonProperty(value = "amount")
    private Integer amount;
    /**
     * <pre>
     * 字段名:提现备注
     * 变量名:remark
     * 是否必填:否
     * 类型:string[1, 56]
     * 描述:
     *  body商户对提现单的备注。
     *  示例值:交易提现
     * </pre>
     */
    @JsonProperty(value = "remark")
    private String remark;
    /**
     * <pre>
     * 字段名:银行附言
     * 变量名:bank_memo
     * 是否必填:否
     * 类型:string[1, 32]
     * 描述:
     *  body展示在收款银行系统中的附言,由数字、字母、汉字组成(能否成功展示依赖银行系统支持)。
     *  示例值:xx平台提现
     * </pre>
     */
    @JsonProperty(value = "bank_memo")
    private String bankMemo;
    /**
     * <pre>
     * 字段名:出款账户类型
     * 变量名:account_type
     * 是否必填:是
     * 类型:string[1,16]
     * 描述:
     *  body枚举值:
     *  BASIC:基本户
     *  OPERATION:运营账户
     *  FEES:手续费账户
     *  示例值:BASIC
     * </pre>
     */
    @JsonProperty(value = "account_type")
    private String accountType;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/fund/WithdrawForSubMchRequest.java
New file
@@ -0,0 +1,88 @@
package com.ruoyi.order.tools.request.ecommerce.fund;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商平台通过余额提现API帮助二级商户发起账户余额提现申请,完成账户余额提现。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_2.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class WithdrawForSubMchRequest {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1, 32]
     * 描述:
     *  body电商平台二级商户号,由微信支付生成并下发。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:商户提现单号
     * 变量名:out_request_no
     * 是否必填:是
     * 类型:string[1, 32]
     * 描述:
     *  body商户提现单号,由商户自定义生成,必须是字母数字。
     *  示例值:20190611222222222200000000012122
     * </pre>
     */
    @JsonProperty(value = "out_request_no")
    private String outRequestNo;
    /**
     * <pre>
     * 字段名:提现金额
     * 变量名:amount
     * 是否必填:是
     * 类型:int
     * 描述:
     *  body单位:分,金额不能超过8亿元
     *  示例值:1
     * </pre>
     */
    @JsonProperty(value = "amount")
    private Integer amount;
    /**
     * <pre>
     * 字段名:提现备注
     * 变量名:remark
     * 是否必填:否
     * 类型:string[1, 56]
     * 描述:
     *  body商户对提现单的备注,商户自定义字段。
     *  示例值:交易提现
     * </pre>
     */
    @JsonProperty(value = "remark")
    private String remark;
    /**
     * <pre>
     * 字段名:银行附言
     * 变量名:bank_memo
     * 是否必填:否
     * 类型:string[1, 32]
     * 描述:
     *  body展示在收款银行系统中的附言,数字、字母最长32个汉字(能否成功展示依赖银行系统支持)
     *  示例值:微信支付提现
     * </pre>
     */
    @JsonProperty(value = "bank_memo")
    private String bankMemo;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/fund/WithdrawStatusForPlatformRequest.java
New file
@@ -0,0 +1,34 @@
package com.ruoyi.order.tools.request.ecommerce.fund;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商平台通过该接口查询其提现结果,该查询服务提供两种查询方式(两种查询方式返回结果一致): 方式1:微信支付提现单号查询; 方式2:商户提现单号查询。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_6.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties("withdrawId")
public class WithdrawStatusForPlatformRequest {
    /**
     * <pre>
     * 字段名:微信支付提现单号
     * 变量名:withdraw_id
     * 是否必填:是
     * 类型:string[1, 128]
     * 描述:
     *  path电商平台提交二级商户提现申请后,由微信支付返回的申请单号,作为查询申请状态的唯一标识。
     *  示例值:12321937198237912739132791732123
     * </pre>
     */
    @JsonIgnore
    @JsonProperty(value = "withdraw_id")
    private String withdrawId;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/fund/WithdrawStatusForPlatformRequest1.java
New file
@@ -0,0 +1,34 @@
package com.ruoyi.order.tools.request.ecommerce.fund;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商平台通过该接口查询其提现结果,该查询服务提供两种查询方式(两种查询方式返回结果一致): 方式1:微信支付提现单号查询; 方式2:商户提现单号查询。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_6.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties("outRequestNo")
public class WithdrawStatusForPlatformRequest1 {
    /**
     * <pre>
     * 字段名:商户提现单号
     * 变量名:out_request_no
     * 是否必填:是
     * 类型:string[1, 32]
     * 描述:
     *  path商户提现单号,由商户自定义生成。
     *  示例值:20190611222222222200000000012122
     * </pre>
     */
    @JsonIgnore
    @JsonProperty(value = "out_request_no")
    private String outRequestNo;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/fund/WithdrawStatusForSubMchRequest.java
New file
@@ -0,0 +1,49 @@
package com.ruoyi.order.tools.request.ecommerce.fund;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商平台通过查询提现状态API查询二级商户提现单的提现结果。 该查询服务提供两种查询方式(两种查询方式返回结果一致): 方式1:微信支付提现单号查询; 方式2:商户提现单号查询。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_3.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties("subMchid")
public class WithdrawStatusForSubMchRequest {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1, 32]
     * 描述:
     *  电商平台二级商户号,由微信支付生成并下发
     *  示例值:1900000109。
     * </pre>
     */
    @JsonIgnore
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:微信支付提现单号
     * 变量名:withdraw_id
     * 是否必填:是
     * 类型:string[1, 128]
     * 描述:
     *  path电商平台提交二级商户提现申请后,由微信支付返回的申请单号,作为查询申请状态的唯一标识。
     *  示例值:1232193719823791273913279173291279
     * </pre>
     */
    @JsonIgnore
    @JsonProperty(value = "withdraw_id")
    private String withdrawId;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/fund/WithdrawStatusForSubMchRequest1.java
New file
@@ -0,0 +1,48 @@
package com.ruoyi.order.tools.request.ecommerce.fund;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商平台通过查询提现状态API查询二级商户提现单的提现结果。 该查询服务提供两种查询方式(两种查询方式返回结果一致): 方式1:微信支付提现单号查询; 方式2:商户提现单号查询。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_3.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties("outRequestNo")
public class WithdrawStatusForSubMchRequest1 {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1, 32]
     * 描述:
     *  电商平台二级商户号,由微信支付生成并下发。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:商户提现单号
     * 变量名:out_request_no
     * 是否必填:是
     * 类型:string[1, 32]
     * 描述:
     *  path商户提现单号,由商户自定义生成
     *  示例值:20190611222222222200
     * </pre>
     */
    @JsonIgnore
    @JsonProperty(value = "out_request_no")
    private String outRequestNo;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/profitsharing/ProfitSharingAddReceiverRequest.java
New file
@@ -0,0 +1,117 @@
package com.ruoyi.order.tools.request.ecommerce.profitsharing;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 1. 电商平台可通过此接口添加分账接收方,建立分账接收方列表。后续通过发起分账请求,将电商平台下的二级商户结算后的资金,分给分账接收方列表中具体的分账接收方。 2. 添加的分账接收方统一都在电商平台维度进行管理,其他二级商户,均可向该分账接收方列表中的接收方进行分账,避免在二级商户维度重复维护。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_7.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ProfitSharingAddReceiverRequest {
    /**
     * <pre>
     * 字段名:公众账号ID
     * 变量名:appid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 电商平台的appid(公众号APPID或者小程序APPID)
     *  示例值:wx8888888888888888
     * </pre>
     */
    @JsonProperty(value = "appid")
    private String appid;
    /**
     * <pre>
     * 字段名:接收方类型
     * 变量名:type
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 分账接收方的类型,枚举值:
     *  MERCHANT_ID:商户
     *  PERSONAL_OPENID:个人
     *  示例值:MERCHANT_ID
     * </pre>
     */
    @JsonProperty(value = "type")
    private String type;
    /**
     * <pre>
     * 字段名:接收方账号
     * 变量名:account
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  body 分账接收方的账号
     *  类型是MERCHANT_ID时,是商户号
     *  类型是PERSONAL_OPENID时,是个人openid,openid获取方法
     *  示例值:190001001
     * </pre>
     */
    @JsonProperty(value = "account")
    private String account;
    /**
     * <pre>
     * 字段名:接收方名称
     * 变量名:name
     * 是否必填:条件选填
     * 类型:string[1,256]
     * 描述:
     *  body 分账接收方的名称,当type为MERCHANT_ID时,接收方名称是商户全称。
     *  示例值:张三网络公司
     * </pre>
     */
    @JsonProperty(value = "name")
    private String name;
    /**
     * <pre>
     * 字段名:接收方名称的密文
     * 变量名:encrypted_name
     * 是否必填:否
     * 类型:string[1,10240]
     * 描述:
     *  body 1、分账接收方类型是PERSONAL_OPENID时,是个人姓名的密文(选传,传则校验)
     *  此字段的加密的方式为:
     *  2、使用微信支付平台证书中的公钥
     *  3、使用RSAES-OAEP算法进行加密
     *  4、将请求中HTTP头部的Wechatpay-Serial设置为证书序列号
     *  字段加密: 使用APIv3定义的方式加密
     *  示例值:hu89ohu89ohu89o
     * </pre>
     */
    @JsonProperty(value = "encrypted_name")
    private String encryptedName;
    /**
     * <pre>
     * 字段名:与分账方的关系类型
     * 变量名:relation_type
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 子商户与接收方的关系。
     *  枚举值:
     *  SUPPLIER:供应商
     *  DISTRIBUTOR:分销商
     *  SERVICE_PROVIDER:服务商
     *  PLATFORM:平台
     *  OTHERS:其他
     *  示例值:SUPPLIER
     * </pre>
     */
    @JsonProperty(value = "relation_type")
    private String relationType;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/profitsharing/ProfitSharingApplyRequest.java
New file
@@ -0,0 +1,188 @@
package com.ruoyi.order.tools.request.ecommerce.profitsharing;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
 * <pre>
 * 微信订单支付成功后,由电商平台发起分账请求,将结算后的资金分给分账接收方。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_1.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ProfitSharingApplyRequest {
    /**
     * <pre>
     * 字段名:公众账号ID
     * 变量名:appid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 电商平台的appid(公众号APPID或者小程序APPID)。
     *  示例值:wx8888888888888888
     * </pre>
     */
    @JsonProperty(value = "appid")
    private String appid;
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 分账出资的电商平台二级商户,填写微信支付分配的商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:微信订单号
     * 变量名:transaction_id
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 微信支付订单号。
     *  示例值: 4208450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "transaction_id")
    private String transactionId;
    /**
     * <pre>
     * 字段名:商户分账单号
     * 变量名:out_order_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  body 商户系统内部的分账单号,在商户系统内部唯一(单次分账、多次分账、完结分账应使用不同的商户分账单号),同一分账单号多次请求等同一次。
     *  示例值:P20150806125346
     * </pre>
     */
    @JsonProperty(value = "out_order_no")
    private String outOrderNo;
    /**
     * <pre>
     * 字段名:+分账接收方列表
     * 变量名:receivers
     * 是否必填:是
     * 类型:array
     * 描述:body 分账接收方列表,支持设置出资商户作为分账接收方,单次分账最多可有5个分账接收方
     * </pre>
     */
    @JsonProperty(value = "receivers")
    private List<Receivers> receivers;
    /**
     * <pre>
     * 字段名:是否分账完成
     * 变量名:finish
     * 是否必填:是
     * 类型:boolean
     * 描述:
     *  body 是否完成分账
     *  1、如果为true,该笔订单剩余未分账的金额会解冻回电商平台二级商户;
     *  2、如果为false,该笔订单剩余未分账的金额不会解冻回电商平台二级商户,可以对该笔订单再次进行分账。
     *  示例值:true
     * </pre>
     */
    @JsonProperty(value = "finish")
    private Boolean finish;
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class Receivers {
        /**
         * <pre>
         * 字段名:分账接收方类型
         * 变量名:type
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  分账接收方类型,枚举值:
         *  MERCHANT_ID:商户
         *  PERSONAL_OPENID:个人
         *  示例值:MERCHANT_ID
         * </pre>
         */
        @JsonProperty(value = "type")
        private String type;
        /**
         * <pre>
         * 字段名:分账接收方账号
         * 变量名:receiver_account
         * 是否必填:是
         * 类型:string[1,64]
         * 描述:
         *  分账接收方账号:
         *  类型是MERCHANT_ID时,是商户号(mch_id或者sub_mch_id)
         *  类型是PERSONAL_OPENID时,是个人openid,openid获取方法
         *  示例值:1900000109
         * </pre>
         */
        @JsonProperty(value = "receiver_account")
        private String receiverAccount;
        /**
         * <pre>
         * 字段名:分账金额
         * 变量名:amount
         * 是否必填:是
         * 类型:int
         * 描述:
         *  分账金额,单位为分,只能为整数,不能超过原订单支付金额及最大分账比例金额。
         *  示例值:190
         * </pre>
         */
        @JsonProperty(value = "amount")
        private Integer amount;
        /**
         * <pre>
         * 字段名:分账描述
         * 变量名:description
         * 是否必填:是
         * 类型:string[1,80]
         * 描述:
         *  分账的原因描述,分账账单中需要体现。
         *  示例值:分给商户1900000109
         * </pre>
         */
        @JsonProperty(value = "description")
        private String description;
        /**
         * <pre>
         * 字段名:分账个人姓名
         * 变量名:receiver_name
         * 是否必填:条件选填
         * 类型:string[1, 10240]
         * 描述:
         *  可选项,在接收方类型为个人的时可选填,若有值,会检查与 receiver_name 是否实名匹配,不匹配会拒绝分账请求
         *  1、分账接收方类型是PERSONAL_OPENID时,是个人姓名的密文(选传,传则校验) 此字段的加密方法详见:敏感信息加密说明
         *  2、使用微信支付平台证书中的公钥
         *  3、使用RSAES-OAEP算法进行加密
         *  4、将请求中HTTP头部的Wechatpay-Serial设置为证书序列号
         *  示例值:hu89ohu89ohu89o
         * </pre>
         */
        @JsonProperty(value = "receiver_name")
        private String receiverName;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/profitsharing/ProfitSharingFinishRequest.java
New file
@@ -0,0 +1,74 @@
package com.ruoyi.order.tools.request.ecommerce.profitsharing;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 不需要进行分账的订单,可直接调用本接口将订单的金额全部解冻给二级商户。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_5.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ProfitSharingFinishRequest {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 分账出资的电商平台二级商户,填写微信支付分配的商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:微信订单号
     * 变量名:transaction_id
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 微信支付订单号。
     *  示例值: 4208450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "transaction_id")
    private String transactionId;
    /**
     * <pre>
     * 字段名:商户分帐单号
     * 变量名:out_order_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  body 商户系统内部的分账单号,在商户系统内部唯一(单次分账、多次分账、完结分账应使用不同的商户分账单号),同一分账单号多次请求等同一次。
     *  示例值:P20150806125346
     * </pre>
     */
    @JsonProperty(value = "out_order_no")
    private String outOrderNo;
    /**
     * <pre>
     * 字段名:分账描述
     * 变量名:description
     * 是否必填:是
     * 类型:string[1,80]
     * 描述:
     *  body 分账的原因描述,分账账单中需要体现。
     *  示例值:分账完结
     * </pre>
     */
    @JsonProperty(value = "description")
    private String description;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/profitsharing/ProfitSharingNotifyRequest.java
New file
@@ -0,0 +1,181 @@
package com.ruoyi.order.tools.request.ecommerce.profitsharing;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 1、此功能仅针对分账接收方。 2、分账动账金额变动后,微信会把相关变动结果发送给需要实时关注的分账接收方。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_6.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ProfitSharingNotifyRequest {
    /**
     * <pre>
     * 字段名:通知ID
     * 变量名:id
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  通知的唯一ID
     *  示例值:EV-2018022511223320873
     * </pre>
     */
    @JsonProperty(value = "id")
    private String id;
    /**
     * <pre>
     * 字段名:通知创建时间
     * 变量名:create_time
     * 是否必填:是
     * 类型:string[1,16]
     * 描述:
     *  通知创建的时间,遵循rfc3339标准格式
     *  格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒。
     *  示例值:2018-06-08T10:34:56+08:00
     * </pre>
     */
    @JsonProperty(value = "create_time")
    private String createTime;
    /**
     * <pre>
     * 字段名:通知类型
     * 变量名:event_type
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  通知的类型:
     *  TRANSACTION.SUCCESS:分账
     *  TRANSACTION.SUCCESS:分账回退
     *  示例值:TRANSACTION.SUCCESS
     * </pre>
     */
    @JsonProperty(value = "event_type")
    private String eventType;
    /**
     * <pre>
     * 字段名:通知简要说明
     * 变量名:summary
     * 是否必填:是
     * 类型:string[1,16]
     * 描述:
     *  通知简要说明
     *  示例值:分账
     * </pre>
     */
    @JsonProperty(value = "summary")
    private String summary;
    /**
     * <pre>
     * 字段名:通知数据类型
     * 变量名:resource_type
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  通知的资源数据类型,通知为encrypt-resource
     *  示例值:encrypt-resource
     * </pre>
     */
    @JsonProperty(value = "resource_type")
    private String resourceType;
    /**
     * <pre>
     * 字段名:+通知数据
     * 变量名:resource
     * 是否必填:是
     * 类型:object
     * 描述:
     *  通知资源数据
     *  json格式,见示例
     * </pre>
     */
    @JsonProperty(value = "resource")
    private Resource resource;
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class Resource {
        /**
         * <pre>
         * 字段名:加密算法类型
         * 变量名:algorithm
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  对开启结果数据进行加密的加密算法,目前只支持AEAD_AES_256_GCM
         *  示例值:AEAD_AES_256_GCM
         * </pre>
         */
        @JsonProperty(value = "algorithm")
        private String algorithm;
        /**
         * <pre>
         * 字段名:加密前的对象类型
         * 变量名:original_type
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  加密前的对象类型,分账动账通知的类型为profitsharing
         *  示例值:profitsharing
         * </pre>
         */
        @JsonProperty(value = "original_type")
        private String originalType;
        /**
         * <pre>
         * 字段名:数据密文
         * 变量名:ciphertext
         * 是否必填:是
         * 类型:string[1,1048576]
         * 描述:
         *  Base64编码后的开启/停用结果数据密文
         *  示例值:fdasFDGAWDWflkja484w
         * </pre>
         */
        @JsonProperty(value = "ciphertext")
        private String ciphertext;
        /**
         * <pre>
         * 字段名:附加数据
         * 变量名:associated_data
         * 是否必填:否
         * 类型:string[1,16]
         * 描述:
         *  附加数据
         *  示例值:adsacfseewfsdSFDS
         * </pre>
         */
        @JsonProperty(value = "associated_data")
        private String associatedData;
        /**
         * <pre>
         * 字段名:随机串
         * 变量名:nonce
         * 是否必填:是
         * 类型:string[1,16]
         * 描述:
         *  加密使用的随机串
         *  示例值:fdasflkja484w
         * </pre>
         */
        @JsonProperty(value = "nonce")
        private String nonce;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/profitsharing/ProfitSharingNotifyRequest1.java
New file
@@ -0,0 +1,200 @@
package com.ruoyi.order.tools.request.ecommerce.profitsharing;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
 * <pre>
 * 1、此功能仅针对分账接收方。 2、分账动账金额变动后,微信会把相关变动结果发送给需要实时关注的分账接收方。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_6.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ProfitSharingNotifyRequest1 {
    /**
     * <pre>
     * 字段名:直连商户号
     * 变量名:mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  直连模式分账发起和出资商户。
     *  注意:适用于直联商户模式
     *  示例值:1900000100
     * </pre>
     */
    @JsonProperty(value = "mchid")
    private String mchid;
    /**
     * <pre>
     * 字段名:服务商商户号
     * 变量名:sp_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  服务商模式分账发起商户。
     *  注意:适用于电商服务商 服务商模式
     *  示例值:1900000100
     * </pre>
     */
    @JsonProperty(value = "sp_mchid")
    private String spMchid;
    /**
     * <pre>
     * 字段名:子商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  服务商模式分账出资商户。
     *  注意:适用于电商服务商 服务商模式
     *  示例值:1900000100
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:微信订单号
     * 变量名:transaction_id
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  微信支付订单号。
     *  示例值: 4200000000000000000000000000
     * </pre>
     */
    @JsonProperty(value = "transaction_id")
    private String transactionId;
    /**
     * <pre>
     * 字段名:微信分账/回退单号
     * 变量名:order_id
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  微信分账/回退单号。
     *  示例值: 1217752501201407033233368018
     * </pre>
     */
    @JsonProperty(value = "order_id")
    private String orderId;
    /**
     * <pre>
     * 字段名:商户分账/回退单号
     * 变量名:out_order_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  分账方系统内部的分账/回退单号。
     *  示例值:P20150806125346
     * </pre>
     */
    @JsonProperty(value = "out_order_no")
    private String outOrderNo;
    /**
     * <pre>
     * 字段名:+分账接收方列表
     * 变量名:receivers
     * 是否必填:是
     * 类型:array
     * 描述:分账接收方对象
     * </pre>
     */
    @JsonProperty(value = "receivers")
    private List<Receivers> receivers;
    /**
     * <pre>
     * 字段名:成功时间
     * 变量名:success_time
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  成功时间,遵循rfc3339标准
     *  格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒。
     *  示例值:2018-06-08T10:34:56+08:00
     * </pre>
     */
    @JsonProperty(value = "success_time")
    private String successTime;
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class Receivers {
        /**
         * <pre>
         * 字段名:分账接收方类型
         * 变量名:type
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  分账接收方的类型,枚举值:
         *  MERCHANT_ID:商户
         *  PERSONAL_OPENID:个人
         *  示例值:MERCHANT_ID
         * </pre>
         */
        @JsonProperty(value = "type")
        private String type;
        /**
         * <pre>
         * 字段名:分账接收方账号
         * 变量名:account
         * 是否必填:是
         * 类型:string[1,64]
         * 描述:
         *  分账接收方的账号
         *  类型是MERCHANT_ID时,是商户号
         *  类型是PERSONAL_OPENID时,是个人openid
         *  示例值:190001001
         * </pre>
         */
        @JsonProperty(value = "account")
        private String account;
        /**
         * <pre>
         * 字段名:分账动账金额
         * 变量名:amount
         * 是否必填:是
         * 类型:int
         * 描述:
         *  分账动账金额,单位为分,只能为整数。
         *  示例值:888
         * </pre>
         */
        @JsonProperty(value = "amount")
        private Integer amount;
        /**
         * <pre>
         * 字段名:分账/回退描述
         * 变量名:description
         * 是否必填:是
         * 类型:string[1,80]
         * 描述:
         *  分账/回退描述
         *  示例值:运费/交易分账/及时奖励
         * </pre>
         */
        @JsonProperty(value = "description")
        private String description;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/profitsharing/ProfitSharingQueryApplyRequest.java
New file
@@ -0,0 +1,60 @@
package com.ruoyi.order.tools.request.ecommerce.profitsharing;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 发起分账请求后,可调用此接口查询分账结果 ;发起分账完结请求后,可调用此接口查询分账完结的结果
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_2.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ProfitSharingQueryApplyRequest {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *   分账出资的电商平台二级商户,填写微信支付分配的商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:微信订单号
     * 变量名:transaction_id
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *   微信支付订单号。
     *  示例值: 4208450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "transaction_id")
    private String transactionId;
    /**
     * <pre>
     * 字段名:商户分账单号
     * 变量名:out_order_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *   商户系统内部的分账单号,在商户系统内部唯一(单次分账、多次分账、完结分账应使用不同的商户分账单号),同一分账单号多次请求等同一次。
     *  示例值:P20150806125346
     * </pre>
     */
    @JsonProperty(value = "out_order_no")
    private String outOrderNo;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/profitsharing/ProfitSharingQueryRefundRequest.java
New file
@@ -0,0 +1,72 @@
package com.ruoyi.order.tools.request.ecommerce.profitsharing;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 商户需要核实回退结果,可调用此接口查询回退结果;如果分账回退接口返回状态为处理中,可调用此接口查询回退结果
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_4.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ProfitSharingQueryRefundRequest {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *   分账回退的接收商户,对应原分账出资的电商平台二级商户,填写微信支付分配的商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:微信分账单号
     * 变量名:order_id
     * 是否必填:二选一
     * 类型:string[1,64]
     * 描述:
     *   微信分账单号,微信系统返回的唯一标识。微信分账单号和商户分账单号二选一填写。
     *  示例值: 3008450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "order_id")
    private String orderId;
    /**
     * <pre>
     * 字段名:商户分账单号
     * 变量名:out_order_no
     * 是否必填: 原发起分账请求时使用的商户系统内部的分账单号。微信分账单号与商户分账单号二选一填写。 示例值:P20150806125346
     * 类型:string[1,64]
     * 描述:
     * </pre>
     */
    @JsonProperty(value = "out_order_no")
    private String outOrderNo;
    /**
     * <pre>
     * 字段名:商户回退单号
     * 变量名:out_return_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  调用回退接口提供的商户系统内部的回退单号
     *  示例值:R20190516001
     * </pre>
     */
    @JsonProperty(value = "out_return_no")
    private String outReturnNo;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/profitsharing/ProfitSharingRefundRequest.java
New file
@@ -0,0 +1,114 @@
package com.ruoyi.order.tools.request.ecommerce.profitsharing;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 订单已经分账,在退款时,可以先调此接口,将已分账的资金从分账接收方的账户回退给分账方,再发起退款。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_3.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ProfitSharingRefundRequest {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 分账出资的电商平台二级商户,填写微信支付分配的商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:微信分账单号
     * 变量名:order_id
     * 是否必填:二选一
     * 类型:string[1,64]
     * 描述:
     *  body 微信分账单号,微信系统返回的唯一标识。微信分账单号和商户分账单号二选一填写。
     *  示例值:3008450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "order_id")
    private String orderId;
    /**
     * <pre>
     * 字段名:商户分账单号
     * 变量名:out_order_no
     * 是否必填:body 商户系统内部的分账单号,在商户系统内部唯一(单次分账、多次分账、完结分账应使用不同的商户分账单号),同一分账单号多次请求等同一次。 示例值:P20150806125346
     * 类型:string[1,64]
     * 描述:
     * </pre>
     */
    @JsonProperty(value = "out_order_no")
    private String outOrderNo;
    /**
     * <pre>
     * 字段名:商户回退单号
     * 变量名:out_return_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  body 此回退单号是商户在自己后台生成的一个新的回退单号,在商户后台唯一。
     *  示例值:R20190516001
     * </pre>
     */
    @JsonProperty(value = "out_return_no")
    private String outReturnNo;
    /**
     * <pre>
     * 字段名:回退商户号
     * 变量名:return_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 只能对原分账请求中成功分给商户接收方进行回退。
     *  示例值:86693852
     * </pre>
     */
    @JsonProperty(value = "return_mchid")
    private String returnMchid;
    /**
     * <pre>
     * 字段名:回退金额
     * 变量名:amount
     * 是否必填:是
     * 类型:int
     * 描述:
     *  body 需要从分账接收方回退的金额,单位为分,只能为整数,不能超过原始分账单分出给该接收方的金额。
     *  示例值:10
     * </pre>
     */
    @JsonProperty(value = "amount")
    private Integer amount;
    /**
     * <pre>
     * 字段名:回退描述
     * 变量名:description
     * 是否必填:是
     * 类型:string[1,80]
     * 描述:
     *  body 分账回退的原因描述
     *  示例值:分账回退
     * </pre>
     */
    @JsonProperty(value = "description")
    private String description;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/profitsharing/ProfitSharingRemoveReceiverRequest.java
New file
@@ -0,0 +1,64 @@
package com.ruoyi.order.tools.request.ecommerce.profitsharing;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商平台发起删除分账接收方请求。删除后,不支持将电商平台下二级商户结算后的资金,分到该分账接收方。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_8.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ProfitSharingRemoveReceiverRequest {
    /**
     * <pre>
     * 字段名:公众账号ID
     * 变量名:appid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 电商平台的appid(公众号APPID或者小程序APPID)
     *  示例值:wx8888888888888888
     * </pre>
     */
    @JsonProperty(value = "appid")
    private String appid;
    /**
     * <pre>
     * 字段名:接收方类型
     * 变量名:type
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 分账接收方的类型,枚举值:
     *  MERCHANT_ID:商户
     *  PERSONAL_OPENID:个人
     *  示例值:MERCHANT_ID
     * </pre>
     */
    @JsonProperty(value = "type")
    private String type;
    /**
     * <pre>
     * 字段名:接收方账号
     * 变量名:account
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  body 分账接收方的账号
     *  类型是MERCHANT_ID时,是商户号
     *  类型是PERSONAL_OPENID时,是个人openid,openid获取方法
     *  示例值:190001001
     * </pre>
     */
    @JsonProperty(value = "account")
    private String account;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/refunds/RefundApplyRequest.java
New file
@@ -0,0 +1,189 @@
package com.ruoyi.order.tools.request.ecommerce.refunds;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,微信支付将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家账号上。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/refunds/chapter3_1.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class RefundApplyRequest {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 微信支付分配二级商户的商户号。
     *  示例值: 1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:电商平台APPID
     * 变量名:sp_appid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 电商平台在微信公众平台申请服务号对应的APPID,申请商户功能的时候微信支付会配置绑定关系。
     *  示例值:wx8888888888888888
     * </pre>
     */
    @JsonProperty(value = "sp_appid")
    private String spAppid;
    /**
     * <pre>
     * 字段名:二级商户APPID
     * 变量名:sub_appid
     * 是否必填:否
     * 类型:string[1,32]
     * 描述:
     *  body 二级商户在微信申请公众号成功后分配的账号ID,需要电商平台侧配置绑定关系才能传参(即二级商户已绑定微信公众号时传入)。
     *  示例值:wx8888888888888888
     * </pre>
     */
    @JsonProperty(value = "sub_appid")
    private String subAppid;
    /**
     * <pre>
     * 字段名:微信订单号
     * 变量名:transaction_id
     * 是否必填:二选一
     * 类型:string[1,32]
     * 描述:
     *  body 原支付交易对应的微信订单号。
     *  示例值:1217752501201407033233368018
     * </pre>
     */
    @JsonProperty(value = "transaction_id")
    private String transactionId;
    /**
     * <pre>
     * 字段名:商户订单号
     * 变量名:out_trade_no
     * 是否必填:body 原支付交易对应的商户订单号。 示例值:1217752501201407033233368018
     * 类型:string[1,32]
     * 描述:
     * </pre>
     */
    @JsonProperty(value = "out_trade_no")
    private String outTradeNo;
    /**
     * <pre>
     * 字段名:商户退款单号
     * 变量名:out_refund_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  body 商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@,同一退款单号多次请求只退一笔。
     *  示例值:1217752501201407033233368018
     * </pre>
     */
    @JsonProperty(value = "out_refund_no")
    private String outRefundNo;
    /**
     * <pre>
     * 字段名:退款原因
     * 变量名:reason
     * 是否必填:否
     * 类型:string[1,80]
     * 描述:
     *  body 若商户传入,会在下发给用户的退款消息中体现退款原因。
     *  注意:若订单退款金额≤1元,且属于部分退款,则不会在退款消息中体现退款原因
     *  示例值:商品已售完
     * </pre>
     */
    @JsonProperty(value = "reason")
    private String reason;
    /**
     * <pre>
     * 字段名:+订单金额
     * 变量名:amount
     * 是否必填:是
     * 类型:object
     * 描述:body 订单金额信息
     * </pre>
     */
    @JsonProperty(value = "amount")
    private Amount amount;
    /**
     * <pre>
     * 字段名:退款结果回调url
     * 变量名:notify_url
     * 是否必填:否
     * 类型:string[1,256]
     * 描述:
     *  body 异步接收微信支付退款结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。 如果参数中传了notify_url,则商户平台上配置的回调地址将不会生效,优先回调当前传的地址。
     *  示例值:https://weixin.qq.com
     * </pre>
     */
    @JsonProperty(value = "notify_url")
    private String notifyUrl;
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class Amount {
        /**
         * <pre>
         * 字段名:退款金额
         * 变量名:refund
         * 是否必填:是
         * 类型:int
         * 描述:
         *  退款金额,币种的最小单位,只能为整数,不能超过原订单支付金额。
         *  示例值:888
         * </pre>
         */
        @JsonProperty(value = "refund")
        private Integer refund;
        /**
         * <pre>
         * 字段名:原订单金额
         * 变量名:total
         * 是否必填:是
         * 类型:int
         * 描述:
         *  原支付交易的订单总金额,币种的最小单位,只能为整数。
         *  示例值:888
         * </pre>
         */
        @JsonProperty(value = "total")
        private Integer total;
        /**
         * <pre>
         * 字段名:退款币种
         * 变量名:currency
         * 是否必填:是
         * 类型:string[1,18]
         * 描述:
         *  符合ISO 4217标准的三位字母代码,目前只支持人民币:CNY。
         *  示例值:CNY
         * </pre>
         */
        @JsonProperty(value = "currency")
        private String currency;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/refunds/RefundNotifyRequest.java
New file
@@ -0,0 +1,181 @@
package com.ruoyi.order.tools.request.ecommerce.refunds;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 退款状态改变后,微信会把相关退款结果发送给商户。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/refunds/chapter3_3.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class RefundNotifyRequest {
    /**
     * <pre>
     * 字段名:通知ID
     * 变量名:id
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  通知的唯一ID
     *  示例值:EV-2018022511223320873
     * </pre>
     */
    @JsonProperty(value = "id")
    private String id;
    /**
     * <pre>
     * 字段名:通知创建时间
     * 变量名:create_time
     * 是否必填:是
     * 类型:string[1,16]
     * 描述:
     *  通知创建的时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日13点29分35秒。
     *  示例值:2018-06-08T10:34:56+08:00
     * </pre>
     */
    @JsonProperty(value = "create_time")
    private String createTime;
    /**
     * <pre>
     * 字段名:通知类型
     * 变量名:event_type
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  通知的类型:
     *  REFUND.SUCCESS:退款成功通知
     *  REFUND.ABNORMAL:退款异常通知
     *  REFUND.CLOSED:退款关闭通知
     *  示例值:REFUND.SUCCESS
     * </pre>
     */
    @JsonProperty(value = "event_type")
    private String eventType;
    /**
     * <pre>
     * 字段名:通知简要说明
     * 变量名:summary
     * 是否必填:是
     * 类型:string[1,16]
     * 描述:
     *  通知简要说明
     *  示例值:退款成功
     * </pre>
     */
    @JsonProperty(value = "summary")
    private String summary;
    /**
     * <pre>
     * 字段名:通知数据类型
     * 变量名:resource_type
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  通知的资源数据类型,支付成功通知为encrypt-resource
     *  示例值:encrypt-resource
     * </pre>
     */
    @JsonProperty(value = "resource_type")
    private String resourceType;
    /**
     * <pre>
     * 字段名:+通知数据
     * 变量名:resource
     * 是否必填:是
     * 类型:object
     * 描述:
     *  通知资源数据
     *  json格式,见示例
     * </pre>
     */
    @JsonProperty(value = "resource")
    private Resource resource;
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class Resource {
        /**
         * <pre>
         * 字段名:加密算法类型
         * 变量名:algorithm
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  对开启结果数据进行加密的加密算法,目前只支持AEAD_AES_256_GCM
         *  示例值:AEAD_AES_256_GCM
         * </pre>
         */
        @JsonProperty(value = "algorithm")
        private String algorithm;
        /**
         * <pre>
         * 字段名:加密前的对象类型
         * 变量名:original_type
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  加密前的对象类型,退款通知的类型为refund
         *  示例值:refund
         * </pre>
         */
        @JsonProperty(value = "original_type")
        private String originalType;
        /**
         * <pre>
         * 字段名:数据密文
         * 变量名:ciphertext
         * 是否必填:是
         * 类型:string[1,1048576]
         * 描述:
         *  Base64编码后的开启/停用结果数据密文
         *  示例值:fdasfsadsadsalkja484w
         * </pre>
         */
        @JsonProperty(value = "ciphertext")
        private String ciphertext;
        /**
         * <pre>
         * 字段名:附加数据
         * 变量名:associated_data
         * 是否必填:否
         * 类型:string[1,16]
         * 描述:
         *  附加数据
         *  示例值:fdasdsadsafcsflkja484w
         * </pre>
         */
        @JsonProperty(value = "associated_data")
        private String associatedData;
        /**
         * <pre>
         * 字段名:随机串
         * 变量名:nonce
         * 是否必填:是
         * 类型:string[1,16]
         * 描述:
         *  加密使用的随机串
         *  示例值:fdasfjihihihlkja484w
         * </pre>
         */
        @JsonProperty(value = "nonce")
        private String nonce;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/refunds/RefundNotifyRequest1.java
New file
@@ -0,0 +1,226 @@
package com.ruoyi.order.tools.request.ecommerce.refunds;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 退款状态改变后,微信会把相关退款结果发送给商户。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/refunds/chapter3_3.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class RefundNotifyRequest1 {
    /**
     * <pre>
     * 字段名:电商平台商户号
     * 变量名:sp_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  微信支付分配给电商平台的商户号
     *  示例值:1900000100
     * </pre>
     */
    @JsonProperty(value = "sp_mchid")
    private String spMchid;
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  微信支付分配给二级商户的商户号
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:商户订单号
     * 变量名:out_trade_no
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  返回的商户订单号
     *  示例值: 1217752501201407033233368018
     * </pre>
     */
    @JsonProperty(value = "out_trade_no")
    private String outTradeNo;
    /**
     * <pre>
     * 字段名:微信订单号
     * 变量名:transaction_id
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  微信支付订单号
     *  示例值: 1217752501201407033233368018
     * </pre>
     */
    @JsonProperty(value = "transaction_id")
    private String transactionId;
    /**
     * <pre>
     * 字段名:商户退款单号
     * 变量名:out_refund_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  商户退款单号
     *  示例值: 1217752501201407033233368018
     * </pre>
     */
    @JsonProperty(value = "out_refund_no")
    private String outRefundNo;
    /**
     * <pre>
     * 字段名:微信退款单号
     * 变量名:refund_id
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  微信退款单号
     *  示例值: 1217752501201407033233368018
     * </pre>
     */
    @JsonProperty(value = "refund_id")
    private String refundId;
    /**
     * <pre>
     * 字段名:退款状态
     * 变量名:refund_status
     * 是否必填:是
     * 类型:string[1,16]
     * 描述:
     *  退款状态,枚举值:
     *  SUCCESS:退款成功
     *  CLOSE:退款关闭
     *  ABNORMAL:退款异常,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往【服务商平台—>交易中心】,手动处理此笔退款
     *  示例值:SUCCESS
     * </pre>
     */
    @JsonProperty(value = "refund_status")
    private String refundStatus;
    /**
     * <pre>
     * 字段名:退款成功时间
     * 变量名:success_time
     * 是否必填:否
     * 类型:string[1,64]
     * 描述:
     *  1、退款成功时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日13点29分35秒。
     *  2、当退款状态为退款成功时返回此参数。
     *  示例值:2018-06-08T10:34:56+08:00
     * </pre>
     */
    @JsonProperty(value = "success_time")
    private String successTime;
    /**
     * <pre>
     * 字段名:退款入账账户
     * 变量名:user_received_account
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  取当前退款单的退款入账方。
     *  退回银行卡:{银行名称}{卡类型}{卡尾号}
     *  退回支付用户零钱: 支付用户零钱
     *  退还商户: 商户基本账户、商户结算银行账户
     *  退回支付用户零钱通:支付用户零钱通
     *  示例值:招商银行信用卡0403
     * </pre>
     */
    @JsonProperty(value = "user_received_account")
    private String userReceivedAccount;
    /**
     * <pre>
     * 字段名:+金额信息
     * 变量名:amount
     * 是否必填:是
     * 类型:object
     * 描述:金额信息
     * </pre>
     */
    @JsonProperty(value = "amount")
    private Amount amount;
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class Amount {
        /**
         * <pre>
         * 字段名:订单金额
         * 变量名:total
         * 是否必填:是
         * 类型:int
         * 描述:
         *  订单总金额,单位为分,只能为整数,详见支付金额
         *  示例值:999
         * </pre>
         */
        @JsonProperty(value = "total")
        private Integer total;
        /**
         * <pre>
         * 字段名:退款金额
         * 变量名:refund
         * 是否必填:是
         * 类型:int
         * 描述:
         *  退款金额,币种的最小单位,只能为整数,不能超过原订单支付金额,如果有使用券,后台会按比例退。
         *  示例值:999
         * </pre>
         */
        @JsonProperty(value = "refund")
        private Integer refund;
        /**
         * <pre>
         * 字段名:用户支付金额
         * 变量名:payer_total
         * 是否必填:是
         * 类型:int
         * 描述:
         *  用户实际支付金额,单位为分,只能为整数,详见支付金额
         *  示例值:999
         * </pre>
         */
        @JsonProperty(value = "payer_total")
        private Integer payerTotal;
        /**
         * <pre>
         * 字段名:用户退款金额
         * 变量名:payer_refund
         * 是否必填:是
         * 类型:int
         * 描述:
         *  退款给用户的金额,不包含所有优惠券金额
         *  示例值:999
         * </pre>
         */
        @JsonProperty(value = "payer_refund")
        private Integer payerRefund;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/refunds/RefundQueryStatusRequest.java
New file
@@ -0,0 +1,48 @@
package com.ruoyi.order.tools.request.ecommerce.refunds;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 提交退款申请后,通过调用该接口查询退款状态。该查询服务提供两种查询方式(两种查询方式返回结果一致): 方式1:通过微信支付退款单号查询退款; 方式2:通过商户退款单号查询退款。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/refunds/chapter3_2.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties("refundId")
public class RefundQueryStatusRequest {
    /**
     * <pre>
     * 字段名:微信退款单号
     * 变量名:refund_id
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  path 退款单的主键,唯一定义此资源的标识。
     *  示例值: 50000000382019052709732678859
     * </pre>
     */
    @JsonIgnore
    @JsonProperty(value = "refund_id")
    private String refundId;
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *   微信支付分配给二级商户的商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/refunds/RefundQueryStatusRequest1.java
New file
@@ -0,0 +1,48 @@
package com.ruoyi.order.tools.request.ecommerce.refunds;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 提交退款申请后,通过调用该接口查询退款状态。该查询服务提供两种查询方式(两种查询方式返回结果一致): 方式1:通过微信支付退款单号查询退款; 方式2:通过商户退款单号查询退款。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/refunds/chapter3_2.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties("outRefundNo")
public class RefundQueryStatusRequest1 {
    /**
     * <pre>
     * 字段名:商户退款单号
     * 变量名:out_refund_no
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  path 商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔。
     *  示例值: 1217752501201407033233368018
     * </pre>
     */
    @JsonIgnore
    @JsonProperty(value = "out_refund_no")
    private String outRefundNo;
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *   微信支付分配给二级商户的商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/subsidies/SubsidiesCancelRequest.java
New file
@@ -0,0 +1,60 @@
package com.ruoyi.order.tools.request.ecommerce.subsidies;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 对带有补差标识的订单,如果不需要补差,可在发起分账前,可调用这个接口进行取消补差。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/subsidies/chapter3_3.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class SubsidiesCancelRequest {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 补差的电商平台二级商户,填写微信支付分配的商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:微信订单号
     * 变量名:transaction_id
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  body 微信支付订单号。
     *  示例值: 4208450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "transaction_id")
    private String transactionId;
    /**
     * <pre>
     * 字段名:取消补差描述
     * 变量名:description
     * 是否必填:是
     * 类型:string[1,80]
     * 描述:
     *  body 取消补差描述,查询的时候原样带回。
     *  示例值:订单退款
     * </pre>
     */
    @JsonProperty(value = "description")
    private String description;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/subsidies/SubsidiesCreateRequest.java
New file
@@ -0,0 +1,89 @@
package com.ruoyi.order.tools.request.ecommerce.subsidies;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 服务商下单的时候带上补差标识,微信订单支付成功并结算完成后,发起分账前,调用该口进行补差。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/subsidies/chapter3_1.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class SubsidiesCreateRequest {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 补差的电商平台二级商户,填写微信支付分配的商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:微信订单号
     * 变量名:transaction_id
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  body 微信支付订单号。
     *  示例值: 4208450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "transaction_id")
    private String transactionId;
    /**
     * <pre>
     * 字段名:补差金额
     * 变量名:amount
     * 是否必填:是
     * 类型:int
     * 描述:
     *  body 补差金额,单位为分,只能为整数,不能超过下单时候的最大补差金额。
     *  注意:单笔订单最高补差金额为5000元
     *  示例值:10
     * </pre>
     */
    @JsonProperty(value = "amount")
    private Integer amount;
    /**
     * <pre>
     * 字段名:补差描述
     * 变量名:description
     * 是否必填:是
     * 类型:string[1,80]
     * 描述:
     *  body 补差备注描述,查询的时候原样带回。
     *  示例值:测试备注
     * </pre>
     */
    @JsonProperty(value = "description")
    private String description;
    /**
     * <pre>
     * 字段名:微信退款单号
     * 变量名:refund_id
     * 是否必填:否
     * 类型:string[1,64]
     * 描述:
     *  body 微信退款单号,微信系统退款返回的唯一标识,当补差金额小于下单时候的金额,该字段必填
     *  示例值:3008450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "refund_id")
    private String refundId;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/ecommerce/subsidies/SubsidiesRefundRequest.java
New file
@@ -0,0 +1,102 @@
package com.ruoyi.order.tools.request.ecommerce.subsidies;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 订单发送退款的时候,可以对补贴成功的补差单发起回退。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/subsidies/chapter3_2.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class SubsidiesRefundRequest {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 补差的电商平台二级商户,填写微信支付分配的商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:商户补差回退单号
     * 变量名:out_order_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  body 商户系统内部的补差回退单号,在商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一补差回退单号多次请求等同一次。
     *  示例值:P20150806125346
     * </pre>
     */
    @JsonProperty(value = "out_order_no")
    private String outOrderNo;
    /**
     * <pre>
     * 字段名:微信订单号
     * 变量名:transaction_id
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  body 微信支付订单号。
     *  示例值:4208450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "transaction_id")
    private String transactionId;
    /**
     * <pre>
     * 字段名:微信退款单号
     * 变量名:refund_id
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  body 微信退款单号,微信系统退款返回的唯一标识。
     *  示例值:3008450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "refund_id")
    private String refundId;
    /**
     * <pre>
     * 字段名:补差回退金额
     * 变量名:amount
     * 是否必填:是
     * 类型:int
     * 描述:
     *  body 补差回退金额,单位为分,只能为整数,不能超过补差单的补差金额。
     *  示例值:10
     * </pre>
     */
    @JsonProperty(value = "amount")
    private Integer amount;
    /**
     * <pre>
     * 字段名:补差回退描述
     * 变量名:description
     * 是否必填:是
     * 类型:string[1,80]
     * 描述:
     *  body 补差回退描述,查询的时候原样带回。
     *  示例值:测试备注
     * </pre>
     */
    @JsonProperty(value = "description")
    private String description;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/pay/bill/BillOfFundFlowRequest.java
New file
@@ -0,0 +1,67 @@
package com.ruoyi.order.tools.request.pay.bill;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 微信支付按天提供微信支付账户的资金流水账单文件,商户可以通过该接口获取账单文件的下载地址。文件内包含该账户资金操作相关的业务单号、收支金额、记账时间等信息,供商户进行核对。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/bill/chapter3_2.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class BillOfFundFlowRequest {
    /**
     * <pre>
     * 字段名:账单日期
     * 变量名:bill_date
     * 是否必填:是
     * 类型:string[1,10]
     * 描述:
     *   格式YYYY-MM-DD
     *  仅支持三个月内的账单下载申请。
     *  示例值:2019-06-11
     * </pre>
     */
    @JsonProperty(value = "bill_date")
    private String billDate;
    /**
     * <pre>
     * 字段名:资金账户类型
     * 变量名:account_type
     * 是否必填:否
     * 类型:string[1,32]
     * 描述:
     *   不填则默认是BASIC
     *  枚举值:
     *  BASIC:基本账户
     *  OPERATION:运营账户
     *  FEES:手续费账户
     *  示例值:BASIC
     * </pre>
     */
    @JsonProperty(value = "account_type")
    private String accountType;
    /**
     * <pre>
     * 字段名:压缩类型
     * 变量名:tar_type
     * 是否必填:否
     * 类型:string[1,32]
     * 描述:
     *   不填则默认是数据流
     *  枚举值:
     *  GZIP:返回格式为.gzip的压缩包账单
     *  示例值:GZIP
     * </pre>
     */
    @JsonProperty(value = "tar_type")
    private String tarType;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/pay/bill/BillOfTradeRequest.java
New file
@@ -0,0 +1,67 @@
package com.ruoyi.order.tools.request.pay.bill;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 微信支付按天提供交易账单文件,商户可以通过该接口获取账单文件的下载地址。文件内包含交易相关的金额、时间、营销等信息,供商户核对订单、退款、银行到账等情况。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/bill/chapter3_1.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class BillOfTradeRequest {
    /**
     * <pre>
     * 字段名:账单日期
     * 变量名:bill_date
     * 是否必填:是
     * 类型:string[1,10]
     * 描述:
     *   格式YYYY-MM-DD
     *  仅支持三个月内的账单下载申请。
     *  示例值:2019-06-11
     * </pre>
     */
    @JsonProperty(value = "bill_date")
    private String billDate;
    /**
     * <pre>
     * 字段名:账单类型
     * 变量名:bill_type
     * 是否必填:否
     * 类型:string[1,32]
     * 描述:
     *   不填则默认是ALL
     *  枚举值:
     *  ALL:返回当日所有订单信息(不含充值退款订单)
     *  SUCCESS:返回当日成功支付的订单(不含充值退款订单)
     *  REFUND:返回当日退款订单(不含充值退款订单)
     *  示例值:ALL
     * </pre>
     */
    @JsonProperty(value = "bill_type")
    private String billType;
    /**
     * <pre>
     * 字段名:压缩类型
     * 变量名:tar_type
     * 是否必填:否
     * 类型:string[1,32]
     * 描述:
     *   不填则默认是数据流
     *  枚举值:
     *  GZIP:返回格式为.gzip的压缩包账单
     *  示例值:GZIP
     * </pre>
     */
    @JsonProperty(value = "tar_type")
    private String tarType;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/pay/combine/CombineTransactionsAppRequest.java
New file
@@ -0,0 +1,356 @@
package com.ruoyi.order.tools.request.pay.combine;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
 * <pre>
 * 使用合单支付接口,用户只输入一次密码,即可完成多个订单的支付。目前最少一次可支持2笔,最多一次10笔订单进行合单支付。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/combine/chapter3_1.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class CombineTransactionsAppRequest {
    /**
     * <pre>
     * 字段名:合单商户appid
     * 变量名:combine_appid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 合单发起方的appid。
     *  示例值:wxd678efh567hg6787
     * </pre>
     */
    @JsonProperty(value = "combine_appid")
    private String combineAppid;
    /**
     * <pre>
     * 字段名:合单商户号
     * 变量名:combine_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body合单发起方商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "combine_mchid")
    private String combineMchid;
    /**
     * <pre>
     * 字段名:合单商户订单号
     * 变量名:combine_out_trade_no
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body合单支付总订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一 。
     *  示例值:P20150806125346
     * </pre>
     */
    @JsonProperty(value = "combine_out_trade_no")
    private String combineOutTradeNo;
    /**
     * <pre>
     * 字段名:+场景信息
     * 变量名:scene_info
     * 是否必填:否
     * 类型:object
     * 描述:body支付场景信息描述
     * </pre>
     */
    @JsonProperty(value = "scene_info")
    private SceneInfo sceneInfo;
    /**
     * <pre>
     * 字段名:+子单信息
     * 变量名:sub_orders
     * 是否必填:是
     * 类型:array
     * 描述:
     *  body最多支持子单条数:10
     *
     * </pre>
     */
    @JsonProperty(value = "sub_orders")
    private List<SubOrders> subOrders;
    /**
     * <pre>
     * 字段名:+支付者
     * 变量名:combine_payer_info
     * 是否必填:否
     * 类型:object
     * 描述:body支付者信息
     * </pre>
     */
    @JsonProperty(value = "combine_payer_info")
    private CombinePayerInfo combinePayerInfo;
    /**
     * <pre>
     * 字段名:交易起始时间
     * 变量名:time_start
     * 是否必填:否
     * 类型:string[1,32]
     * 描述:
     *  body订单生成时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒。
     *  示例值:2019-12-31T15:59:59+08:00
     * </pre>
     */
    @JsonProperty(value = "time_start")
    private String timeStart;
    /**
     * <pre>
     * 字段名:交易结束时间
     * 变量名:time_expire
     * 是否必填:否
     * 类型:string[1,32]
     * 描述:
     *  body订单失效时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒。
     *  示例值:2019-12-31T15:59:59+08:00
     * </pre>
     */
    @JsonProperty(value = "time_expire")
    private String timeExpire;
    /**
     * <pre>
     * 字段名:通知地址
     * 变量名:notify_url
     * 是否必填:是
     * 类型:string[1,256]
     * 描述:
     *  body接收微信支付异步通知回调地址,通知url必须为直接可访问的URL,不能携带参数。
     *  格式: URL
     *  示例值:https://yourapp.com/notify
     * </pre>
     */
    @JsonProperty(value = "notify_url")
    private String notifyUrl;
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class SceneInfo {
        /**
         * <pre>
         * 字段名:商户端设备号
         * 变量名:device_id
         * 是否必填:否
         * 类型:string[7,16]
         * 描述:
         *  终端设备号(门店号或收银设备ID) 。
         *  示例值:POS1:123
         * </pre>
         */
        @JsonProperty(value = "device_id")
        private String deviceId;
        /**
         * <pre>
         * 字段名:用户终端IP
         * 变量名:payer_client_ip
         * 是否必填:是
         * 类型:string[1,45]
         * 描述:
         *  用户的客户端IP,支持IPv4和IPv6两种格式的IP地址。
         *  格式: ip(ipv4+ipv6)
         *  示例值:14.17.22.32
         * </pre>
         */
        @JsonProperty(value = "payer_client_ip")
        private String payerClientIp;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class SubOrders {
        /**
         * <pre>
         * 字段名:子单商户号
         * 变量名:mchid
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  子单发起方商户号即合单参与方商户号,必须与发起方appid有绑定关系。
         *  示例值:1900000109
         * </pre>
         */
        @JsonProperty(value = "mchid")
        private String mchid;
        /**
         * <pre>
         * 字段名:附加数据
         * 变量名:attach
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用。
         *  示例值:深圳分店
         * </pre>
         */
        @JsonProperty(value = "attach")
        private String attach;
        /**
         * <pre>
         * 字段名:+订单金额
         * 变量名:amount
         * 是否必填:是
         * 类型:object
         * 描述:订单金额信息
         * </pre>
         */
        @JsonProperty(value = "amount")
        private Amount amount;
        /**
         * <pre>
         * 字段名:子单商户订单号
         * 变量名:out_trade_no
         * 是否必填:是
         * 类型:string[6,32]
         * 描述:
         *  商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。
         *  示例值:20150806125346
         * </pre>
         */
        @JsonProperty(value = "out_trade_no")
        private String outTradeNo;
        /**
         * <pre>
         * 字段名:商品描述
         * 变量名:description
         * 是否必填:是
         * 类型:string[1,127]
         * 描述:
         *  商品简单描述。需传入应用市场上的APP名字-实际商品名称,例如:天天爱消除-游戏充值。
         *  示例值:腾讯充值中心-QQ会员充值
         * </pre>
         */
        @JsonProperty(value = "description")
        private String description;
        /**
         * <pre>
         * 字段名:+结算信息
         * 变量名:settle_info
         * 是否必填:否
         * 类型:object
         * 描述:结算信息
         * </pre>
         */
        @JsonProperty(value = "settle_info")
        private SettleInfo settleInfo;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class CombinePayerInfo {
        /**
         * <pre>
         * 字段名:用户标识
         * 变量名:openid
         * 是否必填:否
         * 类型:string[1,128]
         * 描述:
         *  使用合单appid获取的对应用户openid。是用户在商户appid下的唯一标识。
         *  示例值:oUpF8uMuAJO_M2pxb1Q9zNjWeS6o
         * </pre>
         */
        @JsonProperty(value = "openid")
        private String openid;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class Amount {
        /**
         * <pre>
         * 字段名:标价金额
         * 变量名:total_amount
         * 是否必填:是
         * 类型:int
         * 描述:
         *  子单金额,单位为分
         *  境外场景下,标价金额要超过商户结算币种的最小单位金额,例如结算币种为美元,则标价金额必须大于1美分
         *  示例值:100
         * </pre>
         */
        @JsonProperty(value = "total_amount")
        private Integer totalAmount;
        /**
         * <pre>
         * 字段名:标价币种
         * 变量名:currency
         * 是否必填:是
         * 类型:string[1,8]
         * 描述:
         *  符合ISO 4217标准的三位字母代码,人民币:CNY 。
         *  示例值:CNY
         * </pre>
         */
        @JsonProperty(value = "currency")
        private String currency;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class SettleInfo {
        /**
         * <pre>
         * 字段名:是否指定分账
         * 变量名:profit_sharing
         * 是否必填:否
         * 类型:bool
         * 描述:
         *  是否指定分账,枚举值
         *  true:是
         *  false:否
         *  示例值:true
         * </pre>
         */
        @JsonProperty(value = "profit_sharing")
        private Boolean profitSharing;
        /**
         * <pre>
         * 字段名:补差金额
         * 变量名:subsidy_amount
         * 是否必填:否
         * 类型:int64
         * 描述:
         *  SettleInfo.profit_sharing为true时,该金额才生效。
         *  注意:单笔订单最高补差金额为5000元
         *  示例值:10
         * </pre>
         */
        @JsonProperty(value = "subsidy_amount")
        private Integer subsidyAmount;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/pay/combine/CombineTransactionsCloseRequest.java
New file
@@ -0,0 +1,98 @@
package com.ruoyi.order.tools.request.pay.combine;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
 * <pre>
 * 合单支付订单只能使用此合单关单api完成关单。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/combine/chapter3_4.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties("combineOutTradeNo")
public class CombineTransactionsCloseRequest {
    /**
     * <pre>
     * 字段名:合单商户appid
     * 变量名:combine_appid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 合单发起方的appid。
     *  示例值:wxd678efh567hg6787
     * </pre>
     */
    @JsonProperty(value = "combine_appid")
    private String combineAppid;
    /**
     * <pre>
     * 字段名:合单商户订单号
     * 变量名:combine_out_trade_no
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  path 合单支付总订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。
     *  示例值:P20150806125346
     * </pre>
     */
    @JsonIgnore
    @JsonProperty(value = "combine_out_trade_no")
    private String combineOutTradeNo;
    /**
     * <pre>
     * 字段名:+子单信息
     * 变量名:sub_orders
     * 是否必填:是
     * 类型:array
     * 描述:
     *  body 最多支持子单条数:10
     *
     * </pre>
     */
    @JsonProperty(value = "sub_orders")
    private List<SubOrders> subOrders;
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class SubOrders {
        /**
         * <pre>
         * 字段名:子单商户号
         * 变量名:mchid
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  子单发起方商户号,必须与发起方appid有绑定关系。
         *  示例值:1900000109
         * </pre>
         */
        @JsonProperty(value = "mchid")
        private String mchid;
        /**
         * <pre>
         * 字段名:子单商户订单号
         * 变量名:out_trade_no
         * 是否必填:是
         * 类型:string[6,32]
         * 描述:
         *  商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。
         *  示例值:20150806125346
         * </pre>
         */
        @JsonProperty(value = "out_trade_no")
        private String outTradeNo;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/pay/combine/CombineTransactionsDetailRequest.java
New file
@@ -0,0 +1,37 @@
package com.ruoyi.order.tools.request.pay.combine;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
 * <pre>
 * 电商平台通过合单查询订单API查询订单状态,完成下一步的业务逻辑。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/combine/chapter3_3.shtml
 * </pre>
 */
@JsonIgnoreProperties(ignoreUnknown = true)
public class CombineTransactionsDetailRequest {
    /**
     * <pre>
     * 字段名:合单商户订单号
     * 变量名:combine_out_trade_no
     * 是否必填:是
     * 类型:string(32)
     * 描述:
     *  path 合单支付总订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一 。
     *  示例值:P20150806125346
     * </pre>
     */
    @JsonProperty(value = "combine_out_trade_no")
    private String combineOutTradeNo;
    public String getCombineOutTradeNo() {
        return this.combineOutTradeNo;
    }
    public void setCombineOutTradeNo(String combineOutTradeNo) {
        this.combineOutTradeNo = combineOutTradeNo;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/pay/combine/CombineTransactionsJsRequest.java
New file
@@ -0,0 +1,356 @@
package com.ruoyi.order.tools.request.pay.combine;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
 * <pre>
 * 使用合单支付接口,用户只输入一次密码,即可完成多个订单的支付。目前最少一次可支持2笔,最多一次10笔订单进行合单支付。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/combine/chapter3_2.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class CombineTransactionsJsRequest {
    /**
     * <pre>
     * 字段名:合单商户appid
     * 变量名:combine_appid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 合单发起方的appid。
     *  示例值:wxd678efh567hg6787
     * </pre>
     */
    @JsonProperty(value = "combine_appid")
    private String combineAppid;
    /**
     * <pre>
     * 字段名:合单商户号
     * 变量名:combine_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 合单发起方商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "combine_mchid")
    private String combineMchid;
    /**
     * <pre>
     * 字段名:合单商户订单号
     * 变量名:combine_out_trade_no
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  body 合单支付总订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。
     *  示例值:P20150806125346
     * </pre>
     */
    @JsonProperty(value = "combine_out_trade_no")
    private String combineOutTradeNo;
    /**
     * <pre>
     * 字段名:+场景信息
     * 变量名:scene_info
     * 是否必填:否
     * 类型:object
     * 描述:body 支付场景信息描述
     * </pre>
     */
    @JsonProperty(value = "scene_info")
    private SceneInfo sceneInfo;
    /**
     * <pre>
     * 字段名:+子单信息
     * 变量名:sub_orders
     * 是否必填:是
     * 类型:array
     * 描述:
     *  body 最多支持子单条数:10
     *
     * </pre>
     */
    @JsonProperty(value = "sub_orders")
    private List<SubOrders> subOrders;
    /**
     * <pre>
     * 字段名:+支付者
     * 变量名:combine_payer_info
     * 是否必填:是
     * 类型:object
     * 描述:body 支付者信息
     * </pre>
     */
    @JsonProperty(value = "combine_payer_info")
    private CombinePayerInfo combinePayerInfo;
    /**
     * <pre>
     * 字段名:交易起始时间
     * 变量名:time_start
     * 是否必填:否
     * 类型:string[1,32]
     * 描述:
     *  body 订单生成时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒。
     *  示例值:2019-12-31T15:59:59+08:00
     * </pre>
     */
    @JsonProperty(value = "time_start")
    private String timeStart;
    /**
     * <pre>
     * 字段名:交易结束时间
     * 变量名:time_expire
     * 是否必填:否
     * 类型:string[1,32]
     * 描述:
     *  body 订单失效时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日 13点29分35秒。
     *  示例值:2019-12-31T15:59:59+08:00
     * </pre>
     */
    @JsonProperty(value = "time_expire")
    private String timeExpire;
    /**
     * <pre>
     * 字段名:通知地址
     * 变量名:notify_url
     * 是否必填:是
     * 类型:string[1,256]
     * 描述:
     *  body 接收微信支付异步通知回调地址,通知url必须为直接可访问的URL,不能携带参数。
     *  格式: URL
     *  示例值:https://yourapp.com/notify
     * </pre>
     */
    @JsonProperty(value = "notify_url")
    private String notifyUrl;
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class SceneInfo {
        /**
         * <pre>
         * 字段名:商户端设备号
         * 变量名:device_id
         * 是否必填:否
         * 类型:string[7,16]
         * 描述:
         *  终端设备号(门店号或收银设备ID)。
         *  示例值:POS1:123
         * </pre>
         */
        @JsonProperty(value = "device_id")
        private String deviceId;
        /**
         * <pre>
         * 字段名:用户终端IP
         * 变量名:payer_client_ip
         * 是否必填:是
         * 类型:string[1,45]
         * 描述:
         *  用户的客户端IP,支持IPv4和IPv6两种格式的IP地址。
         *  格式: ip(ipv4+ipv6)
         *  示例值:14.17.22.32
         * </pre>
         */
        @JsonProperty(value = "payer_client_ip")
        private String payerClientIp;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class SubOrders {
        /**
         * <pre>
         * 字段名:子单商户号
         * 变量名:mchid
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  子单发起方商户号即合单参与方商户号,必须与发起方appid有绑定关系。
         *  示例值:1900000109
         * </pre>
         */
        @JsonProperty(value = "mchid")
        private String mchid;
        /**
         * <pre>
         * 字段名:附加数据
         * 变量名:attach
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用。
         *  示例值:深圳分店
         * </pre>
         */
        @JsonProperty(value = "attach")
        private String attach;
        /**
         * <pre>
         * 字段名:+订单金额
         * 变量名:amount
         * 是否必填:是
         * 类型:object
         * 描述:订单金额
         * </pre>
         */
        @JsonProperty(value = "amount")
        private Amount amount;
        /**
         * <pre>
         * 字段名:子单商户订单号
         * 变量名:out_trade_no
         * 是否必填:是
         * 类型:string[6,32]
         * 描述:
         *  商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。
         *  示例值:20150806125346
         * </pre>
         */
        @JsonProperty(value = "out_trade_no")
        private String outTradeNo;
        /**
         * <pre>
         * 字段名:商品描述
         * 变量名:description
         * 是否必填:是
         * 类型:string[1,127]
         * 描述:
         *  商品简单描述。需传入应用市场上的APP名字-实际商品名称,例如:天天爱消除-游戏充值。
         *  示例值:腾讯充值中心-QQ会员充值
         * </pre>
         */
        @JsonProperty(value = "description")
        private String description;
        /**
         * <pre>
         * 字段名:+结算信息
         * 变量名:settle_info
         * 是否必填:否
         * 类型:Object
         * 描述:结算信息
         * </pre>
         */
        @JsonProperty(value = "settle_info")
        private SettleInfo settleInfo;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class CombinePayerInfo {
        /**
         * <pre>
         * 字段名:用户标识
         * 变量名:openid
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  使用合单appid获取的对应用户openid。是用户在商户appid下的唯一标识。
         *  示例值:oUpF8uMuAJO_M2pxb1Q9zNjWeS6o
         * </pre>
         */
        @JsonProperty(value = "openid")
        private String openid;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class Amount {
        /**
         * <pre>
         * 字段名:标价金额
         * 变量名:total_amount
         * 是否必填:是
         * 类型:int64
         * 描述:
         *  子单金额,单位为分。
         *  境外场景下,标价金额要超过商户结算币种的最小单位金额,例如结算币种为美元,则标价金额必须大于1美分
         *  示例值:100
         * </pre>
         */
        @JsonProperty(value = "total_amount")
        private Integer totalAmount;
        /**
         * <pre>
         * 字段名:标价币种
         * 变量名:currency
         * 是否必填:是
         * 类型:string[1,8]
         * 描述:
         *  符合ISO 4217标准的三位字母代码,人民币:CNY。
         *  示例值:CNY
         * </pre>
         */
        @JsonProperty(value = "currency")
        private String currency;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class SettleInfo {
        /**
         * <pre>
         * 字段名:是否指定分账
         * 变量名:profit_sharing
         * 是否必填:否
         * 类型:bool
         * 描述:
         *  是否指定分账,枚举值:
         *  true:是
         *  false:否
         *  示例值:true
         * </pre>
         */
        @JsonProperty(value = "profit_sharing")
        private Boolean profitSharing;
        /**
         * <pre>
         * 字段名:补差金额
         * 变量名:subsidy_amount
         * 是否必填:否
         * 类型:int64
         * 描述:
         *  SettleInfo.profit_sharing为true时,该金额才生效。
         *  注意:单笔订单最高补差金额为5000元
         *  示例值:10
         * </pre>
         */
        @JsonProperty(value = "subsidy_amount")
        private Integer subsidyAmount;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/pay/combine/CombineTransactionsNotifyRequest.java
New file
@@ -0,0 +1,150 @@
package com.ruoyi.order.tools.request.pay.combine;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 微信支付通过支付通知接口将用户支付成功消息通知给商户
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/combine/chapter3_7.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class CombineTransactionsNotifyRequest {
    /**
     * <pre>
     * 字段名:通知ID
     * 变量名:id
     * 是否必填:是
     * 类型:string[1,36]
     * 描述:
     *  通知的唯一ID
     *  示例值:EV-2018022511223320873
     * </pre>
     */
    @JsonProperty(value = "id")
    private String id;
    /**
     * <pre>
     * 字段名:通知创建时间
     * 变量名:create_time
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  通知创建的时间, 遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示北京时间2015年05月20日13点29分35秒。
     *  示例值:2015-05-20T13:29:35+08:00
     * </pre>
     */
    @JsonProperty(value = "create_time")
    private String createTime;
    /**
     * <pre>
     * 字段名:通知类型
     * 变量名:event_type
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  通知的类型,支付成功通知的类型为TRANSACTION.SUCCESS
     *  示例值:TRANSACTION.SUCCESS
     * </pre>
     */
    @JsonProperty(value = "event_type")
    private String eventType;
    /**
     * <pre>
     * 字段名:通知数据类型
     * 变量名:resource_type
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  通知的资源数据类型,支付成功通知为encrypt-resource
     *  示例值:encrypt-resource
     * </pre>
     */
    @JsonProperty(value = "resource_type")
    private String resourceType;
    /**
     * <pre>
     * 字段名:+通知数据
     * 变量名:resource
     * 是否必填:是
     * 类型:object
     * 描述:
     *  通知资源数据
     *  json格式,见示例
     * </pre>
     */
    @JsonProperty(value = "resource")
    private Resource resource;
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class Resource {
        /**
         * <pre>
         * 字段名:加密算法类型
         * 变量名:algorithm
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  对开启结果数据进行加密的加密算法,目前只支持AEAD_AES_256_GCM
         *  示例值:AEAD_AES_256_GCM
         * </pre>
         */
        @JsonProperty(value = "algorithm")
        private String algorithm;
        /**
         * <pre>
         * 字段名:数据密文
         * 变量名:ciphertext
         * 是否必填:是
         * 类型:string[1,1048576]
         * 描述:
         *  Base64编码后的开启/停用结果数据密文
         *  示例值:sadsadsadsad
         * </pre>
         */
        @JsonProperty(value = "ciphertext")
        private String ciphertext;
        /**
         * <pre>
         * 字段名:附加数据
         * 变量名:associated_data
         * 是否必填:否
         * 类型:string[1,16]
         * 描述:
         *  附加数据
         *  示例值:fdasfwqewlkja484w
         * </pre>
         */
        @JsonProperty(value = "associated_data")
        private String associatedData;
        /**
         * <pre>
         * 字段名:随机串
         * 变量名:nonce
         * 是否必填:是
         * 类型:string[1,16]
         * 描述:
         *  加密使用的随机串
         *  示例值:fdasflkja484w
         * </pre>
         */
        @JsonProperty(value = "nonce")
        private String nonce;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/pay/combine/CombineTransactionsNotifyRequest1.java
New file
@@ -0,0 +1,592 @@
package com.ruoyi.order.tools.request.pay.combine;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
 * <pre>
 * 微信支付通过支付通知接口将用户支付成功消息通知给商户
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/combine/chapter3_7.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class CombineTransactionsNotifyRequest1 {
    /**
     * <pre>
     * 字段名:合单商户appid
     * 变量名:combine_appid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  合单发起方的appid。
     *  示例值:wxd678efh567hg6787
     * </pre>
     */
    @JsonProperty(value = "combine_appid")
    private String combineAppid;
    /**
     * <pre>
     * 字段名:合单商户号
     * 变量名:combine_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  合单发起方商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "combine_mchid")
    private String combineMchid;
    /**
     * <pre>
     * 字段名:合单商户订单号
     * 变量名:combine_out_trade_no
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  合单支付总订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。
     *  示例值:P20150806125346
     * </pre>
     */
    @JsonProperty(value = "combine_out_trade_no")
    private String combineOutTradeNo;
    /**
     * <pre>
     * 字段名:+场景信息
     * 变量名:scene_info
     * 是否必填:否
     * 类型:object
     * 描述:支付场景信息描述
     * </pre>
     */
    @JsonProperty(value = "scene_info")
    private SceneInfo sceneInfo;
    /**
     * <pre>
     * 字段名:+子单信息
     * 变量名:sub_orders
     * 是否必填:是
     * 类型:array
     * 描述:
     *  最多支持子单条数:10
     *
     * </pre>
     */
    @JsonProperty(value = "sub_orders")
    private List<SubOrders> subOrders;
    /**
     * <pre>
     * 字段名:+支付者
     * 变量名:combine_payer_info
     * 是否必填:是
     * 类型:object
     * 描述:示例值:见请求示例
     * </pre>
     */
    @JsonProperty(value = "combine_payer_info")
    private CombinePayerInfo combinePayerInfo;
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class SceneInfo {
        /**
         * <pre>
         * 字段名:商户端设备号
         * 变量名:device_id
         * 是否必填:否
         * 类型:string[7,16]
         * 描述:
         *  终端设备号(门店号或收银设备ID)。
         *  特殊规则:长度最小7个字节
         *  示例值:POS1:1
         * </pre>
         */
        @JsonProperty(value = "device_id")
        private String deviceId;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class SubOrders {
        /**
         * <pre>
         * 字段名:子单商户号
         * 变量名:mchid
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  子单发起方商户号,必须与发起方Appid有绑定关系。
         *  示例值:1900000109
         * </pre>
         */
        @JsonProperty(value = "mchid")
        private String mchid;
        /**
         * <pre>
         * 字段名:交易类型
         * 变量名:trade_type
         * 是否必填:是
         * 类型:string[1,16]
         * 描述:
         *  枚举值:
         *  NATIVE:扫码支付
         *  JSAPI:公众号支付
         *  APP:APP支付
         *  MWEB:H5支付
         *  示例值: JSAPI
         * </pre>
         */
        @JsonProperty(value = "trade_type")
        private String tradeType;
        /**
         * <pre>
         * 字段名:交易状态
         * 变量名:trade_state
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  枚举值:
         *  SUCCESS:支付成功
         *  REFUND:转入退款
         *  NOTPAY:未支付
         *  CLOSED:已关闭
         *  USERPAYING:用户支付中
         *  PAYERROR:支付失败(其他原因,如银行返回失败)
         *  示例值: SUCCESS
         * </pre>
         */
        @JsonProperty(value = "trade_state")
        private String tradeState;
        /**
         * <pre>
         * 字段名:付款银行
         * 变量名:bank_type
         * 是否必填:是
         * 类型:string[1,16]
         * 描述:
         *  银行类型,采用字符串类型的银行标识。银行标识请参考《银行类型对照表》
         *  示例值:CMC
         * </pre>
         */
        @JsonProperty(value = "bank_type")
        private String bankType;
        /**
         * <pre>
         * 字段名:附加信息
         * 变量名:attach
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用。
         *  示例值:深圳分店
         * </pre>
         */
        @JsonProperty(value = "attach")
        private String attach;
        /**
         * <pre>
         * 字段名:支付完成时间
         * 变量名:success_time
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  订单支付时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss:sss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss:sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示,北京时间2015年5月20日 13点29分35秒。
         *  示例值:2015-05-20T13:29:35.120+08:00
         * </pre>
         */
        @JsonProperty(value = "success_time")
        private String successTime;
        /**
         * <pre>
         * 字段名:微信订单号
         * 变量名:transaction_id
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  微信支付订单号。
         *  示例值: 1009660380201506130728806387
         * </pre>
         */
        @JsonProperty(value = "transaction_id")
        private String transactionId;
        /**
         * <pre>
         * 字段名:子单商户订单号
         * 变量名:out_trade_no
         * 是否必填:是
         * 类型:string[6,32]
         * 描述:
         *  商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。
         *  特殊规则:最小字符长度为6
         *  示例值:20150806125346
         * </pre>
         */
        @JsonProperty(value = "out_trade_no")
        private String outTradeNo;
        /**
         * <pre>
         * 字段名:+订单金额
         * 变量名:amount
         * 是否必填:是
         * 类型:object
         * 描述:订单金额信息
         * </pre>
         */
        @JsonProperty(value = "amount")
        private Amount amount;
        /**
         * <pre>
         * 字段名:+优惠功能
         * 变量名:promotion_detail
         * 是否必填:否
         * 类型:array
         * 描述:优惠功能,子单有核销优惠券时有返回
         * </pre>
         */
        @JsonProperty(value = "promotion_detail")
        private List<PromotionDetail> promotionDetail;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class CombinePayerInfo {
        /**
         * <pre>
         * 字段名:用户标识
         * 变量名:openid
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  使用合单appid获取的对应用户openid。是用户在商户appid下的唯一标识。
         *  示例值:oUpF8uMuAJO_M2pxb1Q9zNjWeS6o
         * </pre>
         */
        @JsonProperty(value = "openid")
        private String openid;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class Amount {
        /**
         * <pre>
         * 字段名:标价金额
         * 变量名:total_amount
         * 是否必填:是
         * 类型:int64
         * 描述:
         *  子单金额,单位为分。
         *  示例值:100
         * </pre>
         */
        @JsonProperty(value = "total_amount")
        private Integer totalAmount;
        /**
         * <pre>
         * 字段名:标价币种
         * 变量名:currency
         * 是否必填:是
         * 类型:string[1,16]
         * 描述:
         *  符合ISO 4217标准的三位字母代码,人民币:CNY。
         *  示例值:CNY
         * </pre>
         */
        @JsonProperty(value = "currency")
        private String currency;
        /**
         * <pre>
         * 字段名:现金支付金额
         * 变量名:payer_amount
         * 是否必填:是
         * 类型:int64
         * 描述:
         *  订单现金支付金额。
         *  示例值:10
         * </pre>
         */
        @JsonProperty(value = "payer_amount")
        private Integer payerAmount;
        /**
         * <pre>
         * 字段名:现金支付币种
         * 变量名:payer_currency
         * 是否必填:是
         * 类型:string[1,8]
         * 描述:
         *  货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY。
         *  示例值: CNY
         * </pre>
         */
        @JsonProperty(value = "payer_currency")
        private String payerCurrency;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class PromotionDetail {
        /**
         * <pre>
         * 字段名:券ID
         * 变量名:coupon_id
         * 是否必填:是
         * 类型:string[1, 32]
         * 描述:
         *  券ID
         *  示例值:109519
         * </pre>
         */
        @JsonProperty(value = "coupon_id")
        private String couponId;
        /**
         * <pre>
         * 字段名:优惠名称
         * 变量名:name
         * 是否必填:否
         * 类型:string[1, 64]
         * 描述:
         *  优惠名称
         *  示例值:单品惠-6
         * </pre>
         */
        @JsonProperty(value = "name")
        private String name;
        /**
         * <pre>
         * 字段名:优惠范围
         * 变量名:scope
         * 是否必填:否
         * 类型:string[1, 32]
         * 描述:
         *  GLOBAL:全场代金券
         *  SINGLE:单品优惠
         *  示例值:GLOBALSINGLE
         * </pre>
         */
        @JsonProperty(value = "scope")
        private String scope;
        /**
         * <pre>
         * 字段名:优惠类型
         * 变量名:type
         * 是否必填:否
         * 类型:string[1,8]
         * 描述:
         *  CASH- 代金券,需要走结算资金的预充值型代金券
         *  NOCASH- 优惠券,不走结算资金的免充值型优惠券
         *  示例值:CASH
         * </pre>
         */
        @JsonProperty(value = "type")
        private String type;
        /**
         * <pre>
         * 字段名:优惠券金额
         * 变量名:amount
         * 是否必填:是
         * 类型:int
         * 描述:
         *  当前子单中享受的优惠券金额
         *  示例值:100
         * </pre>
         */
        @JsonProperty(value = "amount")
        private Integer amount;
        /**
         * <pre>
         * 字段名:活动ID
         * 变量名:stock_id
         * 是否必填:否
         * 类型:string[1, 32]
         * 描述:
         *  活动ID,批次ID
         *  示例值:931386
         * </pre>
         */
        @JsonProperty(value = "stock_id")
        private String stockId;
        /**
         * <pre>
         * 字段名:微信出资
         * 变量名:wechatpay_contribute
         * 是否必填:否
         * 类型:int
         * 描述:
         *  单位为分
         *  示例值:100
         * </pre>
         */
        @JsonProperty(value = "wechatpay_contribute")
        private Integer wechatpayContribute;
        /**
         * <pre>
         * 字段名:商户出资
         * 变量名:merchant_contribute
         * 是否必填:否
         * 类型:int
         * 描述:
         *  单位为分
         *  示例值:100
         * </pre>
         */
        @JsonProperty(value = "merchant_contribute")
        private Integer merchantContribute;
        /**
         * <pre>
         * 字段名:其他出资
         * 变量名:other_contribute
         * 是否必填:否
         * 类型:int
         * 描述:
         *  单位为分
         *  示例值:100
         * </pre>
         */
        @JsonProperty(value = "other_contribute")
        private Integer otherContribute;
        /**
         * <pre>
         * 字段名:优惠币种
         * 变量名:currency
         * 是否必填:否
         * 类型:string[1,16]
         * 描述:
         *  CNY:人民币,境内商户号仅支持人民币。
         *  示例值:CNY
         * </pre>
         */
        @JsonProperty(value = "currency")
        private String currency;
        /**
         * <pre>
         * 字段名:+单品列表
         * 变量名:goods_detail
         * 是否必填:否
         * 类型:array
         * 描述:单品列表
         * </pre>
         */
        @JsonProperty(value = "goods_detail")
        private List<GoodsDetail> goodsDetail;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class GoodsDetail {
        /**
         * <pre>
         * 字段名:商品编码
         * 变量名:goods_id
         * 是否必填:是
         * 类型:string[1, 32]
         * 描述:
         *  商品编码
         *  示例值:M1006
         * </pre>
         */
        @JsonProperty(value = "goods_id")
        private String goodsId;
        /**
         * <pre>
         * 字段名:商品数量
         * 变量名:quantity
         * 是否必填:是
         * 类型:int
         * 描述:
         *  商品数量
         *  示例值:1
         * </pre>
         */
        @JsonProperty(value = "quantity")
        private Integer quantity;
        /**
         * <pre>
         * 字段名:商品价格
         * 变量名:unit_price
         * 是否必填:是
         * 类型:int
         * 描述:
         *  商品价格
         *  示例值:100
         * </pre>
         */
        @JsonProperty(value = "unit_price")
        private Integer unitPrice;
        /**
         * <pre>
         * 字段名:商品优惠金额
         * 变量名:discount_amount
         * 是否必填:是
         * 类型:int
         * 描述:
         *  商品优惠金额
         *  示例值:1
         * </pre>
         */
        @JsonProperty(value = "discount_amount")
        private Integer discountAmount;
        /**
         * <pre>
         * 字段名:商品备注
         * 变量名:goods_remark
         * 是否必填:否
         * 类型:string[1, 128]
         * 描述:
         *  商品备注
         *  示例值:商品备注信息
         * </pre>
         */
        @JsonProperty(value = "goods_remark")
        private String goodsRemark;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/pay/combine/CombineTransactionsStatusRequest.java
New file
@@ -0,0 +1,34 @@
package com.ruoyi.order.tools.request.pay.combine;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商平台通过合单查询订单API查询订单状态,完成下一步的业务逻辑。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/combine/chapter3_3.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties("combineOutTradeNo")
public class CombineTransactionsStatusRequest {
    /**
     * <pre>
     * 字段名:合单商户订单号
     * 变量名:combine_out_trade_no
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  path 合单支付总订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一 。
     *  示例值:P20150806125346
     * </pre>
     */
    @JsonIgnore
    @JsonProperty(value = "combine_out_trade_no")
    private String combineOutTradeNo;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/request/tool/ImageUploadRequest.java
New file
@@ -0,0 +1,72 @@
package com.ruoyi.order.tools.request.tool;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 部分微信支付业务指定商户需要使用图片上传 API来上报图片信息,从而获得必传参数的值:图片MediaID 。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/chapter3_1.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ImageUploadRequest {
    /**
     * <pre>
     * 字段名:图片文件
     * 变量名:file
     * 是否必填:是
     * 类型:message
     * 描述:body 将媒体图片进行二进制转换,得到的媒体图片二进制内容,在请求body中上传此二进制内容。媒体图片只支持JPG、BMP、PNG格式,文件大小不能超过2M。
     * </pre>
     */
    @JsonProperty(value = "file")
    private String file;
    /**
     * <pre>
     * 字段名:+媒体文件元信息
     * 变量名:meta
     * 是否必填:是
     * 类型:Object
     * 描述:媒体文件元信息,使用json表示,包含两个对象:filename、sha256。
     * </pre>
     */
    @JsonProperty(value = "meta")
    private Meta meta;
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class Meta {
        /**
         * <pre>
         * 字段名:文件名称
         * 变量名:filename
         * 是否必填:否
         * 类型:string[1,128]
         * 描述:商户上传的媒体图片的名称,商户自定义,必须以JPG、BMP、PNG为后缀。
         * </pre>
         */
        @JsonProperty(value = "filename")
        private String filename;
        /**
         * <pre>
         * 字段名:文件摘要
         * 变量名:sha256
         * 是否必填:否
         * 类型:string[1,64]
         * 描述:图片文件的文件摘要,即对图片文件的二进制内容进行sha256计算得到的值。
         * </pre>
         */
        @JsonProperty(value = "sha256")
        private String sha256;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/AbstractResponse.java
New file
@@ -0,0 +1,41 @@
package com.ruoyi.order.tools.response;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class AbstractResponse {
    protected int httpStatusCode;
    protected String code;
    protected String message;
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
    public int getHttpStatusCode() {
        return httpStatusCode;
    }
    public void setHttpStatusCode(int httpStatusCode) {
        this.httpStatusCode = httpStatusCode;
    }
    @JsonIgnore
    public boolean isOk () {
        // 认为200内的是正常的
        return httpStatusCode >= 200 && httpStatusCode < 300;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/amount/AmountDayEndOfPlatformResponse.java
New file
@@ -0,0 +1,51 @@
package com.ruoyi.order.tools.response.ecommerce.amount;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 通过此接口可以查询本商户号指定日期当天24点的账户余额。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/amount/chapter3_4.shtml
 * 状态码    错误码    描述    解决方案
 * 403    NO_AUTH    当前商户号没有使用该接口的权限    请确认是否已经开通相关权限
 * 400    INVALID_REQUEST    该账户在指定时间不存在    请检查account_type和date输入是否正确,修改后重新调用
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class AmountDayEndOfPlatformResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:可用余额
     * 变量名:available_amount
     * 是否必填:是
     * 类型:int
     * 描述:
     *  可用余额(单位:分),此余额可做提现操作。
     *  示例值: 100
     * </pre>
     */
    @JsonProperty(value = "available_amount")
    private Integer availableAmount;
    /**
     * <pre>
     * 字段名:不可用余额
     * 变量名:pending_amount
     * 是否必填:否
     * 类型:int
     * 描述:
     *  不可用余额(单位:分)。
     *  示例值: 100
     * </pre>
     */
    @JsonProperty(value = "pending_amount")
    private Integer pendingAmount;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/amount/AmountDayEndOfSubMchResponse.java
New file
@@ -0,0 +1,66 @@
package com.ruoyi.order.tools.response.ecommerce.amount;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商服务商通过该接口可以查询二级商户指定日期当天24点的账户余额。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/amount/chapter3_2.shtml
 * 状态码    错误码    描述    解决方案
 * 403    NO_AUTH    你无权查询该商户余额    请确认电商平台商户号和二级商户商户号是否存在受理关系
 * 403    NO_AUTH    你无接口权限    请确认是否已经开通相关权限
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用
 * 400    INVALID_REQUEST    该账户在指定时间不存在    请检查date输入是否正确,修改后重新调用
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class AmountDayEndOfSubMchResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  电商平台二级商户号,由微信支付生成并下发。
     *  示例值: 1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:可用余额
     * 变量名:available_amount
     * 是否必填:是
     * 类型:int64
     * 描述:
     *  可用余额(单位:分),此余额可做提现操作。
     *  示例值: 100
     * </pre>
     */
    @JsonProperty(value = "available_amount")
    private Integer availableAmount;
    /**
     * <pre>
     * 字段名:不可用余额
     * 变量名:pending_amount
     * 是否必填:否
     * 类型:int64
     * 描述:
     *  不可用余额(单位:分)。
     *  示例值: 100
     * </pre>
     */
    @JsonProperty(value = "pending_amount")
    private Integer pendingAmount;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/amount/AmountOnlineOfPlatformResponse.java
New file
@@ -0,0 +1,51 @@
package com.ruoyi.order.tools.response.ecommerce.amount;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商平台可通过此接口可以查询本商户号的账号余额情况。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/amount/chapter3_3.shtml
 * 状态码    错误码    描述    解决方案
 * 403    NO_AUTH    当前商户号没有使用该接口的权限    请确认是否已经开通相关权限
 * 400    INVALID_REQUEST    输入账户类型未开通    请检查account_type,并重新调用
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class AmountOnlineOfPlatformResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:可用余额
     * 变量名:available_amount
     * 是否必填:是
     * 类型:int64
     * 描述:
     *  可用余额(单位:分),此余额可做提现操作。
     *  示例值: 100
     * </pre>
     */
    @JsonProperty(value = "available_amount")
    private Integer availableAmount;
    /**
     * <pre>
     * 字段名:不可用余额
     * 变量名:pending_amount
     * 是否必填:否
     * 类型:int64
     * 描述:
     *  不可用余额(单位:分)。
     *  示例值: 100
     * </pre>
     */
    @JsonProperty(value = "pending_amount")
    private Integer pendingAmount;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/amount/AmountOnlineOfSubMchResponse.java
New file
@@ -0,0 +1,83 @@
package com.ruoyi.order.tools.response.ecommerce.amount;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商服务商通过此接口可以查询二级商户账户余额信息。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/amount/chapter3_1.shtml
 * 状态码    错误码    描述    解决方案
 * 403    NO_AUTH    你无权查询该商户余额    请确认电商平台商户号和二级商户商户号是否存在受理关系
 * 403    NO_AUTH    你无权调用此接口    请确认是否已经开通相关权限
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用
 * 400    INVALID_REQUEST    输入账户类型未开通    请检查account_type,并重新调用
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class AmountOnlineOfSubMchResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  电商平台二级商户号,由微信支付生成并下发。
     *  示例值: 1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:账户类型
     * 变量名:account_type
     * 是否必填:否
     * 类型:string[1,16]
     * 描述:
     *  枚举值:
     *  BASIC:基本账户
     *  OPERATION:运营账户
     *  FEES:手续费账户
     *  示例值: BASIC
     * </pre>
     */
    @JsonProperty(value = "account_type")
    private String accountType;
    /**
     * <pre>
     * 字段名:可用余额
     * 变量名:available_amount
     * 是否必填:是
     * 类型:int64
     * 描述:
     *  可用余额(单位:分),此余额可做提现操作。
     *  示例值: 100
     * </pre>
     */
    @JsonProperty(value = "available_amount")
    private Integer availableAmount;
    /**
     * <pre>
     * 字段名:不可用余额
     * 变量名:pending_amount
     * 是否必填:否
     * 类型:int64
     * 描述:
     *  不可用余额(单位:分)。
     *  示例值: 100
     * </pre>
     */
    @JsonProperty(value = "pending_amount")
    private Integer pendingAmount;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/applyments/ApplymentsDownCertificatesResponse.java
New file
@@ -0,0 +1,64 @@
package com.ruoyi.order.tools.response.ecommerce.applyments;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
 * <pre>
 * 由于证书有效期限制和交易安全的原因,微信支付会不定期的更换平台证书。微信支付提供了一系列接口,帮助商户后台系统实现平滑的证书更换。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_3.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEMERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用
 * 400    RESOURCE_ALREADY_EXISTS    存在流程进行中的申请单,请检查是否重入    可通过查询申请状态查看此申请单的申请状态,或更换out_request_no提交新的申请单
 * 403    NO_AUTH    商户权限异常    请确认是否已经开通相关权限
 * 429    RATE_LIMITED    频率限制    请降低调用频率
 * 404    RESOURCE_NOT_EXISTS    申请单不存在    确认入参,传入正确的申请单编号
 * </pre>
 */
@EqualsAndHashCode(callSuper = true)
@Data
public class ApplymentsDownCertificatesResponse extends AbstractResponse {
    @JsonProperty(value = "data")
    private List<Data> data;
    @lombok.Data
    public static class Data {
        /**
         * <pre>
         * 字段名:序列号
         * 变量名:serial_no
         * 是否必填:是
         * 类型:string(32)
         * 描述:证书的序列号
         * </pre>
         */
        @JsonProperty(value = "serial_no")
        private String serialNo;
        /**
         * <pre>
         * 字段名:证书
         * 变量名:encrypt_certificate
         * 是否必填:是
         * 类型:string(4096)
         * 描述:证书内容
         * </pre>
         */
        @JsonProperty(value = "encrypt_certificate")
        private EncryptCertificate encryptCertificate;
    }
    @lombok.Data
    public static class EncryptCertificate {
        private String algorithm;
        private String nonce;
        private String associated_data;
        private String ciphertext;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/applyments/ApplymentsModifySettlementResponse.java
New file
@@ -0,0 +1,19 @@
package com.ruoyi.order.tools.response.ecommerce.applyments;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 服务商/电商平台(不包括支付机构、银行),可使用本接口,修改其进件且已签约特约商户/二级商户的结算银行账户。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_4.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode(callSuper = true)
@JsonIgnoreProperties()
public class ApplymentsModifySettlementResponse extends AbstractResponse {
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/applyments/ApplymentsResponse.java
New file
@@ -0,0 +1,54 @@
package com.ruoyi.order.tools.response.ecommerce.applyments;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商平台,可使用该接口,帮助其二级商户进件成为微信支付商户。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_1.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEMERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用
 * 400    RESOURCE_ALREADY_EXISTS    存在流程进行中的申请单,请检查是否重入    可通过查询申请状态查看此申请单的申请状态,或更换out_request_no提交新的申请单
 * 403    NO_AUTH    商户权限异常    请确认是否已经开通相关权限
 * 429    RATE_LIMITED    频率限制    请降低调用频率
 * 404    RESOURCE_NOT_EXISTS    申请单不存在    确认入参,传入正确的申请单编号
 * </pre>
 */
@Data
@EqualsAndHashCode(callSuper = true)
@JsonIgnoreProperties()
public class ApplymentsResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:微信支付申请单号
     * 变量名:applyment_id
     * 是否必填:是
     * 类型:uint64
     * 描述:
     *  微信支付分配的申请单号 。
     *  示例值:2000002124775691
     * </pre>
     */
    @JsonProperty(value = "applyment_id")
    private String applymentId;
    /**
     * <pre>
     * 字段名:业务申请编号
     * 变量名:out_request_no
     * 是否必填:是
     * 类型:string[1,124]
     * 描述:
     *  服务商自定义的商户唯一编号。每个编号对应一个申请单,每个申请单审核通过后会生成一个微信支付商户号。
     *  示例值:APPLYMENT_00000000001
     * </pre>
     */
    @JsonProperty(value = "out_request_no")
    private String outRequestNo;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/applyments/ApplymentsSettlementStatusResponse.java
New file
@@ -0,0 +1,121 @@
package com.ruoyi.order.tools.response.ecommerce.applyments;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 服务商/电商平台(不包括支付机构、银行),可使用本接口,查询其进件且已签约特约商户/二级商户的结算账户信息(敏感信息掩码)。 该接口可用于核实是否成功修改结算账户信息、及查询系统汇款验证结果。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_5.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ApplymentsSettlementStatusResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:账户类型
     * 变量名:account_type
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  返回特约商户的结算账户类型。
     *  枚举值: ACCOUNT_TYPE_BUSINESS:对公银行账户 ACCOUNT_TYPE_PRIVATE:经营者个人银行卡 示例值:ACCOUNT_TYPE_BUSINESS
     * </pre>
     */
    @JsonProperty(value = "account_type")
    private String accountType;
    /**
     * <pre>
     * 字段名:开户银行
     * 变量名:account_bank
     * 是否必填:是
     * 类型:string[1,128]
     * 描述:
     *  返回特约商户的结算账户-开户银行全称。
     *  示例值:工商银行
     * </pre>
     */
    @JsonProperty(value = "account_bank")
    private String accountBank;
    /**
     * <pre>
     * 字段名:开户银行全称(含支行)
     * 变量名:bank_name
     * 是否必填:否
     * 类型:string[1,128]
     * 描述:
     *  返回特约商户的结算账户-开户银行全称(含支行)。
     *  示例值:施秉县农村信用合作联社城关信用社
     * </pre>
     */
    @JsonProperty(value = "bank_name")
    private String bankName;
    /**
     * <pre>
     * 字段名:开户银行联行号
     * 变量名:bank_branch_id
     * 是否必填:否
     * 类型:string[1,128]
     * 描述:
     *  返回特约商户的结算账户-联行号。
     *  示例值:402713354941
     * </pre>
     */
    @JsonProperty(value = "bank_branch_id")
    private String bankBranchId;
    /**
     * <pre>
     * 字段名:银行账号
     * 变量名:account_number
     * 是否必填:是
     * 类型:string[1,128]
     * 描述:
     *  返回特约商户的结算账户-银行账号,掩码显示。
     *  示例值:62*************78
     * </pre>
     */
    @JsonProperty(value = "account_number")
    private String accountNumber;
    /**
     * <pre>
     * 字段名:汇款验证结果
     * 变量名:verify_result
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  返回特约商户的结算账户-汇款验证结果。
     *  VERIFYING:系统汇款验证中,商户可发起提现尝试。
     *  VERIFY_SUCCESS:系统成功汇款,该账户可正常发起提现。
     *  VERIFY_FAIL:系统汇款失败,该账户无法发起提现,请检查修改。
     *  注:该字段,入驻后若没有修改过银行卡,除非汇款失败,否则是不返回的
     *  示例值:VERIFY_SUCCESS
     * </pre>
     */
    @JsonProperty(value = "verify_result")
    private String verifyResult;
    /**
     * <pre>
     * 字段名:汇款验证失败原因
     * 变量名:verify_fail_reason
     * 是否必填:否
     * 类型:string[1, 1024]
     * 描述:
     *  如果汇款验证成功为空,汇款验证失败为具体原因。
     *  示例值:用户姓名/证件/手机不匹配,请核对后重试
     * </pre>
     */
    @JsonProperty(value = "verify_fail_reason")
    private String verifyFailReason;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/applyments/ApplymentsStatusResponse.java
New file
@@ -0,0 +1,343 @@
package com.ruoyi.order.tools.response.ecommerce.applyments;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
 * <pre>
 * 电商平台通过查询申请状态API查询二级商户入驻申请结果。该查询服务提供两种查询方式(两种查询方式返回结果一致): 方式1:业务申请编号查询申请状态; 方式2:申请单号查询申请状态。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_2.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEMERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用
 * 400    RESOURCE_ALREADY_EXISTS    存在流程进行中的申请单,请检查是否重入    可通过查询申请状态查看此申请单的申请状态,或更换out_request_no提交新的申请单
 * 403    NO_AUTH    商户权限异常    请确认是否已经开通相关权限
 * 404    RESOURCE_NOT_EXISTS    申请单不存在    确认入参,传入正确的申请单编号
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ApplymentsStatusResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:申请状态
     * 变量名:applyment_state
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  枚举值:
     *  CHECKING:资料校验中
     *  ACCOUNT_NEED_VERIFY:待账户验证
     *  AUDITING:审核中
     *  REJECTED:已驳回
     *  NEED_SIGN:待签约
     *  FINISH:完成
     *  FROZEN:已冻结
     *  示例值:FINISH
     * </pre>
     */
    @JsonProperty(value = "applyment_state")
    private String applymentState;
    /**
     * <pre>
     * 字段名:申请状态描述
     * 变量名:applyment_state_desc
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  申请状态描述
     *  示例值:“审核中”
     * </pre>
     */
    @JsonProperty(value = "applyment_state_desc")
    private String applymentStateDesc;
    /**
     * <pre>
     * 字段名:签约状态
     * 变量名:sign_state
     * 是否必填:否
     * 类型:string[1,16]
     * 描述:
     *  1、UNSIGNED:未签约。该状态下,电商平台可查询获取签约链接,引导二级商户的超级管理员完成签约;
     *  2、SIGNED :已签约。指二级商户的超级管理员已完成签约。注意:若申请单被驳回,商户修改了商户主体名称、法人名称、超级管理员信息、主体类型等信息,则需重新签约。
     *  3、NOT_SIGNABLE:不可签约。该状态下,暂不支持超级管理员签约。一般为申请单处于已驳回、已冻结、机器校验中状态,无法签约。
     *  示例值:SIGNED
     * </pre>
     */
    @JsonProperty(value = "sign_state")
    private String signState;
    /**
     * <pre>
     * 字段名:签约链接
     * 变量名:sign_url
     * 是否必填:否
     * 类型:string[1,256]
     * 描述:
     *  1、当申请状态为NEED_SIGN 或 签约状态为UNSIGNED时返回,该链接为永久有效;
     *  2、申请单中的超级管理者,需用已实名认证的微信扫码打开,完成签约。
     *  示例值:https://pay.weixin.qq.com/public/apply4ec_sign/s?applymentId=2000002126198476&sign=b207b673049a32c858f3aabd7d27c7ec
     * </pre>
     */
    @JsonProperty(value = "sign_url")
    private String signUrl;
    /**
     * <pre>
     * 字段名:电商平台二级商户号
     * 变量名:sub_mchid
     * 是否必填:否
     * 类型:string[1,32]
     * 描述:
     *  当申请状态为NEED_SIGN或FINISH时才返回。
     *  示例值:1542488631
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:+汇款账户验证信息
     * 变量名:account_validation
     * 是否必填:否
     * 类型:object
     * 描述:当申请状态为ACCOUNT_NEED_VERIFY 时有返回,可根据指引汇款,完成账户验证。
     * </pre>
     */
    @JsonProperty(value = "account_validation")
    private AccountValidation accountValidation;
    /**
     * <pre>
     * 字段名:+驳回原因详情
     * 变量名:audit_detail
     * 是否必填:否
     * 类型:array
     * 描述:各项资料的审核情况。当申请状态为REJECTED或 FROZEN时才返回。
     * </pre>
     */
    @JsonProperty(value = "audit_detail")
    private List<AuditDetail> auditDetail;
    /**
     * <pre>
     * 字段名:法人验证链接
     * 变量名:legal_validation_url
     * 是否必填:否
     * 类型:string[1,256]
     * 描述:
     *  1、当申请状态为
     *  ACCOUNT_NEED_VERIFY,且通过系统校验的申请单,将返回链接。
     *  2、建议将链接转为二维码展示,让商户法人用微信扫码打开,完成账户验证。
     *  示例值: https://pay.weixin.qq.com/public/apply4ec_sign/s?applymentId=2000002126198476&sign=b207b673049a32c858f3aabd7d27c7ec
     * </pre>
     */
    @JsonProperty(value = "legal_validation_url")
    private String legalValidationUrl;
    /**
     * <pre>
     * 字段名:业务申请编号
     * 变量名:out_request_no
     * 是否必填:是
     * 类型:string[1,124]
     * 描述:
     *  提交接口填写的业务申请编号。
     *  示例值:APPLYMENT_00000000001
     * </pre>
     */
    @JsonProperty(value = "out_request_no")
    private String outRequestNo;
    /**
     * <pre>
     * 字段名:微信支付申请单号
     * 变量名:applyment_id
     * 是否必填:是
     * 类型:uint64
     * 描述:
     *  微信支付分配的申请单号。
     *  示例值:2000002124775691
     * </pre>
     */
    @JsonProperty(value = "applyment_id")
    private String applymentId;
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class AccountValidation {
        /**
         * <pre>
         * 字段名:付款户名
         * 变量名:account_name
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  需商户使用该户名的账户进行汇款。
         *  该字段需进行解密处理,解密方法详见敏感信息加解密说明。
         *  示例值: rDdICA3ZYXshYqeOSslSjSMf+MhhC4oaujiISFzq3AE+as7mAEDJly+DgRuVs74msmKUH8pl+3oA==
         * </pre>
         */
        @JsonProperty(value = "account_name")
        private String accountName;
        /**
         * <pre>
         * 字段名:付款卡号
         * 变量名:account_no
         * 是否必填:否
         * 类型:string[1,128]
         * 描述:
         *  结算账户为对私时会返回,商户需使用该付款卡号进行汇款。
         *  该字段需进行解密处理,解密方法详见敏感信息加解密说明。
         *  示例值:9nZYDEvBT4rDdICA3ZYXshYqeOSslSjSauAE+as7mAEDJly+DgRuVs74msmKUH8pl+3oA==
         * </pre>
         */
        @JsonProperty(value = "account_no")
        private String accountNo;
        /**
         * <pre>
         * 字段名:汇款金额
         * 变量名:pay_amount
         * 是否必填:是
         * 类型:int
         * 描述:
         *  需要汇款的金额(单位:分)。
         *  示例值:124
         * </pre>
         */
        @JsonProperty(value = "pay_amount")
        private Integer payAmount;
        /**
         * <pre>
         * 字段名:收款卡号
         * 变量名:destination_account_number
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  收款账户的卡号
         *  示例值:7222223333322332
         * </pre>
         */
        @JsonProperty(value = "destination_account_number")
        private String destinationAccountNumber;
        /**
         * <pre>
         * 字段名:收款户名
         * 变量名:destination_account_name
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  收款账户名
         *  示例值:财付通支付科技有限公司
         * </pre>
         */
        @JsonProperty(value = "destination_account_name")
        private String destinationAccountName;
        /**
         * <pre>
         * 字段名:开户银行
         * 变量名:destination_account_bank
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  收款账户的开户银行名称。
         *  示例值:招商银行威盛大厦支行
         * </pre>
         */
        @JsonProperty(value = "destination_account_bank")
        private String destinationAccountBank;
        /**
         * <pre>
         * 字段名:省市信息
         * 变量名:city
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  收款账户的省市。
         *  示例值:深圳
         * </pre>
         */
        @JsonProperty(value = "city")
        private String city;
        /**
         * <pre>
         * 字段名:备注信息
         * 变量名:remark
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  商户汇款时,需要填写的备注信息。
         *  示例值:入驻账户验证
         * </pre>
         */
        @JsonProperty(value = "remark")
        private String remark;
        /**
         * <pre>
         * 字段名:汇款截止时间
         * 变量名:deadline
         * 是否必填:是
         * 类型:string[1,20]
         * 描述:
         *  请在此时间前完成汇款。
         *  示例值:2018-12-10 17:09:01
         * </pre>
         */
        @JsonProperty(value = "deadline")
        private String deadline;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class AuditDetail {
        /**
         * <pre>
         * 字段名:参数名称
         * 变量名:param_name
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  提交申请单的资料项名称。
         *  示例值:id_card_copy
         * </pre>
         */
        @JsonProperty(value = "param_name")
        private String paramName;
        /**
         * <pre>
         * 字段名:驳回原因
         * 变量名:reject_reason
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  提交资料项被驳回原因。
         *  示例值:身份证背面识别失败,请上传更清晰的身份证图片
         * </pre>
         */
        @JsonProperty(value = "reject_reason")
        private String rejectReason;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/fund/WithdrawExceptionLogResponse.java
New file
@@ -0,0 +1,68 @@
package com.ruoyi.order.tools.response.ecommerce.fund;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商服务商按日查询并下载提现状态为异常的提现单,提现异常包括提现失败和银行退票。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_4.shtml
 * 状态码    错误码    描述    解决方案
 * 403    NO_AUTH    当前商户号没有使用该接口的权限    请确认是否已经开通相关权限
 * 400    INVALID_REQUEST    请求的账单日期已过期    请检查bill_date,并重新调用
 * 400    NO_STATEMENT_EXIST    请求的账单文件不存在    请检查当前商户号请求的微信支付账户在指定日期是否有资金操作
 * 400    STATEMENT_CREATING    请求的账单正在生成中    请先检查当前商户号的微信支付账户在指定日期内是否有资金操作,若有,则在T+1日上午10点后再重新下载
 * 500    SYSTEM_ERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class WithdrawExceptionLogResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:哈希类型
     * 变量名:hash_type
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  从download_url下载的文件的哈希类型,用于校验文件的完整性。
     *  示例值:SHA1
     * </pre>
     */
    @JsonProperty(value = "hash_type")
    private String hashType;
    /**
     * <pre>
     * 字段名:哈希值
     * 变量名:hash_value
     * 是否必填:是
     * 类型:string[1,1024]
     * 描述:
     *  从download_url下载的文件的哈希值,用于校验文件的完整性。
     *  示例值:79bb0f45fc4c42234a918000b2668d689e2bde04
     * </pre>
     */
    @JsonProperty(value = "hash_value")
    private String hashValue;
    /**
     * <pre>
     * 字段名:账单下载地址
     * 变量名:download_url
     * 是否必填:是
     * 类型:string[1,2048]
     * 描述:
     *  供下一步请求账单文件的下载地址,该地址30s内有效。
     *  示例值:https://api.mch.weixin.qq.com/v3/billdownload/file?token=xxx
     * </pre>
     */
    @JsonProperty(value = "download_url")
    private String downloadUrl;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/fund/WithdrawForPlatformResponse.java
New file
@@ -0,0 +1,60 @@
package com.ruoyi.order.tools.response.ecommerce.fund;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商平台通过该接口可将其平台的收入进行提现
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_5.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEM_ERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * 403    REQUEST_BLOCKED    二级商户未开启手动提现权限    二级商户号提现权限被冻结,无法发起提现
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用,电商平台提交相同商户单号的请求但参数和历史提交的参数不一致
 * 404    ORDER_NOT_EXIST    提现单号不存在    请检查订单号是否正确
 * 403    NOT_ENOUGH    二级商户号账户可用余额不足    二级商户号账户可用余额不足
 * 403    NO_AUTH    无接口使用权限    请开通商户号相关权限
 * 400    INVALID_REQUEST    二级商户未开启手动提现权限    请确认电商平台商户号和二级商户商户号是否存在受理关系
 * 429    FREQUENCY_LIMITED    频率限制    请降低频率后重试
 * 403    CONTRACT_NOT_CONFIRM    二级商户未开启手动提现权限    二级商户号提现权限已关闭,无法发起提现
 * 403    ACCOUNT_NOT_VERIFIED    二级商户下行打款未成功    二级商户号结算银行卡信息有误,修改后重试
 * 403    ACCOUNT_ERROR    二级商户未绑卡    二级商户号没有绑定结算银行卡,绑定后重试
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class WithdrawForPlatformResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:微信支付提现单号
     * 变量名:withdraw_id
     * 是否必填:是
     * 类型:string[1, 128]
     * 描述:
     *  微信支付系统生成的提现单号。
     *  示例值:123219371982379127391327917329791239112123
     * </pre>
     */
    @JsonProperty(value = "withdraw_id")
    private String withdrawId;
    /**
     * <pre>
     * 字段名:商户提现单号
     * 变量名:out_request_no
     * 是否必填:是
     * 类型:string[1, 32]
     * 描述:
     *  商户提现单号,由商户自定义生成。
     *  示例值:2019061122200000000012122
     * </pre>
     */
    @JsonProperty(value = "out_request_no")
    private String outRequestNo;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/fund/WithdrawForSubMchResponse.java
New file
@@ -0,0 +1,74 @@
package com.ruoyi.order.tools.response.ecommerce.fund;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商平台通过余额提现API帮助二级商户发起账户余额提现申请,完成账户余额提现。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_2.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEM_ERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * 403    REQUEST_BLOCKED    二级商户未开启手动提现权限    二级商户号提现权限被冻结,无法发起提现
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用,电商平台提交相同商户单号的请求但参数和历史提交的参数不一致
 * 404    ORDER_NOT_EXIST    提现单号不存在    请检查订单号是否正确
 * 403    NOT_ENOUGH    二级商户号账户可用余额不足    二级商户号账户可用余额不足
 * 403    NO_AUTH    无接口使用权限    请开通商户号相关权限
 * 400    INVALID_REQUEST    二级商户未开启手动提现权限    请确认电商平台商户号和二级商户商户号是否存在受理关系
 * 429    FREQUENCY_LIMITED    频率限制    请降低频率后重试
 * 403    CONTRACT_NOT_CONFIRM    二级商户未开启手动提现权限    二级商户号提现权限已关闭,无法发起提现
 * 403    ACCOUNT_NOT_VERIFIED    二级商户下行打款未成功    二级商户号结算银行卡信息有误,修改后重试
 * 403    ACCOUNT_ERROR    二级商户未绑卡    二级商户号没有绑定结算银行卡,绑定后重试
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class WithdrawForSubMchResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1, 32]
     * 描述:
     *  电商平台二级商户号,由微信支付生成并下发。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:微信支付提现单号
     * 变量名:withdraw_id
     * 是否必填:是
     * 类型:string[1, 128]
     * 描述:
     *  电商平台提交二级商户提现申请后,由微信支付返回的申请单号,作为查询申请状态的唯一标识。
     *  示例值:12321937198237912739132791732912793127931279317929791239112123
     * </pre>
     */
    @JsonProperty(value = "withdraw_id")
    private String withdrawId;
    /**
     * <pre>
     * 字段名:商户提现单号
     * 变量名:out_request_no
     * 是否必填:是
     * 类型:string[1, 32]
     * 描述:
     *  商户提现单号,由商户自定义生成。
     *  示例值:20190611222222222200000000012122
     * </pre>
     */
    @JsonProperty(value = "out_request_no")
    private String outRequestNo;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/fund/WithdrawStatusForPlatformResponse.java
New file
@@ -0,0 +1,194 @@
package com.ruoyi.order.tools.response.ecommerce.fund;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商平台通过该接口查询其提现结果,该查询服务提供两种查询方式(两种查询方式返回结果一致): 方式1:微信支付提现单号查询; 方式2:商户提现单号查询。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_6.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEM_ERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * 403    REQUEST_BLOCKED    二级商户未开启手动提现权限    二级商户号提现权限被冻结,无法发起提现
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用,电商平台提交相同商户单号的请求但参数和历史提交的参数不一致
 * 404    ORDER_NOT_EXIST    提现单号不存在    请检查订单号是否正确
 * 403    NOT_ENOUGH    二级商户号账户可用余额不足    二级商户号账户可用余额不足
 * 403    NO_AUTH    无接口使用权限    请开通商户号相关权限
 * 400    INVALID_REQUEST    二级商户未开启手动提现权限    请确认电商平台商户号和二级商户商户号是否存在受理关系
 * 429    FREQUENCY_LIMITED    频率限制    请降低频率后重试
 * 403    CONTRACT_NOT_CONFIRM    二级商户未开启手动提现权限    二级商户号提现权限已关闭,无法发起提现
 * 403    ACCOUNT_NOT_VERIFIED    二级商户下行打款未成功    二级商户号结算银行卡信息有误,修改后重试
 * 403    ACCOUNT_ERROR    二级商户未绑卡    二级商户号没有绑定结算银行卡,绑定后重试
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class WithdrawStatusForPlatformResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:提现单状态
     * 变量名:status
     * 是否必填:是
     * 类型:string[1,16]
     * 描述:
     *  枚举值:
     *  CREATE_SUCCESS:受理成功
     *  SUCCESS:提现成功
     *  FAIL:提现失败
     *  REFUND:提现退票
     *  CLOSE:关单
     *  INIT:业务单已创建
     *  示例值:CREATE_SUCCESS
     * </pre>
     */
    @JsonProperty(value = "status")
    private String status;
    /**
     * <pre>
     * 字段名:微信支付提现单号
     * 变量名:withdraw_id
     * 是否必填:是
     * 类型:string[1, 128]
     * 描述:
     *  电商平台提交提现申请后,由微信支付返回的申请单号,作为查询申请状态的唯一标识。
     *  示例值:12321937198237912739132791732912793127931279317929791239112123
     * </pre>
     */
    @JsonProperty(value = "withdraw_id")
    private String withdrawId;
    /**
     * <pre>
     * 字段名:商户提现单号
     * 变量名:out_request_no
     * 是否必填:是
     * 类型:string[1, 32]
     * 描述:
     *  商户提现单号,由商户自定义生成。
     *  示例值:20190611222222222200000000012122
     * </pre>
     */
    @JsonProperty(value = "out_request_no")
    private String outRequestNo;
    /**
     * <pre>
     * 字段名:提现金额
     * 变量名:amount
     * 是否必填:是
     * 类型:int
     * 描述:
     *  单位:分
     *  示例值:1
     * </pre>
     */
    @JsonProperty(value = "amount")
    private Integer amount;
    /**
     * <pre>
     * 字段名:发起提现时间
     * 变量名:create_time
     * 是否必填:是
     * 类型:string[29, 29]
     * 描述:
     *  遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss:sss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss:sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日13点29分35秒。
     *  示例值:2015-05-20T13:29:35.120+08:00
     * </pre>
     */
    @JsonProperty(value = "create_time")
    private String createTime;
    /**
     * <pre>
     * 字段名:提现状态更新时间
     * 变量名:update_time
     * 是否必填:是
     * 类型:string[29, 29]
     * 描述:
     *  遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss:sss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss:sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日13点29分35秒。
     *  示例值:2015-05-20T13:29:35.120+08:00
     * </pre>
     */
    @JsonProperty(value = "update_time")
    private String updateTime;
    /**
     * <pre>
     * 字段名:失败原因
     * 变量名:reason
     * 是否必填:是
     * 类型:string[1, 255]
     * 描述:
     *  仅在提现失败、退票、关单时有值
     *  示例值:卡号错误
     * </pre>
     */
    @JsonProperty(value = "reason")
    private String reason;
    /**
     * <pre>
     * 字段名:提现备注
     * 变量名:remark
     * 是否必填:是
     * 类型:string[1, 56]
     * 描述:
     *  商户对提现单的备注,若发起提现时未传入相应值或输入不合法,则该值为空
     *  示例值:交易提现
     * </pre>
     */
    @JsonProperty(value = "remark")
    private String remark;
    /**
     * <pre>
     * 字段名:银行附言
     * 变量名:bank_memo
     * 是否必填:是
     * 类型:string[1, 32]
     * 描述:
     *  展示在收款银行系统中的附言,由数字、字母、汉字组成(能否成功展示依赖银行系统支持)。若发起提现时未传入相应值或输入不合法,则该值为空
     *  示例值:微信提现
     * </pre>
     */
    @JsonProperty(value = "bank_memo")
    private String bankMemo;
    /**
     * <pre>
     * 字段名:出款账户类型
     * 变量名:account_type
     * 是否必填:是
     * 类型:string[1,16]
     * 描述:
     *  BASIC:基本户
     *  OPERATION:运营账户
     *  FEES:手续费账户
     *  示例值:BASIC
     * </pre>
     */
    @JsonProperty(value = "account_type")
    private String accountType;
    /**
     * <pre>
     * 字段名:提现失败解决方案
     * 变量名:solution
     * 是否必填:是
     * 类型:string[1, 255]
     * 描述:
     *  仅在提现失败、退票、关单时有值
     *  示例值:请修改结算银行卡信息
     * </pre>
     */
    @JsonProperty(value = "solution")
    private String solution;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/fund/WithdrawStatusForSubMchResponse.java
New file
@@ -0,0 +1,192 @@
package com.ruoyi.order.tools.response.ecommerce.fund;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商平台通过查询提现状态API查询二级商户提现单的提现结果。 该查询服务提供两种查询方式(两种查询方式返回结果一致): 方式1:微信支付提现单号查询; 方式2:商户提现单号查询。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_3.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEM_ERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * 403    REQUEST_BLOCKED    二级商户未开启手动提现权限    二级商户号提现权限被冻结,无法发起提现
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用,电商平台提交相同商户单号的请求但参数和历史提交的参数不一致
 * 404    ORDER_NOT_EXIST    提现单号不存在    请检查订单号是否正确
 * 403    NOT_ENOUGH    二级商户号账户可用余额不足    二级商户号账户可用余额不足
 * 403    NO_AUTH    无接口使用权限    请开通商户号相关权限
 * 400    INVALID_REQUEST    二级商户未开启手动提现权限    请确认电商平台商户号和二级商户商户号是否存在受理关系
 * 429    FREQUENCY_LIMITED    频率限制    请降低频率后重试
 * 403    CONTRACT_NOT_CONFIRM    二级商户未开启手动提现权限    二级商户号提现权限已关闭,无法发起提现
 * 403    ACCOUNT_NOT_VERIFIED    二级商户下行打款未成功    二级商户号结算银行卡信息有误,修改后重试
 * 403    ACCOUNT_ERROR    二级商户未绑卡    二级商户号没有绑定结算银行卡,绑定后重试
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class WithdrawStatusForSubMchResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1, 32]
     * 描述:
     *  电商平台二级商户号,由微信支付生成并下发。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:电商平台商户号
     * 变量名:sp_mchid
     * 是否必填:是
     * 类型:string[1, 32]
     * 描述:
     *  电商平台商户号
     *  示例值:1800000123
     * </pre>
     */
    @JsonProperty(value = "sp_mchid")
    private String spMchid;
    /**
     * <pre>
     * 字段名:提现单状态
     * 变量名:status
     * 是否必填:是
     * 类型:string[1,16]
     * 描述:
     *  枚举值:
     *  CREATE_SUCCESS:受理成功
     *  SUCCESS:提现成功
     *  FAIL:提现失败
     *  REFUND:提现退票
     *  CLOSE:关单
     *  INIT:业务单已创建
     *  示例值:CREATE_SUCCESS
     * </pre>
     */
    @JsonProperty(value = "status")
    private String status;
    /**
     * <pre>
     * 字段名:微信支付提现单号
     * 变量名:withdraw_id
     * 是否必填:是
     * 类型:string[1, 128]
     * 描述:
     *  电商平台提交二级商户提现申请后,由微信支付返回的申请单号,作为查询申请状态的唯一标识。
     *  示例值:12321937198237912739132791732912793127
     * </pre>
     */
    @JsonProperty(value = "withdraw_id")
    private String withdrawId;
    /**
     * <pre>
     * 字段名:商户提现单号
     * 变量名:out_request_no
     * 是否必填:是
     * 类型:string[1, 32]
     * 描述:
     *  商户提现单号
     *  示例值:20190611222222222200000000012122
     * </pre>
     */
    @JsonProperty(value = "out_request_no")
    private String outRequestNo;
    /**
     * <pre>
     * 字段名:提现金额
     * 变量名:amount
     * 是否必填:是
     * 类型:int
     * 描述:
     *  单位:分
     *  示例值:1
     * </pre>
     */
    @JsonProperty(value = "amount")
    private Integer amount;
    /**
     * <pre>
     * 字段名:发起提现时间
     * 变量名:create_time
     * 是否必填:是
     * 类型:string[29, 29]
     * 描述:
     *  遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss:sss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss:sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日13点29分35秒。
     *  示例值:2015-05-20T13:29:35.120+08:00
     * </pre>
     */
    @JsonProperty(value = "create_time")
    private String createTime;
    /**
     * <pre>
     * 字段名:提现状态更新时间
     * 变量名:update_time
     * 是否必填:是
     * 类型:string[29, 29]
     * 描述:
     *  遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss:sss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss:sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日13点29分35秒。
     *  示例值:2015-05-20T13:29:35.120+08:00
     * </pre>
     */
    @JsonProperty(value = "update_time")
    private String updateTime;
    /**
     * <pre>
     * 字段名:失败原因
     * 变量名:reason
     * 是否必填:是
     * 类型:string[1, 255]
     * 描述:
     *  提现失败原因,仅在提现失败、退票、关单时有值
     *  示例值:卡号错误
     * </pre>
     */
    @JsonProperty(value = "reason")
    private String reason;
    /**
     * <pre>
     * 字段名:提现备注
     * 变量名:remark
     * 是否必填:是
     * 类型:string[1, 56]
     * 描述:
     *  商户对提现单的备注,若发起提现时未传入相应值或输入不合法,则该值为空
     *  示例值:交易提现
     * </pre>
     */
    @JsonProperty(value = "remark")
    private String remark;
    /**
     * <pre>
     * 字段名:银行附言
     * 变量名:bank_memo
     * 是否必填:是
     * 类型:string[1, 32]
     * 描述:
     *  展示在收款银行系统中的附言,由数字、字母、汉字组成(能否成功展示依赖银行系统支持)。若发起提现时未传入相应值或输入不合法,则该值为空
     *  示例值:微信提现
     * </pre>
     */
    @JsonProperty(value = "bank_memo")
    private String bankMemo;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/profitsharing/ProfitSharingAddReceiverResponse.java
New file
@@ -0,0 +1,57 @@
package com.ruoyi.order.tools.response.ecommerce.profitsharing;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 1. 电商平台可通过此接口添加分账接收方,建立分账接收方列表。后续通过发起分账请求,将电商平台下的二级商户结算后的资金,分给分账接收方列表中具体的分账接收方。 2. 添加的分账接收方统一都在电商平台维度进行管理,其他二级商户,均可向该分账接收方列表中的接收方进行分账,避免在二级商户维度重复维护。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_7.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEM_ERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * 400    PARAM_ERROR    请求参数不符合参数格式    请使用正确的参数重新调用
 * 400    INVALID_REQUEST    无效请求    请确认分账接收方是否存在
 * 403    NO_AUTH    商户无权限    请开通商户号分账权限
 * 429    FREQUENCY_LIMITED    添加接收方频率过高    请降低频率后重试
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ProfitSharingAddReceiverResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:接收方类型
     * 变量名:type
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  分账接收方的类型,枚举值:
     *  MERCHANT_ID:商户
     *  PERSONAL_OPENID:个人
     *  示例值:MERCHANT_ID
     * </pre>
     */
    @JsonProperty(value = "type")
    private String type;
    /**
     * <pre>
     * 字段名:接收方账号
     * 变量名:account
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  分账接收方的账号
     *  类型是MERCHANT_ID时,是商户号
     *  类型是PERSONAL_OPENID时,是个人openid
     *  示例值:190001001
     * </pre>
     */
    @JsonProperty(value = "account")
    private String account;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/profitsharing/ProfitSharingApplyResponse.java
New file
@@ -0,0 +1,261 @@
package com.ruoyi.order.tools.response.ecommerce.profitsharing;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 微信订单支付成功后,由电商平台发起分账请求,将结算后的资金分给分账接收方。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_1.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEM_ERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * 400    PARAM_ERROR    订单号格式不正确    请使用正确的参数重新调用
 * 400    INVALID_REQUEST    非分账订单不支持分账    请根据返回的错误信息确认违反的业务规则
 * 429    FREQUENCY_LIMITED    对同笔订单分账频率过高    请降低频率后重试
 * 403    RULE_LIMIT    分账金额超出最大分账比例    分账金额超出最大分账比例
 * 403    NO_AUTH    商户无权限    请开通商户号分账权限
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ProfitSharingApplyResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  分账出资的电商平台二级商户,填写微信支付分配的商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:微信订单号
     * 变量名:transaction_id
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  微信支付订单号。
     *  示例值: 4208450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "transaction_id")
    private String transactionId;
    /**
     * <pre>
     * 字段名:商户分账单号
     * 变量名:out_order_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  商户系统内部的分账单号,在商户系统内部唯一(单次分账、多次分账、完结分账应使用不同的商户分账单号),同一分账单号多次请求等同一次。
     *  示例值:P20150806125346
     * </pre>
     */
    @JsonProperty(value = "out_order_no")
    private String outOrderNo;
    /**
     * <pre>
     * 字段名:微信分账单号
     * 变量名:order_id
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  微信分账单号,微信系统返回的唯一标识。
     *  示例值: 6754760740201411110007865434
     * </pre>
     */
    @JsonProperty(value = "order_id")
    private String orderId;
    /**
     * <pre>
     * 字段名:分账单状态
     * 变量名:status
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  分账单状态,枚举值:
     * PROCESSING:处理中
     * FINISHED:处理完成
     *  示例值: FINISHED
     * </pre>
     */
    @JsonProperty(value = "status")
    private String status;
    /**
     * <pre>
     * 字段名:分账接收方列表
     * 变量名:receivers
     * 是否必填:是
     * 类型:array
     * 描述:
     *  分账接收方列表
     * </pre>
     */
    @JsonProperty(value = "status")
    private Receivers receivers;
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class Receivers {
        /**
         * <pre>
         * 字段名:分账金额
         * 变量名:amount
         * 是否必填:是
         * 类型:int
         * 描述:
         *  分账金额,单位为分,只能为整数,不能超过原订单支付金额及最大分账比例金额。
         *  示例值:10
         * </pre>
         */
        @JsonProperty(value = "amount")
        private Integer amount;
        /**
         * <pre>
         * 字段名:分账描述
         * 变量名:description
         * 是否必填:是
         * 类型:string[1,80]
         * 描述:
         *  分账的原因描述,将体现在资金账单和分账账单中。
         *  示例值:分帐1900000110
         * </pre>
         */
        @JsonProperty(value = "description")
        private String description;
        /**
         * <pre>
         * 字段名:分账失败原因
         * 变量名:fail_reason
         * 是否必填:否
         * 类型:string[1,32]
         * 描述:
         *  分账失败原因,当分账结果result为CLOSED(已关闭)时,返回该字段
         * 枚举值:
         * 1、ACCOUNT_ABNORMAL : 分账接收账户异常
         * 2、NO_RELATION : 分账关系已解除
         * 3、RECEIVER_HIGH_RISK : 高风险接收方
         * 4、RECEIVER_REAL_NAME_NOT_VERIFIED : 接收方未实名
         * 5、NO_AUTH : 分账权限已解除
         * 6、RECEIVER_RECEIPT_LIMIT : 接收方已达收款限额
         * 7、PAYER_ACCOUNT_ABNORMAL : 分出方账户异常
         *  示例值:NO_RELATION
         * </pre>
         */
        @JsonProperty(value = "fail_reason")
        private String failReason;
        /**
         * <pre>
         * 字段名:分账明细单号
         * 变量名:detail_id
         * 是否必填:是
         * 类型:string[1,64]
         * 描述:
         *  微信分账明细单号,每笔分账业务执行的明细单号,可与资金账单对账使用
         *  示例值:36011111111111111111111
         * </pre>
         */
        @JsonProperty(value = "detail_id")
        private String detailId;
        /**
         * <pre>
         * 字段名:完成时间
         * 变量名:finish_time
         * 是否必填:是
         * 类型:string[1,64]
         * 描述:
         *  分账完成时间,遵循RFC3339标准格式,格式为
         * yyyy-MM-DDTHH:mm:ss.sss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,
         * TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35:120+08:00表示北京时间2015年05月20日13点29分35秒。
         *  示例值:2015-05-20T13:29:35.120+0
         * </pre>
         */
        @JsonProperty(value = "finish_time")
        private String finishTime;
        /**
         * <pre>
         * 字段名:分账接收方账号
         * 变量名:receiver_account
         * 是否必填:是
         * 类型:string[1,64]
         * 描述:
         *  分账接收方账号:
         * 类型是MERCHANT_ID时,是商户号(mch_id或者sub_mch_id)
         * 类型是PERSONAL_OPENID时,是个人openid,
         *  示例值:1900000109
         * </pre>
         */
        @JsonProperty(value = "receiver_account")
        private String receiverAccount;
        /**
         * <pre>
         * 字段名:分账接收商户号
         * 变量名:receiver_mchid
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  仅分账接收方类型为MERCHANT_ID时,填写微信支付分配的商户号
         *  示例值:1900000110
         * </pre>
         */
        @JsonProperty(value = "receiver_mchid")
        private String receiverMchid;
        /**
         * <pre>
         * 字段名:分账结果
         * 变量名:result
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  枚举值:
         * PENDING:待分账
         * SUCCESS:分账成功
         * CLOSED:已关闭
         *  示例值:SUCCESS
         * </pre>
         */
        @JsonProperty(value = "result")
        private String result;
        /**
         * <pre>
         * 字段名:分账接收方类型
         * 变量名:type
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  枚举值:
         * MERCHANT_ID:商户号(mch_id或者sub_mch_id)
         * PERSONAL_OPENID:个人openid(由服务商的APPID转换得到)
         * PERSONAL_SUB_OPENID:个人sub_openid(由品牌主的APPID转换得到)
         *  示例值:MERCHANT_ID
         * </pre>
         */
        @JsonProperty(value = "type")
        private String type;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/profitsharing/ProfitSharingFinishResponse.java
New file
@@ -0,0 +1,83 @@
package com.ruoyi.order.tools.response.ecommerce.profitsharing;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 不需要进行分账的订单,可直接调用本接口将订单的金额全部解冻给二级商户。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_5.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEM_ERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * 400    PARAM_ERROR    订单号格式不正确    请使用正确的参数重新调用
 * 400    INVALID_REQUEST    非分账订单不支持完结分账    请根据返回的错误信息确认违反的业务规则
 * 订单处理中,请稍后重试    订单未正常结算(如余额不足等原因)
 * 429    FREQUENCY_LIMITED    对同笔订单分账频率过高    请降低频率后重试
 * 403    NOT_ENOUGH    分账金额为0    分账已完成,无需再请求分账完结
 * 403    NO_AUTH    商户无权限    请开通商户号分账权限
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ProfitSharingFinishResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  分账出资的电商平台二级商户,填写微信支付分配的商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:微信订单号
     * 变量名:transaction_id
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  微信支付订单号。
     *  示例值: 4208450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "transaction_id")
    private String transactionId;
    /**
     * <pre>
     * 字段名:商户分帐单号
     * 变量名:out_order_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  商户系统内部的分账单号,在商户系统内部唯一(单次分账、多次分账、完结分账应使用不同的商户分账单号),同一分账单号多次请求等同一次。
     *  示例值:P20150806125346
     * </pre>
     */
    @JsonProperty(value = "out_order_no")
    private String outOrderNo;
    /**
     * <pre>
     * 字段名:微信分帐单号
     * 变量名:order_id
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  微信分账单号,微信系统返回的唯一标识。
     *  示例值: 3008450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "order_id")
    private String orderId;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/profitsharing/ProfitSharingNotifyResponse.java
New file
@@ -0,0 +1,47 @@
package com.ruoyi.order.tools.response.ecommerce.profitsharing;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 1、此功能仅针对分账接收方。 2、分账动账金额变动后,微信会把相关变动结果发送给需要实时关注的分账接收方。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_6.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ProfitSharingNotifyResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:返回状态码
     * 变量名:code
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  错误码,SUCCESS为接收成功,其他错误码为失败。
     *  示例值:SUCCESS
     * </pre>
     */
    @JsonProperty(value = "code")
    private String code;
    /**
     * <pre>
     * 字段名:返回信息
     * 变量名:message
     * 是否必填:否
     * 类型:string[1,256]
     * 描述:
     *  返回信息,如非空,为错误原因。
     *  示例值:系统错误
     * </pre>
     */
    @JsonProperty(value = "message")
    private String message;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/profitsharing/ProfitSharingQueryApplyResponse.java
New file
@@ -0,0 +1,283 @@
package com.ruoyi.order.tools.response.ecommerce.profitsharing;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
 * <pre>
 * 发起分账请求后,可调用此接口查询分账结果 ;发起分账完结请求后,可调用此接口查询分账完结的结果
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_2.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEM_ERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * 400    PARAM_ERROR    商户号未设置    请使用正确的参数重新调用
 * 429    FREQUENCY_LIMITED    频率限制    请降低频率后重试
 * 404    RESOURCE_NOT_EXISTS    记录不存在    请检查请求的单号是否正确
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ProfitSharingQueryApplyResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  分账出资的电商平台二级商户,填写微信支付分配的商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:微信订单号
     * 变量名:transaction_id
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  微信支付订单号。
     *  示例值: 4208450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "transaction_id")
    private String transactionId;
    /**
     * <pre>
     * 字段名:商户分账单号
     * 变量名:out_order_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  商户系统内部的分账单号,在商户系统内部唯一(单次分账、多次分账、完结分账应使用不同的商户分账单号),同一分账单号多次请求等同一次。
     *  示例值:P20150806125346
     * </pre>
     */
    @JsonProperty(value = "out_order_no")
    private String outOrderNo;
    /**
     * <pre>
     * 字段名:微信分账单号
     * 变量名:order_id
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  微信分账单号,微信系统返回的唯一标识
     *  示例值: 008450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "order_id")
    private String orderId;
    /**
     * <pre>
     * 字段名:分账单状态
     * 变量名:status
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  分账单状态,枚举值:
     *  PROCESSING:处理中
     *  FINISHED:处理完成
     *  示例值:FINISHED
     * </pre>
     */
    @JsonProperty(value = "status")
    private String status;
    /**
     * <pre>
     * 字段名:+分账接收方列表
     * 变量名:receivers
     * 是否必填:否
     * 类型:array
     * 描述:分账接收方列表。当查询分账完结的执行结果时,不返回该字段
     * </pre>
     */
    @JsonProperty(value = "receivers")
    private List<Receivers> receivers;
    /**
     * <pre>
     * 字段名:关单原因
     * 变量名:close_reason
     * 是否必填:否
     * 类型:string[1,32]
     * 描述:
     *  关单原因描述,当分账单状态status为CLOSED(处理失败,已关单)时,返回该字段。
     *  枚举值:
     *  NO_AUTH:分账授权已解除
     *  示例值:NO_AUTH
     * </pre>
     */
    @JsonProperty(value = "close_reason")
    private String closeReason;
    /**
     * <pre>
     * 字段名:分账完结金额
     * 变量名:finish_amount
     * 是否必填:否
     * 类型:int
     * 描述:
     *  分账完结的分账金额,单位为分, 仅当查询分账完结的执行结果时,存在本字段。
     *  示例值:100
     * </pre>
     */
    @JsonProperty(value = "finish_amount")
    private Integer finishAmount;
    /**
     * <pre>
     * 字段名:分账完结描述
     * 变量名:finish_description
     * 是否必填:否
     * 类型:string[1,80]
     * 描述:
     *  分账完结的原因描述,仅当查询分账完结的执行结果时,存在本字段。
     *  示例值:分账完结
     * </pre>
     */
    @JsonProperty(value = "finish_description")
    private String finishDescription;
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class Receivers {
        /**
         * <pre>
         * 字段名:分账接收商户号
         * 变量名:receiver_mchid
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  填写微信支付分配的商户号,仅支持通过添加分账接收方接口添加的接收方;电商平台商户已默认添加到分账接收方,无需重复添加。
         *  示例值:1900000109
         * </pre>
         */
        @JsonProperty(value = "receiver_mchid")
        private String receiverMchid;
        /**
         * <pre>
         * 字段名:分账金额
         * 变量名:amount
         * 是否必填:是
         * 类型:int
         * 描述:
         *  分账金额,单位为分,只能为整数,不能超过原订单支付金额及最大分账比例金额。
         *  示例值: 4208450740201411110007820472
         * </pre>
         */
        @JsonProperty(value = "amount")
        private Integer amount;
        /**
         * <pre>
         * 字段名:分账描述
         * 变量名:description
         * 是否必填:是
         * 类型:string[1,80]
         * 描述:
         *  分账的原因描述,分账账单中需要体现。
         *  示例值:分帐1900000110
         * </pre>
         */
        @JsonProperty(value = "description")
        private String description;
        /**
         * <pre>
         * 字段名:分账结果
         * 变量名:result
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  分账结果,枚举值:
         *  PENDING:待分账
         *  SUCCESS:分账成功
         *  CLOSED:分账失败已关闭
         *  示例值:SUCCESS
         * </pre>
         */
        @JsonProperty(value = "result")
        private String result;
        /**
         * <pre>
         * 字段名:完成时间
         * 变量名:finish_time
         * 是否必填:是
         * 类型:string[1,64]
         * 描述:
         *  分账完成时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss.sss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示,北京时间2015年5月20日 13点29分35秒。
         *  示例值: 2015-05-20T13:29:35.120+08:00
         * </pre>
         */
        @JsonProperty(value = "finish_time")
        private String finishTime;
        /**
         * <pre>
         * 字段名:分账失败原因
         * 变量名:fail_reason
         * 是否必填:否
         * 类型:string[1,32]
         * 描述:
         *  分账失败原因,当分账结果result为RETURNED(已转回分账方)或CLOSED(已关闭)时,返回该字段
         *  枚举值:
         *  ACCOUNT_ABNORMAL:分账接收账户异常
         *  NO_RELATION:分账关系已解除
         *  RECEIVER_HIGH_RISK:高风险接收方
         *  示例值:NO_RELATION
         * </pre>
         */
        @JsonProperty(value = "fail_reason")
        private String failReason;
        /**
         * <pre>
         * 字段名:分账接收方类型
         * 变量名:type
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  分账接收方类型,枚举值:
         *  MERCHANT_ID:商户
         *  PERSONAL_OPENID:个人
         *  示例值:MERCHANT_ID
         * </pre>
         */
        @JsonProperty(value = "type")
        private String type;
        /**
         * <pre>
         * 字段名:分账接收方账号
         * 变量名:receiver_account
         * 是否必填:是
         * 类型:string[1,64]
         * 描述:
         *  分账接收方账号:
         *  类型是MERCHANT_ID时,是商户号(mch_id或者sub_mch_id)
         *  类型是PERSONAL_OPENID时,是个人openid
         *  示例值:1900000109
         * </pre>
         */
        @JsonProperty(value = "receiver_account")
        private String receiverAccount;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/profitsharing/ProfitSharingQueryRefundResponse.java
New file
@@ -0,0 +1,172 @@
package com.ruoyi.order.tools.response.ecommerce.profitsharing;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 商户需要核实回退结果,可调用此接口查询回退结果;如果分账回退接口返回状态为处理中,可调用此接口查询回退结果
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_4.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEM_ERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * 400    PARAM_ERROR    商户号未设置    请使用正确的参数重新调用
 * 429    FREQUENCY_LIMITED    频率限制    请降低频率后重试
 * 404    RESOURCE_NOT_EXISTS    记录不存在    请检查请求的单号是否正确
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ProfitSharingQueryRefundResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  分账回退的接收商户,对应原分账出资的电商平台二级商户,填写微信支付分配的商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:微信分账单号
     * 变量名:order_id
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  原发起分账请求时,微信返回的微信分账单号,与商户分账单号一一对应。 微信分账单号与商户分账单号二选一填写。
     *  示例值: 3008450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "order_id")
    private String orderId;
    /**
     * <pre>
     * 字段名:商户分账单号
     * 变量名:out_order_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  原发起分账请求时使用的商户后台系统的分账单号。 微信分账单号与商户分账单号二选一填写。
     *  示例值:P20150806125346
     * </pre>
     */
    @JsonProperty(value = "out_order_no")
    private String outOrderNo;
    /**
     * <pre>
     * 字段名:商户回退单号
     * 变量名:out_return_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  此回退单号是商户在自己后台生成的一个新的回退单号,在商户后台唯一 只能是数字、大小写字母_-*@ ,同一回退单号多次请求等同一次。
     *  示例值:p86691234
     * </pre>
     */
    @JsonProperty(value = "out_return_no")
    private String outReturnNo;
    /**
     * <pre>
     * 字段名:回退商户号
     * 变量名:return_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  只能对原分账请求中成功分给商户接收方进行回退。
     *  示例值:86693852
     * </pre>
     */
    @JsonProperty(value = "return_mchid")
    private String returnMchid;
    /**
     * <pre>
     * 字段名:微信回退单号
     * 变量名:return_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  微信分账回退单号,微信系统返回的唯一标识。
     *  示例值:3008450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "return_no")
    private String returnNo;
    /**
     * <pre>
     * 字段名:回退金额
     * 变量名:amount
     * 是否必填:是
     * 类型:int
     * 描述:
     *  需要从分账接收方回退的金额,单位为分,只能为整数,不能超过原始分账单分出给该接收方的金额。
     *  示例值:10
     * </pre>
     */
    @JsonProperty(value = "amount")
    private Integer amount;
    /**
     * <pre>
     * 字段名:回退结果
     * 变量名:result
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  如果请求返回为处理中,则商户可以通过调用回退结果查询接口获取请求的最终处理结果,枚举值:
     *  PROCESSING:处理中
     *  SUCCESS:已成功
     *  FAILED:已失败
     *
     *  注意:如果返回为处理中,请勿变更商户回退单号,使用相同的参数再次发起分账回退,否则会出现资金风险 在处理中状态的回退单如果5天没有成功,会因为超时被设置为已失败
     *  示例值:SUCCESS
     * </pre>
     */
    @JsonProperty(value = "result")
    private String result;
    /**
     * <pre>
     * 字段名:失败原因
     * 变量名:fail_reason
     * 是否必填:否
     * 类型:string[1,32]
     * 描述:
     *  回退失败的原因,此字段仅回退结果为FAIL时存在,枚举值:
     *  ACCOUNT_ABNORMAL:分账接收方账户异常
     *  TIME_OUT_CLOSED:超时关单
     *  示例值:TIME_OUT_CLOSED
     * </pre>
     */
    @JsonProperty(value = "fail_reason")
    private String failReason;
    /**
     * <pre>
     * 字段名:完成时间
     * 变量名:finish_time
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  分账回退完成时间,遵循rfc3339标准格式
     *  格式为YYYY-MM-DDTHH:mm:ss.sss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示,北京时间2015年5月20日 13点29分35秒。
     *  示例值:2015-05-20T13:29:35.120+08:00
     * </pre>
     */
    @JsonProperty(value = "finish_time")
    private String finishTime;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/profitsharing/ProfitSharingRefundResponse.java
New file
@@ -0,0 +1,174 @@
package com.ruoyi.order.tools.response.ecommerce.profitsharing;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 订单已经分账,在退款时,可以先调此接口,将已分账的资金从分账接收方的账户回退给分账方,再发起退款。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_3.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEM_ERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * 403    NOT_ENOUGH    剩余可回退的金额不足    调整回退金额
 * 400    PARAM_ERROR    订单号格式不正确    请使用正确的参数重新调用
 * 400    INVALID_REQUEST    回退方不存在    请根据返回的错误信息确认违反的业务规则
 * 429    FREQUENCY_LIMITED    商户发起分账回退的频率过高    请降低频率后重试
 * 403    NO_AUTH    回退方未开通分账回退功能    请先让回退方开通分账回退功能
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ProfitSharingRefundResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  分账出资的电商平台二级商户,填写微信支付分配的商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:微信分账单号
     * 变量名:order_id
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  原发起分账请求时,微信返回的微信分账单号,与商户分账单号一一对应。 微信分账单号与商户分账单号二选一填写。
     *  示例值: 3008450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "order_id")
    private String orderId;
    /**
     * <pre>
     * 字段名:商户分账单号
     * 变量名:out_order_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  商户系统内部的分账单号,在商户系统内部唯一(单次分账、多次分账、完结分账应使用不同的商户分账单号),同一分账单号多次请求等同一次。
     *  示例值:P20150806125346
     * </pre>
     */
    @JsonProperty(value = "out_order_no")
    private String outOrderNo;
    /**
     * <pre>
     * 字段名:商户回退单号
     * 变量名:out_return_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  此回退单号是商户在自己后台生成的一个新的回退单号,在商户后台唯一 只能是数字、大小写字母_-*@ ,同一回退单号多次请求等同一次。
     *  示例值:R20190516001
     * </pre>
     */
    @JsonProperty(value = "out_return_no")
    private String outReturnNo;
    /**
     * <pre>
     * 字段名:回退商户号
     * 变量名:return_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  只能对原分账请求中成功分给商户接收方进行回退。
     *  示例值:86693852
     * </pre>
     */
    @JsonProperty(value = "return_mchid")
    private String returnMchid;
    /**
     * <pre>
     * 字段名:回退金额
     * 变量名:amount
     * 是否必填:是
     * 类型:int
     * 描述:
     *  需要从分账接收方回退的金额,单位为分,只能为整数,不能超过原始分账单分出给该接收方的金额。
     *  示例值:10
     * </pre>
     */
    @JsonProperty(value = "amount")
    private Integer amount;
    /**
     * <pre>
     * 字段名:微信回退单号
     * 变量名:return_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  微信分账回退单号,微信系统返回的唯一标识。
     *  示例值: 3008450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "return_no")
    private String returnNo;
    /**
     * <pre>
     * 字段名:回退结果
     * 变量名:result
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  如果请求返回为处理中,则商户可以通过调用回退结果查询接口获取请求的最终处理结果,枚举值:
     *  PROCESSING:处理中
     *  SUCCESS:已成功
     *  FAILED:已失败
     *
     *  注意:如果返回为处理中,请勿变更商户回退单号,使用相同的参数再次发起分账回退,否则会出现资金风险 在处理中状态的回退单如果5天没有成功,会因为超时被设置为已失败
     *  示例值:SUCCESS
     * </pre>
     */
    @JsonProperty(value = "result")
    private String result;
    /**
     * <pre>
     * 字段名:失败原因
     * 变量名:fail_reason
     * 是否必填:否
     * 类型:string[1,32]
     * 描述:
     *  回退失败的原因,此字段仅回退结果为FAIL时存在,枚举值:
     *  ACCOUNT_ABNORMAL:分账接收方账户异常
     *  TIME_OUT_CLOSED::超时关单
     *  示例值:TIME_OUT_CLOSED
     * </pre>
     */
    @JsonProperty(value = "fail_reason")
    private String failReason;
    /**
     * <pre>
     * 字段名:完成时间
     * 变量名:finish_time
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  分账回退完成时间,遵循rfc3339标准格式
     * 格式为YYYY-MM-DDTHH:mm:ss.sss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35.120+08:00表示,北京时间2015年5月20日 13点29分35秒。
     *  示例值:2015-05-20T13:29:35.120+08:00
     * </pre>
     */
    @JsonProperty(value = "finish_time")
    private String finishTime;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/profitsharing/ProfitSharingRemoveReceiverResponse.java
New file
@@ -0,0 +1,57 @@
package com.ruoyi.order.tools.response.ecommerce.profitsharing;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 电商平台发起删除分账接收方请求。删除后,不支持将电商平台下二级商户结算后的资金,分到该分账接收方。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_8.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEM_ERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * 400    PARAM_ERROR    请求参数不符合参数格式    请使用正确的参数重新调用
 * 400    INVALID_REQUEST    无效请求    请确认分账接收方是否存在
 * 403    NO_AUTH    商户无权限    请开通商户号分账权限
 * 429    FREQUENCY_LIMITED    删除接收方频率过高    请降低频率后重试
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ProfitSharingRemoveReceiverResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:接收方类型
     * 变量名:type
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  分账接收方的类型,枚举值:
     *  MERCHANT_ID:商户
     *  PERSONAL_OPENID:个人
     *  示例值:MERCHANT_ID
     * </pre>
     */
    @JsonProperty(value = "type")
    private String type;
    /**
     * <pre>
     * 字段名:接收方账号
     * 变量名:account
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  分账接收方的账号
     *  类型是MERCHANT_ID时,是商户号
     *  类型是PERSONAL_OPENID时,是个人openid
     *  示例值:190001001
     * </pre>
     */
    @JsonProperty(value = "account")
    private String account;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/refunds/RefundApplyResponse.java
New file
@@ -0,0 +1,243 @@
package com.ruoyi.order.tools.response.ecommerce.refunds;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
 * <pre>
 * 当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,微信支付将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家账号上。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/refunds/chapter3_1.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEM_ERROR    接口返回错误    请不要更换商户退款单号,请使用相同参数再次调用API。
 * 404    RESOURCE_NOT_EXISTS    订单不存在    请检查订单号是否正确且是否已支付,未支付的订单不能发起退款
 * 400    PARAM_ERROR    参数错误    请求参数错误,请重新检查再调用退款申请
 * 429    FREQUENCY_LIMITED    频率限制    该笔退款未受理,请降低频率后重试
 * 403    NOT_ENOUGH    余额不足    此状态代表退款申请失败,商户可根据具体的错误提示做相应的处理。
 * 403    USER_ACCOUNT_ABNORMAL    退款请求失败    此状态代表退款申请失败,商户可自行处理退款。
 * 403    NO_AUTH    没有退款权限    此状态代表退款申请失败,请检查是否有退这笔订单的权限
 * 401    SIGN_ERROR    签名错误    请检查签名参数和方法是否都符合签名算法要求
 * 400    INVALID_REQUEST    请求参数符合参数格式,但不符合业务规则    此状态代表退款申请失败,商户可根据具体的错误提示做相应的处理。
 * 400    MCH_NOT_EXISTS    商户号不存在    请检查商户号是否正确
 * 403    REQUEST_BLOCKED    请求受阻    此状态代表退款申请失败,商户可根据具体的错误提示做相应的处理。
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class RefundApplyResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:微信退款单号
     * 变量名:refund_id
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  微信支付退款订单号。
     *  示例值:1217752501201407033233368018
     * </pre>
     */
    @JsonProperty(value = "refund_id")
    private String refundId;
    /**
     * <pre>
     * 字段名:商户退款单号
     * 变量名:out_refund_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔。
     *  示例值:1217752501201407033233368018
     * </pre>
     */
    @JsonProperty(value = "out_refund_no")
    private String outRefundNo;
    /**
     * <pre>
     * 字段名:退款创建时间
     * 变量名:create_time
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  退款受理时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日13点29分35秒。
     *  示例值:2018-06-08T10:34:56+08:00
     * </pre>
     */
    @JsonProperty(value = "create_time")
    private String createTime;
    /**
     * <pre>
     * 字段名:+订单金额
     * 变量名:amount
     * 是否必填:是
     * 类型:object
     * 描述:订单金额信息
     * </pre>
     */
    @JsonProperty(value = "amount")
    private Amount amount;
    /**
     * <pre>
     * 字段名:+优惠退款详情
     * 变量名:promotion_detail
     * 是否必填:否
     * 类型:array
     * 描述:
     *  优惠退款功能信息,discount_refund>0时,返回该字段
     *  示例值:见示例
     * </pre>
     */
    @JsonProperty(value = "promotion_detail")
    private List<PromotionDetail> promotionDetail;
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class Amount {
        /**
         * <pre>
         * 字段名:退款金额
         * 变量名:refund
         * 是否必填:是
         * 类型:int
         * 描述:
         *  退款金额,币种的最小单位,只能为整数,不能超过原订单支付金额。
         *  示例值:888
         * </pre>
         */
        @JsonProperty(value = "refund")
        private Integer refund;
        /**
         * <pre>
         * 字段名:用户退款金额
         * 变量名:payer_refund
         * 是否必填:是
         * 类型:int
         * 描述:
         *  退款给用户的金额,不包含所有优惠券金额。
         *  示例值:888
         * </pre>
         */
        @JsonProperty(value = "payer_refund")
        private Integer payerRefund;
        /**
         * <pre>
         * 字段名:优惠退款金额
         * 变量名:discount_refund
         * 是否必填:是
         * 类型:int
         * 描述:
         *  优惠券的退款金额,原支付单的优惠按比例退款。
         *  示例值:888
         * </pre>
         */
        @JsonProperty(value = "discount_refund")
        private Integer discountRefund;
        /**
         * <pre>
         * 字段名:退款币种
         * 变量名:currency
         * 是否必填:是
         * 类型:string[1,18]
         * 描述:
         *  符合ISO 4217标准的三位字母代码,目前只支持人民币:CNY 。
         *  示例值:CNY
         * </pre>
         */
        @JsonProperty(value = "currency")
        private String currency;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class PromotionDetail {
        /**
         * <pre>
         * 字段名:券ID
         * 变量名:promotion_id
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  券或者立减优惠id。
         *  示例值:109519
         * </pre>
         */
        @JsonProperty(value = "promotion_id")
        private String promotionId;
        /**
         * <pre>
         * 字段名:优惠范围
         * 变量名:scope
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  枚举值:
         *  GLOBAL:全场代金券
         *  SINGLE:单品优惠
         *  示例值:SINGLE
         * </pre>
         */
        @JsonProperty(value = "scope")
        private String scope;
        /**
         * <pre>
         * 字段名:优惠类型
         * 变量名:type
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  枚举值:
         *  COUPON:充值型代金券,商户需要预先充值营销经费
         *  DISCOUNT:免充值型优惠券,商户不需要预先充值营销经费
         *  示例值:DISCOUNT
         * </pre>
         */
        @JsonProperty(value = "type")
        private String type;
        /**
         * <pre>
         * 字段名:优惠券面额
         * 变量名:amount
         * 是否必填:是
         * 类型:int
         * 描述:
         *  用户享受优惠的金额(优惠券面额=微信出资金额+商家出资金额+其他出资方金额 )。
         *  示例值:5
         * </pre>
         */
        @JsonProperty(value = "amount")
        private Integer amount;
        /**
         * <pre>
         * 字段名:优惠退款金额
         * 变量名:refund_amount
         * 是否必填:是
         * 类型:int
         * 描述:
         *  代金券退款金额<=退款金额,退款金额-代金券或立减优惠退款金额为现金,说明详见《代金券或立减优惠》 。
         *  示例值:100
         * </pre>
         */
        @JsonProperty(value = "refund_amount")
        private Integer refundAmount;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/refunds/RefundNotifyResponse.java
New file
@@ -0,0 +1,47 @@
package com.ruoyi.order.tools.response.ecommerce.refunds;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 退款状态改变后,微信会把相关退款结果发送给商户。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/refunds/chapter3_3.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class RefundNotifyResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:返回状态码
     * 变量名:code
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  错误码,SUCCESS为接收成功,其他错误码为失败
     *  示例值:SUCCESS
     * </pre>
     */
    @JsonProperty(value = "code")
    private String code;
    /**
     * <pre>
     * 字段名:返回信息
     * 变量名:message
     * 是否必填:否
     * 类型:string[1,256]
     * 描述:
     *  返回信息,如非空,为错误原因
     *  示例值:系统错误
     * </pre>
     */
    @JsonProperty(value = "message")
    private String message;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/refunds/RefundQueryStatusResponse.java
New file
@@ -0,0 +1,335 @@
package com.ruoyi.order.tools.response.ecommerce.refunds;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
 * <pre>
 * 提交退款申请后,通过调用该接口查询退款状态。该查询服务提供两种查询方式(两种查询方式返回结果一致): 方式1:通过微信支付退款单号查询退款; 方式2:通过商户退款单号查询退款。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/refunds/chapter3_2.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEM_ERROR    接口返回错误    请不要更换商户退款单号,请使用相同参数再次调用API。
 * 404    RESOURCE_NOT_EXISTS    订单不存在    请检查订单号是否正确且是否已支付,未支付的订单不能发起退款
 * 400    PARAM_ERROR    参数错误    请求参数错误,请重新检查再调用退款申请
 * 429    FREQUENCY_LIMITED    频率限制    该笔退款未受理,请降低频率后重试
 * 403    NO_AUTH    没有退款权限    此状态代表退款申请失败,请检查是否有退这笔订单的权限
 * 401    SIGN_ERROR    签名错误    请检查签名参数和方法是否都符合签名算法要求
 * 400    INVALID_REQUEST    请求参数符合参数格式,但不符合业务规则    此状态代表退款申请失败,商户可根据具体的错误提示做相应的处理。
 * 400    MCH_NOT_EXISTS    商户号不存在    请检查商户号是否正确
 * 403    REQUEST_BLOCKED    请求受阻    此状态代表退款申请失败,商户可根据具体的错误提示做相应的处理。
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class RefundQueryStatusResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:微信退款单号
     * 变量名:refund_id
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  微信支付退款订单号。
     *  示例值:1217752501201407033233368018
     * </pre>
     */
    @JsonProperty(value = "refund_id")
    private String refundId;
    /**
     * <pre>
     * 字段名:商户退款单号
     * 变量名:out_refund_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔。
     *  示例值:1217752501201407033233368018
     * </pre>
     */
    @JsonProperty(value = "out_refund_no")
    private String outRefundNo;
    /**
     * <pre>
     * 字段名:微信订单号
     * 变量名:transaction_id
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  微信支付交易订单号。
     *  示例值: 1217752501201407033233368018
     * </pre>
     */
    @JsonProperty(value = "transaction_id")
    private String transactionId;
    /**
     * <pre>
     * 字段名:商户订单号
     * 变量名:out_trade_no
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  返回的原交易订单号。
     *  示例值: 1217752501201407033233368018
     * </pre>
     */
    @JsonProperty(value = "out_trade_no")
    private String outTradeNo;
    /**
     * <pre>
     * 字段名:退款渠道
     * 变量名:channel
     * 是否必填:是
     * 类型:string[1,16]
     * 描述:
     *  ORIGINAL:原路退款
     *  BALANCE:退回到余额
     *  OTHER_BALANCE:原账户异常退到其他余额账户
     *  OTHER_BANKCARD:原银行卡异常退到其他银行卡
     *  示例值: ORIGINAL
     * </pre>
     */
    @JsonProperty(value = "channel")
    private String channel;
    /**
     * <pre>
     * 字段名:退款入账账户
     * 变量名:user_received_account
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  取当前退款单的退款入账方。
     *  退回银行卡:{银行名称}{卡类型}{卡尾号}
     *  退回支付用户零钱:支付用户零钱
     *  退还商户:商户基本账户、商户结算银行账户
     *  退回支付用户零钱通:支付用户零钱通
     *  示例值: 招商银行信用卡0403
     * </pre>
     */
    @JsonProperty(value = "user_received_account")
    private String userReceivedAccount;
    /**
     * <pre>
     * 字段名:退款成功时间
     * 变量名:success_time
     * 是否必填:否
     * 类型:string[1,64]
     * 描述:
     *  退款成功时间,退款状态status为SUCCESS(退款成功)时,返回该字段。遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日13点29分35秒。
     *  示例值: 2018-06-08T10:34:56+08:00
     * </pre>
     */
    @JsonProperty(value = "success_time")
    private String successTime;
    /**
     * <pre>
     * 字段名:退款创建时间
     * 变量名:create_time
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  1、退款受理时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日13点29分35秒。
     *  2、当退款状态为退款成功时返回此字段。
     *  示例值:2018-06-08T10:34:56+08:00
     * </pre>
     */
    @JsonProperty(value = "create_time")
    private String createTime;
    /**
     * <pre>
     * 字段名:退款状态
     * 变量名:status
     * 是否必填:是
     * 类型:string[1,16]
     * 描述:
     *  退款状态,枚举值:
     *  SUCCESS:退款成功
     *  CLOSE:退款关闭
     *  PROCESSING:退款处理中
     *  ABNORMAL:退款异常,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往【服务商平台—>交易中心】,手动处理此笔退款
     *  示例值:SUCCESS
     * </pre>
     */
    @JsonProperty(value = "status")
    private String status;
    /**
     * <pre>
     * 字段名:+退款金额信息
     * 变量名:amount
     * 是否必填:是
     * 类型:object
     * 描述:订单退款金额信息
     * </pre>
     */
    @JsonProperty(value = "amount")
    private Amount amount;
    /**
     * <pre>
     * 字段名:+营销详情
     * 变量名:promotion_detail
     * 是否必填:否
     * 类型:array
     * 描述:优惠退款信息,discount_refund>0时,返回该字段
     * </pre>
     */
    @JsonProperty(value = "promotion_detail")
    private List<PromotionDetail> promotionDetail;
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class Amount {
        /**
         * <pre>
         * 字段名:退款金额
         * 变量名:refund
         * 是否必填:是
         * 类型:int
         * 描述:
         *  退款金额,币种的最小单位,只能为整数,不能超过原订单支付金额。
         *  示例值:888
         * </pre>
         */
        @JsonProperty(value = "refund")
        private Integer refund;
        /**
         * <pre>
         * 字段名:用户退款金额
         * 变量名:payer_refund
         * 是否必填:是
         * 类型:int
         * 描述:
         *  退款给用户的金额,不包含所有优惠券金额。
         *  示例值:888
         * </pre>
         */
        @JsonProperty(value = "payer_refund")
        private Integer payerRefund;
        /**
         * <pre>
         * 字段名:优惠退款金额
         * 变量名:discount_refund
         * 是否必填:是
         * 类型:int
         * 描述:
         *  优惠券的退款金额,原支付单的优惠按比例退款。
         *  示例值:888
         * </pre>
         */
        @JsonProperty(value = "discount_refund")
        private Integer discountRefund;
        /**
         * <pre>
         * 字段名:退款币种
         * 变量名:currency
         * 是否必填:是
         * 类型:string[1,18]
         * 描述:
         *  符合ISO 4217标准的三位字母代码,目前只支持人民币:CNY 。
         *  示例值: CNY
         * </pre>
         */
        @JsonProperty(value = "currency")
        private String currency;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class PromotionDetail {
        /**
         * <pre>
         * 字段名:券ID
         * 变量名:promotion_id
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  券或者立减优惠id 。
         *  示例值:109519
         * </pre>
         */
        @JsonProperty(value = "promotion_id")
        private String promotionId;
        /**
         * <pre>
         * 字段名:优惠范围
         * 变量名:scope
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  枚举值:
         *  GLOBAL:全场代金券
         *  SINGLE:单品优惠
         *  示例值:SINGLE
         * </pre>
         */
        @JsonProperty(value = "scope")
        private String scope;
        /**
         * <pre>
         * 字段名:优惠类型
         * 变量名:type
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  枚举值:
         *  COUPON:充值型代金券,商户需要预先充值营销经费
         *  DISCOUNT:免充值型优惠券,商户不需要预先充值营销经费
         *  示例值:DISCOUNT
         * </pre>
         */
        @JsonProperty(value = "type")
        private String type;
        /**
         * <pre>
         * 字段名:优惠券面额
         * 变量名:amount
         * 是否必填:是
         * 类型:int
         * 描述:
         *  用户享受优惠的金额(优惠券面额=微信出资金额+商家出资金额+其他出资方金额 )。
         *  示例值:5
         * </pre>
         */
        @JsonProperty(value = "amount")
        private Integer amount;
        /**
         * <pre>
         * 字段名:优惠退款金额
         * 变量名:refund_amount
         * 是否必填:是
         * 类型:int
         * 描述:
         *  代金券退款金额<=退款金额,退款金额-代金券或立减优惠退款金额为现金,说明详见《代金券或立减优惠》。
         *  示例值:100
         * </pre>
         */
        @JsonProperty(value = "refund_amount")
        private Integer refundAmount;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/subsidies/SubsidiesCancelResponse.java
New file
@@ -0,0 +1,82 @@
package com.ruoyi.order.tools.response.ecommerce.subsidies;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 对带有补差标识的订单,如果不需要补差,可在发起分账前,可调用这个接口进行取消补差。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/subsidies/chapter3_3.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEM_ERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用
 * 400    INVALID_REQUEST    参数错误    请使用正确的参数重新调用
 * 429    FREQUENCY_LIMITED    频率限制    请降低频率后重试
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class SubsidiesCancelResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  补差的电商平台二级商户,填写微信支付分配的商户号。
     *  示例值:1900013401
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:微信订单号
     * 变量名:transaction_id
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  微信支付订单号。
     *  示例值: 4208450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "transaction_id")
    private String transactionId;
    /**
     * <pre>
     * 字段名:取消补差结果
     * 变量名:result
     * 是否必填:是
     * 类型:string[1,16]
     * 描述:
     *  取消补差结果,枚举值:
     *  SUCCESS:成功
     *  FAIL:失败
     *  示例值:SUCCESS
     * </pre>
     */
    @JsonProperty(value = "result")
    private String result;
    /**
     * <pre>
     * 字段名:取消补差描述
     * 变量名:description
     * 是否必填:是
     * 类型:string[1,80]
     * 描述:
     *  取消补差描述
     *  示例值:订单退款
     * </pre>
     */
    @JsonProperty(value = "description")
    private String description;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/subsidies/SubsidiesCreateResponse.java
New file
@@ -0,0 +1,125 @@
package com.ruoyi.order.tools.response.ecommerce.subsidies;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 服务商下单的时候带上补差标识,微信订单支付成功并结算完成后,发起分账前,调用该口进行补差。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/subsidies/chapter3_1.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEM_ERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用
 * 400    INVALID_REQUEST    参数错误    请使用正确的参数重新调用
 * 429    FREQUENCY_LIMITED    频率限制    请降低频率后重试
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class SubsidiesCreateResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  补差的电商平台二级商户,填写微信支付分配的商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:微信订单号
     * 变量名:transaction_id
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  微信支付订单号。
     *  示例值: 4208450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "transaction_id")
    private String transactionId;
    /**
     * <pre>
     * 字段名:微信补差单号
     * 变量名:subsidy_id
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  微信补差单号,微信系统返回的唯一标识。
     *  示例值: 3008450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "subsidy_id")
    private String subsidyId;
    /**
     * <pre>
     * 字段名:补差描述
     * 变量名:description
     * 是否必填:是
     * 类型:string[1,80]
     * 描述:
     *  补差描述
     *  示例值:满减补差活动
     * </pre>
     */
    @JsonProperty(value = "description")
    private String description;
    /**
     * <pre>
     * 字段名:补差金额
     * 变量名:amount
     * 是否必填:是
     * 类型:int
     * 描述:
     *  补差金额
     *  示例值:10
     * </pre>
     */
    @JsonProperty(value = "amount")
    private Integer amount;
    /**
     * <pre>
     * 字段名:补差单结果
     * 变量名:result
     * 是否必填:是
     * 类型:string[1,16]
     * 描述:
     *  补差单状态,枚举值:
     *  SUCCESS:补差成功
     *  FAIL:补差失败
     *  REFUND:已全额回退
     *  示例值:SUCCESS
     * </pre>
     */
    @JsonProperty(value = "result")
    private String result;
    /**
     * <pre>
     * 字段名:补差完成时间
     * 变量名:success_time
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  补贴完成时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss:sss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss:sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日13点29分35秒。
     *  示例值: 2015-05-20T13:29:35.120+08:00
     * </pre>
     */
    @JsonProperty(value = "success_time")
    private String successTime;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/ecommerce/subsidies/SubsidiesRefundResponse.java
New file
@@ -0,0 +1,152 @@
package com.ruoyi.order.tools.response.ecommerce.subsidies;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 订单发送退款的时候,可以对补贴成功的补差单发起回退。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/subsidies/chapter3_2.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEM_ERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用
 * 400    INVALID_REQUEST    参数错误    请使用正确的参数重新调用
 * 429    FREQUENCY_LIMITED    频率限制    请降低频率后重试
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class SubsidiesRefundResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:二级商户号
     * 变量名:sub_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  补差的电商平台二级商户,填写微信支付分配的商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "sub_mchid")
    private String subMchid;
    /**
     * <pre>
     * 字段名:微信订单号
     * 变量名:transaction_id
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  微信支付订单号。
     *  示例值: 4208450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "transaction_id")
    private String transactionId;
    /**
     * <pre>
     * 字段名:微信补差回退单号
     * 变量名:subsidy_refund_id
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  微信补差回退单号,微信补差回退系统返回的唯一标识。
     *  示例值: 3008450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "subsidy_refund_id")
    private String subsidyRefundId;
    /**
     * <pre>
     * 字段名:微信退款单号
     * 变量名:refund_id
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  微信退款单号,微信系统退款返回的唯一标识。
     *  示例值: 3008450740201411110007820472
     * </pre>
     */
    @JsonProperty(value = "refund_id")
    private String refundId;
    /**
     * <pre>
     * 字段名:商户补差回退单号
     * 变量名:out_order_no
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  商户系统内部的补差回退单号,在商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一补差回退单号多次请求等同一次。
     *  示例值:P20150806125346
     * </pre>
     */
    @JsonProperty(value = "out_order_no")
    private String outOrderNo;
    /**
     * <pre>
     * 字段名:补差回退金额
     * 变量名:amount
     * 是否必填:是
     * 类型:int
     * 描述:
     *  补差回退金额
     *  示例值:10
     * </pre>
     */
    @JsonProperty(value = "amount")
    private Integer amount;
    /**
     * <pre>
     * 字段名:补差回退描述
     * 变量名:description
     * 是否必填:是
     * 类型:string[1,80]
     * 描述:
     *  补差回退描述
     *  示例值:测试备注
     * </pre>
     */
    @JsonProperty(value = "description")
    private String description;
    /**
     * <pre>
     * 字段名:补差回退结果
     * 变量名:result
     * 是否必填:是
     * 类型:string[1,16]
     * 描述:
     *  补差回退结果,枚举值:
     *  SUCCESS:成功
     *  FAIL:失败
     *  示例值:SUCCESS
     * </pre>
     */
    @JsonProperty(value = "result")
    private String result;
    /**
     * <pre>
     * 字段名:补差回退完成时间
     * 变量名:success_time
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  补差回退完成时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss.sss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日13点29分35秒。
     *  示例值:2015-05-20T13:29:35.120+08:00
     * </pre>
     */
    @JsonProperty(value = "success_time")
    private String successTime;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/pay/bill/BillOfFundFlowResponse.java
New file
@@ -0,0 +1,68 @@
package com.ruoyi.order.tools.response.pay.bill;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 微信支付按天提供微信支付账户的资金流水账单文件,商户可以通过该接口获取账单文件的下载地址。文件内包含该账户资金操作相关的业务单号、收支金额、记账时间等信息,供商户进行核对。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/bill/chapter3_2.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEM_ERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用
 * 400    INVALID_REQUEST    参数错误    请检查bill_date,并重新调用
 * 400    NO_STATEMENT_EXIST    账单文件不存在    请检查当前商户号是否在指定日期有交易或退款发生
 * 账单文件不存在    请先检查当前商户号的微信支付账户在指定日期内是否有资金操作
 * 400    STATEMENT_CREATING    账单生成中    请先检查当前商户号的微信支付账户在指定日期内是否有资金操作,若有,则在T+1日上午10点后再重新下载
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class BillOfFundFlowResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:哈希类型
     * 变量名:hash_type
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  原始账单(gzip需要解压缩)的摘要值,用于校验文件的完整性。
     *  示例值:SHA1
     * </pre>
     */
    @JsonProperty(value = "hash_type")
    private String hashType;
    /**
     * <pre>
     * 字段名:哈希值
     * 变量名:hash_value
     * 是否必填:是
     * 类型:string[1,1024]
     * 描述:
     *  原始账单(gzip需要解压缩)的摘要值,用于校验文件的完整性。
     *  示例值:79bb0f45fc4c42234a918000b2668d689e2bde04
     * </pre>
     */
    @JsonProperty(value = "hash_value")
    private String hashValue;
    /**
     * <pre>
     * 字段名:账单下载地址
     * 变量名:download_url
     * 是否必填:是
     * 类型:string[1,2048]
     * 描述:
     *  供下一步请求账单文件的下载地址,该地址30s内有效。
     *  示例值:https://api.mch.weixin.qq.com/v3/billdownload/file?token=xxx
     * </pre>
     */
    @JsonProperty(value = "download_url")
    private String downloadUrl;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/pay/bill/BillOfTradeResponse.java
New file
@@ -0,0 +1,69 @@
package com.ruoyi.order.tools.response.pay.bill;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 微信支付按天提供交易账单文件,商户可以通过该接口获取账单文件的下载地址。文件内包含交易相关的金额、时间、营销等信息,供商户核对订单、退款、银行到账等情况。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/bill/chapter3_1.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEM_ERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * 400    PARAM_ERROR    参数错误    请使用正确的参数重新调用
 * 400    INVALID_REQUEST    参数错误    请检查bill_date,并重新调用
 * 400    NO_STATEMENT_EXIST    账单文件不存在    请检查当前商户号是否在指定日期有交易或退款发生
 * 400    STATEMENT_CREATING    账单生成中    请先检查当前商户号在指定日期内是否有成功的交易或退款,若有,则在T+1日上午8点后再重新下载
 * 400    INVALID_REQUEST    参数错误    请按第一步申请账单的API指引,重新获取账单地址后再请求
 * 403    NO_AUTH    权限异常    请检查本次请求的商户是否与第一步申请账单API的请求商户一致
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class BillOfTradeResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:哈希类型
     * 变量名:hash_type
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  原始账单(gzip需要解压缩)的摘要值,用于校验文件的完整性。
     *  示例值:SHA1
     * </pre>
     */
    @JsonProperty(value = "hash_type")
    private String hashType;
    /**
     * <pre>
     * 字段名:哈希值
     * 变量名:hash_value
     * 是否必填:是
     * 类型:string[1,1024]
     * 描述:
     *  原始账单(gzip需要解压缩)的摘要值,用于校验文件的完整性。
     *  示例值:79bb0f45fc4c42234a918000b2668d689e2bde04
     * </pre>
     */
    @JsonProperty(value = "hash_value")
    private String hashValue;
    /**
     * <pre>
     * 字段名:账单下载地址
     * 变量名:download_url
     * 是否必填:是
     * 类型:string[1,2048]
     * 描述:
     *  供下一步请求账单文件的下载地址,该地址30s内有效。
     *  示例值:https://api.mch.weixin.qq.com/v3/billdownload/file?token=xxx
     * </pre>
     */
    @JsonProperty(value = "download_url")
    private String downloadUrl;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/pay/combine/CombineTransactionsAppResponse.java
New file
@@ -0,0 +1,54 @@
package com.ruoyi.order.tools.response.pay.combine;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 使用合单支付接口,用户只输入一次密码,即可完成多个订单的支付。目前最少一次可支持2笔,最多一次10笔订单进行合单支付。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/combine/chapter3_1.shtml
 * 状态码    错误码    描述    解决方案
 * 202    USERPAYING    用户支付中,需要输入密码    等待5秒,然后调用被扫订单结果查询API,查询当前订单的不同状态,决定下一步的操作
 * 403    TRADE_ERROR    交易错误    因业务原因交易失败,请查看接口返回的详细信息
 * 500    SYSTEMERROR    系统错误    系统异常,请用相同参数重新调用
 * 401    SIGN_ERROR    签名错误    请检查签名参数和方法是否都符合签名算法要求
 * 403    RULELIMIT    业务规则限制    因业务规则限制请求频率,请查看接口返回的详细信息
 * 400    PARAM_ERROR    参数错误    请根据接口返回的详细信息检查请求参数
 * 403    OUT_TRADE_NO_USED    商户订单号重复    请核实商户订单号是否重复提交
 * 404    ORDERNOTEXIST    订单不存在    请检查订单是否发起过交易
 * 400    ORDER_CLOSED    订单已关闭    当前订单已关闭,请重新下单
 * 500    OPENID_MISMATCH    openid和appid不匹配    请确认openid和appid是否匹配
 * 403    NOTENOUGH    余额不足    用户账号余额不足,请用户充值或更换支付卡后再支付
 * 403    NOAUTH    商户无权限    请商户前往申请此接口相关权限
 * 400    MCH_NOT_EXISTS    商户号不存在    请检查商户号是否正确
 * 500    INVALID_TRANSACTIONID    订单号非法    请检查微信支付订单号是否正确
 * 400    INVALID_REQUEST    无效请求    请根据接口返回的详细信息检查
 * 429    FREQUENCY_LIMITED    频率超限    请降低请求接口频率
 * 500    BANKERROR    银行系统异常    银行系统异常,请用相同参数重新调用
 * 400    APPID_MCHID_NOT_MATCH    appid和mch_id不匹配    请确认appid和mch_id是否匹配
 * 403    ACCOUNTERROR    账号异常    用户账号异常,无需更多操作
 *
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class CombineTransactionsAppResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:预支付交易会话标识
     * 变量名:prepay_id
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  数字和字母。微信生成的预支付会话标识,用于后续接口调用使用,该值有效期为2小时。
     *  示例值:wx201410272009395522657a690389285100
     * </pre>
     */
    @JsonProperty(value = "prepay_id")
    private String prepayId;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/pay/combine/CombineTransactionsCloseResponse.java
New file
@@ -0,0 +1,7 @@
package com.ruoyi.order.tools.response.pay.combine;
import com.ruoyi.order.tools.response.AbstractResponse;
public class CombineTransactionsCloseResponse extends AbstractResponse {
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/pay/combine/CombineTransactionsJsResponse.java
New file
@@ -0,0 +1,54 @@
package com.ruoyi.order.tools.response.pay.combine;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 使用合单支付接口,用户只输入一次密码,即可完成多个订单的支付。目前最少一次可支持2笔,最多一次10笔订单进行合单支付。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/combine/chapter3_2.shtml
 * 状态码    错误码    描述    解决方案
 * 202    USERPAYING    用户支付中,需要输入密码    等待5秒,然后调用被扫订单结果查询API,查询当前订单的不同状态,决定下一步的操作
 * 403    TRADE_ERROR    交易错误    因业务原因交易失败,请查看接口返回的详细信息
 * 500    SYSTEMERROR    系统错误    系统异常,请用相同参数重新调用
 * 401    SIGN_ERROR    签名错误    请检查签名参数和方法是否都符合签名算法要求
 * 403    RULELIMIT    业务规则限制    因业务规则限制请求频率,请查看接口返回的详细信息
 * 400    PARAM_ERROR    参数错误    请根据接口返回的详细信息检查请求参数
 * 403    OUT_TRADE_NO_USED    商户订单号重复    请核实商户订单号是否重复提交
 * 404    ORDERNOTEXIST    订单不存在    请检查订单是否发起过交易
 * 400    ORDER_CLOSED    订单已关闭    当前订单已关闭,请重新下单
 * 500    OPENID_MISMATCH    openid和appid不匹配    请确认openid和appid是否匹配
 * 403    NOTENOUGH    余额不足    用户账号余额不足,请用户充值或更换支付卡后再支付
 * 403    NOAUTH    商户无权限    请商户前往申请此接口相关权限
 * 400    MCH_NOT_EXISTS    商户号不存在    请检查商户号是否正确
 * 500    INVALID_TRANSACTIONID    订单号非法    请检查微信支付订单号是否正确
 * 400    INVALID_REQUEST    无效请求    请根据接口返回的详细信息检查
 * 429    FREQUENCY_LIMITED    频率超限    请降低请求接口频率
 * 500    BANKERROR    银行系统异常    银行系统异常,请用相同参数重新调用
 * 400    APPID_MCHID_NOT_MATCH    appid和mch_id不匹配    请确认appid和mch_id是否匹配
 * 403    ACCOUNTERROR    账号异常    用户账号异常,无需更多操作
 *
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class CombineTransactionsJsResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:预支付交易会话标识
     * 变量名:prepay_id
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  数字和字母。微信生成的预支付会话标识,用于后续接口调用使用,该值有效期为2小时。
     *  示例值:wx201410272009395522657a690389285100
     * </pre>
     */
    @JsonProperty(value = "prepay_id")
    private String prepayId;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/pay/combine/CombineTransactionsNotifyResponse.java
New file
@@ -0,0 +1,47 @@
package com.ruoyi.order.tools.response.pay.combine;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 微信支付通过支付通知接口将用户支付成功消息通知给商户
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/combine/chapter3_7.shtml
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class CombineTransactionsNotifyResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:返回状态码
     * 变量名:code
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  错误码,SUCCESS为清算机构接收成功,其他错误码为失败。
     *  示例值:SUCCESS
     * </pre>
     */
    @JsonProperty(value = "code")
    private String code;
    /**
     * <pre>
     * 字段名:返回信息
     * 变量名:message
     * 是否必填:是
     * 类型:string[1,64]
     * 描述:
     *  返回信息,如非空,为错误原因。
     *  示例值:系统错误
     * </pre>
     */
    @JsonProperty(value = "message")
    private String message;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/pay/combine/CombineTransactionsStatusResponse.java
New file
@@ -0,0 +1,379 @@
package com.ruoyi.order.tools.response.pay.combine;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
 * <pre>
 * 电商平台通过合单查询订单API查询订单状态,完成下一步的业务逻辑。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/combine/chapter3_3.shtml
 * 状态码    错误码    描述    解决方案
 * 202    USERPAYING    用户支付中,需要输入密码    等待5秒,然后调用被扫订单结果查询API,查询当前订单的不同状态,决定下一步的操作
 * 403    TRADE_ERROR    交易错误    因业务原因交易失败,请查看接口返回的详细信息
 * 500    SYSTEMERROR    系统错误    系统异常,请用相同参数重新调用
 * 401    SIGN_ERROR    签名错误    请检查签名参数和方法是否都符合签名算法要求
 * 403    RULELIMIT    业务规则限制    因业务规则限制请求频率,请查看接口返回的详细信息
 * 400    PARAM_ERROR    参数错误    请根据接口返回的详细信息检查请求参数
 * 403    OUT_TRADE_NO_USED    商户订单号重复    请核实商户订单号是否重复提交
 * 404    ORDERNOTEXIST    订单不存在    请检查订单是否发起过交易
 * 400    ORDER_CLOSED    订单已关闭    当前订单已关闭,请重新下单
 * 500    OPENID_MISMATCH    openid和appid不匹配    请确认openid和appid是否匹配
 * 403    NOTENOUGH    余额不足    用户帐号余额不足,请用户充值或更换支付卡后再支付
 * 403    NOAUTH    商户无权限    请商户前往申请此接口相关权限
 * 400    MCH_NOT_EXISTS    商户号不存在    请检查商户号是否正确
 * 500    INVALID_TRANSACTIONID    订单号非法    请检查微信支付订单号是否正确
 * 400    INVALID_REQUEST    无效请求    请根据接口返回的详细信息检查
 * 429    FREQUENCY_LIMITED    频率超限    请降低请求接口频率
 * 500    BANKERROR    银行系统异常    银行系统异常,请用相同参数重新调用
 * 400    APPID_MCHID_NOT_MATCH    appid和mch_id不匹配    请确认appid和mch_id是否匹配
 * 403    ACCOUNTERROR    账号异常    用户账号异常,无需更多操作
 *
 * </pre>
 */
@Data
@EqualsAndHashCode(callSuper = true)
@JsonIgnoreProperties()
public class CombineTransactionsStatusResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:合单商户appid
     * 变量名:combine_appid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  合单发起方的appid。
     *  示例值:wxd678efh567hg6787
     * </pre>
     */
    @JsonProperty(value = "combine_appid")
    private String combineAppid;
    /**
     * <pre>
     * 字段名:合单商户号
     * 变量名:combine_mchid
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  合单发起方商户号。
     *  示例值:1900000109
     * </pre>
     */
    @JsonProperty(value = "combine_mchid")
    private String combineMchid;
    /**
     * <pre>
     * 字段名:合单商户订单号
     * 变量名:combine_out_trade_no
     * 是否必填:是
     * 类型:string[1,32]
     * 描述:
     *  合单支付总订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。
     *  示例值:P20150806125346
     * </pre>
     */
    @JsonProperty(value = "combine_out_trade_no")
    private String combineOutTradeNo;
    /**
     * <pre>
     * 字段名:+场景信息
     * 变量名:scene_info
     * 是否必填:否
     * 类型:object
     * 描述:支付场景信息描述
     * </pre>
     */
    @JsonProperty(value = "scene_info")
    private SceneInfo sceneInfo;
    /**
     * <pre>
     * 字段名:+子单信息
     * 变量名:sub_orders
     * 是否必填:是
     * 类型:array
     * 描述:
     *  最多支持子单条数:50
     *
     * </pre>
     */
    @JsonProperty(value = "sub_orders")
    private List<SubOrders> subOrders;
    /**
     * <pre>
     * 字段名:+支付者
     * 变量名:combine_payer_info
     * 是否必填:否
     * 类型:object
     * 描述:示例值:见请求示例
     * </pre>
     */
    @JsonProperty(value = "combine_payer_info")
    private CombinePayerInfo combinePayerInfo;
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class SceneInfo {
        /**
         * <pre>
         * 字段名:商户端设备号
         * 变量名:device_id
         * 是否必填:否
         * 类型:string[7,16]
         * 描述:
         *  终端设备号(门店号或收银设备ID) 。
         *  示例值:POS1:1
         * </pre>
         */
        @JsonProperty(value = "device_id")
        private String deviceId;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class SubOrders {
        /**
         * <pre>
         * 字段名:子单商户号
         * 变量名:mchid
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  子单发起方商户号,必须与发起方Appid有绑定关系。
         *  示例值:1900000109
         * </pre>
         */
        @JsonProperty(value = "mchid")
        private String mchid;
        /**
         * <pre>
         * 字段名:交易类型
         * 变量名:trade_type
         * 是否必填:是
         * 类型:string[1,16]
         * 描述:
         *  枚举值:
         *  NATIVE:扫码支付
         *  JSAPI:公众号支付
         *  APP:APP支付
         *  MWEB:H5支付
         *  示例值: JSAPI
         * </pre>
         */
        @JsonProperty(value = "trade_type")
        private String tradeType;
        /**
         * <pre>
         * 字段名:交易状态
         * 变量名:trade_state
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  枚举值:
         *  SUCCESS:支付成功
         *  REFUND:转入退款
         *  NOTPAY:未支付
         *  CLOSED:已关闭
         *  USERPAYING:用户支付中
         *  PAYERROR:支付失败(其他原因,如银行返回失败)
         *  示例值: SUCCESS
         * </pre>
         */
        @JsonProperty(value = "trade_state")
        private String tradeState;
        /**
         * <pre>
         * 字段名:付款银行
         * 变量名:bank_type
         * 是否必填:否
         * 类型:string[1,16]
         * 描述:
         *  银行类型,采用字符串类型的银行标识。
         *  示例值:CMC
         * </pre>
         */
        @JsonProperty(value = "bank_type")
        private String bankType;
        /**
         * <pre>
         * 字段名:附加数据
         * 变量名:attach
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用。
         *  示例值:深圳分店
         * </pre>
         */
        @JsonProperty(value = "attach")
        private String attach;
        /**
         * <pre>
         * 字段名:支付完成时间
         * 变量名:success_time
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  订单支付时间,遵循rfc3339标准格式,格式为YYYY-MM-DDTHH:mm:ss.sss+TIMEZONE,YYYY-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,HH:mm:ss.sss表示时分秒毫秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC 8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,北京时间2015年5月20日13点29分35秒。
         *  示例值: 2015-05-20T13:29:35.120+08:00
         * </pre>
         */
        @JsonProperty(value = "success_time")
        private String successTime;
        /**
         * <pre>
         * 字段名:微信订单号
         * 变量名:transaction_id
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  微信支付订单号。
         *  示例值:1009660380201506130728806387
         * </pre>
         */
        @JsonProperty(value = "transaction_id")
        private String transactionId;
        /**
         * <pre>
         * 字段名:子单商户订单号
         * 变量名:out_trade_no
         * 是否必填:是
         * 类型:string[6,32]
         * 描述:
         *  商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。
         *  示例值:20150806125346
         * </pre>
         */
        @JsonProperty(value = "out_trade_no")
        private String outTradeNo;
        /**
         * <pre>
         * 字段名:二级商户号
         * 变量名:sub_mchid
         * 是否必填:是
         * 类型:string[1,32]
         * 描述:
         *  二级商户商户号,由微信支付生成并下发。
         *  注意:仅适用于电商平台 服务商
         *  示例值:1900000109
         * </pre>
         */
        @JsonProperty(value = "sub_mchid")
        private String subMchid;
        /**
         * <pre>
         * 字段名:+订单金额
         * 变量名:amount
         * 是否必填:是
         * 类型:object
         * 描述:订单金额信息
         * </pre>
         */
        @JsonProperty(value = "amount")
        private Amount amount;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class CombinePayerInfo {
        /**
         * <pre>
         * 字段名:用户标识
         * 变量名:openid
         * 是否必填:是
         * 类型:string[1,128]
         * 描述:
         *  使用合单appid获取的对应用户openid。是用户在商户appid下的唯一标识。
         *  示例值:oUpF8uMuAJO_M2pxb1Q9zNjWeS6o
         * </pre>
         */
        @JsonProperty(value = "openid")
        private String openid;
    }
    @EqualsAndHashCode
    @Data
    @JsonIgnoreProperties()
    public static class Amount {
        /**
         * <pre>
         * 字段名:标价金额
         * 变量名:total_amount
         * 是否必填:是
         * 类型:int64
         * 描述:
         *  子单金额,单位为分。
         *  示例值:100
         * </pre>
         */
        @JsonProperty(value = "total_amount")
        private Integer totalAmount;
        /**
         * <pre>
         * 字段名:标价币种
         * 变量名:currency
         * 是否必填:否
         * 类型:string[1,8]
         * 描述:
         *  符合ISO 4217标准的三位字母代码,人民币:CNY。
         *  示例值:CNY
         * </pre>
         */
        @JsonProperty(value = "currency")
        private String currency;
        /**
         * <pre>
         * 字段名:现金支付金额
         * 变量名:payer_amount
         * 是否必填:是
         * 类型:int64
         * 描述:
         *  订单现金支付金额。
         *  示例值: 10
         * </pre>
         */
        @JsonProperty(value = "payer_amount")
        private Integer payerAmount;
        /**
         * <pre>
         * 字段名:现金支付币种
         * 变量名:payer_currency
         * 是否必填:否
         * 类型:string[1,8]
         * 描述:
         *  货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY。
         *  示例值: CNY
         * </pre>
         */
        @JsonProperty(value = "payer_currency")
        private String payerCurrency;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/response/tool/ImageUploadResponse.java
New file
@@ -0,0 +1,44 @@
package com.ruoyi.order.tools.response.tool;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.ruoyi.order.tools.response.AbstractResponse;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * <pre>
 * 部分微信支付业务指定商户需要使用图片上传 API来上报图片信息,从而获得必传参数的值:图片MediaID 。
 * 文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/chapter3_1.shtml
 * 状态码    错误码    描述    解决方案
 * 500    SYSTEMERROR    系统错误    系统异常,请使用相同参数稍后重新调用
 * SYSTEMERROR    文件系统错误,请稍后重试    文件系统异常,请使用相同参数稍后重新调用
 * 400    PARAM_ERROR    图片文件名称不正确,请检查后重新提交    图片文件名称不正确,只支持jpg,jpeg,png,bmp,请使用正确图片文件重新调用
 * PARAM_ERROR    文件二进制内容不是图片,请检查后重新提交    上传文件二进制内容头部不正确,只支持jpg,jpeg,png,bmp,请使用正确图片文件重新调用
 * PARAM_ERROR    图片sha256值有误,请检查后重新提交    图片sha256值计算有误,请检查算法,重新计算后提交
 * PARAM_ERROR    文件大小不能超过2M,请检查后重新提交    商户更换文件或者对图片进行压缩后,重新调用
 * PARAM_ERROR    文件为空,请检查后重新提交    商户更换文件后,重新调用
 * 429    FREQUENCY_LIMIT_EXCEED    操作过快,请稍后重试    请商户降低每秒调用频率
 * FREQUENCY_LIMIT_EXCEED    当天上传文件数已达上限    请商户降低每天调用频率
 * 403    NO_AUTH    商户权限异常    请确认是否已经开通相关权限
 * </pre>
 */
@Data
@EqualsAndHashCode
@JsonIgnoreProperties()
public class ImageUploadResponse extends AbstractResponse {
    /**
     * <pre>
     * 字段名:媒体文件标识 Id
     * 变量名:media_id
     * 是否必填:是
     * 类型:string[1,512]
     * 描述:
     *  微信返回的媒体文件标识Id。
     *  示例值:6uqyGjGrCf2GtyXP8bxrbuH9-aAoTjH-rKeSl3Lf4_So6kdkQu4w8BYVP3bzLtvR38lxt4PjtCDXsQpzqge_hQEovHzOhsLleGFQVRF-U_0
     * </pre>
     */
    @JsonProperty(value = "media_id")
    private String mediaId;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/service/ProfitsSharingService.java
New file
@@ -0,0 +1,1024 @@
package com.ruoyi.order.tools.service;
import com.ruoyi.order.tools.constant.AccountType;
import com.ruoyi.order.tools.request.ecommerce.fund.WithdrawExceptionLogRequest;
import com.ruoyi.order.tools.request.ecommerce.fund.WithdrawForPlatformRequest;
import com.ruoyi.order.tools.request.ecommerce.fund.WithdrawForSubMchRequest;
import com.ruoyi.order.tools.request.ecommerce.profitsharing.*;
import com.ruoyi.order.tools.request.ecommerce.refunds.RefundApplyRequest;
import com.ruoyi.order.tools.request.ecommerce.refunds.RefundNotifyRequest;
import com.ruoyi.order.tools.request.ecommerce.refunds.RefundNotifyRequest1;
import com.ruoyi.order.tools.request.ecommerce.subsidies.SubsidiesCancelRequest;
import com.ruoyi.order.tools.request.ecommerce.subsidies.SubsidiesCreateRequest;
import com.ruoyi.order.tools.request.ecommerce.subsidies.SubsidiesRefundRequest;
import com.ruoyi.order.tools.request.pay.bill.BillOfFundFlowRequest;
import com.ruoyi.order.tools.request.pay.bill.BillOfTradeRequest;
import com.ruoyi.order.tools.request.pay.combine.CombineTransactionsAppRequest;
import com.ruoyi.order.tools.request.pay.combine.CombineTransactionsCloseRequest;
import com.ruoyi.order.tools.request.pay.combine.CombineTransactionsJsRequest;
import com.ruoyi.order.tools.request.pay.combine.CombineTransactionsNotifyRequest1;
import com.ruoyi.order.tools.response.ecommerce.amount.AmountDayEndOfPlatformResponse;
import com.ruoyi.order.tools.response.ecommerce.amount.AmountDayEndOfSubMchResponse;
import com.ruoyi.order.tools.response.ecommerce.amount.AmountOnlineOfPlatformResponse;
import com.ruoyi.order.tools.response.ecommerce.amount.AmountOnlineOfSubMchResponse;
import com.ruoyi.order.tools.response.ecommerce.applyments.ApplymentsModifySettlementResponse;
import com.ruoyi.order.tools.response.ecommerce.applyments.ApplymentsResponse;
import com.ruoyi.order.tools.applyments.ApplymentsRequest;
import com.ruoyi.order.tools.response.ecommerce.applyments.ApplymentsSettlementStatusResponse;
import com.ruoyi.order.tools.response.ecommerce.applyments.ApplymentsStatusResponse;
import com.ruoyi.order.tools.applyments.ApplymentsModifySettlementRequest;
import com.ruoyi.order.tools.response.ecommerce.fund.WithdrawForPlatformResponse;
import com.ruoyi.order.tools.response.ecommerce.fund.WithdrawForSubMchResponse;
import com.ruoyi.order.tools.response.ecommerce.fund.WithdrawStatusForPlatformResponse;
import com.ruoyi.order.tools.response.ecommerce.fund.WithdrawStatusForSubMchResponse;
import com.ruoyi.order.tools.response.ecommerce.profitsharing.*;
import com.ruoyi.order.tools.response.ecommerce.refunds.RefundApplyResponse;
import com.ruoyi.order.tools.response.ecommerce.refunds.RefundQueryStatusResponse;
import com.ruoyi.order.tools.response.ecommerce.subsidies.SubsidiesCancelResponse;
import com.ruoyi.order.tools.response.ecommerce.subsidies.SubsidiesCreateResponse;
import com.ruoyi.order.tools.response.ecommerce.subsidies.SubsidiesRefundResponse;
import com.ruoyi.order.tools.response.pay.combine.CombineTransactionsStatusResponse;
import com.ruoyi.order.tools.response.tool.ImageUploadResponse;
import java.io.File;
import java.io.InputStream;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public interface ProfitsSharingService {
    /**
     * <pre>
     * 二级商户进件API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_1.shtml
     * 电商平台,可使用该接口,帮助其二级商户进件成为微信支付商户。
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/applyments/
     * 请求方式:POST
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     *
     * @param request 请求对象
     * @return .
     */
    Optional<ApplymentsResponse> applyments(ApplymentsRequest request);
    /**
     * <pre>
     * 查询申请状态API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_2.shtml
     *
     * 电商平台通过查询申请状态API查询二级商户入驻申请结果。
     *
     * 注意:
     * ● 查询申请状态API可按以下两种不同方式查询:
     *     1、通过申请单ID查询申请状态;
     *     2、通过业务申编号查询申请状态
     * ● 两种不同查询方式返回结果相同
     *
     * 1、通过申请单ID查询申请状态
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/applyments/{applyment_id}
     * 请求方式:GET
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     *
     * @param applymentId 提交申请返回的ID
     * @return .
     */
    Optional<ApplymentsStatusResponse> queryApplymentsStatus(String applymentId);
    /**
     * <pre>
     * 查询申请状态API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_2.shtml
     *
     * 电商平台通过查询申请状态API查询二级商户入驻申请结果。
     *
     * 注意:
     * ● 查询申请状态API可按以下两种不同方式查询:
     *     1、通过申请单ID查询申请状态;
     *     2、通过业务申编号查询申请状态
     * ● 两种不同查询方式返回结果相同
     *
     * 2、通过业务申请编号查询申请状态
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/applyments/out-request-no/{out_request_no}
     * 请求方式:GET
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     *
     * @param outRequestNo 业务编号
     * @return .
     */
    Optional<ApplymentsStatusResponse> queryApplymentsStatusByOutNo(String outRequestNo);
    /**
     * <pre>
     * 下载平台证书API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_3.shtml
     * 由于证书有效期限制和交易安全的原因,微信支付会不定期的更换平台证书。微信支付提供了一系列接口,帮助商户后台系统实现平滑的证书更换。
     *
     * 更换指引:
     * ● 建议开发者使用中控服务器(即统一管理和分发,注意证书的保密和安全性)统一下载和管理微信支付平台证书。其他业务逻辑服务器通过该中控服务器进行报文的验签和解密。
     * ● 在微信支付更换平台证书之前,待更换的证书会提前24小时加入商户的平台证书列表。中控服务器需要定时查询商户的平台证书列表,并及时下载新的平台证书。
     * ● 在微信支付更换平台证书期间,商户收到的应答请求和回调通知中会同时存在不同的证书序列号,商户要能正确处理这种情况。
     * ● 获取平台证书的接口频率限制规则: 单个商户号 1000次/s (查单接口为600次/s)。
     *
     * 最佳实践:
     * 在中控服务器上调用;
     * 定时调用,间隔应小于12小时;
     * 与本地证书序列表对比,如果发现有新增证书序列号,则需要新换的证书。老证书会在1天内失效,应及时清理;
     * 获取到证书后,分发到各业务接口服务器。
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/certificates
     * 请求方式:GET
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     *
     * @return .
     */
    List<X509Certificate> downloadCertificates();
    /**
     * <pre>
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_4.shtml
     * 修改结算帐号API
     * 普通服务商(支付机构、银行不可用),可使用本接口修改其进件、已签约的特约商户-结算账户信息。
     *
     * 注意:
     * • 本接口无需传银行开户名称参数。
     * 若账户类型为“经营者个人银行卡”,则系统自动拉取特约商户的经营者姓名为开户名称。
     * 若账户类型为“对公银行账户”,则系统自动拉取特约商户的公司名称为开户名称。
     * 接口说明
     * 适用对象:普通服务商
     * 请求URL:https://api.mch.weixin.qq.com/v3/apply4sub/sub_merchants/{sub_mchid}/modify-settlement
     * 请求方式:POST
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     *
     * @param request 请求对象
     * @return .
     */
    Optional<ApplymentsModifySettlementResponse> modifySettlement(ApplymentsModifySettlementRequest request);
    /**
     * <pre>
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/applyments/chapter3_5.shtml
     * 查询结算账户API
     * 最新更新时间:2019.09.09 版本说明
     *
     * 普通服务商(支付机构、银行不可用),可使用本接口查询其进件、已签约的特约商户-结算账户信息(敏感信息掩码)。 该接口可用于核实是否成功修改结算账户信息、及查询系统汇款验证结果。
     *
     * 接口说明
     * 适用对象:普通服务商
     * 请求URL:https://api.mch.weixin.qq.com/v3/apply4sub/sub_merchants/{sub_mchid}/settlement
     * 请求方式:GET
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     *
     * @param subMchid 二级商户ID
     * @return .
     */
    Optional<ApplymentsSettlementStatusResponse> querySettlement(String subMchid);
    /**
     * <pre>
     * 合单下单-APP支付API.
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/combine/chapter3_1.shtml
     * 使用合单支付接口,用户只输入一次密码,即可完成多个订单的支付。目前最多一次可支持50笔订单进行合单支付。
     * 注意:
     * • 订单如果需要进行抽佣等,需要在合单中指定需要进行分账(profit_sharing为true);指定后,交易资金进入二级商户账户,处于冻结状态,可在后续使用分账接口进行分账,利用分账完结进行资金解冻,实现抽佣和对二级商户的账期。
     * • 合单中同一个二级商户只允许有一笔子订单。
     *
     * 适用对象:电商平台 服务商 直连商户
     * 请求URL:https://api.mch.weixin.qq.com/v3/combine-transactions/app
     * 请求方式:POST
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     *
     * @param request 请求对象
     * @return 预支付交易会话标识, 数字和字母。微信生成的预支付会话标识,用于后续接口调用使用。
     */
        Optional<String> combineTransactions(CombineTransactionsAppRequest request);
    /**
     * <pre>
     * 合单下单-JS支付API.
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/combine/chapter3_2.shtml
     * 使用合单支付接口,用户只输入一次密码,即可完成多个订单的支付。目前最多一次可支持50笔订单进行合单支付。
     * 注意:
     * • 订单如果需要进行抽佣等,需要在合单中指定需要进行分账(profit_sharing为true);指定后,交易资金进入二级商户账户,处于冻结状态,可在后续使用分账接口进行分账,利用分账完结进行资金解冻,实现抽佣和对二级商户的账期。
     * • 合单中同一个二级商户只允许有一笔子订单。
     * 适用对象:电商平台 服务商 直连商户
     * 请求URL:https://api.mch.weixin.qq.com/v3/combine-transactions/jsapi
     * 请求方式:POST
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     *
     * @param request 请求对象
     * @return 预支付交易会话标识, 数字和字母。微信生成的预支付会话标识,用于后续接口调用使用。
     */
    Optional<String> combineTransactions(CombineTransactionsJsRequest request);
    /**
     * <pre>
     * 合单查询订单API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/combine/chapter3_3.shtml
     * 电商平台通过合单查询订单API查询订单状态,完成下一步的业务逻辑。
     * 注意:
     * • 需要调用查询接口的情况:
     * 1、当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知。
     * 2、调用支付接口后,返回系统错误或未知交易状态情况。
     * 3、调用刷卡支付API,返回USERPAYING的状态。
     * 4、调用关单或撤销接口API之前,需确认支付状态。
     * 适用对象:电商平台 服务商 直连商户
     * 请求URL:https://api.mch.weixin.qq.com/v3/combine-transactions/out-trade-no/{combine_out_trade_no}
     * 请求方式:GET
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     *
     * @param combineOutTradeNo 合单支付总订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一 。
     * @return 订单详情
     */
    Optional<CombineTransactionsStatusResponse> combineTransactionsStatus(String combineOutTradeNo);
    /**
     * <pre>
     * 合单关闭订单API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/combine/chapter3_4.shtml
     * 合单支付订单只能使用此合单关单api完成关单。
     *
     * 适用对象:电商平台 服务商 直连商户
     * 请求URL:https://api.mch.weixin.qq.com/v3/combine-transactions/out-trade-no/{combine_out_trade_no}/close
     * 请求方式:POST
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     * <p>
     * 没有数据,返回状态码204(一般情况)
     * <p>
     * 状态码    错误码    描述    解决方案
     * 202    USERPAYING    用户支付中,需要输入密码    等待5秒,然后调用被扫订单结果查询API,查询当前订单的不同状态,决定下一步的操作
     * 403    TRADE_ERROR    交易错误    因业务原因交易失败,请查看接口返回的详细信息
     * 500    SYSTEMERROR    系统错误    系统异常,请用相同参数重新调用
     * 401    SIGN_ERROR    签名错误    请检查签名参数和方法是否都符合签名算法要求
     * 403    RULELIMIT    业务规则限制    因业务规则限制请求频率,请查看接口返回的详细信息
     * 400    PARAM_ERROR    参数错误    请根据接口返回的详细信息检查请求参数
     * 403    OUT_TRADE_NO_USED    商户订单号重复    请核实商户订单号是否重复提交
     * 404    ORDERNOTEXIST    订单不存在    请检查订单是否发起过交易
     * 400    ORDER_CLOSED    订单已关闭    当前订单已关闭,请重新下单
     * 500    OPENID_MISMATCH    openid和appid不匹配    请确认openid和appid是否匹配
     * 403    NOTENOUGH    余额不足    用户帐号余额不足,请用户充值或更换支付卡后再支付
     * 403    NOAUTH    商户无权限    请商户前往申请此接口相关权限
     * 400    MCH_NOT_EXISTS    商户号不存在    请检查商户号是否正确
     * 500    INVALID_TRANSACTIONID    订单号非法    请检查微信支付订单号是否正确
     * 400    INVALID_REQUEST    无效请求    请根据接口返回的详细信息检查
     * 429    FREQUENCY_LIMITED    频率超限    请降低请求接口频率
     * 500    BANKERROR    银行系统异常    银行系统异常,请用相同参数重新调用
     * 400    APPID_MCHID_NOT_MATCH    appid和mch_id不匹配    请确认appid和mch_id是否匹配
     * 403    ACCOUNTERROR    账号异常    用户账号异常,无需更多操作
     *
     * @param request 请求对象
     */
    void combineTransactionsClose(CombineTransactionsCloseRequest request);
    /**
     * @param prePayId 预下单ID
     * @param appId    appID
     * @return 用于app调起支付的参数
     */
    Map<String, String> getAppPayParams(String prePayId, String appId);
    /**
     * @param prePayId 预下单ID
     * @param appId    appID
     * @return 用于js调起支付的参数
     */
    Map<String, String> getJsPayParams(String prePayId, String appId);
    /**
     * @param prePayId 预下单ID
     * @param appId    appID
     * @return 用于小程序调起支付的参数
     */
    Map<String, String> getSmallPayParams(String prePayId, String appId);
    /**
     * @param timeStamp 时间戳
     * @param nonce     随机串
     * @param body      请求实体
     * @param signed    已签名字符串
     * @param serialNo  证书序列号
     * @return 验签结果
     */
    boolean verifyNotifySign(String timeStamp, String nonce, String body, String signed, String serialNo);
    /**
     * 对通知的数据体进行解析
     *
     * @param notifyContent 消息通知内容
     * @return 支付信息
     */
    Optional<CombineTransactionsNotifyRequest1> parsePayNotify(String notifyContent);
    /**
     * <pre>
     * 请求补差API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/subsidies/chapter3_1.shtml
     * 服务商下单的时候带上补差标识,微信订单支付成功并结算完成后,发起分账前,调用该口进行补差。
     * 注意:
     * • 电商平台下单时传入补差金额,详见【合单下单API】文档中补差字段说明。
     * • 在发起分账前,调用该接口进行补差。
     * • 补差金额需要和下单的时候传入的补差金额保持一致(发生用户退款时可以小于下单时的补差金额,须有对应的微信退款单号,任意一笔该订单的微信退款单)。
     * • 该接口支持重入,请求参数相同只会扣款一次,重入有效期180天。
     * • 系统异常(如返回SYSTEM_ERROR),请使用相同参数稍后重新调用,请务必用原参数来重入此接口,如更换金额重试,可能会导致重复扣款,系统会在1天后回退到原账户。
     *
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/subsidies/create
     * 请求方式:POST
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     *
     * @param request 请求对象
     * @return .
     */
    Optional<SubsidiesCreateResponse> subsidiesCreate(SubsidiesCreateRequest request);
    /**
     * <pre>
     * 请求补差回退API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/subsidies/chapter3_2.shtml
     * 订单发送退款的时候,可以对补贴成功的补差单发起回退。
     * 注意:
     * • 补差回退以原补差单位依据,支持多次回退,申请回退总金额不能超过补差金额。
     * • 此接口采用同步处理模式,即在接收到商户请求后,会实时返回处理结果。
     * • 补差回退的前置条件是订单发生退款。
     * • 系统异常(如返回SYSTEM_ERROR),请使用相同参数稍后重新调用,请务必用原商户补差回退单号和原参数来重入此接口。
     *
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/subsidies/return
     * 请求方式:POST
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     *
     * @param request 请求对象
     * @return .
     */
    Optional<SubsidiesRefundResponse> subsidiesRefund(SubsidiesRefundRequest request);
    /**
     * <pre>
     * 取消补差API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/subsidies/chapter3_3.shtml
     * 对带有补差标识的订单,如果不需要补差,可在发起发起分账前,可调用这个接口进行取消补差。
     * 注意:
     * • 取消补差完成后,商户可以对未补差的订单进行分账。
     * • 订单补差取消的前置条件是订单发生退款。
     *
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/subsidies/cancel
     * 请求方式:POST
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     *
     * @param request 请求对象
     * @return .
     */
    Optional<SubsidiesCancelResponse> subsidiesCancel(SubsidiesCancelRequest request);
    /**
     * <pre>
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_1.shtml
     * 请求分账API
     * 最新更新时间:2020.2.27 版本说明
     *
     * 微信订单支付成功后,由电商平台发起分账请求,将结算后的资金分给分账接收方。
     *
     * 注意:
     * • 微信订单支付成功后,服务商代特约商户发起分账请求,将结算后的钱分到分账接收方。
     * • 对同一笔订单最多能发起20次分账请求,每次请求最多分给5个接收方。
     * • 此接口采用异步处理模式,即在接收到商户请求后,会先受理请求再异步处理,最终的分账结果可以通过查询分账接口获取。
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/orders
     * 请求方式:POST
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     *
     * path 指该参数需在请求URL传参
     * query 指该参数需在请求JSON传参
     * </pre>
     *
     * @param request 请求对象
     * @return .
     */
    Optional<ProfitSharingApplyResponse> applyProfitSharing(ProfitSharingApplyRequest request);
    /**
     * @return 平台的商户ID
     */
    Optional<String> getPlatformId();
    /**
     * <pre>
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_2.shtml
     *
     * 返回上一层文档首页 / 电商收付通 / 分账 / 查询分账结果API
     * 查询分账结果API
     * 最新更新时间:2020.04.01 版本说明
     *
     * 发起分账请求后,可调用此接口查询分账结果 ;发起分账完结请求后,可调用此接口查询分账完结的结果
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/orders
     * 请求方式:GET
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     *
     * path 指该参数需在请求URL传参
     * query 指该参数需在请求JSON传参
     * </pre>
     *
     * @param request 请求对象
     * @return .
     */
    Optional<ProfitSharingQueryApplyResponse> queryProfitSharingStatus(ProfitSharingQueryApplyRequest request);
    /**
     * <pre>
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_3.shtml
     * 请求分账回退API
     * 最新更新时间:2019.09.11 版本说明
     *
     * 订单已经分账,在退款时,可以先调此接口,将已分账的资金从分账接收方的账户回退给分账方,再发起退款。
     *
     * 注意:
     * • 分账回退以原分账单为依据,支持多次回退,申请回退总金额不能超过原分账单分给该接收方的金额。
     * • 此接口采用同步处理模式,即在接收到商户请求后,会实时返回处理结果。
     * • 此功能需要接收方在商户平台开启同意分账回退后,才能使用。
     * • 对同一笔分账单最多能发起20次分账回退请求。
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/returnorders
     * 请求方式:POST
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     *
     * path 指该参数需在请求URL传参
     * query 指该参数需在请求JSON传参
     * </pre>
     *
     * @param request 请求对象
     * @return .
     */
    Optional<ProfitSharingRefundResponse> refundProfitSharing(ProfitSharingRefundRequest request);
    /**
     * <pre>
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_4.shtml
     * 查询分账回退结果API
     * 最新更新时间:2019.09.11 版本说明
     *
     * 商户需要核实回退结果,可调用此接口查询回退结果;如果分账回退接口返回状态为处理中,可调用此接口查询回退结果
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/returnorders
     * 请求方式:GET
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     *
     * path 指该参数需在请求URL传参
     * query 指该参数需在请求JSON传参
     * </pre>
     *
     * @param request 请求对象
     * @return .
     */
    Optional<ProfitSharingQueryRefundResponse> queryRefundProfitSharingStatus(ProfitSharingQueryRefundRequest request);
    /**
     * <pre>
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_5.shtml
     * 完结分账API
     * 最新更新时间:2019.09.11 版本说明
     *
     * 不需要进行分账的订单,可直接调用本接口将订单的金额全部解冻给特约商户。
     *
     * 注意:
     * • 调用分账接口后,需要解冻剩余资金时,调用本接口将剩余的分账金额全部解冻给特约商户。
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/finish-order
     * 请求方式:POST
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     *
     * path 指该参数需在请求URL传参
     * query 指该参数需在请求JSON传参
     * </pre>
     *
     * @param request 请求对象
     * @return .
     */
    Optional<ProfitSharingFinishResponse> finishProfitSharing(ProfitSharingFinishRequest request);
    /**
     * <pre>
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_7.shtml
     * 添加分账接收方API
     * 最新更新时间:2020.03.05 版本说明
     *
     * 1. 电商平台可通过此接口添加分账接收方,建立分账接收方列表。后续通过发起分账请求,将电商平台下的二级商户结算后的资金,分给分账接收方列表中具体的分账接收方。
     * 2. 添加的分账接收方统一都在电商平台维度进行管理,其他二级商户,均可向该分账接收方列表中的接收方进行分账,避免在二级商户维度重复维护。
     *
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/receivers/add
     * 请求方式:POST
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     *
     * path 指该参数需在请求URL传参
     * query 指该参数需在请求JSON传参
     * </pre>
     *
     * @param request 请求对象
     * @return .
     */
    Optional<ProfitSharingAddReceiverResponse> addReceiver(ProfitSharingAddReceiverRequest request);
    /**
     * <pre>
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_8.shtml
     * 删除分账接收方API
     * 最新更新时间:2020.03.05 版本说明
     *
     * 电商平台发起删除分账接收方请求。删除后,不支持将电商平台下二级商户结算后的资金,分到该分账接收方。
     *
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/receivers/delete
     * 请求方式:POST
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     *
     * path 指该参数需在请求URL传参
     * query 指该参数需在请求JSON传参
     * </pre>
     *
     * @param request 请求对象
     * @return .
     */
    Optional<ProfitSharingRemoveReceiverResponse> removeReceiver(ProfitSharingRemoveReceiverRequest request);
    /**
     * <pre>
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/profitsharing/chapter3_6.shtml
     *
     * 返回上一层文档首页 / 电商收付通 / 分账 / 分账动账通知API
     * 分账动账通知API
     * 最新更新时间:2020.03.23 版本说明
     *
     * 1、此功能仅针对分账接收方。
     * 2、分账动账金额变动后,微信会把相关变动结果发送给需要实时关注的分账接收方。
     *
     * 注意:
     * 对后台通知交互时,如果微信收到应答不是成功或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功
     *
     * • 同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。 推荐的做法是,当商户系统收到通知进行处理时,先检查对应业务数据的状态,并判断该通知是否已经处理。如果未处理,则再进行处理;如果已处理,则直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。
     * • 如果在所有通知频率(4小时)后没有收到微信侧回调,商户应调用查询订单接口确认订单状态。
     *
     * 特别提醒:商户系统对于开启结果通知的内容一定要做签名验证,并校验通知的信息是否与商户侧的信息一致,防止数据泄漏导致出现“假通知”,造成资金损失。
     * 接口说明
     * 适用对象:直联商户电商服务商 服务商
     * 请求URL:该链接是通过[商户配置]提交service_notify_url设置,必须为https协议。如果链接无法访问,商户将无法接收到微信通知。 通知url必须为直接可访问的url,不能携带参数。示例: “https://pay.weixin.qq.com/wxpay/pay.action”
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * 通知规则
     * 用户支付完成后,微信会把相关支付结果和用户信息发送给清算机构,清算机构需要接收处理后返回应答成功,然后继续给异步通知到下游从业机构。
     * 对后台通知交互时,如果微信收到应答不是成功或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。(通知频率为15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h - 总计 24h4m)
     * 通知报文
     * 支付结果通知是以POST 方法访问商户设置的通知url,通知的数据以JSON 格式通过请求主体(BODY)传输。通知的数据包括了加密的支付结果详情。
     *
     * 下面详细描述对通知数据进行解密的流程:
     * 1、用商户平台上设置的APIv3密钥【微信商户平台—&gt;账户设置—&gt;API安全—&gt;设置APIv3密钥】,记为key。
     * 2、针对resource.algorithm中描述的算法(目前为AEAD_AES_256_GCM),取得对应的参数nonce和associated_data。
     * 3、使用key、nonce和associated_data,对数据密文resource.ciphertext进行解密,得到JSON形式的资源对象。
     *
     * 注: AEAD_AES_256_GCM算法的接口细节,请参考rfc5116。微信支付使用的密钥key长度为32个字节,随机串nonce长度12个字节,associated_data长度小于16个字节并可能为空。
     * </pre>
     *
     * @param request 请求对象
     * @return .
     */
    Optional<ProfitSharingNotifyRequest1> parseProfitsSharingNotify(ProfitSharingNotifyRequest request);
    /**
     * <pre>
     * 退款申请API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/refunds/chapter3_1.shtml
     * 当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,微信支付将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家帐号上。
     *
     * 注意:
     * • 交易时间超过一年的订单无法提交退款。
     * • 微信支付退款支持单笔交易分多次退款,多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。申请退款总金额不能超过订单金额。 一笔退款失败后重新提交,请不要更换退款单号,请使用原商户退款单号。
     * • 请求频率限制:150qps,即每秒钟正常的申请退款请求次数不超过150次,错误或无效请求频率限制:6qps,即每秒钟异常或错误的退款申请请求不超过6次。
     * • 每个支付订单的部分退款次数不能超过50次。
     *
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/refunds/apply
     * 请求方式:POST
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     *
     * @param request 请求对象
     * @return .
     */
    Optional<RefundApplyResponse> refundApply(RefundApplyRequest request);
    /**
     * <pre>
     * 查询退款API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/refunds/chapter3_2.shtml
     * 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。
     *
     * 注意:
     * ● 退款查询API可按以下两种不同方式查询:
     *     1、通过微信支付退款单号查询退款;
     *     2、通过商户退款单号查询退款。
     * ● 两种不同查询方式返回结果相同
     *
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/refunds/id/{refund_id}
     * 请求方式:POST
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     *
     * @param subMchid 二级商户
     * @param refundId 退款记录ID
     * @return .
     */
    Optional<RefundQueryStatusResponse> refundQueryById(String subMchid, String refundId);
    /**
     * <pre>
     * 查询退款API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/refunds/chapter3_2.shtml
     * 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。
     *
     * 注意:
     * ● 退款查询API可按以下两种不同方式查询:
     *     1、通过微信支付退款单号查询退款;
     *     2、通过商户退款单号查询退款。
     * ● 两种不同查询方式返回结果相同
     *
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/refunds/out-refund-no/{out_refund_no}
     * 请求方式:GET
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     *
     * @param subMchid    二级商户
     * @param outRefundNo 退款记录单号
     * @return .
     */
    Optional<RefundQueryStatusResponse> refundQueryByNumber(String subMchid, String outRefundNo);
    /**
     * 对通知的数据体进行解析
     *
     * @param request 请求对象
     * @return 退款信息
     */
    Optional<RefundNotifyRequest1> parseRefundNotify(RefundNotifyRequest request);
    /**
     * <pre>
     * 查询二级商户账户实时余额API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/amount/chapter3_1.shtml
     *
     * 电商服务商通过此接口可以查询二级商户账户余额信息。
     *
     * 注意:
     * • 电商平台可利用分账实现对二级商户的账期,不建议电商平台利用限制二级商户提现进行账期控制,特殊情况下商户可直接到微信支付进行提现,造成账期控制无效。
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/fund/balance/{sub_mchid}
     * 请求方式:GET
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     *
     * </pre>
     *
     * @param subMchid 电商平台二级商户号,由微信支付生成并下发。
     * @return .
     */
    Optional<AmountOnlineOfSubMchResponse> queryOnlineAmount(String subMchid);
    /**
     * <pre>
     * 查询二级商户账户日终余额API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/amount/chapter3_2.shtml
     *
     * 电商服务商通过该接口可以查询二级商户指定日期当天24点的账户余额。
     *
     * 注意:
     * • 可查询90天内的日终余额。
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/fund/enddaybalance/{sub_mchid}
     * 请求方式:GET
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     *
     * </pre>
     *
     * @param subMchid 电商平台二级商户号,由微信支付生成并下发。
     * @param date     指定查询商户日终余额的日期 示例值:2019-08-17
     * @return .
     */
    Optional<AmountDayEndOfSubMchResponse> queryDayEndAmount(String subMchid, Date date);
    /**
     * <pre>
     * 查询电商平台账户实时余额API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/amount/chapter3_3.shtml
     *
     * 电商平台可通过此接口可以查询本商户号的账号余额情况。
     *
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/merchant/fund/balance/{account_type}
     * 请求方式:GET
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     *
     * </pre>
     *
     * @param accountType 账户类型
     * @return .
     */
    Optional<AmountOnlineOfPlatformResponse> queryOnlineAmount(AccountType accountType);
    /**
     * <pre>
     * 查询电商平台账户日终余额API
     * 通过此接口可以查询本商户号指定日期当天24点的账户余额。。
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/amount/chapter3_4.shtml
     *
     * 注意:
     * • 可查询90天内的日终余额。
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/merchant/fund/dayendbalance/{account_type}
     * 请求方式:GET
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     *
     * </pre>
     *
     * @param accountType 账户类型
     * @param date        指定查询商户日终余额的日期 示例值:2019-08-17
     * @return .
     */
    Optional<AmountDayEndOfPlatformResponse> queryDayEndAmount(AccountType accountType, Date date);
    /**
     * <pre>
     * 账户余额提现API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_2.shtml
     *
     * 电商平台通过余额提现API帮助二级商户发起账户余额提现申请,完成账户余额提现。
     *
     * 注意:
     * • 相同的“商户提现单号”+“二级商户商户号”可以提供20天内防重。
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/fund/withdraw
     * 请求方式:POST
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     *
     * @param request 请求对象
     * @return .
     */
    Optional<WithdrawForSubMchResponse> withdraw(WithdrawForSubMchRequest request);
    /**
     * <pre>
     * 二级商户查询提现状态API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_3.shtml
     *
     * 电商平台通过查询提现状态API查询二级商户提现单的提现结果。
     *
     * 注意:
     * • 支持查询一年内提现结果。
     *
     * 两种查询方式返回结果相同。
     *
     * 1、微信支付提现单号查询
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/fund/withdraw/{withdraw_id}
     * 请求方式:GET
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     *
     * </pre>
     *
     * @param subMchId   二级商户号
     * @param withdrawId 提现记录ID
     * @return .
     */
    Optional<WithdrawStatusForSubMchResponse> queryWithdrawStatus(String subMchId, String withdrawId);
    /**
     * <pre>
     * 二级商户查询提现状态API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_3.shtml
     *
     * 电商平台通过查询提现状态API查询二级商户提现单的提现结果。
     *
     * 注意:
     * • 支持查询一年内提现结果。
     *
     * 两种查询方式返回结果相同。
     *
     * 2、商户提现单号查询
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/ecommerce/fund/withdraw/out-request-no/{out_request_no}
     * 请求方式:GET
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     *
     * </pre>
     *
     * @param subMchId     二级商户ID
     * @param outRequestNo 业务编号
     * @return .
     */
    Optional<WithdrawStatusForSubMchResponse> queryWithdrawStatusByOutNo(String subMchId, String outRequestNo);
    /**
     * <pre>
     * 电商平台提现API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_5.shtml
     *
     * 电商平台通过该接口可将其平台的收入进行提现
     *
     * 注意:
     * • 只能在电商平台指定账户的可用余额中进行提现。
     * • 发起提现后如果微信支付正确返回了微信支付提现单号,查询状态需要隔日早上8点后进行。
     * • 查询结果可能存在延迟,提现发起后查询无单据并不代表没有发起提现,应以隔日查询结果为准判断单据是否存在。
     * • 查询结果中状态为INIT时并不代表一定未受理成功,需要等待7日后确定单据最终状态或者原单(所有请求参数保持不变)重入请求。
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/merchant/fund/withdraw
     * 请求方式:POST
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     *
     * </pre>
     *
     * @param request 请求对象
     * @return .
     */
    Optional<WithdrawForPlatformResponse> withdraw(WithdrawForPlatformRequest request);
    /**
     * <pre>
     * 电商平台查询提现状态API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_6.shtml
     *
     * 电商平台通过该接口查询其提现结果
     *
     * 注意:
     * • 发起提现后如果微信支付正确返回了微信支付提现单号,查询状态需要隔日早上8点后进行。
     * • 查询结果可能存在延迟,提现发起后查询无单据并不代表没有发起提现,应以隔日查询结果为准判断单据是否存在。
     * • 查询结果中状态为INIT时并不代表一定未受理成功,需要等待7日后确定单据最终状态或者原单(所有请求参数保持不变)重入请求。
     * • 可查询90天内的提现数据,时间以微信支付提现单创建时间为准。
     *
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/merchant/fund/withdraw/out-request-no/{out_request_no}
     * 请求方式:GET
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     *
     * @param outRequestNo 业务编号
     * @return .
     */
    Optional<WithdrawStatusForPlatformResponse> queryWithdrawStatus(String outRequestNo);
    /**
     * <pre>
     * 按日下载提现异常文件API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/ecommerce/fund/chapter3_4.shtml
     *
     * 电商服务商按日查询并下载提现状态为异常的提现单,提现异常包括提现失败和银行退票。
     *
     * 注意:
     * • 每日09:00开始可以下载前一日的提现异常文件,支持下载90天内提现状态变为提现异常的提现单文件。
     * • 日期(date)字段为提现状态变为提现异常的日期。建议输入日期为昨日,每天定时(早上9点后)查询昨日是否有状态为异常的提现单。
     * • 电商服务商查询的结果包括电商服务商发起的提现和给电商二级商户发起的提现。
     *
     * • 同一笔提现的相同数据可能出现在不同日期。即提现单A的失败数据,可能同时出现在1日和3日。
     * • 历史数据如果有某一日遗漏,则系统会补入当天的账单中。例如:今日为2019-11-15日,发现2019-11-12日某数据遗漏,则该数据会补入2019-11-15日。
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/merchant/fund/withdraw/bill-type/{bill_type}
     * 请求方式:GET
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     *
     * @param request 请求对象
     * @return 下载文件的地址
     */
    Optional<String> downloadWithdrawExceptionFile(WithdrawExceptionLogRequest request);
    /**
     * <pre>
     * 申请交易账单API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/bill/chapter3_1.shtml
     *
     * 微信支付按天提供交易账单文件,商户可以通过该接口获取账单文件的下载地址。文件内包含交易相关的金额、时间、营销等信息,供商户核对订单、退款、银行到账等情况。
     *
     * 注意:
     * • 微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账单中,跟原支付单订单号一致;
     * • 对账单中涉及金额的字段单位为“元”;
     * • 对账单接口只能下载三个月以内的账单。
     * • 小微商户不单独提供对账单下载,如有需要,可在调取“下载对账单”API接口时不传sub_mch_id,获取服务商下全量电商二级商户(包括小微商户和非小微商户)的对账单。
     * 接口说明
     * 适用对象:电商平台 服务商 直连商户
     * 请求URL:https://api.mch.weixin.qq.com/v3/bill/tradebill
     * 请求方式:GET
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     *
     * @param request 请求对象
     * @return 下载文件的地址
     */
    Optional<String> downloadTradeBill(BillOfTradeRequest request);
    /**
     * <pre>
     * 申请资金账单API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/bill/chapter3_2.shtml
     *
     * 微信支付按天提供微信支付账户的资金流水账单文件,商户可以通过该接口获取账单文件的下载地址。文件内包含该账户资金操作相关的业务单号、收支金额、记账时间等信息,供商户进行核对。
     *
     * 注意:
     * • 资金账单中的数据反映的是商户微信支付账户资金变动情况;
     * • 对账单中涉及金额的字段单位为“元”。
     * 接口说明
     * 适用对象:电商平台 服务商 直连商户
     * 请求URL:https://api.mch.weixin.qq.com/v3/bill/fundflowbill
     * 请求方式:GET
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     * </pre>
     *
     * @param request 请求对象
     * @return 下载文件的地址
     */
    Optional<String> downloadTradeBill(BillOfFundFlowRequest request);
    /**
     * <pre>
     * 下载账单API
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pay/bill/chapter3_3.shtml
     * 下载账单API为通用接口,交易/资金账单都可以通过该接口获取到对应的账单。
     *
     * 注意:
     * • 账单文件的下载地址的有效时间为30s。
     * • 强烈建议商户将实际账单文件的哈希值和之前从接口获取到的哈希值进行比对,以确认数据的完整性。
     * 接口说明
     * 适用对象:电商平台 服务商 直连商户
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     *
     * </pre>
     *
     * @param downloadUrl 下载地址
     * @return .
     */
    InputStream downloadBillFile(String downloadUrl);
    /**
     * <pre>
     * 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/tool/chapter3_1.shtml
     * 图片上传API
     * 最新更新时间:2019.09.09 版本说明
     * 部分微信支付业务指定商户需要使用图片上传 API来上报图片信息,从而获得必传参数的值:图片MediaID 。
     *
     * 接口说明
     * 适用对象:电商平台
     * 请求URL:https://api.mch.weixin.qq.com/v3/merchant/media/upload
     * 请求主体类型:multipart/form-data
     * 请求方式:POST
     * 接口规则:https://wechatpay-api.gitbook.io/wechatpay-api-v3
     *
     * path 指该参数需在请求URL传参
     * query 指该参数需在请求JSON传参
     * </pre>
     *
     * @param file 文件
     * @return .
     */
    Optional<ImageUploadResponse> uploadImage(File file) throws Exception;
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/service/ProfitsSharingServiceEmptyImpl.java
New file
@@ -0,0 +1,274 @@
package com.ruoyi.order.tools.service;
import com.ruoyi.order.tools.constant.AccountType;
import com.ruoyi.order.tools.request.ecommerce.fund.WithdrawExceptionLogRequest;
import com.ruoyi.order.tools.request.ecommerce.fund.WithdrawForPlatformRequest;
import com.ruoyi.order.tools.request.ecommerce.fund.WithdrawForSubMchRequest;
import com.ruoyi.order.tools.request.ecommerce.profitsharing.*;
import com.ruoyi.order.tools.request.ecommerce.refunds.RefundApplyRequest;
import com.ruoyi.order.tools.request.ecommerce.refunds.RefundNotifyRequest;
import com.ruoyi.order.tools.request.ecommerce.refunds.RefundNotifyRequest1;
import com.ruoyi.order.tools.request.ecommerce.subsidies.SubsidiesCancelRequest;
import com.ruoyi.order.tools.request.ecommerce.subsidies.SubsidiesCreateRequest;
import com.ruoyi.order.tools.request.ecommerce.subsidies.SubsidiesRefundRequest;
import com.ruoyi.order.tools.request.pay.bill.BillOfFundFlowRequest;
import com.ruoyi.order.tools.request.pay.bill.BillOfTradeRequest;
import com.ruoyi.order.tools.request.pay.combine.CombineTransactionsAppRequest;
import com.ruoyi.order.tools.request.pay.combine.CombineTransactionsCloseRequest;
import com.ruoyi.order.tools.request.pay.combine.CombineTransactionsJsRequest;
import com.ruoyi.order.tools.request.pay.combine.CombineTransactionsNotifyRequest1;
import com.ruoyi.order.tools.response.ecommerce.amount.AmountDayEndOfPlatformResponse;
import com.ruoyi.order.tools.response.ecommerce.amount.AmountDayEndOfSubMchResponse;
import com.ruoyi.order.tools.response.ecommerce.amount.AmountOnlineOfPlatformResponse;
import com.ruoyi.order.tools.response.ecommerce.amount.AmountOnlineOfSubMchResponse;
import com.ruoyi.order.tools.response.ecommerce.applyments.ApplymentsModifySettlementResponse;
import com.ruoyi.order.tools.response.ecommerce.applyments.ApplymentsResponse;
import com.ruoyi.order.tools.applyments.ApplymentsRequest;
import com.ruoyi.order.tools.response.ecommerce.applyments.ApplymentsSettlementStatusResponse;
import com.ruoyi.order.tools.response.ecommerce.applyments.ApplymentsStatusResponse;
import com.ruoyi.order.tools.applyments.ApplymentsModifySettlementRequest;
import com.ruoyi.order.tools.response.ecommerce.fund.WithdrawForPlatformResponse;
import com.ruoyi.order.tools.response.ecommerce.fund.WithdrawForSubMchResponse;
import com.ruoyi.order.tools.response.ecommerce.fund.WithdrawStatusForPlatformResponse;
import com.ruoyi.order.tools.response.ecommerce.fund.WithdrawStatusForSubMchResponse;
import com.ruoyi.order.tools.response.ecommerce.profitsharing.*;
import com.ruoyi.order.tools.response.ecommerce.refunds.RefundApplyResponse;
import com.ruoyi.order.tools.response.ecommerce.refunds.RefundQueryStatusResponse;
import com.ruoyi.order.tools.response.ecommerce.subsidies.SubsidiesCancelResponse;
import com.ruoyi.order.tools.response.ecommerce.subsidies.SubsidiesCreateResponse;
import com.ruoyi.order.tools.response.ecommerce.subsidies.SubsidiesRefundResponse;
import com.ruoyi.order.tools.response.pay.combine.CombineTransactionsStatusResponse;
import com.ruoyi.order.tools.response.tool.ImageUploadResponse;
import java.io.File;
import java.io.InputStream;
import java.security.cert.X509Certificate;
import java.util.*;
public class ProfitsSharingServiceEmptyImpl implements ProfitsSharingService {
    @Override
    public Optional<ApplymentsResponse> applyments(ApplymentsRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<ApplymentsStatusResponse> queryApplymentsStatus(String applymentId) {
        return Optional.empty();
    }
    @Override
    public Optional<ApplymentsStatusResponse> queryApplymentsStatusByOutNo(String outRequestNo) {
        return Optional.empty();
    }
    @Override
    public List<X509Certificate> downloadCertificates() {
        return Collections.emptyList();
    }
    @Override
    public Optional<ApplymentsModifySettlementResponse> modifySettlement(ApplymentsModifySettlementRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<ApplymentsSettlementStatusResponse> querySettlement(String subMchid) {
        return Optional.empty();
    }
    @Override
    public Optional<String> combineTransactions(CombineTransactionsAppRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<String> combineTransactions(CombineTransactionsJsRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<CombineTransactionsStatusResponse> combineTransactionsStatus(String combineOutTradeNo) {
        return Optional.empty();
    }
    @Override
    public void combineTransactionsClose(CombineTransactionsCloseRequest request) {
    }
    @Override
    public Map<String, String> getAppPayParams(String prePayId, String appId) {
        return null;
    }
    @Override
    public Map<String, String> getJsPayParams(String prePayId, String appId) {
        return null;
    }
    @Override
    public Map<String, String> getSmallPayParams(String prePayId, String appId) {
        return null;
    }
    @Override
    public boolean verifyNotifySign(String timeStamp, String nonce, String body, String signed, String serialNo) {
        return false;
    }
    @Override
    public Optional<CombineTransactionsNotifyRequest1> parsePayNotify(String notifyContent) {
        return Optional.empty();
    }
    @Override
    public Optional<SubsidiesCreateResponse> subsidiesCreate(SubsidiesCreateRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<SubsidiesRefundResponse> subsidiesRefund(SubsidiesRefundRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<SubsidiesCancelResponse> subsidiesCancel(SubsidiesCancelRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<ProfitSharingApplyResponse> applyProfitSharing(ProfitSharingApplyRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<String> getPlatformId() {
        return Optional.empty();
    }
    @Override
    public Optional<ProfitSharingQueryApplyResponse> queryProfitSharingStatus(ProfitSharingQueryApplyRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<ProfitSharingRefundResponse> refundProfitSharing(ProfitSharingRefundRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<ProfitSharingQueryRefundResponse> queryRefundProfitSharingStatus(ProfitSharingQueryRefundRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<ProfitSharingFinishResponse> finishProfitSharing(ProfitSharingFinishRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<ProfitSharingAddReceiverResponse> addReceiver(ProfitSharingAddReceiverRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<ProfitSharingRemoveReceiverResponse> removeReceiver(ProfitSharingRemoveReceiverRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<ProfitSharingNotifyRequest1> parseProfitsSharingNotify(ProfitSharingNotifyRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<RefundApplyResponse> refundApply(RefundApplyRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<RefundQueryStatusResponse> refundQueryById(String subMchid, String refundId) {
        return Optional.empty();
    }
    @Override
    public Optional<RefundQueryStatusResponse> refundQueryByNumber(String subMchid, String outRefundNo) {
        return Optional.empty();
    }
    @Override
    public Optional<RefundNotifyRequest1> parseRefundNotify(RefundNotifyRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<AmountOnlineOfSubMchResponse> queryOnlineAmount(String subMchid) {
        return Optional.empty();
    }
    @Override
    public Optional<AmountDayEndOfSubMchResponse> queryDayEndAmount(String subMchid, Date date) {
        return Optional.empty();
    }
    @Override
    public Optional<AmountOnlineOfPlatformResponse> queryOnlineAmount(AccountType accountType) {
        return Optional.empty();
    }
    @Override
    public Optional<AmountDayEndOfPlatformResponse> queryDayEndAmount(AccountType accountType, Date date) {
        return Optional.empty();
    }
    @Override
    public Optional<WithdrawForSubMchResponse> withdraw(WithdrawForSubMchRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<WithdrawStatusForSubMchResponse> queryWithdrawStatusByOutNo(String subMchId, String outRequestNo) {
        return Optional.empty();
    }
    @Override
    public Optional<WithdrawForPlatformResponse> withdraw(WithdrawForPlatformRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<WithdrawStatusForSubMchResponse> queryWithdrawStatus(String subMchId, String withdrawId) {
        return Optional.empty();
    }
    @Override
    public Optional<WithdrawStatusForPlatformResponse> queryWithdrawStatus(String outRequestNo) {
        return Optional.empty();
    }
    @Override
    public Optional<String> downloadWithdrawExceptionFile(WithdrawExceptionLogRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<String> downloadTradeBill(BillOfTradeRequest request) {
        return Optional.empty();
    }
    @Override
    public Optional<String> downloadTradeBill(BillOfFundFlowRequest request) {
        return Optional.empty();
    }
    @Override
    public InputStream downloadBillFile(String downloadUrl) {
        return null;
    }
    @Override
    public Optional<ImageUploadResponse> uploadImage(File file) {
        return Optional.empty();
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/service/ProfitsSharingServiceImpl.java
New file
@@ -0,0 +1,636 @@
package com.ruoyi.order.tools.service;
import com.ruoyi.order.tools.auth.CacheService;
import com.ruoyi.order.tools.config.ProfitsSharingConfig;
import com.ruoyi.order.tools.request.pay.combine.*;
import com.ruoyi.order.tools.response.AbstractResponse;
import com.ruoyi.order.tools.response.ecommerce.fund.*;
import com.ruoyi.order.tools.response.pay.bill.BillOfFundFlowResponse;
import com.ruoyi.order.tools.response.pay.bill.BillOfTradeResponse;
import com.ruoyi.order.tools.response.pay.combine.CombineTransactionsAppResponse;
import com.ruoyi.order.tools.response.pay.combine.CombineTransactionsCloseResponse;
import com.ruoyi.order.tools.response.pay.combine.CombineTransactionsJsResponse;
import com.ruoyi.order.tools.utils.HttpUtils;
import com.ruoyi.order.tools.utils.JsonUtils;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import com.ruoyi.order.tools.constant.AccountType;
import com.ruoyi.order.tools.request.ecommerce.fund.WithdrawExceptionLogRequest;
import com.ruoyi.order.tools.request.ecommerce.fund.WithdrawForPlatformRequest;
import com.ruoyi.order.tools.request.ecommerce.fund.WithdrawForSubMchRequest;
import com.ruoyi.order.tools.request.ecommerce.profitsharing.*;
import com.ruoyi.order.tools.request.ecommerce.refunds.RefundApplyRequest;
import com.ruoyi.order.tools.request.ecommerce.refunds.RefundNotifyRequest;
import com.ruoyi.order.tools.request.ecommerce.refunds.RefundNotifyRequest1;
import com.ruoyi.order.tools.request.ecommerce.subsidies.SubsidiesCancelRequest;
import com.ruoyi.order.tools.request.ecommerce.subsidies.SubsidiesCreateRequest;
import com.ruoyi.order.tools.request.ecommerce.subsidies.SubsidiesRefundRequest;
import com.ruoyi.order.tools.request.pay.bill.BillOfFundFlowRequest;
import com.ruoyi.order.tools.request.pay.bill.BillOfTradeRequest;
import com.ruoyi.order.tools.response.ecommerce.amount.AmountDayEndOfPlatformResponse;
import com.ruoyi.order.tools.response.ecommerce.amount.AmountDayEndOfSubMchResponse;
import com.ruoyi.order.tools.response.ecommerce.amount.AmountOnlineOfPlatformResponse;
import com.ruoyi.order.tools.response.ecommerce.amount.AmountOnlineOfSubMchResponse;
import com.ruoyi.order.tools.response.ecommerce.applyments.ApplymentsModifySettlementResponse;
import com.ruoyi.order.tools.response.ecommerce.applyments.ApplymentsResponse;
import com.ruoyi.order.tools.applyments.ApplymentsRequest;
import com.ruoyi.order.tools.response.ecommerce.applyments.ApplymentsSettlementStatusResponse;
import com.ruoyi.order.tools.response.ecommerce.applyments.ApplymentsStatusResponse;
import com.ruoyi.order.tools.applyments.ApplymentsModifySettlementRequest;
import com.ruoyi.order.tools.response.ecommerce.profitsharing.*;
import com.ruoyi.order.tools.response.ecommerce.refunds.RefundApplyResponse;
import com.ruoyi.order.tools.response.ecommerce.refunds.RefundQueryStatusResponse;
import com.ruoyi.order.tools.response.ecommerce.subsidies.SubsidiesCancelResponse;
import com.ruoyi.order.tools.response.ecommerce.subsidies.SubsidiesCreateResponse;
import com.ruoyi.order.tools.response.ecommerce.subsidies.SubsidiesRefundResponse;
import com.ruoyi.order.tools.response.pay.combine.CombineTransactionsStatusResponse;
import com.ruoyi.order.tools.response.tool.ImageUploadResponse;
import javax.crypto.Cipher;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
public class ProfitsSharingServiceImpl implements ProfitsSharingService {
    private final ProfitsSharingConfig config;
    private final HttpUtils httpUtils;
    private final AesUtil aesUtil;
    public ProfitsSharingServiceImpl(ProfitsSharingConfig config, CacheService cacheService) {
        this.config = config;
        httpUtils = new HttpUtils(config, cacheService);
        aesUtil = new AesUtil(config.getApiKey().getBytes());
    }
    private PrivateKey getPrivateKey() {
        return config.getPrivateKey();
    }
    @Override
    public Optional<ApplymentsResponse> applyments(ApplymentsRequest request) {
        Optional<X509Certificate> x509Certificate = getFirstCertificate();
        if (x509Certificate.isPresent()) {
            X509Certificate certificate = x509Certificate.get();
            ApplymentsRequest.AccountInfo accountInfo = request.getAccountInfo();
            if (accountInfo != null) {
                accountInfo.setAccountName(rsaEncryptOAEP(accountInfo.getAccountName(), certificate));
                accountInfo.setAccountNumber(rsaEncryptOAEP(accountInfo.getAccountNumber(), certificate));
            }
            ApplymentsRequest.ContactInfo contactInfo = request.getContactInfo();
            if (contactInfo != null) {
                contactInfo.setMobilePhone(rsaEncryptOAEP(contactInfo.getMobilePhone(), certificate));
                contactInfo.setContactEmail(rsaEncryptOAEP(contactInfo.getContactEmail(), certificate));
                contactInfo.setContactName(rsaEncryptOAEP(contactInfo.getContactName(), certificate));
                contactInfo.setContactIdCardNumber(rsaEncryptOAEP(contactInfo.getContactIdCardNumber(), certificate));
            }
            ApplymentsRequest.IdCardInfo idCardInfo = request.getIdCardInfo();
            if (idCardInfo != null) {
                idCardInfo.setIdCardNumber(rsaEncryptOAEP(idCardInfo.getIdCardNumber(), certificate));
                idCardInfo.setIdCardName(rsaEncryptOAEP(idCardInfo.getIdCardName(), certificate));
            }
            return post(ApplymentsResponse.class, request, "https://api.mch.weixin.qq.com/v3/ecommerce/applyments/", certificate);
        }
        return Optional.empty();
    }
    private String rsaEncryptOAEP(String message, X509Certificate x509Cert) {
        if (StringUtils.isBlank(message)) {
            return message;
        }
        try {
            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, x509Cert.getPublicKey());
            byte[] data = message.getBytes(StandardCharsets.UTF_8);
            byte[] cipherdata = cipher.doFinal(data);
            return Base64.getEncoder().encodeToString(cipherdata);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return null;
        }
    }
    @Override
    public Optional<ApplymentsStatusResponse> queryApplymentsStatus(String applymentId) {
        return get(ApplymentsStatusResponse.class, String.format("https://api.mch.weixin.qq.com/v3/ecommerce/applyments/%s",
                applymentId));
    }
    @Override
    public Optional<ApplymentsStatusResponse> queryApplymentsStatusByOutNo(String outRequestNo) {
        return get(ApplymentsStatusResponse.class, String.format("https://api.mch.weixin.qq.com/v3/ecommerce/applyments/out-request-no/%s",
                outRequestNo));
    }
    @Override
    public List<X509Certificate> downloadCertificates() {
        return httpUtils.getLastCertificateList(); // 和内置的工具统一出口
    }
    @Override
    public Optional<ApplymentsModifySettlementResponse> modifySettlement(ApplymentsModifySettlementRequest request) {
        Optional<X509Certificate> x509Certificate = getFirstCertificate();
        if (x509Certificate.isPresent()) {
            X509Certificate certificate = x509Certificate.get();
            String accountNumber = request.getAccountNumber();
            request.setAccountNumber(rsaEncryptOAEP(accountNumber, certificate));
            return post(ApplymentsModifySettlementResponse.class, request,
                    String.format("https://api.mch.weixin.qq.com/v3/apply4sub/sub_merchants/%s/modify-settlement",
                            request.getSubMchid()), certificate);
        }
        return Optional.empty();
    }
    private Optional<X509Certificate> getFirstCertificate() {
        List<X509Certificate> lastCertificateList = downloadCertificates();
        return lastCertificateList.stream().findFirst();
    }
    @Override
    public Optional<ApplymentsSettlementStatusResponse> querySettlement(String subMchid) {
        return get(ApplymentsSettlementStatusResponse.class,
                String.format("https://api.mch.weixin.qq.com/v3/apply4sub/sub_merchants/%s/settlement", subMchid));
    }
    @Override
    public Optional<String> combineTransactions(CombineTransactionsAppRequest request) {
        Optional<CombineTransactionsAppResponse> responseOptional = post(CombineTransactionsAppResponse.class, request,
                "https://api.mch.weixin.qq.com/v3/combine-transactions/app");
        return responseOptional.map(CombineTransactionsAppResponse::getPrepayId);
    }
    @Override
    public Optional<String> combineTransactions(CombineTransactionsJsRequest request) {
        Optional<CombineTransactionsJsResponse> responseOptional = post(CombineTransactionsJsResponse.class, request,
                "https://api.mch.weixin.qq.com/v3/combine-transactions/jsapi");
        return responseOptional.map(CombineTransactionsJsResponse::getPrepayId);
    }
    @Override
    public Optional<CombineTransactionsStatusResponse> combineTransactionsStatus(String combineOutTradeNo) {
        String url = String.format("https://api.mch.weixin.qq.com/v3/combine-transactions/out-trade-no/%s", combineOutTradeNo);
        return get(CombineTransactionsStatusResponse.class, url);
    }
    @Override
    public void combineTransactionsClose(CombineTransactionsCloseRequest request) {
        String url = String.format("https://api.mch.weixin.qq.com/v3/combine-transactions/out-trade-no/%s/close", request.getCombineOutTradeNo());
        post(CombineTransactionsCloseResponse.class, request, url);
    }
    @Override
    public Map<String, String> getAppPayParams(String prePayId, String appId) {
        Map<String, String> params = getParams();
        params.put("appId", appId);
        long timeStamp = System.currentTimeMillis();
        String nonceStr = timeStamp + "_app";
        params.put("timeStamp", timeStamp + "");
        params.put("nonceStr", nonceStr);
        params.put("package", "Sign=WXPay");
        params.put("signType", "RSA");
        String singSource = String.format("%s\n%s\n%s\n%s\n",
                appId,
                timeStamp,
                nonceStr,
                prePayId);
        String sign = sign(singSource);
        params.put("paySign", sign);
        return params;
    }
    @Override
    public Map<String, String> getJsPayParams(String prePayId, String appId) {
        Map<String, String> params = getParams();
        params.put("appId", appId);
        long timeStamp = System.currentTimeMillis();
        String nonceStr = timeStamp + "_js";
        params.put("timeStamp", timeStamp + "");
        params.put("nonceStr", nonceStr);
        String packageVal = "prepay_id=" + prePayId;
        params.put("package", packageVal);
        String signType = "RSA";
        params.put("signType", signType);
        String singSource = String.format("%s\n%s\n%s\n%s\n",
                appId,
                timeStamp,
                nonceStr,
                packageVal);
        String sign = sign(singSource);
        params.put("paySign", sign);
        return params;
    }
    private Map<String, String> getParams() {
        return new HashMap<>();
    }
    @Override
    public Map<String, String> getSmallPayParams(String prePayId, String appId) {
        return getJsPayParams(prePayId, appId);
    }
    @Override
    public boolean verifyNotifySign(String timeStamp, String nonce, String body, String signed, String serialNo) {
        String beforeSign = timeStamp + "\n" + nonce + "\n" + body + "\n";
        return httpUtils.getVerifier().verify(serialNo, beforeSign.getBytes(StandardCharsets.UTF_8), signed);
    }
    @Override
    public Optional<CombineTransactionsNotifyRequest1> parsePayNotify(String notifyContent) {
        if (StringUtils.isNoneBlank(notifyContent)) {
            CombineTransactionsNotifyRequest request = JsonUtils.json2Bean(CombineTransactionsNotifyRequest.class, notifyContent);
            CombineTransactionsNotifyRequest.Resource resource = request.getResource();
            try {
                String json = aesUtil.decryptToString(resource.getAssociatedData().getBytes(), resource.getNonce().getBytes(), resource.getCiphertext());
                CombineTransactionsNotifyRequest1 request1 = JsonUtils.json2Bean(CombineTransactionsNotifyRequest1.class, json);
                return Optional.ofNullable(request1);
            } catch (GeneralSecurityException  e) {
                log.error(e.getMessage(), e);
            }
        }
        return Optional.empty();
    }
    @Override
    public Optional<SubsidiesCreateResponse> subsidiesCreate(SubsidiesCreateRequest request) {
        return post(SubsidiesCreateResponse.class, request,
                "https://api.mch.weixin.qq.com/v3/ecommerce/subsidies/create");
    }
    @Override
    public Optional<SubsidiesRefundResponse> subsidiesRefund(SubsidiesRefundRequest request) {
        return post(SubsidiesRefundResponse.class, request,
                "https://api.mch.weixin.qq.com/v3/ecommerce/subsidies/return");
    }
    @Override
    public Optional<SubsidiesCancelResponse> subsidiesCancel(SubsidiesCancelRequest request) {
        return post(SubsidiesCancelResponse.class, request,
                "https://api.mch.weixin.qq.com/v3/ecommerce/subsidies/cancel");
    }
    @Override
    public Optional<ProfitSharingApplyResponse> applyProfitSharing(ProfitSharingApplyRequest request) {
        return post(ProfitSharingApplyResponse.class, request, "https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/orders");
    }
    @Override
    public Optional<String> getPlatformId() {
        return Optional.ofNullable(config.getMchId());
    }
    @Override
    public Optional<ProfitSharingQueryApplyResponse> queryProfitSharingStatus(ProfitSharingQueryApplyRequest request) {
        Map<String, String> params = getParams();
        params.put("sub_mchid", request.getSubMchid());
        params.put("transaction_id", request.getTransactionId());
        params.put("out_order_no", request.getOutOrderNo());
        return get(ProfitSharingQueryApplyResponse.class, "https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/orders", params);
    }
    @Override
    public Optional<ProfitSharingRefundResponse> refundProfitSharing(ProfitSharingRefundRequest request) {
        return post(ProfitSharingRefundResponse.class, request, "https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/returnorders");
    }
    @Override
    public Optional<ProfitSharingQueryRefundResponse> queryRefundProfitSharingStatus(ProfitSharingQueryRefundRequest request) {
        Map<String, String> params = getParams();
        params.put("sub_mchid", request.getSubMchid());
        params.put("order_id", request.getOrderId());
        params.put("out_order_no", request.getOutOrderNo());
        params.put("out_return_no", request.getOutReturnNo());
        return get(ProfitSharingQueryRefundResponse.class, "https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/returnorders", params);
    }
    @Override
    public Optional<ProfitSharingFinishResponse> finishProfitSharing(ProfitSharingFinishRequest request) {
        return post(ProfitSharingFinishResponse.class, request, "https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/finish-order");
    }
    @Override
    public Optional<ProfitSharingAddReceiverResponse> addReceiver(ProfitSharingAddReceiverRequest request) {
        return post(ProfitSharingAddReceiverResponse.class, request, "https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/receivers/add");
    }
    @Override
    public Optional<ProfitSharingRemoveReceiverResponse> removeReceiver(ProfitSharingRemoveReceiverRequest request) {
        return post(ProfitSharingRemoveReceiverResponse.class, request, "https://api.mch.weixin.qq.com/v3/ecommerce/profitsharing/receivers/delete");
    }
    @Override
    public Optional<ProfitSharingNotifyRequest1> parseProfitsSharingNotify(ProfitSharingNotifyRequest request) {
        if (request != null) {
            ProfitSharingNotifyRequest.Resource resource = request.getResource();
            try {
                String json = aesUtil.decryptToString(resource.getAssociatedData().getBytes(), resource.getNonce().getBytes(), resource.getCiphertext());
                ProfitSharingNotifyRequest1 request1 = JsonUtils.json2Bean(ProfitSharingNotifyRequest1.class, json);
                return Optional.ofNullable(request1);
            } catch (GeneralSecurityException  e) {
                log.error(e.getMessage(), e);
            }
        }
        return Optional.empty();
    }
    @Override
    public Optional<RefundApplyResponse> refundApply(RefundApplyRequest request) {
        return post(RefundApplyResponse.class, request,
                "https://api.mch.weixin.qq.com/v3/ecommerce/refunds/apply");
    }
    @Override
    public Optional<RefundQueryStatusResponse> refundQueryById(String subMchid, String refundId) {
        String url = String.format("https://api.mch.weixin.qq.com/v3/ecommerce/refunds/%s/%s", subMchid, refundId);
        return post(RefundQueryStatusResponse.class, new Object(), url);
    }
    @Override
    public Optional<RefundQueryStatusResponse> refundQueryByNumber(String subMchid, String outRefundNo) {
        String url = String.format("https://api.mch.weixin.qq.com/v3/ecommerce/refunds/%s/%s", subMchid, outRefundNo);
        return post(RefundQueryStatusResponse.class, new Object(), url);
    }
    @Override
    public Optional<RefundNotifyRequest1> parseRefundNotify(RefundNotifyRequest request) {
        if (request != null) {
            RefundNotifyRequest.Resource resource = request.getResource();
            try {
                String json = aesUtil.decryptToString(resource.getAssociatedData().getBytes(), resource.getNonce().getBytes(), resource.getCiphertext());
                RefundNotifyRequest1 request1 = JsonUtils.json2Bean(RefundNotifyRequest1.class, json);
                return Optional.ofNullable(request1);
            } catch (GeneralSecurityException  e) {
                log.error(e.getMessage(), e);
            }
        }
        return Optional.empty();
    }
    @Override
    public Optional<AmountOnlineOfSubMchResponse> queryOnlineAmount(String subMchid) {
        return get(AmountOnlineOfSubMchResponse.class,
                String.format("https://api.mch.weixin.qq.com/v3/ecommerce/fund/balance/%s", subMchid));
    }
    @Override
    public Optional<AmountDayEndOfSubMchResponse> queryDayEndAmount(String subMchid, Date date) {
        // 这边文档写的是在body json数据体中,可是。。。按照标准,应该get请求直接包含在query参数中。。
        String url = String.format("https://api.mch.weixin.qq.com/v3/ecommerce/fund/enddaybalance/%s?date=%s",
                subMchid, getFormatDate(date));
        return get(AmountDayEndOfSubMchResponse.class, url);
    }
    @Override
    public Optional<AmountOnlineOfPlatformResponse> queryOnlineAmount(AccountType accountType) {
        String url = String.format("https://api.mch.weixin.qq.com/v3/merchant/fund/balance/%s", accountType);
        return get(AmountOnlineOfPlatformResponse.class, url);
    }
    @Override
    public Optional<AmountDayEndOfPlatformResponse> queryDayEndAmount(AccountType accountType, Date date) {
        String url = String.format("https://api.mch.weixin.qq.com/v3/merchant/fund/dayendbalance/%s?date=%s",
                accountType, getFormatDate(date));
        return get(AmountDayEndOfPlatformResponse.class, url);
    }
    @Override
    public Optional<WithdrawForSubMchResponse> withdraw(WithdrawForSubMchRequest request) {
        return post(WithdrawForSubMchResponse.class, request, "https://api.mch.weixin.qq.com/v3/ecommerce/fund/withdraw");
    }
    @Override
    public Optional<WithdrawStatusForSubMchResponse> queryWithdrawStatus(String subMchId, String withdrawId) {
        return get(WithdrawStatusForSubMchResponse.class,
                String.format("https://api.mch.weixin.qq.com/v3/ecommerce/fund/withdraw/%s?sub_mchid=%s",
                        withdrawId,
                        subMchId));
    }
    @Override
    public Optional<WithdrawStatusForSubMchResponse> queryWithdrawStatusByOutNo(String subMchId, String outRequestNo) {
        return get(WithdrawStatusForSubMchResponse.class,
                String.format("https://api.mch.weixin.qq.com/v3/ecommerce/fund/withdraw/out-request-no/%s?sub_mchid=%s",
                        outRequestNo,
                        subMchId));
    }
    @Override
    public Optional<WithdrawForPlatformResponse> withdraw(WithdrawForPlatformRequest request) {
        return post(WithdrawForPlatformResponse.class, request, "https://api.mch.weixin.qq.com/v3/merchant/fund/withdraw");
    }
    @Override
    public Optional<WithdrawStatusForPlatformResponse> queryWithdrawStatus(String outRequestNo) {
        return get(WithdrawStatusForPlatformResponse.class,
                String.format("https://api.mch.weixin.qq.com/v3/merchant/fund/withdraw/out-request-no/%s",
                        outRequestNo));
    }
    @Override
    public Optional<String> downloadWithdrawExceptionFile(WithdrawExceptionLogRequest request) {
        Optional<WithdrawExceptionLogResponse> responseOptional = get(WithdrawExceptionLogResponse.class,
                String.format("https://api.mch.weixin.qq.com/v3/merchant/fund/withdraw/bill-type/%s?bill_date=%s&tar_type=%s",
                        request.getBillType(),
                        request.getBillDate(),
                        request.getTarType())
        );
        return responseOptional.map(WithdrawExceptionLogResponse::getDownloadUrl);
    }
    @Override
    public Optional<String> downloadTradeBill(BillOfTradeRequest request) {
        Map<String, String> query = new HashMap<>();
        query.put("bill_date", request.getBillDate());
        query.put("bill_type", request.getBillType());
        query.put("tar_type", request.getTarType());
        Optional<BillOfTradeResponse> response = get(BillOfTradeResponse.class, "https://api.mch.weixin.qq.com/v3/bill/tradebill", query);
        return response.map(BillOfTradeResponse::getDownloadUrl);
    }
    @Override
    public Optional<String> downloadTradeBill(BillOfFundFlowRequest request) {
        Map<String, String> query = new HashMap<>();
        query.put("bill_date", request.getBillDate());
        query.put("account_type", request.getAccountType());
        String tarType = request.getTarType();
        if (StringUtils.isNoneBlank(tarType)) {
            query.put("tar_type", tarType);
        }
        Optional<BillOfFundFlowResponse> response = get(BillOfFundFlowResponse.class, "https://api.mch.weixin.qq.com/v3/bill/fundflowbill", query);
        return response.map(BillOfFundFlowResponse::getDownloadUrl);
    }
    @Override
    public InputStream downloadBillFile(String downloadUrl) {
        return httpUtils.download(downloadUrl);
    }
    @Override
    public Optional<ImageUploadResponse> uploadImage(File file) throws Exception {
        // 商户号
        String mchid = config.getMchId();
        // 证书序列号
        String serial_no = config.getMchSerialNo();
        // 时间戳
        String timestamp = Long.toString(System.currentTimeMillis() / 1000);
        // 随机数
        String nonce_str = UUID.randomUUID().toString();
        // 图片文件
        String filename = file.getName();//文件名
        String fileSha256 = DigestUtils.sha256Hex(new FileInputStream(file));//文件sha256
        //计算签名
        String sb = "POST" + "\n" +
                "/v3/merchant/media/upload" + "\n" +
                timestamp + "\n" +
                nonce_str + "\n" +
                "{\"filename\":\"" + filename + "\",\"sha256\":\"" + fileSha256 + "\"}" + "\n";
        String sign = sign(sb);
        // 拼装http头的Authorization内容
        String authorization = "WECHATPAY2-SHA256-RSA2048 mchid=\"" + mchid + "\",nonce_str=\"" + nonce_str + "\",signature=\"" + sign + "\",timestamp=\"" + timestamp + "\",serial_no=\"" + serial_no + "\"";
        //接口URL
        CloseableHttpClient httpclient = HttpClients.createDefault();
        String url = "https://api.mch.weixin.qq.com/v3/merchant/media/upload";
        HttpPost httpPost = new HttpPost(url);
        // 设置头部
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-Type", "multipart/form-data");
        httpPost.addHeader("Authorization", authorization);
        // 创建MultipartEntityBuilder
        MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);
        // 设置boundary
        multipartEntityBuilder.setBoundary("boundary");
        multipartEntityBuilder.setCharset(StandardCharsets.UTF_8);
        // 设置meta内容
        multipartEntityBuilder.addTextBody("meta", "{\"filename\":\"" + filename + "\",\"sha256\":\"" + fileSha256 + "\"}", ContentType.APPLICATION_JSON);
        // 设置图片内容
        multipartEntityBuilder.addBinaryBody("file", file, ContentType.create("image/jpg"), filename);
        // 放入内容
        httpPost.setEntity(multipartEntityBuilder.build());
        // 获取返回内容
        CloseableHttpResponse response = httpclient.execute(httpPost);
        HttpEntity httpEntity = response.getEntity();
        String responseText = new String(InputStreamTOByte(httpEntity.getContent()));
        // 验证微信支付返回签名
        String timestampHeader = getHeaderString(response, "Wechatpay-Timestamp");
        String nonceHeader = getHeaderString(response, "Wechatpay-Nonce");
        String singedHear = getHeaderString(response, "Wechatpay-Signature");
        if (timestampHeader != null && nonceHeader != null && singedHear != null) {
            String serialHeader = getHeaderString(response, "Wechatpay-Serial");
            if (verifyNotifySign(timestampHeader, nonceHeader, responseText, singedHear, serialHeader)) {
                EntityUtils.consume(httpEntity);
                response.close();
                ImageUploadResponse imageUploadResponse = JsonUtils.json2Bean(ImageUploadResponse.class, responseText);
                if (imageUploadResponse == null) {
                    return Optional.empty();
                }
                imageUploadResponse.setHttpStatusCode(response.getStatusLine().getStatusCode());
                return Optional.of(imageUploadResponse);
            } else {
                log.info("签名验证失败");
            }
        }
        return Optional.empty();
    }
    private String getHeaderString(CloseableHttpResponse response, String name) {
        Header firstHeader = response.getFirstHeader(name);
        if (firstHeader != null) {
            return firstHeader.getValue();
        }
        return null;
    }
    private String sign(String message) {
        try {
            Signature sign = Signature.getInstance("SHA256withRSA");
            sign.initSign(getPrivateKey());
            sign.update(message.getBytes());
            return Base64.getEncoder().encodeToString(sign.sign());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return message;
    }
    public static byte[] InputStreamTOByte(InputStream in) throws IOException {
        int BUFFER_SIZE = 4096;
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] data = new byte[BUFFER_SIZE];
        int count;
        while ((count = in.read(data, 0, BUFFER_SIZE)) != -1)
            outStream.write(data, 0, count);
        byte[] outByte = outStream.toByteArray();
        outStream.close();
        return outByte;
    }
    private <T extends AbstractResponse> Optional<T> post(Class<T> classZ, Object request, String url) {
        T post = httpUtils.post(classZ, request, url);
        if (post == null) {
            return Optional.empty();
        }
        return Optional.of(post);
    }
    private <T extends AbstractResponse> Optional<T> post(Class<T> classZ, Object request, String url, X509Certificate certificate) {
        T post = httpUtils.post(classZ, request, url, certificate);
        if (post == null) {
            return Optional.empty();
        }
        return Optional.of(post);
    }
    private <T extends AbstractResponse> Optional<T> get(Class<T> classZ, String url) {
        T value = httpUtils.get(classZ, url);
        if (value == null) {
            return Optional.empty();
        }
        return Optional.of(value);
    }
    private <T extends AbstractResponse> Optional<T> get(Class<T> classZ, String url, Map<String, String> query) {
        if (query != null && !query.isEmpty()) {
            if (!url.contains("?")) {
                url += "?";
            }
            String queryStr = query.keySet().stream().map(key -> key + "=" + query.get(key)).collect(Collectors.joining("&"));
            url += queryStr;
        }
        return get(classZ, url);
    }
    private String getFormatDate(Date date) {
        return DateFormatUtils.format(date, "yyyy-MM-dd");
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/utils/BuilderDTOUtils.java
New file
@@ -0,0 +1,362 @@
package com.ruoyi.order.tools.utils;
import lombok.Data;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class BuilderDTOUtils {
    @Data
    static class DTO {
        private boolean isObject;
        private String name;
        private String field;
        private String type;
        private String required;
        private String desc;
        private List<DTO> childList = new ArrayList<>();
        public DTO(boolean isObject, String name, String field, String type, String required, String desc) {
            this.isObject = isObject;
            this.name = name;
            this.field = field;
            this.type = type;
            this.required = required;
            this.desc = desc;
        }
    }
    public void builder(String url, String path, String fileName) throws IOException {
        String[] modules = url.split("/wxpay/")[1].split("chapter")[0].split("/");
        Document document = Jsoup.connect(url).get();
        String redirectUrl;
        // 由于新的文档使用了js脚本转跳,所以需要递归去获取实际的文档地址
        while ((redirectUrl = getRedirect(document)) != null) {
            document = Jsoup.connect(redirectUrl).get();
        }
        // 单页文档中有多个接口
        boolean mulEntity = document.select(".part").size() > 4;
        int[] is = new int[]{-1, -1};
        Elements tables = document.select("table");
        for (Element table : tables) {
            List<DTO> list = getDtos(table);
            boolean containsPathParams = containsPathParams(list);
            String text = table.parent().parent().select("h3").text();
            boolean request = isRequest(text);
            boolean response = isResponse(text);
            if (!request && !response) {
                continue;
            }
            String newFileName = fileName + (request ? "Request" : "Response");
            if (mulEntity && is[request ? 0 : 1]++ >= 0) {
                newFileName += is[request ? 0 : 1];
            }
            try {
                String module = String.join("/", modules);
                String sourcePath = path + (request ? "request/" : "response/") + module;
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.append("package ").append(sourcePath.replaceAll("src/main/java/", "").replaceAll("/", ".")).append(";\n\n");
                if (containsPathParams) {
                    stringBuilder.append("import com.fasterxml.jackson.annotation.JsonIgnore;\n");
                }
                stringBuilder.append("import com.fasterxml.jackson.annotation.JsonIgnoreProperties;\n" +
                        "import com.fasterxml.jackson.annotation.JsonProperty;\n" +
                        "import lombok.Data;\n" +
                        "import lombok.EqualsAndHashCode;\n");
                if (response) {
                    stringBuilder.append("import top.gabin.tools.response.AbstractResponse;\n");
                }
                List<DTO> tempList = list;
                outer:
                while (!tempList.isEmpty()) {
                    List<DTO> temp = new ArrayList<>();
                    for (DTO dto : tempList) {
                        if (dto.getType().equals("array")) {
                            stringBuilder.append("import java.util.List;\n\n");
                            break outer;
                        }
                        List<DTO> childList = dto.getChildList();
                        if (!childList.isEmpty()) {
                            temp.addAll(childList);
                        }
                    }
                    tempList = temp;
                }
                stringBuilder.append("\n");
                String classFunc = table.parent().parent().parent().select(".overview p").eq(1).text();
                stringBuilder.append("/**\n" + " * <pre>\n" + " * ").append(classFunc).append("\n");
                stringBuilder.append(String.format(" * 文档地址:%s\n", url));
                if (response) {
                    tables.stream().filter(element -> element.select("tbody tr").eq(0).select("td").size() == 4).findFirst().ifPresent(codeTable -> {
                        stringBuilder.append(String.format(" * %s\t%s\t%s\t%s\n", "状态码", "错误码", "描述", "解决方案"));
                        codeTable.select("tbody tr").forEach(tr -> {
                            Elements tds = tr.select("td");
                            stringBuilder.append(String.format(" * %s\t%s\t%s\t%s\n",
                                    getText(tds, 0),
                                    getText(tds, 1),
                                    getText(tds, 2),
                                    getText(tds, 3)
                            ));
                        });
                    });
                }
                stringBuilder.append(" * </pre>\n */\n");
                String ignoreFields = getIgnoreFields(list);
                stringBuilder.append("@Data\n" + "@EqualsAndHashCode").append(getCallSuper(list) ? "(callSuper = true)" : "").append("\n").append("@JsonIgnoreProperties(").append(ignoreFields).append(")\n").append("public class ").append(newFileName).append(response ? " extends AbstractResponse" : "").append(" {");
                stringBuilder.append("\n");
                for (DTO dto : list) {
                    if (dto == null) {
                        continue;
                    }
                    String content = "\t/**\n\t * <pre>\n\t * 字段名:%s\n\t * 变量名:%s\n\t * 是否必填:%s\n\t * 类型:%s\n\t * 描述:%s \n\t * </pre>\n\t */\n";
                    String field = dto.getField();
                    content = String.format(content, dto.getName(), field, dto.getRequired(), dto.getType(), dto.getDesc());
                    stringBuilder.append(content);
                    if (isPathParams(dto)) {
                        stringBuilder.append("\t@JsonIgnore\n");
                    }
                    stringBuilder.append(String.format("\t@JsonProperty(value = \"%s\")\n", field));
                    stringBuilder.append("\tprivate ").append(getType(dto)).append(" ").append(getField(field)).append(";\n\n");
                }
                List<DTO> objectDTOList = new ArrayList<>();
                for (DTO dto : list) {
                    if (dto == null) {
                        continue;
                    }
                    List<DTO> childList = dto.getChildList();
                    if (!childList.isEmpty()) {
                        objectDTOList.add(dto);
                    }
                }
                while (!objectDTOList.isEmpty()) {
                    objectDTOList = buildObject(stringBuilder, objectDTOList);
                }
                stringBuilder.append("}");
                Path file = Paths.get(sourcePath);
                if (!Files.exists(file)) {
                    Files.createDirectory(file);
                }
                Files.write(file.resolve(newFileName + ".java"), stringBuilder.toString().getBytes());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    private String getRedirect(Document document) {
        Optional<Element> script = document.select("script").stream()
                .filter(o -> o.html().startsWith("window.location.href=")).findFirst();
        if (script.isPresent()) {
            String url = script.get().html().replaceAll("window.location.href=", "").replaceAll("\"", "");
            String baseUri = document.baseUri();
            String uri = baseUri.substring(0, baseUri.indexOf("/", baseUri.indexOf("//") + 2));
            return uri + url;
        }
        return null;
    }
    private boolean getCallSuper(List<DTO> list) {
        return list.stream().allMatch(dto -> dto.getType().equalsIgnoreCase("string"));
    }
    private String getIgnoreFields(List<DTO> list) {
        Stream<String> stringStream = list.stream()
                .filter(this::isPathParams)
                .map(dto -> "\"" + getField(dto.getField()) + "\"");
        String collect = stringStream.collect(Collectors.joining(", "));
        if (collect.split(",").length > 1) {
            return "{" + collect +  "}";
        }
        return collect;
    }
    private boolean containsPathParams(List<DTO> list) {
        return list.stream().anyMatch(this::isPathParams);
    }
    private boolean isPathParams(DTO dto) {
        return dto.getDesc().contains("path");
    }
    private boolean isResponse(String text) {
        switch (text) {
            case "返回参数":
            case "通知应答":
                return true;
            default:
                return false;
        }
    }
    private boolean isRequest(String text) {
        switch (text) {
            case "请求参数":
            case "通知参数":
            case "支付成功通知参数":
                return true;
            default:
                return false;
        }
    }
    private List<DTO> buildObject(StringBuilder stringBuilder, List<DTO> objectDTOList) {
        List<DTO> childDTOList = new ArrayList<>();
        for (DTO parentDTO : objectDTOList) {
            String uppercaseField = getTopUppercaseField(parentDTO.getField());
            List<DTO> childList = parentDTO.getChildList();
            String ignoreFields = getIgnoreFields(childList);
            stringBuilder.append("\t@EqualsAndHashCode").append(getCallSuper(childList) ? "(callSuper = true)" : "").append("\n\t@Data\n\t@JsonIgnoreProperties(").append(ignoreFields).append(")\n\tpublic static class ").append(uppercaseField).append(" {\n");
            for (DTO dto : childList) {
                String content = "\t\t/**\n\t\t * <pre>\n\t\t * 字段名:%s\n\t\t * 变量名:%s\n\t\t * 是否必填:%s\n\t\t * 类型:%s\n\t\t * 描述:%s \n\t\t * </pre>\n\t\t */\n";
                String field = dto.getField();
                content = String.format(content, dto.getName(), field, dto.getRequired(), dto.getType(), dto.getDesc());
                stringBuilder.append(content);
                if (isPathParams(dto)) {
                    stringBuilder.append("\t\t@JsonIgnore\n");
                }
                stringBuilder.append(String.format("\t\t@JsonProperty(value = \"%s\")\n", field));
                stringBuilder.append("\t\tprivate ").append(getType(dto)).append(" ").append(getField(field)).append(";\n\n");
            }
            for (DTO dto : childList) {
                List<DTO> childList1 = dto.getChildList();
                if (!childList1.isEmpty()) {
                    childDTOList.add(dto);
                }
            }
            stringBuilder.append("\t}\n\n");
        }
        return childDTOList;
    }
    private List<DTO> getDtos(Element table) {
        Elements trs = table.select("tbody tr").eq(0).first().parent().children();
        if (trs.size() == 1 && trs.eq(0).select("td").size() != 5) {
            return Collections.emptyList();
        }
        return trs.stream().map(tr -> {
            Elements tds = tr.select("td");
            if (tds.eq(0).hasClass("object-sub")) {
                return null;
            }
            Elements descElement = tds.eq(4);
            String html = descElement.html();
            descElement.html(html.replaceAll("<br>", "@换行@"));
            DTO dto = new DTO(tr.hasClass("object"), getText(tds, 0), getText(tds, 1), getText(tds, 2), getText(tds, 3), getText(tds, 4));
            List<DTO> childList = getChildDtos(tr);
            dto.getChildList().addAll(childList);
            return dto;
        }).filter(Objects::nonNull).collect(Collectors.toList());
    }
    private List<DTO> getChildDtos(Element sourceTr) {
        if (!sourceTr.hasClass("object")) {
            return Collections.emptyList();
        }
        Element object = sourceTr.nextElementSibling();
        Elements objectTrs = object.select("table tbody tr").eq(0).first().parent().children();
        if (objectTrs.size() == 1 && objectTrs.eq(0).select("td").size() != 5) {
            return Collections.emptyList();
        }
        return objectTrs.stream().map(tr -> {
            Elements tds = tr.select("td");
            if (tds.eq(0).hasClass("object-sub")) {
                return null;
            }
            Elements objectTds = tr.select("td");
            Elements objDescElement = objectTds.eq(4);
            String objHtml = objDescElement.html();
            objDescElement.html(objHtml.replaceAll("<br>", "@换行@"));
            DTO dto = new DTO(tr.hasClass("object"), getText(objectTds, 0), getText(objectTds, 1), getText(objectTds, 2), getText(objectTds, 3), get2Text(objectTds));
            if (dto.getField().isEmpty()) {
                return null;
            }
            List<DTO> childDtos = getChildDtos(tr);
            dto.getChildList().addAll(childDtos);
            return dto;
        }).filter(Objects::nonNull).collect(Collectors.toList());
    }
    private String getType(DTO dto) {
        String type = dto.getType();
        type = type.toLowerCase();
        switch (type) {
            case "object":
                return getTopUppercaseField(dto.getField());
            case "array":
                return String.format("List<%s>", dto.isObject ? getTopUppercaseField(dto.getField()) : "String");
            case "bool":
            case "boolean":
                return "Boolean";
            default:
                if (type.startsWith("string")) {
                    return "String";
                }
                if (type.startsWith("int")) {
                    return "Integer";
                }
                return "String";
        }
    }
    private String getField(String field) {
        if (field.contains("_")) {
            String[] arr = field.split("_");
            StringBuilder sb = new StringBuilder(arr[0]);
            for (int i = 1; i < arr.length; i++) {
                String str = arr[i];
                sb.append(str.substring(0, 1).toUpperCase()).append(str.substring(1));
            }
            return sb.toString();
        }
        return field;
    }
    private String getTopUppercaseField(String field) {
        if (field.contains("_")) {
            String[] arr = field.split("_");
            StringBuilder sb = new StringBuilder();
            for (String str : arr) sb.append(str.substring(0, 1).toUpperCase()).append(str.substring(1));
            return sb.toString();
        }
        return field.substring(0, 1).toUpperCase() + field.substring(1);
    }
    private String getText(Elements tds, int i) {
        String regex = "@换行@";
        String text = tds.eq(i).text();
        if (text.startsWith("query")) {
            text = text.substring(5);
        }
        if (text.contains(regex)) {
            return "\n\t *  " + text.replaceAll(regex, "\n\t * ");
        } else {
            return text;
        }
    }
    private String get2Text(Elements tds) {
        String regex = "@换行@";
        String text = tds.eq(4).text();
        if (text.startsWith("query")) {
            text = text.substring(5);
        }
        if (text.contains(regex)) {
            return "\n\t\t *  " + text.replaceAll(regex, "\n\t\t * ");
        } else {
            return text;
        }
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/utils/DateFormatUtils.java
New file
@@ -0,0 +1,23 @@
package com.ruoyi.order.tools.utils;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class DateFormatUtils {
    // 使用线程变量,避免出现并发问题,SimpleDateFormat非线程安全
    private static final ThreadLocal<SimpleDateFormat> simpleDateFormatThreadLocal =
            ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX", Locale.US));
    /**
     * 格式化日期为RFC3339格式,某些接口需要用
     * @param date 需要格式化的日期
     * @return 格式化后的字符串
     */
    public static String formatRFC3339ToString(Date date) {
        SimpleDateFormat simpleDateFormat = simpleDateFormatThreadLocal.get();
        return simpleDateFormat.format(date);
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/utils/HttpUtils.java
New file
@@ -0,0 +1,156 @@
package com.ruoyi.order.tools.utils;
import com.ruoyi.order.tools.auth.AutoUpdateInCloudCertificatesVerifier;
import com.ruoyi.order.tools.auth.CacheService;
import com.ruoyi.order.tools.config.ProfitsSharingConfig;
import com.ruoyi.order.tools.response.AbstractResponse;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
public class HttpUtils {
    private final ProfitsSharingConfig config;
    private CloseableHttpClient httpClient;
    private CloseableHttpClient httpClientNotVerify;
    private volatile AutoUpdateInCloudCertificatesVerifier verifier;
    public HttpUtils(ProfitsSharingConfig config, CacheService cacheService) {
        this.config = config;
        init(cacheService);
    }
    public AutoUpdateInCloudCertificatesVerifier getVerifier() {
        return verifier;
    }
    private void init(CacheService cacheService) {
        String mchId = config.getMchId();
        String apiKey = config.getApiKey();
        String mchSerialNo = config.getMchSerialNo();
        PrivateKey privateKey = config.getPrivateKey();
        // 不需要传入微信支付证书,将会自动更新
        verifier = new AutoUpdateInCloudCertificatesVerifier(
                new WechatPay2Credentials(mchId, new PrivateKeySigner(mchSerialNo, privateKey)),
                apiKey.getBytes(StandardCharsets.UTF_8), cacheService);
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(mchId, mchSerialNo, privateKey)
                .withValidator(new WechatPay2Validator(verifier));
        httpClient = builder.build();
        builder = WechatPayHttpClientBuilder.create()
                .withMerchant(mchId, mchSerialNo, privateKey)
                .withValidator(response -> true);
        httpClientNotVerify = builder.build();
    }
    public List<X509Certificate> getLastCertificateList() {
        List<X509Certificate> certificateList = verifier.getLastCertificateList().stream().filter(certificate -> {
            try {
                certificate.checkValidity();
                return true;
            } catch (CertificateExpiredException | CertificateNotYetValidException e) {
                e.printStackTrace();
                return false;
            }
        }).collect(Collectors.toList());
        log.info("可用证书数量:" + certificateList.size());
        return certificateList;
    }
    private <T extends AbstractResponse> T request(Class<T> responseClass, HttpUriRequest request) {
        request.addHeader("Content-Type", "application/json");
        request.addHeader("Accept", "application/json");
        try {
            HttpResponse response = httpClient.execute(request);
            int statusCode = response.getStatusLine().getStatusCode();
            HttpEntity entity = response.getEntity();
            String responseText = entity == null ? "{}" : EntityUtils.toString(entity, "utf-8");
            EntityUtils.consume(entity);
            log.info(responseText);
            T responseInstance = JsonUtils.json2Bean(responseClass, responseText);
            responseInstance.setHttpStatusCode(statusCode);
            return responseInstance;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    public <T extends AbstractResponse> T get(Class<T> responseClass, String url) {
        return request(responseClass, new HttpGet(url));
    }
    public <T extends AbstractResponse> T post(Class<T> responseClass, Object requestObj, String url) {
        HttpPost httpPost = getHttpPost(requestObj, url);
        return request(responseClass, httpPost);
    }
    public <T extends AbstractResponse> T post(Class<T> responseClass, Object requestObj, String url, X509Certificate certificate) {
        HttpPost httpPost = getHttpPost(requestObj, url);
        httpPost.addHeader("Wechatpay-Serial", certificate.getSerialNumber().toString(16).toUpperCase());
        return request(responseClass, httpPost);
    }
    private HttpPost getHttpPost(Object requestObj, String url) {
        HttpPost httpPost = new HttpPost(url);
        String jsonData = "";
        //增加一个判断是否有Declared方法,要不JsonUtils.bean2Json(requestBody)会报异常
        int methodsNum = requestObj.getClass().getDeclaredMethods().length;
        if (requestObj instanceof String) {
            jsonData = requestObj.toString();
        } else if (methodsNum > 0) {
            jsonData = JsonUtils.bean2Json(requestObj);
        }
        if (jsonData != null && !jsonData.equals("{}")) {
            log.info(jsonData);
            StringEntity reqEntity = new StringEntity(
                    jsonData, ContentType.create("application/json", "utf-8"));
            httpPost.setEntity(reqEntity);
        }
        return httpPost;
    }
    public InputStream download(String downloadUrl) {
        HttpGet httpGet = new HttpGet(downloadUrl);
        httpGet.addHeader("Accept", "application/json");
        try (CloseableHttpResponse response = httpClientNotVerify.execute(httpGet)) {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) {
                return response.getEntity().getContent();
            } else {
                String body = EntityUtils.toString(response.getEntity());
                log.info(body);
                throw new IOException("request failed");
            }
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }
}
ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/tools/utils/JsonUtils.java
New file
@@ -0,0 +1,123 @@
package com.ruoyi.order.tools.utils;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
/**
 * json工具类简单封装
 *
 * @author GaBin  on  15/8/29
 */
public class JsonUtils {
    /**
     * <pre>
     *     将对象转换成json字符串
     * </pre>
     *
     * @param object 实例对象
     * @return String
     */
    public static String bean2Json(Object object) {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        try {
            return objectMapper.writeValueAsString(object);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }
    /**
     * <pre>
     *     将json字符串转化成对象
     * </pre>
     *
     * @param clazz 转化成的对象类型
     * @param json  需要转化的json字符串
     * @param <T>   泛型
     * @return T
     */
    public static <T> T json2Bean(Class<T> clazz, String json) {
        if (json == null) {
            return null;
        }
        if (json.contains("<html>")) {
            return null;
        }
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
        try {
            return objectMapper.readValue(json, clazz);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * <pre>
     *     将json字符串转化成List对象
     * </pre>
     *
     * @param clazz Class类型
     * @param json  json字符串
     * @param <T>   泛型
     * @return List
     */
    public static <T> List<T> json2List(Class<T> clazz, String json) {
        if (json == null || json.contains("<html>")) {
            return null;
        }
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            JavaType javaType = getCollectionType(objectMapper, ArrayList.class, clazz);
            return objectMapper.readValue(json, javaType);
        } catch (Exception ignored) {
        }
        return null;
    }
    /**
     * @param clazz Class类型
     * @param json  json字符串
     * @param <T>   泛型
     * @return T
     */
    public static <T> Map<String, T> json2Map(Class<T> clazz, String json) {
        if (json == null || json.contains("<html>")) {
            return null;
        }
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            JavaType javaType = getCollectionType(objectMapper, clazz);
            return objectMapper.readValue(json, javaType);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    public static JavaType getCollectionType(ObjectMapper objectMapper, Class<?> collectionClass, Class<?>... elementClasses) {
        TypeFactory typeFactory = objectMapper.getTypeFactory();
        return typeFactory.constructParametricType(collectionClass, elementClasses);
    }
    public static JavaType getCollectionType(ObjectMapper objectMapper, Class<?> elementClasse) {
        TypeFactory typeFactory = objectMapper.getTypeFactory();
        return typeFactory.constructMapType(TreeMap.class, String.class, elementClasse);
    }
}