From 93586a4530cef33af7d00233910e65e406616ecd Mon Sep 17 00:00:00 2001 From: zzs Date: Tue, 7 Mar 2017 20:26:24 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AF=B9=E4=BA=A4=E6=98=93=E8=BE=85=E5=8A=A9?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E8=BF=9B=E8=A1=8C=E7=A9=BA=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pay/fuiou/api/FuiouPayConfigStorage.java | 2 +- .../egan/pay/fuiou/api/FuiouPayService.java | 16 +- .../utils/SimplePostRequestExecutor.java | 6 +- .../api/WxYouDianPayConfigStorage.java | 8 +- .../wx/youdian/api/WxYouDianPayService.java | 134 ++++++---- .../egan/pay/wx/youdian/bean/YdPayError.java | 58 ++++ .../egan/pay/wx/api/WxPayConfigStorage.java | 19 +- .../java/in/egan/pay/wx/api/WxPayService.java | 253 ++++++------------ .../java/in/egan/pay/wx/bean/WxPayError.java | 61 +++++ .../wx/utils/SimplePostRequestExecutor.java | 74 ----- 10 files changed, 327 insertions(+), 304 deletions(-) create mode 100644 pay-java-wx-youdian/src/main/java/in/egan/pay/wx/youdian/bean/YdPayError.java create mode 100644 pay-java-wx/src/main/java/in/egan/pay/wx/bean/WxPayError.java delete mode 100644 pay-java-wx/src/main/java/in/egan/pay/wx/utils/SimplePostRequestExecutor.java diff --git a/pay-java-fuiou/src/main/java/in/egan/pay/fuiou/api/FuiouPayConfigStorage.java b/pay-java-fuiou/src/main/java/in/egan/pay/fuiou/api/FuiouPayConfigStorage.java index 7fdef12..94f0b06 100644 --- a/pay-java-fuiou/src/main/java/in/egan/pay/fuiou/api/FuiouPayConfigStorage.java +++ b/pay-java-fuiou/src/main/java/in/egan/pay/fuiou/api/FuiouPayConfigStorage.java @@ -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 diff --git a/pay-java-fuiou/src/main/java/in/egan/pay/fuiou/api/FuiouPayService.java b/pay-java-fuiou/src/main/java/in/egan/pay/fuiou/api/FuiouPayService.java index eaa8811..293402a 100644 --- a/pay-java-fuiou/src/main/java/in/egan/pay/fuiou/api/FuiouPayService.java +++ b/pay-java-fuiou/src/main/java/in/egan/pay/fuiou/api/FuiouPayService.java @@ -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)); diff --git a/pay-java-fuiou/src/main/java/in/egan/pay/fuiou/utils/SimplePostRequestExecutor.java b/pay-java-fuiou/src/main/java/in/egan/pay/fuiou/utils/SimplePostRequestExecutor.java index 15b0b89..9ef6720 100644 --- a/pay-java-fuiou/src/main/java/in/egan/pay/fuiou/utils/SimplePostRequestExecutor.java +++ b/pay-java-fuiou/src/main/java/in/egan/pay/fuiou/utils/SimplePostRequestExecutor.java @@ -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; diff --git a/pay-java-wx-youdian/src/main/java/in/egan/pay/wx/youdian/api/WxYouDianPayConfigStorage.java b/pay-java-wx-youdian/src/main/java/in/egan/pay/wx/youdian/api/WxYouDianPayConfigStorage.java index d95b094..e48bc82 100644 --- a/pay-java-wx-youdian/src/main/java/in/egan/pay/wx/youdian/api/WxYouDianPayConfigStorage.java +++ b/pay-java-wx-youdian/src/main/java/in/egan/pay/wx/youdian/api/WxYouDianPayConfigStorage.java @@ -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; } diff --git a/pay-java-wx-youdian/src/main/java/in/egan/pay/wx/youdian/api/WxYouDianPayService.java b/pay-java-wx-youdian/src/main/java/in/egan/pay/wx/youdian/api/WxYouDianPayService.java index a0b2da9..664cf42 100644 --- a/pay-java-wx-youdian/src/main/java/in/egan/pay/wx/youdian/api/WxYouDianPayService.java +++ b/pay-java-wx-youdian/src/main/java/in/egan/pay/wx/youdian/api/WxYouDianPayService.java @@ -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 params, String sign) { - return SignUtils.valueOf(payConfigStorage.getSignType()).verify(params, sign, "&key=" + payConfigStorage.getKeyPrivate(), payConfigStorage.getInputCharset()); + @Override + public boolean signVerify(Map 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 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 execute(RequestExecutor 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 query(String tradeNo, String outTradeNo, Callback callback) { + return null; + } + @Override public Map close(String tradeNo, String outTradeNo) { return null; } + @Override + public T close(String tradeNo, String outTradeNo, Callback callback) { + return null; + } + @Override public Map refund(String tradeNo, String outTradeNo) { return null; } + @Override + public T refund(String tradeNo, String outTradeNo, Callback callback) { + return null; + } + @Override public Map refundquery(String tradeNo, String outTradeNo) { return null; } + @Override + public T refundquery(String tradeNo, String outTradeNo, Callback callback) { + return null; + } + @Override public Object downloadbill(Date billDate, String billType) { return null; } - public WxYouDianPayService(PayConfigStorage payConfigStorage) { - setPayConfigStorage(payConfigStorage); + @Override + public T downloadbill(Date billDate, String billType, Callback callback) { + return null; } + @Override + public T secondaryInterface(Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType, Callback callback) { + return null; + } + + public WxYouDianPayService(PayConfigStorage payConfigStorage) { + super(payConfigStorage); + } + + public WxYouDianPayService(PayConfigStorage payConfigStorage, HttpConfigStorage configStorage) { + super(payConfigStorage, configStorage); + } } diff --git a/pay-java-wx-youdian/src/main/java/in/egan/pay/wx/youdian/bean/YdPayError.java b/pay-java-wx-youdian/src/main/java/in/egan/pay/wx/youdian/bean/YdPayError.java new file mode 100644 index 0000000..e703cf9 --- /dev/null +++ b/pay-java-wx-youdian/src/main/java/in/egan/pay/wx/youdian/bean/YdPayError.java @@ -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); + } +} diff --git a/pay-java-wx/src/main/java/in/egan/pay/wx/api/WxPayConfigStorage.java b/pay-java-wx/src/main/java/in/egan/pay/wx/api/WxPayConfigStorage.java index 2f45f70..793717a 100644 --- a/pay-java-wx/src/main/java/in/egan/pay/wx/api/WxPayConfigStorage.java +++ b/pay-java-wx/src/main/java/in/egan/pay/wx/api/WxPayConfigStorage.java @@ -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; diff --git a/pay-java-wx/src/main/java/in/egan/pay/wx/api/WxPayService.java b/pay-java-wx/src/main/java/in/egan/pay/wx/api/WxPayService.java index e872eca..2276846 100644 --- a/pay-java-wx/src/main/java/in/egan/pay/wx/api/WxPayService.java +++ b/pay-java-wx/src/main/java/in/egan/pay/wx/api/WxPayService.java @@ -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 params, String sign) { + public boolean signVerify(Map 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 execute(RequestExecutor 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 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 params = new TreeMap(); - 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 params = new TreeMap(); + 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 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 query(String tradeNo, String outTradeNo, Callback callback) { + return null; + } + @Override public Map close(String tradeNo, String outTradeNo) { return null; } + @Override + public T close(String tradeNo, String outTradeNo, Callback callback) { + return null; + } + @Override public Map refund(String tradeNo, String outTradeNo) { return null; } + @Override + public T refund(String tradeNo, String outTradeNo, Callback callback) { + return null; + } + @Override public Map refundquery(String tradeNo, String outTradeNo) { return null; } + @Override + public T refundquery(String tradeNo, String outTradeNo, Callback callback) { + return null; + } + @Override public Object downloadbill(Date billDate, String billType) { return null; } - - protected T executeInternal(RequestExecutor 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 downloadbill(Date billDate, String billType, Callback callback) { + return null; } - public HttpHost getHttpProxy() { - return httpProxy; + @Override + public T secondaryInterface(Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType, Callback 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); - } } diff --git a/pay-java-wx/src/main/java/in/egan/pay/wx/bean/WxPayError.java b/pay-java-wx/src/main/java/in/egan/pay/wx/bean/WxPayError.java new file mode 100644 index 0000000..51ab7bc --- /dev/null +++ b/pay-java-wx/src/main/java/in/egan/pay/wx/bean/WxPayError.java @@ -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); + } +} diff --git a/pay-java-wx/src/main/java/in/egan/pay/wx/utils/SimplePostRequestExecutor.java b/pay-java-wx/src/main/java/in/egan/pay/wx/utils/SimplePostRequestExecutor.java deleted file mode 100644 index 513e017..0000000 --- a/pay-java-wx/src/main/java/in/egan/pay/wx/utils/SimplePostRequestExecutor.java +++ /dev/null @@ -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 { - - @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 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 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;*/ - } - -} \ No newline at end of file