🆕 #2130 【微信支付】增加微信支付部分v3接口

This commit is contained in:
thinsstar
2021-05-21 22:07:02 +08:00
committed by GitHub
parent fa5d892176
commit efb2c52011
18 changed files with 3959 additions and 6 deletions
@@ -0,0 +1,165 @@
package com.github.binarywang.wxpay.bean.notify;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@NoArgsConstructor
public class OriginNotifyResponse implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:通知ID
* 变量名:id
* 是否必填:是
* 类型:string[1,36]
* 描述:
* 通知的唯一ID
* 示例值:EV-2018022511223320873
* </pre>
*/
@SerializedName(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年5月20日13点29分35秒。
* 示例值:2018-06-08T10:34:56+08:00
* </pre>
*/
@SerializedName(value = "create_time")
private String createTime;
/**
* <pre>
* 字段名:通知类型
* 变量名:event_type
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 通知的类型:
* REFUND.SUCCESS:退款成功通知
* REFUND.ABNORMAL:退款异常通知
* REFUND.CLOSED:退款关闭通知
* 示例值:REFUND.SUCCESS
* </pre>
*/
@SerializedName(value = "event_type")
private String eventType;
/**
* <pre>
* 字段名:通知简要说明
* 变量名:summary
* 是否必填:是
* 类型:string[1,16]
* 描述:
* 通知简要说明
* 示例值:退款成功
* </pre>
*/
@SerializedName(value = "summary")
private String summary;
/**
* <pre>
* 字段名:通知数据类型
* 变量名:resource_type
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 通知的资源数据类型,支付成功通知为encrypt-resource
* 示例值:encrypt-resource
* </pre>
*/
@SerializedName(value = "resource_type")
private String resourceType;
/**
* <pre>
* 字段名:通知数据
* 变量名:resource
* 是否必填:是
* 类型:object
* 描述:
* 通知资源数据
* json格式,见示例
* </pre>
*/
@SerializedName(value = "resource")
private Resource resource;
@Data
@NoArgsConstructor
public static class Resource implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:加密算法类型
* 变量名:algorithm
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 对开启结果数据进行加密的加密算法,目前只支持AEAD_AES_256_GCM
* 示例值:AEAD_AES_256_GCM
* </pre>
*/
@SerializedName(value = "algorithm")
private String algorithm;
/**
* <pre>
* 字段名:原始类型
* 变量名:original_type
* 是否必填:是
* 类型:string[1,16]
* 描述:
* 原始回调类型,为transaction
* 示例值:transaction
* </pre>
*/
@SerializedName(value = "original_type")
private String originalType;
/**
* <pre>
* 字段名:数据密文
* 变量名:ciphertext
* 是否必填:是
* 类型:string[1,1048576]
* 描述:
* Base64编码后的开启/停用结果数据密文
* 示例值:sadsadsadsad
* </pre>
*/
@SerializedName(value = "ciphertext")
private String ciphertext;
/**
* <pre>
* 字段名:附加数据
* 变量名:associated_data
* 是否必填:否
* 类型:string[1,16]
* 描述:
* 附加数据
* 示例值:fdasfwqewlkja484w
* </pre>
*/
@SerializedName(value = "associated_data")
private String associatedData;
/**
* <pre>
* 字段名:随机串
* 变量名:nonce
* 是否必填:是
* 类型:string[1,16]
* 描述:
* 加密使用的随机串
* 示例值:fdasflkja484w
* </pre>
*/
@SerializedName(value = "nonce")
private String nonce;
}
}
@@ -0,0 +1,32 @@
package com.github.binarywang.wxpay.bean.notify;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 微信通知接口头部信息,需要做签名验证
* 文档地址: https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_1.shtml
*/
@Data
@NoArgsConstructor
public class SignatureHeader implements Serializable {
private static final long serialVersionUID = -1L;
/**
* 时间戳
*/
private String timeStamp;
/**
* 随机串
*/
private String nonce;
/**
* 已签名字符串
*/
private String signature;
/**
* 证书序列号
*/
private String serial;
}
@@ -0,0 +1,542 @@
package com.github.binarywang.wxpay.bean.notify;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* 支付结果通知.
* 文档见:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_5.shtml
*
* @author thinsstar
*/
@Data
@NoArgsConstructor
public class WxPayOrderNotifyV3Result implements Serializable {
private static final long serialVersionUID = -1L;
/**
* 源数据
*/
private OriginNotifyResponse rawData;
/**
* 解密后的数据
*/
private DecryptNotifyResult result;
@Data
@NoArgsConstructor
public static class DecryptNotifyResult implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:应用ID
* 变量名:appid
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 直连商户申请的公众号或移动应用appid。
* 示例值:wxd678efh567hg6787
* </pre>
*/
@SerializedName(value = "appid")
private String appid;
/**
* <pre>
* 字段名:商户号
* 变量名:mchid
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一。
* 特殊规则:最小字符长度为6
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "mchid")
private String mchid;
/**
* <pre>
* 字段名:商户订单号
* 变量名:out_trade_no
* 是否必填:是
* 类型:string[6,32]
* 描述:
* 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一。
* 特殊规则:最小字符长度为6
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "out_trade_no")
private String outTradeNo;
/**
* <pre>
* 字段名:微信支付订单号
* 变量名:transaction_id
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 微信支付系统生成的订单号。
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "transaction_id")
private String transactionId;
/**
* <pre>
* 字段名:交易类型
* 变量名:trade_type
* 是否必填:是
* 类型:string[1,16]
* 描述:
* 交易类型,枚举值:
* JSAPI:公众号支付
* NATIVE:扫码支付
* APP:APP支付
* MICROPAY:付款码支付
* MWEB:H5支付
* FACEPAY:刷脸支付
* 示例值:MICROPAY
* </pre>
*/
@SerializedName(value = "trade_type")
private String tradeType;
/**
* <pre>
* 字段名:交易状态
* 变量名:trade_state
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 交易状态,枚举值:
* SUCCESS:支付成功
* REFUND:转入退款
* NOTPAY:未支付
* CLOSED:已关闭
* REVOKED:已撤销(付款码支付)
* USERPAYING:用户支付中(付款码支付)
* PAYERROR:支付失败(其他原因,如银行返回失败)
* 示例值:SUCCESS
* </pre>
*/
@SerializedName(value = "trade_state")
private String tradeState;
/**
* <pre>
* 字段名:交易状态描述
* 变量名:trade_state_desc
* 是否必填:是
* 类型:string[1,256]
* 描述:
* 交易状态描述
* 示例值:支付成功
* </pre>
*/
@SerializedName(value = "trade_state_desc")
private String tradeStateDesc;
/**
* <pre>
* 字段名:付款银行
* 变量名:bank_type
* 是否必填:是
* 类型:string[1,16]
* 描述:
* 银行类型,采用字符串类型的银行标识。银行标识请参考《银行类型对照表》https://pay.weixin.qq.com/wiki/doc/apiv3/terms_definition/chapter1_1_3.shtml#part-6
* 示例值:CMC
* </pre>
*/
@SerializedName(value = "bank_type")
private String bankType;
/**
* <pre>
* 字段名:附加数据
* 变量名:attach
* 是否必填:否
* 类型:string[1,128]
* 描述:
* 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用
* 示例值:自定义数据
* </pre>
*/
@SerializedName(value = "attach")
private String attach;
/**
* <pre>
* 字段名:支付完成时间
* 变量名:success_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>
*/
@SerializedName(value = "success_time")
private String successTime;
/**
* <pre>
* 字段名:支付者
* 变量名:payer
* 是否必填:是
* 类型:object
* 描述:
* 支付者信息
* </pre>
*/
private Payer payer;
/**
* <pre>
* 字段名:订单金额
* 变量名:amount
* 是否必填:否
* 类型:object
* 描述:
* 订单金额信息
* </pre>
*/
@SerializedName(value = "amount")
private Amount amount;
/**
* <pre>
* 字段名:场景信息
* 变量名:scene_info
* 是否必填:否
* 类型:object
* 描述:
* 支付场景信息描述
* </pre>
*/
@SerializedName(value = "scene_info")
private SceneInfo sceneInfo;
/**
* <pre>
* 字段名:优惠功能
* 变量名:promotion_detail
* 是否必填:否
* 类型:array
* 描述:
* 优惠功能,享受优惠时返回该字段。
* </pre>
*/
@SerializedName(value = "promotion_detail")
private List<PromotionDetail> promotionDetails;
}
@Data
@NoArgsConstructor
public static class Payer implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:用户标识
* 变量名:openid
* 是否必填:是
* 类型:string[1,128]
* 描述:
* 用户在直连商户appid下的唯一标识。
* 示例值:oUpF8uMuAJO_M2pxb1Q9zNjWeS6o
* </pre>
*/
@SerializedName(value = "openid")
private String openid;
}
@Data
@NoArgsConstructor
public static class Amount implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:总金额
* 变量名:total
* 是否必填:否
* 类型:int
* 描述:
* 订单总金额,单位为分。
* 示例值:100
* </pre>
*/
@SerializedName(value = "total")
private Integer total;
/**
* <pre>
* 字段名:用户支付金额
* 变量名:payer_total
* 是否必填:否
* 类型:int
* 描述:
* 用户支付金额,单位为分。
* 示例值:100
* </pre>
*/
@SerializedName(value = "payer_total")
private Integer payerTotal;
/**
* <pre>
* 字段名:货币类型
* 变量名:currency
* 是否必填:否
* 类型:string[1,16]
* 描述:
* CNY:人民币,境内商户号仅支持人民币。
* 示例值:CNY
* </pre>
*/
@SerializedName(value = "currency")
private String currency;
/**
* <pre>
* 字段名:用户支付币种
* 变量名:payer_currency
* 是否必填:否
* 类型:string[1,16]
* 描述:
* 用户支付币种
* 示例值: CNY
* </pre>
*/
@SerializedName(value = "payer_currency")
private String payerCurrency;
}
@Data
@NoArgsConstructor
public static class SceneInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:商户端设备号
* 变量名:device_id
* 是否必填:否
* 类型:string[1,32]
* 描述:
* 终端设备号(门店号或收银设备ID)。
* 示例值:013467007045764
* </pre>
*/
@SerializedName(value = "device_id")
private String deviceId;
}
@Data
@NoArgsConstructor
public static class PromotionDetail implements Serializable {
/**
* <pre>
* 字段名:券ID
* 变量名:coupon_id
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 券ID
* 示例值:109519
* </pre>
*/
@SerializedName(value = "coupon_id")
private String couponId;
/**
* <pre>
* 字段名:优惠名称
* 变量名:name
* 是否必填:否
* 类型:string[1,64]
* 描述:
* 优惠名称
* 示例值:单品惠-6
* </pre>
*/
@SerializedName(value = "name")
private String name;
/**
* <pre>
* 字段名:优惠范围
* 变量名:scope
* 是否必填:否
* 类型:string[1,32]
* 描述:
* GLOBAL:全场代金券
* SINGLE:单品优惠
* 示例值:GLOBAL
* </pre>
*/
@SerializedName(value = "scope")
private String scope;
/**
* <pre>
* 字段名:优惠类型
* 变量名:type
* 是否必填:否
* 类型:string[1,32]
* 描述:
* CASH:充值
* NOCASH:预充值
* 示例值:CASH
* </pre>
*/
@SerializedName(value = "type")
private String type;
/**
* <pre>
* 字段名:优惠券面额
* 变量名:amount
* 是否必填:是
* 类型:int
* 描述:
* 优惠券面额
* 示例值:100
* </pre>
*/
@SerializedName(value = "amount")
private Integer amount;
/**
* <pre>
* 字段名:活动ID
* 变量名:stock_id
* 是否必填:否
* 类型:string[1,32]
* 描述:
* 活动ID
* 示例值:931386
* </pre>
*/
@SerializedName(value = "stock_id")
private String stockId;
/**
* <pre>
* 字段名:微信出资
* 变量名:wechatpay_contribute
* 是否必填:否
* 类型:int
* 描述:
* 微信出资,单位为分
* 示例值:0
* </pre>
*/
@SerializedName(value = "wechatpay_contribute")
private Integer wechatpayContribute;
/**
* <pre>
* 字段名:商户出资
* 变量名:merchant_contribute
* 是否必填:否
* 类型:int
* 描述:
* 商户出资,单位为分
* 示例值:0
* </pre>
*/
@SerializedName(value = "merchant_contribute")
private Integer merchantContribute;
/**
* <pre>
* 字段名:其他出资
* 变量名:other_contribute
* 是否必填:否
* 类型:int
* 描述:
* 其他出资,单位为分
* 示例值:0
* </pre>
*/
@SerializedName(value = "other_contribute")
private Integer otherContribute;
/**
* <pre>
* 字段名:优惠币种
* 变量名:currency
* 是否必填:否
* 类型:string[1,16]
* 描述:
* CNY:人民币,境内商户号仅支持人民币。
* 示例值:CNY
* </pre>
*/
@SerializedName(value = "currency")
private String currency;
/**
* <pre>
* 字段名:单品列表
* 变量名:goods_detail
* 是否必填:否
* 类型:array
* 描述:
* 单品列表信息
* </pre>
*/
@SerializedName(value = "goods_detail")
private List<GoodsDetail> goodsDetails;
}
@Data
@NoArgsConstructor
public static class GoodsDetail implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:商品编码
* 变量名:goods_id
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 商品编码
* 示例值:M1006
* </pre>
*/
@SerializedName(value = "goods_id")
private String goodsId;
/**
* <pre>
* 字段名:商品数量
* 变量名:quantity
* 是否必填:是
* 类型:int
* 描述:
* 用户购买的数量
* 示例值:1
* </pre>
*/
@SerializedName(value = "quantity")
private Integer quantity;
/**
* <pre>
* 字段名:商品单价
* 变量名:unit_price
* 是否必填:是
* 类型:int
* 描述:
* 商品单价,单位为分
* 示例值:100
* </pre>
*/
@SerializedName(value = "unit_price")
private Integer unitPrice;
/**
* <pre>
* 字段名:商品优惠金额
* 变量名:discount_amount
* 是否必填:是
* 类型:int
* 描述:
* 商品优惠金额
* 示例值:0
* </pre>
*/
@SerializedName(value = "discount_amount")
private Integer discountAmount;
/**
* <pre>
* 字段名:商品备注
* 变量名:goods_remark
* 是否必填:否
* 类型:string[1,128]
* 描述:
* 商品备注信息
* 示例值:商品备注信息
* </pre>
*/
@SerializedName(value = "goods_remark")
private String goodsRemark;
}
}
@@ -0,0 +1,214 @@
package com.github.binarywang.wxpay.bean.notify;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 退款结果通知.
* 文档见:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_11.shtml
*
* @author thinsstar
*/
@Data
@NoArgsConstructor
public class WxPayRefundNotifyV3Result implements Serializable {
private static final long serialVersionUID = -1L;
/**
* 源数据
*/
private OriginNotifyResponse rawData;
/**
* 解密后的数据
*/
private DecryptNotifyResult result;
@Data
@NoArgsConstructor
public static class DecryptNotifyResult implements Serializable {
private static final long serialVersionUID = -1L;
/**
* <pre>
* 字段名:直连商户号
* 变量名:mchid
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 直连商户的商户号,由微信支付生成并下发。
* 示例值:1900000100
* </pre>
*/
@SerializedName(value = "mchid")
private String mchid;
/**
* <pre>
* 字段名:商户订单号
* 变量名:out_trade_no
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 返回的商户订单号
* 示例值: 1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "out_trade_no")
private String outTradeNo;
/**
* <pre>
* 字段名:微信支付订单号
* 变量名:transaction_id
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 微信支付订单号
* 示例值: 1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "transaction_id")
private String transactionId;
/**
* <pre>
* 字段名:商户退款单号
* 变量名:out_refund_no
* 是否必填:是
* 类型:string[1,64]
* 描述:
* 商户退款单号
* 示例值: 1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "out_refund_no")
private String outRefundNo;
/**
* <pre>
* 字段名:微信支付退款号
* 变量名:refund_id
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 微信退款单号
* 示例值: 1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "refund_id")
private String refundId;
/**
* <pre>
* 字段名:退款状态
* 变量名:refund_status
* 是否必填:是
* 类型:string[1,16]
* 描述:
* 退款状态,枚举值:
* SUCCESS:退款成功
* CLOSE:退款关闭
* ABNORMAL:退款异常,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往【商户平台—>交易中心】,手动处理此笔退款
* 示例值:SUCCESS
* </pre>
*/
@SerializedName(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>
*/
@SerializedName(value = "success_time")
private String successTime;
/**
* <pre>
* 字段名:退款入账账户
* 变量名:user_received_account
* 是否必填:是
* 类型:string[1,64]
* 描述:
* 取当前退款单的退款入账方。
* 1、退回银行卡:{银行名称}{卡类型}{卡尾号}
* 2、退回支付用户零钱: 支付用户零钱
* 3、退还商户: 商户基本账户、商户结算银行账户
* 4、退回支付用户零钱通:支付用户零钱通
* 示例值:招商银行信用卡0403
* </pre>
*/
@SerializedName(value = "user_received_account")
private String userReceivedAccount;
/**
* <pre>
* 字段名:金额信息
* 变量名:amount
* 是否必填:是
* 类型:object
* 描述:
* 金额信息
* </pre>
*/
@SerializedName(value = "amount")
private Amount amount;
}
@Data
@NoArgsConstructor
public static class Amount implements Serializable {
/**
* <pre>
* 字段名:订单金额
* 变量名:total
* 是否必填:是
* 类型:int
* 描述:
* 订单总金额,单位为分,只能为整数,详见支付金额
* 示例值:999
* </pre>
*/
@SerializedName(value = "total")
private Integer total;
/**
* <pre>
* 字段名:退款金额
* 变量名:refund
* 是否必填:是
* 类型:int
* 描述:
* 退款金额,币种的最小单位,只能为整数,不能超过原订单支付金额,如果有使用券,后台会按比例退。
* 示例值:999
* </pre>
*/
@SerializedName(value = "refund")
private String refund;
/**
* <pre>
* 字段名:用户支付金额
* 变量名:payer_total
* 是否必填:是
* 类型:int
* 描述:
* 用户实际支付金额,单位为分,只能为整数,详见支付金额
* 示例值:999
* </pre>
*/
@SerializedName(value = "payer_total")
private Integer payerTotal;
/**
* <pre>
* 字段名:用户退款金额
* 变量名:payer_refund
* 是否必填:是
* 类型:int
* 描述:
* 退款给用户的金额,不包含所有优惠券金额
* 示例值:999
* </pre>
*/
@SerializedName(value = "payer_refund")
private String payerRefund;
}
}
@@ -0,0 +1,47 @@
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;
/**
* <pre>
* 关闭订单请求对象类
* </pre>
*
* @author thinsstar
*/
@Data
@NoArgsConstructor
@Accessors(chain = true)
public class WxPayOrderCloseV3Request implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:直连商户号
* 变量名:mchid
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 直连商户的商户号,由微信支付生成并下发。
* 示例值:1230000109
* </pre>
*/
@SerializedName(value = "mchid")
private String mchid;
/**
* <pre>
* 字段名:商户订单号
* 变量名:out_trade_no
* 是否必填:是
* 类型:string[6,32]
* 描述:
* 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一
* 示例值:1217752501201407033233368018
* </pre>
*/
private transient String outTradeNo;
}
@@ -0,0 +1,62 @@
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;
/**
* <pre>
* 订单查询请求对象
* </pre>
*
* @author thinsstar
*/
@Data
@NoArgsConstructor
@Accessors(chain = true)
public class WxPayOrderQueryV3Request implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:直连商户号
* 变量名:mchid
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 直连商户的商户号,由微信支付生成并下发。
* 示例值:1230000109
* </pre>
*/
@SerializedName(value = "mchid")
private String mchid;
/**
* <pre>
* 字段名:微信支付订单号
* 变量名:transaction_id
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 微信支付系统生成的订单号
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "transaction_id")
private String transactionId;
/**
* <pre>
* 字段名:商户订单号
* 变量名:out_trade_no
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一。
* 特殊规则:最小字符长度为6
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "out_trade_no")
private String outTradeNo;
}
@@ -0,0 +1,34 @@
package com.github.binarywang.wxpay.bean.request;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* <pre>
* 微信支付-查询单笔退款API
* </pre>
*
* @author thinsstar
*/
@Data
@NoArgsConstructor
public class WxPayRefundQueryV3Request implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:商户订单号
* 变量名:out_trade_no
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一。
* 特殊规则:最小字符长度为6
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "out_trade_no")
private String outTradeNo;
}
@@ -0,0 +1,240 @@
package com.github.binarywang.wxpay.bean.request;
import com.google.gson.annotations.SerializedName;
import lombok.*;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.List;
/**
* <pre>
* 微信支付-申请退款请求参数
* </pre>
*
* @author thinsstar
*/
@Data
@NoArgsConstructor
@Accessors(chain = true)
public class WxPayRefundV3Request implements Serializable {
private static final long serialVersionUID = -1L;
/**
* <pre>
* 字段名:微信支付订单号
* 变量名:transaction_id
* 是否必填:与out_order_no二选一
* 类型:string[1, 32]
* 描述:
* 原支付交易对应的微信订单号。
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "transaction_id")
private String transactionId;
/**
* <pre>
* 字段名:商户订单号
* 变量名:out_trade_no
* 是否必填:与transaction_id二选一
* 类型:string[1, 32]
* 描述:
* 原支付交易对应的商户订单号。
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "out_trade_no")
private String outTradeNo;
/**
* <pre>
* 字段名:商户退款单号
* 变量名:out_refund_no
* 是否必填:是
* 类型:string[1, 64]
* 描述:
* 商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔。
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "out_refund_no")
private String outRefundNo;
/**
* <pre>
* 字段名:退款原因
* 变量名:reason
* 是否必填:否
* 类型:string[1, 80]
* 描述:
* 若商户传入,会在下发给用户的退款消息中体现退款原因。
* 示例值:商品已售完
* </pre>
*/
@SerializedName(value = "reason")
private String reason;
/**
* <pre>
* 字段名:退款结果回调url
* 变量名:notify_url
* 是否必填:否
* 类型:string[8, 256]
* 描述:
* 异步接收微信支付退款结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。 如果参数中传了notify_url,则商户平台上配置的回调地址将不会生效,优先回调当前传的这个地址。
* 示例值:https://weixin.qq.com
* </pre>
*/
@SerializedName(value = "notify_url")
private String notifyUrl;
/**
* <pre>
* 字段名:订单金额
* 变量名:amount
* 是否必填:是
* 类型:object
* 描述:
* 订单金额信息
* </pre>
*/
@SerializedName(value = "amount")
private Amount amount;
/**
* <pre>
* 字段名:退款商品
* 变量名:goods_detail
* 是否必填:否
* 类型:array
* 描述:
* 指定商品退款需要传此参数,其他场景无需传递。
* </pre>
*/
@SerializedName(value = "goods_detail")
private List<GoodsDetail> goodsDetails;
@Data
@NoArgsConstructor
public static class Amount implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:退款金额
* 变量名:refund
* 是否必填:是
* 类型:int
* 描述:
* 退款金额,币种的最小单位,只能为整数,不能超过原订单支付金额。
* 示例值:888
* </pre>
*/
@SerializedName(value = "refund")
private Integer refund;
/**
* <pre>
* 字段名:原订单金额
* 变量名:total
* 是否必填:是
* 类型:int
* 描述:
* 原支付交易的订单总金额,币种的最小单位,只能为整数。
* 示例值:888
* </pre>
*/
@SerializedName(value = "total")
private Integer total;
/**
* <pre>
* 字段名:币类型
* 变量名:currency
* 是否必填:否
* 类型:string[1, 16]
* 描述:
* 符合ISO 4217标准的三位字母代码,目前只支持人民币:CNY。
* 示例值:CNY
* </pre>
*/
@SerializedName(value = "currency")
private String currency;
}
@Data
@NoArgsConstructor
public static class GoodsDetail implements Serializable {
private static final long serialVersionUID = -1L;
/**
* <pre>
* 字段名:商户侧商品编码
* 变量名:merchant_goods_id
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 由半角的大小写字母、数字、中划线、下划线中的一种或几种组成。
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "merchant_goods_id")
private String merchantGoodsId;
/**
* <pre>
* 字段名:微信侧商品编码
* 变量名:wechatpay_goods_id
* 是否必填:否
* 类型:string[1,32]
* 描述:
* 微信支付定义的统一商品编号(没有可不传)。
* 示例值:1001
* </pre>
*/
@SerializedName(value = "wechatpay_goods_id")
private String wechatpayGoodsId;
/**
* <pre>
* 字段名:商品名称
* 变量名:goods_name
* 是否必填:否
* 类型:string[1,256]
* 描述:
* 商品的实际名称。
* 示例值:iPhone6s 16G
* </pre>
*/
@SerializedName(value = "goods_name")
private String goodsName;
/**
* <pre>
* 字段名:商品单价
* 变量名:unit_price
* 是否必填:是
* 类型:int
* 描述:
* 商品单价金额,单位为分。
* 示例值:528800
* </pre>
*/
@SerializedName(value = "unit_price")
private Integer unitPrice;
/**
* <pre>
* 字段名:商品退款金额
* 变量名:refund_amount
* 是否必填:是
* 类型:int
* 描述:
* 商品退款金额,单位为分。
* 示例值:528800
* </pre>
*/
@SerializedName(value = "refund_amount")
private Integer refundAmount;
/**
* <pre>
* 字段名:商品退货数量
* 变量名:refund_quantity
* 是否必填:是
* 类型:int
* 描述:
* 单品的退款数量。
* 示例值:1
* </pre>
*/
@SerializedName(value = "refund_quantity")
private Integer refundQuantity;
}
}
@@ -0,0 +1,565 @@
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;
/**
* <pre>
* 统一下单请求参数对象.
* 参考文档:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml
* https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_1.shtml
* https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_1.shtml
* https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_1.shtml
* https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_1.shtml
* </pre>
*
* @author thinsstar
*/
@Data
@NoArgsConstructor
@Accessors(chain = true)
public class WxPayUnifiedOrderV3Request implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:应用ID
* 变量名:appid
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 由微信生成的应用ID,全局唯一。请求统一下单接口时请注意APPID的应用属性,例如公众号场景下,需使用应用属性为公众号的APPID
* 示例值:wxd678efh567hg6787
* </pre>
*/
@SerializedName(value = "appid")
protected String appid;
/**
* <pre>
* 字段名:直连商户号
* 变量名:mchid
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 直连商户的商户号,由微信支付生成并下发。
* 示例值:1230000109
* </pre>
*/
@SerializedName(value = "mchid")
protected String mchid;
/**
* <pre>
* 字段名:商品描述
* 变量名:description
* 是否必填:是
* 类型:string[1,127]
* 描述:
* 商品描述
* 示例值:Image形象店-深圳腾大-QQ公仔
* </pre>
*/
@SerializedName(value = "description")
protected String description;
/**
* <pre>
* 字段名:商户订单号
* 变量名:out_trade_no
* 是否必填:是
* 类型:string[6,32]
* 描述:
* 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "out_trade_no")
protected String outTradeNo;
/**
* <pre>
* 字段名:交易结束时间
* 变量名:out_trade_no
* 是否必填:是
* 类型: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>
*/
@SerializedName(value = "time_expire")
protected String timeExpire;
/**
* <pre>
* 字段名:附加数据
* 变量名:attach
* 是否必填:否
* 类型:string[1,128]
* 描述:
* 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用
* 示例值:自定义数据
* </pre>
*/
@SerializedName(value = "attach")
protected String attach;
/**
* <pre>
* 字段名:通知地址
* 变量名:notify_url
* 是否必填:是
* 类型:string[1,256]
* 描述:
* 通知URL必须为直接可访问的URL,不允许携带查询串,要求必须为https地址。
* 格式:URL
* 示例值:https://www.weixin.qq.com/wxpay/pay.php
* </pre>
*/
@SerializedName(value = "notify_url")
private String notifyUrl;
/**
* <pre>
* 字段名:订单优惠标记
* 变量名:goods_tag
* 是否必填:否
* 类型:string[1,256]
* 描述:
* 订单优惠标记
* 示例值:WXG
* </pre>
*/
@SerializedName(value = "goods_tag")
private String goodsTag;
/**
* <pre>
* 字段名:订单金额
* 变量名:amount
* 是否必填:是
* 类型:object
* 描述:
* 订单金额信息
* </pre>
*/
@SerializedName(value = "amount")
private Amount amount;
/**
* <pre>
* 字段名:支付者
* 变量名:payer
* 是否必填:是
* 类型:object
* 描述:
* 支付者信息
* </pre>
*/
@SerializedName(value = "payer")
private Payer payer;
/**
* <pre>
* 字段名:优惠功能
* 变量名:detail
* 是否必填:否
* 类型:object
* 描述:
* 优惠功能
* </pre>
*/
@SerializedName(value = "detail")
private Discount detail;
/**
* <pre>
* 字段名:场景信息
* 变量名:scene_info
* 是否必填:否
* 类型:object
* 描述:
* 支付场景描述
* </pre>
*/
@SerializedName(value = "scene_info")
private SceneInfo sceneInfo;
/**
* <pre>
* 字段名:结算信息
* 变量名:settle_info
* 是否必填:否
* 类型:Object
* 描述:结算信息
* </pre>
*/
@SerializedName(value = "settle_info")
private SettleInfo settleInfo;
@Data
@NoArgsConstructor
public static class Amount implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:总金额
* 变量名:total
* 是否必填:是
* 类型:int
* 描述:
* 订单总金额,单位为分。
* 示例值:100
* </pre>
*/
@SerializedName(value = "total")
private Integer total;
/**
* <pre>
* 字段名:币类型
* 变量名:currency
* 是否必填:否
* 类型:string[1,16]
* 描述:
* CNY:人民币,境内商户号仅支持人民币。
* 示例值:CNY
* </pre>
*/
@SerializedName(value = "currency")
private String currency;
}
@Data
@NoArgsConstructor
public static class Payer implements Serializable {
private static final long serialVersionUID = -1L;
/**
* <pre>
* 字段名:用户标识
* 变量名:openid
* 是否必填:是
* 类型:string[1,128]
* 描述:
* 用户在直连商户appid下的唯一标识。
* 示例值:oUpF8uMuAJO_M2pxb1Q9zNjWeS6o
* </pre>
*/
@SerializedName(value = "openid")
private String openid;
}
@Data
@NoArgsConstructor
public static class Discount implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:订单原价
* 变量名:cost_price
* 是否必填:否
* 类型:int
* 描述:
* 1、商户侧一张小票订单可能被分多次支付,订单原价用于记录整张小票的交易金额。
* 2、当订单原价与支付金额不相等,则不享受优惠。
* 3、该字段主要用于防止同一张小票分多次支付,以享受多次优惠的情况,正常支付订单不必上传此参数。
* 示例值:608800
* </pre>
*/
@SerializedName(value = "cost_price")
private Integer costPrice;
/**
* <pre>
* 字段名:商品小票ID
* 变量名:invoice_id
* 是否必填:否
* 类型:string[1,32]
* 描述:
* 商品小票ID
* 示例值:微信123
* </pre>
*/
@SerializedName(value = "invoice_id")
private String invoiceId;
/**
* <pre>
* 字段名:单品列表
* 变量名:goods_detail
* 是否必填:否
* 类型:array
* 描述:
* 单品列表信息
* 条目个数限制:【1,6000】
* </pre>
*/
@SerializedName(value = "goods_detail")
private List<GoodsDetail> goodsDetails;
}
@Data
@NoArgsConstructor
public static class GoodsDetail implements Serializable {
private static final long serialVersionUID = -1L;
/**
* <pre>
* 字段名:商户侧商品编码
* 变量名:merchant_goods_id
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 由半角的大小写字母、数字、中划线、下划线中的一种或几种组成。
* 示例值:商品编码
* </pre>
*/
@SerializedName(value = "merchant_goods_id")
private String merchantGoodsId;
/**
* <pre>
* 字段名:微信侧商品编码
* 变量名:wechatpay_goods_id
* 是否必填:否
* 类型:string[1,32]
* 描述:
* 微信支付定义的统一商品编号(没有可不传)
* 示例值:1001
* </pre>
*/
@SerializedName(value = "wechatpay_goods_id")
private String wechatpayGoodsId;
/**
* <pre>
* 字段名:商品名称
* 变量名:goods_name
* 是否必填:否
* 类型:string[1,256]
* 描述:
* 商品的实际名称
* 示例值:iPhoneX 256G
* </pre>
*/
@SerializedName(value = "goods_name")
private String goodsName;
/**
* <pre>
* 字段名:商品数量
* 变量名:quantity
* 是否必填:是
* 类型:int
* 描述:
* 用户购买的数量
* 示例值:1
* </pre>
*/
@SerializedName(value = "quantity")
private Integer quantity;
/**
* <pre>
* 字段名:商品单价
* 变量名:unit_price
* 是否必填:是
* 类型:int
* 描述:
* 商品单价,单位为分
* 示例值:828800
* </pre>
*/
@SerializedName(value = "unit_price")
private Integer unitPrice;
}
@Data
@NoArgsConstructor
public static class SceneInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:用户终端IP
* 变量名:payer_client_ip
* 是否必填:是
* 类型:string[1,45]
* 描述:
* 用户的客户端IP,支持IPv4和IPv6两种格式的IP地址。
* 示例值:14.23.150.211
* </pre>
*/
@SerializedName(value = "payer_client_ip")
private String payerClientIp;
/**
* <pre>
* 字段名:商户端设备号
* 变量名:device_id
* 是否必填:否
* 类型:string[1,32]
* 描述:
* 商户端设备号(门店号或收银设备ID)。
* 示例值:013467007045764
* </pre>
*/
@SerializedName(value = "device_id")
private String deviceId;
/**
* <pre>
* 字段名:商户门店信息
* 变量名:store_info
* 是否必填:否
* 类型:object
* 描述:
* 商户门店信息
* </pre>
*/
@SerializedName(value = "store_info")
private StoreInfo storeInfo;
/**
* <pre>
* 字段名:H5场景信息
* 变量名:h5_info
* 是否必填:否(H5支付必填)
* 类型:object
* 描述:
* H5场景信息
* </pre>
*/
@SerializedName(value = "h5_info")
private H5Info h5Info;
}
@Data
@NoArgsConstructor
public static class StoreInfo implements Serializable {
private static final long serialVersionUID = -1L;
/**
* <pre>
* 字段名:门店编号
* 变量名:id
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 商户侧门店编号
* 示例值:0001
* </pre>
*/
@SerializedName(value = "id")
private String id;
/**
* <pre>
* 字段名:门店名称
* 变量名:name
* 是否必填:否
* 类型:string[1,256]
* 描述:
* 商户侧门店名称
* 示例值:腾讯大厦分店
* </pre>
*/
@SerializedName(value = "name")
private String name;
/**
* <pre>
* 字段名:地区编码
* 变量名:area_code
* 是否必填:否
* 类型:string[1,32]
* 描述:
* 地区编码,详细请见省市区编号对照表(https://pay.weixin.qq.com/wiki/doc/apiv3/terms_definition/chapter1_1_3.shtml)。
* 示例值:440305
* </pre>
*/
@SerializedName(value = "area_code")
private String areaCode;
/**
* <pre>
* 字段名:详细地址
* 变量名:address
* 是否必填:是
* 类型:string[1,512]
* 描述:
* 详细的商户门店地址
* 示例值:广东省深圳市南山区科技中一道10000号
* </pre>
*/
@SerializedName(value = "address")
private String address;
}
@Data
@NoArgsConstructor
public static class H5Info implements Serializable {
private static final long serialVersionUID = -1L;
/**
* <pre>
* 字段名:场景类型
* 变量名:type
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 场景类型
* 示例值:iOS, Android, Wap
* </pre>
*/
@SerializedName(value = "type")
private String type;
/**
* <pre>
* 字段名:应用名称
* 变量名:app_name
* 是否必填:否
* 类型:string[1,64]
* 描述:
* 应用名称
* 示例值:王者荣耀
* </pre>
*/
@SerializedName(value = "app_name")
private String appName;
/**
* <pre>
* 字段名:网站URL
* 变量名:app_url
* 是否必填:否
* 类型:string[1,128]
* 描述:
* 网站URL
* 示例值:https://pay.qq.com
* </pre>
*/
@SerializedName(value = "app_url")
private String appUrl;
/**
* <pre>
* 字段名:iOS平台BundleID
* 变量名:bundle_id
* 是否必填:否
* 类型:string[1,128]
* 描述:
* iOS平台BundleID
* 示例值:com.tencent.wzryiOS
* </pre>
*/
@SerializedName(value = "bundle_id")
private String bundleId;
/**
* <pre>
* 字段名:Android平台PackageName
* 变量名:package_name
* 是否必填:否
* 类型:string[1,128]
* 描述:
* Android平台PackageName
* 示例值:com.tencent.tmgp.sgame
* </pre>
*/
@SerializedName(value = "package_name")
private String packageName;
}
@Data
@NoArgsConstructor
public static class SettleInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:是否指定分账
* 变量名:profit_sharing
* 是否必填:否
* 类型:boolean
* 描述:
* 是否指定分账
* 示例值:false
* </pre>
*/
@SerializedName(value = "profit_sharing")
private Boolean profitSharing;
}
}
@@ -0,0 +1,528 @@
package com.github.binarywang.wxpay.bean.result;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* <pre>
* 查询订单 返回结果对象
* </pre>
*
* @author thinsstar
*/
@Data
@NoArgsConstructor
public class WxPayOrderQueryV3Result implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:应用ID
* 变量名:appid
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 直连商户申请的公众号或移动应用appid。
* 示例值:wxd678efh567hg6787
* </pre>
*/
@SerializedName(value = "appid")
private String appid;
/**
* <pre>
* 字段名:直连商户号
* 变量名:mchid
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 直连商户的商户号,由微信支付生成并下发。
* 示例值:1230000109
* </pre>
*/
@SerializedName(value = "mchid")
private String mchid;
/**
* <pre>
* 字段名:商户订单号
* 变量名:out_trade_no
* 是否必填:是
* 类型:string[6,32]
* 描述:
* 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一,详见【商户订单号】。
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "out_trade_no")
private String outTradeNo;
/**
* <pre>
* 字段名:微信支付订单号
* 变量名:transaction_id
* 是否必填:否
* 类型:string[1,32]
* 描述:
* 微信支付系统生成的订单号。
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "transaction_id")
private String transactionId;
/**
* <pre>
* 字段名:交易类型
* 变量名:trade_type
* 是否必填:否
* 类型:string[1,16]
* 描述:
* 交易类型,枚举值:
* JSAPI:公众号支付
* NATIVE:扫码支付
* APP:APP支付
* MICROPAY:付款码支付
* MWEB:H5支付
* FACEPAY:刷脸支付
* 示例值:MICROPAY
* </pre>
*/
@SerializedName(value = "trade_type")
private String tradeType;
/**
* <pre>
* 字段名:交易状态
* 变量名:trade_state
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 交易状态,枚举值:
* SUCCESS:支付成功
* REFUND:转入退款
* NOTPAY:未支付
* CLOSED:已关闭
* REVOKED:已撤销(付款码支付)
* USERPAYING:用户支付中(付款码支付)
* PAYERROR:支付失败(其他原因,如银行返回失败)
* ACCEPT:已接收,等待扣款
* 示例值:SUCCESS
* </pre>
*/
@SerializedName(value = "trade_state")
private String tradeState;
/**
* <pre>
* 字段名:交易状态描述
* 变量名:trade_state_desc
* 是否必填:是
* 类型:string[1,256]
* 描述:
* 交易状态描述
* 示例值:支付成功
* </pre>
*/
@SerializedName(value = "trade_state_desc")
private String tradeStateDesc;
/**
* <pre>
* 字段名:付款银行
* 变量名:bank_type
* 是否必填:否
* 类型:string[1,16]
* 描述:
* 银行类型,采用字符串类型的银行标识。银行标识请参考《银行类型对照表》https://pay.weixin.qq.com/wiki/doc/apiv3/terms_definition/chapter1_1_3.shtml#part-6
* 示例值:CMC
* </pre>
*/
@SerializedName(value = "bank_type")
private String bankType;
/**
* <pre>
* 字段名:附加数据
* 变量名:attach
* 是否必填:否
* 类型:string[1,128]
* 描述:
* 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用
* 示例值:自定义数据
* </pre>
*/
@SerializedName(value = "attach")
private String attach;
/**
* <pre>
* 字段名:支付完成时间
* 变量名:success_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>
*/
@SerializedName(value = "success_time")
private String successTime;
/**
* <pre>
* 字段名:支付者
* 变量名:payer
* 是否必填:是
* 类型:object
* 描述:
* 支付者信息
* </pre>
*/
private Payer payer;
/**
* <pre>
* 字段名:订单金额
* 变量名:amount
* 是否必填:否
* 类型:object
* 描述:
* 订单金额信息,当支付成功时返回该字段。
* </pre>
*/
@SerializedName(value = "amount")
private Amount amount;
/**
* <pre>
* 字段名:场景信息
* 变量名:scene_info
* 是否必填:否
* 类型:object
* 描述:
* 支付场景描述
* </pre>
*/
@SerializedName(value = "scene_info")
private SceneInfo sceneInfo;
/**
* <pre>
* 字段名:优惠功能
* 变量名:promotion_detail
* 是否必填:否
* 类型:array
* 描述:
* 优惠功能,享受优惠时返回该字段。
* </pre>
*/
@SerializedName(value = "promotion_detail")
private List<PromotionDetail> promotionDetails;
@Data
@NoArgsConstructor
public static class Payer implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:用户标识
* 变量名:openid
* 是否必填:是
* 类型:string[1,128]
* 描述:
* 用户在直连商户appid下的唯一标识。
* 示例值:oUpF8uMuAJO_M2pxb1Q9zNjWeS6o
* </pre>
*/
@SerializedName(value = "openid")
private String openid;
}
@Data
@NoArgsConstructor
public static class Amount implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:总金额
* 变量名:total
* 是否必填:否
* 类型:int
* 描述:
* 订单总金额,单位为分。
* 示例值:100
* </pre>
*/
@SerializedName(value = "total")
private Integer total;
/**
* <pre>
* 字段名:用户支付金额
* 变量名:payer_total
* 是否必填:否
* 类型:int
* 描述:
* 用户支付金额,单位为分。
* 示例值:100
* </pre>
*/
@SerializedName(value = "payer_total")
private Integer payerTotal;
/**
* <pre>
* 字段名:货币类型
* 变量名:currency
* 是否必填:否
* 类型:string[1,16]
* 描述:
* CNY:人民币,境内商户号仅支持人民币。
* 示例值:CNY
* </pre>
*/
@SerializedName(value = "currency")
private String currency;
/**
* <pre>
* 字段名:用户支付币种
* 变量名:payer_currency
* 是否必填:否
* 类型:string[1,16]
* 描述:
* 用户支付币种
* 示例值: CNY
* </pre>
*/
@SerializedName(value = "payer_currency")
private String payerCurrency;
}
@Data
@NoArgsConstructor
public static class SceneInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:商户端设备号
* 变量名:device_id
* 是否必填:否
* 类型:string[1,32]
* 描述:
* 商户端设备号(发起扣款请求的商户服务器设备号)。
* 示例值:013467007045764
* </pre>
*/
@SerializedName(value = "device_id")
private String deviceId;
}
@Data
@NoArgsConstructor
public static class PromotionDetail implements Serializable {
/**
* <pre>
* 字段名:券ID
* 变量名:coupon_id
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 券ID
* 示例值:109519
* </pre>
*/
@SerializedName(value = "coupon_id")
private String couponId;
/**
* <pre>
* 字段名:优惠名称
* 变量名:name
* 是否必填:否
* 类型:string[1,64]
* 描述:
* 优惠名称
* 示例值:单品惠-6
* </pre>
*/
@SerializedName(value = "name")
private String name;
/**
* <pre>
* 字段名:优惠范围
* 变量名:scope
* 是否必填:否
* 类型:string[1,32]
* 描述:
* GLOBAL:全场代金券
* SINGLE:单品优惠
* 示例值:GLOBAL
* </pre>
*/
@SerializedName(value = "scope")
private String scope;
/**
* <pre>
* 字段名:优惠类型
* 变量名:type
* 是否必填:否
* 类型:string[1,32]
* 描述:
* CASH:充值
* NOCASH:预充值
* 示例值:CASH
* </pre>
*/
@SerializedName(value = "type")
private String type;
/**
* <pre>
* 字段名:优惠券面额
* 变量名:amount
* 是否必填:是
* 类型:int
* 描述:
* 优惠券面额
* 示例值:100
* </pre>
*/
@SerializedName(value = "amount")
private Integer amount;
/**
* <pre>
* 字段名:活动ID
* 变量名:stock_id
* 是否必填:否
* 类型:string[1,32]
* 描述:
* 活动ID
* 示例值:931386
* </pre>
*/
@SerializedName(value = "stock_id")
private String stockId;
/**
* <pre>
* 字段名:微信出资
* 变量名:wechatpay_contribute
* 是否必填:否
* 类型:int
* 描述:
* 微信出资,单位为分
* 示例值:0
* </pre>
*/
@SerializedName(value = "wechatpay_contribute")
private Integer wechatpayContribute;
/**
* <pre>
* 字段名:商户出资
* 变量名:merchant_contribute
* 是否必填:否
* 类型:int
* 描述:
* 商户出资,单位为分
* 示例值:0
* </pre>
*/
@SerializedName(value = "merchant_contribute")
private Integer merchantContribute;
/**
* <pre>
* 字段名:其他出资
* 变量名:other_contribute
* 是否必填:否
* 类型:int
* 描述:
* 其他出资,单位为分
* 示例值:0
* </pre>
*/
@SerializedName(value = "other_contribute")
private Integer otherContribute;
/**
* <pre>
* 字段名:优惠币种
* 变量名:currency
* 是否必填:否
* 类型:string[1,16]
* 描述:
* CNY:人民币,境内商户号仅支持人民币。
* 示例值:CNY
* </pre>
*/
@SerializedName(value = "currency")
private String currency;
/**
* <pre>
* 字段名:单品列表
* 变量名:goods_detail
* 是否必填:否
* 类型:array
* 描述:
* 单品列表信息
* </pre>
*/
@SerializedName(value = "goods_detail")
private List<GoodsDetail> goodsDetails;
}
@Data
@NoArgsConstructor
public static class GoodsDetail implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:商品编码
* 变量名:goods_id
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 商品编码
* 示例值:M1006
* </pre>
*/
@SerializedName(value = "goods_id")
private String goodsId;
/**
* <pre>
* 字段名:商品数量
* 变量名:quantity
* 是否必填:是
* 类型:int
* 描述:
* 用户购买的数量
* 示例值:1
* </pre>
*/
@SerializedName(value = "quantity")
private Integer quantity;
/**
* <pre>
* 字段名:商品单价
* 变量名:unit_price
* 是否必填:是
* 类型:int
* 描述:
* 商品单价,单位为分
* 示例值:100
* </pre>
*/
@SerializedName(value = "unit_price")
private Integer unitPrice;
/**
* <pre>
* 字段名:商品优惠金额
* 变量名:discount_amount
* 是否必填:是
* 类型:int
* 描述:
* 商品优惠金额
* 示例值:0
* </pre>
*/
@SerializedName(value = "discount_amount")
private Integer discountAmount;
/**
* <pre>
* 字段名:商品备注
* 变量名:goods_remark
* 是否必填:否
* 类型:string[1,128]
* 描述:
* 商品备注信息
* 示例值:商品备注信息
* </pre>
*/
@SerializedName(value = "goods_remark")
private String goodsRemark;
}
}
@@ -0,0 +1,473 @@
package com.github.binarywang.wxpay.bean.result;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* <pre>
* 微信支付-退款查询返回结果
* </pre>
*
* @author thinsstar
*/
@Data
@NoArgsConstructor
public class WxPayRefundQueryV3Result implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:微信支付退款号
* 变量名:refund_id
* 是否必填:是
* 类型:string[1, 32]
* 描述:
* 微信支付退款号。
* 示例值:50000000382019052709732678859
* </pre>
*/
@SerializedName(value = "refund_id")
private String refundId;
/**
* <pre>
* 字段名:商户退款单号
* 变量名:out_refund_no
* 是否必填:是
* 类型:string[1, 64]
* 描述:
* 商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔。
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "out_refund_no")
private String outRefundNo;
/**
* <pre>
* 字段名:微信支付订单号
* 变量名:transaction_id
* 是否必填:是
* 类型:string[1, 32]
* 描述:
* 微信支付交易订单号。
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "transaction_id")
private String transactionId;
/**
* <pre>
* 字段名:商户订单号
* 变量名:out_trade_no
* 是否必填:是
* 类型:string[1, 32]
* 描述:
* 原支付交易对应的商户订单号。
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "out_trade_no")
private String outTradeNo;
/**
* <pre>
* 字段名:退款渠道
* 变量名:channel
* 是否必填:否
* 类型:string[1, 16]
* 描述:
* 枚举值:
* ORIGINAL:原路退款
* BALANCE:退回到余额
* OTHER_BALANCE:原账户异常退到其他余额账户
* OTHER_BANKCARD:原银行卡异常退到其他银行卡
* 示例值:ORIGINAL
* </pre>
*/
@SerializedName(value = "channel")
private String channel;
/**
* <pre>
* 字段名:退款入账账户
* 变量名:user_received_account
* 是否必填:是
* 类型:string[1, 64]
* 描述:
* 取当前退款单的退款入账方,有以下几种情况:
* 1)退回银行卡:{银行名称}{卡类型}{卡尾号}
* 2)退回支付用户零钱:支付用户零钱
* 3)退还商户:商户基本账户商户结算银行账户
* 4)退回支付用户零钱通:支付用户零钱通。
* 示例值:招商银行信用卡0403
* </pre>
*/
@SerializedName(value = "user_received_account")
private String userReceivedAccount;
/**
* <pre>
* 字段名:退款成功时间
* 变量名:success_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秒。
* 示例值:2020-12-01T16:18:12+08:00
* </pre>
*/
@SerializedName(value = "success_time")
private String successTime;
/**
* <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秒。
* 示例值:2020-12-01T16:18:12+08:00
* </pre>
*/
@SerializedName(value = "create_time")
private String createTime;
/**
* <pre>
* 字段名:退款状态
* 变量名:status
* 是否必填:是
* 类型:string[1, 32]
* 描述:
* 退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往商户平台-交易中心,手动处理此笔退款。
* 枚举值:
* SUCCESS:退款成功
* CLOSED:退款关闭
* PROCESSING:退款处理中
* ABNORMAL:退款异常
* 示例值:SUCCESS
* </pre>
*/
@SerializedName(value = "status")
private String status;
/**
* <pre>
* 字段名:资金账户
* 变量名:funds_account
* 是否必填:否
* 类型:string[1, 32]
* 描述:
* 退款所使用资金对应的资金账户类型。 枚举值:
* UNSETTLED : 未结算资金
* AVAILABLE : 可用余额
* UNAVAILABLE : 不可用余额
* OPERATION : 运营户
* 示例值:UNSETTLED
* </pre>
*/
@SerializedName(value = "funds_account")
private String fundsAccount;
/**
* <pre>
* 字段名:金额信息
* 变量名:amount
* 是否必填:是
* 类型:object
* 描述:
* 金额详细信息。
* </pre>
*/
@SerializedName(value = "amount")
private Amount amount;
/**
* <pre>
* 字段名:优惠退款信息
* 变量名:promotion_detail
* 是否必填:否
* 类型:array
* 描述:
* 优惠退款信息。
* </pre>
*/
public List<PromotionDetail> promotionDetails;
@Data
@NoArgsConstructor
public static class Amount implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:订单金额
* 变量名:total
* 是否必填:是
* 类型:int
* 描述:
* 订单总金额,单位为分。
* 示例值:100
* </pre>
*/
@SerializedName(value = "total")
private Integer total;
/**
* <pre>
* 字段名:退款金额
* 变量名:refund
* 是否必填:是
* 类型:int
* 描述:
* 退款标价金额,单位为分,可以做部分退款。
* 示例值:100
* </pre>
*/
@SerializedName(value = "refund")
private Integer refund;
/**
* <pre>
* 字段名:用户支付金额
* 变量名:payer_total
* 是否必填:是
* 类型:int
* 描述:
* 现金支付金额,单位为分,只能为整数。
* 示例值:90
* </pre>
*/
@SerializedName(value = "payer_total")
private Integer payerTotal;
/**
* <pre>
* 字段名:用户退款金额
* 变量名:payer_refund
* 是否必填:是
* 类型:int
* 描述:
* 退款给用户的金额,不包含所有优惠券金额。
* 示例值:90
* </pre>
*/
@SerializedName(value = "payer_refund")
private Integer payerRefund;
/**
* <pre>
* 字段名:应结退款金额
* 变量名:settlement_refund
* 是否必填:是
* 类型:int
* 描述:
* 去掉非充值代金券退款金额后的退款金额,单位为分,退款金额=申请退款金额-非充值代金券退款金额,退款金额<=申请退款金额。
* 示例值:100
* </pre>
*/
@SerializedName(value = "settlement_refund")
private Integer settlementRefund;
/**
* <pre>
* 字段名:用户退款金额
* 变量名:settlement_total
* 是否必填:是
* 类型:int
* 描述:
* 应结订单金额=订单金额-免充值代金券金额,应结订单金额<=订单金额,单位为分。
* 示例值:100
* </pre>
*/
@SerializedName(value = "settlement_total")
private Integer settlementTotal;
/**
* <pre>
* 字段名:优惠退款金额
* 变量名:discount_refund
* 是否必填:否
* 类型:int64
* 描述:
* 优惠退款金额<=退款金额,退款金额-代金券或立减优惠退款金额为现金,说明详见代金券或立减优惠,单位为分。
* 示例值:10
* </pre>
*/
@SerializedName(value = "discount_refund")
private Integer discountRefund;
/**
* <pre>
* 字段名:币类型
* 变量名:currency
* 是否必填:否
* 类型:string[1, 16]
* 描述:
* 符合ISO 4217标准的三位字母代码,目前只支持人民币:CNY。
* 示例值:CNY
* </pre>
*/
@SerializedName(value = "currency")
private String currency;
}
@Data
@NoArgsConstructor
public static class PromotionDetail implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:券ID
* 变量名:promotion_id
* 是否必填:是
* 类型:string[1, 32]
* 描述:
* 券或者立减优惠id。
* 示例值:109519
* </pre>
*/
@SerializedName(value = "promotion_id")
private String promotionId;
/**
* <pre>
* 字段名:优惠范围
* 变量名:scope
* 是否必填:是
* 类型:string[1, 32]
* 描述:
* 枚举值:
* GLOBAL:全场代金券
* SINGLE:单品优惠
* 示例值:SINGLE
* </pre>
*/
@SerializedName(value = "scope")
private String scope;
/**
* <pre>
* 字段名:优惠类型
* 变量名:type
* 是否必填:是
* 类型:string[1, 32]
* 描述:
* 枚举值:
* COUPON:代金券,需要走结算资金的充值型代金券
* DISCOUNT:优惠券,不走结算资金的免充值型优惠券
* 示例值:DISCOUNT
* </pre>
*/
@SerializedName(value = "type")
private String type;
/**
* <pre>
* 字段名:优惠券面额
* 变量名:amount
* 是否必填:是
* 类型:int
* 描述:
* 用户享受优惠的金额(优惠券面额=微信出资金额+商家出资金额+其他出资方金额 ),单位为分。
* 示例值:5
* </pre>
*/
@SerializedName(value = "amount")
private Integer amount;
/**
* <pre>
* 字段名:优惠退款金额
* 变量名:refund_amount
* 是否必填:是
* 类型:int
* 描述:
* 优惠退款金额<=退款金额,退款金额-代金券或立减优惠退款金额为用户支付的现金,说明详见代金券或立减优惠,单位为分。
* 示例值:100
* </pre>
*/
@SerializedName(value = "refund_amount")
private Integer refundAmount;
/**
* <pre>
* 字段名:商品列表
* 变量名:goods_detail
* 是否必填:否
* 类型:array
* 描述:
* 优惠商品发生退款时返回商品信息。
* </pre>
*/
@SerializedName(value = "goods_detail")
private List<GoodsDetail> goodsDetails;
}
@Data
@NoArgsConstructor
public static class GoodsDetail implements Serializable {
private static final long serialVersionUID = -1L;
/**
* <pre>
* 字段名:商户侧商品编码
* 变量名:merchant_goods_id
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 由半角的大小写字母、数字、中划线、下划线中的一种或几种组成。
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "merchant_goods_id")
private String merchantGoodsId;
/**
* <pre>
* 字段名:微信侧商品编码
* 变量名:wechatpay_goods_id
* 是否必填:否
* 类型:string[1,32]
* 描述:
* 微信支付定义的统一商品编号(没有可不传)。
* 示例值:1001
* </pre>
*/
@SerializedName(value = "wechatpay_goods_id")
private String wechatpayGoodsId;
/**
* <pre>
* 字段名:商品名称
* 变量名:goods_name
* 是否必填:否
* 类型:string[1,256]
* 描述:
* 商品的实际名称。
* 示例值:iPhone6s 16G
* </pre>
*/
@SerializedName(value = "goods_name")
private String goodsName;
/**
* <pre>
* 字段名:商品单价
* 变量名:unit_price
* 是否必填:是
* 类型:int
* 描述:
* 商品单价金额,单位为分。
* 示例值:528800
* </pre>
*/
@SerializedName(value = "unit_price")
private Integer unitPrice;
/**
* <pre>
* 字段名:商品退款金额
* 变量名:refund_amount
* 是否必填:是
* 类型:int
* 描述:
* 商品退款金额,单位为分。
* 示例值:528800
* </pre>
*/
@SerializedName(value = "refund_amount")
private Integer refundAmount;
/**
* <pre>
* 字段名:商品退货数量
* 变量名:refund_quantity
* 是否必填:是
* 类型:int
* 描述:
* 单品的退款数量。
* 示例值:1
* </pre>
*/
@SerializedName(value = "refund_quantity")
private Integer refundQuantity;
}
}
@@ -0,0 +1,474 @@
package com.github.binarywang.wxpay.bean.result;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
* <pre>
* 微信支付-申请退款返回结果.
* https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_9.shtml
* </pre>
*
* @author thinsstar
*/
@Data
@NoArgsConstructor
public class WxPayRefundV3Result implements Serializable {
private static final long serialVersionUID = -1L;
/**
* <pre>
* 字段名:微信退款单号
* 变量名:refund_id
* 是否必填:是
* 类型:string[1, 32]
* 描述:
* 微信支付退款号。
* 示例值:50000000382019052709732678859
* </pre>
*/
@SerializedName(value = "refund_id")
private String refundId;
/**
* <pre>
* 字段名:商户退款单号
* 变量名:out_refund_no
* 是否必填:是
* 类型:string[1, 64]
* 描述:
* 商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔。
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "out_refund_no")
private String outRefundNo;
/**
* <pre>
* 字段名:微信支付订单号
* 变量名:transaction_id
* 是否必填:是
* 类型:string[1, 32]
* 描述:
* 微信支付交易订单号。
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "transaction_id")
private String transactionId;
/**
* <pre>
* 字段名:商户订单号
* 变量名:out_trade_no
* 是否必填:是
* 类型:string[1, 32]
* 描述:
* 原支付交易对应的商户订单号。
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "out_trade_no")
private String outTradeNo;
/**
* <pre>
* 字段名:退款渠道
* 变量名:channel
* 是否必填:是
* 类型:string[1, 32]
* 描述:
* 枚举值:
* ORIGINAL:原路退款
* BALANCE:退回到余额
* OTHER_BALANCE:原账户异常退到其他余额账户
* OTHER_BANKCARD:原银行卡异常退到其他银行卡
* 示例值:ORIGINAL
* </pre>
*/
@SerializedName(value = "channel")
private String channel;
/**
* <pre>
* 字段名:退款入账账户
* 变量名:user_received_account
* 是否必填:是
* 类型:string[1, 64]
* 描述:
* 取当前退款单的退款入账方,有以下几种情况:
* 1)退回银行卡:{银行名称}{卡类型}{卡尾号}
* 2)退回支付用户零钱:支付用户零钱
* 3)退还商户:商户基本账户商户结算银行账户
* 4)退回支付用户零钱通:支付用户零钱通。
* 示例值:招商银行信用卡0403
* </pre>
*/
@SerializedName(value = "user_received_account")
private String userReceivedAccount;
/**
* <pre>
* 字段名:退款成功时间
* 变量名:success_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秒。
* 示例值:2020-12-01T16:18:12+08:00
* </pre>
*/
@SerializedName(value = "success_time")
private String successTime;
/**
* <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秒。
* 示例值:2020-12-01T16:18:12+08:00
* </pre>
*/
@SerializedName(value = "create_time")
private String createTime;
/**
* <pre>
* 字段名:退款状态
* 变量名:status
* 是否必填:是
* 类型:string[1, 32]
* 描述:
* 退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往商户平台-交易中心,手动处理此笔退款。
* 枚举值:
* SUCCESS:退款成功
* CLOSED:退款关闭
* PROCESSING:退款处理中
* ABNORMAL:退款异常
* 示例值:SUCCESS
* </pre>
*/
@SerializedName(value = "status")
private String status;
/**
* <pre>
* 字段名:资金账户
* 变量名:funds_account
* 是否必填:是
* 类型:string[1, 32]
* 描述:
* 退款所使用资金对应的资金账户类型。 枚举值:
* UNSETTLED : 未结算资金
* AVAILABLE : 可用余额
* UNAVAILABLE : 不可用余额
* OPERATION : 运营户
* 示例值:UNSETTLED
* </pre>
*/
@SerializedName(value = "funds_account")
private String fundsAccount;
/**
* <pre>
* 字段名:金额信息
* 变量名:amount
* 是否必填:是
* 类型:object
* 描述:
* 金额详细信息。
* </pre>
*/
@SerializedName(value = "amount")
private Amount amount;
/**
* <pre>
* 字段名:优惠退款信息
* 变量名:promotion_detail
* 是否必填:否
* 类型:array
* 描述:
* 优惠退款信息。
* </pre>
*/
@SerializedName(value = "promotion_detail")
private List<PromotionDetail> promotionDetail;
@Data
@NoArgsConstructor
public static class Amount implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:订单金额
* 变量名:total
* 是否必填:是
* 类型:int
* 描述:
* 订单总金额,单位为分。
* 示例值:100
* </pre>
*/
@SerializedName(value = "total")
private Integer total;
/**
* <pre>
* 字段名:退款金额
* 变量名:refund
* 是否必填:是
* 类型:int
* 描述:
* 退款标价金额,单位为分,可以做部分退款。
* 示例值:100
* </pre>
*/
@SerializedName(value = "refund")
private Integer refund;
/**
* <pre>
* 字段名:用户支付金额
* 变量名:payer_total
* 是否必填:是
* 类型:int
* 描述:
* 现金支付金额,单位为分,只能为整数。
* 示例值:90
* </pre>
*/
@SerializedName(value = "payer_total")
private Integer payerTotal;
/**
* <pre>
* 字段名:用户退款金额
* 变量名:payer_refund
* 是否必填:是
* 类型:int
* 描述:
* 退款给用户的金额,不包含所有优惠券金额。
* 示例值:90
* </pre>
*/
@SerializedName(value = "payer_refund")
private Integer payerRefund;
/**
* <pre>
* 字段名:应结退款金额
* 变量名:settlement_refund
* 是否必填:是
* 类型:int
* 描述:
* 去掉非充值代金券退款金额后的退款金额,单位为分,退款金额=申请退款金额-非充值代金券退款金额,退款金额<=申请退款金额。
* 示例值:100
* </pre>
*/
@SerializedName(value = "settlement_refund")
private Integer settlementRefund;
/**
* <pre>
* 字段名:用户退款金额
* 变量名:settlement_total
* 是否必填:是
* 类型:int
* 描述:
* 应结订单金额=订单金额-免充值代金券金额,应结订单金额<=订单金额,单位为分。
* 示例值:100
* </pre>
*/
@SerializedName(value = "settlement_total")
private Integer settlementTotal;
/**
* <pre>
* 字段名:优惠退款金额
* 变量名:discount_refund
* 是否必填:否
* 类型:int64
* 描述:
* 优惠退款金额<=退款金额,退款金额-代金券或立减优惠退款金额为现金,说明详见代金券或立减优惠,单位为分。
* 示例值:10
* </pre>
*/
@SerializedName(value = "discount_refund")
private Integer discountRefund;
/**
* <pre>
* 字段名:币类型
* 变量名:currency
* 是否必填:否
* 类型:string[1, 16]
* 描述:
* 符合ISO 4217标准的三位字母代码,目前只支持人民币:CNY。
* 示例值:CNY
* </pre>
*/
@SerializedName(value = "currency")
private String currency;
}
@Data
@NoArgsConstructor
public static class PromotionDetail implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:券ID
* 变量名:promotion_id
* 是否必填:是
* 类型:string[1, 32]
* 描述:
* 券或者立减优惠id。
* 示例值:109519
* </pre>
*/
@SerializedName(value = "promotion_id")
private String promotionId;
/**
* <pre>
* 字段名:优惠范围
* 变量名:scope
* 是否必填:是
* 类型:string[1, 32]
* 描述:
* 枚举值:
* GLOBAL:全场代金券
* SINGLE:单品优惠
* 示例值:SINGLE
* </pre>
*/
@SerializedName(value = "scope")
private String scope;
/**
* <pre>
* 字段名:优惠类型
* 变量名:type
* 是否必填:是
* 类型:string[1, 32]
* 描述:
* 枚举值:
* COUPON:代金券,需要走结算资金的充值型代金券
* DISCOUNT:优惠券,不走结算资金的免充值型优惠券
* 示例值:DISCOUNT
* </pre>
*/
@SerializedName(value = "type")
private String type;
/**
* <pre>
* 字段名:优惠券面额
* 变量名:amount
* 是否必填:是
* 类型:int
* 描述:
* 用户享受优惠的金额(优惠券面额=微信出资金额+商家出资金额+其他出资方金额 ),单位为分。
* 示例值:5
* </pre>
*/
@SerializedName(value = "amount")
private Integer amount;
/**
* <pre>
* 字段名:优惠退款金额
* 变量名:refund_amount
* 是否必填:是
* 类型:int
* 描述:
* 优惠退款金额<=退款金额,退款金额-代金券或立减优惠退款金额为用户支付的现金,说明详见代金券或立减优惠,单位为分。
* 示例值:100
* </pre>
*/
@SerializedName(value = "refund_amount")
private Integer refundAmount;
/**
* <pre>
* 字段名:商品列表
* 变量名:goods_detail
* 是否必填:否
* 类型:array
* 描述:
* 优惠商品发生退款时返回商品信息。
* </pre>
*/
@SerializedName(value = "goods_detail")
private List<GoodsDetail> goodsDetails;
}
@Data
@NoArgsConstructor
public static class GoodsDetail implements Serializable {
private static final long serialVersionUID = -1L;
/**
* <pre>
* 字段名:商户侧商品编码
* 变量名:merchant_goods_id
* 是否必填:是
* 类型:string[1,32]
* 描述:
* 由半角的大小写字母、数字、中划线、下划线中的一种或几种组成。
* 示例值:1217752501201407033233368018
* </pre>
*/
@SerializedName(value = "merchant_goods_id")
private String merchantGoodsId;
/**
* <pre>
* 字段名:微信侧商品编码
* 变量名:wechatpay_goods_id
* 是否必填:否
* 类型:string[1,32]
* 描述:
* 微信支付定义的统一商品编号(没有可不传)。
* 示例值:1001
* </pre>
*/
@SerializedName(value = "wechatpay_goods_id")
private String wechatpayGoodsId;
/**
* <pre>
* 字段名:商品名称
* 变量名:goods_name
* 是否必填:否
* 类型:string[1,256]
* 描述:
* 商品的实际名称。
* 示例值:iPhone6s 16G
* </pre>
*/
@SerializedName(value = "goods_name")
private String goodsName;
/**
* <pre>
* 字段名:商品单价
* 变量名:unit_price
* 是否必填:是
* 类型:int
* 描述:
* 商品单价金额,单位为分。
* 示例值:528800
* </pre>
*/
@SerializedName(value = "unit_price")
private Integer unitPrice;
/**
* <pre>
* 字段名:商品退款金额
* 变量名:refund_amount
* 是否必填:是
* 类型:int
* 描述:
* 商品退款金额,单位为分。
* 示例值:528800
* </pre>
*/
@SerializedName(value = "refund_amount")
private Integer refundAmount;
/**
* <pre>
* 字段名:商品退货数量
* 变量名:refund_quantity
* 是否必填:是
* 类型:int
* 描述:
* 单品的退款数量。
* 示例值:1
* </pre>
*/
@SerializedName(value = "refund_quantity")
private Integer refundQuantity;
}
}
@@ -0,0 +1,124 @@
package com.github.binarywang.wxpay.bean.result;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.v3.util.SignUtils;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.security.PrivateKey;
/**
* <pre>
* 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识"返回的结果
* 参考文档:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml
* https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_1.shtml
* https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_1.shtml
* https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_1.shtml
* https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_1.shtml
* </pre>
*
* @author thinsstar
*/
@Data
@NoArgsConstructor
public class WxPayUnifiedOrderV3Result implements Serializable {
private static final long serialVersionUID = 1L;
/**
* <pre>
* 字段名:预支付交易会话标识(APP支付、JSAPI支付 会返回)
* 变量名:prepay_id
* 是否必填:是
* 类型:string[1,64]
* 描述:
* 预支付交易会话标识。用于后续接口调用中使用,该值有效期为2小时
* 示例值:wx201410272009395522657a690389285100
* </pre>
*/
@SerializedName("prepay_id")
private String prepayId;
/**
* <pre>
* 字段名:支付跳转链接(H5支付 会返回)
* 变量名:h5_url
* 是否必填:是
* 类型:string[1,512]
* 描述:
* h5_url为拉起微信支付收银台的中间页面,可通过访问该url来拉起微信客户端,完成支付,h5_url的有效期为5分钟。
* 示例值:https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id=wx2016121516420242444321ca0631331346&package=1405458241
* </pre>
*/
@SerializedName("h5_url")
private String h5Url;
/**
* <pre>
* 字段名:二维码链接(NATIVE支付 会返回)
* 变量名:h5_url
* 是否必填:是
* 类型:string[1,512]
* 描述:
* 此URL用于生成支付二维码,然后提供给用户扫码支付。
* 注意:code_url并非固定值,使用时按照URL格式转成二维码即可。
* 示例值:weixin://wxpay/bizpayurl/up?pr=NwY5Mz9&groupid=00
* </pre>
*/
@SerializedName("code_url")
private String codeUrl;
@Data
@Accessors(chain = true)
public static class JsapiResult implements Serializable {
private String appId;
private String timeStamp;
private String nonceStr;
private String packageValue;
private String signType;
private String paySign;
private String getSignStr() {
return String.format("%s\n%s\n%s\n%s\n", appId, timeStamp, nonceStr, packageValue);
}
}
@Data
@Accessors(chain = true)
public static class AppResult implements Serializable {
private String appid;
private String partnerid;
private String prepayid;
private String packageValue;
private String noncestr;
private String timestamp;
}
public <T> T getPayInfo(TradeTypeEnum tradeType, String appId, String mchId, PrivateKey privateKey) {
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
String nonceStr = SignUtils.genRandomStr();
switch (tradeType) {
case JSAPI:
JsapiResult jsapiResult = new JsapiResult();
jsapiResult.setAppId(appId).setTimeStamp(timestamp)
.setPackageValue("prepay_id=" + this.prepayId).setNonceStr(nonceStr)
//签名类型,默认为RSA,仅支持RSA。
.setSignType("RSA").setPaySign(SignUtils.sign(jsapiResult.getSignStr(), privateKey));
return (T) jsapiResult;
case H5:
return (T) this.h5Url;
case APP:
AppResult appResult = new AppResult();
appResult.setAppid(appId).setPrepayid(this.prepayId).setPartnerid(mchId)
.setNoncestr(nonceStr).setTimestamp(timestamp)
//暂填写固定值Sign=WXPay
.setPackageValue("Sign=WXPay");
return (T) appResult;
case NATIVE:
return (T) this.codeUrl;
}
return null;
}
}
@@ -0,0 +1,33 @@
package com.github.binarywang.wxpay.bean.result.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 支付方式
*/
@Getter
@AllArgsConstructor
public enum TradeTypeEnum {
/**
* APP
*/
APP("/v3/pay/transactions/app"),
/**
* JSAPI 或 小程序
*/
JSAPI("/v3/pay/transactions/jsapi"),
/**
* NATIVE
*/
NATIVE("/v3/pay/transactions/native"),
/**
* H5
*/
H5("/v3/pay/transactions/h5");
/**
* 单独下单url
*/
private final String partnerUrl;
}
@@ -0,0 +1,24 @@
package com.github.binarywang.wxpay.service;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
import com.github.binarywang.wxpay.exception.WxPayException;
/**
* <pre>
* 微信基础支付v3相关服务类.
* </pre>
*
* @author thinsstar
*/
public interface BasePayV3Service {
/**
* 调用统一下单接口,并组装生成支付所需参数对象.
*
* @param <T> 请使用{@link com.github.binarywang.wxpay.bean.order}包下的类
* @param request 统一下单请求参数
* @return 返回 {@link com.github.binarywang.wxpay.bean.order}包下的类对象
* @throws WxPayException the wx pay exception
*/
<T> T createOrder(WxPayUnifiedOrderV3Request request) throws WxPayException;
}
@@ -2,11 +2,10 @@ package com.github.binarywang.wxpay.service;
import com.github.binarywang.wxpay.bean.WxPayApiData;
import com.github.binarywang.wxpay.bean.coupon.*;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxScanPayNotifyResult;
import com.github.binarywang.wxpay.bean.notify.*;
import com.github.binarywang.wxpay.bean.request.*;
import com.github.binarywang.wxpay.bean.result.*;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
@@ -291,6 +290,53 @@ public interface WxPayService {
*/
WxPayOrderQueryResult queryOrder(WxPayOrderQueryRequest request) throws WxPayException;
/**
* <pre>
* 查询订单
* 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_2.shtml
* 商户可以通过查询订单接口主动查询订单状态,完成下一步的业务逻辑。查询订单状态可通过微信支付订单号或商户订单号两种方式查询
* 注意:
* 查询订单可通过微信支付订单号和商户订单号两种方式查询,两种查询方式返回结果相同
* 需要调用查询接口的情况:
* ◆ 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知。
* ◆ 调用支付接口后,返回系统错误或未知交易状态情况。
* ◆ 调用付款码支付API,返回USERPAYING的状态。
* ◆ 调用关单或撤销接口API之前,需确认支付状态。
* 接口地址:
* https://api.mch.weixin.qq.com/v3/pay/transactions/id/{transaction_id}
* https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{out_trade_no}
* </pre>
*
* @param transactionId 微信订单号
* @param outTradeNo 商户系统内部的订单号,当没提供transactionId时需要传这个。
* @return the wx pay order query result
* @throws WxPayException the wx pay exception
*/
WxPayOrderQueryV3Result queryOrderV3(String transactionId, String outTradeNo) throws WxPayException;
/**
* <pre>
* 查询订单
* 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_2.shtml
* 商户可以通过查询订单接口主动查询订单状态,完成下一步的业务逻辑。查询订单状态可通过微信支付订单号或商户订单号两种方式查询
* 注意:
* 查询订单可通过微信支付订单号和商户订单号两种方式查询,两种查询方式返回结果相同
* 需要调用查询接口的情况:
* ◆ 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知。
* ◆ 调用支付接口后,返回系统错误或未知交易状态情况。
* ◆ 调用付款码支付API,返回USERPAYING的状态。
* ◆ 调用关单或撤销接口API之前,需确认支付状态。
* 接口地址:
* https://api.mch.weixin.qq.com/v3/pay/transactions/id/{transaction_id}
* https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{out_trade_no}
* </pre>
*
* @param request 查询订单请求对象
* @return the wx pay order query result
* @throws WxPayException the wx pay exception
*/
WxPayOrderQueryV3Result queryOrderV3(WxPayOrderQueryV3Request request) throws WxPayException;
/**
* <pre>
* 关闭订单.
@@ -327,6 +373,40 @@ public interface WxPayService {
*/
WxPayOrderCloseResult closeOrder(WxPayOrderCloseRequest request) throws WxPayException;
/**
* <pre>
* 关闭订单
* 应用场景
* 以下情况需要调用关单接口:
* 1、商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;
* 2、系统下单后,用户支付超时,系统退出不再受理,避免用户继续,请调用关单接口。
* 注意:关单没有时间限制,建议在订单生成后间隔几分钟(最短5分钟)再调用关单接口,避免出现订单状态同步不及时导致关单失败。
* 接口地址:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_3.shtml
* </pre>
*
* @param outTradeNo 商户系统内部的订单号
* @return the wx pay order close result
* @throws WxPayException the wx pay exception
*/
void closeOrderV3(String outTradeNo) throws WxPayException;
/**
* <pre>
* 关闭订单
* 应用场景
* 以下情况需要调用关单接口:
* 1、商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;
* 2、系统下单后,用户支付超时,系统退出不再受理,避免用户继续,请调用关单接口。
* 注意:关单没有时间限制,建议在订单生成后间隔几分钟(最短5分钟)再调用关单接口,避免出现订单状态同步不及时导致关单失败。
* 接口地址:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_3.shtml
* </pre>
*
* @param request 关闭订单请求对象
* @return the wx pay order close result
* @throws WxPayException the wx pay exception
*/
void closeOrderV3(WxPayOrderCloseV3Request request) throws WxPayException;
/**
* 调用统一下单接口,并组装生成支付所需参数对象.
*
@@ -360,6 +440,25 @@ public interface WxPayService {
*/
WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) throws WxPayException;
/**
* 调用统一下单接口,并组装生成支付所需参数对象.
*
* @param <T> 请使用{@link com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result}里的内部类或字段
* @param request 统一下单请求参数
* @return 返回 {@link com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result}里的内部类或字段
* @throws WxPayException the wx pay exception
*/
<T> T createOrderV3(TradeTypeEnum tradeType, WxPayUnifiedOrderV3Request request) throws WxPayException;
/**
* 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识"
*
* @param request 请求对象,注意一些参数如appid、mchid等不用设置,方法内会自动从配置对象中获取到(前提是对应配置中已经设置)
* @return the wx pay unified order result
* @throws WxPayException the wx pay exception
*/
WxPayUnifiedOrderV3Result unifiedOrderV3(TradeTypeEnum tradeType, WxPayUnifiedOrderV3Request request) throws WxPayException;
/**
* 该接口调用“统一下单”接口,并拼装发起支付请求需要的参数.
* 详见https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5
@@ -426,6 +525,33 @@ public interface WxPayService {
*/
WxPayRefundResult refundV2(WxPayRefundRequest request) throws WxPayException;
/**
* <pre>
* 申请退款API(支持单品).
* 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_9.shtml
*
* 应用场景
* 当交易发生之后一年内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付金额退还给买家,微信支付将在收到退款请求并且验证成功之后,将支付款按原路退还至买家账号上。
*
* 注意:
* 1、交易时间超过一年的订单无法提交退款
* 2、微信支付退款支持单笔交易分多次退款(不超50次),多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。申请退款总金额不能超过订单金额。 一笔退款失败后重新提交,请不要更换退款单号,请使用原商户退款单号
* 3、错误或无效请求频率限制:6qps,即每秒钟异常或错误的退款申请请求不超过6次
* 4、每个支付订单的部分退款次数不能超过50次
* 5、如果同一个用户有多笔退款,建议分不同批次进行退款,避免并发退款导致退款失败
* 6、申请退款接口的返回仅代表业务的受理情况,具体退款是否成功,需要通过退款查询接口获取结果
* 7、一个月之前的订单申请退款频率限制为:5000/min
*
* 接口地址
* https://api.mch.weixin.qq.com/v3/refund/domestic/refunds
* </pre>
*
* @param request 请求对象
* @return 退款操作结果 wx pay refund result
* @throws WxPayException the wx pay exception
*/
WxPayRefundV3Result refundV3(WxPayRefundV3Request request) throws WxPayException;
/**
* <pre>
* 微信支付-查询退款.
@@ -486,6 +612,36 @@ public interface WxPayService {
*/
WxPayRefundQueryResult refundQueryV2(WxPayRefundQueryRequest request) throws WxPayException;
/**
* <pre>
* 微信支付-查询退款
* 应用场景:
* 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,建议在提交退款申请后1分钟发起查询退款状态,一般来说零钱支付的退款5分钟内到账,银行卡支付的退款1-3个工作日到账。
* 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_10.shtml
* 接口链接:https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/{out_refund_no}
* </pre>
*
* @param outTradeNo 商户订单号
* @return 退款信息 wx pay refund query result
* @throws WxPayException the wx pay exception
*/
WxPayRefundQueryV3Result refundQueryV3(String outTradeNo) throws WxPayException;
/**
* <pre>
* 微信支付-查询退款
* 应用场景:
* 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,建议在提交退款申请后1分钟发起查询退款状态,一般来说零钱支付的退款5分钟内到账,银行卡支付的退款1-3个工作日到账。
* 详见 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_10.shtml
* 接口链接:https://api.mch.weixin.qq.com/v3/refund/domestic/refunds/{out_refund_no}
* </pre>
*
* @param request 微信退款单号
* @return 退款信息 wx pay refund query result
* @throws WxPayException the wx pay exception
*/
WxPayRefundQueryV3Result refundQueryV3(WxPayRefundQueryV3Request request) throws WxPayException;
/**
* 解析支付结果通知.
* 详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
@@ -507,6 +663,17 @@ public interface WxPayService {
*/
WxPayOrderNotifyResult parseOrderNotifyResult(String xmlData, String signType) throws WxPayException;
/**
* 解析支付结果v3通知.
* 详见https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_5.shtml
*
* @param notifyData 通知数据
* @param header 通知头部数据,不传则表示不校验头
* @return the wx pay order notify result
* @throws WxPayException the wx pay exception
*/
WxPayOrderNotifyV3Result parseOrderNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException;
/**
* 解析退款结果通知
* 详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_16&index=9
@@ -517,6 +684,17 @@ public interface WxPayService {
*/
WxPayRefundNotifyResult parseRefundNotifyResult(String xmlData) throws WxPayException;
/**
* 解析退款结果通知
* 详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_16&index=9
*
* @param notifyData 通知数据
* @param header 通知头部数据,不传则表示不校验头
* @return the wx pay refund notify result
* @throws WxPayException the wx pay exception
*/
WxPayRefundNotifyV3Result parseRefundNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException;
/**
* 解析扫码支付回调通知
* 详见https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4
@@ -3,15 +3,14 @@ package com.github.binarywang.wxpay.service.impl;
import com.github.binarywang.utils.qrcode.QrcodeUtils;
import com.github.binarywang.wxpay.bean.WxPayApiData;
import com.github.binarywang.wxpay.bean.coupon.*;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxScanPayNotifyResult;
import com.github.binarywang.wxpay.bean.notify.*;
import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayMwebOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayNativeOrderResult;
import com.github.binarywang.wxpay.bean.request.*;
import com.github.binarywang.wxpay.bean.result.*;
import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.config.WxPayConfigHolder;
import com.github.binarywang.wxpay.constant.WxPayConstants;
@@ -21,9 +20,12 @@ import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.*;
import com.github.binarywang.wxpay.util.SignUtils;
import com.github.binarywang.wxpay.util.XmlConfig;
import com.github.binarywang.wxpay.v3.util.AesUtils;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import jodd.io.ZipUtil;
import me.chanjar.weixin.common.error.WxRuntimeException;
import org.apache.commons.lang3.StringUtils;
@@ -31,10 +33,12 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.GeneralSecurityException;
import java.util.*;
import java.util.zip.ZipException;
@@ -52,6 +56,7 @@ import static com.github.binarywang.wxpay.constant.WxPayConstants.TarType;
public abstract class BaseWxPayServiceImpl implements WxPayService {
private static final String TOTAL_FUND_COUNT = "资金流水总笔数";
private static final Gson GSON = new GsonBuilder().create();
final Logger log = LoggerFactory.getLogger(this.getClass());
@@ -242,6 +247,13 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
return result;
}
@Override
public WxPayRefundV3Result refundV3(WxPayRefundV3Request request) throws WxPayException {
String url = String.format("%s/v3/refund/domestic/refunds", this.getPayBaseUrl());
String response = this.postV3(url, GSON.toJson(request));
return GSON.fromJson(response, WxPayRefundV3Result.class);
}
@Override
public WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, String outRefundNo, String refundId)
throws WxPayException {
@@ -278,6 +290,20 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
return result;
}
@Override
public WxPayRefundQueryV3Result refundQueryV3(String outTradeNo) throws WxPayException {
String url = String.format("%s/v3/refund/domestic/refunds/%s", this.getPayBaseUrl(), outTradeNo);
String response = this.getV3(url);
return GSON.fromJson(response, WxPayRefundQueryV3Result.class);
}
@Override
public WxPayRefundQueryV3Result refundQueryV3(WxPayRefundQueryV3Request request) throws WxPayException {
String url = String.format("%s/v3/refund/domestic/refunds/%s", this.getPayBaseUrl(), request.getOutTradeNo());
String response = this.getV3(url);
return GSON.fromJson(response, WxPayRefundQueryV3Result.class);
}
@Override
public WxPayOrderNotifyResult parseOrderNotifyResult(String xmlData) throws WxPayException {
return this.parseOrderNotifyResult(xmlData, null);
@@ -308,6 +334,44 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
}
}
/**
* 校验通知签名
* @param header 通知头信息
* @param data 通知数据
* @return true:校验通过 false:校验不通过
*/
private boolean verifyNotifySign(SignatureHeader header, String data) {
String beforeSign = String.format("%s\n%s\n%s\n",
header.getTimeStamp(),
header.getNonce(),
data);
return this.getConfig().getVerifier().verify(header.getSerial(),
beforeSign.getBytes(StandardCharsets.UTF_8), header.getSignature());
}
@Override
public WxPayOrderNotifyV3Result parseOrderNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException {
if (Objects.nonNull(header) && !this.verifyNotifySign(header, notifyData)) {
throw new WxPayException("非法请求,头部信息验证失败");
}
OriginNotifyResponse response = GSON.fromJson(notifyData, OriginNotifyResponse.class);
OriginNotifyResponse.Resource resource = response.getResource();
String cipherText = resource.getCiphertext();
String associatedData = resource.getAssociatedData();
String nonce = resource.getNonce();
String apiV3Key = this.getConfig().getApiV3Key();
try {
String result = AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key);
WxPayOrderNotifyV3Result.DecryptNotifyResult decryptNotifyResult = GSON.fromJson(result, WxPayOrderNotifyV3Result.DecryptNotifyResult.class);
WxPayOrderNotifyV3Result notifyResult = new WxPayOrderNotifyV3Result();
notifyResult.setRawData(response);
notifyResult.setResult(decryptNotifyResult);
return notifyResult;
} catch (GeneralSecurityException | IOException e) {
throw new WxPayException("解析报文异常!", e);
}
}
@Override
public WxPayRefundNotifyResult parseRefundNotifyResult(String xmlData) throws WxPayException {
try {
@@ -326,6 +390,29 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
}
}
@Override
public WxPayRefundNotifyV3Result parseRefundNotifyV3Result(String notifyData, SignatureHeader header) throws WxPayException {
if (Objects.nonNull(header) && !this.verifyNotifySign(header, notifyData)) {
throw new WxPayException("非法请求,头部信息验证失败");
}
OriginNotifyResponse response = GSON.fromJson(notifyData, OriginNotifyResponse.class);
OriginNotifyResponse.Resource resource = response.getResource();
String cipherText = resource.getCiphertext();
String associatedData = resource.getAssociatedData();
String nonce = resource.getNonce();
String apiV3Key = this.getConfig().getApiV3Key();
try {
String result = AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key);
WxPayRefundNotifyV3Result.DecryptNotifyResult decryptNotifyResult = GSON.fromJson(result, WxPayRefundNotifyV3Result.DecryptNotifyResult.class);
WxPayRefundNotifyV3Result notifyResult = new WxPayRefundNotifyV3Result();
notifyResult.setRawData(response);
notifyResult.setResult(decryptNotifyResult);
return notifyResult;
} catch (GeneralSecurityException | IOException e) {
throw new WxPayException("解析报文异常!", e);
}
}
@Override
public WxScanPayNotifyResult parseScanPayNotifyResult(String xmlData, String signType) throws WxPayException {
try {
@@ -372,6 +459,28 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
return result;
}
@Override
public WxPayOrderQueryV3Result queryOrderV3(String transactionId, String outTradeNo) throws WxPayException {
WxPayOrderQueryV3Request request = new WxPayOrderQueryV3Request();
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
request.setTransactionId(StringUtils.trimToNull(transactionId));
return this.queryOrderV3(request);
}
@Override
public WxPayOrderQueryV3Result queryOrderV3(WxPayOrderQueryV3Request request) throws WxPayException {
if (StringUtils.isBlank(request.getMchid())) {
request.setMchid(this.getConfig().getMchId());
}
String url = String.format("%s/v3/pay/transactions/out-trade-no/%s", this.getPayBaseUrl(), request.getOutTradeNo());
if (Objects.isNull(request.getOutTradeNo())) {
url = String.format("%s/v3/pay/transactions/id/%s", this.getPayBaseUrl(), request.getTransactionId());
}
String query = String.format("?mchid=%s", request.getMchid());
String response = this.getV3(url + query);
return GSON.fromJson(response, WxPayOrderQueryV3Result.class);
}
@Override
public WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxPayException {
if (StringUtils.isBlank(outTradeNo)) {
@@ -396,6 +505,25 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
return result;
}
@Override
public void closeOrderV3(String outTradeNo) throws WxPayException {
if (StringUtils.isBlank(outTradeNo)) {
throw new WxPayException("out_trade_no不能为空");
}
WxPayOrderCloseV3Request request = new WxPayOrderCloseV3Request();
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
this.closeOrderV3(request);
}
@Override
public void closeOrderV3(WxPayOrderCloseV3Request request) throws WxPayException {
if (StringUtils.isBlank(request.getMchid())) {
request.setMchid(this.getConfig().getMchId());
}
String url = String.format("%s/v3/pay/transactions/out-trade-no/%s/close", this.getPayBaseUrl(), request.getOutTradeNo());
this.postV3(url, GSON.toJson(request));
}
@Override
public <T> T createOrder(WxPayUnifiedOrderRequest request) throws WxPayException {
WxPayUnifiedOrderResult unifiedOrderResult = this.unifiedOrder(request);
@@ -500,6 +628,25 @@ public abstract class BaseWxPayServiceImpl implements WxPayService {
return result;
}
@Override
public <T> T createOrderV3(TradeTypeEnum tradeType, WxPayUnifiedOrderV3Request request) throws WxPayException {
WxPayUnifiedOrderV3Result result = this.unifiedOrderV3(tradeType, request);
return result.getPayInfo(tradeType, request.getAppid(), request.getMchid(), this.getConfig().getPrivateKey());
}
@Override
public WxPayUnifiedOrderV3Result unifiedOrderV3(TradeTypeEnum tradeType, WxPayUnifiedOrderV3Request 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 = this.getPayBaseUrl() + tradeType.getPartnerUrl();
String response = this.postV3(url, GSON.toJson(request));
return GSON.fromJson(response, WxPayUnifiedOrderV3Result.class);
}
@Override
@Deprecated
public Map<String, String> getPayInfo(WxPayUnifiedOrderRequest request) throws WxPayException {