|
@@ -0,0 +1,236 @@
|
|
|
|
+package com.fs.wx.dto;
|
|
|
|
+
|
|
|
|
+import cn.hutool.core.annotation.Alias;
|
|
|
|
+import cn.hutool.json.JSONObject;
|
|
|
|
+import cn.hutool.json.JSONUtil;
|
|
|
|
+import lombok.Data;
|
|
|
|
+
|
|
|
|
+import java.math.BigDecimal;
|
|
|
|
+
|
|
|
|
+@Data
|
|
|
|
+public class OrderQueryResponse {
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 100:成功,101:失败 (Required)
|
|
|
|
+ */
|
|
|
|
+ private Integer status;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 消息描述 (Required)
|
|
|
|
+ */
|
|
|
|
+ private String message;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 上游订单号 (Required)
|
|
|
|
+ */
|
|
|
|
+ private String channelOrderId;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 通莞订单号 (Required)
|
|
|
|
+ */
|
|
|
|
+ private String upOrderId;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 默认传null (Required) - Although API doc says required, it seems informational.
|
|
|
|
+ */
|
|
|
|
+ private String payoffType;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 支付时间 (Required)
|
|
|
|
+ */
|
|
|
|
+ private String payTime;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * WX: openid; Alipay: account name (Required)
|
|
|
|
+ * Mapped from both "openId" and "openid" in JSON
|
|
|
|
+ */
|
|
|
|
+ @Alias("openid") // Instruct Hutool to map "openid" to this field as well
|
|
|
|
+ private String openId;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 签名 (Required) - For response validation
|
|
|
|
+ */
|
|
|
|
+ private String sign;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 结算渠道编号 (Required)
|
|
|
|
+ */
|
|
|
|
+ private String settlementChannel;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 下游订单号 (Required)
|
|
|
|
+ */
|
|
|
|
+ private String lowOrderId;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 支付金额,单位元 (Required)
|
|
|
|
+ */
|
|
|
|
+ private String payMoney; // Keep as String as per API doc, can be converted later
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 支付方式 0:WX, 1:ZFB, 2:UnionPay QR, 6:LongPay, 8:BestPay, H:Digital Currency (Required)
|
|
|
|
+ */
|
|
|
|
+ private String payType;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 0:Success, 1:Fail, 2:Revoked, 4:Pending, 5:Refunded, 6:Partial Refund (Required)
|
|
|
|
+ */
|
|
|
|
+ private String state;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 订单备注 (Optional)
|
|
|
|
+ */
|
|
|
|
+ private String attach;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 聚合账户 (Required)
|
|
|
|
+ */
|
|
|
|
+ private String account;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 支付方式例:WX、ZFB、YZF、LZF、YLZF (Required)
|
|
|
|
+ */
|
|
|
|
+ private String channelId;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 渠道优惠金额 JSON String, e.g., {"discountAmt":"100"} (Unit: Fen) (Optional)
|
|
|
|
+ */
|
|
|
|
+ private String discountInfo;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 扩展信息 JSON String (Optional, if requested)
|
|
|
|
+ * Need to be parsed into an object if needed.
|
|
|
|
+ */
|
|
|
|
+ private String extendInfo; // Raw JSON string
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 易宝/SAAS分账详情 JSON Object (Optional, if requested)
|
|
|
|
+ */
|
|
|
|
+ private JSONObject extend; // Parsed JSON Object
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * SAAS分账订单详情 JSON Object (Optional, if requested)
|
|
|
|
+ */
|
|
|
|
+ private JSONObject upInfo; // Parsed JSON Object
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 渠道商户订单号 (Optional, if requested)
|
|
|
|
+ */
|
|
|
|
+ private String channelMchOrderId;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 订单管控状态 FROZEN/UN_FROZEN (Optional, if requested via isNeedUpInfo=1)
|
|
|
|
+ */
|
|
|
|
+ private String fundControlCsStatus;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 管控订单解冻时间 yyyy-mm-dd hh:mm:ss (Optional, if requested via isNeedUpInfo=1 and status is UN_FROZEN)
|
|
|
|
+ */
|
|
|
|
+ private String csUnFrozenCompleteDate;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 因公付金额信息 JSON String, e.g., {"invoiceAmount":"0.01","isUseEnterprisePay":false} (Optional, if requested)
|
|
|
|
+ */
|
|
|
|
+ private String enterprisePayInfo; // Raw JSON String
|
|
|
|
+
|
|
|
|
+ // --- Helper methods to access parsed nested JSON data ---
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Gets parsed DiscountInfo object from discountInfo string.
|
|
|
|
+ * @return DiscountInfo object or null if parsing fails or discountInfo is null/empty.
|
|
|
|
+ */
|
|
|
|
+ public DiscountInfo getParsedDiscountInfo() {
|
|
|
|
+ if (JSONUtil.isJson(this.discountInfo)) {
|
|
|
|
+ try {
|
|
|
|
+ return JSONUtil.toBean(this.discountInfo, DiscountInfo.class);
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ // Log parsing error if needed
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Gets parsed EnterprisePayInfo object from enterprisePayInfo string.
|
|
|
|
+ * @return EnterprisePayInfo object or null if parsing fails or enterprisePayInfo is null/empty.
|
|
|
|
+ */
|
|
|
|
+ public EnterprisePayInfo getParsedEnterprisePayInfo() {
|
|
|
|
+ if (JSONUtil.isJson(this.enterprisePayInfo)) {
|
|
|
|
+ try {
|
|
|
|
+ return JSONUtil.toBean(this.enterprisePayInfo, EnterprisePayInfo.class);
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ // Log parsing error if needed
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Gets parsed ExtendInfo object from extendInfo string.
|
|
|
|
+ * @return JSONObject or null if parsing fails or extendInfo is null/empty.
|
|
|
|
+ */
|
|
|
|
+ public JSONObject getParsedExtendInfo() {
|
|
|
|
+ if (JSONUtil.isJson(this.extendInfo)) {
|
|
|
|
+ try {
|
|
|
|
+ return JSONUtil.parseObj(this.extendInfo);
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ // Log parsing error if needed
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // --- Nested DTOs for parsed JSON strings ---
|
|
|
|
+
|
|
|
|
+ @Data
|
|
|
|
+ public static class DiscountInfo {
|
|
|
|
+ /**
|
|
|
|
+ * Discount amount in Fen (分)
|
|
|
|
+ */
|
|
|
|
+ private String discountAmt; // Keep as String as per API, or use Integer/Long
|
|
|
|
+
|
|
|
|
+ public BigDecimal getDiscountAmtYuan() {
|
|
|
|
+ if (discountAmt != null) {
|
|
|
|
+ try {
|
|
|
|
+ // Assuming discountAmt is in Fen (cents)
|
|
|
|
+ return new BigDecimal(discountAmt).divide(new BigDecimal("100"));
|
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
|
+ return null; // Or handle error appropriately
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Data
|
|
|
|
+ public static class EnterprisePayInfo {
|
|
|
|
+ private String invoiceAmount; // Amount in Yuan (元)
|
|
|
|
+ private Boolean isUseEnterprisePay;
|
|
|
|
+
|
|
|
|
+ public BigDecimal getInvoiceAmountValue() {
|
|
|
|
+ if (invoiceAmount != null) {
|
|
|
|
+ try {
|
|
|
|
+ return new BigDecimal(invoiceAmount);
|
|
|
|
+ } catch (NumberFormatException e) {
|
|
|
|
+ return null; // Or handle error appropriately
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return null;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Validates the response signature.
|
|
|
|
+ * IMPORTANT: Implement the actual signature validation logic based on Tongguan's specification.
|
|
|
|
+ * @param secretKey The secret key.
|
|
|
|
+ * @return true if the signature is valid, false otherwise.
|
|
|
|
+ */
|
|
|
|
+ public boolean isResponseSignValid(String secretKey) {
|
|
|
|
+
|
|
|
|
+ System.err.println("WARN: Response signature validation is not implemented!");
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+}
|