mirror of
https://gitee.com/egzosn/pay-java-parent.git
synced 2026-06-01 05:19:47 +08:00
对交易辅助接口进行空实现
This commit is contained in:
@@ -2,7 +2,7 @@ package in.egan.pay.fuiou.api;/**
|
||||
* Created by Fuzx on 2017/1/16 0016.
|
||||
*/
|
||||
|
||||
import in.egan.pay.common.api.BasePayConfigStorage;
|
||||
import in.egan.pay.common.before.api.BasePayConfigStorage;
|
||||
|
||||
/**
|
||||
* @author Fuzx
|
||||
|
||||
@@ -2,13 +2,13 @@ package in.egan.pay.fuiou.api;/**
|
||||
* Created by Fuzx on 2017/1/16 0016.
|
||||
*/
|
||||
|
||||
import in.egan.pay.common.api.BasePayService;
|
||||
import in.egan.pay.common.api.PayConfigStorage;
|
||||
import in.egan.pay.common.api.RequestExecutor;
|
||||
import in.egan.pay.common.before.api.BasePayService;
|
||||
import in.egan.pay.common.before.api.PayConfigStorage;
|
||||
import in.egan.pay.common.before.api.RequestExecutor;
|
||||
import in.egan.pay.common.bean.MethodType;
|
||||
import in.egan.pay.common.bean.PayOrder;
|
||||
import in.egan.pay.common.bean.PayOutMessage;
|
||||
import in.egan.pay.common.bean.result.PayError;
|
||||
import in.egan.pay.common.before.bean.result.PayError;
|
||||
import in.egan.pay.common.exception.PayErrorException;
|
||||
import in.egan.pay.common.util.sign.SignUtils;
|
||||
import in.egan.pay.common.util.str.StringUtils;
|
||||
@@ -29,8 +29,8 @@ public class FuiouPayService extends BasePayService {
|
||||
|
||||
protected final Log log = LogFactory.getLog(FuiouPayService.class);
|
||||
|
||||
// public final static String fuiouBaseDomain = "https://pay.fuiou.com/";//正式域名
|
||||
public final static String fuiouBaseDomain = "http://www-1.fuiou.com:8888/wg1_run/";//测试域名
|
||||
public final static String fuiouBaseDomain = "https://pay.fuiou.com/";//正式域名
|
||||
// public final static String fuiouBaseDomain = "http://www-1.fuiou.com:8888/wg1_run/";//测试域名
|
||||
|
||||
public final static String fuiouSmpGate = fuiouBaseDomain + "smpGate.do";//B2C/B2B支付
|
||||
|
||||
@@ -132,8 +132,8 @@ public class FuiouPayService extends BasePayService {
|
||||
try {
|
||||
return executeInternal(executor, uri, data);
|
||||
} catch (PayErrorException e) {
|
||||
PayError error = e.getError();
|
||||
if (error.getErrorCode() == 404) {
|
||||
PayError error = (PayError) e.getPayError();
|
||||
if ("404".equals(error.getErrorCode()) ) {
|
||||
int sleepMillis = retrySleepMillis * (1 << retryTimes);
|
||||
try {
|
||||
log.debug(String.format("富友支付系统错误,错误信息:<%s>,(%s)ms 后重试(第%s次)",e.getMessage(),sleepMillis, retryTimes + 1));
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package in.egan.pay.fuiou.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import in.egan.pay.common.api.RequestExecutor;
|
||||
import in.egan.pay.common.bean.result.PayError;
|
||||
import in.egan.pay.common.before.api.RequestExecutor;
|
||||
import in.egan.pay.common.before.bean.result.PayError;
|
||||
import in.egan.pay.common.exception.PayErrorException;
|
||||
import in.egan.pay.common.util.XML;
|
||||
import in.egan.pay.common.util.http.Utf8ResponseHandler;
|
||||
import in.egan.pay.common.before.util.http.Utf8ResponseHandler;
|
||||
import org.apache.http.Consts;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
|
||||
@@ -2,9 +2,6 @@ package in.egan.pay.wx.youdian.api;
|
||||
|
||||
import in.egan.pay.common.api.BasePayConfigStorage;
|
||||
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* 支付客户端配置存储
|
||||
* @author egan
|
||||
@@ -40,6 +37,11 @@ public class WxYouDianPayConfigStorage extends BasePayConfigStorage {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPid() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setSeller(String seller) {
|
||||
this.seller = seller;
|
||||
}
|
||||
|
||||
@@ -2,20 +2,21 @@ package in.egan.pay.wx.youdian.api;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import in.egan.pay.common.api.BasePayService;
|
||||
import in.egan.pay.common.api.Callback;
|
||||
import in.egan.pay.common.api.PayConfigStorage;
|
||||
import in.egan.pay.common.api.RequestExecutor;
|
||||
import in.egan.pay.common.bean.MethodType;
|
||||
import in.egan.pay.common.bean.PayOrder;
|
||||
import in.egan.pay.common.bean.PayOutMessage;
|
||||
import in.egan.pay.common.bean.TransactionType;
|
||||
import in.egan.pay.common.bean.outbuilder.JsonBuilder;
|
||||
import in.egan.pay.common.bean.result.PayError;
|
||||
import in.egan.pay.common.exception.PayErrorException;
|
||||
import in.egan.pay.common.http.HttpConfigStorage;
|
||||
import in.egan.pay.common.util.MatrixToImageWriter;
|
||||
import in.egan.pay.common.util.sign.SignUtils;
|
||||
import in.egan.pay.wx.youdian.utils.SimpleGetRequestExecutor;
|
||||
import in.egan.pay.wx.youdian.bean.YdPayError;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
@@ -43,6 +44,7 @@ public class WxYouDianPayService extends BasePayService {
|
||||
public final static String unifiedOrderUrl = "http://life.51youdian.com/Api/CheckoutCounter/unifiedorder";
|
||||
|
||||
|
||||
|
||||
public String getAccessToken() {
|
||||
try {
|
||||
return getAccessToken(false);
|
||||
@@ -76,12 +78,12 @@ public class WxYouDianPayService extends BasePayService {
|
||||
StringBuilder param = new StringBuilder().append("access_token=").append(payConfigStorage.getAccessToken());
|
||||
String sign = createSign(param.toString() + apbNonce, payConfigStorage.getInputCharset());
|
||||
param.append("&apb_nonce=").append(apbNonce).append("&sign=").append(sign);
|
||||
JSONObject json = execute(new SimpleGetRequestExecutor(), resetLoginUrl, param.toString());
|
||||
JSONObject json = execute(resetLoginUrl + "?" + param.toString(), MethodType.GET, null );
|
||||
int errorcode = json.getIntValue("errorcode");
|
||||
if (0 == errorcode){
|
||||
payConfigStorage.updateAccessToken(payConfigStorage.getAccessToken(), 7200);
|
||||
}else {
|
||||
throw new PayErrorException(new PayError(errorcode, json.getString("msg"), json.toJSONString()));
|
||||
throw new PayErrorException(new YdPayError(errorcode, json.getString("msg"), json.toJSONString()));
|
||||
}
|
||||
|
||||
/* try {
|
||||
@@ -141,7 +143,8 @@ public class WxYouDianPayService extends BasePayService {
|
||||
// 4、将拼接出来的字符串连接上apb_nonce的值即AAAAAAAAAA。再连接 password=XXXXXXXusername=XXXXXAAAAAAAAAA
|
||||
String sign = createSign(SignUtils.parameterText(data, "") + apbNonce, payConfigStorage.getInputCharset());
|
||||
String queryParam = SignUtils.parameterText(data) + "&apb_nonce=" + apbNonce + "&sign=" + sign;
|
||||
JSONObject json = execute(new SimpleGetRequestExecutor(), loginUrl, queryParam);
|
||||
|
||||
JSONObject json = execute(loginUrl + "?" + queryParam, MethodType.GET, null);
|
||||
payConfigStorage.updateAccessToken(json.getString("access_token"), json.getLongValue("viptime"));
|
||||
return json;
|
||||
}
|
||||
@@ -152,7 +155,6 @@ public class WxYouDianPayService extends BasePayService {
|
||||
* 微信友店2支付状态校验
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public String getHttpsVerifyUrl() {
|
||||
return unifiedorderStatusUrl;
|
||||
}
|
||||
@@ -166,82 +168,91 @@ public class WxYouDianPayService extends BasePayService {
|
||||
if(params.get("sign") == null) {log.debug("友店微信支付异常:签名为空!out_trade_no=" + params.get("out_trade_no"));}
|
||||
|
||||
try {
|
||||
return getSignVerify(params, params.get("sign")) && "0".equals(verifyUrl(params.get("out_trade_no")));
|
||||
return signVerify(params, params.get("sign")) && verifySource(params.get("out_trade_no"));
|
||||
} catch (PayErrorException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据反馈回来的信息,生成签名结果
|
||||
* @param params 通知返回来的参数数组
|
||||
* @param sign 比对的签名结果
|
||||
* @return 生成的签名结果
|
||||
*/
|
||||
public boolean getSignVerify(Map<String, String> params, String sign) {
|
||||
return SignUtils.valueOf(payConfigStorage.getSignType()).verify(params, sign, "&key=" + payConfigStorage.getKeyPrivate(), payConfigStorage.getInputCharset());
|
||||
@Override
|
||||
public boolean signVerify(Map<String, String> params, String sign) {
|
||||
return SignUtils.valueOf(payConfigStorage.getSignType()).verify(params, sign, "&key=" + payConfigStorage.getKeyPrivate(), payConfigStorage.getInputCharset());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 验证链接来源是否有效
|
||||
* @param outTradeNo 商户订单号(扫码收款返回的order_sn)
|
||||
* @param id 商户订单号(扫码收款返回的order_sn)
|
||||
* @return
|
||||
* @throws PayErrorException
|
||||
*/
|
||||
@Override
|
||||
public String verifyUrl(String outTradeNo) throws PayErrorException {
|
||||
public boolean verifySource(String id) {
|
||||
String apbNonce = SignUtils.randomStr();
|
||||
TreeMap<String, String> data = new TreeMap<>();
|
||||
data.put("access_token", payConfigStorage.getAccessToken());
|
||||
data.put("order_sn", outTradeNo);
|
||||
data.put("order_sn", id);
|
||||
String sign = createSign(SignUtils.parameterText(data, "") + apbNonce, payConfigStorage.getInputCharset());
|
||||
String queryParam = SignUtils.parameterText(data) + "&apb_nonce=" + apbNonce + "&sign=" + sign;
|
||||
|
||||
JSONObject jsonObject = execute(new SimpleGetRequestExecutor(), getHttpsVerifyUrl(), queryParam);
|
||||
|
||||
return jsonObject.getIntValue("errorcode") + "";
|
||||
JSONObject jsonObject = execute(getHttpsVerifyUrl() + "?" + queryParam, MethodType.GET, null);
|
||||
|
||||
return 0 == jsonObject.getIntValue("errorcode");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 向友店端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求
|
||||
*
|
||||
* @param executor
|
||||
* @param uri
|
||||
* @param data
|
||||
* @param uri 请求地址
|
||||
* @param method 请求方式
|
||||
* @see MethodType#GET
|
||||
* @see MethodType#POST
|
||||
* @param request 请求内容,GET无需
|
||||
* @return
|
||||
* @throws PayErrorException
|
||||
*/
|
||||
@Override
|
||||
public <T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) throws PayErrorException {
|
||||
public JSONObject execute(String uri, MethodType method, Object request) throws PayErrorException {
|
||||
int retryTimes = 0;
|
||||
do {
|
||||
try {
|
||||
return executeInternal(executor, uri, data);
|
||||
} catch (PayErrorException e) {
|
||||
PayError error = e.getError();
|
||||
if (error.getErrorCode() == 401) {
|
||||
// 强制设置wxMpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token
|
||||
payConfigStorage.expireAccessToken();
|
||||
//进行重新登陆授权
|
||||
login();
|
||||
int sleepMillis = retrySleepMillis * (1 << retryTimes);
|
||||
try {
|
||||
log.debug(String.format("友店微信系统繁忙,(%s)ms 后重试(第%s次)", sleepMillis, retryTimes + 1));
|
||||
Thread.sleep(sleepMillis);
|
||||
} catch (InterruptedException e1) {
|
||||
throw new RuntimeException(e1);
|
||||
}
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
try {
|
||||
JSONObject result = requestTemplate.doExecute(uri, request, JSONObject.class, method);
|
||||
if ( 0 != result.getIntValue("errorcode")){
|
||||
throw new PayErrorException(new YdPayError(result.getIntValue("errorcode"), result.getString("msg"), result.toJSONString()));
|
||||
}
|
||||
|
||||
}catch (PayErrorException e){
|
||||
PayError error = e.getPayError();
|
||||
if ("401".equals(error.getErrorCode()) ) {
|
||||
// 强制设置wxMpConfigStorage它的access token过期了,这样在下一次请求里就会刷新access token
|
||||
payConfigStorage.expireAccessToken();
|
||||
//进行重新登陆授权
|
||||
login();
|
||||
int sleepMillis = retrySleepMillis * (1 << retryTimes);
|
||||
try {
|
||||
log.debug(String.format("友店微信系统繁忙,(%s)ms 后重试(第%s次)", sleepMillis, retryTimes + 1));
|
||||
Thread.sleep(sleepMillis);
|
||||
} catch (InterruptedException e1) {
|
||||
throw new PayErrorException(new YdPayError(-1, "友店支付服务端重试失败", e1.getMessage()));
|
||||
}
|
||||
}else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
} while (++retryTimes < maxRetryTimes);
|
||||
|
||||
throw new PayErrorException(new PayError(-1, "友店微信服务端异常,超出重试次数"));
|
||||
throw new PayErrorException(new YdPayError(-1, "友店微信服务端异常,超出重试次数"));
|
||||
}
|
||||
|
||||
|
||||
@@ -250,7 +261,7 @@ public class WxYouDianPayService extends BasePayService {
|
||||
*
|
||||
* @param order 支付订单
|
||||
* @return
|
||||
* @see in.egan.pay.common.bean.PayOrder
|
||||
* @see PayOrder
|
||||
*/
|
||||
@Override
|
||||
public JSONObject orderInfo(PayOrder order) {
|
||||
@@ -262,7 +273,7 @@ public class WxYouDianPayService extends BasePayService {
|
||||
data.put("PayMoney", data.remove("paymoney"));
|
||||
String params = SignUtils.parameterText(data) + "&apb_nonce=" + apbNonce + "&sign=" + sign;
|
||||
try {
|
||||
JSONObject json = execute(new SimpleGetRequestExecutor(), unifiedOrderUrl, params);
|
||||
JSONObject json = execute(unifiedOrderUrl+ "?" + params, MethodType.GET, null);
|
||||
//友店比较特殊,需要在下完预订单后,自己存储 order_sn 对应 微信官方文档 out_trade_no
|
||||
order.setTradeNo(json.getString("order_sn"));
|
||||
return json;
|
||||
@@ -360,28 +371,61 @@ public class WxYouDianPayService extends BasePayService {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T query(String tradeNo, String outTradeNo, Callback<T> callback) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> close(String tradeNo, String outTradeNo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T close(String tradeNo, String outTradeNo, Callback<T> callback) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> refund(String tradeNo, String outTradeNo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T refund(String tradeNo, String outTradeNo, Callback<T> callback) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> refundquery(String tradeNo, String outTradeNo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T refundquery(String tradeNo, String outTradeNo, Callback<T> callback) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object downloadbill(Date billDate, String billType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public WxYouDianPayService(PayConfigStorage payConfigStorage) {
|
||||
setPayConfigStorage(payConfigStorage);
|
||||
@Override
|
||||
public <T> T downloadbill(Date billDate, String billType, Callback<T> callback) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T secondaryInterface(Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType, Callback<T> callback) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public WxYouDianPayService(PayConfigStorage payConfigStorage) {
|
||||
super(payConfigStorage);
|
||||
}
|
||||
|
||||
public WxYouDianPayService(PayConfigStorage payConfigStorage, HttpConfigStorage configStorage) {
|
||||
super(payConfigStorage, configStorage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original huodull or egan.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package in.egan.pay.wx.youdian.bean;
|
||||
|
||||
import in.egan.pay.common.bean.result.PayError;
|
||||
|
||||
/**
|
||||
* @author: egan
|
||||
* @email egzosn@gmail.com
|
||||
* @date 2017/3/6 19:41
|
||||
*/
|
||||
public class YdPayError implements PayError {
|
||||
|
||||
private int errorcode;
|
||||
private String msg;
|
||||
private String content;
|
||||
|
||||
@Override
|
||||
public String getErrorCode() {
|
||||
return errorcode + "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public YdPayError(int errorcode, String msg) {
|
||||
this.errorcode = errorcode;
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public YdPayError(int errorcode, String msg, String content) {
|
||||
this.errorcode = errorcode;
|
||||
this.msg = msg;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString() {
|
||||
return "支付错误: errcode=" + errorcode + ", msg=" + msg + (null == content ? "" : "\n content:" + content);
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,8 @@ public class WxPayConfigStorage extends BasePayConfigStorage {
|
||||
|
||||
public String appSecret;
|
||||
public String appid ;
|
||||
public String mchId;// 商户号
|
||||
// 商户号 合作者id
|
||||
public String mchId;
|
||||
|
||||
|
||||
@Override
|
||||
@@ -34,20 +35,28 @@ public class WxPayConfigStorage extends BasePayConfigStorage {
|
||||
this.appid = appid;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public String getPartner() {
|
||||
return mchId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPid() {
|
||||
return mchId;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getSeller() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getToken() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getMchId() {
|
||||
return mchId;
|
||||
|
||||
@@ -1,29 +1,23 @@
|
||||
package in.egan.pay.wx.api;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import in.egan.pay.common.api.BasePayService;
|
||||
import in.egan.pay.common.api.Callback;
|
||||
import in.egan.pay.common.api.PayConfigStorage;
|
||||
import in.egan.pay.common.api.PayService;
|
||||
import in.egan.pay.common.api.RequestExecutor;
|
||||
import in.egan.pay.common.bean.MethodType;
|
||||
import in.egan.pay.common.bean.PayOrder;
|
||||
import in.egan.pay.common.bean.PayOutMessage;
|
||||
import in.egan.pay.common.bean.result.PayError;
|
||||
import in.egan.pay.common.bean.TransactionType;
|
||||
import in.egan.pay.common.exception.PayErrorException;
|
||||
import in.egan.pay.common.http.HttpConfigStorage;
|
||||
import in.egan.pay.common.util.MatrixToImageWriter;
|
||||
import in.egan.pay.common.util.sign.SignUtils;
|
||||
import in.egan.pay.common.util.str.StringUtils;
|
||||
import in.egan.pay.wx.bean.WxPayError;
|
||||
import in.egan.pay.wx.bean.WxTransactionType;
|
||||
import in.egan.pay.wx.utils.SimplePostRequestExecutor;
|
||||
import in.egan.pay.common.util.XML;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||
import org.apache.http.client.CredentialsProvider;
|
||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -36,30 +30,31 @@ import java.util.*;
|
||||
* @email egzosn@gmail.com
|
||||
* @date 2016-5-18 14:09:01
|
||||
*/
|
||||
public class WxPayService implements PayService {
|
||||
public class WxPayService extends BasePayService {
|
||||
protected final Log log = LogFactory.getLog(WxPayService.class);
|
||||
|
||||
protected PayConfigStorage payConfigStorage;
|
||||
|
||||
protected CloseableHttpClient httpClient;
|
||||
|
||||
protected HttpHost httpProxy;
|
||||
|
||||
private int retrySleepMillis = 1000;
|
||||
|
||||
private int maxRetryTimes = 5;
|
||||
|
||||
public final static String httpsVerifyUrl = "https://gw.tenpay.com/gateway";
|
||||
public final static String unifiedOrderUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
|
||||
// public final static String orderqueryUrl = "https://api.mch.weixin.qq.com/pay/orderquery";
|
||||
// public final static String orderqueryUrl = "https://api.mch.weixin.qq.com/pay/orderquery";
|
||||
|
||||
|
||||
|
||||
public WxPayService(PayConfigStorage payConfigStorage) {
|
||||
super(payConfigStorage);
|
||||
}
|
||||
|
||||
public WxPayService(PayConfigStorage payConfigStorage, HttpConfigStorage configStorage) {
|
||||
super(payConfigStorage, configStorage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 微信支付V2版本所需
|
||||
* 当前版本不需要
|
||||
* 当前版本不需要 ?
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public String getHttpsVerifyUrl() {
|
||||
return httpsVerifyUrl + "/verifynotifyid.xml";
|
||||
}
|
||||
@@ -71,13 +66,13 @@ public class WxPayService implements PayService {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(params.get("sign") == null) {
|
||||
if(null == params.get("sign")) {
|
||||
|
||||
log.debug("微信支付异常:签名为空!out_trade_no=" + params.get("out_trade_no"));
|
||||
}
|
||||
|
||||
try {
|
||||
return getSignVerify(params, params.get("sign")) && "true".equals(verifyUrl(params.get("out_trade_no")));
|
||||
return signVerify(params, params.get("sign")) && verifySource(params.get("out_trade_no"));
|
||||
} catch (PayErrorException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -85,6 +80,16 @@ public class WxPayService implements PayService {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 支付宝需要,微信是否也需要再次校验来源,进行订单查询
|
||||
* @param id 商户单号
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean verifySource(String id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据反馈回来的信息,生成签名结果
|
||||
@@ -92,57 +97,11 @@ public class WxPayService implements PayService {
|
||||
* @param sign 比对的签名结果
|
||||
* @return 生成的签名结果
|
||||
*/
|
||||
public boolean getSignVerify(Map<String, String> params, String sign) {
|
||||
public boolean signVerify(Map<String, String> params, String sign) {
|
||||
return SignUtils.valueOf(payConfigStorage.getSignType()).verify(params, sign, "&key=" + payConfigStorage.getKeyPublic(), payConfigStorage.getInputCharset());
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付宝需要,暂时预留
|
||||
* @param out_trade_no 商户单号
|
||||
* @return
|
||||
* @throws PayErrorException
|
||||
*/
|
||||
@Override
|
||||
public String verifyUrl(String out_trade_no) throws PayErrorException {
|
||||
// return execute(new SimplePostRequestExecutor(), getHttpsVerifyUrl(), "partner=" + payConfigStorage.getPartner() + "¬ify_id=" + notify_id);
|
||||
|
||||
return "true";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 向支付端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求
|
||||
*
|
||||
* @param executor
|
||||
* @param uri
|
||||
* @param data
|
||||
* @return
|
||||
* @throws PayErrorException
|
||||
*/
|
||||
@Override
|
||||
public <T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) throws PayErrorException {
|
||||
int retryTimes = 0;
|
||||
do {
|
||||
try {
|
||||
return executeInternal(executor, uri, data);
|
||||
} catch (PayErrorException e) {
|
||||
PayError error = e.getError();
|
||||
if (error.getErrorCode() == 403) {
|
||||
int sleepMillis = retrySleepMillis * (1 << retryTimes);
|
||||
try {
|
||||
log.debug(String.format("微信支付系统繁忙,(%s)ms 后重试(第%s次)", sleepMillis, retryTimes + 1));
|
||||
Thread.sleep(sleepMillis);
|
||||
} catch (InterruptedException e1) {
|
||||
throw new RuntimeException(e1);
|
||||
}
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
} while (++retryTimes < maxRetryTimes);
|
||||
|
||||
throw new PayErrorException(new PayError(-1, "微信支付服务端异常,超出重试次数"));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@@ -150,7 +109,7 @@ public class WxPayService implements PayService {
|
||||
*
|
||||
* @param order 支付订单
|
||||
* @return
|
||||
* @see in.egan.pay.common.bean.PayOrder
|
||||
* @see PayOrder
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> orderInfo(PayOrder order) {
|
||||
@@ -177,44 +136,35 @@ public class WxPayService implements PayService {
|
||||
|
||||
String requestXML = XML.getMap2Xml(parameters);
|
||||
log.debug("requestXML:" + requestXML);
|
||||
String result = null;
|
||||
try {
|
||||
result = execute(new SimplePostRequestExecutor(), unifiedOrderUrl, requestXML);
|
||||
log.debug("获取预支付订单返回结果33:" + result);
|
||||
/////////APP端调起支付的参数列表
|
||||
JSONObject result = getHttpRequestTemplate().postForObject(unifiedOrderUrl, requestXML, JSONObject.class);
|
||||
|
||||
/////////APP端调起支付的参数列表
|
||||
Map map = XML.toJSONObject(result);
|
||||
if (!"SUCCESS".equals(map.get("return_code"))){
|
||||
throw new PayErrorException(new PayError(-1, (String) map.get("return_msg"), result));
|
||||
}
|
||||
//如果是扫码支付无需处理,直接返回
|
||||
if (WxTransactionType.NATIVE == order.getTransactionType()){
|
||||
return map;
|
||||
}
|
||||
|
||||
SortedMap<String, Object> params = new TreeMap<String, Object>();
|
||||
params.put("appid", payConfigStorage.getAppid());
|
||||
params.put("partnerid", payConfigStorage.getPartner());
|
||||
params.put("prepayid", map.get("prepay_id"));
|
||||
params.put("timestamp", System.currentTimeMillis() / 1000);
|
||||
params.put("noncestr", map.get("nonce_str")/*WxpayCore.genNonceStr()*/);
|
||||
|
||||
if (WxTransactionType.JSAPI == order.getTransactionType()){
|
||||
params.put("package", "prepay_id=" + map.get("prepay_id"));
|
||||
params.put("signType", payConfigStorage.getSignType());
|
||||
}else if (WxTransactionType.APP == order.getTransactionType()){
|
||||
params.put("package", "Sign=WXPay");
|
||||
}
|
||||
String paySign = createSign(SignUtils.parameterText(params), payConfigStorage.getInputCharset());
|
||||
params.put("sign", paySign);
|
||||
return params;
|
||||
} catch (PayErrorException e) {
|
||||
e.printStackTrace();
|
||||
if (!"SUCCESS".equals(result.get("return_code"))){
|
||||
throw new PayErrorException(new WxPayError(result.getString("return_code"), result.getString("return_msg"), result.toJSONString()));
|
||||
}
|
||||
//如果是扫码支付无需处理,直接返回
|
||||
if (WxTransactionType.NATIVE == order.getTransactionType()){
|
||||
return result;
|
||||
}
|
||||
|
||||
// result = WxpayCore.httpsRequest2(httpsVerifyUrl, "POST", requestXML);
|
||||
//////////////////////////
|
||||
return null;
|
||||
SortedMap<String, Object> params = new TreeMap<String, Object>();
|
||||
params.put("appid", payConfigStorage.getAppid());
|
||||
params.put("partnerid", payConfigStorage.getPartner());
|
||||
params.put("prepayid", result.get("prepay_id"));
|
||||
params.put("timestamp", System.currentTimeMillis() / 1000);
|
||||
params.put("noncestr", result.get("nonce_str")/*WxpayCore.genNonceStr()*/);
|
||||
|
||||
if (WxTransactionType.JSAPI == order.getTransactionType()){
|
||||
params.put("package", "prepay_id=" + result.get("prepay_id"));
|
||||
params.put("signType", payConfigStorage.getSignType());
|
||||
}else if (WxTransactionType.APP == order.getTransactionType()){
|
||||
params.put("package", "Sign=WXPay");
|
||||
}
|
||||
String paySign = createSign(SignUtils.parameterText(params), payConfigStorage.getInputCharset());
|
||||
params.put("sign", paySign);
|
||||
return params;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -262,9 +212,9 @@ public class WxPayService implements PayService {
|
||||
@Override
|
||||
public BufferedImage genQrPay(Map<String, Object> orderInfo) {
|
||||
//获取对应的支付账户操作工具(可根据账户id)
|
||||
if (!"SUCCESS".equals(orderInfo.get("result_code"))){
|
||||
throw new RuntimeException(new PayError(-1, (String) orderInfo.get("err_code")).toString());
|
||||
}
|
||||
if (!"SUCCESS".equals(orderInfo.get("result_code"))) {
|
||||
throw new PayErrorException(new WxPayError("-1", (String) orderInfo.get("err_code")));
|
||||
}
|
||||
|
||||
|
||||
return MatrixToImageWriter.writeInfoToJpgBuff((String) orderInfo.get("code_url"));
|
||||
@@ -275,87 +225,60 @@ public class WxPayService implements PayService {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T query(String tradeNo, String outTradeNo, Callback<T> callback) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> close(String tradeNo, String outTradeNo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T close(String tradeNo, String outTradeNo, Callback<T> callback) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> refund(String tradeNo, String outTradeNo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T refund(String tradeNo, String outTradeNo, Callback<T> callback) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> refundquery(String tradeNo, String outTradeNo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T refundquery(String tradeNo, String outTradeNo, Callback<T> callback) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object downloadbill(Date billDate, String billType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected <T, E> T executeInternal(RequestExecutor<T, E> executor, String uri, E data) throws PayErrorException {
|
||||
|
||||
try {
|
||||
return executor.execute(getHttpClient(), httpProxy, uri, data);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@Override
|
||||
public <T> T downloadbill(Date billDate, String billType, Callback<T> callback) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public HttpHost getHttpProxy() {
|
||||
return httpProxy;
|
||||
@Override
|
||||
public <T> T secondaryInterface(Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType, Callback<T> callback) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public CloseableHttpClient getHttpClient() {
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置支付配置
|
||||
* @param payConfigStorage 支付配置
|
||||
*/
|
||||
public void setPayConfigStorage(PayConfigStorage payConfigStorage) {
|
||||
this.payConfigStorage = payConfigStorage;
|
||||
|
||||
String http_proxy_host = payConfigStorage.getHttpProxyHost();
|
||||
int http_proxy_port = payConfigStorage.getHttpProxyPort();
|
||||
String http_proxy_username = payConfigStorage.getHttpProxyUsername();
|
||||
String http_proxy_password = payConfigStorage.getHttpProxyPassword();
|
||||
|
||||
if (StringUtils.isNotBlank(http_proxy_host)) {
|
||||
// 使用代理服务器
|
||||
if (StringUtils.isNotBlank(http_proxy_username)) {
|
||||
// 需要用户认证的代理服务器
|
||||
CredentialsProvider credsProvider = new BasicCredentialsProvider();
|
||||
credsProvider.setCredentials(
|
||||
new AuthScope(http_proxy_host, http_proxy_port),
|
||||
new UsernamePasswordCredentials(http_proxy_username, http_proxy_password));
|
||||
httpClient = HttpClients
|
||||
.custom()
|
||||
.setDefaultCredentialsProvider(credsProvider)
|
||||
.build();
|
||||
} else {
|
||||
// 无需用户认证的代理服务器
|
||||
httpClient = HttpClients.createDefault();
|
||||
}
|
||||
httpProxy = new HttpHost(http_proxy_host, http_proxy_port);
|
||||
} else {
|
||||
httpClient = HttpClients.createDefault();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayConfigStorage getPayConfigStorage() {
|
||||
return payConfigStorage;
|
||||
}
|
||||
|
||||
public WxPayService() {
|
||||
}
|
||||
|
||||
public WxPayService(PayConfigStorage payConfigStorage) {
|
||||
setPayConfigStorage(payConfigStorage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2002-2017 the original huodull or egan.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package in.egan.pay.wx.bean;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import in.egan.pay.common.bean.result.PayError;
|
||||
|
||||
/**
|
||||
* @author: egan
|
||||
* @email egzosn@gmail.com
|
||||
* @date 2017/3/6 17:31
|
||||
*/
|
||||
public class WxPayError implements PayError {
|
||||
|
||||
private String errorCode;
|
||||
|
||||
private String errorMsg;
|
||||
private String content;
|
||||
|
||||
|
||||
@Override
|
||||
public String getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorMsg() {
|
||||
return errorMsg;
|
||||
}
|
||||
|
||||
public WxPayError(String errorCode, String errorMsg) {
|
||||
this.errorCode = errorCode;
|
||||
this.errorMsg = errorMsg;
|
||||
}
|
||||
|
||||
public WxPayError(String errorCode, String errorMsg, String content) {
|
||||
this.errorCode = errorCode;
|
||||
this.errorMsg = errorMsg;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString() {
|
||||
return "支付错误: errcode=" + errorCode + ", errmsg=" + errorMsg + (null == content ? "" : "\n content:" + content);
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package in.egan.pay.wx.utils;
|
||||
|
||||
import in.egan.pay.common.api.RequestExecutor;
|
||||
import in.egan.pay.common.bean.result.PayError;
|
||||
import in.egan.pay.common.exception.PayErrorException;
|
||||
import in.egan.pay.common.util.XML;
|
||||
import in.egan.pay.common.util.http.Utf8ResponseHandler;
|
||||
import org.apache.http.Consts;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
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.apache.http.impl.client.CloseableHttpClient;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author egan
|
||||
* @email egzosn@gmail.com
|
||||
* @date 2016-5-18 14:09:01
|
||||
*/
|
||||
public class SimplePostRequestExecutor implements RequestExecutor<String, String> {
|
||||
|
||||
@Override
|
||||
public String execute(CloseableHttpClient httpclient, HttpHost httpProxy, String uri, String postEntity) throws PayErrorException, ClientProtocolException, IOException {
|
||||
HttpPost httpPost = new HttpPost(uri);
|
||||
if (httpProxy != null) {
|
||||
RequestConfig config = RequestConfig.custom().setProxy(httpProxy).build();
|
||||
httpPost.setConfig(config);
|
||||
}
|
||||
|
||||
if (postEntity != null) {
|
||||
StringEntity entity = new StringEntity(postEntity, Consts.UTF_8);
|
||||
httpPost.setEntity(entity);
|
||||
}
|
||||
|
||||
|
||||
try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
|
||||
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
|
||||
/* Map<String, Object> map = XML.toMap(responseContent);
|
||||
|
||||
PayError error = PayError.fromMap(map);
|
||||
if (null != error) {
|
||||
throw new PayErrorException(error);
|
||||
}*/
|
||||
return responseContent;
|
||||
}
|
||||
|
||||
/* CloseableHttpResponse response = null;
|
||||
try {
|
||||
response = httpclient.execute(httpPost);
|
||||
// String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
|
||||
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
|
||||
Map<String, Object> map = XML.toMap(responseContent);
|
||||
|
||||
PayError error = PayError.fromMap(map);
|
||||
if (null != error) {
|
||||
throw new PayErrorException(error);
|
||||
}
|
||||
return responseContent;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
if (response != null) {
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
return null;*/
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user