mirror of
https://gitee.com/binary/weixin-java-tools.git
synced 2026-03-10 00:13:40 +08:00
Merge branch 'develop' into store
This commit is contained in:
@@ -1,10 +1,17 @@
|
||||
package me.chanjar.weixin.mp.api;
|
||||
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.mp.bean.result.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.mp.bean.pay.WxMpPayCallback;
|
||||
import me.chanjar.weixin.mp.bean.pay.WxMpPayRefundResult;
|
||||
import me.chanjar.weixin.mp.bean.pay.WxMpPayResult;
|
||||
import me.chanjar.weixin.mp.bean.pay.WxMpPrepayIdResult;
|
||||
import me.chanjar.weixin.mp.bean.pay.WxRedpackResult;
|
||||
import me.chanjar.weixin.mp.bean.pay.WxSendRedpackRequest;
|
||||
import me.chanjar.weixin.mp.bean.pay.WxUnifiedOrderRequest;
|
||||
import me.chanjar.weixin.mp.bean.pay.WxUnifiedOrderResult;
|
||||
|
||||
/**
|
||||
* 微信支付相关接口
|
||||
* Created by Binary Wang on 2016/7/28.
|
||||
@@ -12,7 +19,6 @@ import java.util.Map;
|
||||
*/
|
||||
public interface WxMpPayService {
|
||||
|
||||
|
||||
/**
|
||||
* 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
|
||||
* 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识"
|
||||
@@ -24,22 +30,39 @@ public interface WxMpPayService {
|
||||
* @param tradeType 交易类型 JSAPI,NATIVE,APP,WAP
|
||||
* @param ip 发起支付的客户端IP
|
||||
* @param notifyUrl 通知地址
|
||||
* @throws WxErrorException
|
||||
* @deprecated Use me.chanjar.weixin.mp.api.WxMpService.getPrepayId(Map<String, String>) instead
|
||||
*/
|
||||
@Deprecated
|
||||
WxMpPrepayIdResult getPrepayId(String openId, String outTradeNo, double amt, String body, String tradeType, String ip, String notifyUrl);
|
||||
WxMpPrepayIdResult getPrepayId(String openId, String outTradeNo, double amt,
|
||||
String body, String tradeType, String ip, String notifyUrl)
|
||||
throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
|
||||
* 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识"
|
||||
*
|
||||
* @param parameters All required/optional parameters for weixin payment
|
||||
* @throws WxErrorException
|
||||
* @deprecated use me.chanjar.weixin.mp.api.WxMpPayService.unifiedOrder(WxUnifiedOrderRequest) instead
|
||||
*/
|
||||
WxMpPrepayIdResult getPrepayId(Map<String, String> parameters);
|
||||
@Deprecated
|
||||
WxMpPrepayIdResult getPrepayId(Map<String, String> parameters)
|
||||
throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 统一下单(详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
|
||||
* 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识"
|
||||
* 接口地址:https://api.mch.weixin.qq.com/pay/unifiedorder
|
||||
* @throws WxErrorException
|
||||
*
|
||||
*/
|
||||
WxUnifiedOrderResult unifiedOrder(WxUnifiedOrderRequest request)
|
||||
throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 该接口调用“统一下单”接口,并拼装发起支付请求需要的参数
|
||||
* 详见http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E5.8F.91.E8.B5.B7.E4.B8.80.E4.B8.AA.E5.BE.AE.E4.BF.A1.E6.94.AF.E4.BB.98.E8.AF.B7.E6.B1.82
|
||||
* 详见http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
|
||||
*
|
||||
* @param parameters the required or optional parameters
|
||||
*/
|
||||
@@ -47,7 +70,7 @@ public interface WxMpPayService {
|
||||
|
||||
/**
|
||||
* 该接口调用“统一下单”接口,并拼装NATIVE发起支付请求需要的参数
|
||||
* 详见http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E5.8F.91.E8.B5.B7.E4.B8.80.E4.B8.AA.E5.BE.AE.E4.BF.A1.E6.94.AF.E4.BB.98.E8.AF.B7.E6.B1.82
|
||||
* 详见http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
|
||||
* tradeType 交易类型 NATIVE (其他交易类型JSAPI,APP,WAP)
|
||||
*
|
||||
* @param productId 商户商品ID
|
||||
@@ -56,14 +79,14 @@ public interface WxMpPayService {
|
||||
* @param body 商品描述
|
||||
* @param ip 发起支付的客户端IP
|
||||
* @param notifyUrl 通知地址
|
||||
* @deprecated Use me.chanjar.weixin.mp.api.WxMpService.getPayInfo(Map<String, String>) instead
|
||||
* @deprecated Use me.chanjar.weixin.mp.api.WxMpPayService.getPayInfo(Map<String, String>) instead
|
||||
*/
|
||||
@Deprecated
|
||||
Map<String, String> getNativePayInfo(String productId, String outTradeNo, double amt, String body, String ip, String notifyUrl) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 该接口调用“统一下单”接口,并拼装JSAPI发起支付请求需要的参数
|
||||
* 详见http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E5.8F.91.E8.B5.B7.E4.B8.80.E4.B8.AA.E5.BE.AE.E4.BF.A1.E6.94.AF.E4.BB.98.E8.AF.B7.E6.B1.82
|
||||
* 详见http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115&token=&lang=zh_CN
|
||||
* tradeType 交易类型 JSAPI(其他交易类型NATIVE,APP,WAP)
|
||||
*
|
||||
* @param openId 支付人openId
|
||||
@@ -72,7 +95,7 @@ public interface WxMpPayService {
|
||||
* @param body 商品描述
|
||||
* @param ip 发起支付的客户端IP
|
||||
* @param notifyUrl 通知地址
|
||||
* @deprecated Use me.chanjar.weixin.mp.api.WxMpService.getPayInfo(Map<String, String>) instead
|
||||
* @deprecated Use me.chanjar.weixin.mp.api.WxMpPayService.getPayInfo(Map<String, String>) instead
|
||||
*/
|
||||
@Deprecated
|
||||
Map<String, String> getJsapiPayInfo(String openId, String outTradeNo, double amt, String body, String ip, String notifyUrl) throws WxErrorException;
|
||||
@@ -80,9 +103,11 @@ public interface WxMpPayService {
|
||||
/**
|
||||
* 该接口提供所有微信支付订单的查询,当支付通知处理异常戒丢失的情冴,商户可以通过该接口查询订单支付状态。
|
||||
* 详见http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2
|
||||
* @throws WxErrorException
|
||||
*
|
||||
*/
|
||||
WxMpPayResult getJSSDKPayResult(String transactionId, String outTradeNo);
|
||||
WxMpPayResult getJSSDKPayResult(String transactionId, String outTradeNo)
|
||||
throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 读取支付结果通知
|
||||
@@ -115,8 +140,8 @@ public interface WxMpPayService {
|
||||
boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm, String signature);
|
||||
|
||||
/**
|
||||
* 发送微信红包给个人用户
|
||||
* <p>
|
||||
* 发送普通微信红包给个人用户
|
||||
* <pre>
|
||||
* 需要传入的必填参数如下:
|
||||
* mch_billno//商户订单号
|
||||
* send_name//商户名称
|
||||
@@ -127,12 +152,25 @@ public interface WxMpPayService {
|
||||
* client_ip//服务器Ip地址
|
||||
* act_name//活动名称
|
||||
* remark //备注
|
||||
* 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5
|
||||
* <p>
|
||||
* 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
|
||||
* 使用现金红包功能需要在xml配置文件中额外设置:
|
||||
* </pre>
|
||||
* <partnerId></partnerId>微信商户平台ID
|
||||
* <partnerKey></partnerKey>商户平台设置的API密钥
|
||||
* @deprecated use me.chanjar.weixin.mp.api.WxMpPayService.sendRedpack(WxSendRedpackRequest) instead
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
WxRedpackResult sendRedpack(Map<String, String> parameters) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 发送微信红包给个人用户
|
||||
* <pre>
|
||||
* 文档详见:
|
||||
* 发送普通红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
|
||||
* 发送裂变红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5&index=4
|
||||
* </pre>
|
||||
*/
|
||||
WxRedpackResult sendRedpack(WxSendRedpackRequest request) throws WxErrorException;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,29 +1,38 @@
|
||||
package me.chanjar.weixin.mp.api.impl;
|
||||
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import me.chanjar.weixin.common.bean.result.WxError;
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.util.crypto.WxCryptUtil;
|
||||
import me.chanjar.weixin.common.util.http.Utf8ResponseHandler;
|
||||
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
|
||||
import me.chanjar.weixin.mp.api.WxMpPayService;
|
||||
import me.chanjar.weixin.mp.bean.result.*;
|
||||
import org.apache.http.Consts;
|
||||
import org.apache.http.HttpHost;
|
||||
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.entity.StringEntity;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.helpers.MessageFormatter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.joor.Reflect;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
import me.chanjar.weixin.common.annotation.Required;
|
||||
import me.chanjar.weixin.common.bean.result.WxError;
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
|
||||
import me.chanjar.weixin.mp.api.WxMpPayService;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.pay.WxMpPayCallback;
|
||||
import me.chanjar.weixin.mp.bean.pay.WxMpPayRefundResult;
|
||||
import me.chanjar.weixin.mp.bean.pay.WxMpPayResult;
|
||||
import me.chanjar.weixin.mp.bean.pay.WxMpPrepayIdResult;
|
||||
import me.chanjar.weixin.mp.bean.pay.WxRedpackResult;
|
||||
import me.chanjar.weixin.mp.bean.pay.WxSendRedpackRequest;
|
||||
import me.chanjar.weixin.mp.bean.pay.WxUnifiedOrderRequest;
|
||||
import me.chanjar.weixin.mp.bean.pay.WxUnifiedOrderResult;
|
||||
|
||||
/**
|
||||
* Created by Binary Wang on 2016/7/28.
|
||||
*
|
||||
@@ -31,27 +40,28 @@ import java.util.TreeMap;
|
||||
*/
|
||||
public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
|
||||
private static final List<String> TRADE_TYPES = Lists.newArrayList("JSAPI",
|
||||
"NATIVE", "APP");
|
||||
private final Logger log = LoggerFactory.getLogger(WxMpPayServiceImpl.class);
|
||||
private final String[] REQUIRED_ORDER_PARAMETERS = new String[]{"appid",
|
||||
"mch_id", "body", "out_trade_no", "total_fee", "spbill_create_ip",
|
||||
"notify_url", "trade_type"};
|
||||
private HttpHost httpProxy;
|
||||
private WxMpServiceImpl wxMpService;
|
||||
private final String[] REQUIRED_ORDER_PARAMETERS = new String[] { "appid",
|
||||
"mch_id", "body", "out_trade_no", "total_fee", "spbill_create_ip",
|
||||
"notify_url", "trade_type" };
|
||||
private WxMpService wxMpService;
|
||||
|
||||
public WxMpPayServiceImpl(WxMpServiceImpl wxMpService) {
|
||||
public WxMpPayServiceImpl(WxMpService wxMpService) {
|
||||
this.wxMpService = wxMpService;
|
||||
this.httpProxy = wxMpService.getHttpProxy();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public WxMpPrepayIdResult getPrepayId(String openId, String outTradeNo,
|
||||
double amt, String body, String tradeType, String ip,
|
||||
String callbackUrl) {
|
||||
double amt, String body, String tradeType, String ip,
|
||||
String callbackUrl) throws WxErrorException {
|
||||
Map<String, String> packageParams = new HashMap<>();
|
||||
packageParams.put("appid",
|
||||
this.wxMpService.getWxMpConfigStorage().getAppId());
|
||||
this.wxMpService.getWxMpConfigStorage().getAppId());
|
||||
packageParams.put("mch_id",
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerId());
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerId());
|
||||
packageParams.put("body", body);
|
||||
packageParams.put("out_trade_no", outTradeNo);
|
||||
packageParams.put("total_fee", (int) (amt * 100) + "");
|
||||
@@ -64,82 +74,67 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxMpPrepayIdResult getPrepayId(final Map<String, String> parameters) {
|
||||
@Deprecated
|
||||
public WxMpPrepayIdResult getPrepayId(final Map<String, String> parameters)
|
||||
throws WxErrorException {
|
||||
final SortedMap<String, String> packageParams = new TreeMap<>(parameters);
|
||||
packageParams.put("appid",
|
||||
this.wxMpService.getWxMpConfigStorage().getAppId());
|
||||
this.wxMpService.getWxMpConfigStorage().getAppId());
|
||||
packageParams.put("mch_id",
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerId());
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerId());
|
||||
packageParams.put("nonce_str", System.currentTimeMillis() + "");
|
||||
checkParameters(packageParams);
|
||||
|
||||
String sign = WxCryptUtil.createSign(packageParams,
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerKey());
|
||||
String sign = this.createSign(packageParams,
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerKey());
|
||||
packageParams.put("sign", sign);
|
||||
|
||||
StringBuilder request = new StringBuilder("<xml>");
|
||||
for (Map.Entry<String, String> para : packageParams.entrySet()) {
|
||||
request.append(String.format("<%s>%s</%s>", para.getKey(),
|
||||
para.getValue(), para.getKey()));
|
||||
para.getValue(), para.getKey()));
|
||||
}
|
||||
|
||||
request.append("</xml>");
|
||||
|
||||
HttpPost httpPost = new HttpPost(
|
||||
"https://api.mch.weixin.qq.com/pay/unifiedorder");
|
||||
if (this.httpProxy != null) {
|
||||
RequestConfig config = RequestConfig.custom().setProxy(this.httpProxy)
|
||||
.build();
|
||||
httpPost.setConfig(config);
|
||||
}
|
||||
|
||||
StringEntity entity = new StringEntity(request.toString(), Consts.UTF_8);
|
||||
httpPost.setEntity(entity);
|
||||
try (CloseableHttpResponse response = this.wxMpService.getHttpclient()
|
||||
.execute(httpPost)) {
|
||||
String responseContent = Utf8ResponseHandler.INSTANCE
|
||||
.handleResponse(response);
|
||||
XStream xstream = XStreamInitializer.getInstance();
|
||||
xstream.alias("xml", WxMpPrepayIdResult.class);
|
||||
return (WxMpPrepayIdResult) xstream.fromXML(responseContent);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to get prepay id due to IO exception.",
|
||||
e);
|
||||
} finally {
|
||||
httpPost.releaseConnection();
|
||||
}
|
||||
String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
|
||||
String responseContent = this.wxMpService.post(url, request.toString());
|
||||
XStream xstream = XStreamInitializer.getInstance();
|
||||
xstream.alias("xml", WxMpPrepayIdResult.class);
|
||||
return (WxMpPrepayIdResult) xstream.fromXML(responseContent);
|
||||
}
|
||||
|
||||
private void checkParameters(Map<String, String> parameters) {
|
||||
for (String para : this.REQUIRED_ORDER_PARAMETERS) {
|
||||
if (!parameters.containsKey(para)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Reqiured argument '" + para + "' is missing.");
|
||||
"Reqiured argument '" + para + "' is missing.");
|
||||
}
|
||||
}
|
||||
|
||||
if ("JSAPI".equals(parameters.get("trade_type"))
|
||||
&& !parameters.containsKey("openid")) {
|
||||
&& !parameters.containsKey("openid")) {
|
||||
throw new IllegalArgumentException(
|
||||
"Reqiured argument 'openid' is missing when trade_type is 'JSAPI'.");
|
||||
"Reqiured argument 'openid' is missing when trade_type is 'JSAPI'.");
|
||||
}
|
||||
|
||||
if ("NATIVE".equals(parameters.get("trade_type"))
|
||||
&& !parameters.containsKey("product_id")) {
|
||||
&& !parameters.containsKey("product_id")) {
|
||||
throw new IllegalArgumentException(
|
||||
"Reqiured argument 'product_id' is missing when trade_type is 'NATIVE'.");
|
||||
"Reqiured argument 'product_id' is missing when trade_type is 'NATIVE'.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public Map<String, String> getJsapiPayInfo(String openId, String outTradeNo,
|
||||
double amt, String body, String ip, String callbackUrl)
|
||||
throws WxErrorException {
|
||||
double amt, String body, String ip, String callbackUrl)
|
||||
throws WxErrorException {
|
||||
Map<String, String> packageParams = new HashMap<>();
|
||||
packageParams.put("appid",
|
||||
this.wxMpService.getWxMpConfigStorage().getAppId());
|
||||
this.wxMpService.getWxMpConfigStorage().getAppId());
|
||||
packageParams.put("mch_id",
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerId());
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerId());
|
||||
packageParams.put("body", body);
|
||||
packageParams.put("out_trade_no", outTradeNo);
|
||||
packageParams.put("total_fee", (int) (amt * 100) + "");
|
||||
@@ -152,14 +147,15 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public Map<String, String> getNativePayInfo(String productId,
|
||||
String outTradeNo, double amt, String body, String ip, String callbackUrl)
|
||||
throws WxErrorException {
|
||||
String outTradeNo, double amt, String body, String ip, String callbackUrl)
|
||||
throws WxErrorException {
|
||||
Map<String, String> packageParams = new HashMap<>();
|
||||
packageParams.put("appid",
|
||||
this.wxMpService.getWxMpConfigStorage().getAppId());
|
||||
this.wxMpService.getWxMpConfigStorage().getAppId());
|
||||
packageParams.put("mch_id",
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerId());
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerId());
|
||||
packageParams.put("body", body);
|
||||
packageParams.put("out_trade_no", outTradeNo);
|
||||
packageParams.put("total_fee", (int) (amt * 100) + "");
|
||||
@@ -173,27 +169,27 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
|
||||
@Override
|
||||
public Map<String, String> getPayInfo(Map<String, String> parameters)
|
||||
throws WxErrorException {
|
||||
throws WxErrorException {
|
||||
WxMpPrepayIdResult wxMpPrepayIdResult = getPrepayId(parameters);
|
||||
|
||||
if (!"SUCCESS".equalsIgnoreCase(wxMpPrepayIdResult.getReturn_code())
|
||||
|| !"SUCCESS".equalsIgnoreCase(wxMpPrepayIdResult.getResult_code())) {
|
||||
|| !"SUCCESS".equalsIgnoreCase(wxMpPrepayIdResult.getResult_code())) {
|
||||
WxError error = new WxError();
|
||||
error.setErrorCode(-1);
|
||||
error.setErrorMsg("return_code:" + wxMpPrepayIdResult.getReturn_code()
|
||||
+ ";return_msg:" + wxMpPrepayIdResult.getReturn_msg()
|
||||
+ ";result_code:" + wxMpPrepayIdResult.getResult_code() + ";err_code"
|
||||
+ wxMpPrepayIdResult.getErr_code() + ";err_code_des"
|
||||
+ wxMpPrepayIdResult.getErr_code_des());
|
||||
+ ";return_msg:" + wxMpPrepayIdResult.getReturn_msg()
|
||||
+ ";result_code:" + wxMpPrepayIdResult.getResult_code() + ";err_code"
|
||||
+ wxMpPrepayIdResult.getErr_code() + ";err_code_des"
|
||||
+ wxMpPrepayIdResult.getErr_code_des());
|
||||
throw new WxErrorException(error);
|
||||
}
|
||||
|
||||
String prepayId = wxMpPrepayIdResult.getPrepay_id();
|
||||
if (prepayId == null || prepayId.equals("")) {
|
||||
throw new RuntimeException(
|
||||
String.format("Failed to get prepay id due to error code '%s'(%s).",
|
||||
wxMpPrepayIdResult.getErr_code(),
|
||||
wxMpPrepayIdResult.getErr_code_des()));
|
||||
String.format("Failed to get prepay id due to error code '%s'(%s).",
|
||||
wxMpPrepayIdResult.getErr_code(),
|
||||
wxMpPrepayIdResult.getErr_code_des()));
|
||||
}
|
||||
|
||||
Map<String, String> payInfo = new HashMap<>();
|
||||
@@ -207,22 +203,22 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
payInfo.put("codeUrl", wxMpPrepayIdResult.getCode_url());
|
||||
}
|
||||
|
||||
String finalSign = WxCryptUtil.createSign(payInfo,
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerKey());
|
||||
String finalSign = this.createSign(payInfo,
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerKey());
|
||||
payInfo.put("paySign", finalSign);
|
||||
return payInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxMpPayResult getJSSDKPayResult(String transactionId,
|
||||
String outTradeNo) {
|
||||
String outTradeNo) throws WxErrorException {
|
||||
String nonce_str = System.currentTimeMillis() + "";
|
||||
|
||||
SortedMap<String, String> packageParams = new TreeMap<>();
|
||||
packageParams.put("appid",
|
||||
this.wxMpService.getWxMpConfigStorage().getAppId());
|
||||
this.wxMpService.getWxMpConfigStorage().getAppId());
|
||||
packageParams.put("mch_id",
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerId());
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerId());
|
||||
|
||||
if (transactionId != null && !"".equals(transactionId.trim())) {
|
||||
packageParams.put("transaction_id", transactionId);
|
||||
@@ -230,41 +226,25 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
packageParams.put("out_trade_no", outTradeNo);
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"Either 'transactionId' or 'outTradeNo' must be given.");
|
||||
"Either 'transactionId' or 'outTradeNo' must be given.");
|
||||
}
|
||||
|
||||
packageParams.put("nonce_str", nonce_str);
|
||||
packageParams.put("sign", WxCryptUtil.createSign(packageParams,
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerKey()));
|
||||
packageParams.put("sign", this.createSign(packageParams,
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerKey()));
|
||||
|
||||
StringBuilder request = new StringBuilder("<xml>");
|
||||
for (Map.Entry<String, String> para : packageParams.entrySet()) {
|
||||
request.append(String.format("<%s>%s</%s>", para.getKey(),
|
||||
para.getValue(), para.getKey()));
|
||||
para.getValue(), para.getKey()));
|
||||
}
|
||||
request.append("</xml>");
|
||||
|
||||
HttpPost httpPost = new HttpPost(
|
||||
"https://api.mch.weixin.qq.com/pay/orderquery");
|
||||
if (this.httpProxy != null) {
|
||||
RequestConfig config = RequestConfig.custom().setProxy(this.httpProxy)
|
||||
.build();
|
||||
httpPost.setConfig(config);
|
||||
}
|
||||
|
||||
StringEntity entity = new StringEntity(request.toString(), Consts.UTF_8);
|
||||
httpPost.setEntity(entity);
|
||||
try (CloseableHttpResponse response = this.wxMpService.getHttpclient()
|
||||
.execute(httpPost)) {
|
||||
String responseContent = Utf8ResponseHandler.INSTANCE
|
||||
.handleResponse(response);
|
||||
XStream xstream = XStreamInitializer.getInstance();
|
||||
xstream.alias("xml", WxMpPayResult.class);
|
||||
return (WxMpPayResult) xstream.fromXML(responseContent);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to query order due to IO exception.",
|
||||
e);
|
||||
}
|
||||
String url = "https://api.mch.weixin.qq.com/pay/orderquery";
|
||||
String responseContent = this.wxMpService.post(url, request.toString());
|
||||
XStream xstream = XStreamInitializer.getInstance();
|
||||
xstream.alias("xml", WxMpPayResult.class);
|
||||
return (WxMpPayResult) xstream.fromXML(responseContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -282,126 +262,232 @@ public class WxMpPayServiceImpl implements WxMpPayService {
|
||||
|
||||
@Override
|
||||
public WxMpPayRefundResult refundPay(Map<String, String> parameters)
|
||||
throws WxErrorException {
|
||||
throws WxErrorException {
|
||||
SortedMap<String, String> refundParams = new TreeMap<>(parameters);
|
||||
refundParams.put("appid",
|
||||
this.wxMpService.getWxMpConfigStorage().getAppId());
|
||||
this.wxMpService.getWxMpConfigStorage().getAppId());
|
||||
refundParams.put("mch_id",
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerId());
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerId());
|
||||
refundParams.put("nonce_str", System.currentTimeMillis() + "");
|
||||
refundParams.put("op_user_id",
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerId());
|
||||
String sign = WxCryptUtil.createSign(refundParams,
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerKey());
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerId());
|
||||
String sign = this.createSign(refundParams,
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerKey());
|
||||
refundParams.put("sign", sign);
|
||||
|
||||
StringBuilder request = new StringBuilder("<xml>");
|
||||
for (Map.Entry<String, String> para : refundParams.entrySet()) {
|
||||
request.append(String.format("<%s>%s</%s>", para.getKey(),
|
||||
para.getValue(), para.getKey()));
|
||||
para.getValue(), para.getKey()));
|
||||
}
|
||||
request.append("</xml>");
|
||||
|
||||
HttpPost httpPost = new HttpPost(
|
||||
"https://api.mch.weixin.qq.com/secapi/pay/refund");
|
||||
if (this.httpProxy != null) {
|
||||
RequestConfig config = RequestConfig.custom().setProxy(this.httpProxy)
|
||||
.build();
|
||||
httpPost.setConfig(config);
|
||||
String url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
|
||||
String responseContent = this.wxMpService.post(url, request.toString());
|
||||
XStream xstream = XStreamInitializer.getInstance();
|
||||
xstream.processAnnotations(WxMpPayRefundResult.class);
|
||||
WxMpPayRefundResult wxMpPayRefundResult = (WxMpPayRefundResult) xstream
|
||||
.fromXML(responseContent);
|
||||
|
||||
if (!"SUCCESS".equalsIgnoreCase(wxMpPayRefundResult.getResultCode())
|
||||
|| !"SUCCESS".equalsIgnoreCase(wxMpPayRefundResult.getReturnCode())) {
|
||||
WxError error = new WxError();
|
||||
error.setErrorCode(-1);
|
||||
error.setErrorMsg("return_code:" + wxMpPayRefundResult.getReturnCode()
|
||||
+ ";return_msg:" + wxMpPayRefundResult.getReturnMsg()
|
||||
+ ";result_code:" + wxMpPayRefundResult.getResultCode() + ";err_code"
|
||||
+ wxMpPayRefundResult.getErrCode() + ";err_code_des"
|
||||
+ wxMpPayRefundResult.getErrCodeDes());
|
||||
throw new WxErrorException(error);
|
||||
}
|
||||
|
||||
StringEntity entity = new StringEntity(request.toString(), Consts.UTF_8);
|
||||
httpPost.setEntity(entity);
|
||||
try (CloseableHttpResponse response = this.wxMpService.getHttpclient()
|
||||
.execute(httpPost)) {
|
||||
String responseContent = Utf8ResponseHandler.INSTANCE
|
||||
.handleResponse(response);
|
||||
XStream xstream = XStreamInitializer.getInstance();
|
||||
xstream.processAnnotations(WxMpPayRefundResult.class);
|
||||
WxMpPayRefundResult wxMpPayRefundResult = (WxMpPayRefundResult) xstream
|
||||
.fromXML(responseContent);
|
||||
|
||||
if (!"SUCCESS".equalsIgnoreCase(wxMpPayRefundResult.getResultCode())
|
||||
|| !"SUCCESS".equalsIgnoreCase(wxMpPayRefundResult.getReturnCode())) {
|
||||
WxError error = new WxError();
|
||||
error.setErrorCode(-1);
|
||||
error.setErrorMsg("return_code:" + wxMpPayRefundResult.getReturnCode()
|
||||
+ ";return_msg:" + wxMpPayRefundResult.getReturnMsg()
|
||||
+ ";result_code:" + wxMpPayRefundResult.getResultCode()
|
||||
+ ";err_code" + wxMpPayRefundResult.getErrCode() + ";err_code_des"
|
||||
+ wxMpPayRefundResult.getErrCodeDes());
|
||||
throw new WxErrorException(error);
|
||||
}
|
||||
|
||||
return wxMpPayRefundResult;
|
||||
} catch (IOException e) {
|
||||
String message = MessageFormatter
|
||||
.format("Exception happened when sending refund '{}'.",
|
||||
request.toString())
|
||||
.getMessage();
|
||||
this.log.error(message, e);
|
||||
throw new WxErrorException(
|
||||
WxError.newBuilder().setErrorMsg(message).build());
|
||||
} finally {
|
||||
httpPost.releaseConnection();
|
||||
}
|
||||
return wxMpPayRefundResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkJSSDKCallbackDataSignature(Map<String, String> kvm,
|
||||
String signature) {
|
||||
return signature.equals(WxCryptUtil.createSign(kvm,
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerKey()));
|
||||
String signature) {
|
||||
return signature.equals(this.createSign(kvm,
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerKey()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public WxRedpackResult sendRedpack(Map<String, String> parameters)
|
||||
throws WxErrorException {
|
||||
throws WxErrorException {
|
||||
SortedMap<String, String> packageParams = new TreeMap<>(parameters);
|
||||
packageParams.put("wxappid",
|
||||
this.wxMpService.getWxMpConfigStorage().getAppId());
|
||||
this.wxMpService.getWxMpConfigStorage().getAppId());
|
||||
packageParams.put("mch_id",
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerId());
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerId());
|
||||
packageParams.put("nonce_str", System.currentTimeMillis() + "");
|
||||
|
||||
String sign = WxCryptUtil.createSign(packageParams,
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerKey());
|
||||
String sign = this.createSign(packageParams,
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerKey());
|
||||
packageParams.put("sign", sign);
|
||||
|
||||
StringBuilder request = new StringBuilder("<xml>");
|
||||
for (Map.Entry<String, String> para : packageParams.entrySet()) {
|
||||
request.append(String.format("<%s>%s</%s>", para.getKey(),
|
||||
para.getValue(), para.getKey()));
|
||||
para.getValue(), para.getKey()));
|
||||
}
|
||||
|
||||
request.append("</xml>");
|
||||
|
||||
HttpPost httpPost = new HttpPost(
|
||||
"https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack");
|
||||
if (this.httpProxy != null) {
|
||||
RequestConfig config = RequestConfig.custom().setProxy(this.httpProxy)
|
||||
.build();
|
||||
httpPost.setConfig(config);
|
||||
String url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";
|
||||
|
||||
String responseContent = this.wxMpService.post(url, request.toString());
|
||||
XStream xstream = XStreamInitializer.getInstance();
|
||||
xstream.processAnnotations(WxRedpackResult.class);
|
||||
return (WxRedpackResult) xstream.fromXML(responseContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxRedpackResult sendRedpack(WxSendRedpackRequest request)
|
||||
throws WxErrorException {
|
||||
XStream xstream = XStreamInitializer.getInstance();
|
||||
xstream.processAnnotations(WxSendRedpackRequest.class);
|
||||
xstream.processAnnotations(WxRedpackResult.class);
|
||||
|
||||
request.setWxAppid(this.wxMpService.getWxMpConfigStorage().getAppId());
|
||||
request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId());
|
||||
request.setNonceStr(System.currentTimeMillis() + "");
|
||||
|
||||
String sign = this.createSign(xmlBean2Map(request),
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerKey());
|
||||
request.setSign(sign);
|
||||
|
||||
String url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";
|
||||
if (request.getAmtType() != null) {
|
||||
//裂变红包
|
||||
url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack";
|
||||
}
|
||||
|
||||
StringEntity entity = new StringEntity(request.toString(), Consts.UTF_8);
|
||||
httpPost.setEntity(entity);
|
||||
try (CloseableHttpResponse response = this.wxMpService.getHttpclient()
|
||||
.execute(httpPost)) {
|
||||
String responseContent = Utf8ResponseHandler.INSTANCE
|
||||
.handleResponse(response);
|
||||
XStream xstream = XStreamInitializer.getInstance();
|
||||
xstream.processAnnotations(WxRedpackResult.class);
|
||||
return (WxRedpackResult) xstream.fromXML(responseContent);
|
||||
} catch (IOException e) {
|
||||
String message = MessageFormatter
|
||||
.format("Exception occured when sending redpack '{}'.",
|
||||
request.toString())
|
||||
.getMessage();
|
||||
this.log.error(message, e);
|
||||
throw new WxErrorException(WxError.newBuilder().setErrorMsg(message).build());
|
||||
} finally {
|
||||
httpPost.releaseConnection();
|
||||
String responseContent = this.wxMpService.post(url, xstream.toXML(request));
|
||||
WxRedpackResult redpackResult = (WxRedpackResult) xstream
|
||||
.fromXML(responseContent);
|
||||
if ("FAIL".equals(redpackResult.getResultCode())) {
|
||||
throw new WxErrorException(WxError.newBuilder()
|
||||
.setErrorMsg(
|
||||
redpackResult.getErrCode() + ":" + redpackResult.getErrCodeDes())
|
||||
.build());
|
||||
}
|
||||
|
||||
return redpackResult;
|
||||
}
|
||||
|
||||
private Map<String, String> xmlBean2Map(Object bean) {
|
||||
Map<String, String> result = Maps.newHashMap();
|
||||
for (Entry<String, Reflect> entry : Reflect.on(bean).fields().entrySet()) {
|
||||
Reflect reflect = entry.getValue();
|
||||
if (reflect.get() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
Field field = bean.getClass().getDeclaredField(entry.getKey());
|
||||
if (field.isAnnotationPresent(XStreamAlias.class)) {
|
||||
result.put(field.getAnnotation(XStreamAlias.class).value(),
|
||||
reflect.get().toString());
|
||||
}
|
||||
} catch (NoSuchFieldException | SecurityException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信公众号支付签名算法(详见:https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=4_3)
|
||||
* @param packageParams 原始参数
|
||||
* @param signKey 加密Key(即 商户Key)
|
||||
* @return 签名字符串
|
||||
*/
|
||||
private String createSign(Map<String, String> packageParams, String signKey) {
|
||||
SortedMap<String, String> sortedMap = new TreeMap<>(packageParams);
|
||||
|
||||
StringBuffer toSign = new StringBuffer();
|
||||
for (String key : sortedMap.keySet()) {
|
||||
String value = packageParams.get(key);
|
||||
if (null != value && !"".equals(value) && !"sign".equals(key)
|
||||
&& !"key".equals(key)) {
|
||||
toSign.append(key + "=" + value + "&");
|
||||
}
|
||||
}
|
||||
|
||||
toSign.append("key=" + signKey);
|
||||
|
||||
return DigestUtils.md5Hex(toSign.toString()).toUpperCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxUnifiedOrderResult unifiedOrder(WxUnifiedOrderRequest request)
|
||||
throws WxErrorException {
|
||||
checkParameters(request);
|
||||
|
||||
XStream xstream = XStreamInitializer.getInstance();
|
||||
xstream.processAnnotations(WxUnifiedOrderRequest.class);
|
||||
xstream.processAnnotations(WxUnifiedOrderResult.class);
|
||||
|
||||
request.setAppid(this.wxMpService.getWxMpConfigStorage().getAppId());
|
||||
request.setMchId(this.wxMpService.getWxMpConfigStorage().getPartnerId());
|
||||
request.setNonceStr(System.currentTimeMillis() + "");
|
||||
|
||||
String sign = this.createSign(xmlBean2Map(request),
|
||||
this.wxMpService.getWxMpConfigStorage().getPartnerKey());
|
||||
request.setSign(sign);
|
||||
|
||||
String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
|
||||
|
||||
String responseContent = this.wxMpService.post(url, xstream.toXML(request));
|
||||
WxUnifiedOrderResult result = (WxUnifiedOrderResult) xstream
|
||||
.fromXML(responseContent);
|
||||
if ("FAIL".equals(result.getResultCode())) {
|
||||
throw new WxErrorException(WxError.newBuilder()
|
||||
.setErrorMsg(result.getErrCode() + ":" + result.getErrCodeDes())
|
||||
.build());
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
private void checkParameters(WxUnifiedOrderRequest request) {
|
||||
|
||||
List<String> nullFields = Lists.newArrayList();
|
||||
for (Entry<String, Reflect> entry : Reflect.on(request).fields()
|
||||
.entrySet()) {
|
||||
Reflect reflect = entry.getValue();
|
||||
try {
|
||||
Field field = request.getClass().getDeclaredField(entry.getKey());
|
||||
if (field.isAnnotationPresent(Required.class)
|
||||
&& reflect.get() == null) {
|
||||
nullFields.add(entry.getKey());
|
||||
}
|
||||
} catch (NoSuchFieldException | SecurityException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!nullFields.isEmpty()) {
|
||||
throw new IllegalArgumentException("必填字段[" + nullFields + "]必须提供值");
|
||||
}
|
||||
|
||||
if (!TRADE_TYPES.contains(request.getTradeType())) {
|
||||
throw new IllegalArgumentException(
|
||||
"trade_type目前必须为" + TRADE_TYPES + "其中之一");
|
||||
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user