From d41fc4cec1845558f5863e1480a128cefb1c5d3c Mon Sep 17 00:00:00 2001 From: zzs Date: Tue, 7 Mar 2017 20:27:01 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E4=BB=98=E5=AE=9D=E4=BA=A4=E6=98=93?= =?UTF-8?q?=E8=BE=85=E5=8A=A9=E6=8E=A5=E5=8F=A3=E5=AE=9E=E7=8E=B0=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../egan/pay/ali/api/AliPayConfigStorage.java | 2 +- .../in/egan/pay/ali/api/AliPayService.java | 339 ++++++++++++------ .../egan/pay/ali/bean/AliTransactionType.java | 23 +- .../pay/ali/before/api/AliPayService.java | 330 +++++++++++------ .../ali/before/bean/AliTransactionType.java | 19 +- .../util/SimpleGetRequestExecutor.java | 9 +- .../pay/demo/controller/PayController.java | 39 +- .../pay/demo/dao/ApyAccountRepository.java | 19 +- .../java/in/egan/pay/demo/entity/PayType.java | 6 +- .../in/egan/pay/demo/service/PayResponse.java | 9 +- .../service/handler/AliPayMessageHandler.java | 8 +- .../service/handler/WxPayMessageHandler.java | 1 - 12 files changed, 543 insertions(+), 261 deletions(-) rename pay-java-ali/src/main/java/in/egan/pay/ali/{ => before}/util/SimpleGetRequestExecutor.java (87%) diff --git a/pay-java-ali/src/main/java/in/egan/pay/ali/api/AliPayConfigStorage.java b/pay-java-ali/src/main/java/in/egan/pay/ali/api/AliPayConfigStorage.java index ea6ea7a..374d4dd 100644 --- a/pay-java-ali/src/main/java/in/egan/pay/ali/api/AliPayConfigStorage.java +++ b/pay-java-ali/src/main/java/in/egan/pay/ali/api/AliPayConfigStorage.java @@ -58,7 +58,7 @@ public class AliPayConfigStorage extends BasePayConfigStorage { } /** - * @see #setPid() + * @see #setPid(String) * @return 合作者id */ @Deprecated diff --git a/pay-java-ali/src/main/java/in/egan/pay/ali/api/AliPayService.java b/pay-java-ali/src/main/java/in/egan/pay/ali/api/AliPayService.java index e09f821..bd3fc2b 100644 --- a/pay-java-ali/src/main/java/in/egan/pay/ali/api/AliPayService.java +++ b/pay-java-ali/src/main/java/in/egan/pay/ali/api/AliPayService.java @@ -1,26 +1,29 @@ package in.egan.pay.ali.api; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import in.egan.pay.ali.bean.AliTransactionType; -import in.egan.pay.ali.util.SimpleGetRequestExecutor; 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.result.PayError; +import in.egan.pay.common.bean.TransactionType; +import in.egan.pay.common.bean.result.PayException; import in.egan.pay.common.exception.PayErrorException; +import in.egan.pay.common.http.ClientHttpRequest; +import in.egan.pay.common.http.HttpConfigStorage; import in.egan.pay.common.util.sign.SignUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.awt.image.BufferedImage; -import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.net.URLEncoder; import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.*; /** @@ -36,6 +39,14 @@ public class AliPayService extends BasePayService { private String httpsReqUrl = "https://openapi.alipay.com/gateway.do"; private String httpsReqUrlBefore = "https://mapi.alipay.com/gateway.do"; + public AliPayService(PayConfigStorage payConfigStorage, HttpConfigStorage configStorage) { + super(payConfigStorage, configStorage); + } + + public AliPayService(PayConfigStorage payConfigStorage) { + super(payConfigStorage); + } + public String getHttpsVerifyUrl() { return httpsReqUrl + "?service=notify_verify"; @@ -50,81 +61,68 @@ public class AliPayService extends BasePayService { return false; } - try { - return getSignVerify(params, params.get("sign")) && "true".equals(verifyUrl(params.get("notify_id"))); - } catch (PayErrorException e) { - e.printStackTrace(); - } + return signVerify(params, params.get("sign")) && verifySource(params.get("notify_id")); - return false; } - /** * 根据反馈回来的信息,生成签名结果 * @param params 通知返回来的参数数组 * @param sign 比对的签名结果 * @return 生成的签名结果 */ - public boolean getSignVerify(Map params, String sign) { + @Override + public boolean signVerify(Map params, String sign) { return SignUtils.valueOf(payConfigStorage.getSignType()).verify(params, sign, payConfigStorage.getKeyPublic(), payConfigStorage.getInputCharset()); } + + + + + /** + * + * @param id 业务id, 数据的真实性. + * @return + */ @Override - public String verifyUrl(String notify_id) throws PayErrorException { - return execute(new SimpleGetRequestExecutor(), getHttpsVerifyUrl(), "partner=" + payConfigStorage.getPartner() + "¬ify_id=" + notify_id); + public boolean verifySource(String id) { + + return "true".equals(requestTemplate.getForObject( getHttpsVerifyUrl() + "partner=" + payConfigStorage.getPid() + "¬ify_id=" + id, String.class)); } /** - * 向支付宝端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 - * - * @param executor - * @param uri - * @param data + * 生成并设置签名 + * @param parameters 请求参数 * @return - * @throws PayErrorException - * @source chanjarster/weixin-java-tools */ - @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() == 404) { - 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); + private Map setSign(Map parameters){ + parameters.put("sign_type", payConfigStorage.getSignType()); + String sign = createSign( SignUtils.parameterText(parameters, "&", "sign", "appId"), payConfigStorage.getInputCharset()); - throw new RuntimeException("支付宝服务端异常,超出重试次数"); + /* try { + sign = URLEncoder.encode(sign, payConfigStorage.getInputCharset()); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + }*/ + parameters.put("sign", sign); + return parameters; } - /** * 返回创建的订单信息 * * @param order 支付订单 * @return - * @see in.egan.pay.common.bean.PayOrder + * @see PayOrder */ @Override public Map orderInfo(PayOrder order) { - Map orderInfo = getOrder(order); +/* Map orderInfo = getOrder(order); String sign = createSign( SignUtils.parameterText(orderInfo, "&"), "UTF-8"); @@ -134,8 +132,8 @@ public class AliPayService extends BasePayService { e.printStackTrace(); } orderInfo.put("sign", sign); - orderInfo.put("sign_type", payConfigStorage.getSignType()); - return orderInfo; + orderInfo.put("sign_type", payConfigStorage.getSignType());*/ + return setSign(getOrder(order)); } @@ -145,25 +143,28 @@ public class AliPayService extends BasePayService { * * @param order 支付订单 * @return - * @see in.egan.pay.common.bean.PayOrder + * @see PayOrder */ private Map getOrder(PayOrder order) { - //兼容上一版本的即时到账 - if (AliTransactionType.DIRECT == order.getTransactionType()){ - return getOrderDirect(order); + //兼容上一版本 + /* if (AliTransactionType.DIRECT == order.getTransactionType() || AliTransactionType.MOBILE == order.getTransactionType() || AliTransactionType.WAPPAY == order.getTransactionType()){ + return getOrderBefore(order); } +*/ - Map orderInfo = new TreeMap<>(); + /* Map orderInfo = new TreeMap<>(); orderInfo.put("app_id", payConfigStorage.getAppid()); orderInfo.put("method", order.getTransactionType().getType()); orderInfo.put("charset", payConfigStorage.getInputCharset()); DateFormat formatter = DateFormat.getDateTimeInstance(); orderInfo.put("timestamp", formatter.format( new Date())); - orderInfo.put("version", "1.0"); + orderInfo.put("version", "1.0");*/ + Map orderInfo = getPublicParameters(order.getTransactionType()); + orderInfo.put("notify_url", payConfigStorage.getNotifyUrl()); - JSONObject bizContent = new JSONObject(); + Map bizContent = new TreeMap<>(); if ("alipay.trade.pay".equals(order.getTransactionType().getType())){ bizContent.put("scene", order.getTransactionType().toString().toLowerCase()); bizContent.put("product_code", "FACE_TO_FACE_PAYMENT"); @@ -176,13 +177,25 @@ public class AliPayService extends BasePayService { bizContent.put("subject", order.getSubject()); bizContent.put("out_trade_no", order.getOutTradeNo()); bizContent.put("total_amount", order.getPrice().setScale(2, BigDecimal.ROUND_HALF_UP).toString()); - orderInfo.put("biz_content", bizContent.toJSONString()); - - - + orderInfo.put("biz_content", JSON.toJSONString(bizContent)); return orderInfo; } + /** + * 获取公共请求参数 + * @param transactionType 交易类型 + * @return + */ + private Map getPublicParameters(TransactionType transactionType ){ + Map orderInfo = new TreeMap<>(); + orderInfo.put("app_id", payConfigStorage.getAppid()); + orderInfo.put("method", transactionType.getType()); + orderInfo.put("charset", payConfigStorage.getInputCharset()); + DateFormat formatter = DateFormat.getDateTimeInstance(); + orderInfo.put("timestamp", formatter.format( new Date())); + orderInfo.put("version", "1.0"); + return orderInfo; + } /** * 支付宝创建订单信息 @@ -190,11 +203,10 @@ public class AliPayService extends BasePayService { * * @param order 支付订单 * @return - * @see in.egan.pay.common.bean.PayOrder + * @see PayOrder */ - private Map getOrderDirect(PayOrder order) { + private Map getOrderBefore(PayOrder order) { Map orderInfo = new TreeMap<>(); -// StringBuilder orderInfo = new StringBuilder(); // 签约合作者身份ID orderInfo.put("partner", payConfigStorage.getPartner()); @@ -232,10 +244,8 @@ public class AliPayService extends BasePayService { // 该参数数值不接受小数点,如1.5h,可转换为90m。 // TODO 2017/2/6 11:05 author: egan 目前写死,这一块建议配置 orderInfo.put("it_b_pay", "30m"); - // extern_token为经过快登授权获取到的alipay_open_id,带上此参数用户将使用授权的账户进行支付 // orderInfo.put("extern_token", extern_token ); - // 支付宝处理完请求后,当前页面跳转到商户指定页面的路径,可空 orderInfo.put("return_url", payConfigStorage.getReturnUrl()); @@ -248,12 +258,6 @@ public class AliPayService extends BasePayService { - @Override - public String createSign(String content, String characterEncoding) { - - return SignUtils.valueOf(payConfigStorage.getSignType()).createSign(content, payConfigStorage.getKeyPrivate(),characterEncoding); - } - @Override public Map getParameter2Map(Map parameterMap, InputStream is) { @@ -264,11 +268,8 @@ public class AliPayService extends BasePayService { String[] values = parameterMap.get(name); String valueStr = ""; for (int i = 0,len = values.length; i < len; i++) { - valueStr += (i == len - 1) ? values[i] - : values[i] + ","; + valueStr += (i == len - 1) ? values[i] : values[i] + ","; } - //乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化 - //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk"); params.put(name, valueStr); } @@ -319,62 +320,176 @@ public class AliPayService extends BasePayService { public BufferedImage genQrPay(Map orderInfo) { throw new UnsupportedOperationException(); } - + /** + * 交易查询接口 + * @param tradeNo 支付平台订单号 + * @param outTradeNo 商户单号 + * @return + */ @Override public Map query(String tradeNo, String outTradeNo) { - return null; - } - @Override - public Map close(String tradeNo, String outTradeNo) { - return null; - } - - @Override - public Map refund(String tradeNo, String outTradeNo) { - return null; - } - - @Override - public Map refundquery(String tradeNo, String outTradeNo) { - return null; - } - - @Override - public Object downloadbill(Date billDate, String billType) { - return null; + return query(tradeNo, outTradeNo, new Callback>() { + @Override + public Map perform(Map map) { + return map; + } + }); } /** * - * @param executor - * @param uri - * @param data + * @param tradeNo 支付平台订单号 + * @param outTradeNo 商户单号 + * @param callback 处理器 * @param - * @param * @return - * @throws PayErrorException */ - protected T executeInternal(RequestExecutor executor, String uri, E data) throws PayErrorException { + @Override + public T query(String tradeNo, String outTradeNo, Callback callback) { - try { - return executor.execute(getHttpClient(), httpProxy, uri, data); - } catch (IOException e) { - throw new RuntimeException(e); - } + return secondaryInterface(tradeNo, outTradeNo, AliTransactionType.QUERY, callback); } - @Override - public PayConfigStorage getPayConfigStorage() { - return payConfigStorage; + public Map close(String tradeNo, String outTradeNo) { + + return close(tradeNo, outTradeNo, new Callback>() { + @Override + public Map perform(Map map) { + return map; + } + }); } - public AliPayService() { + @Override + public T close(String tradeNo, String outTradeNo, Callback callback) { + return secondaryInterface(tradeNo, outTradeNo, AliTransactionType.CLOSE, callback); } - public AliPayService(PayConfigStorage payConfigStorage) { - setPayConfigStorage(payConfigStorage); + @Override + public Map refund(String tradeNo, String outTradeNo) { + + return refund(tradeNo, outTradeNo, new Callback>() { + @Override + public Map perform(Map map) { + return map; + } + }); } + + @Override + public T refund(String tradeNo, String outTradeNo, Callback callback) { + return secondaryInterface(tradeNo, outTradeNo, AliTransactionType.REFUND, callback); + } + + @Override + public Map refundquery(String tradeNo, String outTradeNo) { + return refundquery(tradeNo, outTradeNo, new Callback>() { + @Override + public Map perform(Map map) { + return map; + } + }); + } + + @Override + public T refundquery(String tradeNo, String outTradeNo, Callback callback) { + return secondaryInterface(tradeNo, outTradeNo, AliTransactionType.REFUNDQUERY, callback); + } + + /** + * 目前只支持日账单 + * @param billDate 账单类型,商户通过接口或商户经开放平台授权后其所属服务商通过接口可以获取以下账单类型:trade、signcustomer;trade指商户基于支付宝交易收单的业务账单;signcustomer是指基于商户支付宝余额收入及支出等资金变动的帐务账单; + * @param billType 账单时间:日账单格式为yyyy-MM-dd,月账单格式为yyyy-MM。 + * @return + */ + @Override + public Map downloadbill(Date billDate, String billType) { + return downloadbill(billDate, billType, new Callback>() { + @Override + public Map perform(Map map) { + return map; + } + }); + } + + /** + * 目前只支持日账单 + * @param billDate 账单时间:具体请查看对应支付平台 + * @param billType 账单类型,具体请查看对应支付平台 + * @param callback 处理器 + * @param + * @return + */ + @Override + public T downloadbill(Date billDate, String billType, Callback callback) { + + //获取公共参数 + Map parameters = getPublicParameters(AliTransactionType.DOWNLOADBILL); + + Map bizContent = new TreeMap<>(); + bizContent.put("bill_type", billType); + //目前只支持日账单 + DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); + df.setTimeZone(TimeZone.getTimeZone("GMT+8")); + bizContent.put("bill_date", df.format(billDate)); + //设置请求参数的集合 + parameters.put("biz_content", JSON.toJSONString(bizContent)); + //设置签名 + setSign(parameters); + return callback.perform(requestTemplate.getForObject(httpsReqUrl + "?" + ClientHttpRequest.getMapToParameters(parameters), JSONObject.class)); + } + + /** + * + * @param tradeNoOrBillDate 支付平台订单号或者账单类型, 具体请 + * 类型为{@link String }或者 {@link Date },类型须强制限制,类型不对应则抛出异常{@link in.egan.pay.common.exception.PayErrorException} + * @param outTradeNoBillType 商户单号或者 账单类型 + * @param transactionType 交易类型 + * @param callback 处理器 + * @param + * @return + */ + @Override + public T secondaryInterface(Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType, Callback callback) { + if (transactionType == AliTransactionType.DOWNLOADBILL){ + if (tradeNoOrBillDate instanceof Date){ + return downloadbill((Date) tradeNoOrBillDate, outTradeNoBillType, callback); + } + throw new PayErrorException(new PayException("failure", "非法类型异常:" + tradeNoOrBillDate.getClass())); + } + + if (!(tradeNoOrBillDate instanceof String)){ + throw new PayErrorException(new PayException("failure", "非法类型异常:" + tradeNoOrBillDate.getClass())); + } + + //获取公共参数 + Map parameters = getPublicParameters(transactionType); + //设置请求参数的集合 + parameters.put("biz_content", getContentToJson(tradeNoOrBillDate.toString(), outTradeNoBillType)); + //设置签名 + setSign(parameters); + return callback.perform(requestTemplate.getForObject(httpsReqUrl + "?" + ClientHttpRequest.getMapToParameters(parameters), JSONObject.class)); + + } + + /** + * 获取biz_content。不包含下载账单 + * @param tradeNo 支付平台订单号 + * @param outTradeNo 商户单号 + * @return + */ + private String getContentToJson(String tradeNo, String outTradeNo){ + Map bizContent = new TreeMap<>(); + if (null != outTradeNo){ + bizContent.put("out_trade_no", outTradeNo); + } + if (null != tradeNo){ + bizContent.put("trade_no", tradeNo); + } + return JSON.toJSONString(bizContent); + } + } diff --git a/pay-java-ali/src/main/java/in/egan/pay/ali/bean/AliTransactionType.java b/pay-java-ali/src/main/java/in/egan/pay/ali/bean/AliTransactionType.java index 981f75b..4d3feae 100644 --- a/pay-java-ali/src/main/java/in/egan/pay/ali/bean/AliTransactionType.java +++ b/pay-java-ali/src/main/java/in/egan/pay/ali/bean/AliTransactionType.java @@ -4,16 +4,33 @@ import in.egan.pay.common.bean.TransactionType; /** * 阿里交易类型 + *
+ * 说明交易类型主要用于支付接口调用参数所需
+ * {@link #APP 新版app支付}
+ * {@link #UNAWARE  不知道交易类型,主要用于回调通知,回调后不清楚交易类型,以此定义}
+ *
+ *
+ *
+ * 
+ * * @author egan * @email egzosn@gmail.com * @date 2016/10/19 22:58 */ public enum AliTransactionType implements TransactionType { - //即时到帐 //移动支付 //手机网站支付 - DIRECT("create_direct_pay_by_user"),APP("alipay.trade.app.pay"),WAP("alipay.trade.wap.pay") + //app支付 //手机网站支付 + APP("alipay.trade.app.pay"),WAP("alipay.trade.wap.pay") // TODO 2017/2/23 20:26 author: egan 以下三个为主动交易类型 暂未测试, //扫码付 //条码付 // 声波付 - ,SWEEPPAY("alipay.trade.precreate"),BAR_CODE("alipay.trade.pay"),WAVE_CODE("alipay.trade.pay"),; + ,SWEEPPAY("alipay.trade.precreate"),BAR_CODE("alipay.trade.pay"),WAVE_CODE("alipay.trade.pay") + //交易辅助接口 + ,QUERY("alipay.trade.query"),CLOSE("alipay.trade.close"),REFUND("alipay.trade.refund"),REFUNDQUERY("alipay.trade.fastpay.refund.query"),DOWNLOADBILL("alipay.data.dataservice.bill.downloadurl.query") + + //回调通知,回调后不清楚交易类型,以此定义 + ,UNAWARE("UNAWARE") + ; + + private String type; diff --git a/pay-java-ali/src/main/java/in/egan/pay/ali/before/api/AliPayService.java b/pay-java-ali/src/main/java/in/egan/pay/ali/before/api/AliPayService.java index 276bc1e..355d273 100644 --- a/pay-java-ali/src/main/java/in/egan/pay/ali/before/api/AliPayService.java +++ b/pay-java-ali/src/main/java/in/egan/pay/ali/before/api/AliPayService.java @@ -1,23 +1,29 @@ package in.egan.pay.ali.before.api; -import in.egan.pay.ali.util.SimpleGetRequestExecutor; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import in.egan.pay.ali.before.bean.AliTransactionType; 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.result.PayError; +import in.egan.pay.common.bean.TransactionType; +import in.egan.pay.common.bean.result.PayException; import in.egan.pay.common.exception.PayErrorException; +import in.egan.pay.common.http.ClientHttpRequest; +import in.egan.pay.common.http.HttpConfigStorage; import in.egan.pay.common.util.sign.SignUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.awt.image.BufferedImage; -import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.net.URLEncoder; +import java.text.DateFormat; +import java.text.SimpleDateFormat; import java.util.*; /** @@ -27,12 +33,20 @@ import java.util.*; * @date 2016-5-18 14:09:01 * @see in.egan.pay.ali.api.AliPayService */ -@Deprecated public class AliPayService extends BasePayService { protected final Log log = LogFactory.getLog(AliPayService.class); private String httpsReqUrl = "https://mapi.alipay.com/gateway.do"; + private String queryReqUrl = "https://openapi.alipay.com/gateway.do"; + + public AliPayService(PayConfigStorage payConfigStorage) { + super(payConfigStorage); + } + + public AliPayService(PayConfigStorage payConfigStorage, HttpConfigStorage configStorage) { + super(payConfigStorage, configStorage); + } public String getHttpsVerifyUrl() { @@ -42,14 +56,13 @@ public class AliPayService extends BasePayService { @Override public boolean verify(Map params) { - if (params.get("sign") == null || params.get("notify_id") == null) { log.debug("支付宝支付异常:params:" + params); return false; } try { - return getSignVerify(params, params.get("sign")) && "true".equals(verifyUrl(params.get("notify_id"))); + return signVerify(params, params.get("sign")) && verifySource(params.get("notify_id")); } catch (PayErrorException e) { e.printStackTrace(); } @@ -57,6 +70,10 @@ public class AliPayService extends BasePayService { return false; } + @Override + public boolean verifySource(String id) { + return "true".equals(requestTemplate.getForObject( getHttpsVerifyUrl() + "partner=" + payConfigStorage.getPid() + "¬ify_id=" + id, String.class)); + } /** * 根据反馈回来的信息,生成签名结果 @@ -64,51 +81,49 @@ public class AliPayService extends BasePayService { * @param sign 比对的签名结果 * @return 生成的签名结果 */ - public boolean getSignVerify(Map params, String sign) { + @Override + public boolean signVerify(Map params, String sign) { return SignUtils.valueOf(payConfigStorage.getSignType()).verify(params, sign, payConfigStorage.getKeyPublic(), payConfigStorage.getInputCharset()); } - @Override - public String verifyUrl(String notify_id) throws PayErrorException { - return execute(new SimpleGetRequestExecutor(), getHttpsVerifyUrl(), "partner=" + payConfigStorage.getPartner() + "¬ify_id=" + notify_id); + /** + * 生成并设置签名 + * @param parameters 请求参数 + * @return + */ + private Map setSign(Map parameters){ + parameters.put("sign_type", payConfigStorage.getSignType()); + String sign = createSign(SignUtils.parameterText(parameters, "&", "sign", "appId"), payConfigStorage.getInputCharset()); + /* try { + sign = URLEncoder.encode(sign, payConfigStorage.getInputCharset()); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + }*/ + parameters.put("sign", sign); + + return parameters; } - /** - * 向支付宝端发送请求,在这里执行的策略是当发生access_token过期时才去刷新,然后重新执行请求,而不是全局定时请求 - * - * @param executor - * @param uri - * @param data + * 获取公共请求参数 + * @param transactionType 交易类型 * @return - * @throws PayErrorException - * @source chanjarster/weixin-java-tools */ - @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() == 404) { - 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); + private Map getPublicParameters(TransactionType transactionType ){ + Map orderInfo = new TreeMap<>(); + orderInfo.put("app_id", payConfigStorage.getAppid()); + orderInfo.put("method", transactionType.getType()); + orderInfo.put("format", "json"); + orderInfo.put("charset", payConfigStorage.getInputCharset()); - throw new RuntimeException("支付宝服务端异常,超出重试次数"); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + df.setTimeZone(TimeZone.getTimeZone("GMT+8")); +// DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + orderInfo.put("timestamp", df.format(new Date())); + orderInfo.put("version", "1.0"); + return orderInfo; } @@ -124,7 +139,7 @@ public class AliPayService extends BasePayService { Map orderInfo = getOrder(order); - String sign = createSign( SignUtils.parameterText(orderInfo, "&"), "UTF-8"); + String sign = createSign(orderInfo, "UTF-8"); try { sign = URLEncoder.encode(sign, "UTF-8"); @@ -142,51 +157,30 @@ public class AliPayService extends BasePayService { * * @param order 支付订单 * @return - * @see in.egan.pay.common.bean.PayOrder + * @see PayOrder */ private Map getOrder(PayOrder order) { Map orderInfo = new TreeMap<>(); -// StringBuilder orderInfo = new StringBuilder(); // 签约合作者身份ID orderInfo.put("partner", payConfigStorage.getPartner()); -// orderInfo.append( "partner=").append( "\"").append( payConfigStorage.getPartner() ).append("\""); - // 签约卖家支付宝账号 orderInfo.put("seller_id", payConfigStorage.getSeller()); -// orderInfo.append("&seller_id=" ) .append("\"" ) .append(payConfigStorage.getSeller() ) .append("\""); - // 商户网站唯一订单号 orderInfo.put("out_trade_no", order.getTradeNo()); -// orderInfo.append("&out_trade_no=" ) .append("\"" ).append(order.getTradeNo() ) .append("\""); - // 商品名称 orderInfo.put("subject", order.getSubject()); -// orderInfo.append("&subject=" ) .append("\"" ) .append(order.getSubject() ) .append("\""); - // 商品详情 orderInfo.put("body", order.getBody()); -// orderInfo.append("&body=" ) .append("\"" ) .append(order.getBody() ) .append("\""); - // 商品金额 orderInfo.put("total_fee", order.getPrice().setScale(2, BigDecimal.ROUND_HALF_UP).toString() ); -// orderInfo.append("&total_fee=" ) .append("\"" ) .append(order.getPrice().setScale(2, BigDecimal.ROUND_HALF_UP) ) .append("\""); - // 服务器异步通知页面路径 orderInfo.put("notify_url", payConfigStorage.getNotifyUrl() ); -// orderInfo.append("¬ify_url=" ) .append("\"" ).append( payConfigStorage.getNotifyUrl() ) .append("\""); - // 服务接口名称, 固定值 orderInfo.put("service", order.getTransactionType().getType() ); -// orderInfo.append("&service=\"" ).append( order.getTransactionType().getType() ).append("\""); - // 支付类型, 固定值 orderInfo.put("payment_type", "1" ); -// orderInfo.append("&payment_type=\"1\""); - // 参数编码, 固定值 orderInfo.put("_input_charset", payConfigStorage.getInputCharset()); -// orderInfo.append("&_input_charset=\"utf-8\""); - // 设置未付款交易的超时时间 // 默认30分钟,一旦超时,该笔交易就会自动被关闭。 // 取值范围:1m~15d。 @@ -194,29 +188,16 @@ public class AliPayService extends BasePayService { // 该参数数值不接受小数点,如1.5h,可转换为90m。 // TODO 2017/2/6 11:05 author: egan 目前写死,这一块建议配置 orderInfo.put("it_b_pay", "30m"); -// orderInfo.append("&it_b_pay=\"30m\""); - - // extern_token为经过快登授权获取到的alipay_open_id,带上此参数用户将使用授权的账户进行支付 - // orderInfo.append("&extern_token=" ) .append("\"" ) extern_token ) .append("\""); - // 支付宝处理完请求后,当前页面跳转到商户指定页面的路径,可空 orderInfo.put("return_url", payConfigStorage.getReturnUrl()); -// orderInfo.append("&return_url=\"m.alipay.com\""); - // 调用银行卡支付,需配置此参数,参与签名, 固定值 (需要签约《无线银行卡快捷支付》才能使用) // if (order.getTransactionType().getType()) -// orderInfo.append("&paymethod=\"expressGateway\""); +// orderInfo.put("paymethod","expressGateway"); return orderInfo; } - @Override - public String createSign(String content, String characterEncoding) { - - return SignUtils.valueOf(payConfigStorage.getSignType()).createSign(content, payConfigStorage.getKeyPrivate(),characterEncoding); - } - @Override public Map getParameter2Map(Map parameterMap, InputStream is) { @@ -265,13 +246,14 @@ public class AliPayService extends BasePayService { //submit按钮控件请不要含有name属性 -// formHtml.append(""); formHtml.append(""); formHtml.append(""); return formHtml.toString(); } + + /** * 生成二维码支付 * 暂未实现或无此功能 @@ -283,61 +265,177 @@ public class AliPayService extends BasePayService { throw new UnsupportedOperationException(); } + + /** + * 交易查询接口 + * @param tradeNo 支付平台订单号 + * @param outTradeNo 商户单号 + * @return + */ @Override public Map query(String tradeNo, String outTradeNo) { - return null; - } - @Override - public Map close(String tradeNo, String outTradeNo) { - return null; - } - - @Override - public Map refund(String tradeNo, String outTradeNo) { - return null; - } - - @Override - public Map refundquery(String tradeNo, String outTradeNo) { - return null; - } - - @Override - public Object downloadbill(Date billDate, String billType) { - return null; + return query(tradeNo, outTradeNo, new Callback>() { + @Override + public Map perform(Map map) { + return map; + } + }); } /** * - * @param executor - * @param uri - * @param data + * @param tradeNo 支付平台订单号 + * @param outTradeNo 商户单号 + * @param callback 处理器 * @param - * @param * @return - * @throws PayErrorException */ - protected T executeInternal(RequestExecutor executor, String uri, E data) throws PayErrorException { + @Override + public T query(String tradeNo, String outTradeNo, Callback callback) { - try { - return executor.execute(getHttpClient(), httpProxy, uri, data); - } catch (IOException e) { - throw new RuntimeException(e); - } + return secondaryInterface(tradeNo, outTradeNo, AliTransactionType.QUERY, callback); } - @Override - public PayConfigStorage getPayConfigStorage() { - return payConfigStorage; + public Map close(String tradeNo, String outTradeNo) { + + return close(tradeNo, outTradeNo, new Callback>() { + @Override + public Map perform(Map map) { + return map; + } + }); } - public AliPayService() { + @Override + public T close(String tradeNo, String outTradeNo, Callback callback) { + return secondaryInterface(tradeNo, outTradeNo, AliTransactionType.CLOSE, callback); } - public AliPayService(PayConfigStorage payConfigStorage) { - setPayConfigStorage(payConfigStorage); + @Override + public Map refund(String tradeNo, String outTradeNo) { + + return refund(tradeNo, outTradeNo, new Callback>() { + @Override + public Map perform(Map map) { + return map; + } + }); } + + @Override + public T refund(String tradeNo, String outTradeNo, Callback callback) { + return secondaryInterface(tradeNo, outTradeNo, AliTransactionType.REFUND, callback); + } + + @Override + public Map refundquery(String tradeNo, String outTradeNo) { + return refundquery(tradeNo, outTradeNo, new Callback>() { + @Override + public Map perform(Map map) { + return map; + } + }); + } + + @Override + public T refundquery(String tradeNo, String outTradeNo, Callback callback) { + return secondaryInterface(tradeNo, outTradeNo, AliTransactionType.REFUNDQUERY, callback); + } + + /** + * 目前只支持日账单 + * @param billDate 账单类型,商户通过接口或商户经开放平台授权后其所属服务商通过接口可以获取以下账单类型:trade、signcustomer;trade指商户基于支付宝交易收单的业务账单;signcustomer是指基于商户支付宝余额收入及支出等资金变动的帐务账单; + * @param billType 账单时间:日账单格式为yyyy-MM-dd,月账单格式为yyyy-MM。 + * @return + */ + @Override + public Map downloadbill(Date billDate, String billType) { + return downloadbill(billDate, billType, new Callback>() { + @Override + public Map perform(Map map) { + return map; + } + }); + } + + /** + * 目前只支持日账单 + * @param billDate 账单时间:具体请查看对应支付平台 + * @param billType 账单类型,具体请查看对应支付平台 + * @param callback 处理器 + * @param + * @return + */ + @Override + public T downloadbill(Date billDate, String billType, Callback callback) { + + //获取公共参数 + Map parameters = getPublicParameters(AliTransactionType.DOWNLOADBILL); + + Map bizContent = new TreeMap<>(); + bizContent.put("bill_type", billType); + //目前只支持日账单 + DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); + df.setTimeZone(TimeZone.getTimeZone("GMT+8")); + bizContent.put("bill_date", df.format(billDate)); + //设置请求参数的集合 + parameters.put("biz_content", JSON.toJSONString(bizContent)); + //设置签名 + setSign(parameters); + return callback.perform(requestTemplate.getForObject(queryReqUrl + "?" + ClientHttpRequest.getMapToParameters(parameters), JSONObject.class)); + } + + /** + * + * @param tradeNoOrBillDate 支付平台订单号或者账单类型, 具体请 + * 类型为{@link String }或者 {@link Date },类型须强制限制,类型不对应则抛出异常{@link in.egan.pay.common.exception.PayErrorException} + * @param outTradeNoBillType 商户单号或者 账单类型 + * @param transactionType 交易类型 + * @param callback 处理器 + * @param + * @return + */ + @Override + public T secondaryInterface(Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType, Callback callback) { + if (transactionType == AliTransactionType.DOWNLOADBILL){ + if (tradeNoOrBillDate instanceof Date){ + return downloadbill((Date) tradeNoOrBillDate, outTradeNoBillType, callback); + } + throw new PayErrorException(new PayException("failure", "非法类型异常:" + tradeNoOrBillDate.getClass())); + } + + if (!(tradeNoOrBillDate instanceof String)){ + throw new PayErrorException(new PayException("failure", "非法类型异常:" + tradeNoOrBillDate.getClass())); + } + + //获取公共参数 + Map parameters = getPublicParameters(transactionType); + //设置请求参数的集合 + parameters.put("biz_content", getContentToJson(tradeNoOrBillDate.toString(), outTradeNoBillType)); + //设置签名 + setSign(parameters); + return callback.perform(requestTemplate.getForObject(queryReqUrl + "?" + ClientHttpRequest.getMapToParameters(parameters), JSONObject.class)); + + } + + /** + * 获取biz_content。不包含下载账单 + * @param tradeNo 支付平台订单号 + * @param outTradeNo 商户单号 + * @return + */ + private String getContentToJson(String tradeNo, String outTradeNo){ + Map bizContent = new TreeMap<>(); + if (null != outTradeNo){ + bizContent.put("out_trade_no", outTradeNo); + } + if (null != tradeNo){ + bizContent.put("trade_no", tradeNo); + } + return JSON.toJSONString(bizContent); + } + } diff --git a/pay-java-ali/src/main/java/in/egan/pay/ali/before/bean/AliTransactionType.java b/pay-java-ali/src/main/java/in/egan/pay/ali/before/bean/AliTransactionType.java index dd1b5d2..cc2bd1d 100644 --- a/pay-java-ali/src/main/java/in/egan/pay/ali/before/bean/AliTransactionType.java +++ b/pay-java-ali/src/main/java/in/egan/pay/ali/before/bean/AliTransactionType.java @@ -4,6 +4,15 @@ import in.egan.pay.common.bean.TransactionType; /** * 阿里交易类型 + *
+ * 说明交易类型主要用于支付接口调用参数所需
+ * {@link #APP 新版app支付}
+ * {@link #UNAWARE  不知道交易类型,主要用于回调通知,回调后不清楚交易类型,以此定义}
+ *
+ *
+ *
+ * 
+ * * @author egan * @email egzosn@gmail.com * @date 2016/10/19 22:58 @@ -11,8 +20,14 @@ import in.egan.pay.common.bean.TransactionType; */ @Deprecated public enum AliTransactionType implements TransactionType { - //即时到帐 //移动支付 //手机网站支付 - DIRECT("create_direct_pay_by_user"),APP("mobile.securitypay.pay"),WAP("alipay.wap.create.direct.pay.by.user"); + //即时到帐 //移动支付 //手机网站支付 + DIRECT("create_direct_pay_by_user"),APP("mobile.securitypay.pay"),WAP("alipay.wap.create.direct.pay.by.user"), + //交易辅助接口 + QUERY("alipay.trade.query"),CLOSE("alipay.trade.close"),REFUND("alipay.trade.refund"),REFUNDQUERY("alipay.trade.fastpay.refund.query"),DOWNLOADBILL("alipay.data.dataservice.bill.downloadurl.query") + + //不知道交易类型,主要用于回调通知,回调后不清楚交易类型,以此定义 + ,UNAWARE("UNAWARE") + ; private String type; diff --git a/pay-java-ali/src/main/java/in/egan/pay/ali/util/SimpleGetRequestExecutor.java b/pay-java-ali/src/main/java/in/egan/pay/ali/before/util/SimpleGetRequestExecutor.java similarity index 87% rename from pay-java-ali/src/main/java/in/egan/pay/ali/util/SimpleGetRequestExecutor.java rename to pay-java-ali/src/main/java/in/egan/pay/ali/before/util/SimpleGetRequestExecutor.java index 990f055..307f60a 100644 --- a/pay-java-ali/src/main/java/in/egan/pay/ali/util/SimpleGetRequestExecutor.java +++ b/pay-java-ali/src/main/java/in/egan/pay/ali/before/util/SimpleGetRequestExecutor.java @@ -1,4 +1,4 @@ -package in.egan.pay.ali.util; +package in.egan.pay.ali.before.util; /** * @author egan @@ -6,10 +6,10 @@ package in.egan.pay.ali.util; * @date 2016-5-24 */ -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.http.Utf8ResponseHandler; +import in.egan.pay.common.before.util.http.Utf8ResponseHandler; import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; @@ -24,6 +24,7 @@ import java.io.IOException; * @source chanjarster/weixin-java-tools * */ +@Deprecated public class SimpleGetRequestExecutor implements RequestExecutor { @Override diff --git a/pay-java-demo/src/main/java/in/egan/pay/demo/controller/PayController.java b/pay-java-demo/src/main/java/in/egan/pay/demo/controller/PayController.java index 79e1d08..8df7906 100644 --- a/pay-java-demo/src/main/java/in/egan/pay/demo/controller/PayController.java +++ b/pay-java-demo/src/main/java/in/egan/pay/demo/controller/PayController.java @@ -2,6 +2,13 @@ package in.egan.pay.demo.controller; +import com.alipay.api.AlipayApiException; +import com.alipay.api.AlipayClient; +import com.alipay.api.DefaultAlipayClient; +import com.alipay.api.request.AlipayTradeQueryRequest; +import com.alipay.api.response.AlipayTradeQueryResponse; +import in.egan.pay.ali.before.bean.AliTransactionType; +import in.egan.pay.common.api.Callback; import in.egan.pay.common.util.str.StringUtils; import in.egan.pay.demo.entity.ApyAccount; import in.egan.pay.demo.entity.PayType; @@ -14,7 +21,6 @@ import in.egan.pay.common.bean.PayOrder; import in.egan.pay.common.bean.PayOutMessage; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; @@ -149,6 +155,37 @@ public class PayController{ return payResponse.getService().getPayOutMessage("fail","失败").toMessage(); } + /** + * 查询 + * @param payId + * @return + */ + @RequestMapping("query") + public Map query(Integer payId) { + PayResponse payResponse = service.getPayResponse(payId); + + + return payResponse.getService().query("2017012921001004530273937216", "8a2950f959cf08740159ea0666fc04bd"); + } + + /** + * 查询 + * @param payId + * @return + */ + @RequestMapping("query1") + public Map query1(Integer payId) { + PayResponse payResponse = service.getPayResponse(payId); + + return payResponse.getService().secondaryInterface("2017012921001004530273937216", "8a2950f959cf08740159ea0666fc04bd", AliTransactionType.QUERY, new Callback>() { + @Override + public Map perform(Map map) { + return map; + } + }); + } + + diff --git a/pay-java-demo/src/main/java/in/egan/pay/demo/dao/ApyAccountRepository.java b/pay-java-demo/src/main/java/in/egan/pay/demo/dao/ApyAccountRepository.java index aa6f61a..70f3d51 100644 --- a/pay-java-demo/src/main/java/in/egan/pay/demo/dao/ApyAccountRepository.java +++ b/pay-java-demo/src/main/java/in/egan/pay/demo/dao/ApyAccountRepository.java @@ -29,24 +29,25 @@ public class ApyAccountRepository { ApyAccount apyAccount1 = new ApyAccount(); apyAccount1.setPayId(1); apyAccount1.setPartner("2088911944978307"); - apyAccount1.setAppid("2016052301431829"); + apyAccount1.setAppid("2016041301292728"); // TODO 2017/2/9 16:20 author: egan sign_type只有单一key时public_key与private_key相等,比如sign_type=MD5的情况 - apyAccount1.setPublicKey("48gf0iwuhr***********r9weh9eiut9"); - apyAccount1.setPrivateKey("48gf0iwuhr***********r9weh9eiut9"); + apyAccount1.setPublicKey("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCnxj/9qwVfgoUh/y2W89L6BkRAFljhNhgPdyPuBV64bfQNN1PjbCzkIM6qRdKBoLPXmKKMiFYnkd6rAoprih3/PrQEB/VsW8OoM8fxn67UDYuyBTqA23MML9q1+ilIZwBC2AQ2UBVOrFXfFl75p6/B5KsiNG9zpgmLCUYuLkxpLQIDAQAB"); + apyAccount1.setPrivateKey("MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANJ480HqtM0gcAFfU1Mi9D/U8VCb51nUIQkxAcbCABh1awhVte7cVRU5Qf+iJr9OewPVRSEyFzAbstrSDggv5Igq7qiQr3HeM265FIMdfY5snxe4u+BBrFDmdpewSAa6WpSJRtcKW2uO6Ui5ycD6n61j2B6TvCCKsDijTzFcxOcpAgMBAAECgYEAorOJKL2tQpz+uLDeEviEZAvS+ANtFo3bc+WEgAdcV4v9T5YibCG7TArVMC5DUcPzaIUnSYAVWMUwv+N9oWqUeB9sue04sdfaBpHPAaOSezzb4J/TtEaJoX72HcjWhgrG1AIAKyaw1P1nQ99zr2EbS1wIGXw4FNLWuo92tKDCsZkCQQD19Feh5Xm8N49Mqt8of+Mpez2dbxKVcU3yZLZFTDj47SZVto32q+kRqngRmgM037c2ms6Rnb9qyw6tbvzTUr8rAkEA2xGdPBu5Fmm2/+Jm8/1hxfqzwVATyc/TOAaeVAK7bS2GaWNoe4wJ4Xea/U2XPl+8+qP5Q+RYJ98IUOLC+e5o+wJBAKynEmEWikcipVhHVpHCfH8hARaj4uK+/92Y7w5kPFYZe2CN3sf604hQJysL9xZFuQH+1+UGXFmmIy6CC754hrMCQCmeoBPCZJiofvcAaXTjZ8b4SVxpvUizLjrPrxbg6gDlDEtLcpc+VMY8Nfr32csk3z9zFbFbWZBBpE/RtR9Mty8CQFqhVygF3FIiz5Sc38sz12RqOT7kUQK3R0FiATOtXkKHLzb/QyolOXi/avhLp/gIl7+IqZg51Vx8BvyypnIfKgw="); apyAccount1.setNotifyUrl("http://pay.egan.in/payBack2.json"); // 无需同步回调可不填 apyAccount1.setReturnUrl(""); apyAccount1.setInputCharset("UTF-8"); - apyAccount1.setSignType("MD5"); - apyAccount1.setPayType(PayType.wxPay); - apyAccount1.setMsgType(MsgType.xml); + apyAccount1.setSignType("RSA"); + apyAccount1.setPayType(PayType.aliPay); + apyAccount1.setMsgType(MsgType.text); apyAccounts.put(1, apyAccount1); ApyAccount apyAccount2 = new ApyAccount(); apyAccount2.setPayId(2); - apyAccount2.setPartner("2088****8307"); - apyAccount2.setPublicKey("MIGfMA0GCSqGSIb3DQEBAQUAA4*****IZwBC2AQ2UBVOrFXfFl75p6/B5KsiNG9zpgmLCUYuLkxpLQIDAQAB"); - apyAccount2.setPrivateKey("MIICdwIBADANBgkqhkiG9w0BAQ**********g51Vx8BvyypnIfKgw="); + apyAccount2.setPartner("2088911944978307"); + apyAccount2.setAppid("2017030105973474"); + apyAccount2.setPublicKey("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDI6d306Q8fIfCOaTXyiUeJHkrIvYISRcc73s3vF1ZT7XN8RNPwJxo8pWaJMmvyTn9N4HQ632qJBVHf8sxHi/fEsraprwCtzvzQETrNRwVxLO5jVmRGi60j8Ue1efIlzPXV9je9mkjzOmdssymZkh2QhUrCmZYI/FCEa3/cNMW0QIDAQAB"); + apyAccount2.setPrivateKey("MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAI6D7p2Dza+JYQEnLUKTeGTkJ/QSWA7dulJJS/8ETTQDEwb5ODwKXK3ItOLjeJ9yTAemSqJefIMHBTG+MvONrWgZpmz2oK8dAxH/iqyqxb4r9IODsMgzziNb9EjCs3vfHx9zgcmBhTDnqQZE0jnY2MchOXwnUDz45gDdxwhBHZEpAgMBAAECgYBzKU1CX2VwOVT3t46tQ7l/3ZYjdkdODAIpyCzu76zrIKjZc73rVnw5ufvhc+re/V9OtyOMPUnkH2IlJgrKIGxEg2OuBFdl8rDmNYjBdiFSykjMmsyj2s5uLZ73iEfXxtNDVrahh5ISdNYJAaANL6pMLE7mGoTinc/jv0cUKS1aAQJBAMrfLx/vnu5dvDE7+NvJ8xv8xLhR94NTzpGZl9tNYa2FgxsrD9n9j7SBf5AbWOcZzc5eRYMSDFt18DS5jpjx+2ECQQCz1l2AWWbWHwW+JcDgHI3CXUjOv4f1mltOc+tGA2aqKkXV6Euy5r5kla9BXCFr/b1XGGt4dhXDczWWLTfV7nLJAkAfMMkyA8lPpKG2gB32zMnP18D3BcMkMdJkmFS8pt0JrKlHmAtL3KwneHGAWnQEs/bsb5oIWNIFjdBsisrdwPaBAkEAm8ymOpC5Z91+cypv+3ihU3bPodYK6rssST5h4MkHg3qV/+h81GPVJH0NVPmFNvKfuzm7uaPL3QUNsqpACkXHCQJBAIfxCQjvmmj5HrXh0HF+VLYJVsVg6WVcLRNOLAi2xP39Ep1JN/Gsq7D/O7K9RJhs8g+69jKCVW83C4Wss/O7AQM="); apyAccount2.setNotifyUrl("http://pay.egan.in/payBack3.json"); // 无需同步回调可不填 app填这个就可以 apyAccount2.setReturnUrl("m.alipay.com"); diff --git a/pay-java-demo/src/main/java/in/egan/pay/demo/entity/PayType.java b/pay-java-demo/src/main/java/in/egan/pay/demo/entity/PayType.java index a868527..fdad387 100644 --- a/pay-java-demo/src/main/java/in/egan/pay/demo/entity/PayType.java +++ b/pay-java-demo/src/main/java/in/egan/pay/demo/entity/PayType.java @@ -1,8 +1,8 @@ package in.egan.pay.demo.entity; import in.egan.pay.ali.api.AliPayConfigStorage; -import in.egan.pay.ali.api.AliPayService; -import in.egan.pay.ali.bean.AliTransactionType; +import in.egan.pay.ali.before.api.AliPayService; +import in.egan.pay.ali.before.bean.AliTransactionType; import in.egan.pay.common.api.PayService; import in.egan.pay.common.bean.BasePayType; import in.egan.pay.common.bean.TransactionType; @@ -22,11 +22,13 @@ import in.egan.pay.wx.youdian.bean.YoudianTransactionType; */ public enum PayType implements BasePayType { + aliPay{ @Override public PayService getPayService(ApyAccount apyAccount) { AliPayConfigStorage aliPayConfigStorage = new AliPayConfigStorage(); aliPayConfigStorage.setPid(apyAccount.getPartner()); + aliPayConfigStorage.setAppId(apyAccount.getAppid()); aliPayConfigStorage.setAliPublicKey(apyAccount.getPublicKey()); aliPayConfigStorage.setKeyPrivate(apyAccount.getPrivateKey()); aliPayConfigStorage.setNotifyUrl(apyAccount.getNotifyUrl()); diff --git a/pay-java-demo/src/main/java/in/egan/pay/demo/service/PayResponse.java b/pay-java-demo/src/main/java/in/egan/pay/demo/service/PayResponse.java index 99ef7fb..5fee84e 100644 --- a/pay-java-demo/src/main/java/in/egan/pay/demo/service/PayResponse.java +++ b/pay-java-demo/src/main/java/in/egan/pay/demo/service/PayResponse.java @@ -2,10 +2,10 @@ package in.egan.pay.demo.service; +import in.egan.pay.ali.bean.AliTransactionType; import in.egan.pay.demo.entity.ApyAccount; import in.egan.pay.demo.entity.PayType; import in.egan.pay.demo.service.handler.AliPayMessageHandler; -import in.egan.pay.demo.service.handler.FuiouPayMessageHandler; import in.egan.pay.demo.service.handler.WxPayMessageHandler; import in.egan.pay.demo.service.handler.YouDianPayMessageHandler; import in.egan.pay.demo.service.interceptor.AliPayMessageInterceptor; @@ -64,20 +64,21 @@ public class PayResponse { .rule() .async(false) .msgType(MsgType.text.name()) //消息类型 - .event(PayType.aliPay.name()) //支付账户事件类型 + .payType(PayType.aliPay.name()) //支付账户事件类型 + .transactionType(AliTransactionType.UNAWARE.name())//交易类型,有关回调的可在这处理 .interceptor(new AliPayMessageInterceptor(payId)) //拦截器 .handler(autowire(new AliPayMessageHandler(payId))) //处理器 .end() .rule() .async(false) .msgType(MsgType.xml.name()) - .event(PayType.wxPay.name()) + .payType(PayType.wxPay.name()) .handler(autowire(new WxPayMessageHandler(payId))) .end() .rule() .async(false) .msgType(MsgType.json.name()) - .event(PayType.youdianPay.name()) + .payType(PayType.youdianPay.name()) .handler(autowire(new YouDianPayMessageHandler(payId))) .end() diff --git a/pay-java-demo/src/main/java/in/egan/pay/demo/service/handler/AliPayMessageHandler.java b/pay-java-demo/src/main/java/in/egan/pay/demo/service/handler/AliPayMessageHandler.java index 7850770..2172fbc 100644 --- a/pay-java-demo/src/main/java/in/egan/pay/demo/service/handler/AliPayMessageHandler.java +++ b/pay-java-demo/src/main/java/in/egan/pay/demo/service/handler/AliPayMessageHandler.java @@ -24,12 +24,8 @@ public class AliPayMessageHandler extends BasePayMessageHandler { @Override public PayOutMessage handle(PayMessage payMessage, Map context, PayService payService) throws PayErrorException { //交易状态 - String trade_status = null; - try { - trade_status = new String(payMessage.getPayMessage().get("trade_status").getBytes("ISO-8859-1"),"UTF-8"); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } + String trade_status =payMessage.getPayMessage().get("trade_status"); + if(trade_status.equals("TRADE_FINISHED")){ //判断该笔订单是否在商户网站中已经做过处理 diff --git a/pay-java-demo/src/main/java/in/egan/pay/demo/service/handler/WxPayMessageHandler.java b/pay-java-demo/src/main/java/in/egan/pay/demo/service/handler/WxPayMessageHandler.java index b29c5a0..777f0ee 100644 --- a/pay-java-demo/src/main/java/in/egan/pay/demo/service/handler/WxPayMessageHandler.java +++ b/pay-java-demo/src/main/java/in/egan/pay/demo/service/handler/WxPayMessageHandler.java @@ -4,7 +4,6 @@ import in.egan.pay.common.api.PayService; import in.egan.pay.common.bean.PayMessage; import in.egan.pay.common.bean.PayOutMessage; import in.egan.pay.common.exception.PayErrorException; -import in.egan.pay.demo.service.handler.BasePayMessageHandler; import java.util.Map;