diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationQueryRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationQueryRequest.java new file mode 100644 index 0000000000..beaa3f2604 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationQueryRequest.java @@ -0,0 +1,125 @@ +package com.github.binarywang.wxpay.bean.customs; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * @author xifenzhu + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class DeclarationQueryRequest implements Serializable { + + private static final long serialVersionUID = -251403491989628142L; + /** + *
+   * 字段名:机构APPID
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:wxd678efh567hg6787
+   * 
+ */ + @SerializedName(value = "appid") + private String appid; + + /** + *
+   * 字段名:商户号
+   * 变量名:mchid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信支付分配的商户号
+   *  示例值:1230000109
+   * 
+ */ + @SerializedName(value = "mchid") + private String mchid; + + /** + *
+   * 字段名:订单类型
+   * 变量名:order_type
+   * 是否必填:是
+   * 类型:string(16)
+   * 描述:
+   *  4种订单号类型,选择一种
+   *  out_trade_no   商户订单号
+   *  transaction_id  微信支付订单号
+   *  sub_order_no  商户子订单号
+   *  sub_order_id  微信子订单号
+   *  示例值:out_trade_no
+   * 
+ */ + @SerializedName(value = "order_type") + private String orderType; + + /** + *
+   * 字段名:订单号
+   * 变量名:order_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  根据订单号类型,传入不同的订单号码
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "order_no") + private String orderNo; + + /** + *
+   * 字段名:海关
+   * 变量名:customs
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  海关代码, 枚举值参见参数规定-海关列表(https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter2_3.shtml#menu11)
+   *  示例值:SHANGHAI_ZS
+   * 
+ */ + @SerializedName(value = "customs") + private String customs; + + /** + *
+   * 字段名:偏移量
+   * 变量名:offset
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  非0整数,该次请求资源的起始位置,从0开始计数。调用方选填,默认为0
+   *  示例值:0
+   * 
+ */ + @SerializedName(value = "offset") + private String offset; + + /** + *
+   * 字段名:请求最大记录条数
+   * 变量名:limit
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  非0非负的整数,该次请求可返回的最大资源条数。调用方选填,默认值建议为20
+   *  示例值:20
+   * 
+ */ + @SerializedName(value = "limit") + private String limit; + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationQueryResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationQueryResult.java new file mode 100644 index 0000000000..e84370ca11 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationQueryResult.java @@ -0,0 +1,337 @@ +package com.github.binarywang.wxpay.bean.customs; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + +/** + * @author xifenzhu + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class DeclarationQueryResult implements Serializable { + + private static final long serialVersionUID = 7776809282150143165L; + /** + *
+   * 字段名:机构APPID
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:wxd678efh567hg6787
+   * 
+ */ + @SerializedName(value = "appid") + private String appid; + + /** + *
+   * 字段名:商户号
+   * 变量名:mchid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信支付分配的商户号
+   *  示例值:1230000109
+   * 
+ */ + @SerializedName(value = "mchid") + private String mchid; + + /** + *
+   * 字段名:微信支付返回的订单号
+   * 变量名:transaction_id
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:1000320306201511078440737890
+   * 
+ */ + @SerializedName(value = "transaction_id") + private String transactionId; + + /** + *
+   * 字段名:核验机构
+   * 变量名:verify_department
+   * 是否必填:是
+   * 类型:string(16)
+   * 描述:
+   *  核验机构代码
+   *  UNIONPAY:银联
+   *  NETSUNION:网联
+   *  OTHERS:其他
+   *  示例值:UNIONPAY
+   * 
+ */ + @SerializedName(value = "verify_department") + private String verifyDepartment; + + /** + *
+   * 字段名:核验机构交易流水号
+   * 变量名:Verify_department_trade_id
+   * 是否必填:是
+   * 类型:string(64)
+   * 描述:
+   *  交易流水号,来自验核机构,如银联记录的交易流水号,供商户报备海关
+   *  示例值:2018112288340107038204310100000
+   * 
+ */ + @SerializedName(value = "verify_department_trade_id") + private String verifyDepartmentTradeId; + + /** + *
+   * 字段名:偏移量
+   * 变量名:offset
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  非0整数,该次请求资源的起始位置,从0开始计数。调用方选填,默认为0
+   *  示例值:0
+   * 
+ */ + @SerializedName(value = "offset") + private Integer offset; + + /** + *
+   * 字段名:请求最大记录条数
+   * 变量名:limit
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  非0非负的整数,该次请求可返回的最大资源条数。调用方选填,默认值建议为20
+   *  示例值:20
+   * 
+ */ + @SerializedName(value = "limit") + private Integer limit; + + /** + *
+   * 字段名:查询结果总条数
+   * 变量名:total_count
+   * 是否必填:是
+   * 类型:int
+   * 描述:
+   *  查询结果总条数
+   *  示例值:1
+   * 
+ */ + @SerializedName(value = "total_count") + private Integer totalCount; + + /** + *
+   * 字段名:报关数据包
+   * 变量名:data
+   * 是否必填:是
+   * 类型:array
+   * 描述:
+   *  报关单结果数组,具体内容参见下方描述
+   *  示例值:
+   * 
+ */ + @SerializedName(value = "data") + private List data; + + /** + * 驳回原因详情 + */ + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + @Accessors(chain = true) + public static class DeclarationData { + /** + *
+     * 字段名:商户子订单号
+     * 变量名:sub_order_no
+     * 是否必填:否
+     * 类型:string(32)
+     * 描述:
+     *  微信子订单号,如有拆单则返回
+     *  示例值:20150806125346
+     * 
+ */ + @SerializedName(value = "sub_order_no") + private String subOrderNo; + + /** + *
+     * 字段名:微信子订单号
+     * 变量名:sub_order_id
+     * 是否必填:否
+     * 类型:string(32)
+     * 描述:
+     *  商户子订单号,如有拆单则必传
+     *  注意:仅适用于机构模式
+     *  示例值:20150806125346
+     * 
+ */ + @SerializedName(value = "sub_order_id") + private String subOrderId; + + /** + *
+     * 字段名:商户海关备案号
+     * 变量名:merchant_customs_no
+     * 是否必填:是
+     * 类型:string(32)
+     * 描述:
+     *  商户在海关登记的备案号
+     *  示例值:123456
+     * 
+ */ + @SerializedName(value = "mch_customs_no") + private String merchantCustomsNo; + + /** + *
+     * 字段名:海关
+     * 变量名:customs
+     * 是否必填:是
+     * 类型:string(32)
+     * 描述:
+     *  海关代码, 枚举值参见参数规定-海关列表(https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter2_3.shtml#menu11)
+     *  示例值:SHANGHAI_ZS
+     * 
+ */ + @SerializedName(value = "customs") + private String customs; + + /** + *
+     * 字段名:关税
+     * 变量名:duty
+     * 是否必填:否
+     * 类型:int
+     * 描述:
+     *  关税,以分为单位,非必填项,不会提交给海关
+     *  示例值:888
+     * 
+ */ + @SerializedName(value = "duty") + private Integer duty; + + /** + *
+     * 字段名:货币类型
+     * 变量名:fee_type
+     * 是否必填:否
+     * 类型:string(32)
+     * 描述:
+     *  微信支付订单支付时使用的币种,暂只支持人民币CNY,如有拆单则必传
+     *  示例值:CNY
+     * 
+ */ + @SerializedName(value = "fee_type") + private String feeType; + + /** + *
+     * 字段名:子订单金额
+     * 变量名:order_fee
+     * 是否必填:否
+     * 类型:int
+     * 描述:
+     *  子订单金额,以分为单位,不能超过原订单金额,order_fee=transport_fee+product_fee(应付金额=物流费+商品价格),如有拆单则必传
+     *  示例值:888
+     * 
+ */ + @SerializedName(value = "order_fee") + private Integer orderFee; + + /** + *
+     * 字段名:物流费用
+     * 变量名:transport_fee
+     * 是否必填:否
+     * 类型:int
+     * 描述:
+     *  物流费用,以分为单位,如有拆单则必传
+     *  示例值:888
+     * 
+ */ + @SerializedName(value = "transport_fee") + private Integer transportFee; + + /** + *
+     * 字段名:商品费用
+     * 变量名:product_fee
+     * 是否必填:否
+     * 类型:int
+     * 描述:
+     *  商品费用,以分为单位,如有拆单则必传
+     *  示例值:888
+     * 
+ */ + @SerializedName(value = "product_fee") + private Integer productFee; + + /** + *
+     * 字段名:报关状态
+     * 变量名:state
+     * 是否必填:是
+     * 类型:string(32)
+     * 描述:
+     *  申报结果状态码
+     *  PROCESSING:申报中
+     *  UNDECLARED:未申报
+     *  SUBMITTED:已修改未申报
+     *  SUCCESS:申报成功
+     *  FAIL:申报失败
+     *  EXCEPT:海关接口异常
+     *  示例值:PROCESSING
+     * 
+ */ + @SerializedName(value = "state") + private String state; + + /** + *
+     * 字段名:报关结果说明
+     * 变量名:explanation
+     * 是否必填:是
+     * 类型:string(128)
+     * 描述:
+     *  申报结果说明,如果状态是失败或异常,显示失败原因
+     *  示例值:支付单已存在并且为非退单状态
+     * 
+ */ + @SerializedName(value = "explanation") + private String explanation; + + /** + *
+     * 字段名:最后更新时间
+     * 变量名:modify_time
+     * 是否必填:是
+     * 类型:string(32)
+     * 描述:
+     *  最后更新时间,该时间取自微信服务器
+     *  示例值:2015-09-01T10:00:00+08:00
+     * 
+ */ + @SerializedName(value = "modify_time") + private String modifyTime; + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationRequest.java new file mode 100644 index 0000000000..89b1b79654 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationRequest.java @@ -0,0 +1,191 @@ +package com.github.binarywang.wxpay.bean.customs; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * @author xifenzhu + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class DeclarationRequest implements Serializable { + + private static final long serialVersionUID = -170115210896346836L; + /** + *
+   * 字段名:机构APPID
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:wxd678efh567hg6787
+   * 
+ */ + @SerializedName(value = "appid") + private String appid; + + /** + *
+   * 字段名:商户号
+   * 变量名:mchid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信支付分配的商户号
+   *  示例值:1230000109
+   * 
+ */ + @SerializedName(value = "mchid") + private String mchid; + + /** + *
+   * 字段名:商户订单号
+   * 变量名:out_trade_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "out_trade_no") + private String outTradeNo; + + /** + *
+   * 字段名:微信支付返回的订单号
+   * 变量名:transaction_id
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:1000320306201511078440737890
+   * 
+ */ + @SerializedName(value = "transaction_id") + private String transactionId; + + /** + *
+   * 字段名:海关
+   * 变量名:customs
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  海关代码, 枚举值参见参数规定-海关列表(https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter2_3.shtml#menu11)
+   *  示例值:SHANGHAI_ZS
+   * 
+ */ + @SerializedName(value = "customs") + private String customs; + + /** + *
+   * 字段名:商户海关备案号
+   * 变量名:merchant_customs_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户在海关登记的备案号
+   *  示例值:123456
+   * 
+ */ + @SerializedName(value = "merchant_customs_no") + private String merchantCustomsNo; + + /** + *
+   * 字段名:关税
+   * 变量名:duty
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  关税,以分为单位,非必填项,不会提交给海关
+   *  示例值:888
+   * 
+ */ + @SerializedName(value = "duty") + private String duty; + + /** + *
+   * 字段名:商户子订单号
+   * 变量名:sub_order_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户子订单号,如有拆单则必传
+   *  注意:仅适用于机构模式
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "sub_order_no") + private String subOrderNo; + + /** + *
+   * 字段名:货币类型
+   * 变量名:fee_type
+   * 是否必填:否
+   * 类型:string(32)
+   * 描述:
+   *  微信支付订单支付时使用的币种,暂只支持人民币CNY,如有拆单则必传
+   *  示例值:CNY
+   * 
+ */ + @SerializedName(value = "fee_type") + private String feeType; + + /** + *
+   * 字段名:子订单金额
+   * 变量名:order_fee
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  子订单金额,以分为单位,不能超过原订单金额,order_fee=transport_fee+product_fee(应付金额=物流费+商品价格),如有拆单则必传
+   *  示例值:888
+   * 
+ */ + @SerializedName(value = "order_fee") + private String orderFee; + + /** + *
+   * 字段名:物流费用
+   * 变量名:transport_fee
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  物流费用,以分为单位,如有拆单则必传
+   *  示例值:888
+   * 
+ */ + @SerializedName(value = "transport_fee") + private String transportFee; + + /** + *
+   * 字段名:商品费用
+   * 变量名:product_fee
+   * 是否必填:否
+   * 类型:int
+   * 描述:
+   *  商品费用,以分为单位,如有拆单则必传
+   *  示例值:888
+   * 
+ */ + @SerializedName(value = "product_fee") + private String productFee; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationResult.java new file mode 100644 index 0000000000..06f604f742 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/DeclarationResult.java @@ -0,0 +1,158 @@ +package com.github.binarywang.wxpay.bean.customs; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * @author xifengzhu + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class DeclarationResult implements Serializable { + + private static final long serialVersionUID = -5895139329545995308L; + /** + *
+   * 字段名:机构APPID
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:wxd678efh567hg6787
+   * 
+ */ + @SerializedName(value = "appid") + private String appid; + + /** + *
+   * 字段名:商户号
+   * 变量名:mchid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信支付分配的商户号
+   *  示例值:1230000109
+   * 
+ */ + @SerializedName(value = "mchid") + private String mchid; + + /** + *
+   * 字段名:商户订单号
+   * 变量名:out_trade_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一
+   *  示例值:wxd678efh567hg6787
+   * 
+ */ + @SerializedName(value = "20150806125346") + private String outTradeNo; + + /** + *
+   * 字段名:微信支付返回的订单号
+   * 变量名:transaction_id
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:1000320306201511078440737890
+   * 
+ */ + @SerializedName(value = "transaction_id") + private String transactionId; + + /** + *
+   * 字段名:报关状态
+   * 变量名:state
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  申报结果状态码
+   *  PROCESSING:申报中
+   *  UNDECLARED:未申报
+   *  SUBMITTED:已修改未申报
+   *  SUCCESS:申报成功
+   *  FAIL:申报失败
+   *  EXCEPT:海关接口异常
+   *  示例值:PROCESSING
+   * 
+ */ + @SerializedName(value = "state") + private String state; + + /** + *
+   * 字段名:商户子订单号
+   * 变量名:sub_order_no
+   * 是否必填:否
+   * 类型:string(32)
+   * 描述:
+   *  微信子订单号,如有拆单则返回
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "sub_order_no") + private String subOrderNo; + + /** + *
+   * 字段名:微信子订单号
+   * 变量名:sub_order_id
+   * 是否必填:否
+   * 类型:string(32)
+   * 描述:
+   *  商户子订单号,如有拆单则必传
+   *  注意:仅适用于机构模式
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "sub_order_id") + private String subOrderId; + + /** + *
+   * 字段名:核验机构
+   * 变量名:verify_department
+   * 是否必填:是
+   * 类型:string(16)
+   * 描述:
+   *  核验机构代码
+   *  UNIONPAY:银联
+   *  NETSUNION:网联
+   *  OTHERS:其他
+   *  示例值:UNIONPAY
+   * 
+ */ + @SerializedName(value = "verify_department") + private String verifyDepartment; + + /** + *
+   * 字段名:核验机构交易流水号
+   * 变量名:Verify_department_trade_id
+   * 是否必填:是
+   * 类型:string(64)
+   * 描述:
+   *  交易流水号,来自验核机构,如银联记录的交易流水号,供商户报备海关
+   *  示例值:2018112288340107038204310100000
+   * 
+ */ + @SerializedName(value = "verify_department_trade_id") + private String verifyDepartmentTradeId; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/RedeclareRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/RedeclareRequest.java new file mode 100644 index 0000000000..d3645d13da --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/RedeclareRequest.java @@ -0,0 +1,136 @@ +package com.github.binarywang.wxpay.bean.customs; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * @author xifengzhu + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class RedeclareRequest implements Serializable { + private static final long serialVersionUID = -5092107027805161479L; + + /** + *
+   * 字段名:机构APPID
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:wxd678efh567hg6787
+   * 
+ */ + @SerializedName(value = "appid") + private String appid; + + /** + *
+   * 字段名:商户号
+   * 变量名:mchid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信支付分配的商户号
+   *  示例值:1230000109
+   * 
+ */ + @SerializedName(value = "mchid") + private String mchid; + + /** + *
+   * 字段名:微信订单号
+   * 变量名:transaction_id
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  out_trade_no, transaction_id二选一传入
+   *  示例值:1000320306201511078440737890
+   * 
+ */ + @SerializedName(value = "transaction_id") + private String transactionId; + + /** + *
+   * 字段名:商户订单号
+   * 变量名:out_trade_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  out_trade_no, transaction_id二选一传入
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "out_trade_no") + private String outTradeNo; + + /** + *
+   * 字段名:商户子订单号
+   * 变量名:sub_order_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户子订单号,如有拆单则必传
+   *  注意:仅适用于机构模式
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "sub_order_no") + private String subOrderNo; + + /** + *
+   * 字段名:微信子订单号
+   * 变量名:sub_order_id
+   * 是否必填:否
+   * 类型:string(32)
+   * 描述:
+   *  商户子订单号,如有拆单则必传
+   *  注意:仅适用于机构模式
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "sub_order_id") + private String subOrderId; + + /** + *
+   * 字段名:海关
+   * 变量名:customs
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  海关代码, 枚举值参见参数规定-海关列表(https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter2_3.shtml#menu11)
+   *  示例值:SHANGHAI_ZS
+   * 
+ */ + @SerializedName(value = "customs") + private String customs; + + /** + *
+   * 字段名:商户海关备案号
+   * 变量名:merchant_customs_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户在海关登记的备案号
+   *  示例值:123456
+   * 
+ */ + @SerializedName(value = "merchant_customs_no") + private String merchantCustomsNo; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/RedeclareResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/RedeclareResult.java new file mode 100644 index 0000000000..25e09d7c07 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/RedeclareResult.java @@ -0,0 +1,156 @@ +package com.github.binarywang.wxpay.bean.customs; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * @author xifengzhu + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class RedeclareResult implements Serializable { + + private static final long serialVersionUID = 8863516626598050095L; + /** + *
+   * 字段名:机构APPID
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:wxd678efh567hg6787
+   * 
+ */ + @SerializedName(value = "appid") + private String appid; + + /** + *
+   * 字段名:商户号
+   * 变量名:mchid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信支付分配的商户号
+   *  示例值:1230000109
+   * 
+ */ + @SerializedName(value = "mchid") + private String mchid; + + /** + *
+   * 字段名:微信订单号
+   * 变量名:transaction_id
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信支付返回的订单号
+   *  示例值:1000320306201511078440737890
+   * 
+ */ + @SerializedName(value = "transaction_id") + private String transactionId; + + /** + *
+   * 字段名:商户订单号
+   * 变量名:out_trade_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "out_trade_no") + private String outTradeNo; + + /** + *
+   * 字段名:商户子订单号
+   * 变量名:sub_order_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户子订单号,如有拆单则必传
+   *  注意:仅适用于机构模式
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "sub_order_no") + private String subOrderNo; + + /** + *
+   * 字段名:微信子订单号
+   * 变量名:sub_order_id
+   * 是否必填:否
+   * 类型:string(32)
+   * 描述:
+   *  商户子订单号,如有拆单则必传
+   *  注意:仅适用于机构模式
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "sub_order_id") + private String subOrderId; + + /** + *
+   * 字段名:报关状态
+   * 变量名:state
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  申报结果状态码
+   *  PROCESSING:申报中
+   *  UNDECLARED:未申报
+   *  SUBMITTED:已修改未申报
+   *  SUCCESS:申报成功
+   *  FAIL:申报失败
+   *  EXCEPT:海关接口异常
+   *  示例值:PROCESSING
+   * 
+ */ + @SerializedName(value = "state") + private String state; + + /** + *
+   * 字段名:报关结果说明
+   * 变量名:explanation
+   * 是否必填:是
+   * 类型:string(128)
+   * 描述:
+   *  申报结果说明,如果状态是失败或异常,显示失败原因
+   *  示例值:支付单已存在并且为非退单状态
+   * 
+ */ + @SerializedName(value = "explanation") + private String explanation; + + /** + *
+   * 字段名:最后更新时间
+   * 变量名:modify_time
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  最后更新时间,该时间取自微信服务器
+   *  示例值:2015-09-01T10:00:00+08:00
+   * 
+ */ + @SerializedName(value = "modify_time") + private String modifyTime; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/VerifyCertificateRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/VerifyCertificateRequest.java new file mode 100644 index 0000000000..767a4ce8d8 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/VerifyCertificateRequest.java @@ -0,0 +1,156 @@ +package com.github.binarywang.wxpay.bean.customs; + +import com.github.binarywang.wxpay.v3.SpecEncrypt; +import com.google.gson.annotations.SerializedName; +import lombok.Data; + +import java.io.Serializable; + +/** + * @author xifengzhu + */ +@Data +public class VerifyCertificateRequest implements Serializable { + private static final long serialVersionUID = 721089103541592315L; + /** + *
+   * 字段名:机构APPID
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:wxd678efh567hg6787
+   * 
+ */ + @SerializedName(value = "appid") + private String appid; + + /** + *
+   * 字段名:商户号
+   * 变量名:mchid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信支付分配的商户号
+   *  示例值:1230000109
+   * 
+ */ + @SerializedName(value = "mchid") + private String mchid; + + /** + *
+   * 字段名:商户订单号
+   * 变量名:out_trade_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "out_trade_no") + private String outTradeNo; + + /** + *
+   * 字段名:微信支付返回的订单号
+   * 变量名:transaction_id
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:1000320306201511078440737890
+   * 
+ */ + @SerializedName(value = "transaction_id") + private String transactionId; + + /** + *
+   * 字段名:海关
+   * 变量名:customs
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  海关代码, 枚举值参见参数规定-海关列表(https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter2_3.shtml#menu11)
+   *  示例值:SHANGHAI_ZS
+   * 
+ */ + @SerializedName(value = "customs") + private String customs; + + /** + *
+   * 字段名:商户海关备案号
+   * 变量名:merchant_customs_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户在海关登记的备案号
+   *  示例值:123456
+   * 
+ */ + @SerializedName(value = "merchant_customs_no") + private String merchantCustomsNo; + + /** + *
+   * 字段名:商户子订单号
+   * 变量名:sub_order_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户子订单号,如有拆单则必传
+   *  注意:仅适用于机构模式
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "sub_order_no") + private String subOrderNo; + + /** + *
+   * 字段名:证件类型
+   * 变量名:certificate_type
+   * 是否必填:是
+   * 类型:string(16)
+   * 描述:
+   *  请传固定值IDCARD,暂只支持大陆身份证
+   *  示例值:IDCARD
+   * 
+ */ + @SerializedName(value = "certificate_type") + private String certificateType; + + /** + *
+   * 字段名:证件号
+   * 变量名:certificate_id
+   * 是否必填:是
+   * 类型:string
+   * 描述:
+   *  用户大陆身份证号,尾号为字母X的身份证号,请大写字母X。该字段需要进行加密
+   *  示例值:330821198809085211
+   * 
+ */ + @SerializedName(value = "certificate_id") + private String certificateId; + + /** + *
+   * 字段名:证件姓名
+   * 变量名:certificate_name
+   * 是否必填:是
+   * 类型:string
+   * 描述:
+   *  证件姓名,字段值需要进行加密
+   *  示例值:330821198809085211
+   * 
+ */ + @SerializedName(value = "certificate_name") + private String certificateName; + +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/VerifyCertificateResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/VerifyCertificateResult.java new file mode 100644 index 0000000000..d97049cb46 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/customs/VerifyCertificateResult.java @@ -0,0 +1,93 @@ +package com.github.binarywang.wxpay.bean.customs; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * @author xifengzhu + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Accessors(chain = true) +public class VerifyCertificateResult implements Serializable { + private static final long serialVersionUID = -8578640869555299753L; + /** + *
+   * 字段名:机构APPID
+   * 变量名:appid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:wxd678efh567hg6787
+   * 
+ */ + @SerializedName(value = "appid") + private String appid; + + /** + *
+   * 字段名:商户号
+   * 变量名:mchid
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信支付分配的商户号
+   *  示例值:1230000109
+   * 
+ */ + @SerializedName(value = "mchid") + private String mchid; + + /** + *
+   * 字段名:商户订单号
+   * 变量名:out_trade_no
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一
+   *  示例值:20150806125346
+   * 
+ */ + @SerializedName(value = "out_trade_no") + private String outTradeNo; + + /** + *
+   * 字段名:微信支付返回的订单号
+   * 变量名:transaction_id
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  微信分配的公众账号ID
+   *  示例值:1000320306201511078440737890
+   * 
+ */ + @SerializedName(value = "transaction_id") + private String transactionId; + + /** + *
+   * 字段名:身份核验结果
+   * 变量名:certificate_check_result
+   * 是否必填:是
+   * 类型:string(32)
+   * 描述:
+   *  订购人和支付人身份信息校验结果
+   *  SAME:身份信息校验匹配
+   *  DIFFERENT:身份信息校验不匹配
+   *  示例值:SAME
+   * 
+ */ + @SerializedName(value = "certificate_check_result") + private String certificateCheckResult; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/CustomDeclarationService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/CustomDeclarationService.java new file mode 100644 index 0000000000..f2980fed43 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/CustomDeclarationService.java @@ -0,0 +1,77 @@ +package com.github.binarywang.wxpay.service; + +import com.github.binarywang.wxpay.bean.customs.*; +import com.github.binarywang.wxpay.exception.WxPayException; + +/** + *
+ * 微信支付 支付报关 API.
+ * Created by xifengzhu on 2022/05/05.
+ * 
+ * + * @author xifengzhu + */ +public interface CustomDeclarationService { + + static String DECLARATION_BASE_URL = "https://apihk.mch.weixin.qq.com/global/v3/customs"; + + /** + *
+   * 报关API
+   * 文档地址: https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter3_1.shtml
+   * 
+ * + * @param request + * @return 返回数据 declaration result + * @throws WxPayException the wx pay exception + */ + DeclarationResult declare(DeclarationRequest request) throws WxPayException; + + /** + *
+   * 报关查询API
+   * 文档地址: https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter3_3.shtml
+   * 
+ * + * @param request + * @return 返回数据 declaration query result + * @throws WxPayException the wx pay exception + */ + DeclarationQueryResult query(DeclarationQueryRequest request) throws WxPayException; + + /** + *
+   * 身份信息校验API
+   * 文档地址: https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter3_2.shtml
+   * 
+ * + * @param request + * @return 返回数据 verify certification result + * @throws WxPayException the wx pay exception + */ + VerifyCertificateResult verifyCertificate(VerifyCertificateRequest request) throws WxPayException; + + /** + *
+   * 报关信息修改API
+   * 文档地址: https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter3_5.shtml
+   * 
+ * + * @param request + * @return 返回数据 declaration result + * @throws WxPayException the wx pay exception + */ + DeclarationResult modify(DeclarationRequest request) throws WxPayException; + + /** + *
+   * 报关重推API
+   * 文档地址: https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter3_4.shtml
+   * 
+ * + * @param request + * @return 返回数据 redeclaration result + * @throws WxPayException the wx pay exception + */ + RedeclareResult redeclare(RedeclareRequest request) throws WxPayException; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/CustomDeclarationServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/CustomDeclarationServiceImpl.java new file mode 100644 index 0000000000..d25ed7c0a2 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/CustomDeclarationServiceImpl.java @@ -0,0 +1,110 @@ +package com.github.binarywang.wxpay.service.impl; + +import com.github.binarywang.wxpay.bean.customs.*; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.service.CustomDeclarationService; +import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.v3.util.RsaCryptoUtil; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import lombok.RequiredArgsConstructor; +import me.chanjar.weixin.common.error.WxRuntimeException; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import java.nio.charset.StandardCharsets; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.util.Base64; + +/** + *
+ * 支付报关 实现.
+ * Created by xifengzhu on 2022/05/05.
+ * 
+ * + * @author xifengzhu + */ +@RequiredArgsConstructor +public class CustomDeclarationServiceImpl implements CustomDeclarationService { + private static final Gson GSON = new GsonBuilder().create(); + private final WxPayService payService; + + @Override + public DeclarationResult declare(DeclarationRequest request) throws WxPayException { + String response = this.payService.postV3(DECLARATION_BASE_URL.concat("/orders"), GSON.toJson(request)); + return GSON.fromJson(response, DeclarationResult.class); + } + + @Override + public DeclarationQueryResult query(DeclarationQueryRequest request) throws WxPayException { + String url = String.format("%s/orders?appid=%s&mchid=%s&order_type=%s&order_no=%s&customs=%s&offset=%s&limit=%s", + DECLARATION_BASE_URL, + request.getAppid(), + request.getMchid(), + request.getOrderType(), + request.getOrderNo(), + request.getCustoms(), + request.getOffset(), + request.getLimit() + ); + String result = this.payService.getV3(url); + return GSON.fromJson(result, DeclarationQueryResult.class); + } + + @Override + public VerifyCertificateResult verifyCertificate(VerifyCertificateRequest request) throws WxPayException { + this.encryptFields(request); + String response = this.payService.postV3WithWechatpaySerial(DECLARATION_BASE_URL.concat("/verify-certificate"), GSON.toJson(request)); + return GSON.fromJson(response, VerifyCertificateResult.class); + } + + @Override + public DeclarationResult modify(DeclarationRequest request) throws WxPayException { + String response = this.payService.patchV3(DECLARATION_BASE_URL.concat("/orders"), GSON.toJson(request)); + return GSON.fromJson(response, DeclarationResult.class); + } + + @Override + public RedeclareResult redeclare(RedeclareRequest request) throws WxPayException { + String response = this.payService.postV3(DECLARATION_BASE_URL.concat("/redeclare"), GSON.toJson(request)); + return GSON.fromJson(response, RedeclareResult.class); + } + + private void encryptFields(VerifyCertificateRequest request) throws WxPayException { + try { + request.setCertificateId(encryptOAEP(request.getCertificateId())); + request.setCertificateName(encryptOAEP(request.getCertificateName())); + } catch (Exception e) { + throw new WxPayException("敏感信息加密失败", e); + } + } + + private X509Certificate getValidCertificate() { + return this.payService.getConfig().getVerifier().getValidCertificate(); + } + + private String encryptOAEP(String message) + throws IllegalBlockSizeException { + X509Certificate certificate = getValidCertificate(); + try { + // 身份信息校验 RSA 加密,填充方案使用 `RSAES-PKCS1-v1_5` + // https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/declarecustom_ch/chapter3_2.shtml + Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + cipher.init(Cipher.ENCRYPT_MODE, certificate.getPublicKey()); + + byte[] data = message.getBytes(StandardCharsets.UTF_8); + byte[] ciphertext = cipher.doFinal(data); + return Base64.getEncoder().encodeToString(ciphertext); + } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { + throw new WxRuntimeException("当前Java环境不支持RSA v1.5/OAEP", e); + } catch (InvalidKeyException e) { + throw new IllegalArgumentException("无效的证书", e); + } catch (IllegalBlockSizeException | BadPaddingException e) { + throw new IllegalBlockSizeException("加密原串的长度不能超过214字节"); + } + } +} diff --git a/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/CustomDeclarationServiceImplTest.java b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/CustomDeclarationServiceImplTest.java new file mode 100644 index 0000000000..6a219ee2f3 --- /dev/null +++ b/weixin-java-pay/src/test/java/com/github/binarywang/wxpay/service/impl/CustomDeclarationServiceImplTest.java @@ -0,0 +1,74 @@ +package com.github.binarywang.wxpay.service.impl; + +import com.github.binarywang.wxpay.bean.customs.*; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.service.CustomDeclarationService; +import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.testbase.ApiTestModule; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.inject.Inject; +import lombok.extern.slf4j.Slf4j; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +@Slf4j +@Test +@Guice(modules = ApiTestModule.class) +public class CustomDeclarationServiceImplTest { + private static final Gson GSON = new GsonBuilder().create(); + @Inject + private WxPayService wxPayService; + + @Test + public void testDeclare() throws WxPayException { + CustomDeclarationService customDeclarationService = new CustomDeclarationServiceImpl(wxPayService); + String requestParamStr = "{\"appid\":\"wx4275b35dac8f1bde\",\"mchid\":\"1623887211\",\"out_trade_no\":\"schiff32205031811186126779176\",\"transaction_id\":\"4200001480202205035540107159\",\"customs\":\"NINGBO\",\"merchant_customs_no\":\"4401230148\"}"; + DeclarationRequest request = GSON.fromJson(requestParamStr, DeclarationRequest.class); + + DeclarationResult result = customDeclarationService.declare(request); + System.out.println("result = " + result); + } + + @Test + public void testQuery() throws WxPayException { + CustomDeclarationService customDeclarationService = new CustomDeclarationServiceImpl(wxPayService); + String requestParamStr = "{\"appid\":\"wx4275b35dac8f1bde\",\"mchid\":\"1623887211\",\"order_type\":\"transaction_id\",\"order_no\":\"4200001480202205035540107159\",\"customs\":\"NINGBO\",\"offset\":\"0\",\"limit\":\"20\"}"; + DeclarationQueryRequest request = GSON.fromJson(requestParamStr, DeclarationQueryRequest.class); + + DeclarationQueryResult result = customDeclarationService.query(request); + System.out.println("result = " + result); + } + + @Test + public void testVerifyCertificate() throws WxPayException { + CustomDeclarationService customDeclarationService = new CustomDeclarationServiceImpl(wxPayService); + String requestParamStr = "{\"appid\":\"wx4275b35dac8f1bde\",\"mchid\":\"1623887211\",\"out_trade_no\":\"schiff32205031811186126779176\",\"transaction_id\":\"4200001480202205035540107159\",\"customs\":\"NINGBO\",\"merchant_customs_no\":\"4401230148\",\"certificate_type\":\"IDCARD\",\"certificate_id\":\"430223199101264838\",\"certificate_name\":\"易株强\"}"; + VerifyCertificateRequest request = GSON.fromJson(requestParamStr, VerifyCertificateRequest.class); + + VerifyCertificateResult result = customDeclarationService.verifyCertificate(request); + System.out.println("result = " + result); + } + + @Test + public void testModify() throws WxPayException { + CustomDeclarationService customDeclarationService = new CustomDeclarationServiceImpl(wxPayService); + + String requestParamStr = "{\"appid\":\"wx4275b35dac8f1bde\",\"mchid\":\"1623887211\",\"out_trade_no\":\"schiff32205031811186126779176\",\"transaction_id\":\"4200001480202205035540107159\",\"customs\":\"NINGBO\",\"merchant_customs_no\":\"4401230148\"}"; + + DeclarationRequest request = GSON.fromJson(requestParamStr, DeclarationRequest.class); + + DeclarationResult result = customDeclarationService.modify(request); + System.out.println("result = " + result); + } + + @Test + public void testRedeclare() throws WxPayException { + CustomDeclarationService customDeclarationService = new CustomDeclarationServiceImpl(wxPayService); + String requestParamStr = "{\"appid\":\"wx4275b35dac8f1bde\",\"mchid\":\"1623887211\",\"out_trade_no\":\"schiff32205031811186126779176\",\"transaction_id\":\"4200001480202205035540107159\",\"customs\":\"NINGBO\",\"merchant_customs_no\":\"4401230148\"}"; + RedeclareRequest request = GSON.fromJson(requestParamStr, RedeclareRequest.class); + + RedeclareResult result = customDeclarationService.redeclare(request); + System.out.println("result = " + result); + } +}