微信支付相关代码独立成一个子模块

This commit is contained in:
Binary Wang
2017-03-05 22:49:17 +08:00
parent 8a270c8f7e
commit eee954b736
49 changed files with 1596 additions and 1308 deletions

View File

@@ -0,0 +1,63 @@
package com.github.binarywang.wxpay.bean;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* 支付异步通知代金券详细
*/
public class WxPayOrderNotifyCoupon implements Serializable {
/**
* @fields serialVersionUID
*/
private static final long serialVersionUID = -4165343733538156097L;
@XStreamAlias("coupon_id")
private String couponId;
@XStreamAlias("coupon_type")
private String couponType;
@XStreamAlias("coupon_fee")
private Integer couponFee;
public String getCouponId() {
return couponId;
}
public void setCouponId(String couponId) {
this.couponId = couponId;
}
public String getCouponType() {
return couponType;
}
public void setCouponType(String couponType) {
this.couponType = couponType;
}
public Integer getCouponFee() {
return couponFee;
}
public void setCouponFee(Integer couponFee) {
this.couponFee = couponFee;
}
public Map<String, String> toMap(int index) {
Map<String, String> map = new HashMap<>();
map.put("coupon_id_" + index, this.getCouponId());
map.put("coupon_type_" + index, this.getCouponType());
map.put("coupon_fee_" + index, this.getCouponFee() + "");
return map;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
}
}

View File

@@ -0,0 +1,59 @@
package com.github.binarywang.wxpay.bean;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
@XStreamAlias("xml")
public class WxPayOrderNotifyResponse {
@XStreamOmitField
private transient static final String FAIL = "FAIL";
@XStreamOmitField
private transient static final String SUCCESS = "SUCCESS";
@XStreamAlias("return_code")
private String returnCode;
@XStreamAlias("return_msg")
private String returnMsg;
public WxPayOrderNotifyResponse() {
super();
}
public WxPayOrderNotifyResponse(String returnCode, String returnMsg) {
super();
this.returnCode = returnCode;
this.returnMsg = returnMsg;
}
public static String fail(String msg) {
WxPayOrderNotifyResponse response = new WxPayOrderNotifyResponse(FAIL, msg);
XStream xstream = XStreamInitializer.getInstance();
xstream.autodetectAnnotations(true);
return xstream.toXML(response);
}
public static String success(String msg) {
WxPayOrderNotifyResponse response = new WxPayOrderNotifyResponse(SUCCESS, msg);
XStream xstream = XStreamInitializer.getInstance();
xstream.autodetectAnnotations(true);
return xstream.toXML(response);
}
public String getReturnCode() {
return returnCode;
}
public void setReturnCode(String returnCode) {
this.returnCode = returnCode;
}
public String getReturnMsg() {
return returnMsg;
}
public void setReturnMsg(String returnMsg) {
this.returnMsg = returnMsg;
}
}

View File

@@ -0,0 +1,74 @@
package com.github.binarywang.wxpay.bean.request;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.annotation.Required;
import me.chanjar.weixin.common.util.ToStringUtils;
/**
* <pre>
* 企业付款请求对象
* 注释中各行每个字段描述对应如下:
* <li>字段名
* <li>变量名
* <li>是否必填
* <li>类型
* <li>示例值
* <li>描述
* </pre>
* Created by Binary Wang on 2016/10/19.
*
* @author binarywang (https://github.com/binarywang)
*/
@XStreamAlias("xml")
public class WxEntPayQueryRequest extends WxPayBaseRequest {
/**
* <pre>
* 商户号
* mch_id
* 是
* 10000098
* String(32)
* 微信支付分配的商户号
* </pre>
*/
@XStreamAlias("mchid")
private String mchId;
/**
* <pre>
* 商户订单号
* partner_trade_no
* 是
* 10000098201411111234567890
* String
* 商户订单号
* </pre>
*/
@Required
@XStreamAlias("partner_trade_no")
private String partnerTradeNo;
@Override
public String getMchId() {
return this.mchId;
}
@Override
public void setMchId(String mchId) {
this.mchId = mchId;
}
public String getPartnerTradeNo() {
return this.partnerTradeNo;
}
public void setPartnerTradeNo(String partnerTradeNo) {
this.partnerTradeNo = partnerTradeNo;
}
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}
}

View File

@@ -0,0 +1,246 @@
package com.github.binarywang.wxpay.bean.request;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.util.ToStringUtils;
/**
* <pre>
* 企业付款请求对象
* 注释中各行每个字段描述对应如下:
* <li>字段名
* <li>变量名
* <li>是否必填
* <li>类型
* <li>示例值
* <li>描述
* </pre>
* Created by Binary Wang on 2016/10/02.
*
* @author binarywang (https://github.com/binarywang)
*/
@XStreamAlias("xml")
public class WxEntPayRequest extends WxPayBaseRequest {
/**
* <pre>
* 公众账号appid
* mch_appid
* 是
* wx8888888888888888
* String
* 微信分配的公众账号ID企业号corpid即为此appId
* </pre>
*/
@XStreamAlias("mch_appid")
private String mchAppid;
/**
* <pre>
* 商户号
* mchid
* 是
* 1900000109
* String(32)
* 微信支付分配的商户号
* </pre>
*/
@XStreamAlias("mchid")
private String mchId;
/**
* <pre>
* 设备号
* device_info
* 否
* 13467007045764
* String(32)
* 微信支付分配的终端设备号
* </pre>
*/
@XStreamAlias("device_info")
private String deviceInfo;
/**
* <pre>
* 商户订单号
* partner_trade_no
* 是
* 10000098201411111234567890
* String
* 商户订单号
* </pre>
*/
@XStreamAlias("partner_trade_no")
private String partnerTradeNo;
/**
* <pre>
* 需保持唯一性 用户openid
* openid
* 是
* oxTWIuGaIt6gTKsQRLau2M0yL16E
* String
* 商户appid下某用户的openid
* </pre>
*/
@XStreamAlias("openid")
private String openid;
/**
* <pre>
* 校验用户姓名选项
* check_name
* 是
* OPTION_CHECK
* String
* NO_CHECK不校验真实姓名 
* FORCE_CHECK强校验真实姓名未实名认证的用户会校验失败无法转账 
* OPTION_CHECK针对已实名认证的用户才校验真实姓名未实名认证用户不校验可以转账成功
* </pre>
*/
@XStreamAlias("check_name")
private String checkName;
/**
* <pre>
* 收款用户姓名
* re_user_name
* 可选
* 马花花
* String
* 收款用户真实姓名。
* 如果check_name设置为FORCE_CHECK或OPTION_CHECK 则必填用户真实姓名
* </pre>
*/
@XStreamAlias("re_user_name")
private String reUserName;
/**
* <pre>
* 金额
* amount
* 是
* 10099
* int
* 企业付款金额, 单位为分
* </pre>
*/
@XStreamAlias("amount")
private Integer amount;
/**
* <pre>
* 企业付款描述信息
* desc
* 是
* 理赔
* String
* 企业付款操作说明信息。必填。
* </pre>
*/
@XStreamAlias("desc")
private String description;
/**
* <pre>
* Ip地址
* spbill_create_ip
* 是
* 192.168.0.1
* String(32)
* 调用接口的机器Ip地址
* </pre>
*/
@XStreamAlias("spbill_create_ip")
private String spbillCreateIp;
@Override
public String getAppid() {
return this.mchAppid;
}
@Override
public void setAppid(String appid) {
this.mchAppid = appid;
}
@Override
public String getMchId() {
return this.mchId;
}
@Override
public void setMchId(String mchId) {
this.mchId = mchId;
}
public String getDeviceInfo() {
return this.deviceInfo;
}
public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}
public String getPartnerTradeNo() {
return this.partnerTradeNo;
}
public void setPartnerTradeNo(String partnerTradeNo) {
this.partnerTradeNo = partnerTradeNo;
}
public String getOpenid() {
return this.openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getCheckName() {
return this.checkName;
}
public void setCheckName(String checkName) {
this.checkName = checkName;
}
public String getReUserName() {
return this.reUserName;
}
public void setReUserName(String reUserName) {
this.reUserName = reUserName;
}
public Integer getAmount() {
return this.amount;
}
public void setAmount(Integer amount) {
this.amount = amount;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
public String getSpbillCreateIp() {
return this.spbillCreateIp;
}
public void setSpbillCreateIp(String spbillCreateIp) {
this.spbillCreateIp = spbillCreateIp;
}
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}
}

View File

@@ -0,0 +1,183 @@
package com.github.binarywang.wxpay.bean.request;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.util.ToStringUtils;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import java.math.BigDecimal;
/**
* <pre>
* Created by Binary Wang on 2016-10-24.
* 微信支付请求对象共用的参数存放类
* 注释中各行每个字段描述对应如下:
* <li>字段名
* <li>变量名
* <li>是否必填
* <li>类型
* <li>示例值
* <li>描述
* </pre>
*
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
*/
public abstract class WxPayBaseRequest {
/**
* <pre>
* 公众账号ID
* appid
* 是
* String(32)
* wxd678efh567hg6787
* 微信分配的公众账号ID企业号corpid即为此appId
* </pre>
*/
@XStreamAlias("appid")
protected String appid;
/**
* <pre>
* 商户号
* mch_id
* 是
* String(32)
* 1230000109
* 微信支付分配的商户号
* </pre>
*/
@XStreamAlias("mch_id")
protected String mchId;
/**
* <pre>
* 服务商模式下的子商户公众账号ID
* sub_appid
* 是
* String(32)
* wxd678efh567hg6787
* 微信分配的子商户公众账号ID
* </pre>
*/
@XStreamAlias("sub_appid")
protected String subAppId;
/**
* <pre>
* 服务商模式下的子商户号
* sub_mch_id
* 是
* String(32)
* 1230000109
* 微信支付分配的子商户号,开发者模式下必填
* </pre>
*/
@XStreamAlias("sub_mch_id")
protected String subMchId;
/**
* <pre>
* 随机字符串
* nonce_str
* 是
* String(32)
* 5K8264ILTKCH16CQ2502SI8ZNMTM67VS
* 随机字符串不长于32位。推荐随机数生成算法
* </pre>
*/
@XStreamAlias("nonce_str")
protected String nonceStr;
/**
* <pre>
* 签名
* sign
* 是
* String(32)
* C380BEC2BFD727A4B6845133519F3AD6
* 签名,详见签名生成算法
* </pre>
*/
@XStreamAlias("sign")
protected String sign;
/**
* 将单位为元转换为单位为分
*
* @param yuan 将要转换的元的数值字符串
*/
public static Integer yuanToFee(String yuan) {
return new BigDecimal(yuan).setScale(2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue();
}
public String getAppid() {
return this.appid;
}
/**
* 如果配置中已经设置,可以不设置值
*
* @param appid 微信公众号appid
*/
public void setAppid(String appid) {
this.appid = appid;
}
public String getMchId() {
return this.mchId;
}
/**
* 如果配置中已经设置,可以不设置值
*
* @param mchId 微信商户号
*/
public void setMchId(String mchId) {
this.mchId = mchId;
}
public String getNonceStr() {
return this.nonceStr;
}
/**
* 默认采用时间戳为随机字符串,可以不设置
*
* @param nonceStr 随机字符串
*/
public void setNonceStr(String nonceStr) {
this.nonceStr = nonceStr;
}
public String getSign() {
return this.sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getSubAppId() {
return subAppId;
}
public void setSubAppId(String subAppId) {
this.subAppId = subAppId;
}
public String getSubMchId() {
return subMchId;
}
public void setSubMchId(String subMchId) {
this.subMchId = subMchId;
}
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}
public String toXML() {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(this.getClass());
return xstream.toXML(this);
}
}

View File

@@ -0,0 +1,123 @@
package com.github.binarywang.wxpay.bean.request;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.annotation.Required;
/**
* <pre>
* 微信支付下载对账单请求参数类
* Created by Binary Wang on 2017-01-11.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
@XStreamAlias("xml")
public class WxPayDownloadBillRequest extends WxPayBaseRequest {
/**
* <pre>
* 设备号
* device_info
* 否
* String(32)
* 13467007045764
* 终端设备号
* </pre>
*/
@XStreamAlias("device_info")
private String deviceInfo;
/**
* <pre>
* 签名类型
* sign_type
* 否
* String(32)
* HMAC-SHA256
* 签名类型目前支持HMAC-SHA256和MD5默认为MD5
* </pre>
*/
@XStreamAlias("sign_type")
private String signType;
/**
* <pre>
* 账单类型
* bill_type
* 是
* ALL
* String(8)
* --ALL返回当日所有订单信息默认值
* --SUCCESS返回当日成功支付的订单
* --REFUND返回当日退款订单
* </pre>
*/
@Required
@XStreamAlias("bill_type")
private String billType;
/**
* <pre>
* 对账单日期
* bill_date
* 是
* String(8)
* 20140603
* 下载对账单的日期格式20140603
* </pre>
*/
@Required
@XStreamAlias("bill_date")
private String billDate;
/**
* <pre>
* 压缩账单
* tar_type
* 否
* String(8)
* GZIP
* 非必传参数固定值GZIP返回格式为.gzip的压缩包账单。不传则默认为数据流形式。
* </pre>
*/
@XStreamAlias("tar_type")
private String tarType;
public String getDeviceInfo() {
return deviceInfo;
}
public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}
public String getSignType() {
return signType;
}
public void setSignType(String signType) {
this.signType = signType;
}
public String getBillType() {
return billType;
}
public void setBillType(String billType) {
this.billType = billType;
}
public String getBillDate() {
return billDate;
}
public void setBillDate(String billDate) {
this.billDate = billDate;
}
public String getTarType() {
return tarType;
}
public void setTarType(String tarType) {
this.tarType = tarType;
}
}

View File

@@ -0,0 +1,36 @@
package com.github.binarywang.wxpay.bean.request;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* <pre>
* 关闭订单请求对象类
* Created by Binary Wang on 2016-10-27.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
@XStreamAlias("xml")
public class WxPayOrderCloseRequest extends WxPayBaseRequest {
/**
* <pre>
* 商户订单号
* out_trade_no
* 二选一
* String(32)
* 20150806125346
* 商户系统内部的订单号当没提供transaction_id时需要传这个。
* </pre>
*/
@XStreamAlias("out_trade_no")
private String outTradeNo;
public String getOutTradeNo() {
return this.outTradeNo;
}
public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}
}

View File

@@ -0,0 +1,64 @@
package com.github.binarywang.wxpay.bean.request;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* <pre>
* 订单查询请求对象
* Created by Binary Wang on 2016-10-24.
* 注释中各行每个字段描述对应如下:
* <li>字段名
* <li>变量名
* <li>是否必填
* <li>类型
* <li>示例值
* <li>描述
* </pre>
*
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
*/
@XStreamAlias("xml")
public class WxPayOrderQueryRequest extends WxPayBaseRequest {
/**
* <pre>
* 微信订单号
* transaction_id
* 二选一
* String(32)
* 1009660380201506130728806387
* 微信的订单号,优先使用
* </pre>
*/
@XStreamAlias("transaction_id")
private String transactionId;
/**
* <pre>
* 商户订单号
* out_trade_no
* 二选一
* String(32)
* 20150806125346
* 商户系统内部的订单号当没提供transaction_id时需要传这个。
* </pre>
*/
@XStreamAlias("out_trade_no")
private String outTradeNo;
public String getTransactionId() {
return this.transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getOutTradeNo() {
return this.outTradeNo;
}
public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}
}

View File

@@ -0,0 +1,57 @@
package com.github.binarywang.wxpay.bean.request;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* <pre>
* 注释中各行对应含义:
* 字段名
* 字段
* 必填
* 示例值
* 类型
* 说明
* Created by Binary Wang on 2016-11-28.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
@XStreamAlias("xml")
public class WxPayRedpackQueryRequest extends WxPayBaseRequest {
/**
* 商户订单号
* mch_billno
* 是
* 10000098201411111234567890
* String(28)
* 商户发放红包的商户订单号
*/
@XStreamAlias("mch_billno")
private String mchBillNo;
/**
* 订单类型
* bill_type
* 是
* MCHT
* String(32)
* MCHT:通过商户订单号获取红包信息。
*/
@XStreamAlias("bill_type")
private String billType;
public String getBillType() {
return billType;
}
public void setBillType(String billType) {
this.billType = billType;
}
public String getMchBillNo() {
return mchBillNo;
}
public void setMchBillNo(String mchBillNo) {
this.mchBillNo = mchBillNo;
}
}

View File

@@ -0,0 +1,135 @@
package com.github.binarywang.wxpay.bean.request;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* <pre>
* Created by Binary Wang on 2016-11-24.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
@XStreamAlias("xml")
public class WxPayRefundQueryRequest extends WxPayBaseRequest {
/**
* <pre>
* 设备号
* device_info
* 否
* String(32)
* 013467007045764
* 商户自定义的终端设备号如门店编号、设备的ID等
* </pre>
*/
@XStreamAlias("device_info")
private String deviceInfo;
/**
* <pre>
* 签名类型
* sign_type
* 否
* String(32)
* HMAC-SHA256
* 签名类型目前支持HMAC-SHA256和MD5默认为MD5
* </pre>
*/
@XStreamAlias("sign_type")
private String signType;
//************以下四选一************
/**
* <pre>
* 微信订单号
* transaction_id
* String(32)
* 1217752501201407033233368018
* 微信订单号
* </pre>
*/
@XStreamAlias("transaction_id")
private String transactionId;
/**
* <pre>
* 商户订单号
* out_trade_no
* String(32)
* 1217752501201407033233368018
* 商户系统内部的订单号
* </pre>
*/
@XStreamAlias("out_trade_no")
private String outTradeNo;
/**
* <pre>
* 商户退款单号
* out_refund_no
* String(32)
* 1217752501201407033233368018
* 商户侧传给微信的退款单号
* </pre>
*/
@XStreamAlias("out_refund_no")
private String outRefundNo;
/**
* <pre>
* 微信退款单号
* refund_id
* String(28)
* 1217752501201407033233368018
* 微信生成的退款单号,在申请退款接口有返回
* </pre>
*/
@XStreamAlias("refund_id")
private String refundId;
public String getDeviceInfo() {
return deviceInfo;
}
public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}
public String getSignType() {
return signType;
}
public void setSignType(String signType) {
this.signType = signType;
}
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getOutTradeNo() {
return outTradeNo;
}
public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}
public String getOutRefundNo() {
return outRefundNo;
}
public void setOutRefundNo(String outRefundNo) {
this.outRefundNo = outRefundNo;
}
public String getRefundId() {
return refundId;
}
public void setRefundId(String refundId) {
this.refundId = refundId;
}
}

View File

@@ -0,0 +1,339 @@
package com.github.binarywang.wxpay.bean.request;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.annotation.Required;
/**
* <pre>
* 微信支付-申请退款请求参数
* 注释中各行每个字段描述对应如下:
* <li>字段名
* <li>变量名
* <li>是否必填
* <li>类型
* <li>示例值
* <li>描述
* </pre>
*
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* Created by Binary Wang on 2016-10-08.
*/
@XStreamAlias("xml")
public class WxPayRefundRequest extends WxPayBaseRequest {
/**
* <pre>
* 设备号
* device_info
* 否
* String(32)
* 13467007045764
* 终端设备号
* </pre>
*/
@XStreamAlias("device_info")
private String deviceInfo;
/**
* <pre>
* 微信订单号
* transaction_id
* 跟out_trade_no二选一
* String(28)
* 1217752501201400000000000000
* 微信生成的订单号,在支付通知中有返回
* </pre>
*/
@XStreamAlias("transaction_id")
private String transactionId;
/**
* <pre>
* 商户订单号
* out_trade_no
* 跟transaction_id二选一
* String(32)
* 1217752501201400000000000000
* 商户侧传给微信的订单号
* </pre>
*/
@XStreamAlias("out_trade_no")
private String outTradeNo;
/**
* <pre>
* 商户退款单号
* out_refund_no
* 是
* String(32)
* 1217752501201400000000000000
* 商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔
* </pre>
*/
@Required
@XStreamAlias("out_refund_no")
private String outRefundNo;
/**
* <pre>
* 订单金额
* total_fee
* 是
* Int
* 100
* 订单总金额,单位为分,只能为整数,详见支付金额
* </pre>
*/
@Required
@XStreamAlias("total_fee")
private Integer totalFee;
/**
* <pre>
* 退款金额
* refund_fee
* 是
* Int
* 100
* 退款总金额,订单总金额,单位为分,只能为整数,详见支付金额
* </pre>
*/
@Required
@XStreamAlias("refund_fee")
private Integer refundFee;
/**
* <pre>
* 货币种类
* refund_fee_type
* 否
* String(8)
* CNY
* 货币类型符合ISO 4217标准的三位字母代码默认人民币CNY其他值列表详见货币类型
* </pre>
*/
@XStreamAlias("refund_fee_type")
private String refundFeeType;
/**
* <pre>
* 操作员
* op_user_id
* 是
* String(32)
* 1900000109
* 操作员帐号, 默认为商户号
* </pre>
*/
//@Required
@XStreamAlias("op_user_id")
private String opUserId;
/**
* <pre>
* 退款资金来源
* refund_account
* 否
* String(30)
* REFUND_SOURCE_RECHARGE_FUNDS
* 仅针对老资金流商户使用,
* <li>REFUND_SOURCE_UNSETTLED_FUNDS---未结算资金退款(默认使用未结算资金退款),
* <li>REFUND_SOURCE_RECHARGE_FUNDS---可用余额退款
* </pre>
*/
@XStreamAlias("refund_account")
private String refundAccount;
private WxPayRefundRequest(Builder builder) {
setDeviceInfo(builder.deviceInfo);
setAppid(builder.appid);
setTransactionId(builder.transactionId);
setMchId(builder.mchId);
setOutTradeNo(builder.outTradeNo);
setSubAppId(builder.subAppId);
setSubMchId(builder.subMchId);
setOutRefundNo(builder.outRefundNo);
setNonceStr(builder.nonceStr);
setTotalFee(builder.totalFee);
setSign(builder.sign);
setRefundFee(builder.refundFee);
setRefundFeeType(builder.refundFeeType);
setOpUserId(builder.opUserId);
setRefundAccount(builder.refundAccount);
}
public static Builder newBuilder() {
return new Builder();
}
public String getDeviceInfo() {
return this.deviceInfo;
}
public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}
public String getTransactionId() {
return this.transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getOutTradeNo() {
return this.outTradeNo;
}
public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}
public String getOutRefundNo() {
return this.outRefundNo;
}
public void setOutRefundNo(String outRefundNo) {
this.outRefundNo = outRefundNo;
}
public Integer getTotalFee() {
return this.totalFee;
}
public void setTotalFee(Integer totalFee) {
this.totalFee = totalFee;
}
public Integer getRefundFee() {
return this.refundFee;
}
public void setRefundFee(Integer refundFee) {
this.refundFee = refundFee;
}
public String getRefundFeeType() {
return this.refundFeeType;
}
public void setRefundFeeType(String refundFeeType) {
this.refundFeeType = refundFeeType;
}
public String getOpUserId() {
return this.opUserId;
}
public void setOpUserId(String opUserId) {
this.opUserId = opUserId;
}
public String getRefundAccount() {
return this.refundAccount;
}
public void setRefundAccount(String refundAccount) {
this.refundAccount = refundAccount;
}
public static final class Builder {
private String deviceInfo;
private String appid;
private String transactionId;
private String mchId;
private String outTradeNo;
private String subAppId;
private String subMchId;
private String outRefundNo;
private String nonceStr;
private Integer totalFee;
private String sign;
private Integer refundFee;
private String refundFeeType;
private String opUserId;
private String refundAccount;
private Builder() {
}
public Builder deviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
return this;
}
public Builder appid(String appid) {
this.appid = appid;
return this;
}
public Builder transactionId(String transactionId) {
this.transactionId = transactionId;
return this;
}
public Builder mchId(String mchId) {
this.mchId = mchId;
return this;
}
public Builder outTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
return this;
}
public Builder subAppId(String subAppId) {
this.subAppId = subAppId;
return this;
}
public Builder subMchId(String subMchId) {
this.subMchId = subMchId;
return this;
}
public Builder outRefundNo(String outRefundNo) {
this.outRefundNo = outRefundNo;
return this;
}
public Builder nonceStr(String nonceStr) {
this.nonceStr = nonceStr;
return this;
}
public Builder totalFee(Integer totalFee) {
this.totalFee = totalFee;
return this;
}
public Builder sign(String sign) {
this.sign = sign;
return this;
}
public Builder refundFee(Integer refundFee) {
this.refundFee = refundFee;
return this;
}
public Builder refundFeeType(String refundFeeType) {
this.refundFeeType = refundFeeType;
return this;
}
public Builder opUserId(String opUserId) {
this.opUserId = opUserId;
return this;
}
public Builder refundAccount(String refundAccount) {
this.refundAccount = refundAccount;
return this;
}
public WxPayRefundRequest build() {
return new WxPayRefundRequest(this);
}
}
}

View File

@@ -0,0 +1,273 @@
package com.github.binarywang.wxpay.bean.request;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.annotation.Required;
/**
* <pre>
* 微信支付-交易保障请求参数
* 注释中各行每个字段描述对应如下:
* <li>字段名
* <li>变量名
* <li>是否必填
* <li>类型
* <li>示例值
* <li>描述
* </pre>
*
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
*/
@XStreamAlias("xml")
public class WxPayReportRequest extends WxPayBaseRequest {
/**
* <pre>
* 设备号
* device_info
* 否
* String(32)
* 013467007045764
* 商户自定义的终端设备号如门店编号、设备的ID等
* </pre>
*/
@XStreamAlias("device_info")
private String deviceInfo;
/**
* <pre>
* 签名类型
* sign_type
* 否
* String(32)
* HMAC-SHA256
* 签名类型目前支持HMAC-SHA256和MD5默认为MD5
* </pre>
*/
@XStreamAlias("sign_type")
private String signType;
/**
* <pre>
* 接口URL
* interface_url
* 是
* String(127)
* https://api.mch.weixin.qq.com/pay/unifiedorder
* 报对应的接口的完整URL类似https://api.mch.weixin.qq.com/pay/unifiedorder
* 对于刷卡支付,为更好的和商户共同分析一次业务行为的整体耗时情况,
* 对于两种接入模式,请都在门店侧对一次刷卡支付进行一次单独的整体上报,
* 上报URL指定为https://api.mch.weixin.qq.com/pay/micropay/total关于两种接入模式具体可参考本文档章节
* 刷卡支付商户接入模式,其它接口调用仍然按照调用一次,上报一次来进行。
* </pre>
*/
@Required
@XStreamAlias("interface_url")
private String interfaceUrl;
/**
* <pre>
* 接口耗时
* execute_time
* 是
* Int
* 1000
* 接口耗时情况,单位为毫秒
* </pre>
*/
@Required
@XStreamAlias("execute_time_")//估计是官方接口搞错了
private Integer executeTime;
/**
* <pre>
* 返回状态码
* return_code
* 是
* String(16)
* SUCCESS
* SUCCESS/FAIL此字段是通信标识非交易标识交易是否成功需要查看trade_state来判断
* </pre>
*/
@Required
@XStreamAlias("return_code")
private String returnCode;
/**
* <pre>
* 返回信息
* return_msg
* 否
* String(128)
* 签名失败
* 返回信息,如非空,为错误原因,签名失败,参数格式校验错误
* </pre>
*/
@XStreamAlias("return_msg")
private String returnMsg;
/**
* <pre>
* 业务结果
* result_code
* 是
* String(16)
* SUCCESS
* SUCCESS/FAIL
* </pre>
*/
@Required
@XStreamAlias("result_code")
private String resultCode;
/**
* <pre>
* 错误代码
* err_code
* 否
* String(32)
* SYSTEMERROR
* ORDERNOTEXIST—订单不存在SYSTEMERROR—系统错误
* </pre>
*/
@XStreamAlias("err_code")
private String errCode;
/**
* <pre>
* 错误代码描述
* err_code_des
* 否
* String(128)
* 系统错误
* 结果信息描述
* </pre>
*/
@XStreamAlias("err_code_des")
private String errCodeDes;
/**
* <pre>
* 商户订单号
* out_trade_no
* 否
* String(32)
* 1217752501201407033233368018
* 商户系统内部的订单号,商户可以在上报时提供相关商户订单号方便微信支付更好的提高服务质量。
* </pre>
*/
@XStreamAlias("out_trade_no")
private String outTradeNo;
/**
* <pre>
* 访问接口IP
* user_ip
* 是
* String(16)
* 8.8.8.8
* 发起接口调用时的机器IP
* </pre>
*/
@Required
@XStreamAlias("user_ip")
private String userIp;
/**
* <pre>
* 商户上报时间
* time
* 否
* String(14)
* 20091227091010
* 系统时间格式为yyyyMMddHHmmss如2009年12月27日9点10分10秒表示为20091227091010。其他详见时间规则
* </pre>
*/
@XStreamAlias("time")
private String time;
public String getDeviceInfo() {
return deviceInfo;
}
public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}
public String getSignType() {
return signType;
}
public void setSignType(String signType) {
this.signType = signType;
}
public String getInterfaceUrl() {
return interfaceUrl;
}
public void setInterfaceUrl(String interfaceUrl) {
this.interfaceUrl = interfaceUrl;
}
public Integer getExecuteTime() {
return executeTime;
}
public void setExecuteTime(Integer executeTime) {
this.executeTime = executeTime;
}
public String getReturnCode() {
return returnCode;
}
public void setReturnCode(String returnCode) {
this.returnCode = returnCode;
}
public String getReturnMsg() {
return returnMsg;
}
public void setReturnMsg(String returnMsg) {
this.returnMsg = returnMsg;
}
public String getResultCode() {
return resultCode;
}
public void setResultCode(String resultCode) {
this.resultCode = resultCode;
}
public String getErrCode() {
return errCode;
}
public void setErrCode(String errCode) {
this.errCode = errCode;
}
public String getErrCodeDes() {
return errCodeDes;
}
public void setErrCodeDes(String errCodeDes) {
this.errCodeDes = errCodeDes;
}
public String getOutTradeNo() {
return outTradeNo;
}
public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}
public String getUserIp() {
return userIp;
}
public void setUserIp(String userIp) {
this.userIp = userIp;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
}

View File

@@ -0,0 +1,254 @@
package com.github.binarywang.wxpay.bean.request;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 发送红包请求参数对象
* Created by Binary Wang on 2016/9/24.
*
* @author binarywang (https://github.com/binarywang)
*/
@XStreamAlias("xml")
public class WxPaySendRedpackRequest extends WxPayBaseRequest {
/**
* mch_billno
* 商户订单号(每个订单号必须唯一) 组成mch_id+yyyymmdd+10位一天内不能重复的数字。 接口根据商户订单号支持重入,如出现超时可再调用。
*/
@XStreamAlias("mch_billno")
private String mchBillNo;
/**
* send_name
* 商户名称
* 红包发送者名称
*/
@XStreamAlias("send_name")
private String sendName;
/**
* re_openid
* 接受红包的用户 用户在wxappid下的openid
*/
@XStreamAlias("re_openid")
private String reOpenid;
/**
* total_amount
* 红包总额
*/
@XStreamAlias("total_amount")
private Integer totalAmount;
/**
* total_num
* 红包发放总人数
*/
@XStreamAlias("total_num")
private Integer totalNum;
/**
* amt_type
* 红包金额设置方式
* ALL_RAND—全部随机,商户指定总金额和红包发放总人数,由微信支付随机计算出各红包金额
* 裂变红包必填
*/
@XStreamAlias("amt_type")
private String amtType;
/**
* wishing
* 红包祝福语
*/
@XStreamAlias("wishing")
private String wishing;
/**
* client_ip
* 服务器Ip地址
* 调用接口的机器Ip地址
*/
@XStreamAlias("client_ip")
private String clientIp;
/**
* act_name
* 活动名称
*/
@XStreamAlias("act_name")
private String actName;
/**
* remark
* 备注
*/
@XStreamAlias("remark")
private String remark;
/**
* wxappid
* 微信分配的公众账号ID企业号corpid即为此appId。接口传入的所有appid应该为公众号的appid在mp.weixin.qq.com申请的不能为APP的appid在open.weixin.qq.com申请的
*/
@XStreamAlias("wxappid")
private String wxAppid;
/**
* <pre>
* scene_id
* 场景id
* PRODUCT_1:商品促销
* PRODUCT_2:抽奖
* PRODUCT_3:虚拟物品兑奖
* PRODUCT_4:企业内部福利
* PRODUCT_5:渠道分润
* PRODUCT_6:保险回馈
* PRODUCT_7:彩票派奖
* PRODUCT_8:税务刮奖
* 非必填字段
* </pre>
*/
@XStreamAlias("scene_id")
private String sceneId;
/**
* <pre>
* risk_info
* 活动信息
* posttime:用户操作的时间戳
* mobile:业务系统账号的手机号,国家代码-手机号。不需要+号
* deviceid :mac 地址或者设备唯一标识
* clientversion :用户操作的客户端版本
* 把值为非空的信息用key=value进行拼接再进行urlencode
* urlencode(posttime=xx&mobile=xx&deviceid=xx)
* 非必填字段
* </pre>
*/
@XStreamAlias("risk_info")
private String riskInfo;
/**
* <pre>
* consume_mch_id
* 资金授权商户号
* 资金授权商户号
* 服务商替特约商户发放时使用
* 非必填字段
* </pre>
*/
@XStreamAlias("consume_mch_id")
private String consumeMchId;
public String getMchBillNo() {
return mchBillNo;
}
public void setMchBillNo(String mchBillNo) {
this.mchBillNo = mchBillNo;
}
public String getSendName() {
return this.sendName;
}
public void setSendName(String sendName) {
this.sendName = sendName;
}
public String getReOpenid() {
return this.reOpenid;
}
public void setReOpenid(String reOpenid) {
this.reOpenid = reOpenid;
}
public Integer getTotalAmount() {
return this.totalAmount;
}
public void setTotalAmount(Integer totalAmount) {
this.totalAmount = totalAmount;
}
public Integer getTotalNum() {
return this.totalNum;
}
public void setTotalNum(Integer totalNum) {
this.totalNum = totalNum;
}
public String getAmtType() {
return this.amtType;
}
public void setAmtType(String amtType) {
this.amtType = amtType;
}
public String getWishing() {
return this.wishing;
}
public void setWishing(String wishing) {
this.wishing = wishing;
}
public String getClientIp() {
return this.clientIp;
}
public void setClientIp(String clientIp) {
this.clientIp = clientIp;
}
public String getActName() {
return this.actName;
}
public void setActName(String actName) {
this.actName = actName;
}
public String getRemark() {
return this.remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
@Override
public String getAppid() {
return this.wxAppid;
}
@Override
public void setAppid(String appid) {
this.wxAppid = appid;
}
public String getSceneId() {
return this.sceneId;
}
public void setSceneId(String sceneId) {
this.sceneId = sceneId;
}
public String getRiskInfo() {
return this.riskInfo;
}
public void setRiskInfo(String riskInfo) {
this.riskInfo = riskInfo;
}
public String getConsumeMchId() {
return this.consumeMchId;
}
public void setConsumeMchId(String consumeMchId) {
this.consumeMchId = consumeMchId;
}
}

View File

@@ -0,0 +1,584 @@
package com.github.binarywang.wxpay.bean.request;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.annotation.Required;
/**
* <pre>
* 统一下单请求参数对象
* 参考文档https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
* 注释中各行每个字段描述对应如下:
* <li>字段名
* <li>变量名
* <li>是否必填
* <li>类型
* <li>示例值
* <li>描述
* </pre>
* Created by Binary Wang on 2016/9/25.
*
* @author binarywang (https://github.com/binarywang)
*/
@XStreamAlias("xml")
public class WxPayUnifiedOrderRequest extends WxPayBaseRequest {
/**
* <pre>
* 设备号
* device_info
* 否
* String(32)
* 013467007045764
* 终端设备号(门店号或收银设备Id)注意PC网页或公众号内支付请传"WEB"
* </pre>
*/
@XStreamAlias("device_info")
private String deviceInfo;
/**
* <pre>
* 商品描述
* body
* 是
* String(128)
* 腾讯充值中心-QQ会员充值
* 商品简单描述,该字段须严格按照规范传递,具体请见参数规定
* </pre>
*/
@Required
@XStreamAlias("body")
private String body;
/**
* <pre>
* 商品详情
* detail
* 否
* String(6000)
* { "goods_detail":[
* {
* "goods_id":"iphone6s_16G",
* "wxpay_goods_id":"1001",
* "goods_name":"iPhone6s 16G",
* "goods_num":1,
* "price":528800,
* "goods_category":"123456",
* "body":"苹果手机"
* },
* {
* "goods_id":"iphone6s_32G",
* "wxpay_goods_id":"1002",
* "goods_name":"iPhone6s 32G",
* "quantity":1,
* "price":608800,
* "goods_category":"123789",
* "body":"苹果手机"
* }
* ]
* }
* 商品详细列表使用Json格式传输签名前请务必使用CDATA标签将JSON文本串保护起来。
* goods_detail []
* └ goods_id String 必填 32 商品的编号
* └ wxpay_goods_id String 可选 32 微信支付定义的统一商品编号
* └ goods_name String 必填 256 商品名称
* └ goods_num Int 必填 商品数量
* └ price Int 必填 商品单价,单位为分
* └ goods_category String 可选 32 商品类目Id
* └ body String 可选 1000 商品描述信息
* </pre>
*/
@XStreamAlias("detail")
private String detail;
/**
* <pre>
* 附加数据
* attach
* 否
* String(127)
* 深圳分店
* 附加数据在查询API和支付通知中原样返回该字段主要用于商户携带订单的自定义数据
* </pre>
*/
@XStreamAlias("attach")
private String attach;
/**
* <pre>
* 商户订单号
* out_trade_no
* 是
* String(32)
* 20150806125346
* 商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号
* </pre>
*/
@Required
@XStreamAlias("out_trade_no")
private String outTradeNo;
/**
* <pre>
* 货币类型
* fee_type
* 否
* String(16)
* CNY
* 符合ISO 4217标准的三位字母代码默认人民币CNY其他值列表详见货币类型
* </pre>
*/
@XStreamAlias("fee_type")
private String feeType;
/**
* <pre>
* 总金额
* total_fee
* 是
* Int
* 888
* 订单总金额,单位为分,详见支付金额
* </pre>
*/
@Required
@XStreamAlias("total_fee")
private Integer totalFee;
/**
* <pre>
* 终端IP
* spbill_create_ip
* 是
* String(16)
* 123.12.12.123
* APP和网页支付提交用户端ipNative支付填调用微信支付API的机器IP。
* </pre>
*/
@Required
@XStreamAlias("spbill_create_ip")
private String spbillCreateIp;
/**
* <pre>
* 交易起始时间
* time_start
* 否
* String(14)
* 20091225091010
* 订单生成时间格式为yyyyMMddHHmmss如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
* </pre>
*/
@XStreamAlias("time_start")
private String timeStart;
/**
* <pre>
* 交易结束时间
* time_expire
* 否
* String(14)
* 20091227091010
* 订单失效时间格式为yyyyMMddHHmmss如2009年12月27日9点10分10秒表示为20091227091010。其他详见时间规则
* 注意最短失效时间间隔必须大于5分钟
* </pre>
*/
@XStreamAlias("time_expire")
private String timeExpire;
/**
* <pre>
* 商品标记
* goods_tag
* 否
* String(32)
* WXG
* 商品标记,代金券或立减优惠功能的参数,说明详见代金券或立减优惠
* </pre>
*/
@XStreamAlias("goods_tag")
private String goodsTag;
/**
* <pre>
* 通知地址
* notify_url
* 是
* String(256)
* http://www.weixin.qq.com/wxpay/pay.php
* 接收微信支付异步通知回调地址通知url必须为直接可访问的url不能携带参数。
* </pre>
*/
@Required
@XStreamAlias("notify_url")
private String notifyURL;
/**
* <pre>
* 交易类型
* trade_type
* 是
* String(16)
* JSAPI
* 取值如下JSAPINATIVEAPP详细说明见参数规定:
* JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付统一下单接口trade_type的传参可参考这里
* </pre>
*/
@Required
@XStreamAlias("trade_type")
private String tradeType;
/**
* <pre>
* 商品Id
* product_id
* 否
* String(32)
* 12235413214070356458058
* trade_type=NATIVE此参数必传。此id为二维码中包含的商品Id商户自行定义。
* </pre>
*/
@XStreamAlias("product_id")
private String productId;
/**
* <pre>
* 指定支付方式
* limit_pay
* 否
* String(32)
* no_credit no_credit--指定不能使用信用卡支付
* </pre>
*/
@XStreamAlias("limit_pay")
private String limitPay;
/**
* <pre>
* 用户标识
* openid
* 否
* String(128)
* oUpF8uMuAJO_M2pxb1Q9zNjWeS6o
* trade_type=JSAPI此参数必传用户在商户appid下的唯一标识。
* openid如何获取可参考【获取openid】。
* 企业号请使用【企业号OAuth2.0接口】获取企业号内成员userid再调用【企业号userid转openid接口】进行转换
* </pre>
*/
@XStreamAlias("openid")
private String openid;
public static WxUnifiedOrderRequestBuilder builder() {
return new WxUnifiedOrderRequestBuilder();
}
public String getDeviceInfo() {
return this.deviceInfo;
}
public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}
public String getBody() {
return this.body;
}
public void setBody(String body) {
this.body = body;
}
public String getDetail() {
return this.detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
public String getAttach() {
return this.attach;
}
public void setAttach(String attach) {
this.attach = attach;
}
public String getOutTradeNo() {
return this.outTradeNo;
}
public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}
public String getFeeType() {
return this.feeType;
}
public void setFeeType(String feeType) {
this.feeType = feeType;
}
public Integer getTotalFee() {
return this.totalFee;
}
public void setTotalFee(Integer totalFee) {
this.totalFee = totalFee;
}
public String getSpbillCreateIp() {
return this.spbillCreateIp;
}
public void setSpbillCreateIp(String spbillCreateIp) {
this.spbillCreateIp = spbillCreateIp;
}
public String getTimeStart() {
return this.timeStart;
}
public void setTimeStart(String timeStart) {
this.timeStart = timeStart;
}
public String getTimeExpire() {
return this.timeExpire;
}
public void setTimeExpire(String timeExpire) {
this.timeExpire = timeExpire;
}
public String getGoodsTag() {
return this.goodsTag;
}
public void setGoodsTag(String goodsTag) {
this.goodsTag = goodsTag;
}
public String getNotifyURL() {
return this.notifyURL;
}
/**
* 如果配置中已经设置,可以不设置值
*
* @param notifyURL
*/
public void setNotifyURL(String notifyURL) {
this.notifyURL = notifyURL;
}
public String getTradeType() {
return this.tradeType;
}
/**
* 如果配置中已经设置,可以不设置值
*
* @param tradeType 交易类型
*/
public void setTradeType(String tradeType) {
this.tradeType = tradeType;
}
public String getProductId() {
return this.productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public String getLimitPay() {
return this.limitPay;
}
public void setLimitPay(String limitPay) {
this.limitPay = limitPay;
}
public String getOpenid() {
return this.openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public static class WxUnifiedOrderRequestBuilder {
private String appid;
private String mchId;
private String deviceInfo;
private String nonceStr;
private String sign;
private String body;
private String detail;
private String attach;
private String outTradeNo;
private String feeType;
private Integer totalFee;
private String spbillCreateIp;
private String timeStart;
private String timeExpire;
private String goodsTag;
private String notifyURL;
private String tradeType;
private String productId;
private String limitPay;
private String openid;
public WxUnifiedOrderRequestBuilder appid(String appid) {
this.appid = appid;
return this;
}
public WxUnifiedOrderRequestBuilder mchId(String mchId) {
this.mchId = mchId;
return this;
}
public WxUnifiedOrderRequestBuilder deviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
return this;
}
public WxUnifiedOrderRequestBuilder nonceStr(String nonceStr) {
this.nonceStr = nonceStr;
return this;
}
public WxUnifiedOrderRequestBuilder sign(String sign) {
this.sign = sign;
return this;
}
public WxUnifiedOrderRequestBuilder body(String body) {
this.body = body;
return this;
}
public WxUnifiedOrderRequestBuilder detail(String detail) {
this.detail = detail;
return this;
}
public WxUnifiedOrderRequestBuilder attach(String attach) {
this.attach = attach;
return this;
}
public WxUnifiedOrderRequestBuilder outTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
return this;
}
public WxUnifiedOrderRequestBuilder feeType(String feeType) {
this.feeType = feeType;
return this;
}
public WxUnifiedOrderRequestBuilder totalFee(Integer totalFee) {
this.totalFee = totalFee;
return this;
}
public WxUnifiedOrderRequestBuilder spbillCreateIp(String spbillCreateIp) {
this.spbillCreateIp = spbillCreateIp;
return this;
}
public WxUnifiedOrderRequestBuilder timeStart(String timeStart) {
this.timeStart = timeStart;
return this;
}
public WxUnifiedOrderRequestBuilder timeExpire(String timeExpire) {
this.timeExpire = timeExpire;
return this;
}
public WxUnifiedOrderRequestBuilder goodsTag(String goodsTag) {
this.goodsTag = goodsTag;
return this;
}
public WxUnifiedOrderRequestBuilder notifyURL(String notifyURL) {
this.notifyURL = notifyURL;
return this;
}
public WxUnifiedOrderRequestBuilder tradeType(String tradeType) {
this.tradeType = tradeType;
return this;
}
public WxUnifiedOrderRequestBuilder productId(String productId) {
this.productId = productId;
return this;
}
public WxUnifiedOrderRequestBuilder limitPay(String limitPay) {
this.limitPay = limitPay;
return this;
}
public WxUnifiedOrderRequestBuilder openid(String openid) {
this.openid = openid;
return this;
}
public WxUnifiedOrderRequestBuilder from(WxPayUnifiedOrderRequest origin) {
this.appid(origin.appid);
this.mchId(origin.mchId);
this.deviceInfo(origin.deviceInfo);
this.nonceStr(origin.nonceStr);
this.sign(origin.sign);
this.body(origin.body);
this.detail(origin.detail);
this.attach(origin.attach);
this.outTradeNo(origin.outTradeNo);
this.feeType(origin.feeType);
this.totalFee(origin.totalFee);
this.spbillCreateIp(origin.spbillCreateIp);
this.timeStart(origin.timeStart);
this.timeExpire(origin.timeExpire);
this.goodsTag(origin.goodsTag);
this.notifyURL(origin.notifyURL);
this.tradeType(origin.tradeType);
this.productId(origin.productId);
this.limitPay(origin.limitPay);
this.openid(origin.openid);
return this;
}
public WxPayUnifiedOrderRequest build() {
WxPayUnifiedOrderRequest m = new WxPayUnifiedOrderRequest();
m.appid = this.appid;
m.mchId = this.mchId;
m.deviceInfo = this.deviceInfo;
m.nonceStr = this.nonceStr;
m.sign = this.sign;
m.body = this.body;
m.detail = this.detail;
m.attach = this.attach;
m.outTradeNo = this.outTradeNo;
m.feeType = this.feeType;
m.totalFee = this.totalFee;
m.spbillCreateIp = this.spbillCreateIp;
m.timeStart = this.timeStart;
m.timeExpire = this.timeExpire;
m.goodsTag = this.goodsTag;
m.notifyURL = this.notifyURL;
m.tradeType = this.tradeType;
m.productId = this.productId;
m.limitPay = this.limitPay;
m.openid = this.openid;
return m;
}
}
}

View File

@@ -0,0 +1,139 @@
package com.github.binarywang.wxpay.bean.result;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 企业付款查询返回结果
* Created by Binary Wang on 2016/10/19.
*
* @author binarywang (https://github.com/binarywang)
*/
@XStreamAlias("xml")
public class WxEntPayQueryResult extends WxPayBaseResult {
/**
* 商户订单号
*/
@XStreamAlias("partner_trade_no")
private String partnerTradeNo;
/**
* 付款单号
*/
@XStreamAlias("detail_id")
private String detailId;
/**
* 转账状态
*/
@XStreamAlias("status")
private String status;
/**
* 失败原因
*/
@XStreamAlias("reason")
private String reason;
/**
* 收款用户openid
*/
@XStreamAlias("openid")
private String openid;
/**
* 收款用户姓名
*/
@XStreamAlias("transfer_name")
private String transferName;
/**
* 付款金额
*/
@XStreamAlias("payment_amount")
private Integer paymentAmount;
/**
* 转账时间
*/
@XStreamAlias("transfer_time")
private String transferTime;
/**
* 付款描述
*/
@XStreamAlias("desc")
private String desc;
public String getPartnerTradeNo() {
return this.partnerTradeNo;
}
public void setPartnerTradeNo(String partnerTradeNo) {
this.partnerTradeNo = partnerTradeNo;
}
public String getDetailId() {
return this.detailId;
}
public void setDetailId(String detailId) {
this.detailId = detailId;
}
public String getStatus() {
return this.status;
}
public void setStatus(String status) {
this.status = status;
}
public String getReason() {
return this.reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public String getOpenid() {
return this.openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getTransferName() {
return this.transferName;
}
public void setTransferName(String transferName) {
this.transferName = transferName;
}
public Integer getPaymentAmount() {
return this.paymentAmount;
}
public void setPaymentAmount(Integer paymentAmount) {
this.paymentAmount = paymentAmount;
}
public String getTransferTime() {
return this.transferTime;
}
public void setTransferTime(String transferTime) {
this.transferTime = transferTime;
}
public String getDesc() {
return this.desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}

View File

@@ -0,0 +1,84 @@
package com.github.binarywang.wxpay.bean.result;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 企业付款返回结果
* Created by Binary Wang on 2016/10/02.
*
* @author binarywang (https://github.com/binarywang)
*/
@XStreamAlias("xml")
public class WxEntPayResult extends WxPayBaseResult {
/**
* 商户appid
*/
@XStreamAlias("mch_appid")
private String mchAppid;
/**
* 设备号
*/
@XStreamAlias("device_info")
private String deviceInfo;
//############以下字段在return_code 和result_code都为SUCCESS的时候有返回##############
/**
* 商户订单号
*/
@XStreamAlias("partner_trade_no")
private String partnerTradeNo;
/**
* 微信订单号
*/
@XStreamAlias("payment_no")
private String paymentNo;
/**
* 微信支付成功时间
*/
@XStreamAlias("payment_time")
private String paymentTime;
public String getMchAppid() {
return this.mchAppid;
}
public void setMchAppid(String mchAppid) {
this.mchAppid = mchAppid;
}
public String getDeviceInfo() {
return this.deviceInfo;
}
public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}
public String getPartnerTradeNo() {
return this.partnerTradeNo;
}
public void setPartnerTradeNo(String partnerTradeNo) {
this.partnerTradeNo = partnerTradeNo;
}
public String getPaymentNo() {
return this.paymentNo;
}
public void setPaymentNo(String paymentNo) {
this.paymentNo = paymentNo;
}
public String getPaymentTime() {
return this.paymentTime;
}
public void setPaymentTime(String paymentTime) {
this.paymentTime = paymentTime;
}
}

View File

@@ -0,0 +1,261 @@
package com.github.binarywang.wxpay.bean.result;
import com.google.common.collect.Maps;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import io.restassured.internal.path.xml.NodeChildrenImpl;
import io.restassured.internal.path.xml.NodeImpl;
import io.restassured.path.xml.XmlPath;
import io.restassured.path.xml.element.Node;
import io.restassured.path.xml.exception.XmlPathException;
import me.chanjar.weixin.common.util.ToStringUtils;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
import java.util.Iterator;
import java.util.Map;
/**
* <pre>
* 微信支付结果共用属性类
* Created by Binary Wang on 2016-10-24.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
public abstract class WxPayBaseResult {
/**
* 返回状态码
*/
@XStreamAlias("return_code")
protected String returnCode;
/**
* 返回信息
*/
@XStreamAlias("return_msg")
protected String returnMsg;
private String xmlString;
/**
* 业务结果
*/
@XStreamAlias("result_code")
private String resultCode;
/**
* 错误代码
*/
@XStreamAlias("err_code")
private String errCode;
/**
* 错误代码描述
*/
@XStreamAlias("err_code_des")
private String errCodeDes;
/**
* 公众账号ID
*/
@XStreamAlias("appid")
private String appid;
/**
* 商户号
*/
@XStreamAlias("mch_id")
private String mchId;
/**
* 服务商模式下的子公众账号ID
*/
@XStreamAlias("appid")
private String subAppId;
/**
* 服务商模式下的子商户号
*/
@XStreamAlias("sub_mch_id")
private String subMchId;
/**
* 随机字符串
*/
@XStreamAlias("nonce_str")
private String nonceStr;
/**
* 签名
*/
@XStreamAlias("sign")
private String sign;
/**
* 将单位分转换成单位圆
*
* @param fee 将要被转换为元的分的数值
*/
public static String feeToYuan(Integer fee) {
return new BigDecimal(Double.valueOf(fee) / 100).setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString();
}
/**
* 从xml字符串创建bean对象
*/
public static <T extends WxPayBaseResult> T fromXML(String xmlString, Class<T> clz) {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(clz);
T result = (T) xstream.fromXML(xmlString);
result.setXmlString(xmlString);
return result;
}
public String getXmlString() {
return this.xmlString;
}
public void setXmlString(String xmlString) {
this.xmlString = xmlString;
}
protected Logger getLogger() {
return LoggerFactory.getLogger(this.getClass());
}
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}
public String getReturnCode() {
return this.returnCode;
}
public void setReturnCode(String returnCode) {
this.returnCode = returnCode;
}
public String getReturnMsg() {
return this.returnMsg;
}
public void setReturnMsg(String returnMsg) {
this.returnMsg = returnMsg;
}
public String getResultCode() {
return this.resultCode;
}
public void setResultCode(String resultCode) {
this.resultCode = resultCode;
}
public String getErrCode() {
return this.errCode;
}
public void setErrCode(String errCode) {
this.errCode = errCode;
}
public String getErrCodeDes() {
return this.errCodeDes;
}
public void setErrCodeDes(String errCodeDes) {
this.errCodeDes = errCodeDes;
}
public String getAppid() {
return this.appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getMchId() {
return this.mchId;
}
public void setMchId(String mchId) {
this.mchId = mchId;
}
public String getNonceStr() {
return this.nonceStr;
}
public void setNonceStr(String nonceStr) {
this.nonceStr = nonceStr;
}
public String getSign() {
return this.sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getSubAppId() {
return subAppId;
}
public void setSubAppId(String subAppId) {
this.subAppId = subAppId;
}
public String getSubMchId() {
return subMchId;
}
public void setSubMchId(String subMchId) {
this.subMchId = subMchId;
}
/**
* 将bean通过保存的xml字符串转换成map
*/
public Map<String, String> toMap() {
Map<String, String> result = Maps.newHashMap();
XmlPath xmlPath = new XmlPath(this.xmlString);
NodeImpl rootNode = null;
try {
rootNode = xmlPath.get("xml");
} catch (XmlPathException e) {
throw new RuntimeException("xml数据有问题请核实");
}
if (rootNode == null) {
throw new RuntimeException("xml数据有问题请核实");
}
Iterator<Node> iterator = rootNode.children().nodeIterator();
while (iterator.hasNext()) {
Node node = iterator.next();
result.put(node.name(), node.value());
}
return result;
}
private String getXmlValue(XmlPath xmlPath, String path) {
if (xmlPath.get(path) instanceof NodeChildrenImpl) {
if (((NodeChildrenImpl) xmlPath.get(path)).size() == 0) {
return null;
}
}
return xmlPath.getString(path);
}
protected <T> T getXmlValue(XmlPath xmlPath, String path, Class<T> clz) {
String value = this.getXmlValue(xmlPath, path);
if (value == null) {
return null;
}
switch (clz.getSimpleName()) {
case "String":
return (T) value;
case "Integer":
return (T) Integer.valueOf(value);
}
throw new UnsupportedOperationException("暂时不支持此种类型的数据");
}
}

View File

@@ -0,0 +1,15 @@
package com.github.binarywang.wxpay.bean.result;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* <pre>
* 微信支付结果仅包含有return 和result等相关信息的的属性类
* Created by Binary Wang on 2017-01-09.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
@XStreamAlias("xml")
public class WxPayCommonResult extends WxPayBaseResult {
}

View File

@@ -0,0 +1,28 @@
package com.github.binarywang.wxpay.bean.result;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* <pre>
* 关闭订单结果对象类
* Created by Binary Wang on 2016-10-27.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
@XStreamAlias("xml")
public class WxPayOrderCloseResult extends WxPayBaseResult {
/**
* 业务结果描述
*/
@XStreamAlias("result_msg")
private String resultMsg;
public String getResultMsg() {
return this.resultMsg;
}
public void setResultMsg(String resultMsg) {
this.resultMsg = resultMsg;
}
}

View File

@@ -0,0 +1,392 @@
package com.github.binarywang.wxpay.bean.result;
import com.github.binarywang.wxpay.bean.WxPayOrderNotifyCoupon;
import com.github.binarywang.wxpay.converter.WxPayOrderNotifyResultConverter;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.util.BeanUtils;
import me.chanjar.weixin.common.util.ToStringUtils;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
/**
* 支付结果通用通知 文档见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
*
* @author aimilin6688
* @since 2.5.0
*/
@XStreamAlias("xml")
public class WxPayOrderNotifyResult extends WxPayBaseResult implements Serializable {
private static final long serialVersionUID = 5389718115223345496L;
/**
* <pre>
* 设备号
* device_info
* 否
* String(32)
* 013467007045764
* 微信支付分配的终端设备号,
* </pre>
*/
@XStreamAlias("device_info")
private String deviceInfo;
/**
* <pre>
* 用户标识
* openid
* 是
* String(128)
* wxd930ea5d5a258f4f
* 用户在商户appid下的唯一标识
* </pre>
*/
@XStreamAlias("openid")
private String openid;
/**
* <pre>
* 是否关注公众账号
* is_subscribe
* 否
* String(1)
* Y
* 用户是否关注公众账号Y-关注N-未关注,仅在公众账号类型支付有效
* </pre>
*/
@XStreamAlias("is_subscribe")
private String isSubscribe;
/**
* <pre>
* 交易类型
* trade_type
* 是
* String(16)
* JSAPI JSAPI、NATIVE、APP
* </pre>
*/
@XStreamAlias("trade_type")
private String tradeType;
/**
* <pre>
* 付款银行
* bank_type
* 是
* String(16)
* CMC
* 银行类型,采用字符串类型的银行标识,银行类型见银行列表
* </pre>
*/
@XStreamAlias("bank_type")
private String bankType;
/**
* <pre>
* 订单金额
* total_fee
* 是
* Int
* 100
* 订单总金额,单位为分
* </pre>
*/
@XStreamAlias("total_fee")
private Integer totalFee;
/**
* <pre>
* 应结订单金额
* settlement_total_fee
* 否
* Int
* 100
* 应结订单金额=订单金额-非充值代金券金额,应结订单金额<=订单金额。
* </pre>
*/
@XStreamAlias("settlement_total_fee")
private Integer settlementTotalFee;
/**
* <pre>
* 货币种类
* fee_type
* 否
* String(8)
* CNY
* 货币类型符合ISO4217标准的三位字母代码默认人民币CNY其他值列表详见货币类型
* </pre>
*/
@XStreamAlias("fee_type")
private String feeType;
/**
* <pre>
* 现金支付金额
* cash_fee
* 是
* Int
* 100
* 现金支付金额订单现金支付金额,详见支付金额
* </pre>
*/
@XStreamAlias("cash_fee")
private Integer cashFee;
/**
* <pre>
* 现金支付货币类型
* cash_fee_type
* 否
* String(16)
* CNY
* 货币类型符合ISO4217标准的三位字母代码默认人民币CNY其他值列表详见货币类型
* </pre>
*/
@XStreamAlias("cash_fee_type")
private String cashFeeType;
/**
* <pre>
* 总代金券金额
* coupon_fee
* 否
* Int
* 10
* 代金券金额<=订单金额,订单金额-代金券金额=现金支付金额,详见支付金额
* </pre>
*/
@XStreamAlias("coupon_fee")
private Integer couponFee;
/**
* <pre>
* 代金券使用数量
* coupon_count
* 否
* Int
* 1
* 代金券使用数量
* </pre>
*/
@XStreamAlias("coupon_count")
private Integer couponCount;
private List<WxPayOrderNotifyCoupon> couponList;
/**
* <pre>
* 微信支付订单号
* transaction_id
* 是
* String(32)
* 1217752501201407033233368018
* 微信支付订单号
* </pre>
*/
@XStreamAlias("transaction_id")
private String transactionId;
/**
* <pre>
* 商户订单号
* out_trade_no
* 是
* String(32)
* 1212321211201407033568112322
* 商户系统的订单号,与请求一致。
* </pre>
*/
@XStreamAlias("out_trade_no")
private String outTradeNo;
/**
* <pre>
* 商家数据包
* attach
* 否
* String(128)
* 123456
* 商家数据包,原样返回
* </pre>
*/
@XStreamAlias("attach")
private String attach;
/**
* <pre>
* 支付完成时间
* time_end
* 是
* String(14)
* 20141030133525
* 支付完成时间格式为yyyyMMddHHmmss如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
* </pre>
*/
@XStreamAlias("time_end")
private String timeEnd;
public static WxPayOrderNotifyResult fromXML(String xmlString) {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxPayOrderNotifyResult.class);
xstream.registerConverter(new WxPayOrderNotifyResultConverter(xstream.getMapper(), xstream.getReflectionProvider()));
WxPayOrderNotifyResult result = (WxPayOrderNotifyResult) xstream.fromXML(xmlString);
result.setXmlString(xmlString);
return result;
}
public Integer getCouponCount() {
return couponCount;
}
public void setCouponCount(Integer couponCount) {
this.couponCount = couponCount;
}
public List<WxPayOrderNotifyCoupon> getCouponList() {
return couponList;
}
public void setCouponList(List<WxPayOrderNotifyCoupon> couponList) {
this.couponList = couponList;
}
public String getDeviceInfo() {
return deviceInfo;
}
public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getIsSubscribe() {
return isSubscribe;
}
public void setIsSubscribe(String isSubscribe) {
this.isSubscribe = isSubscribe;
}
public String getTradeType() {
return tradeType;
}
public void setTradeType(String tradeType) {
this.tradeType = tradeType;
}
public String getBankType() {
return bankType;
}
public void setBankType(String bankType) {
this.bankType = bankType;
}
public Integer getTotalFee() {
return totalFee;
}
public void setTotalFee(Integer totalFee) {
this.totalFee = totalFee;
}
public Integer getSettlementTotalFee() {
return settlementTotalFee;
}
public void setSettlementTotalFee(Integer settlementTotalFee) {
this.settlementTotalFee = settlementTotalFee;
}
public String getFeeType() {
return feeType;
}
public void setFeeType(String feeType) {
this.feeType = feeType;
}
public Integer getCashFee() {
return cashFee;
}
public void setCashFee(Integer cashFee) {
this.cashFee = cashFee;
}
public String getCashFeeType() {
return cashFeeType;
}
public void setCashFeeType(String cashFeeType) {
this.cashFeeType = cashFeeType;
}
public Integer getCouponFee() {
return couponFee;
}
public void setCouponFee(Integer couponFee) {
this.couponFee = couponFee;
}
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getOutTradeNo() {
return outTradeNo;
}
public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}
public String getAttach() {
return attach;
}
public void setAttach(String attach) {
this.attach = attach;
}
public String getTimeEnd() {
return timeEnd;
}
public void setTimeEnd(String timeEnd) {
this.timeEnd = timeEnd;
}
@Override
public Map<String, String> toMap() {
Map<String, String> resultMap = BeanUtils.xmlBean2Map(this);
if (this.getCouponCount() != null && this.getCouponCount() > 0) {
for (int i = 0; i < this.getCouponCount(); i++) {
WxPayOrderNotifyCoupon coupon = couponList.get(i);
resultMap.putAll(coupon.toMap(i));
}
}
return resultMap;
}
@Override
public String toString() {
return ToStringUtils.toSimpleString(this);
}
}

View File

@@ -0,0 +1,474 @@
package com.github.binarywang.wxpay.bean.result;
import com.google.common.collect.Lists;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import io.restassured.path.xml.XmlPath;
import java.util.List;
/**
* <pre>
* 查询订单 返回结果对象
* Created by Binary Wang on 2016-10-24.
* 注释中各行每个字段描述对应如下:
* <li>字段名
* <li>变量名
* <li>是否必填
* <li>类型
* <li>示例值
* <li>描述
* </pre>
*
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
*/
@XStreamAlias("xml")
public class WxPayOrderQueryResult extends WxPayBaseResult {
/**
* <pre>设备号
* device_info
* 否
* String(32)
* 013467007045764
* 微信支付分配的终端设备号,
* </pre>
*/
@XStreamAlias("device_info")
private String deviceInfo;
/**
* <pre>用户标识
* openid
* 是
* String(128)
* oUpF8uMuAJO_M2pxb1Q9zNjWeS6o
* 用户在商户appid下的唯一标识
* </pre>
*/
@XStreamAlias("openid")
private String openid;
/**
* <pre>是否关注公众账号
* is_subscribe
* 否
* String(1)
* Y
* 用户是否关注公众账号Y-关注N-未关注,仅在公众账号类型支付有效
* </pre>
*/
@XStreamAlias("is_subscribe")
private String isSubscribe;
/**
* <pre>交易类型
* trade_type
* 是
* String(16)
* JSAPI
* 调用接口提交的交易类型取值如下JSAPINATIVEAPPMICROPAY详细说明见参数规定
* </pre>
*/
@XStreamAlias("trade_type")
private String tradeType;
/**
* <pre>交易状态
* trade_state
* 是
* String(32)
* SUCCESS
* SUCCESS—支付成功,REFUND—转入退款,NOTPAY—未支付,CLOSED—已关闭,REVOKED—已撤销刷卡支付,USERPAYING--用户支付中,PAYERROR--支付失败(其他原因,如银行返回失败)
* </pre>
*/
@XStreamAlias("trade_state")
private String tradeState;
/**
* <pre>付款银行
* bank_type
* 是
* String(16)
* CMC
* 银行类型,采用字符串类型的银行标识
* </pre>
*/
@XStreamAlias("bank_type")
private String bankType;
/**
* <pre>订单金额
* total_fee
* 是
* Int
* 100
* 订单总金额,单位为分
* </pre>
*/
@XStreamAlias("total_fee")
private Integer totalFee;
/**
* <pre>应结订单金额
* settlement_total_fee
* 否
* Int
* 100
* 应结订单金额=订单金额-非充值代金券金额,应结订单金额<=订单金额。
* </pre>
*/
@XStreamAlias("settlement_total_fee")
private Integer settlementTotalFee;
/**
* <pre>货币种类
* fee_type
* 否
* String(8)
* CNY
* 货币类型符合ISO 4217标准的三位字母代码默认人民币CNY其他值列表详见货币类型
* </pre>
*/
@XStreamAlias("fee_type")
private String feeType;
/**
* <pre>现金支付金额
* cash_fee
* 是
* Int
* 100
* 现金支付金额订单现金支付金额,详见支付金额
* </pre>
*/
@XStreamAlias("cash_fee")
private Integer cashFee;
/**
* <pre>现金支付货币类型
* cash_fee_type
* 否
* String(16)
* CNY
* 货币类型符合ISO 4217标准的三位字母代码默认人民币CNY其他值列表详见货币类型
* </pre>
*/
@XStreamAlias("cash_fee_type")
private String cashFeeType;
/**
* <pre>代金券金额
* coupon_fee
* 否
* Int
* 100
* “代金券”金额<=订单金额,订单金额-“代金券”金额=现金支付金额,详见支付金额
* </pre>
*/
@XStreamAlias("coupon_fee")
private Integer couponFee;
/**
* <pre>代金券使用数量
* coupon_count
* 否
* Int
* 1
* 代金券使用数量
* </pre>
*/
@XStreamAlias("coupon_count")
private Integer couponCount;
private List<Coupon> coupons;
/**
* <pre>微信支付订单号
* transaction_id
* 是
* String(32)
* 1009660380201506130728806387
* 微信支付订单号
* </pre>
*/
@XStreamAlias("transaction_id")
private String transactionId;
/**
* <pre>商户订单号
* out_trade_no
* 是
* String(32)
* 20150806125346
* 商户系统的订单号,与请求一致。
* </pre>
*/
@XStreamAlias("out_trade_no")
private String outTradeNo;
/**
* <pre>附加数据
* attach
* 否
* String(128)
* 深圳分店
* 附加数据,原样返回
* </pre>
*/
@XStreamAlias("attach")
private String attach;
/**
* <pre>支付完成时间
* time_end
* 是
* String(14)
* 20141030133525
* 订单支付时间格式为yyyyMMddHHmmss如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
* </pre>
*/
@XStreamAlias("time_end")
private String timeEnd;
/**
* <pre>交易状态描述
* trade_state_desc
* 是
* String(256)
* 支付失败,请重新下单支付
* 对当前查询订单状态的描述和下一步操作的指引
* </pre>
*/
@XStreamAlias("trade_state_desc")
private String tradeStateDesc;
public String getDeviceInfo() {
return this.deviceInfo;
}
public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}
public String getOpenid() {
return this.openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getIsSubscribe() {
return this.isSubscribe;
}
public void setIsSubscribe(String isSubscribe) {
this.isSubscribe = isSubscribe;
}
public String getTradeType() {
return this.tradeType;
}
public void setTradeType(String tradeType) {
this.tradeType = tradeType;
}
public String getTradeState() {
return this.tradeState;
}
public void setTradeState(String tradeState) {
this.tradeState = tradeState;
}
public String getBankType() {
return this.bankType;
}
public void setBankType(String bankType) {
this.bankType = bankType;
}
public Integer getTotalFee() {
return this.totalFee;
}
public void setTotalFee(Integer totalFee) {
this.totalFee = totalFee;
}
public Integer getSettlementTotalFee() {
return this.settlementTotalFee;
}
public void setSettlementTotalFee(Integer settlementTotalFee) {
this.settlementTotalFee = settlementTotalFee;
}
public String getFeeType() {
return this.feeType;
}
public void setFeeType(String feeType) {
this.feeType = feeType;
}
public Integer getCashFee() {
return this.cashFee;
}
public void setCashFee(Integer cashFee) {
this.cashFee = cashFee;
}
public String getCashFeeType() {
return this.cashFeeType;
}
public void setCashFeeType(String cashFeeType) {
this.cashFeeType = cashFeeType;
}
public Integer getCouponFee() {
return this.couponFee;
}
public void setCouponFee(Integer couponFee) {
this.couponFee = couponFee;
}
public Integer getCouponCount() {
return this.couponCount;
}
public void setCouponCount(Integer couponCount) {
this.couponCount = couponCount;
}
public List<Coupon> getCoupons() {
return this.coupons;
}
public void setCoupons(List<Coupon> coupons) {
this.coupons = coupons;
}
public String getTransactionId() {
return this.transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getOutTradeNo() {
return this.outTradeNo;
}
public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}
public String getAttach() {
return this.attach;
}
public void setAttach(String attach) {
this.attach = attach;
}
public String getTimeEnd() {
return this.timeEnd;
}
public void setTimeEnd(String timeEnd) {
this.timeEnd = timeEnd;
}
public String getTradeStateDesc() {
return this.tradeStateDesc;
}
public void setTradeStateDesc(String tradeStateDesc) {
this.tradeStateDesc = tradeStateDesc;
}
/**
* 通过xml组装coupons属性内容
*/
public void composeCoupons() {
if (this.couponCount != null && this.couponCount > 0) {
this.coupons = Lists.newArrayList();
XmlPath xmlPath = new XmlPath(this.getXmlString());
for (int i = 0; i < this.couponCount; i++) {
this.coupons.add(new Coupon(this.getXmlValue(xmlPath, "xml.coupon_type_" + i, String.class),
this.getXmlValue(xmlPath, "xml.coupon_id_" + i, String.class),
this.getXmlValue(xmlPath, "xml.coupon_fee_" + i, Integer.class)));
}
}
}
public static class Coupon {
/**
* <pre>代金券类型
* coupon_type_$n
* 否
* String
* CASH
* <li>CASH--充值代金券
* <li>NO_CASH---非充值代金券
* 订单使用代金券时有返回取值CASH、NO_CASH。$n为下标,从0开始编号举例coupon_type_$0
* </pre>
*/
private String couponType;
/**
* <pre>代金券ID
* coupon_id_$n
* 否
* String(20)
* 10000
* 代金券ID, $n为下标从0开始编号
* </pre>
*/
private String couponId;
/**
* <pre>单个代金券支付金额
* coupon_fee_$n
* 否
* Int
* 100
* 单个代金券支付金额, $n为下标从0开始编号
* </pre>
*/
private Integer couponFee;
public Coupon(String couponType, String couponId, Integer couponFee) {
this.couponType = couponType;
this.couponId = couponId;
this.couponFee = couponFee;
}
public String getCouponType() {
return this.couponType;
}
public void setCouponType(String couponType) {
this.couponType = couponType;
}
public String getCouponId() {
return this.couponId;
}
public void setCouponId(String couponId) {
this.couponId = couponId;
}
public Integer getCouponFee() {
return this.couponFee;
}
public void setCouponFee(Integer couponFee) {
this.couponFee = couponFee;
}
}
}

View File

@@ -0,0 +1,406 @@
package com.github.binarywang.wxpay.bean.result;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* <pre>
* 注释中各行对应含义:
* 字段名
* 字段
* 必填
* 示例值
* 类型
* 说明
* Created by Binary Wang on 2016-11-28.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
@XStreamAlias("xml")
public class WxPayRedpackQueryResult extends WxPayBaseResult {
/**
* <pre>
* 商户订单号
* mch_billno
* 是
* 10000098201411111234567890
* String(28)
* 商户使用查询API填写的商户单号的原路返回
* </pre>
*/
@XStreamAlias("mch_billno")
private String mchBillNo;
/**
* <pre>
* 红包单号
* detail_id
* 是
* 1000000000201503283103439304
* String(32)
* 使用API发放现金红包时返回的红包单号
* </pre>
*/
@XStreamAlias("detail_id")
private String detailId;
/**
* <pre>
* 红包状态
* status
* 是
* RECEIVED
* string(16)
* SENDING:发放中,
* SENT:已发放待领取,
* FAILED发放失败
* RECEIVED:已领取,
* RFUND_ING:退款中,
* REFUND:已退款
* </pre>
*/
@XStreamAlias("status")
private String status;
/**
* <pre>
* 发放类型
* send_type
* 是
* API
* String(32)
* API:通过API接口发放
* UPLOAD:通过上传文件方式发放,
* ACTIVITY:通过活动方式发放
* </pre>
*/
@XStreamAlias("send_type")
private String sendType;
/**
* <pre>
* 红包类型
* hb_type
* 是
* GROUP
* String(32)
* GROUP:裂变红包,
* NORMAL:普通红包
* </pre>
*/
@XStreamAlias("hb_type")
private String hbType;
/**
* <pre>
* 红包个数
* total_num
* 是
* 1
* int
* 红包个数
* </pre>
*/
@XStreamAlias("total_num")
private Integer totalNum;
/**
* <pre>
* 红包金额
* total_amount
* 是
* 5000
* int
* 红包总金额(单位分)
* </pre>
*/
@XStreamAlias("total_amount")
private Integer totalAmount;
/**
* <pre>
* 失败原因
* reason
* 否
* 余额不足
* String(32)
* 发送失败原因
* </pre>
*/
@XStreamAlias("reason")
private String reason;
/**
* <pre>
* 红包发送时间
* send_time
* 是
* 2015-04-21 20:00:00
* String(32)
* 红包的发送时间
* </pre>
*/
@XStreamAlias("send_time")
private String sendTime;
/**
* <pre>
* 红包退款时间
* refund_time
* 否
* 2015-04-21 23:03:00
* String(32)
* 红包的退款时间(如果其未领取的退款)
* </pre>
*/
@XStreamAlias("refund_time")
private String refundTime;
/**
* <pre>
* 红包退款金额
* refund_amount
* 否
* 8000
* Int
* 红包退款金额
* </pre>
*/
@XStreamAlias("refund_amount")
private Integer refundAmount;
/**
* <pre>
* 祝福语
* wishing
* 否
* 新年快乐
* String(128)
* 祝福语
* </pre>
*/
@XStreamAlias("wishing")
private String wishing;
/**
* <pre>
* 活动描述
* remark
* 否
* 新年红包
* String(256)
* 活动描述,低版本微信可见
* </pre>
*/
@XStreamAlias("remark")
private String remark;
/**
* <pre>
* 活动名称
* act_name
* 否
* 新年红包
* String(32)
* 发红包的活动名称
* </pre>
*/
@XStreamAlias("act_name")
private String actName;
/**
* <pre>
* 裂变红包领取列表
* hblist
* 否
*
*
* 裂变红包的领取列表
* </pre>
*/
@XStreamAlias("hblist")
private String hblist;
/**
* <pre>
* 领取红包的Openid
* openid
* 是
* ohO4GtzOAAYMp2yapORH3dQB3W18
* String(32)
* 领取红包的openid
* </pre>
*/
@XStreamAlias("openid")
private String openid;
/**
* <pre>
* 金额
* amount
* 是
* 100
* int
* 领取金额
* </pre>
*/
@XStreamAlias("amount")
private Integer amount;
/**
* <pre>
* 接收时间
* rcv_time
* 是
* 2015-04-21 20:00:00
* String(32)
* 领取红包的时间
* </pre>
*/
@XStreamAlias("rcv_time")
private String receiveTime;
public String getMchBillNo() {
return mchBillNo;
}
public void setMchBillNo(String mchBillNo) {
this.mchBillNo = mchBillNo;
}
public String getDetailId() {
return detailId;
}
public void setDetailId(String detailId) {
this.detailId = detailId;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getSendType() {
return sendType;
}
public void setSendType(String sendType) {
this.sendType = sendType;
}
public String getHbType() {
return hbType;
}
public void setHbType(String hbType) {
this.hbType = hbType;
}
public Integer getTotalNum() {
return totalNum;
}
public void setTotalNum(Integer totalNum) {
this.totalNum = totalNum;
}
public Integer getTotalAmount() {
return totalAmount;
}
public void setTotalAmount(Integer totalAmount) {
this.totalAmount = totalAmount;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public String getSendTime() {
return sendTime;
}
public void setSendTime(String sendTime) {
this.sendTime = sendTime;
}
public String getRefundTime() {
return refundTime;
}
public void setRefundTime(String refundTime) {
this.refundTime = refundTime;
}
public Integer getRefundAmount() {
return refundAmount;
}
public void setRefundAmount(Integer refundAmount) {
this.refundAmount = refundAmount;
}
public String getWishing() {
return wishing;
}
public void setWishing(String wishing) {
this.wishing = wishing;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getActName() {
return actName;
}
public void setActName(String actName) {
this.actName = actName;
}
public String getHblist() {
return hblist;
}
public void setHblist(String hblist) {
this.hblist = hblist;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public Integer getAmount() {
return amount;
}
public void setAmount(Integer amount) {
this.amount = amount;
}
public String getReceiveTime() {
return receiveTime;
}
public void setReceiveTime(String receiveTime) {
this.receiveTime = receiveTime;
}
}

View File

@@ -0,0 +1,532 @@
package com.github.binarywang.wxpay.bean.result;
import com.google.common.collect.Lists;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import io.restassured.path.xml.XmlPath;
import java.util.List;
/**
* <pre>
* Created by Binary Wang on 2016-11-24.
* @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a>
* </pre>
*/
@XStreamAlias("xml")
public class WxPayRefundQueryResult extends WxPayBaseResult {
/**
* <pre>
* 设备号
* device_info
* 否
* String(32)
* 013467007045764
* 终端设备号
*/
@XStreamAlias("device_info")
private String deviceInfo;
/**
* <pre>
* 微信订单号
* transaction_id
* 是
* String(32)
* 1217752501201407033233368018
* 微信订单号
*/
@XStreamAlias("transaction_id")
private String transactionId;
/**
* <pre>
* 商户订单号
* out_trade_no
* 是
* String(32)
* 1217752501201407033233368018
* 商户系统内部的订单号
*/
@XStreamAlias("out_trade_no")
private String outTradeNo;
/**
* <pre>
* 订单金额
* total_fee
* 是
* Int
* 100
* 订单总金额,单位为分,只能为整数,详见支付金额
*/
@XStreamAlias("total_fee")
private Integer totalFee;
/**
* <pre>
* 应结订单金额
* settlement_total_fee
* 否
* Int
* 100
* 应结订单金额=订单金额-非充值代金券金额,应结订单金额<=订单金额。
*/
@XStreamAlias("settlement_total_fee")
private Integer settlementTotalFee;
/**
* <pre>
* 货币种类
* fee_type
* 否
* String(8)
* CNY
* 订单金额货币类型符合ISO 4217标准的三位字母代码默认人民币CNY其他值列表详见货币类型
*/
@XStreamAlias("fee_type")
private String feeType;
/**
* <pre>
* 现金支付金额
* cash_fee
* 是
* Int
* 100
* 现金支付金额,单位为分,只能为整数,详见支付金额
*/
@XStreamAlias("cash_fee")
private Integer cashFee;
/**
* <pre>
* 退款笔数
* refund_count
* 是
* Int
* 1
* 退款记录数
*/
@XStreamAlias("refund_count")
private Integer refundCount;
private List<RefundRecord> refundRecords;
public String getDeviceInfo() {
return deviceInfo;
}
public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getOutTradeNo() {
return outTradeNo;
}
public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}
public Integer getTotalFee() {
return totalFee;
}
public void setTotalFee(Integer totalFee) {
this.totalFee = totalFee;
}
public Integer getSettlementTotalFee() {
return settlementTotalFee;
}
public void setSettlementTotalFee(Integer settlementTotalFee) {
this.settlementTotalFee = settlementTotalFee;
}
public String getFeeType() {
return feeType;
}
public void setFeeType(String feeType) {
this.feeType = feeType;
}
public Integer getCashFee() {
return cashFee;
}
public void setCashFee(Integer cashFee) {
this.cashFee = cashFee;
}
public Integer getRefundCount() {
return refundCount;
}
public void setRefundCount(Integer refundCount) {
this.refundCount = refundCount;
}
public List<RefundRecord> getRefundRecords() {
return refundRecords;
}
public void setRefundRecords(List<RefundRecord> refundRecords) {
this.refundRecords = refundRecords;
}
/**
* 组装生成退款记录属性的内容
*/
public void composeRefundRecords() {
if (this.refundCount != null && this.refundCount > 0) {
this.refundRecords = Lists.newArrayList();
XmlPath xmlPath = new XmlPath(this.getXmlString());
for (int i = 0; i < this.refundCount; i++) {
RefundRecord refundRecord = new RefundRecord();
this.refundRecords.add(refundRecord);
refundRecord.setOutRefundNo(this.getXmlValue(xmlPath, "xml.out_refund_no_" + i, String.class));
refundRecord.setRefundId(this.getXmlValue(xmlPath, "xml.refund_id_" + i, String.class));
refundRecord.setRefundChannel(this.getXmlValue(xmlPath, "xml.refund_channel_" + i, String.class));
refundRecord.setRefundFee(this.getXmlValue(xmlPath, "xml.refund_fee_" + i, Integer.class));
refundRecord.setSettlementRefundFee(this.getXmlValue(xmlPath, "xml.settlement_refund_fee_" + i, Integer.class));
refundRecord.setCouponType(this.getXmlValue(xmlPath, "xml.coupon_type_" + i, String.class));
refundRecord.setCouponRefundFee(this.getXmlValue(xmlPath, "xml.coupon_refund_fee_" + i, Integer.class));
refundRecord.setCouponRefundCount(this.getXmlValue(xmlPath, "xml.coupon_refund_count_" + i, Integer.class));
refundRecord.setRefundStatus(this.getXmlValue(xmlPath, "xml.refund_status_" + i, String.class));
refundRecord.setRefundRecvAccout(this.getXmlValue(xmlPath, "xml.refund_recv_accout_" + i, String.class));
if (refundRecord.getCouponRefundCount() == null || refundRecord.getCouponRefundCount() == 0) {
continue;
}
List<RefundRecord.RefundCoupon> coupons = Lists.newArrayList();
for (int j = 0; j < refundRecord.getCouponRefundCount(); j++) {
coupons.add(
new RefundRecord.RefundCoupon(
this.getXmlValue(xmlPath, "xml.coupon_refund_id_" + i + "_" + j, String.class),
this.getXmlValue(xmlPath, "xml.coupon_refund_fee_" + i + "_" + j, Integer.class)
)
);
}
}
}
}
public static class RefundRecord {
/**
* <pre>
* 商户退款单号
* out_refund_no_$n
* 是
* String(32)
* 1217752501201407033233368018
* 商户退款单号
* </pre>
*/
@XStreamAlias("out_refund_no")
private String outRefundNo;
/**
* <pre>
* 微信退款单号
* refund_id_$n
* 是
* String(28)
* 1217752501201407033233368018
* 微信退款单号
* </pre>
*/
@XStreamAlias("refund_id")
private String refundId;
/**
* <pre>
* 退款渠道
* refund_channel_$n
* 否
* String(16)
* ORIGINAL
* ORIGINAL—原路退款 BALANCE—退回到余额
* </pre>
*/
@XStreamAlias("refund_channel")
private String refundChannel;
/**
* <pre>
* 申请退款金额
* refund_fee_$n
* 是
* Int
* 100
* 退款总金额,单位为分,可以做部分退款
* </pre>
*/
@XStreamAlias("refund_fee")
private Integer refundFee;
/**
* <pre>
* 退款金额
* settlement_refund_fee_$n
* 否
* Int
* 100
* 退款金额=申请退款金额-非充值代金券退款金额,退款金额<=申请退款金额
* </pre>
*/
@XStreamAlias("settlement_refund_fee")
private Integer settlementRefundFee;
/**
* <pre>
* 退款资金来源
* refund_account
* 否
* String(30)
* REFUND_SOURCE_RECHARGE_FUNDS
* REFUND_SOURCE_RECHARGE_FUNDS---可用余额退款/基本账户, REFUND_SOURCE_UNSETTLED_FUNDS---未结算资金退款
* </pre>
*/
@XStreamAlias("refund_account")
private String refundAccount;
/**
* <pre>
* 代金券类型
* coupon_type_$n
* 否
* Int
* CASH
* CASH--充值代金券 , NO_CASH---非充值代金券。订单使用代金券时有返回取值CASH、NO_CASH。$n为下标,从0开始编号举例coupon_type_$0
* </pre>
*/
@XStreamAlias("coupon_type")
private String couponType;
/**
* <pre>
* 代金券退款金额
* coupon_refund_fee_$n
* 否
* Int
* 100
* 代金券退款金额<=退款金额,退款金额-代金券或立减优惠退款金额为现金,说明详见代金券或立减优惠
* </pre>
*/
@XStreamAlias("coupon_refund_fee")
private Integer couponRefundFee;
/**
* <pre>
* 退款代金券使用数量
* coupon_refund_count_$n
* 否
* Int
* 1
* 退款代金券使用数量 ,$n为下标,从0开始编号
* </pre>
*/
@XStreamAlias("coupon_refund_count")
private Integer couponRefundCount;
private List<RefundCoupon> refundCoupons;
/**
* <pre>
* 退款状态
* refund_status_$n
* 是
* String(16)
* SUCCESS
* 退款状态:
* SUCCESS—退款成功
* FAIL—退款失败
* PROCESSING—退款处理中
* CHANGE—转入代发
* 退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,资金回流到商户的现金帐号,需要商户人工干预,通过线下或者财付通转账的方式进行退款。
* </pre>
*/
@XStreamAlias("refund_status")
private String refundStatus;
/**
* <pre>
* 退款入账账户
* refund_recv_accout_$n
* 是
* String(64)
* 招商银行信用卡0403
* 取当前退款单的退款入账方1退回银行卡{银行名称}{卡类型}{卡尾号}2退回支付用户零钱:支付用户零钱
* </pre>
*/
@XStreamAlias("refund_recv_accout")
private String refundRecvAccout;
public String getOutRefundNo() {
return outRefundNo;
}
public void setOutRefundNo(String outRefundNo) {
this.outRefundNo = outRefundNo;
}
public String getRefundId() {
return refundId;
}
public void setRefundId(String refundId) {
this.refundId = refundId;
}
public String getRefundChannel() {
return refundChannel;
}
public void setRefundChannel(String refundChannel) {
this.refundChannel = refundChannel;
}
public Integer getRefundFee() {
return refundFee;
}
public void setRefundFee(Integer refundFee) {
this.refundFee = refundFee;
}
public Integer getSettlementRefundFee() {
return settlementRefundFee;
}
public void setSettlementRefundFee(Integer settlementRefundFee) {
this.settlementRefundFee = settlementRefundFee;
}
public String getRefundAccount() {
return refundAccount;
}
public void setRefundAccount(String refundAccount) {
this.refundAccount = refundAccount;
}
public String getCouponType() {
return couponType;
}
public void setCouponType(String couponType) {
this.couponType = couponType;
}
public Integer getCouponRefundFee() {
return couponRefundFee;
}
public void setCouponRefundFee(Integer couponRefundFee) {
this.couponRefundFee = couponRefundFee;
}
public Integer getCouponRefundCount() {
return couponRefundCount;
}
public void setCouponRefundCount(Integer couponRefundCount) {
this.couponRefundCount = couponRefundCount;
}
public List<RefundCoupon> getRefundCoupons() {
return refundCoupons;
}
public void setRefundCoupons(List<RefundCoupon> refundCoupons) {
this.refundCoupons = refundCoupons;
}
public String getRefundStatus() {
return refundStatus;
}
public void setRefundStatus(String refundStatus) {
this.refundStatus = refundStatus;
}
public String getRefundRecvAccout() {
return refundRecvAccout;
}
public void setRefundRecvAccout(String refundRecvAccout) {
this.refundRecvAccout = refundRecvAccout;
}
public static class RefundCoupon {
/**
* <pre>
* 退款代金券批次ID
* coupon_refund_batch_id_$n_$m
* 否
* String(20)
* 100
* 退款代金券批次ID ,$n为下标$m为下标从0开始编号
* </pre>
*
* @deprecated 貌似是被去掉了,但不知是何时!
*/
@XStreamAlias("coupon_refund_batch_id")
private String couponRefundBatchId;
/**
* <pre>
* 退款代金券ID
* coupon_refund_id_$n_$m
* 否
* String(20)
* 10000
* 退款代金券ID, $n为下标$m为下标从0开始编号
* </pre>
*/
@XStreamAlias("coupon_refund_id")
private String couponRefundId;
/**
* <pre>
* 单个退款代金券支付金额
* coupon_refund_fee_$n_$m
* 否
* Int
* 100
* 单个退款代金券支付金额, $n为下标$m为下标从0开始编号
* </pre>
*/
@XStreamAlias("coupon_refund_fee")
private Integer couponRefundFee;
public RefundCoupon(String couponRefundId, Integer couponRefundFee) {
this.couponRefundId = couponRefundId;
this.couponRefundFee = couponRefundFee;
}
@Deprecated
public RefundCoupon(String couponRefundBatchId, String couponRefundId, Integer couponRefundFee) {
this.couponRefundBatchId = couponRefundBatchId;
this.couponRefundId = couponRefundId;
this.couponRefundFee = couponRefundFee;
}
}
}
}

View File

@@ -0,0 +1,173 @@
package com.github.binarywang.wxpay.bean.result;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import java.io.Serializable;
/**
* <pre>
* 微信支付-申请退款返回结果
* https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
* </pre>
*
* @author liukaitj
*/
@XStreamAlias("xml")
public class WxPayRefundResult extends WxPayBaseResult implements Serializable {
private static final long serialVersionUID = 1L;
@XStreamAlias("device_info")
private String deviceInfo;
@XStreamAlias("transaction_id")
private String transactionId;
@XStreamAlias("out_trade_no")
private String outTradeNo;
@XStreamAlias("out_refund_no")
private String outRefundNo;
@XStreamAlias("refund_id")
private String refundId;
@XStreamAlias("refund_channel")
private String refundChannel;
@XStreamAlias("refund_fee")
private String refundFee;
@XStreamAlias("total_fee")
private String totalFee;
@XStreamAlias("fee_type")
private String feeType;
@XStreamAlias("cash_fee")
private String cashFee;
@XStreamAlias("cash_refund_fee")
private String cashRefundFee;
@XStreamAlias("coupon_refund_fee")
private String couponRefundFee;
@XStreamAlias("coupon_refund_count")
private String couponRefundCount;
@XStreamAlias("coupon_refund_id")
private String couponRefundId;
public String getDeviceInfo() {
return this.deviceInfo;
}
public void setDeviceInfo(String deviceInfo) {
this.deviceInfo = deviceInfo;
}
public String getTransactionId() {
return this.transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId;
}
public String getOutTradeNo() {
return this.outTradeNo;
}
public void setOutTradeNo(String outTradeNo) {
this.outTradeNo = outTradeNo;
}
public String getOutRefundNo() {
return this.outRefundNo;
}
public void setOutRefundNo(String outRefundNo) {
this.outRefundNo = outRefundNo;
}
public String getRefundId() {
return this.refundId;
}
public void setRefundId(String refundId) {
this.refundId = refundId;
}
public String getRefundChannel() {
return this.refundChannel;
}
public void setRefundChannel(String refundChannel) {
this.refundChannel = refundChannel;
}
public String getRefundFee() {
return this.refundFee;
}
public void setRefundFee(String refundFee) {
this.refundFee = refundFee;
}
public String getTotalFee() {
return this.totalFee;
}
public void setTotalFee(String totalFee) {
this.totalFee = totalFee;
}
public String getFeeType() {
return this.feeType;
}
public void setFeeType(String feeType) {
this.feeType = feeType;
}
public String getCashFee() {
return this.cashFee;
}
public void setCashFee(String cashFee) {
this.cashFee = cashFee;
}
public String getCashRefundFee() {
return this.cashRefundFee;
}
public void setCashRefundFee(String cashRefundFee) {
this.cashRefundFee = cashRefundFee;
}
public String getCouponRefundFee() {
return this.couponRefundFee;
}
public void setCouponRefundFee(String couponRefundFee) {
this.couponRefundFee = couponRefundFee;
}
public String getCouponRefundCount() {
return this.couponRefundCount;
}
public void setCouponRefundCount(String couponRefundCount) {
this.couponRefundCount = couponRefundCount;
}
public String getCouponRefundId() {
return this.couponRefundId;
}
public void setCouponRefundId(String couponRefundId) {
this.couponRefundId = couponRefundId;
}
}

View File

@@ -0,0 +1,82 @@
package com.github.binarywang.wxpay.bean.result;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import java.io.Serializable;
/**
* 向微信用户个人发现金红包返回结果
* https://pay.weixin.qq.com/wiki/doc/api/cash_coupon.php?chapter=13_5
*
* @author kane
*/
@XStreamAlias("xml")
public class WxPaySendRedpackResult extends WxPayBaseResult implements Serializable {
private static final long serialVersionUID = -4837415036337132073L;
@XStreamAlias("mch_billno")
private String mchBillno;
@XStreamAlias("wxappid")
private String wxappid;
@XStreamAlias("re_openid")
private String reOpenid;
@XStreamAlias("total_amount")
private int totalAmount;
@XStreamAlias("send_time")
private String sendTime;
@XStreamAlias("send_listid")
private String sendListid;
public String getMchBillno() {
return this.mchBillno;
}
public void setMchBillno(String mchBillno) {
this.mchBillno = mchBillno;
}
public String getWxappid() {
return this.wxappid;
}
public void setWxappid(String wxappid) {
this.wxappid = wxappid;
}
public String getReOpenid() {
return this.reOpenid;
}
public void setReOpenid(String reOpenid) {
this.reOpenid = reOpenid;
}
public int getTotalAmount() {
return this.totalAmount;
}
public void setTotalAmount(int totalAmount) {
this.totalAmount = totalAmount;
}
public String getSendTime() {
return this.sendTime;
}
public void setSendTime(String sendTime) {
this.sendTime = sendTime;
}
public String getSendListid() {
return this.sendListid;
}
public void setSendListid(String sendListid) {
this.sendListid = sendListid;
}
}

View File

@@ -0,0 +1,57 @@
package com.github.binarywang.wxpay.bean.result;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* <pre>
* 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识"返回的结果
* 统一下单(详见http://com.github.binarywang.wechat.pay.bean.pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
* </pre>
*
* @author chanjarster
*/
@XStreamAlias("xml")
public class WxPayUnifiedOrderResult extends WxPayBaseResult {
/**
* 微信生成的预支付回话标识用于后续接口调用中使用该值有效期为2小时
*/
@XStreamAlias("prepay_id")
private String prepayId;
/**
* 交易类型取值为JSAPINATIVEAPP等
*/
@XStreamAlias("trade_type")
private String tradeType;
/**
* trade_type为NATIVE时有返回用于生成二维码展示给用户进行扫码支付
*/
@XStreamAlias("code_url")
private String codeURL;
public String getPrepayId() {
return this.prepayId;
}
public void setPrepayId(String prepayId) {
this.prepayId = prepayId;
}
public String getTradeType() {
return this.tradeType;
}
public void setTradeType(String tradeType) {
this.tradeType = tradeType;
}
public String getCodeURL() {
return this.codeURL;
}
public void setCodeURL(String codeURL) {
this.codeURL = codeURL;
}
}

View File

@@ -0,0 +1,157 @@
package com.github.binarywang.wxpay.config;
import org.apache.http.ssl.SSLContexts;
import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
/**
* 微信支付配置
*
* @author Binary Wang (https://github.com/binarywang)
*/
public class WxPayConfig {
private String appId;
private String subAppId;
private String mchId;
private String mchKey;
private String subMchId;
private String notifyUrl;
private String tradeType;
private SSLContext sslContext;
private String keyPath;
public void setNotifyUrl(String notifyUrl) {
this.notifyUrl = notifyUrl;
}
public void setTradeType(String tradeType) {
this.tradeType = tradeType;
}
/**
* 设置证书
* @param keyPath apiclient_cert.p12的文件的绝对路径
*/
public void setKeyPath(String keyPath) {
this.keyPath = keyPath;
}
public String getKeyPath() {
return keyPath;
}
public void setAppId(String appId) {
this.appId = appId;
}
public void setSubAppId(String subAppId) {
this.subAppId = subAppId;
}
public void setMchId(String mchId) {
this.mchId = mchId;
}
public void setMchKey(String mchKey) {
this.mchKey = mchKey;
}
public void setSubMchId(String subMchId) {
this.subMchId = subMchId;
}
public void setSslContext(SSLContext sslContext) {
this.sslContext = sslContext;
}
/**
* 商户号
*/
public String getMchId() {
return this.mchId;
}
/**
* 商户密钥
*/
public String getMchKey() {
return this.mchKey;
}
/**
* 公众号appid
*/
public String getAppId() {
return this.appId;
}
/**
* 服务商模式下的子商户公众账号ID
*/
public String getSubAppId() {
return this.subAppId;
}
/**
* 服务商模式下的子商户号
*/
public String getSubMchId() {
return this.subMchId;
}
/**
* 微信支付异步回掉地址通知url必须为直接可访问的url不能携带参数。
*/
public String getNotifyUrl() {
return this.notifyUrl;
}
/**
* 交易类型
* <pre>
* JSAPI--公众号支付
* NATIVE--原生扫码支付
* APP--app支付
* </pre>
*/
public String getTradeType() {
return this.tradeType;
}
public SSLContext getSslContext() {
return this.sslContext;
}
/**
* 微信支付是否使用仿真测试环境
* 默认不使用
*/
public boolean useSandboxForWxPay() {
return false;
}
public SSLContext initSSLContext() {
if (null == mchId) {
throw new IllegalArgumentException("请確保mchId已設置");
}
File file = new File(this.keyPath);
if (!file.exists()) {
throw new RuntimeException("证书文件:【" + file.getPath() + "】不存在!");
}
try {
FileInputStream inputStream = new FileInputStream(file);
KeyStore keystore = KeyStore.getInstance("PKCS12");
char[] partnerId2charArray = mchId.toCharArray();
keystore.load(inputStream, partnerId2charArray);
this.sslContext = SSLContexts.custom().loadKeyMaterial(keystore, partnerId2charArray).build();
return this.sslContext;
} catch (Exception e) {
throw new RuntimeException("证书文件有问题,请核实!", e);
}
}
}

View File

@@ -0,0 +1,129 @@
package com.github.binarywang.wxpay.converter;
import com.github.binarywang.wxpay.bean.WxPayOrderNotifyCoupon;
import com.github.binarywang.wxpay.bean.result.WxPayOrderNotifyResult;
import com.google.common.base.Function;
import com.google.common.collect.Maps;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter;
import com.thoughtworks.xstream.converters.reflection.ReflectionProvider;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.mapper.Mapper;
import org.apache.commons.lang3.StringUtils;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class WxPayOrderNotifyResultConverter extends AbstractReflectionConverter {
public WxPayOrderNotifyResultConverter(Mapper mapper, ReflectionProvider reflectionProvider) {
super(mapper, reflectionProvider);
}
@Override
@SuppressWarnings("rawtypes")
public boolean canConvert(Class type) {
return type.equals(WxPayOrderNotifyResult.class);
}
@Override
public void marshal(Object original, HierarchicalStreamWriter writer, MarshallingContext context) {
super.marshal(original, writer, context);
WxPayOrderNotifyResult obj = (WxPayOrderNotifyResult) original;
List<WxPayOrderNotifyCoupon> list = obj.getCouponList();
if (list == null || list.size() == 0) {
return;
}
for (int i = 0; i < list.size(); i++) {
WxPayOrderNotifyCoupon coupon = list.get(i);
writer.startNode("coupon_id_" + i);
writer.setValue(coupon.getCouponId());
writer.endNode();
writer.startNode("coupon_type_" + i);
writer.setValue(coupon.getCouponType());
writer.endNode();
writer.startNode("coupon_fee_" + i);
writer.setValue(coupon.getCouponFee() + "");
writer.endNode();
}
}
@Override
protected void marshallField(MarshallingContext context, Object newObj, Field field) {
if (field.getName().equals("couponList")) {
return;
} else {
super.marshallField(context, newObj, field);
}
}
@Override
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
WxPayOrderNotifyResult obj = new WxPayOrderNotifyResult();
List<Field> fields = new ArrayList<>(Arrays.asList(obj.getClass().getDeclaredFields()));
fields.addAll(Arrays.asList(obj.getClass().getSuperclass().getDeclaredFields()));
Map<String, Field> fieldMap = getFieldMap(fields);
List<WxPayOrderNotifyCoupon> coupons = new ArrayList<>(10);
while (reader.hasMoreChildren()) {
reader.moveDown();
if (fieldMap.containsKey(reader.getNodeName())) {
Field field = fieldMap.get(reader.getNodeName());
setFieldValue(context, obj, field);
} else if (StringUtils.startsWith(reader.getNodeName(), "coupon_id_")) {
String id = (String) context.convertAnother(obj, String.class);
getIndex(coupons, reader.getNodeName()).setCouponId(id);
} else if (StringUtils.startsWith(reader.getNodeName(), "coupon_type_")) {
String type = (String) context.convertAnother(obj, String.class);
getIndex(coupons, reader.getNodeName()).setCouponType(type);
} else if (StringUtils.startsWith(reader.getNodeName(), "coupon_fee_")) {
Integer fee = (Integer) context.convertAnother(obj, Integer.class);
getIndex(coupons, reader.getNodeName()).setCouponFee(fee);
}
reader.moveUp();
}
obj.setCouponList(coupons);
return obj;
}
private void setFieldValue(UnmarshallingContext context, WxPayOrderNotifyResult obj, Field field) {
Object val = context.convertAnother(obj, field.getType());
try {
if (val != null) {
PropertyDescriptor pd = new PropertyDescriptor(field.getName(), obj.getClass());
pd.getWriteMethod().invoke(obj, val);
}
} catch (Exception e) {
}
}
private Map<String, Field> getFieldMap(List<Field> fields) {
Map<String, Field> fieldMap = Maps.uniqueIndex(fields, new Function<Field, String>() {
@Override
public String apply(Field field) {
if (field.isAnnotationPresent(XStreamAlias.class)) {
return field.getAnnotation(XStreamAlias.class).value();
}
return field.getName();
}
});
return fieldMap;
}
private WxPayOrderNotifyCoupon getIndex(List<WxPayOrderNotifyCoupon> coupons, String nodeName) {
Integer index = Integer.valueOf(StringUtils.substring(nodeName, nodeName.lastIndexOf("_") + 1));
if (index >= coupons.size() || coupons.get(index) == null) {
coupons.add(index, new WxPayOrderNotifyCoupon());
}
return coupons.get(index);
}
}

View File

@@ -0,0 +1,314 @@
package com.github.binarywang.wxpay.service;
import com.github.binarywang.wxpay.bean.request.*;
import com.github.binarywang.wxpay.bean.result.*;
import com.github.binarywang.wxpay.config.WxPayConfig;
import me.chanjar.weixin.common.exception.WxErrorException;
import java.io.File;
import java.util.Map;
/**
* <pre>
* 微信支付相关接口
* Created by Binary Wang on 2016/7/28.
* </pre>
*
* @author binarywang (https://github.com/binarywang)
*/
public interface WxPayService {
/**
* <pre>
* 查询订单(详见https://com.github.binarywang.wechat.pay.bean.pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2)
* 该接口提供所有微信支付订单的查询,商户可以通过查询订单接口主动查询订单状态,完成下一步的业务逻辑。
* 需要调用查询接口的情况:
* ◆ 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知;
* ◆ 调用支付接口后,返回系统错误或未知交易状态情况;
* ◆ 调用被扫支付API返回USERPAYING的状态
* ◆ 调用关单或撤销接口API之前需确认支付状态
* 接口地址https://api.mch.weixin.qq.com/pay/orderquery
* </pre>
*
* @param transactionId 微信订单号
* @param outTradeNo 商户系统内部的订单号当没提供transactionId时需要传这个。
*/
WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxErrorException;
/**
* <pre>
* 关闭订单
* 应用场景
* 以下情况需要调用关单接口:
* 1. 商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;
* 2. 系统下单后,用户支付超时,系统退出不再受理,避免用户继续,请调用关单接口。
* 注意订单生成后不能马上调用关单接口最短调用时间间隔为5分钟。
* 接口地址https://api.mch.weixin.qq.com/pay/closeorder
* 是否需要证书: 不需要。
* </pre>
*
* @param outTradeNo 商户系统内部的订单号
*/
WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxErrorException;
/**
* 统一下单(详见http://com.github.binarywang.wechat.pay.bean.pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
* 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识"
* 接口地址https://api.mch.weixin.qq.com/pay/unifiedorder
*
* @param request 请求对象注意一些参数如appid、mchid等不用设置方法内会自动从配置对象中获取到前提是对应配置中已经设置
*/
WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) throws WxErrorException;
/**
* 该接口调用“统一下单”接口,并拼装发起支付请求需要的参数
* 详见http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
*
* @param request 请求对象注意一些参数如appid、mchid等不用设置方法内会自动从配置对象中获取到前提是对应配置中已经设置
*/
Map<String, String> getPayInfo(WxPayUnifiedOrderRequest request) throws WxErrorException;
/**
* 获取配置
*/
WxPayConfig getConfig();
/**
* 设置配置对象
*/
void setConfig(WxPayConfig config);
/**
* <pre>
* 微信支付-申请退款
* 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
* 接口链接https://api.mch.weixin.qq.com/secapi/pay/refund
* </pre>
*
* @param request 请求对象
* @return 退款操作结果
*/
WxPayRefundResult refund(WxPayRefundRequest request) throws WxErrorException;
/**
* <pre>
* 微信支付-查询退款
* 应用场景:
* 提交退款申请后通过调用该接口查询退款状态。退款有一定延时用零钱支付的退款20分钟内到账
* 银行卡支付的退款3个工作日后重新查询退款状态。
* 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5
* 接口链接https://api.mch.weixin.qq.com/pay/refundquery
* </pre>
* 以下四个参数四选一
*
* @param transactionId 微信订单号
* @param outTradeNo 商户订单号
* @param outRefundNo 商户退款单号
* @param refundId 微信退款单号
* @return 退款信息
*/
WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, String outRefundNo, String refundId)
throws WxErrorException;
/**
* 读取支付结果通知
* 详见http://com.github.binarywang.wechat.pay.bean.pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7
*/
WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxErrorException;
/**
* 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3)
*
* @param xmlbean Bean需要标记有XML注解默认使用配置中的PartnerKey进行签名
* @return 签名字符串
* @see #createSign(Map, String)
* @since 2.5.0
*/
String createSign(Object xmlbean);
/**
* 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3)
*
* @param xmlbean Bean需要标记有XML注解
* @param signKey 签名Key
* @return 签名字符串
* @see #createSign(Map, String)
*/
String createSign(Object xmlbean, String signKey);
/**
* 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3)
*
* @param prams 参数信息默认使用配置中的PartnerKey进行签名
* @return 签名字符串
* @see #createSign(Map, String)
*/
String createSign(Map<String, String> prams);
/**
* 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3)
*
* @param prams 参数信息
* @param signKey 签名Key
* @return 签名字符串
*/
String createSign(Map<String, String> prams, String signKey);
/**
* 校验签名是否正确默认使用配置中的PartnerKey进行签名
*
* @param xmlbean Bean需要标记有XML注解
* @return true - 签名校验成功false - 签名校验失败
* @see #checkSign(Map, String)
*/
boolean checkSign(Object xmlbean);
/**
* 校验签名是否正确
*
* @param xmlbean Bean需要标记有XML注解
* @param signKey 校验的签名Key
* @return true - 签名校验成功false - 签名校验失败
* @see #checkSign(Map, String)
*/
boolean checkSign(Object xmlbean, String signKey);
/**
* 校验签名是否正确默认使用配置中的PartnerKey进行签名
*
* @param prams 需要校验的参数Map
* @return true - 签名校验成功false - 签名校验失败
* @see #checkSign(Map, String)
*/
boolean checkSign(Map<String, String> prams);
/**
* 校验签名是否正确
*
* @param params 需要校验的参数Map
* @param signKey 校验的签名Key
* @return true - 签名校验成功false - 签名校验失败
* @see #checkSign(Map, String)
*/
boolean checkSign(Map<String, String> params, String signKey);
/**
* 发送微信红包给个人用户
* <pre>
* 文档详见:
* 发送普通红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
* 接口地址https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack
* 发送裂变红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5&index=4
* 接口地址https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack
* </pre>
*
* @param request 请求对象
*/
WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request) throws WxErrorException;
/**
* <pre>
* 查询红包记录
* 用于商户对已发放的红包进行查询红包的具体信息,可支持普通红包和裂变包。
* 请求Url https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo
* 是否需要证书 是(证书及使用说明详见商户证书)
* 请求方式 POST
* </pre>
*
* @param mchBillNo 商户发放红包的商户订单号比如10000098201411111234567890
*/
WxPayRedpackQueryResult queryRedpack(String mchBillNo) throws WxErrorException;
/**
* <pre>
* 企业付款业务是基于微信支付商户平台的资金管理能力为了协助商户方便地实现企业向个人付款针对部分有开发能力的商户提供通过API完成企业付款的功能。
* 比如目前的保险行业向客户退保、给付、理赔。
* 企业付款将使用商户的可用余额需确保可用余额充足。查看可用余额、充值、提现请登录商户平台“资金管理”https://pay.weixin.qq.com/进行操作。
* 注意:与商户微信支付收款资金并非同一账户,需要单独充值。
* 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
* 接口链接https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers
* </pre>
*
* @param request 请求对象
*/
WxEntPayResult entPay(WxEntPayRequest request) throws WxErrorException;
/**
* <pre>
* 查询企业付款API
* 用于商户的企业付款操作进行结果查询,返回付款操作详细结果。
* 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_3
* 接口链接https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo
* </pre>
*
* @param partnerTradeNo 商户订单号
*/
WxEntPayQueryResult queryEntPay(String partnerTradeNo) throws WxErrorException;
/**
* <pre>
* 扫码支付模式一生成二维码的方法
* 二维码中的内容为链接,形式为:
* weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX
* 其中XXXXX为商户需要填写的内容商户将该链接生成二维码如需要打印发布二维码需要采用此格式。商户可调用第三方库生成二维码图片。
* 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4
* </pre>
*
* @param productId 产品Id
* @param sideLength 要生成的二维码的边长如果为空则取默认值400
* @param logoFile 商户logo图片的文件对象可以为空
* @return 生成的二维码的字节数组
*/
byte[] createScanPayQrcodeMode1(String productId, File logoFile, Integer sideLength);
/**
* <pre>
* 扫码支付模式二生成二维码的方法
* 对应链接格式weixin//wxpay/bizpayurl?sr=XXXXX。请商户调用第三方库将code_url生成二维码图片。
* 该模式链接较短,生成的二维码打印到结账小票上的识别率较高。
* 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5
* </pre>
*
* @param codeUrl 微信返回的交易会话的二维码链接
* @param logoFile 商户logo图片的文件对象可以为空
* @param sideLength 要生成的二维码的边长如果为空则取默认值400
* @return 生成的二维码的字节数组
*/
byte[] createScanPayQrcodeMode2(String codeUrl, File logoFile, Integer sideLength);
/**
* <pre>
* 交易保障
* 应用场景:
* 商户在调用微信支付提供的相关接口时,会得到微信支付返回的相关信息以及获得整个接口的响应时间。
* 为提高整体的服务水平,协助商户一起提高服务质量,微信支付提供了相关接口调用耗时和返回信息的主动上报接口,
* 微信支付可以根据商户侧上报的数据进一步优化网络部署,完善服务监控,和商户更好的协作为用户提供更好的业务体验。
* 接口地址: https://api.mch.weixin.qq.com/payitil/report
* 是否需要证书:不需要
* </pre>
*/
void report(WxPayReportRequest request) throws WxErrorException;
/**
* <pre>
* 下载对账单
* 商户可以通过该接口下载历史交易清单。比如掉单、系统错误等导致商户侧和微信侧数据不一致,通过对账单核对后可校正支付状态。
* 注意:
* 1、微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账单中跟原支付单订单号一致bill_type为REVOKED
* 2、微信在次日9点启动生成前一天的对账单建议商户10点后再获取
* 3、对账单中涉及金额的字段单位为“元”。
* 4、对账单接口只能下载三个月以内的账单。
* 接口链接https://api.mch.weixin.qq.com/pay/downloadbill
* 详情请见: <a href="https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6">下载对账单</a>
* </pre>
*
* @param billDate 对账单日期 bill_date 下载对账单的日期格式20140603
* @param billType 账单类型 bill_type ALL返回当日所有订单信息默认值SUCCESS返回当日成功支付的订单REFUND返回当日退款订单
* @param tarType 压缩账单 tar_type 非必传参数固定值GZIP返回格式为.gzip的压缩包账单。不传则默认为数据流形式。
* @param deviceInfo 设备号 device_info 非必传参数,终端设备号
* @return 保存到本地的临时文件
*/
File downloadBill(String billDate, String billType, String tarType, String deviceInfo) throws WxErrorException;
}

View File

@@ -0,0 +1,560 @@
package com.github.binarywang.wxpay.service.impl;
import com.github.binarywang.utils.qrcode.QrcodeUtils;
import com.github.binarywang.wxpay.bean.request.*;
import com.github.binarywang.wxpay.bean.result.*;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.google.common.collect.Maps;
import jodd.http.HttpRequest;
import jodd.http.HttpResponse;
import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.BeanUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.CharEncoding;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.*;
/**
* Created by Binary Wang on 2016/7/28.
*
* @author binarywang (https://github.com/binarywang)
*/
public class WxPayServiceImpl implements WxPayService {
private static final String PAY_BASE_URL = "https://api.mch.weixin.qq.com";
private static final String[] TRADE_TYPES = new String[]{"JSAPI", "NATIVE", "APP"};
private static final String[] REFUND_ACCOUNT = new String[]{"REFUND_SOURCE_RECHARGE_FUNDS", "REFUND_SOURCE_UNSETTLED_FUNDS"};
private static final String[] BILL_TYPE = new String[]{"ALL", "REFUND", "SUCCESS"};
private final Logger log = LoggerFactory.getLogger(this.getClass());
private WxPayConfig config;
@Override
public WxPayConfig getConfig() {
return this.config;
}
@Override
public void setConfig(WxPayConfig config) {
this.config = config;
}
private String getPayBaseUrl() {
if (this.getConfig().useSandboxForWxPay()) {
return PAY_BASE_URL + "/sandboxnew";
}
return PAY_BASE_URL;
}
@Override
public WxPayRefundResult refund(WxPayRefundRequest request) throws WxErrorException {
this.initRequest(request);
if (StringUtils.isBlank(request.getOpUserId())) {
request.setOpUserId(this.getConfig().getMchId());
}
this.checkParameters(request);
request.setSign(this.createSign(request));
String url = this.getPayBaseUrl() + "/secapi/pay/refund";
String responseContent = this.postWithKey(url, request.toXML());
WxPayRefundResult result = WxPayRefundResult.fromXML(responseContent, WxPayRefundResult.class);
this.checkResult(result);
return result;
}
@Override
public WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo,
String outRefundNo, String refundId)
throws WxErrorException {
if ((StringUtils.isBlank(transactionId) && StringUtils.isBlank(outTradeNo)
&& StringUtils.isBlank(outRefundNo) && StringUtils.isBlank(refundId)) ||
(StringUtils.isNotBlank(transactionId) && StringUtils.isNotBlank(outTradeNo)
&& StringUtils.isNotBlank(outRefundNo) && StringUtils.isNotBlank(refundId))) {
throw new IllegalArgumentException("transaction_id out_trade_noout_refund_no refund_id 必须四选一");
}
WxPayRefundQueryRequest request = new WxPayRefundQueryRequest();
this.initRequest(request);
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
request.setTransactionId(StringUtils.trimToNull(transactionId));
request.setOutRefundNo(StringUtils.trimToNull(outRefundNo));
request.setRefundId(StringUtils.trimToNull(refundId));
request.setSign(this.createSign(request));
String url = this.getPayBaseUrl() + "/pay/refundquery";
String responseContent = this.post(url, request.toXML());
WxPayRefundQueryResult result = WxPayRefundQueryResult.fromXML(responseContent, WxPayRefundQueryResult.class);
result.composeRefundRecords();
this.checkResult(result);
return result;
}
private void checkResult(WxPayBaseResult result) throws WxErrorException {
//校验返回结果签名
Map<String, String> map = result.toMap();
if (result.getSign() != null && !this.checkSign(map)) {
log.debug("校验结果签名失败,参数:{}", map);
throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg("参数格式校验错误!").build());
}
//校验结果是否成功
if (!"SUCCESS".equalsIgnoreCase(result.getReturnCode())
|| !"SUCCESS".equalsIgnoreCase(result.getResultCode())) {
StringBuilder errorMsg = new StringBuilder();
if (result.getReturnCode() != null) {
errorMsg.append("返回代码:" + result.getReturnCode());
}
if (result.getReturnMsg() != null) {
errorMsg.append(",返回信息:" + result.getReturnMsg());
}
if (result.getResultCode() != null) {
errorMsg.append(",结果代码:" + result.getResultCode());
}
if (result.getErrCode() != null) {
errorMsg.append(",错误代码:" + result.getErrCode());
}
if (result.getErrCodeDes() != null) {
errorMsg.append(",错误详情:" + result.getErrCodeDes());
}
WxError error = WxError.newBuilder()
.setErrorCode(-1)
.setErrorMsg(errorMsg.toString())
.build();
log.error("\n结果业务代码异常返回結果{},\n{}", map, error);
throw new WxErrorException(error);
}
}
private void checkParameters(WxPayDownloadBillRequest request) throws WxErrorException {
BeanUtils.checkRequiredFields(request);
if (StringUtils.isNotBlank(request.getTarType()) && !"GZIP".equals(request.getTarType())) {
throw new IllegalArgumentException("tar_type值如果存在只能为GZIP");
}
if (!ArrayUtils.contains(BILL_TYPE, request.getBillType())) {
throw new IllegalArgumentException("bill_tpye目前必须为" + Arrays.toString(BILL_TYPE)
+ "其中之一,实际值:" + request.getBillType());
}
}
private void checkParameters(WxPayRefundRequest request) throws WxErrorException {
BeanUtils.checkRequiredFields(request);
if (StringUtils.isNotBlank(request.getRefundAccount())) {
if (!ArrayUtils.contains(REFUND_ACCOUNT, request.getRefundAccount())) {
throw new IllegalArgumentException("refund_account目前必须为" + Arrays.toString(REFUND_ACCOUNT)
+ "其中之一,实际值:" + request.getRefundAccount());
}
}
if (StringUtils.isBlank(request.getOutTradeNo()) && StringUtils.isBlank(request.getTransactionId())) {
throw new IllegalArgumentException("transaction_id 和 out_trade_no 不能同时为空,必须提供一个");
}
}
@Override
public WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxErrorException {
try {
log.debug("微信支付回调参数详细:{}", xmlData);
WxPayOrderNotifyResult result = WxPayOrderNotifyResult.fromXML(xmlData);
log.debug("微信支付回调结果对象:{}", result);
this.checkResult(result);
return result;
} catch (WxErrorException e) {
log.error(e.getMessage(), e);
throw e;
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new WxErrorException(WxError.newBuilder().setErrorMsg("发生异常" + e.getMessage()).build());
}
}
@Override
public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request)
throws WxErrorException {
this.initRequest(request);
request.setSign(this.createSign(request));
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/sendredpack";
if (request.getAmtType() != null) {
//裂变红包
url = this.getPayBaseUrl() + "/mmpaymkttransfers/sendgroupredpack";
}
String responseContent = this.postWithKey(url, request.toXML());
WxPaySendRedpackResult result = WxPaySendRedpackResult.fromXML(responseContent, WxPaySendRedpackResult.class);
//毋须校验,因为没有返回签名信息
// this.checkResult(result);
return result;
}
@Override
public WxPayRedpackQueryResult queryRedpack(String mchBillNo) throws WxErrorException {
WxPayRedpackQueryRequest request = new WxPayRedpackQueryRequest();
request.setMchBillNo(mchBillNo);
request.setBillType("MCHT");
initRequest(request);
request.setSign(this.createSign(request));
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gethbinfo";
String responseContent = this.postWithKey(url, request.toXML());
WxPayRedpackQueryResult result = WxPayRedpackQueryResult.fromXML(responseContent, WxPayRedpackQueryResult.class);
this.checkResult(result);
return result;
}
@Override
public WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxErrorException {
if ((StringUtils.isBlank(transactionId) && StringUtils.isBlank(outTradeNo)) ||
(StringUtils.isNotBlank(transactionId) && StringUtils.isNotBlank(outTradeNo))) {
throw new IllegalArgumentException("transaction_id 和 out_trade_no 不能同时存在或同时为空,必须二选一");
}
WxPayOrderQueryRequest request = new WxPayOrderQueryRequest();
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
request.setTransactionId(StringUtils.trimToNull(transactionId));
initRequest(request);
request.setSign(this.createSign(request));
String url = this.getPayBaseUrl() + "/pay/orderquery";
String responseContent = this.post(url, request.toXML());
if (StringUtils.isBlank(responseContent)) {
throw new WxErrorException(WxError.newBuilder().setErrorMsg("无响应结果").build());
}
WxPayOrderQueryResult result = WxPayOrderQueryResult.fromXML(responseContent, WxPayOrderQueryResult.class);
result.composeCoupons();
this.checkResult(result);
return result;
}
@Override
public WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxErrorException {
if (StringUtils.isBlank(outTradeNo)) {
throw new IllegalArgumentException("out_trade_no不能为空");
}
WxPayOrderCloseRequest request = new WxPayOrderCloseRequest();
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
this.initRequest(request);
request.setSign(this.createSign(request));
String url = this.getPayBaseUrl() + "/pay/closeorder";
String responseContent = this.post(url, request.toXML());
WxPayOrderCloseResult result = WxPayBaseResult.fromXML(responseContent, WxPayOrderCloseResult.class);
this.checkResult(result);
return result;
}
@Override
public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request)
throws WxErrorException {
this.initRequest(request);
if (StringUtils.isBlank(request.getNotifyURL())) {
request.setNotifyURL(getConfig().getNotifyUrl());
}
if (StringUtils.isBlank(request.getTradeType())) {
request.setTradeType(getConfig().getTradeType());
}
this.checkParameters(request);//校验参数
request.setSign(this.createSign(request));
String url = this.getPayBaseUrl() + "/pay/unifiedorder";
String responseContent = this.post(url, request.toXML());
WxPayUnifiedOrderResult result = WxPayUnifiedOrderResult.fromXML(responseContent, WxPayUnifiedOrderResult.class);
this.checkResult(result);
return result;
}
private void initRequest(WxPayBaseRequest request) {
if (StringUtils.isBlank(request.getAppid())) {
request.setAppid(this.getConfig().getAppId());
}
if (StringUtils.isBlank(request.getMchId())) {
request.setMchId(this.getConfig().getMchId());
}
if (StringUtils.isBlank(request.getSubAppId())) {
request.setSubAppId(this.getConfig().getSubAppId());
}
if (StringUtils.isBlank(request.getSubMchId())) {
request.setSubMchId(this.getConfig().getSubMchId());
}
if (StringUtils.isBlank(request.getNonceStr())) {
request.setNonceStr(String.valueOf(System.currentTimeMillis()));
}
}
private void checkParameters(WxPayUnifiedOrderRequest request) throws WxErrorException {
BeanUtils.checkRequiredFields(request);
if (!ArrayUtils.contains(TRADE_TYPES, request.getTradeType())) {
throw new IllegalArgumentException("trade_type目前必须为" + Arrays.toString(TRADE_TYPES) + "其中之一,实际值:" + request.getTradeType());
}
if ("JSAPI".equals(request.getTradeType()) && request.getOpenid() == null) {
throw new IllegalArgumentException("当 trade_type是'JSAPI'时未指定openid");
}
if ("NATIVE".equals(request.getTradeType()) && request.getProductId() == null) {
throw new IllegalArgumentException("当 trade_type是'NATIVE'时未指定product_id");
}
}
@Override
public Map<String, String> getPayInfo(WxPayUnifiedOrderRequest request) throws WxErrorException {
WxPayUnifiedOrderResult unifiedOrderResult = this.unifiedOrder(request);
String prepayId = unifiedOrderResult.getPrepayId();
if (StringUtils.isBlank(prepayId)) {
throw new RuntimeException(String.format("无法获取prepay id错误代码 '%s',信息:%s。",
unifiedOrderResult.getErrCode(), unifiedOrderResult.getErrCodeDes()));
}
Map<String, String> payInfo = new HashMap<>();
payInfo.put("appId", getConfig().getAppId());
// 支付签名时间戳注意微信jssdk中的所有使用timestamp字段均为小写。
// 但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
payInfo.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
payInfo.put("nonceStr", String.valueOf(System.currentTimeMillis()));
payInfo.put("package", "prepay_id=" + prepayId);
payInfo.put("signType", "MD5");
if ("NATIVE".equals(request.getTradeType())) {
payInfo.put("codeUrl", unifiedOrderResult.getCodeURL());
}
payInfo.put("paySign", this.createSign(payInfo));
return payInfo;
}
@Override
public WxEntPayResult entPay(WxEntPayRequest request) throws WxErrorException {
this.initRequest(request);
BeanUtils.checkRequiredFields(request);
request.setSign(this.createSign(request));
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/promotion/transfers";
String responseContent = this.postWithKey(url, request.toXML());
WxEntPayResult result = WxEntPayResult.fromXML(responseContent, WxEntPayResult.class);
this.checkResult(result);
return result;
}
@Override
public WxEntPayQueryResult queryEntPay(String partnerTradeNo) throws WxErrorException {
WxEntPayQueryRequest request = new WxEntPayQueryRequest();
this.initRequest(request);
request.setSign(this.createSign(request));
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gettransferinfo";
String responseContent = this.postWithKey(url, request.toXML());
WxEntPayQueryResult result = WxEntPayQueryResult.fromXML(responseContent, WxEntPayQueryResult.class);
this.checkResult(result);
return result;
}
@Override
public byte[] createScanPayQrcodeMode1(String productId, File logoFile, Integer sideLength) {
//weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX
StringBuilder codeUrl = new StringBuilder("weixin://wxpay/bizpayurl?");
Map<String, String> params = Maps.newHashMap();
params.put("appid", this.getConfig().getAppId());
params.put("mch_id", this.getConfig().getMchId());
params.put("product_id", productId);
params.put("time_stamp", String.valueOf(System.currentTimeMillis()));
params.put("nonce_str", String.valueOf(System.currentTimeMillis()));
String sign = this.createSign(params);
params.put("sign", sign);
for (String key : params.keySet()) {
codeUrl.append(key + "=" + params.get(key) + "&");
}
String content = codeUrl.toString().substring(0, codeUrl.length() - 1);
if (sideLength == null || sideLength < 1) {
return QrcodeUtils.createQrcode(content, logoFile);
}
return QrcodeUtils.createQrcode(content, sideLength, logoFile);
}
@Override
public byte[] createScanPayQrcodeMode2(String codeUrl, File logoFile, Integer sideLength) {
if (sideLength == null || sideLength < 1) {
return QrcodeUtils.createQrcode(codeUrl, logoFile);
}
return QrcodeUtils.createQrcode(codeUrl, sideLength, logoFile);
}
public void report(WxPayReportRequest request) throws WxErrorException {
BeanUtils.checkRequiredFields(request);
this.initRequest(request);
request.setSign(this.createSign(request));
String url = this.getPayBaseUrl() + "/payitil/report";
String responseContent = this.post(url, request.toXML());
WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class);
this.checkResult(result);
}
@Override
public File downloadBill(String billDate, String billType, String tarType, String deviceInfo) throws WxErrorException {
WxPayDownloadBillRequest request = new WxPayDownloadBillRequest();
this.initRequest(request);
request.setBillType(billType);
request.setBillDate(billDate);
request.setTarType(tarType);
request.setDeviceInfo(deviceInfo);
this.checkParameters(request);
request.setSign(this.createSign(request));
String url = this.getPayBaseUrl() + "/pay/downloadbill";
//TODO 返回的内容可能是文件流也有可能是xml需要区分对待
String responseContent = this.post(url, request.toXML());
WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class);
this.checkResult(result);
//TODO 待实现,暂时无测试帐号,无法调试
return null;
}
private String post(String url, String xmlParam) {
String requestString = null;
try {
requestString = new String(xmlParam.getBytes(CharEncoding.UTF_8), CharEncoding.ISO_8859_1);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
HttpRequest request = HttpRequest.post(url).body(requestString);
HttpResponse response = request.send();
String responseString = null;
try {
responseString = new String(response.bodyText().getBytes(CharEncoding.ISO_8859_1), CharEncoding.UTF_8);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", url, xmlParam, responseString);
return responseString;
}
/**
* 由于暂时未找到使用jodd-http实现证书配置的办法故而暂时使用httpclient
*/
private String postWithKey(String url, String requestStr) throws WxErrorException {
try {
SSLContext sslContext = this.getConfig().getSslContext();
if (null == sslContext) {
sslContext = this.getConfig().initSSLContext();
}
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,
new String[]{"TLSv1"}, null, new DefaultHostnameVerifier());
HttpPost httpPost = new HttpPost(url);
try (CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build()) {
httpPost.setEntity(new StringEntity(new String(requestStr.getBytes("UTF-8"), "ISO-8859-1")));
try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
String result = EntityUtils.toString(response.getEntity(), Consts.UTF_8);
this.log.debug("\n[URL]: {}\n[PARAMS]: {}\n[RESPONSE]: {}", url, requestStr, result);
return result;
}
} finally {
httpPost.releaseConnection();
}
} catch (Exception e) {
this.log.error("\n[URL]: {}\n[PARAMS]: {}\n[EXCEPTION]: {}", url, requestStr, e.getMessage());
throw new WxErrorException(WxError.newBuilder().setErrorCode(-1).setErrorMsg(e.getMessage()).build(), e);
}
}
@Override
public String createSign(Object xmlBean) {
return this.createSign(BeanUtils.xmlBean2Map(xmlBean), this.getConfig().getMchKey());
}
@Override
public String createSign(Object xmlBean, String signKey) {
return this.createSign(BeanUtils.xmlBean2Map(xmlBean), signKey);
}
@Override
public String createSign(Map<String, String> params) {
return this.createSign(params, this.getConfig().getMchKey());
}
@Override
public String createSign(Map<String, String> params, String signKey) {
if (this.getConfig().useSandboxForWxPay()) {
//使用仿真测试环境
//TODO 目前测试发现,以下两行代码都会出问题,所以暂不建议使用仿真测试环境
signKey = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456";
//return "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456";
}
SortedMap<String, String> sortedMap = new TreeMap<>(params);
StringBuilder toSign = new StringBuilder();
for (String key : sortedMap.keySet()) {
String value = params.get(key);
if (StringUtils.isNotEmpty(value) && !"sign".equals(key) && !"key".equals(key)) {
toSign.append(key + "=" + value + "&");
}
}
toSign.append("key=" + signKey);
return DigestUtils.md5Hex(toSign.toString()).toUpperCase();
}
@Override
public boolean checkSign(Object xmlBean) {
return this.checkSign(BeanUtils.xmlBean2Map(xmlBean), getConfig().getMchKey());
}
@Override
public boolean checkSign(Object xmlBean, String signKey) {
return this.checkSign(BeanUtils.xmlBean2Map(xmlBean), signKey);
}
@Override
public boolean checkSign(Map<String, String> params) {
return this.checkSign(params, getConfig().getMchKey());
}
@Override
public boolean checkSign(Map<String, String> params, String signKey) {
String sign = this.createSign(params, signKey);
return sign.equals(params.get("sign"));
}
}