diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayCodepayRequest.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayCodepayRequest.java new file mode 100644 index 0000000000..ecfa614a16 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayCodepayRequest.java @@ -0,0 +1,593 @@ +package com.github.binarywang.wxpay.bean.request; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + +/** + * V3付款码支付请求对象类 + * @author DaxPay + * @date 2024/7/29 + */ +@Data +@NoArgsConstructor +@Accessors(chain = true) +public class WxPayCodepayRequest implements Serializable { + + private static final long serialVersionUID = 1L; + /** + *
+ * 字段名:应用ID + * 变量名:appid + * 是否必填:是 + * 类型:string[1,32] + * 描述: + * 由微信生成的应用ID,全局唯一。请求统一下单接口时请注意APPID的应用属性,例如公众号场景下,需使用应用属性为公众号的APPID + * 示例值:wxd678efh567hg6787 + *+ */ + @SerializedName(value = "appid") + protected String appid; + /** + *
+ * 字段名:直连商户号 + * 变量名:mchid + * 是否必填:是 + * 类型:string[1,32] + * 描述: + * 直连商户的商户号,由微信支付生成并下发。 + * 示例值:1230000109 + *+ */ + @SerializedName(value = "mchid") + protected String mchid; + /** + *
+ * 字段名:商品描述 + * 变量名:description + * 是否必填:是 + * 类型:string[1,127] + * 描述: + * 商品描述 + * 示例值:Image形象店-深圳腾大-QQ公仔 + *+ */ + @SerializedName(value = "description") + protected String description; + /** + *
+ * 字段名:商户订单号 + * 变量名:out_trade_no + * 是否必填:是 + * 类型:string[6,32] + * 描述: + * 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一 + * 示例值:1217752501201407033233368018 + *+ */ + @SerializedName(value = "out_trade_no") + protected String outTradeNo; + + /** + *
+ * 字段名:微信支付返回的订单号 + * 变量名:transaction_id + * 是否必填:是 + * 类型:string(32) + * 描述: + * 微信分配的公众账号ID + * 示例值:1000320306201511078440737890 + *+ */ + @SerializedName(value = "transaction_id") + private String transactionId; + /** + *
+ * 字段名:附加数据 + * 变量名:attach + * 是否必填:否 + * 类型:string[1,128] + * 描述: + * 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用 + * 示例值:自定义数据 + *+ */ + @SerializedName(value = "attach") + protected String attach; + + /** + *
+ * 字段名:订单优惠标记 + * 变量名:goods_tag + * 是否必填:否 + * 类型:string[1,256] + * 描述: + * 订单优惠标记 + * 示例值:WXG + *+ */ + @SerializedName(value = "goods_tag") + private String goodsTag; + /** + *
+ * 字段名:电子发票入口开放标识 + * 变量名:support_fapiao + * 是否必填:否 + * 类型:boolean + * 描述:传入true时,支付成功消息和支付详情页将出现开票入口。需要在微信支付商户平台或微信公众平台开通电子发票功能,传此字段才可生效。 + *+ */ + @SerializedName(value = "support_fapiao") + private Boolean supportFapiao; + /** + *
+ * 字段名:支付者 + * 变量名:payer + * 是否必填:是 + * 类型:object + * 描述: + * 支付者信息 + *+ */ + @SerializedName(value = "payer") + private Payer payer; + /** + *
+ * 字段名:订单金额 + * 变量名:amount + * 是否必填:是 + * 类型:object + * 描述: + * 订单金额信息 + *+ */ + @SerializedName(value = "amount") + private Amount amount; + /** + *
+ * 字段名:场景信息 + * 变量名:scene_info + * 是否必填:否 + * 类型:object + * 描述: + * 支付场景描述 + *+ */ + @SerializedName(value = "scene_info") + private SceneInfo sceneInfo; + + /** + *
+ * 字段名:优惠功能 + * 变量名:promotion_detail + * 是否必填:否 + * 类型:array + * 描述: + * 优惠功能,享受优惠时返回该字段。 + *+ */ + @SerializedName(value = "promotion_detail") + private List
+ * 字段名:结算信息 + * 变量名:settle_info + * 是否必填:否 + * 类型:Object + * 描述:结算信息 + *+ */ + @SerializedName(value = "settle_info") + private SettleInfo settleInfo; + + + @Data + @NoArgsConstructor + public static class Amount implements Serializable { + private static final long serialVersionUID = 1L; + /** + *
+ * 字段名:总金额 + * 变量名:total + * 是否必填:否 + * 类型:int + * 描述: + * 订单总金额,单位为分。 + * 示例值:100 + *+ */ + @SerializedName(value = "total") + private Integer total; + /** + *
+ * 字段名:用户支付金额 + * 变量名:payer_total + * 是否必填:否 + * 类型:int + * 描述: + * 用户支付金额,单位为分。 + * 示例值:100 + *+ */ + @SerializedName(value = "payer_total") + private Integer payerTotal; + /** + *
+ * 字段名:货币类型 + * 变量名:currency + * 是否必填:否 + * 类型:string[1,16] + * 描述: + * CNY:人民币,境内商户号仅支持人民币。 + * 示例值:CNY + *+ */ + @SerializedName(value = "currency") + private String currency; + /** + *
+ * 字段名:用户支付币种 + * 变量名:payer_currency + * 是否必填:否 + * 类型:string[1,16] + * 描述: + * 用户支付币种 + * 示例值: CNY + *+ */ + @SerializedName(value = "payer_currency") + private String payerCurrency; + } + + @Data + @NoArgsConstructor + public static class Payer implements Serializable { + private static final long serialVersionUID = -1L; + /** + *
+ * 字段名:用户标识 + * 变量名:auth_code + * 是否必填:是 + * 类型:string[32] + * 描述: + * 付款码支付授权码,即用户打开微信钱包显示的码。 + * 示例值:130061098828009406 + *+ */ + @SerializedName(value = "auth_code") + private String authCode; + } + + @Data + @NoArgsConstructor + public static class SceneInfo implements Serializable { + private static final long serialVersionUID = 1L; + /** + *
+ * 字段名:商户端设备 IP + * 变量名:device_ip + * 是否必填:是 + * 类型:string[1,45] + * 描述: + * 用户的客户端IP,支持IPv4和IPv6两种格式的IP地址。 + * 示例值:14.23.150.211 + *+ */ + @SerializedName(value = "device_ip") + private String deviceIp; + /** + *
+ * 字段名:商户端设备号 + * 变量名:device_id + * 是否必填:否 + * 类型:string[1,32] + * 描述: + * 商户端设备号(门店号或收银设备ID)。 + * 示例值:013467007045764 + *+ */ + @SerializedName(value = "device_id") + private String deviceId; + /** + *
+ * 字段名:商户门店信息 + * 变量名:store_info + * 是否必填:否 + * 类型:object + * 描述: + * 商户门店信息 + *+ */ + @SerializedName(value = "store_info") + private StoreInfo storeInfo; + } + + /** + * 商户门店信息 + */ + @Data + @NoArgsConstructor + public static class StoreInfo implements Serializable { + private static final long serialVersionUID = -1L; + /** + *
+ * 字段名:门店编号 + * 变量名:id + * 是否必填:是 + * 类型:string[1,32] + * 描述: + * 此参数与商家自定义编码(out_id)二选一必填。 + * 微信支付线下场所ID,格式为纯数字。 + * 基于合规要求与风险管理目的,线下条码支付时需传入用户实际付款的场景信息。 + * 指引参见:https://kf.qq.com/faq/230817neeaem2308177ZFfqM.html。 + * 示例值:0001 + *+ */ + @SerializedName(value = "id") + private String id; + /** + *
+ * 字段名:商家自定义编码 + * 变量名:out_id + * 是否必填:否 + * 类型:string[1,256] + * 描述: + * 此参数与门店(id)二选一必填。 + * 商户系统的门店编码,支持大小写英文字母、数字,仅支持utf-8格式。 + * 基于合规要求与风险管理目的,线下条码支付时需传入用户实际付款的场景信息。 + * 示例值:A1111 + *+ */ + @SerializedName(value = "out_id") + private String outId; + } + + + @Data + @NoArgsConstructor + public static class SettleInfo implements Serializable { + private static final long serialVersionUID = 1L; + /** + *
+ * 字段名:是否指定分账 + * 变量名:profit_sharing + * 是否必填:否 + * 类型:boolean + * 描述: + * 是否指定分账 + * 示例值:false + *+ */ + @SerializedName(value = "profit_sharing") + private Boolean profitSharing; + } + + + /** + * 优惠功能 + */ + @Data + @NoArgsConstructor + public static class PromotionDetail implements Serializable { + /** + *
+ * 字段名:券ID + * 变量名:coupon_id + * 是否必填:是 + * 类型:string[1,32] + * 描述: + * 券ID + * 示例值:109519 + *+ */ + @SerializedName(value = "coupon_id") + private String couponId; + /** + *
+ * 字段名:优惠名称 + * 变量名:name + * 是否必填:否 + * 类型:string[1,64] + * 描述: + * 优惠名称 + * 示例值:单品惠-6 + *+ */ + @SerializedName(value = "name") + private String name; + /** + *
+ * 字段名:优惠范围 + * 变量名:scope + * 是否必填:否 + * 类型:string[1,32] + * 描述: + * GLOBAL:全场代金券 + * SINGLE:单品优惠 + * 示例值:GLOBAL + *+ */ + @SerializedName(value = "scope") + private String scope; + /** + *
+ * 字段名:优惠类型 + * 变量名:type + * 是否必填:否 + * 类型:string[1,32] + * 描述: + * CASH:充值 + * NOCASH:预充值 + * 示例值:CASH + *+ */ + @SerializedName(value = "type") + private String type; + /** + *
+ * 字段名:优惠券面额 + * 变量名:amount + * 是否必填:是 + * 类型:int + * 描述: + * 优惠券面额 + * 示例值:100 + *+ */ + @SerializedName(value = "amount") + private Integer amount; + /** + *
+ * 字段名:活动ID + * 变量名:stock_id + * 是否必填:否 + * 类型:string[1,32] + * 描述: + * 活动ID + * 示例值:931386 + *+ */ + @SerializedName(value = "stock_id") + private String stockId; + /** + *
+ * 字段名:微信出资 + * 变量名:wechatpay_contribute + * 是否必填:否 + * 类型:int + * 描述: + * 微信出资,单位为分 + * 示例值:0 + *+ */ + @SerializedName(value = "wechatpay_contribute") + private Integer wechatpayContribute; + /** + *
+ * 字段名:商户出资 + * 变量名:merchant_contribute + * 是否必填:否 + * 类型:int + * 描述: + * 商户出资,单位为分 + * 示例值:0 + *+ */ + @SerializedName(value = "merchant_contribute") + private Integer merchantContribute; + /** + *
+ * 字段名:其他出资 + * 变量名:other_contribute + * 是否必填:否 + * 类型:int + * 描述: + * 其他出资,单位为分 + * 示例值:0 + *+ */ + @SerializedName(value = "other_contribute") + private Integer otherContribute; + /** + *
+ * 字段名:优惠币种 + * 变量名:currency + * 是否必填:否 + * 类型:string[1,16] + * 描述: + * CNY:人民币,境内商户号仅支持人民币。 + * 示例值:CNY + *+ */ + @SerializedName(value = "currency") + private String currency; + /** + *
+ * 字段名:单品列表 + * 变量名:goods_detail + * 是否必填:否 + * 类型:array + * 描述: + * 单品列表信息 + *+ */ + @SerializedName(value = "goods_detail") + private List
+ * 字段名:商品编码 + * 变量名:goods_id + * 是否必填:是 + * 类型:string[1,32] + * 描述: + * 商品编码 + * 示例值:M1006 + *+ */ + @SerializedName(value = "goods_id") + private String goodsId; + /** + *
+ * 字段名:商品数量 + * 变量名:quantity + * 是否必填:是 + * 类型:int + * 描述: + * 用户购买的数量 + * 示例值:1 + *+ */ + @SerializedName(value = "quantity") + private Integer quantity; + /** + *
+ * 字段名:商品单价 + * 变量名:unit_price + * 是否必填:是 + * 类型:int + * 描述: + * 商品单价,单位为分 + * 示例值:100 + *+ */ + @SerializedName(value = "unit_price") + private Integer unitPrice; + /** + *
+ * 字段名:商品优惠金额 + * 变量名:discount_amount + * 是否必填:是 + * 类型:int + * 描述: + * 商品优惠金额 + * 示例值:0 + *+ */ + @SerializedName(value = "discount_amount") + private Integer discountAmount; + /** + *
+ * 字段名:商品备注 + * 变量名:goods_remark + * 是否必填:否 + * 类型:string[1,128] + * 描述: + * 商品备注信息 + * 示例值:商品备注信息 + *+ */ + @SerializedName(value = "goods_remark") + private String goodsRemark; + } +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderReverseV3Request.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderReverseV3Request.java new file mode 100644 index 0000000000..2505d6130e --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/request/WxPayOrderReverseV3Request.java @@ -0,0 +1,59 @@ +package com.github.binarywang.wxpay.bean.request; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * V3撤销订单请求对象类 + * @author DaxPay + * @date 2024/7/29 + */ +@Data +@NoArgsConstructor +@Accessors(chain = true) +public class WxPayOrderReverseV3Request implements Serializable { + private static final long serialVersionUID = 1L; + /** + *
+ * 字段名:应用ID + * 变量名:appid + * 是否必填:是 + * 类型:string[1,32] + * 描述: + * 由微信生成的应用ID,全局唯一。请求统一下单接口时请注意APPID的应用属性,例如公众号场景下,需使用应用属性为公众号的APPID + * 示例值:wxd678efh567hg6787 + *+ */ + @SerializedName(value = "appid") + protected String appid; + /** + *
+ * 字段名:直连商户号 + * 变量名:mchid + * 是否必填:是 + * 类型:string[1,32] + * 描述: + * 直连商户的商户号,由微信支付生成并下发。 + * 示例值:1230000109 + *+ */ + @SerializedName(value = "mchid") + protected String mchid; + + /** + *
+ * 字段名:商户订单号 + * 变量名:out_trade_no + * 是否必填:是 + * 类型:string[6,32] + * 描述: + * 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一 + * 示例值:1217752501201407033233368018 + *+ */ + private transient String outTradeNo; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayCodepayResult.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayCodepayResult.java new file mode 100644 index 0000000000..ad6a8be705 --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayCodepayResult.java @@ -0,0 +1,636 @@ +package com.github.binarywang.wxpay.bean.result; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + +/** + * 微信V3付款码返回结果 + * @author DaxPay + * @date 2024/7/29 + */ +@Data +@Accessors(chain = true) +public class WxPayCodepayResult implements Serializable { + private static final long serialVersionUID = 1L; + /** + *
+ * 字段名:应用ID + * 变量名:appid + * 是否必填:是 + * 类型:string[1,32] + * 描述: + * 由微信生成的应用ID,全局唯一。请求统一下单接口时请注意APPID的应用属性,例如公众号场景下,需使用应用属性为公众号的APPID + * 示例值:wxd678efh567hg6787 + *+ */ + @SerializedName(value = "appid") + protected String appid; + /** + *
+ * 字段名:直连商户号 + * 变量名:mchid + * 是否必填:是 + * 类型:string[1,32] + * 描述: + * 直连商户的商户号,由微信支付生成并下发。 + * 示例值:1230000109 + *+ */ + @SerializedName(value = "mchid") + protected String mchid; + /** + *
+ * 字段名:商户订单号 + * 变量名:out_trade_no + * 是否必填:是 + * 类型:string[6,32] + * 描述: + * 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一 + * 示例值:1217752501201407033233368018 + *+ */ + @SerializedName(value = "out_trade_no") + protected String outTradeNo; + + /** + *
+ * 字段名:微信支付返回的订单号 + * 变量名:transaction_id + * 是否必填:是 + * 类型:string(32) + * 描述: + * 微信分配的公众账号ID + * 示例值:1000320306201511078440737890 + *+ */ + @SerializedName(value = "transaction_id") + private String transactionId; + /** + *
+ * 字段名:交易类型 + * 变量名:trade_type + * 是否必填:是 + * 类型:string[1,16] + * 描述: + * 枚举值: + * NATIVE:扫码支付 + * JSAPI:公众号支付 + * APP:APP支付 + * MWEB:H5支付 + * 示例值: JSAPI + *+ */ + @SerializedName(value = "trade_type") + private String tradeType; + /** + *
+ * 字段名:付款银行 + * 变量名:bank_type + * 是否必填:否 + * 类型:string(16) + * 描述: + * 银行类型,采用字符串类型的银行标识。 + * 示例值:CMC + *+ */ + @SerializedName(value = "bank_type") + private String bankType; + /** + *
+ * 字段名:支付完成时间 + * 变量名:success_time + * 是否必填:否 + * 类型:string(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 + *+ */ + @SerializedName(value = "success_time") + private String successTime; + /** + *
+ * 字段名:交易状态 + * 变量名:trade_state + * 是否必填:是 + * 类型:string[1,32] + * 描述: + * 交易状态,枚举值: + * SUCCESS:支付成功 + * REFUND:转入退款 + * NOTPAY:未支付 + * REVOKED:已撤销(付款码支付) + * USERPAYING:用户支付中(付款码支付) + * PAYERROR:支付失败(其他原因,如银行返回失败) + * 示例值:SUCCESS + *+ */ + @SerializedName(value = "trade_state") + private String tradeState; + /** + *
+ * 字段名:交易状态描述 + * 变量名:trade_state_desc + * 是否必填:是 + * 类型:string(256) + * 描述:交易状态描述 + * 示例值:支付失败,请重新下单支付 + *+ */ + @SerializedName(value = "trade_state_desc") + private String tradeStateDesc; + /** + *
+ * 字段名:附加数据 + * 变量名:attach + * 是否必填:否 + * 类型:string[1,128] + * 描述: + * 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用 + * 示例值:自定义数据 + *+ */ + @SerializedName(value = "attach") + protected String attach; + + /** + *
+ * 字段名:订单优惠标记 + * 变量名:goods_tag + * 是否必填:否 + * 类型:string[1,256] + * 描述: + * 订单优惠标记 + * 示例值:WXG + *+ */ + @SerializedName(value = "goods_tag") + private String goodsTag; + /** + *
+ * 字段名:电子发票入口开放标识 + * 变量名:support_fapiao + * 是否必填:否 + * 类型:boolean + * 描述:传入true时,支付成功消息和支付详情页将出现开票入口。需要在微信支付商户平台或微信公众平台开通电子发票功能,传此字段才可生效。 + *+ */ + @SerializedName(value = "support_fapiao") + private Boolean supportFapiao; + /** + *
+ * 字段名:支付者 + * 变量名:payer + * 是否必填:是 + * 类型:object + * 描述: + * 支付者信息 + *+ */ + @SerializedName(value = "payer") + private Payer payer; + /** + *
+ * 字段名:订单金额 + * 变量名:amount + * 是否必填:是 + * 类型:object + * 描述: + * 订单金额信息 + *+ */ + @SerializedName(value = "amount") + private Amount amount; + /** + *
+ * 字段名:场景信息 + * 变量名:scene_info + * 是否必填:否 + * 类型:object + * 描述: + * 支付场景描述 + *+ */ + @SerializedName(value = "scene_info") + private SceneInfo sceneInfo; + + /** + *
+ * 字段名:优惠功能 + * 变量名:promotion_detail + * 是否必填:否 + * 类型:array + * 描述: + * 优惠功能,享受优惠时返回该字段。 + *+ */ + @SerializedName(value = "promotion_detail") + private List
+ * 字段名:总金额 + * 变量名:total + * 是否必填:否 + * 类型:int + * 描述: + * 订单总金额,单位为分。 + * 示例值:100 + *+ */ + @SerializedName(value = "total") + private Integer total; + /** + *
+ * 字段名:用户支付金额 + * 变量名:payer_total + * 是否必填:否 + * 类型:int + * 描述: + * 用户支付金额,单位为分。 + * 示例值:100 + *+ */ + @SerializedName(value = "payer_total") + private Integer payerTotal; + /** + *
+ * 字段名:货币类型 + * 变量名:currency + * 是否必填:否 + * 类型:string[1,16] + * 描述: + * CNY:人民币,境内商户号仅支持人民币。 + * 示例值:CNY + *+ */ + @SerializedName(value = "currency") + private String currency; + /** + *
+ * 字段名:用户支付币种 + * 变量名:payer_currency + * 是否必填:否 + * 类型:string[1,16] + * 描述: + * 用户支付币种 + * 示例值: CNY + *+ */ + @SerializedName(value = "payer_currency") + private String payerCurrency; + } + + @Data + @NoArgsConstructor + public static class Payer implements Serializable { + private static final long serialVersionUID = -1L; + /** + *
+ * 字段名:用户标识 + * 变量名:auth_code + * 是否必填:是 + * 类型:string[32] + * 描述: + * 付款码支付授权码,即用户打开微信钱包显示的码。 + * 示例值:130061098828009406 + *+ */ + @SerializedName(value = "auth_code") + private String authCode; + } + + @Data + @NoArgsConstructor + public static class SceneInfo implements Serializable { + private static final long serialVersionUID = 1L; + /** + *
+ * 字段名:商户端设备 IP + * 变量名:device_ip + * 是否必填:是 + * 类型:string[1,45] + * 描述: + * 用户的客户端IP,支持IPv4和IPv6两种格式的IP地址。 + * 示例值:14.23.150.211 + *+ */ + @SerializedName(value = "device_ip") + private String deviceIp; + /** + *
+ * 字段名:商户端设备号 + * 变量名:device_id + * 是否必填:否 + * 类型:string[1,32] + * 描述: + * 商户端设备号(门店号或收银设备ID)。 + * 示例值:013467007045764 + *+ */ + @SerializedName(value = "device_id") + private String deviceId; + /** + *
+ * 字段名:商户门店信息 + * 变量名:store_info + * 是否必填:否 + * 类型:object + * 描述: + * 商户门店信息 + *+ */ + @SerializedName(value = "store_info") + private StoreInfo storeInfo; + } + + /** + * 商户门店信息 + */ + @Data + @NoArgsConstructor + public static class StoreInfo implements Serializable { + private static final long serialVersionUID = -1L; + /** + *
+ * 字段名:门店编号 + * 变量名:id + * 是否必填:是 + * 类型:string[1,32] + * 描述: + * 此参数与商家自定义编码(out_id)二选一必填。 + * 微信支付线下场所ID,格式为纯数字。 + * 基于合规要求与风险管理目的,线下条码支付时需传入用户实际付款的场景信息。 + * 指引参见:https://kf.qq.com/faq/230817neeaem2308177ZFfqM.html。 + * 示例值:0001 + *+ */ + @SerializedName(value = "id") + private String id; + /** + *
+ * 字段名:商家自定义编码 + * 变量名:out_id + * 是否必填:否 + * 类型:string[1,256] + * 描述: + * 此参数与门店(id)二选一必填。 + * 商户系统的门店编码,支持大小写英文字母、数字,仅支持utf-8格式。 + * 基于合规要求与风险管理目的,线下条码支付时需传入用户实际付款的场景信息。 + * 示例值:A1111 + *+ */ + @SerializedName(value = "out_id") + private String outId; + } + + + @Data + @NoArgsConstructor + public static class SettleInfo implements Serializable { + private static final long serialVersionUID = 1L; + /** + *
+ * 字段名:是否指定分账 + * 变量名:profit_sharing + * 是否必填:否 + * 类型:boolean + * 描述: + * 是否指定分账 + * 示例值:false + *+ */ + @SerializedName(value = "profit_sharing") + private Boolean profitSharing; + } + + + @Data + @NoArgsConstructor + public static class PromotionDetail implements Serializable { + /** + *
+ * 字段名:券ID + * 变量名:coupon_id + * 是否必填:是 + * 类型:string[1,32] + * 描述: + * 券ID + * 示例值:109519 + *+ */ + @SerializedName(value = "coupon_id") + private String couponId; + /** + *
+ * 字段名:优惠名称 + * 变量名:name + * 是否必填:否 + * 类型:string[1,64] + * 描述: + * 优惠名称 + * 示例值:单品惠-6 + *+ */ + @SerializedName(value = "name") + private String name; + /** + *
+ * 字段名:优惠范围 + * 变量名:scope + * 是否必填:否 + * 类型:string[1,32] + * 描述: + * GLOBAL:全场代金券 + * SINGLE:单品优惠 + * 示例值:GLOBAL + *+ */ + @SerializedName(value = "scope") + private String scope; + /** + *
+ * 字段名:优惠类型 + * 变量名:type + * 是否必填:否 + * 类型:string[1,32] + * 描述: + * CASH:充值 + * NOCASH:预充值 + * 示例值:CASH + *+ */ + @SerializedName(value = "type") + private String type; + /** + *
+ * 字段名:优惠券面额 + * 变量名:amount + * 是否必填:是 + * 类型:int + * 描述: + * 优惠券面额 + * 示例值:100 + *+ */ + @SerializedName(value = "amount") + private Integer amount; + /** + *
+ * 字段名:活动ID + * 变量名:stock_id + * 是否必填:否 + * 类型:string[1,32] + * 描述: + * 活动ID + * 示例值:931386 + *+ */ + @SerializedName(value = "stock_id") + private String stockId; + /** + *
+ * 字段名:微信出资 + * 变量名:wechatpay_contribute + * 是否必填:否 + * 类型:int + * 描述: + * 微信出资,单位为分 + * 示例值:0 + *+ */ + @SerializedName(value = "wechatpay_contribute") + private Integer wechatpayContribute; + /** + *
+ * 字段名:商户出资 + * 变量名:merchant_contribute + * 是否必填:否 + * 类型:int + * 描述: + * 商户出资,单位为分 + * 示例值:0 + *+ */ + @SerializedName(value = "merchant_contribute") + private Integer merchantContribute; + /** + *
+ * 字段名:其他出资 + * 变量名:other_contribute + * 是否必填:否 + * 类型:int + * 描述: + * 其他出资,单位为分 + * 示例值:0 + *+ */ + @SerializedName(value = "other_contribute") + private Integer otherContribute; + /** + *
+ * 字段名:优惠币种 + * 变量名:currency + * 是否必填:否 + * 类型:string[1,16] + * 描述: + * CNY:人民币,境内商户号仅支持人民币。 + * 示例值:CNY + *+ */ + @SerializedName(value = "currency") + private String currency; + /** + *
+ * 字段名:单品列表 + * 变量名:goods_detail + * 是否必填:否 + * 类型:array + * 描述: + * 单品列表信息 + *+ */ + @SerializedName(value = "goods_detail") + private List
+ * 字段名:商品编码 + * 变量名:goods_id + * 是否必填:是 + * 类型:string[1,32] + * 描述: + * 商品编码 + * 示例值:M1006 + *+ */ + @SerializedName(value = "goods_id") + private String goodsId; + /** + *
+ * 字段名:商品数量 + * 变量名:quantity + * 是否必填:是 + * 类型:int + * 描述: + * 用户购买的数量 + * 示例值:1 + *+ */ + @SerializedName(value = "quantity") + private Integer quantity; + /** + *
+ * 字段名:商品单价 + * 变量名:unit_price + * 是否必填:是 + * 类型:int + * 描述: + * 商品单价,单位为分 + * 示例值:100 + *+ */ + @SerializedName(value = "unit_price") + private Integer unitPrice; + /** + *
+ * 字段名:商品优惠金额 + * 变量名:discount_amount + * 是否必填:是 + * 类型:int + * 描述: + * 商品优惠金额 + * 示例值:0 + *+ */ + @SerializedName(value = "discount_amount") + private Integer discountAmount; + /** + *
+ * 字段名:商品备注 + * 变量名:goods_remark + * 是否必填:否 + * 类型:string[1,128] + * 描述: + * 商品备注信息 + * 示例值:商品备注信息 + *+ */ + @SerializedName(value = "goods_remark") + private String goodsRemark; + } +} + diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayOrderReverseV3Result.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayOrderReverseV3Result.java new file mode 100644 index 0000000000..bcc990face --- /dev/null +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/bean/result/WxPayOrderReverseV3Result.java @@ -0,0 +1,57 @@ +package com.github.binarywang.wxpay.bean.result; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +/** + * 微信V3撤销支付订单返回结果 + * @author DaxPay + * @date 2024/7/29 + */ +@Data +@Accessors(chain = true) +public class WxPayOrderReverseV3Result implements Serializable { + private static final long serialVersionUID = 1L; + /** + *
+ * 字段名:应用ID + * 变量名:appid + * 是否必填:是 + * 类型:string[1,32] + * 描述: + * 由微信生成的应用ID,全局唯一。请求统一下单接口时请注意APPID的应用属性,例如公众号场景下,需使用应用属性为公众号的APPID + * 示例值:wxd678efh567hg6787 + *+ */ + @SerializedName(value = "appid") + protected String appid; + /** + *
+ * 字段名:直连商户号 + * 变量名:mchid + * 是否必填:是 + * 类型:string[1,32] + * 描述: + * 直连商户的商户号,由微信支付生成并下发。 + * 示例值:1230000109 + *+ */ + @SerializedName(value = "mchid") + protected String mchid; + /** + *
+ * 字段名:商户订单号 + * 变量名:out_trade_no + * 是否必填:是 + * 类型:string[6,32] + * 描述: + * 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一 + * 示例值:1217752501201407033233368018 + *+ */ + @SerializedName(value = "out_trade_no") + protected String outTradeNo; +} diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java index b73029f4e1..57c2937c62 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/WxPayService.java @@ -1275,6 +1275,25 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri */ WxPayMicropayResult micropay(WxPayMicropayRequest request) throws WxPayException; + /** + *
+ * 付款码支付API. + * 文档地址:https://pay.weixin.qq.com/docs/merchant/apis/code-payment-v3/direct/code-pay.html + * 应用场景: + * 收银员使用扫码设备读取微信用户付款码以后,二维码或条码信息会传送至商户收银台,由商户收银台或者商户后台调用该接口发起支付。 + * 提醒1:提交支付请求后微信会同步返回支付结果。当返回结果为“系统错误”时,商户系统等待5秒后调用【查询订单API】,查询支付实际交易结果;当返回结果为“USERPAYING”时,商户系统可设置间隔时间(建议10秒)重新查询支付结果,直到支付成功或超时(建议30秒); + * 提醒2:在调用查询接口返回后,如果交易状况不明晰,请调用【撤销订单API】,此时如果交易失败则关闭订单,该单不能再支付成功;如果交易成功,则将扣款退回到用户账户。当撤销无返回或错误时,请再次调用。注意:请勿扣款后立即调用【撤销订单API】,建议至少15秒后再调用。撤销订单API需要双向证书。 + * 接口地址: https://pay.weixin.qq.com/docs/merchant/apis/code-payment-v3/direct/reverse.html + * 是否需要证书:不需要。 + *+ * + * @param request the request + * @return the wx codepay result + * @throws WxPayException the wx pay exception + */ + WxPayCodepayResult codepay(WxPayCodepayRequest request) throws WxPayException; + + /** *
* 撤销订单API. @@ -1295,6 +1314,47 @@ WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, Stri */ WxPayOrderReverseResult reverseOrder(WxPayOrderReverseRequest request) throws WxPayException; + /** + *+ * 撤销订单API. + * 文档地址:https://pay.weixin.qq.com/docs/merchant/apis/code-payment-v3/direct/reverse.html + * 应用场景: + * 支付交易返回失败或支付系统超时,调用该接口撤销交易。如果此订单用户支付失败,微信支付系统会将此订单关闭; + * 如果用户支付成功,微信支付系统会将此订单资金退还给用户。 + * 注意:7天以内的交易单可调用撤销,其他正常支付的单如需实现相同功能请调用申请退款API。 + * 提交支付交易后调用【查询订单API】,没有明确的支付结果再调用【撤销订单API】。 + * 调用支付接口后请勿立即调用撤销订单API,建议支付后至少15s后再调用撤销订单接口。 + * 接口链接 :https://pay.weixin.qq.com/docs/merchant/apis/code-payment-v3/direct/reverse.html + * 是否需要证书:请求需要双向证书。 + *+ * + * @param request the request + * @return the wx pay order reverse result + * @throws WxPayException the wx pay exception + */ + WxPayOrderReverseV3Result reverseOrderV3(WxPayOrderReverseV3Request request) throws WxPayException; + + /** + *+ * 撤销订单API. + * 文档地址:https://pay.weixin.qq.com/docs/merchant/apis/code-payment-v3/direct/reverse.html + * 应用场景: + * 支付交易返回失败或支付系统超时,调用该接口撤销交易。如果此订单用户支付失败,微信支付系统会将此订单关闭; + * 如果用户支付成功,微信支付系统会将此订单资金退还给用户。 + * 注意:7天以内的交易单可调用撤销,其他正常支付的单如需实现相同功能请调用申请退款API。 + * 提交支付交易后调用【查询订单API】,没有明确的支付结果再调用【撤销订单API】。 + * 调用支付接口后请勿立即调用撤销订单API,建议支付后至少15s后再调用撤销订单接口。 + * 接口链接 :https://pay.weixin.qq.com/docs/merchant/apis/code-payment-v3/direct/reverse.html + * 是否需要证书:请求需要双向证书。 + *+ * + * @param outTradeNo 商户系统内部的订单号 + * @return the wx pay order reverse result + * @throws WxPayException the wx pay exception + */ + WxPayOrderReverseV3Result reverseOrderV3(String outTradeNo) throws WxPayException; + + /** ** 转换短链接. diff --git a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java index 1187880cb6..851040dd13 100644 --- a/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java +++ b/weixin-java-pay/src/main/java/com/github/binarywang/wxpay/service/impl/BaseWxPayServiceImpl.java @@ -1130,6 +1130,19 @@ public WxPayMicropayResult micropay(WxPayMicropayRequest request) throws WxPayEx return result; } + @Override + public WxPayCodepayResult codepay(WxPayCodepayRequest request) throws WxPayException { + if (StringUtils.isBlank(request.getAppid())) { + request.setAppid(this.getConfig().getAppId()); + } + if (StringUtils.isBlank(request.getMchid())) { + request.setMchid(this.getConfig().getMchId()); + } + String url = String.format("%s/v3/pay/transactions/codepay", this.getPayBaseUrl()); + String body = this.postV3(url, GSON.toJson(request)); + return GSON.fromJson(body, WxPayCodepayResult.class); + } + @Override public WxPayOrderReverseResult reverseOrder(WxPayOrderReverseRequest request) throws WxPayException { request.checkAndSign(this.getConfig()); @@ -1141,6 +1154,31 @@ public WxPayOrderReverseResult reverseOrder(WxPayOrderReverseRequest request) th return result; } + + @Override + public WxPayOrderReverseV3Result reverseOrderV3(WxPayOrderReverseV3Request request) throws WxPayException { + if (StringUtils.isBlank(request.getAppid())) { + request.setAppid(this.getConfig().getAppId()); + } + if (StringUtils.isBlank(request.getMchid())) { + request.setMchid(this.getConfig().getMchId()); + } + // 拼接参数请求路径并发送 + String url = String.format("%s/v3/pay/transactions/out-trade-no/%s/reverse", this.getPayBaseUrl(), request.getOutTradeNo()); + String response = this.postV3(url, GSON.toJson(request)); + return GSON.fromJson(response, WxPayOrderReverseV3Result.class); + } + + @Override + public WxPayOrderReverseV3Result reverseOrderV3(String outTradeNo) throws WxPayException { + if (StringUtils.isBlank(outTradeNo)) { + throw new WxPayException("out_trade_no不能为空"); + } + WxPayOrderReverseV3Request request = new WxPayOrderReverseV3Request(); + request.setOutTradeNo(StringUtils.trimToNull(outTradeNo)); + return this.reverseOrderV3(request); + } + @Override public String shorturl(WxPayShorturlRequest request) throws WxPayException { request.checkAndSign(this.getConfig());