@@ -1,5 +1,6 @@ | |||
package com.github.binarywang.wxpay.bean.request; | |||
import com.github.binarywang.wxpay.constant.WxPayConstants.BillType; | |||
import com.github.binarywang.wxpay.exception.WxPayException; | |||
import com.thoughtworks.xstream.annotations.XStreamAlias; | |||
import me.chanjar.weixin.common.annotation.Required; | |||
@@ -17,7 +18,8 @@ import java.util.Arrays; | |||
*/ | |||
@XStreamAlias("xml") | |||
public class WxPayDownloadBillRequest extends WxPayBaseRequest { | |||
private static final String[] BILL_TYPE = new String[]{"ALL", "REFUND", "SUCCESS"}; | |||
private static final String[] BILL_TYPES = new String[]{BillType.ALL, BillType.SUCCESS, BillType.REFUND, BillType.RECHARGE_REFUND}; | |||
private static final String TAR_TYPE_GZIP = "GZIP"; | |||
/** | |||
* <pre> | |||
@@ -130,13 +132,13 @@ public class WxPayDownloadBillRequest extends WxPayBaseRequest { | |||
@Override | |||
protected void checkConstraints() throws WxPayException { | |||
if (StringUtils.isNotBlank(this.getTarType()) && !"GZIP".equals(this.getTarType())) { | |||
if (StringUtils.isNotBlank(this.getTarType()) && !TAR_TYPE_GZIP.equals(this.getTarType())) { | |||
throw new WxPayException("tar_type值如果存在,只能为GZIP"); | |||
} | |||
if (!ArrayUtils.contains(BILL_TYPE, this.getBillType())) { | |||
throw new WxPayException(String.format("bill_tpye目前必须为%s其中之一,实际值:%s", | |||
Arrays.toString(BILL_TYPE), this.getBillType())); | |||
if (!ArrayUtils.contains(BILL_TYPES, this.getBillType())) { | |||
throw new WxPayException(String.format("bill_type目前必须为%s其中之一,实际值:%s", | |||
Arrays.toString(BILL_TYPES), this.getBillType())); | |||
} | |||
} | |||
} |
@@ -0,0 +1,87 @@ | |||
package com.github.binarywang.wxpay.constant; | |||
/** | |||
* <pre> | |||
* 微信支付常量类 | |||
* Created by Binary Wang on 2017-8-24. | |||
* </pre> | |||
* | |||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | |||
*/ | |||
public class WxPayConstants { | |||
/** | |||
* 校验用户姓名选项,企业付款时使用 | |||
*/ | |||
public static class CheckNameOption { | |||
/** | |||
* 不校验真实姓名 | |||
*/ | |||
public static final String NO_CHECK = "NO_CHECK"; | |||
/** | |||
* 强校验真实姓名 | |||
*/ | |||
public static final String FORCE_CHECK = "FORCE_CHECK"; | |||
} | |||
/** | |||
* 订单类型 | |||
*/ | |||
public static class BillType { | |||
/** | |||
* 查询红包时使用:通过商户订单号获取红包信息 | |||
*/ | |||
public static final String MCHT = "MCHT"; | |||
//以下为下载对账单时的账单类型 | |||
/** | |||
* 返回当日所有订单信息,默认值 | |||
*/ | |||
public static final String ALL = "ALL"; | |||
/** | |||
* 返回当日成功支付的订单 | |||
*/ | |||
public static final String SUCCESS = "SUCCESS"; | |||
/** | |||
* 返回当日退款订单 | |||
*/ | |||
public static final String REFUND = "REFUND"; | |||
/** | |||
* 返回当日充值退款订单(相比其他对账单多一栏“返还手续费”) | |||
*/ | |||
public static final String RECHARGE_REFUND = "RECHARGE_REFUND"; | |||
} | |||
/** | |||
* 交易类型 | |||
*/ | |||
public static class TradeType { | |||
/** | |||
* 原生扫码支付 | |||
*/ | |||
public static final String NATIVE = "NATIVE"; | |||
/** | |||
* App支付 | |||
*/ | |||
public static final String APP = "APP"; | |||
/** | |||
* 公众号支付 | |||
*/ | |||
public static final String JSAPI = "JSAPI"; | |||
/** | |||
* 刷卡支付,刷卡支付有单独的支付接口,不调用统一下单接口 | |||
*/ | |||
public static final String MICROPAY = "MICROPAY"; | |||
} | |||
/** | |||
* 签名类型 | |||
*/ | |||
public static class SignType { | |||
public static final String HMAC_SHA256 = "HMAC-SHA256"; | |||
public static final String MD5 = "MD5"; | |||
} | |||
} |
@@ -5,6 +5,9 @@ import com.github.binarywang.wxpay.bean.coupon.*; | |||
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.constant.WxPayConstants.BillType; | |||
import com.github.binarywang.wxpay.constant.WxPayConstants.SignType; | |||
import com.github.binarywang.wxpay.constant.WxPayConstants.TradeType; | |||
import com.github.binarywang.wxpay.exception.WxPayException; | |||
import com.github.binarywang.wxpay.service.WxPayService; | |||
import com.github.binarywang.wxpay.util.SignUtils; | |||
@@ -129,7 +132,7 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService { | |||
public WxPayRedpackQueryResult queryRedpack(String mchBillNo) throws WxPayException { | |||
WxPayRedpackQueryRequest request = new WxPayRedpackQueryRequest(); | |||
request.setMchBillNo(mchBillNo); | |||
request.setBillType("MCHT"); | |||
request.setBillType(BillType.MCHT); | |||
request.checkAndSign(this.getConfig()); | |||
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gethbinfo"; | |||
@@ -199,35 +202,36 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService { | |||
Map<String, String> payInfo = new HashMap<>(); | |||
String timestamp = String.valueOf(System.currentTimeMillis() / 1000); | |||
String nonceStr = String.valueOf(System.currentTimeMillis()); | |||
if ("NATIVE".equals(request.getTradeType())) { | |||
if (TradeType.NATIVE.equals(request.getTradeType())) { | |||
payInfo.put("codeUrl", unifiedOrderResult.getCodeURL()); | |||
} else if ("APP".equals(request.getTradeType())) { | |||
} else if (TradeType.APP.equals(request.getTradeType())) { | |||
// APP支付绑定的是微信开放平台上的账号,APPID为开放平台上绑定APP后发放的参数 | |||
String appId = getConfig().getAppId(); | |||
Map<String, String> configMap = new HashMap<>(); | |||
// 此map用于参与调起sdk支付的二次签名,格式全小写,timestamp只能是10位,格式固定,切勿修改 | |||
String partnerid = getConfig().getMchId(); | |||
String partnerId = getConfig().getMchId(); | |||
configMap.put("prepayid", prepayId); | |||
configMap.put("partnerid", partnerid); | |||
configMap.put("package", "Sign=WXPay"); | |||
configMap.put("partnerid", partnerId); | |||
String packageValue = "Sign=WXPay"; | |||
configMap.put("package", packageValue); | |||
configMap.put("timestamp", timestamp); | |||
configMap.put("noncestr", nonceStr); | |||
configMap.put("appid", appId); | |||
// 此map用于客户端与微信服务器交互 | |||
payInfo.put("sign", SignUtils.createSign(configMap, this.getConfig().getMchKey())); | |||
payInfo.put("prepayId", prepayId); | |||
payInfo.put("partnerId", partnerid); | |||
payInfo.put("partnerId", partnerId); | |||
payInfo.put("appId", appId); | |||
payInfo.put("packageValue", "Sign=WXPay"); | |||
payInfo.put("packageValue", packageValue); | |||
payInfo.put("timeStamp", timestamp); | |||
payInfo.put("nonceStr", nonceStr); | |||
} else if ("JSAPI".equals(request.getTradeType())) { | |||
} else if (TradeType.JSAPI.equals(request.getTradeType())) { | |||
payInfo.put("appId", unifiedOrderResult.getAppid()); | |||
// 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符 | |||
payInfo.put("timeStamp", timestamp); | |||
payInfo.put("nonceStr", nonceStr); | |||
payInfo.put("package", "prepay_id=" + prepayId); | |||
payInfo.put("signType", "MD5"); | |||
payInfo.put("signType", SignType.MD5); | |||
payInfo.put("paySign", SignUtils.createSign(payInfo, this.getConfig().getMchKey())); | |||
} | |||
@@ -278,7 +282,6 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService { | |||
String sign = SignUtils.createSign(params, this.getConfig().getMchKey()); | |||
params.put("sign", sign); | |||
for (String key : params.keySet()) { | |||
codeUrl.append(key + "=" + params.get(key) + "&"); | |||
} | |||
@@ -327,8 +330,7 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService { | |||
result.checkResult(this); | |||
return null; | |||
} else { | |||
WxPayBillResult wxPayBillResult = billInformationDeal(responseContent); | |||
return wxPayBillResult; | |||
return billInformationDeal(responseContent); | |||
} | |||
} | |||
@@ -346,10 +348,8 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService { | |||
* 交易时间:2017-04-06 01:00:02 公众账号ID: 商户号: 子商户号:0 设备号:WEB 微信订单号: 商户订单号:2017040519091071873216 用户标识: 交易类型:NATIVE | |||
* 交易状态:REFUND 付款银行:CFT 货币种类:CNY 总金额:0.00 企业红包金额:0.00 微信退款单号: 商户退款单号:20170406010000933 退款金额:0.01 企业红包退款金额:0.00 | |||
* 退款类型:ORIGINAL 退款状态:SUCCESS 商品名称: 商户数据包: 手续费:0.00000 费率 :0.60% | |||
* 参考以上格式进行取值 | |||
*/ | |||
// 参考以上格式进行取值 | |||
List<WxPayBillBaseResult> wxPayBillBaseResultLst = new LinkedList<>(); | |||
String newStr = listStr.replaceAll(",", " "); // 去空格 | |||
String[] tempStr = newStr.split("`"); // 数据分组 | |||
@@ -387,12 +387,11 @@ public abstract class WxPayServiceAbstractImpl implements WxPayService { | |||
k += t.length; | |||
} | |||
wxPayBillResult.setWxPayBillBaseResultLst(wxPayBillBaseResultLst); | |||
/* | |||
* 总交易单数,总交易额,总退款金额,总代金券或立减优惠退款金额,手续费总金额 `2,`0.02,`0.0,`0.0,`0 | |||
* 参考以上格式进行取值 | |||
*/ | |||
// 参考以上格式进行取值 | |||
String totalStr = objStr.replaceAll(",", " "); | |||
String[] totalTempStr = totalStr.split("`"); | |||
wxPayBillResult.setTotalRecord(totalTempStr[1]); | |||
@@ -4,6 +4,10 @@ import com.github.binarywang.utils.qrcode.QrcodeUtils; | |||
import com.github.binarywang.wxpay.bean.coupon.*; | |||
import com.github.binarywang.wxpay.bean.request.*; | |||
import com.github.binarywang.wxpay.bean.result.*; | |||
import com.github.binarywang.wxpay.constant.WxPayConstants; | |||
import com.github.binarywang.wxpay.constant.WxPayConstants.BillType; | |||
import com.github.binarywang.wxpay.constant.WxPayConstants.SignType; | |||
import com.github.binarywang.wxpay.constant.WxPayConstants.TradeType; | |||
import com.github.binarywang.wxpay.exception.WxPayException; | |||
import com.github.binarywang.wxpay.service.WxPayService; | |||
import com.github.binarywang.wxpay.testbase.ApiTestModule; | |||
@@ -33,23 +37,58 @@ public class WxPayServiceAbstractImplTest { | |||
@Inject | |||
private WxPayService payService; | |||
/** | |||
* Test method for {@link WxPayService#unifiedOrder(WxPayUnifiedOrderRequest)}. | |||
*/ | |||
@Test | |||
public void testUnifiedOrder() throws WxPayException { | |||
WxPayUnifiedOrderResult result = this.payService | |||
.unifiedOrder(WxPayUnifiedOrderRequest.newBuilder() | |||
.body("我去") | |||
.totalFee(1) | |||
.spbillCreateIp("11.1.11.1") | |||
.notifyURL("111111") | |||
.tradeType(TradeType.JSAPI) | |||
.openid(((XmlWxPayConfig) this.payService.getConfig()).getOpenid()) | |||
.outTradeNo("1111112") | |||
.build()); | |||
this.logger.info(result.toString()); | |||
} | |||
@Test | |||
public void testGetPayInfo() throws Exception { | |||
Map<String, String> payInfo = this.payService.getPayInfo(WxPayUnifiedOrderRequest.newBuilder() | |||
.body("我去") | |||
.totalFee(1) | |||
.spbillCreateIp("111111") | |||
.spbillCreateIp("1.11.1.11") | |||
.notifyURL("111111") | |||
.tradeType("JSAPI") | |||
.outTradeNo("111111") | |||
.tradeType(TradeType.JSAPI) | |||
.outTradeNo("1111113") | |||
.openid(((XmlWxPayConfig) this.payService.getConfig()).getOpenid()) | |||
.build()); | |||
this.logger.info(payInfo.toString()); | |||
} | |||
/** | |||
* Test method for {@link WxPayService#queryOrder(String, String)} . | |||
*/ | |||
@Test | |||
public void testQueryOrder() throws WxPayException { | |||
this.logger.info(this.payService.queryOrder("11212121", null).toString()); | |||
this.logger.info(this.payService.queryOrder(null, "11111").toString()); | |||
} | |||
/** | |||
* Test method for {@link WxPayService#closeOrder(String)} . | |||
*/ | |||
@Test | |||
public void testCloseOrder() throws WxPayException { | |||
this.logger.info(this.payService.closeOrder("11212121").toString()); | |||
} | |||
@Test | |||
public void testDownloadBill() throws Exception { | |||
WxPayBillResult wxPayBillResult = this.payService.downloadBill("20170101", "ALL", "GZIP", "1111111"); | |||
WxPayBillResult wxPayBillResult = this.payService.downloadBill("20170101", BillType.ALL, "GZIP", "1111111"); | |||
//前一天没有账单记录返回null | |||
assertNotNull(wxPayBillResult); | |||
//必填字段为空时,抛出异常 | |||
@@ -60,7 +99,7 @@ public class WxPayServiceAbstractImplTest { | |||
public void testReport() throws Exception { | |||
WxPayReportRequest request = new WxPayReportRequest(); | |||
request.setInterfaceUrl("hahahah"); | |||
request.setSignType("HMAC-SHA256");//貌似接口未校验此字段 | |||
request.setSignType(SignType.HMAC_SHA256);//貌似接口未校验此字段 | |||
request.setExecuteTime(1000); | |||
request.setReturnCode("aaa"); | |||
request.setResultCode("aaa"); | |||
@@ -130,41 +169,6 @@ public class WxPayServiceAbstractImplTest { | |||
this.logger.info(redpackResult.toString()); | |||
} | |||
/** | |||
* Test method for {@link WxPayService#unifiedOrder(WxPayUnifiedOrderRequest)}. | |||
*/ | |||
@Test | |||
public void testUnifiedOrder() throws WxPayException { | |||
WxPayUnifiedOrderResult result = this.payService | |||
.unifiedOrder(WxPayUnifiedOrderRequest.newBuilder() | |||
.body("我去") | |||
.totalFee(1) | |||
.spbillCreateIp("11.1.11.1") | |||
.notifyURL("111111") | |||
.tradeType("JSAPI") | |||
.openid(((XmlWxPayConfig) this.payService.getConfig()).getOpenid()) | |||
.outTradeNo("111111") | |||
.build()); | |||
this.logger.info(result.toString()); | |||
} | |||
/** | |||
* Test method for {@link WxPayService#queryOrder(String, String)} . | |||
*/ | |||
@Test | |||
public void testQueryOrder() throws WxPayException { | |||
this.logger.info(this.payService.queryOrder("11212121", null).toString()); | |||
this.logger.info(this.payService.queryOrder(null, "11111").toString()); | |||
} | |||
/** | |||
* Test method for {@link WxPayService#closeOrder(String)} . | |||
*/ | |||
@Test | |||
public void testCloseOrder() throws WxPayException { | |||
this.logger.info(this.payService.closeOrder("11212121").toString()); | |||
} | |||
/** | |||
* Test method for {@link WxPayService#entPay(WxEntPayRequest)}. | |||
*/ | |||
@@ -175,7 +179,7 @@ public class WxPayServiceAbstractImplTest { | |||
.openid("ojOQA0y9o-Eb6Aep7uVTdbkJqrP4") | |||
.amount(1) | |||
.spbillCreateIp("10.10.10.10") | |||
.checkName("NO_CHECK") | |||
.checkName(WxPayConstants.CheckNameOption.NO_CHECK) | |||
.description("描述信息") | |||
.build(); | |||