mirror of
https://gitee.com/binary/weixin-java-tools.git
synced 2025-08-24 16:18:51 +08:00
微信支付模块调整,跟其他模块保持统一,默认使用apache httpclient
This commit is contained in:
parent
1cd6618f82
commit
166e54c3f5
@ -23,10 +23,11 @@
|
|||||||
<groupId>com.github.binarywang</groupId>
|
<groupId>com.github.binarywang</groupId>
|
||||||
<artifactId>qrcode-utils</artifactId>
|
<artifactId>qrcode-utils</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jodd</groupId>
|
<groupId>org.jodd</groupId>
|
||||||
<artifactId>jodd-http</artifactId>
|
<artifactId>jodd-http</artifactId>
|
||||||
<scope>compile</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.github.binarywang.wxpay.bean.result;
|
package com.github.binarywang.wxpay.bean.result;
|
||||||
|
|
||||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||||
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
|
import com.github.binarywang.wxpay.service.impl.WxPayServiceAbstractImpl;
|
||||||
import com.github.binarywang.wxpay.util.SignUtils;
|
import com.github.binarywang.wxpay.util.SignUtils;
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
@ -307,7 +307,7 @@ public abstract class WxPayBaseResult {
|
|||||||
/**
|
/**
|
||||||
* 校验返回结果签名
|
* 校验返回结果签名
|
||||||
*/
|
*/
|
||||||
public void checkResult(WxPayServiceImpl wxPayService) throws WxPayException {
|
public void checkResult(WxPayServiceAbstractImpl wxPayService) throws WxPayException {
|
||||||
//校验返回结果签名
|
//校验返回结果签名
|
||||||
Map<String, String> map = toMap();
|
Map<String, String> map = toMap();
|
||||||
if (getSign() != null && !SignUtils.checkSign(map, wxPayService.getConfig().getMchKey())) {
|
if (getSign() != null && !SignUtils.checkSign(map, wxPayService.getConfig().getMchKey())) {
|
||||||
|
@ -0,0 +1,466 @@
|
|||||||
|
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.exception.WxPayException;
|
||||||
|
import com.github.binarywang.wxpay.service.WxPayService;
|
||||||
|
import com.github.binarywang.wxpay.util.SignUtils;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 微信支付接口请求抽象实现类
|
||||||
|
* Created by Binary Wang on 2017-7-8.
|
||||||
|
* </pre>
|
||||||
|
* @author <a href="https://github.com/binarywang">Binary Wang</a>
|
||||||
|
*/
|
||||||
|
public abstract class WxPayServiceAbstractImpl implements WxPayService {
|
||||||
|
private static final String PAY_BASE_URL = "https://api.mch.weixin.qq.com";
|
||||||
|
protected final Logger log = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|
||||||
|
protected WxPayConfig config;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxPayConfig getConfig() {
|
||||||
|
return this.config;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setConfig(WxPayConfig config) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getPayBaseUrl() {
|
||||||
|
if (this.getConfig().useSandbox()) {
|
||||||
|
return PAY_BASE_URL + "/sandboxnew";
|
||||||
|
}
|
||||||
|
|
||||||
|
return PAY_BASE_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送post请求
|
||||||
|
*
|
||||||
|
* @param url 请求地址
|
||||||
|
* @param requestStr 请求信息
|
||||||
|
* @param useKey 是否使用证书
|
||||||
|
* @return 返回请求结果字符串
|
||||||
|
*/
|
||||||
|
protected abstract String post(String url, String requestStr, boolean useKey) throws WxPayException;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxPayRefundResult refund(WxPayRefundRequest request) throws WxPayException {
|
||||||
|
request.checkAndSign(this.getConfig());
|
||||||
|
|
||||||
|
String url = this.getPayBaseUrl() + "/secapi/pay/refund";
|
||||||
|
String responseContent = this.post(url, request.toXML(), true);
|
||||||
|
WxPayRefundResult result = WxPayBaseResult.fromXML(responseContent, WxPayRefundResult.class);
|
||||||
|
result.checkResult(this);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, String outRefundNo, String refundId)
|
||||||
|
throws WxPayException {
|
||||||
|
WxPayRefundQueryRequest request = new WxPayRefundQueryRequest();
|
||||||
|
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
|
||||||
|
request.setTransactionId(StringUtils.trimToNull(transactionId));
|
||||||
|
request.setOutRefundNo(StringUtils.trimToNull(outRefundNo));
|
||||||
|
request.setRefundId(StringUtils.trimToNull(refundId));
|
||||||
|
|
||||||
|
request.checkAndSign(this.getConfig());
|
||||||
|
|
||||||
|
String url = this.getPayBaseUrl() + "/pay/refundquery";
|
||||||
|
String responseContent = this.post(url, request.toXML(), false);
|
||||||
|
WxPayRefundQueryResult result = WxPayBaseResult.fromXML(responseContent, WxPayRefundQueryResult.class);
|
||||||
|
result.composeRefundRecords();
|
||||||
|
result.checkResult(this);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxPayException {
|
||||||
|
try {
|
||||||
|
log.debug("微信支付回调参数详细:{}", xmlData);
|
||||||
|
WxPayOrderNotifyResult result = WxPayOrderNotifyResult.fromXML(xmlData);
|
||||||
|
log.debug("微信支付回调结果对象:{}", result);
|
||||||
|
result.checkResult(this);
|
||||||
|
return result;
|
||||||
|
} catch (WxPayException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
throw e;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
throw new WxPayException("发生异常," + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request) throws WxPayException {
|
||||||
|
request.checkAndSign(this.getConfig());
|
||||||
|
|
||||||
|
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/sendredpack";
|
||||||
|
if (request.getAmtType() != null) {
|
||||||
|
//裂变红包
|
||||||
|
url = this.getPayBaseUrl() + "/mmpaymkttransfers/sendgroupredpack";
|
||||||
|
}
|
||||||
|
|
||||||
|
String responseContent = this.post(url, request.toXML(), true);
|
||||||
|
WxPaySendRedpackResult result = WxPayBaseResult.fromXML(responseContent, WxPaySendRedpackResult.class);
|
||||||
|
//毋须校验,因为没有返回签名信息
|
||||||
|
// this.checkResult(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxPayRedpackQueryResult queryRedpack(String mchBillNo) throws WxPayException {
|
||||||
|
WxPayRedpackQueryRequest request = new WxPayRedpackQueryRequest();
|
||||||
|
request.setMchBillNo(mchBillNo);
|
||||||
|
request.setBillType("MCHT");
|
||||||
|
request.checkAndSign(this.getConfig());
|
||||||
|
|
||||||
|
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gethbinfo";
|
||||||
|
String responseContent = this.post(url, request.toXML(), true);
|
||||||
|
WxPayRedpackQueryResult result = WxPayBaseResult.fromXML(responseContent, WxPayRedpackQueryResult.class);
|
||||||
|
result.checkResult(this);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxPayException {
|
||||||
|
WxPayOrderQueryRequest request = new WxPayOrderQueryRequest();
|
||||||
|
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
|
||||||
|
request.setTransactionId(StringUtils.trimToNull(transactionId));
|
||||||
|
request.checkAndSign(this.getConfig());
|
||||||
|
|
||||||
|
String url = this.getPayBaseUrl() + "/pay/orderquery";
|
||||||
|
String responseContent = this.post(url, request.toXML(), false);
|
||||||
|
if (StringUtils.isBlank(responseContent)) {
|
||||||
|
throw new WxPayException("无响应结果");
|
||||||
|
}
|
||||||
|
|
||||||
|
WxPayOrderQueryResult result = WxPayBaseResult.fromXML(responseContent, WxPayOrderQueryResult.class);
|
||||||
|
result.composeCoupons();
|
||||||
|
result.checkResult(this);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxPayException {
|
||||||
|
if (StringUtils.isBlank(outTradeNo)) {
|
||||||
|
throw new IllegalArgumentException("out_trade_no不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
WxPayOrderCloseRequest request = new WxPayOrderCloseRequest();
|
||||||
|
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
|
||||||
|
request.checkAndSign(this.getConfig());
|
||||||
|
|
||||||
|
String url = this.getPayBaseUrl() + "/pay/closeorder";
|
||||||
|
String responseContent = this.post(url, request.toXML(), false);
|
||||||
|
WxPayOrderCloseResult result = WxPayBaseResult.fromXML(responseContent, WxPayOrderCloseResult.class);
|
||||||
|
result.checkResult(this);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) throws WxPayException {
|
||||||
|
request.checkAndSign(this.getConfig());
|
||||||
|
|
||||||
|
String url = this.getPayBaseUrl() + "/pay/unifiedorder";
|
||||||
|
String responseContent = this.post(url, request.toXML(), false);
|
||||||
|
WxPayUnifiedOrderResult result = WxPayBaseResult.fromXML(responseContent, WxPayUnifiedOrderResult.class);
|
||||||
|
result.checkResult(this);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getPayInfo(WxPayUnifiedOrderRequest request) throws WxPayException {
|
||||||
|
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<>();
|
||||||
|
if ("NATIVE".equals(request.getTradeType())) {
|
||||||
|
payInfo.put("codeUrl", unifiedOrderResult.getCodeURL());
|
||||||
|
} else if ("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();
|
||||||
|
configMap.put("prepayid", prepayId);
|
||||||
|
configMap.put("partnerid", partnerid);
|
||||||
|
configMap.put("package", "Sign=WXPay");
|
||||||
|
configMap.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
|
||||||
|
configMap.put("noncestr", String.valueOf(System.currentTimeMillis()));
|
||||||
|
configMap.put("appid", appId);
|
||||||
|
// 此map用于客户端与微信服务器交互
|
||||||
|
payInfo.put("sign", SignUtils.createSign(configMap, this.getConfig().getMchKey()));
|
||||||
|
payInfo.put("prepayId", prepayId);
|
||||||
|
payInfo.put("partnerId", partnerid);
|
||||||
|
payInfo.put("appId", appId);
|
||||||
|
payInfo.put("packageValue", "Sign=WXPay");
|
||||||
|
payInfo.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
|
||||||
|
payInfo.put("nonceStr", String.valueOf(System.currentTimeMillis()));
|
||||||
|
} else if ("JSAPI".equals(request.getTradeType())) {
|
||||||
|
payInfo.put("appId", unifiedOrderResult.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");
|
||||||
|
payInfo.put("paySign", SignUtils.createSign(payInfo, this.getConfig().getMchKey()));
|
||||||
|
}
|
||||||
|
return payInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxEntPayResult entPay(WxEntPayRequest request) throws WxPayException {
|
||||||
|
request.checkAndSign(this.getConfig());
|
||||||
|
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/promotion/transfers";
|
||||||
|
|
||||||
|
String responseContent = this.post(url, request.toXML(), true);
|
||||||
|
WxEntPayResult result = WxPayBaseResult.fromXML(responseContent, WxEntPayResult.class);
|
||||||
|
result.checkResult(this);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxEntPayQueryResult queryEntPay(String partnerTradeNo) throws WxPayException {
|
||||||
|
WxEntPayQueryRequest request = new WxEntPayQueryRequest();
|
||||||
|
request.setPartnerTradeNo(partnerTradeNo);
|
||||||
|
request.checkAndSign(this.getConfig());
|
||||||
|
|
||||||
|
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gettransferinfo";
|
||||||
|
String responseContent = this.post(url, request.toXML(), true);
|
||||||
|
WxEntPayQueryResult result = WxPayBaseResult.fromXML(responseContent, WxEntPayQueryResult.class);
|
||||||
|
result.checkResult(this);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] createScanPayQrcodeMode1(String productId, File logoFile, Integer sideLength) {
|
||||||
|
String content = this.createScanPayQrcodeMode1(productId);
|
||||||
|
return this.createQrcode(content, logoFile, sideLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String createScanPayQrcodeMode1(String productId) {
|
||||||
|
//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() / 1000));//这里需要秒,10位数字
|
||||||
|
params.put("nonce_str", String.valueOf(System.currentTimeMillis()));
|
||||||
|
|
||||||
|
String sign = SignUtils.createSign(params, this.getConfig().getMchKey());
|
||||||
|
params.put("sign", sign);
|
||||||
|
|
||||||
|
|
||||||
|
for (String key : params.keySet()) {
|
||||||
|
codeUrl.append(key + "=" + params.get(key) + "&");
|
||||||
|
}
|
||||||
|
|
||||||
|
String content = codeUrl.toString().substring(0, codeUrl.length() - 1);
|
||||||
|
log.debug("扫码支付模式一生成二维码的URL:{}", content);
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] createScanPayQrcodeMode2(String codeUrl, File logoFile, Integer sideLength) {
|
||||||
|
return this.createQrcode(codeUrl, logoFile, sideLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] createQrcode(String content, File logoFile, Integer sideLength) {
|
||||||
|
if (sideLength == null || sideLength < 1) {
|
||||||
|
return QrcodeUtils.createQrcode(content, logoFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return QrcodeUtils.createQrcode(content, sideLength, logoFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void report(WxPayReportRequest request) throws WxPayException {
|
||||||
|
request.checkAndSign(this.getConfig());
|
||||||
|
|
||||||
|
String url = this.getPayBaseUrl() + "/payitil/report";
|
||||||
|
String responseContent = this.post(url, request.toXML(), false);
|
||||||
|
WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class);
|
||||||
|
result.checkResult(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxPayBillResult downloadBill(String billDate, String billType, String tarType, String deviceInfo) throws WxPayException {
|
||||||
|
WxPayDownloadBillRequest request = new WxPayDownloadBillRequest();
|
||||||
|
request.setBillType(billType);
|
||||||
|
request.setBillDate(billDate);
|
||||||
|
request.setTarType(tarType);
|
||||||
|
request.setDeviceInfo(deviceInfo);
|
||||||
|
|
||||||
|
request.checkAndSign(this.getConfig());
|
||||||
|
|
||||||
|
String url = this.getPayBaseUrl() + "/pay/downloadbill";
|
||||||
|
String responseContent = this.post(url, request.toXML(), false);
|
||||||
|
if (responseContent.startsWith("<")) {
|
||||||
|
WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class);
|
||||||
|
result.checkResult(this);
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
WxPayBillResult wxPayBillResult = billInformationDeal(responseContent);
|
||||||
|
return wxPayBillResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private WxPayBillResult billInformationDeal(String responseContent) {
|
||||||
|
WxPayBillResult wxPayBillResult = new WxPayBillResult();
|
||||||
|
|
||||||
|
String listStr = "";
|
||||||
|
String objStr = "";
|
||||||
|
if (responseContent.contains("总交易单数")) {
|
||||||
|
listStr = responseContent.substring(0, responseContent.indexOf("总交易单数"));
|
||||||
|
objStr = responseContent.substring(responseContent.indexOf("总交易单数"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 交易时间: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("`"); // 数据分组
|
||||||
|
String[] t = tempStr[0].split(" ");// 分组标题
|
||||||
|
int j = tempStr.length / t.length; // 计算循环次数
|
||||||
|
int k = 1; // 纪录数组下标
|
||||||
|
for (int i = 0; i < j; i++) {
|
||||||
|
WxPayBillBaseResult wxPayBillBaseResult = new WxPayBillBaseResult();
|
||||||
|
|
||||||
|
wxPayBillBaseResult.setTradeTime(tempStr[k]);
|
||||||
|
wxPayBillBaseResult.setAppId(tempStr[k + 1]);
|
||||||
|
wxPayBillBaseResult.setMchId(tempStr[k + 2]);
|
||||||
|
wxPayBillBaseResult.setSubMchId(tempStr[k + 3]);
|
||||||
|
wxPayBillBaseResult.setDeviceInfo(tempStr[k + 4]);
|
||||||
|
wxPayBillBaseResult.setTransationId(tempStr[k + 5]);
|
||||||
|
wxPayBillBaseResult.setOutTradeNo(tempStr[k + 6]);
|
||||||
|
wxPayBillBaseResult.setOpenId(tempStr[k + 7]);
|
||||||
|
wxPayBillBaseResult.setTradeType(tempStr[k + 8]);
|
||||||
|
wxPayBillBaseResult.setTradeState(tempStr[k + 9]);
|
||||||
|
wxPayBillBaseResult.setBankType(tempStr[k + 10]);
|
||||||
|
wxPayBillBaseResult.setFeeType(tempStr[k + 11]);
|
||||||
|
wxPayBillBaseResult.setTotalFee(tempStr[k + 12]);
|
||||||
|
wxPayBillBaseResult.setCouponFee(tempStr[k + 13]);
|
||||||
|
wxPayBillBaseResult.setRefundId(tempStr[k + 14]);
|
||||||
|
wxPayBillBaseResult.setOutRefundNo(tempStr[k + 15]);
|
||||||
|
wxPayBillBaseResult.setSettlementRefundFee(tempStr[k + 16]);
|
||||||
|
wxPayBillBaseResult.setCouponRefundFee(tempStr[k + 17]);
|
||||||
|
wxPayBillBaseResult.setRefundChannel(tempStr[k + 18]);
|
||||||
|
wxPayBillBaseResult.setRefundState(tempStr[k + 19]);
|
||||||
|
wxPayBillBaseResult.setBody(tempStr[k + 20]);
|
||||||
|
wxPayBillBaseResult.setAttach(tempStr[k + 21]);
|
||||||
|
wxPayBillBaseResult.setPoundage(tempStr[k + 22]);
|
||||||
|
wxPayBillBaseResult.setPoundageRate(tempStr[k + 23]);
|
||||||
|
wxPayBillBaseResultLst.add(wxPayBillBaseResult);
|
||||||
|
k += t.length;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* 总交易单数,总交易额,总退款金额,总代金券或立减优惠退款金额,手续费总金额 `2,`0.02,`0.0,`0.0,`0
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 参考以上格式进行取值
|
||||||
|
|
||||||
|
String totalStr = objStr.replaceAll(",", " ");
|
||||||
|
String[] totalTempStr = totalStr.split("`");
|
||||||
|
wxPayBillResult.setTotalRecord(totalTempStr[1]);
|
||||||
|
wxPayBillResult.setTotalFee(totalTempStr[2]);
|
||||||
|
wxPayBillResult.setTotalRefundFee(totalTempStr[3]);
|
||||||
|
wxPayBillResult.setTotalCouponFee(totalTempStr[4]);
|
||||||
|
wxPayBillResult.setTotalPoundageFee(totalTempStr[5]);
|
||||||
|
|
||||||
|
return wxPayBillResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxPayMicropayResult micropay(WxPayMicropayRequest request) throws WxPayException {
|
||||||
|
request.checkAndSign(this.getConfig());
|
||||||
|
|
||||||
|
String url = this.getPayBaseUrl() + "/pay/micropay";
|
||||||
|
String responseContent = this.post(url, request.toXML(), false);
|
||||||
|
WxPayMicropayResult result = WxPayBaseResult.fromXML(responseContent, WxPayMicropayResult.class);
|
||||||
|
result.checkResult(this);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WxPayOrderReverseResult reverseOrder(WxPayOrderReverseRequest request) throws WxPayException {
|
||||||
|
request.checkAndSign(this.getConfig());
|
||||||
|
|
||||||
|
String url = this.getPayBaseUrl() + "/secapi/pay/reverse";
|
||||||
|
String responseContent = this.post(url, request.toXML(), true);
|
||||||
|
WxPayOrderReverseResult result = WxPayBaseResult.fromXML(responseContent, WxPayOrderReverseResult.class);
|
||||||
|
result.checkResult(this);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String shorturl(WxPayShorturlRequest request) throws WxPayException {
|
||||||
|
request.checkAndSign(this.getConfig());
|
||||||
|
|
||||||
|
String url = this.getPayBaseUrl() + "/tools/shorturl";
|
||||||
|
String responseContent = this.post(url, request.toXML(), false);
|
||||||
|
WxPayShorturlResult result = WxPayBaseResult.fromXML(responseContent, WxPayShorturlResult.class);
|
||||||
|
result.checkResult(this);
|
||||||
|
return result.getShortUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String shorturl(String longUrl) throws WxPayException {
|
||||||
|
return this.shorturl(new WxPayShorturlRequest(longUrl));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String authcode2Openid(WxPayAuthcode2OpenidRequest request) throws WxPayException {
|
||||||
|
request.checkAndSign(this.getConfig());
|
||||||
|
|
||||||
|
String url = this.getPayBaseUrl() + "/tools/authcodetoopenid";
|
||||||
|
String responseContent = this.post(url, request.toXML(), false);
|
||||||
|
WxPayAuthcode2OpenidResult result = WxPayBaseResult.fromXML(responseContent, WxPayAuthcode2OpenidResult.class);
|
||||||
|
result.checkResult(this);
|
||||||
|
return result.getOpenid();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String authcode2Openid(String authCode) throws WxPayException {
|
||||||
|
return this.authcode2Openid(new WxPayAuthcode2OpenidRequest(authCode));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getSandboxSignKey() throws WxPayException {
|
||||||
|
WxPayDefaultRequest request = new WxPayDefaultRequest();
|
||||||
|
request.checkAndSign(this.getConfig());
|
||||||
|
|
||||||
|
String url = "https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey";
|
||||||
|
String responseContent = this.post(url, request.toXML(), false);
|
||||||
|
WxPaySandboxSignKeyResult result = WxPayBaseResult.fromXML(responseContent, WxPaySandboxSignKeyResult.class);
|
||||||
|
result.checkResult(this);
|
||||||
|
return result.getSandboxSignKey();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
package com.github.binarywang.wxpay.service.impl;
|
||||||
|
|
||||||
|
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||||
|
import org.apache.http.client.config.RequestConfig;
|
||||||
|
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.HttpClientBuilder;
|
||||||
|
import org.apache.http.impl.client.HttpClients;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <pre>
|
||||||
|
* 微信支付请求实现类,apache httpclient实现
|
||||||
|
* Created by Binary Wang on 2016/7/28.
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author binarywang (https://github.com/binarywang)
|
||||||
|
*/
|
||||||
|
public class WxPayServiceApacheHttpImpl extends WxPayServiceAbstractImpl {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String post(String url, String requestStr, boolean useKey) throws WxPayException {
|
||||||
|
try {
|
||||||
|
HttpClientBuilder httpClientBuilder = HttpClients.custom();
|
||||||
|
if (useKey) {
|
||||||
|
SSLContext sslContext = this.getConfig().getSslContext();
|
||||||
|
if (null == sslContext) {
|
||||||
|
sslContext = this.getConfig().initSSLContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,
|
||||||
|
new String[]{"TLSv1"}, null, new DefaultHostnameVerifier());
|
||||||
|
httpClientBuilder.setSSLSocketFactory(sslsf);
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpPost httpPost = new HttpPost(url);
|
||||||
|
httpPost.setConfig(RequestConfig.custom()
|
||||||
|
.setConnectionRequestTimeout(this.getConfig().getHttpConnectionTimeout())
|
||||||
|
.setConnectTimeout(this.getConfig().getHttpConnectionTimeout())
|
||||||
|
.setSocketTimeout(this.getConfig().getHttpTimeout())
|
||||||
|
.build());
|
||||||
|
|
||||||
|
try (CloseableHttpClient httpclient = httpClientBuilder.build()) {
|
||||||
|
httpPost.setEntity(new StringEntity(new String(requestStr.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1)));
|
||||||
|
try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
|
||||||
|
String result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
|
||||||
|
this.log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, requestStr, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
httpPost.releaseConnection();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
this.log.error("\n【请求地址】:{}\n【请求数据】:{}\n【异常信息】:{}", url, requestStr, e.getMessage());
|
||||||
|
throw new WxPayException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,515 +1,12 @@
|
|||||||
package com.github.binarywang.wxpay.service.impl;
|
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.exception.WxPayException;
|
|
||||||
import com.github.binarywang.wxpay.service.WxPayService;
|
|
||||||
import com.github.binarywang.wxpay.util.SignUtils;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import jodd.http.HttpRequest;
|
|
||||||
import jodd.http.HttpResponse;
|
|
||||||
import jodd.http.net.SSLSocketHttpConnectionProvider;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import java.io.File;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Binary Wang on 2016/7/28.
|
* <pre>
|
||||||
|
* 微信支付接口请求实现类,默认使用Apache HttpClient实现
|
||||||
|
* Created by Binary Wang on 2017-7-8.
|
||||||
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author binarywang (https://github.com/binarywang)
|
* @author <a href="https://github.com/binarywang">Binary Wang</a>
|
||||||
*/
|
*/
|
||||||
public class WxPayServiceImpl implements WxPayService {
|
public class WxPayServiceImpl extends WxPayServiceApacheHttpImpl {
|
||||||
private static final String PAY_BASE_URL = "https://api.mch.weixin.qq.com";
|
|
||||||
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().useSandbox()) {
|
|
||||||
return PAY_BASE_URL + "/sandboxnew";
|
|
||||||
}
|
|
||||||
|
|
||||||
return PAY_BASE_URL;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WxPayRefundResult refund(WxPayRefundRequest request) throws WxPayException {
|
|
||||||
request.checkAndSign(this.getConfig());
|
|
||||||
|
|
||||||
String url = this.getPayBaseUrl() + "/secapi/pay/refund";
|
|
||||||
String responseContent = this.post(url, request.toXML(), true);
|
|
||||||
WxPayRefundResult result = WxPayBaseResult.fromXML(responseContent, WxPayRefundResult.class);
|
|
||||||
result.checkResult(this);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WxPayRefundQueryResult refundQuery(String transactionId, String outTradeNo, String outRefundNo, String refundId)
|
|
||||||
throws WxPayException {
|
|
||||||
WxPayRefundQueryRequest request = new WxPayRefundQueryRequest();
|
|
||||||
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
|
|
||||||
request.setTransactionId(StringUtils.trimToNull(transactionId));
|
|
||||||
request.setOutRefundNo(StringUtils.trimToNull(outRefundNo));
|
|
||||||
request.setRefundId(StringUtils.trimToNull(refundId));
|
|
||||||
|
|
||||||
request.checkAndSign(this.getConfig());
|
|
||||||
|
|
||||||
String url = this.getPayBaseUrl() + "/pay/refundquery";
|
|
||||||
String responseContent = this.post(url, request.toXML(), false);
|
|
||||||
WxPayRefundQueryResult result = WxPayBaseResult.fromXML(responseContent, WxPayRefundQueryResult.class);
|
|
||||||
result.composeRefundRecords();
|
|
||||||
result.checkResult(this);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WxPayOrderNotifyResult getOrderNotifyResult(String xmlData) throws WxPayException {
|
|
||||||
try {
|
|
||||||
log.debug("微信支付回调参数详细:{}", xmlData);
|
|
||||||
WxPayOrderNotifyResult result = WxPayOrderNotifyResult.fromXML(xmlData);
|
|
||||||
log.debug("微信支付回调结果对象:{}", result);
|
|
||||||
result.checkResult(this);
|
|
||||||
return result;
|
|
||||||
} catch (WxPayException e) {
|
|
||||||
log.error(e.getMessage(), e);
|
|
||||||
throw e;
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error(e.getMessage(), e);
|
|
||||||
throw new WxPayException("发生异常," + e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WxPaySendRedpackResult sendRedpack(WxPaySendRedpackRequest request) throws WxPayException {
|
|
||||||
request.checkAndSign(this.getConfig());
|
|
||||||
|
|
||||||
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/sendredpack";
|
|
||||||
if (request.getAmtType() != null) {
|
|
||||||
//裂变红包
|
|
||||||
url = this.getPayBaseUrl() + "/mmpaymkttransfers/sendgroupredpack";
|
|
||||||
}
|
|
||||||
|
|
||||||
String responseContent = this.post(url, request.toXML(), true);
|
|
||||||
WxPaySendRedpackResult result = WxPayBaseResult.fromXML(responseContent, WxPaySendRedpackResult.class);
|
|
||||||
//毋须校验,因为没有返回签名信息
|
|
||||||
// this.checkResult(result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WxPayRedpackQueryResult queryRedpack(String mchBillNo) throws WxPayException {
|
|
||||||
WxPayRedpackQueryRequest request = new WxPayRedpackQueryRequest();
|
|
||||||
request.setMchBillNo(mchBillNo);
|
|
||||||
request.setBillType("MCHT");
|
|
||||||
request.checkAndSign(this.getConfig());
|
|
||||||
|
|
||||||
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gethbinfo";
|
|
||||||
String responseContent = this.post(url, request.toXML(), true);
|
|
||||||
WxPayRedpackQueryResult result = WxPayBaseResult.fromXML(responseContent, WxPayRedpackQueryResult.class);
|
|
||||||
result.checkResult(this);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WxPayOrderQueryResult queryOrder(String transactionId, String outTradeNo) throws WxPayException {
|
|
||||||
WxPayOrderQueryRequest request = new WxPayOrderQueryRequest();
|
|
||||||
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
|
|
||||||
request.setTransactionId(StringUtils.trimToNull(transactionId));
|
|
||||||
request.checkAndSign(this.getConfig());
|
|
||||||
|
|
||||||
String url = this.getPayBaseUrl() + "/pay/orderquery";
|
|
||||||
String responseContent = this.post(url, request.toXML(), false);
|
|
||||||
if (StringUtils.isBlank(responseContent)) {
|
|
||||||
throw new WxPayException("无响应结果");
|
|
||||||
}
|
|
||||||
|
|
||||||
WxPayOrderQueryResult result = WxPayBaseResult.fromXML(responseContent, WxPayOrderQueryResult.class);
|
|
||||||
result.composeCoupons();
|
|
||||||
result.checkResult(this);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WxPayOrderCloseResult closeOrder(String outTradeNo) throws WxPayException {
|
|
||||||
if (StringUtils.isBlank(outTradeNo)) {
|
|
||||||
throw new IllegalArgumentException("out_trade_no不能为空");
|
|
||||||
}
|
|
||||||
|
|
||||||
WxPayOrderCloseRequest request = new WxPayOrderCloseRequest();
|
|
||||||
request.setOutTradeNo(StringUtils.trimToNull(outTradeNo));
|
|
||||||
request.checkAndSign(this.getConfig());
|
|
||||||
|
|
||||||
String url = this.getPayBaseUrl() + "/pay/closeorder";
|
|
||||||
String responseContent = this.post(url, request.toXML(), false);
|
|
||||||
WxPayOrderCloseResult result = WxPayBaseResult.fromXML(responseContent, WxPayOrderCloseResult.class);
|
|
||||||
result.checkResult(this);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WxPayUnifiedOrderResult unifiedOrder(WxPayUnifiedOrderRequest request) throws WxPayException {
|
|
||||||
request.checkAndSign(this.getConfig());
|
|
||||||
|
|
||||||
String url = this.getPayBaseUrl() + "/pay/unifiedorder";
|
|
||||||
String responseContent = this.post(url, request.toXML(), false);
|
|
||||||
WxPayUnifiedOrderResult result = WxPayBaseResult.fromXML(responseContent, WxPayUnifiedOrderResult.class);
|
|
||||||
result.checkResult(this);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, String> getPayInfo(WxPayUnifiedOrderRequest request) throws WxPayException {
|
|
||||||
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<>();
|
|
||||||
if ("NATIVE".equals(request.getTradeType())) {
|
|
||||||
payInfo.put("codeUrl", unifiedOrderResult.getCodeURL());
|
|
||||||
} else if ("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();
|
|
||||||
configMap.put("prepayid", prepayId);
|
|
||||||
configMap.put("partnerid", partnerid);
|
|
||||||
configMap.put("package", "Sign=WXPay");
|
|
||||||
configMap.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
|
|
||||||
configMap.put("noncestr", String.valueOf(System.currentTimeMillis()));
|
|
||||||
configMap.put("appid", appId);
|
|
||||||
// 此map用于客户端与微信服务器交互
|
|
||||||
payInfo.put("sign", SignUtils.createSign(configMap, this.getConfig().getMchKey()));
|
|
||||||
payInfo.put("prepayId", prepayId);
|
|
||||||
payInfo.put("partnerId", partnerid);
|
|
||||||
payInfo.put("appId", appId);
|
|
||||||
payInfo.put("packageValue", "Sign=WXPay");
|
|
||||||
payInfo.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000));
|
|
||||||
payInfo.put("nonceStr", String.valueOf(System.currentTimeMillis()));
|
|
||||||
} else if ("JSAPI".equals(request.getTradeType())) {
|
|
||||||
payInfo.put("appId", unifiedOrderResult.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");
|
|
||||||
payInfo.put("paySign", SignUtils.createSign(payInfo, this.getConfig().getMchKey()));
|
|
||||||
}
|
|
||||||
return payInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WxEntPayResult entPay(WxEntPayRequest request) throws WxPayException {
|
|
||||||
request.checkAndSign(this.getConfig());
|
|
||||||
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/promotion/transfers";
|
|
||||||
|
|
||||||
String responseContent = this.post(url, request.toXML(), true);
|
|
||||||
WxEntPayResult result = WxPayBaseResult.fromXML(responseContent, WxEntPayResult.class);
|
|
||||||
result.checkResult(this);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WxEntPayQueryResult queryEntPay(String partnerTradeNo) throws WxPayException {
|
|
||||||
WxEntPayQueryRequest request = new WxEntPayQueryRequest();
|
|
||||||
request.setPartnerTradeNo(partnerTradeNo);
|
|
||||||
request.checkAndSign(this.getConfig());
|
|
||||||
|
|
||||||
String url = this.getPayBaseUrl() + "/mmpaymkttransfers/gettransferinfo";
|
|
||||||
String responseContent = this.post(url, request.toXML(), true);
|
|
||||||
WxEntPayQueryResult result = WxPayBaseResult.fromXML(responseContent, WxEntPayQueryResult.class);
|
|
||||||
result.checkResult(this);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] createScanPayQrcodeMode1(String productId, File logoFile, Integer sideLength) {
|
|
||||||
String content = this.createScanPayQrcodeMode1(productId);
|
|
||||||
return this.createQrcode(content, logoFile, sideLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String createScanPayQrcodeMode1(String productId) {
|
|
||||||
//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() / 1000));//这里需要秒,10位数字
|
|
||||||
params.put("nonce_str", String.valueOf(System.currentTimeMillis()));
|
|
||||||
|
|
||||||
String sign = SignUtils.createSign(params, this.getConfig().getMchKey());
|
|
||||||
params.put("sign", sign);
|
|
||||||
|
|
||||||
|
|
||||||
for (String key : params.keySet()) {
|
|
||||||
codeUrl.append(key + "=" + params.get(key) + "&");
|
|
||||||
}
|
|
||||||
|
|
||||||
String content = codeUrl.toString().substring(0, codeUrl.length() - 1);
|
|
||||||
log.debug("扫码支付模式一生成二维码的URL:{}", content);
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] createScanPayQrcodeMode2(String codeUrl, File logoFile, Integer sideLength) {
|
|
||||||
return this.createQrcode(codeUrl, logoFile, sideLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] createQrcode(String content, File logoFile, Integer sideLength) {
|
|
||||||
if (sideLength == null || sideLength < 1) {
|
|
||||||
return QrcodeUtils.createQrcode(content, logoFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
return QrcodeUtils.createQrcode(content, sideLength, logoFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void report(WxPayReportRequest request) throws WxPayException {
|
|
||||||
request.checkAndSign(this.getConfig());
|
|
||||||
|
|
||||||
String url = this.getPayBaseUrl() + "/payitil/report";
|
|
||||||
String responseContent = this.post(url, request.toXML(), false);
|
|
||||||
WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class);
|
|
||||||
result.checkResult(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WxPayBillResult downloadBill(String billDate, String billType, String tarType, String deviceInfo) throws WxPayException {
|
|
||||||
WxPayDownloadBillRequest request = new WxPayDownloadBillRequest();
|
|
||||||
request.setBillType(billType);
|
|
||||||
request.setBillDate(billDate);
|
|
||||||
request.setTarType(tarType);
|
|
||||||
request.setDeviceInfo(deviceInfo);
|
|
||||||
|
|
||||||
request.checkAndSign(this.getConfig());
|
|
||||||
|
|
||||||
String url = this.getPayBaseUrl() + "/pay/downloadbill";
|
|
||||||
String responseContent = this.post(url, request.toXML(), false);
|
|
||||||
if (responseContent.startsWith("<")) {
|
|
||||||
WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class);
|
|
||||||
result.checkResult(this);
|
|
||||||
return null;
|
|
||||||
} else {
|
|
||||||
WxPayBillResult wxPayBillResult = billInformationDeal(responseContent);
|
|
||||||
return wxPayBillResult;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private WxPayBillResult billInformationDeal(String responseContent) {
|
|
||||||
WxPayBillResult wxPayBillResult = new WxPayBillResult();
|
|
||||||
|
|
||||||
String listStr = "";
|
|
||||||
String objStr = "";
|
|
||||||
if (responseContent.contains("总交易单数")) {
|
|
||||||
listStr = responseContent.substring(0, responseContent.indexOf("总交易单数"));
|
|
||||||
objStr = responseContent.substring(responseContent.indexOf("总交易单数"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 交易时间: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("`"); // 数据分组
|
|
||||||
String[] t = tempStr[0].split(" ");// 分组标题
|
|
||||||
int j = tempStr.length / t.length; // 计算循环次数
|
|
||||||
int k = 1; // 纪录数组下标
|
|
||||||
for (int i = 0; i < j; i++) {
|
|
||||||
WxPayBillBaseResult wxPayBillBaseResult = new WxPayBillBaseResult();
|
|
||||||
|
|
||||||
wxPayBillBaseResult.setTradeTime(tempStr[k]);
|
|
||||||
wxPayBillBaseResult.setAppId(tempStr[k + 1]);
|
|
||||||
wxPayBillBaseResult.setMchId(tempStr[k + 2]);
|
|
||||||
wxPayBillBaseResult.setSubMchId(tempStr[k + 3]);
|
|
||||||
wxPayBillBaseResult.setDeviceInfo(tempStr[k + 4]);
|
|
||||||
wxPayBillBaseResult.setTransationId(tempStr[k + 5]);
|
|
||||||
wxPayBillBaseResult.setOutTradeNo(tempStr[k + 6]);
|
|
||||||
wxPayBillBaseResult.setOpenId(tempStr[k + 7]);
|
|
||||||
wxPayBillBaseResult.setTradeType(tempStr[k + 8]);
|
|
||||||
wxPayBillBaseResult.setTradeState(tempStr[k + 9]);
|
|
||||||
wxPayBillBaseResult.setBankType(tempStr[k + 10]);
|
|
||||||
wxPayBillBaseResult.setFeeType(tempStr[k + 11]);
|
|
||||||
wxPayBillBaseResult.setTotalFee(tempStr[k + 12]);
|
|
||||||
wxPayBillBaseResult.setCouponFee(tempStr[k + 13]);
|
|
||||||
wxPayBillBaseResult.setRefundId(tempStr[k + 14]);
|
|
||||||
wxPayBillBaseResult.setOutRefundNo(tempStr[k + 15]);
|
|
||||||
wxPayBillBaseResult.setSettlementRefundFee(tempStr[k + 16]);
|
|
||||||
wxPayBillBaseResult.setCouponRefundFee(tempStr[k + 17]);
|
|
||||||
wxPayBillBaseResult.setRefundChannel(tempStr[k + 18]);
|
|
||||||
wxPayBillBaseResult.setRefundState(tempStr[k + 19]);
|
|
||||||
wxPayBillBaseResult.setBody(tempStr[k + 20]);
|
|
||||||
wxPayBillBaseResult.setAttach(tempStr[k + 21]);
|
|
||||||
wxPayBillBaseResult.setPoundage(tempStr[k + 22]);
|
|
||||||
wxPayBillBaseResult.setPoundageRate(tempStr[k + 23]);
|
|
||||||
wxPayBillBaseResultLst.add(wxPayBillBaseResult);
|
|
||||||
k += t.length;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* 总交易单数,总交易额,总退款金额,总代金券或立减优惠退款金额,手续费总金额 `2,`0.02,`0.0,`0.0,`0
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 参考以上格式进行取值
|
|
||||||
|
|
||||||
String totalStr = objStr.replaceAll(",", " ");
|
|
||||||
String[] totalTempStr = totalStr.split("`");
|
|
||||||
wxPayBillResult.setTotalRecord(totalTempStr[1]);
|
|
||||||
wxPayBillResult.setTotalFee(totalTempStr[2]);
|
|
||||||
wxPayBillResult.setTotalRefundFee(totalTempStr[3]);
|
|
||||||
wxPayBillResult.setTotalCouponFee(totalTempStr[4]);
|
|
||||||
wxPayBillResult.setTotalPoundageFee(totalTempStr[5]);
|
|
||||||
|
|
||||||
return wxPayBillResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WxPayMicropayResult micropay(WxPayMicropayRequest request) throws WxPayException {
|
|
||||||
request.checkAndSign(this.getConfig());
|
|
||||||
|
|
||||||
String url = this.getPayBaseUrl() + "/pay/micropay";
|
|
||||||
String responseContent = this.post(url, request.toXML(), false);
|
|
||||||
WxPayMicropayResult result = WxPayBaseResult.fromXML(responseContent, WxPayMicropayResult.class);
|
|
||||||
result.checkResult(this);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public WxPayOrderReverseResult reverseOrder(WxPayOrderReverseRequest request) throws WxPayException {
|
|
||||||
request.checkAndSign(this.getConfig());
|
|
||||||
|
|
||||||
String url = this.getPayBaseUrl() + "/secapi/pay/reverse";
|
|
||||||
String responseContent = this.post(url, request.toXML(), true);
|
|
||||||
WxPayOrderReverseResult result = WxPayBaseResult.fromXML(responseContent, WxPayOrderReverseResult.class);
|
|
||||||
result.checkResult(this);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String shorturl(WxPayShorturlRequest request) throws WxPayException {
|
|
||||||
request.checkAndSign(this.getConfig());
|
|
||||||
|
|
||||||
String url = this.getPayBaseUrl() + "/tools/shorturl";
|
|
||||||
String responseContent = this.post(url, request.toXML(), false);
|
|
||||||
WxPayShorturlResult result = WxPayBaseResult.fromXML(responseContent, WxPayShorturlResult.class);
|
|
||||||
result.checkResult(this);
|
|
||||||
return result.getShortUrl();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String shorturl(String longUrl) throws WxPayException {
|
|
||||||
return this.shorturl(new WxPayShorturlRequest(longUrl));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String authcode2Openid(WxPayAuthcode2OpenidRequest request) throws WxPayException {
|
|
||||||
request.checkAndSign(this.getConfig());
|
|
||||||
|
|
||||||
String url = this.getPayBaseUrl() + "/tools/authcodetoopenid";
|
|
||||||
String responseContent = this.post(url, request.toXML(), false);
|
|
||||||
WxPayAuthcode2OpenidResult result = WxPayBaseResult.fromXML(responseContent, WxPayAuthcode2OpenidResult.class);
|
|
||||||
result.checkResult(this);
|
|
||||||
return result.getOpenid();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String authcode2Openid(String authCode) throws WxPayException {
|
|
||||||
return this.authcode2Openid(new WxPayAuthcode2OpenidRequest(authCode));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getSandboxSignKey() throws WxPayException {
|
|
||||||
WxPayDefaultRequest request = new WxPayDefaultRequest();
|
|
||||||
request.checkAndSign(this.getConfig());
|
|
||||||
|
|
||||||
String url = "https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey";
|
|
||||||
String responseContent = this.post(url, request.toXML(), false);
|
|
||||||
WxPaySandboxSignKeyResult result = WxPayBaseResult.fromXML(responseContent, WxPaySandboxSignKeyResult.class);
|
|
||||||
result.checkResult(this);
|
|
||||||
return result.getSandboxSignKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发送post请求
|
|
||||||
*
|
|
||||||
* @param url 请求地址
|
|
||||||
* @param requestStr 请求信息
|
|
||||||
* @param useKey 是否使用证书
|
|
||||||
* @return 返回请求结果字符串
|
|
||||||
*/
|
|
||||||
private String post(String url, String requestStr, boolean useKey) throws WxPayException {
|
|
||||||
try {
|
|
||||||
HttpRequest request = HttpRequest
|
|
||||||
.post(url)
|
|
||||||
.timeout(this.config.getHttpTimeout())
|
|
||||||
.connectionTimeout(this.config.getHttpConnectionTimeout())
|
|
||||||
.bodyText(requestStr);
|
|
||||||
|
|
||||||
if (useKey) {
|
|
||||||
SSLContext sslContext = this.getConfig().getSslContext();
|
|
||||||
if (null == sslContext) {
|
|
||||||
sslContext = this.getConfig().initSSLContext();
|
|
||||||
}
|
|
||||||
request.withConnectionProvider(new SSLSocketHttpConnectionProvider(sslContext));
|
|
||||||
}
|
|
||||||
|
|
||||||
String responseString = this.getResponseString(request.send());
|
|
||||||
|
|
||||||
this.log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, requestStr, responseString);
|
|
||||||
return responseString;
|
|
||||||
} catch (Exception e) {
|
|
||||||
this.log.error("\n【请求地址】:{}\n【请求数据】:{}\n【异常信息】:{}", url, requestStr, e.getMessage());
|
|
||||||
throw new WxPayException(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getResponseString(HttpResponse response) throws WxPayException {
|
|
||||||
try {
|
|
||||||
this.log.debug("【微信服务器响应头信息】:\n{}", response.toString(false));
|
|
||||||
} catch (NullPointerException e) {
|
|
||||||
throw new WxPayException("response.toString() 居然抛出空指针异常了", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
String responseString = response.bodyText();
|
|
||||||
|
|
||||||
if (StringUtils.isBlank(responseString)) {
|
|
||||||
throw new WxPayException("响应信息为空");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringUtils.isBlank(response.charset())) {
|
|
||||||
responseString = new String(responseString.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
|
|
||||||
}
|
|
||||||
|
|
||||||
return responseString;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
package com.github.binarywang.wxpay.service.impl;
|
||||||
|
|
||||||
|
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||||
|
import jodd.http.HttpRequest;
|
||||||
|
import jodd.http.HttpResponse;
|
||||||
|
import jodd.http.net.SSLSocketHttpConnectionProvider;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信支付请求实现类,jodd-http实现
|
||||||
|
* Created by Binary Wang on 2016/7/28.
|
||||||
|
*
|
||||||
|
* @author binarywang (https://github.com/binarywang)
|
||||||
|
*/
|
||||||
|
public class WxPayServiceJoddHttpImpl extends WxPayServiceAbstractImpl {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String post(String url, String requestStr, boolean useKey) throws WxPayException {
|
||||||
|
try {
|
||||||
|
HttpRequest request = HttpRequest
|
||||||
|
.post(url)
|
||||||
|
.timeout(this.config.getHttpTimeout())
|
||||||
|
.connectionTimeout(this.config.getHttpConnectionTimeout())
|
||||||
|
.bodyText(requestStr);
|
||||||
|
|
||||||
|
if (useKey) {
|
||||||
|
SSLContext sslContext = this.getConfig().getSslContext();
|
||||||
|
if (null == sslContext) {
|
||||||
|
sslContext = this.getConfig().initSSLContext();
|
||||||
|
}
|
||||||
|
request.withConnectionProvider(new SSLSocketHttpConnectionProvider(sslContext));
|
||||||
|
}
|
||||||
|
|
||||||
|
String responseString = this.getResponseString(request.send());
|
||||||
|
|
||||||
|
this.log.info("\n【请求地址】:{}\n【请求数据】:{}\n【响应数据】:{}", url, requestStr, responseString);
|
||||||
|
return responseString;
|
||||||
|
} catch (Exception e) {
|
||||||
|
this.log.error("\n【请求地址】:{}\n【请求数据】:{}\n【异常信息】:{}", url, requestStr, e.getMessage());
|
||||||
|
throw new WxPayException(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getResponseString(HttpResponse response) throws WxPayException {
|
||||||
|
try {
|
||||||
|
this.log.debug("【微信服务器响应头信息】:\n{}", response.toString(false));
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
throw new WxPayException("response.toString() 居然抛出空指针异常了", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
String responseString = response.bodyText();
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(responseString)) {
|
||||||
|
throw new WxPayException("响应信息为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isBlank(response.charset())) {
|
||||||
|
responseString = new String(responseString.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
return responseString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user