diff --git a/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/UnionPayController.java b/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/UnionPayController.java index ecd1b121..67792e4e 100644 --- a/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/UnionPayController.java +++ b/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/UnionPayController.java @@ -3,7 +3,9 @@ import com.egzosn.pay.common.api.PayService; -import com.egzosn.pay.common.bean.*; +import com.egzosn.pay.common.bean.MethodType; +import com.egzosn.pay.common.bean.PayOrder; +import com.egzosn.pay.common.bean.RefundOrder; import com.egzosn.pay.common.http.HttpConfigStorage; import com.egzosn.pay.common.util.sign.SignUtils; import com.egzosn.pay.demo.request.QueryOrder; @@ -36,7 +38,7 @@ @RequestMapping("union") public class UnionPayController { - private PayService service = null; + private UnionPayService service = null; @PostConstruct public void init() { @@ -50,17 +52,17 @@ public void init() { unionPayConfigStorage.setAcpMiddleCert("D:/certs/acp_test_middle.cer"); //根证书路径 unionPayConfigStorage.setAcpRootCert("D:/certs/acp_test_root.cer"); - //私钥, 私钥证书格式: 私钥证书路径;私钥证书对应的密码 // unionPayConfigStorage.setKeyPrivate("D:/certs/acp_test_sign.pfx;000000"); // 私钥证书路径 unionPayConfigStorage.setKeyPrivateCert("D:/certs/acp_test_sign.pfx"); //私钥证书对应的密码 unionPayConfigStorage.setKeyPrivateCertPwd("000000"); - - unionPayConfigStorage.setNotifyUrl("http://www.pay.egzosn.com/payBack.json"); - // 无需同步回调可不填 app填这个就可以 + //前台通知网址 即SDKConstants.param_frontUrl unionPayConfigStorage.setReturnUrl("http://www.pay.egzosn.com/payBack.json"); + //后台通知地址 即SDKConstants.param_backUrl + unionPayConfigStorage.setNotifyUrl("http://www.pay.egzosn.com/payBack.json"); + //加密方式 unionPayConfigStorage.setSignType(SignUtils.RSA2.name()); //单一支付可不填 unionPayConfigStorage.setPayType("unionPay"); @@ -82,18 +84,17 @@ public void init() { /** - * 跳到支付页面 - * 针对实时支付,即时付款 - * + * ---业务实现例子1--- + * 功能:生成自动跳转的Html表单 + * 业务类型(关键字):网关支付(WEB)/手机网页支付,企业网银支付(B2B), * @param price 金额 - * @return 跳到支付页面 + * @return 生成自动跳转的Html表单 */ @RequestMapping(value = "toPay.html", produces = "text/html;charset=UTF-8") public String toPay( BigDecimal price) { - //及时收款 - PayOrder order = new PayOrder("订单title", "摘要", null == price ? new BigDecimal(0.01) : price, UUID.randomUUID().toString().replace("-", ""), WEB); - //WAP -// PayOrder order = new PayOrder("订单title", "摘要", null == price ? new BigDecimal(0.01) : price, UUID.randomUUID().toString().replace("-", ""), UnionTransactionType.WAP); + //网关支付(WEB)/手机网页支付 + PayOrder order = new PayOrder("订单title", "摘要", null == price ? new BigDecimal(0.01) : price, UUID.randomUUID().toString().replace("-", ""), + WEB); //企业网银支付(B2B支付) // PayOrder order = new PayOrder("订单title", "摘要", null == price ? new BigDecimal(0.01) : price, UUID.randomUUID().toString().replace("-", ""), UnionTransactionType.B2B); @@ -101,6 +102,20 @@ public String toPay( BigDecimal price) { return service.buildRequest(orderInfo, MethodType.POST); } + /** + * ---业务实现例子2--- + * 功能:获取调起控件的tn号,支付结果等 + * 业务类型:手机控件支付产品(WAP), + * @param price 金额 + * @return 支付结果 + */ + @RequestMapping(value = "toPay.json") + public Map sendHttpRequest( BigDecimal price) { + //手机控件支付产品 + PayOrder order = new PayOrder("订单title", "摘要", null == price ? new BigDecimal(0.01) : price, UUID.randomUUID().toString().replace("-", "") + ,UnionTransactionType.WAP); + return service.sendHttpRequest(order); + } @@ -202,7 +217,7 @@ public String payBackBefore(HttpServletRequest request) throws IOException { * * @return * - * 业务处理在对应的PayMessageHandler里面处理,在哪里设置PayMessageHandler,详情查看{@link com.egzosn.pay.common.api.PayService#setPayMessageHandler(com.egzosn.pay.common.api.PayMessageHandler)} + * 业务处理在对应的PayMessageHandler里面处理,在哪里设置PayMessageHandler,详情查看{@link PayService#setPayMessageHandler(com.egzosn.pay.common.api.PayMessageHandler)} * * 如果未设置 {@link com.egzosn.pay.common.api.PayMessageHandler} 那么会使用默认的 {@link com.egzosn.pay.common.api.DefaultPayMessageHandler} * diff --git a/pay-java-payoneer/pom.xml b/pay-java-payoneer/pom.xml index 84b050be..12c760af 100644 --- a/pay-java-payoneer/pom.xml +++ b/pay-java-payoneer/pom.xml @@ -5,7 +5,7 @@ pay-java-parent com.egzosn - 2.12.6-SNAPSHOT + 2.12.6 4.0.0 pay-java-payoneer diff --git a/pay-java-paypal/pom.xml b/pay-java-paypal/pom.xml index 2a2f2b3c..c1aa1e01 100644 --- a/pay-java-paypal/pom.xml +++ b/pay-java-paypal/pom.xml @@ -5,7 +5,7 @@ pay-java-parent com.egzosn - 2.12.6-SNAPSHOT + 2.12.6 4.0.0 diff --git a/pay-java-union/src/main/java/com/egzosn/pay/union/api/UnionPayService.java b/pay-java-union/src/main/java/com/egzosn/pay/union/api/UnionPayService.java index f6144d94..dab9c79f 100644 --- a/pay-java-union/src/main/java/com/egzosn/pay/union/api/UnionPayService.java +++ b/pay-java-union/src/main/java/com/egzosn/pay/union/api/UnionPayService.java @@ -205,6 +205,21 @@ public boolean verifySource(String id) { return false; } + /** + * 订单超时时间。 + * 超过此时间后,除网银交易外,其他交易银联系统会拒绝受理,提示超时。 跳转银行网银交易如果超时后交易成功,会自动退款,大约5个工作日金额返还到持卡人账户。 + * 此时间建议取支付时的北京时间加15分钟。 + * 超过超时时间调查询接口应答origRespCode不是A6或者00的就可以判断为失败。 + * @param expirationTime 超时时间 + * @return 具体的时间字符串 + */ + private String getPayTimeout(Date expirationTime) { + // + if (null != expirationTime) { + return DateUtils.formatDate(expirationTime, DateUtils.YYYYMMDDHHMMSS); + } + return DateUtils.formatDate(new Timestamp(System.currentTimeMillis() + 30 * 60 * 1000), DateUtils.YYYYMMDDHHMMSS); + } /** * 返回创建的订单信息 * @@ -215,7 +230,11 @@ public boolean verifySource(String id) { @Override public Map orderInfo(PayOrder order) { Map params = this.getCommonParam(); - +// if(order instanceof UnionPayOrder){ +// UnionPayOrder unionPayOrder = (UnionPayOrder)order; +// //todo 其他参数 +//// params.put(); +// } UnionTransactionType type = (UnionTransactionType) order.getTransactionType(); @@ -230,18 +249,11 @@ public Map orderInfo(PayOrder order) { switch (type) { case WAP: case WEB: + //todo PCwap网关跳转支付特殊用法.txt case B2B: params.put(SDKConstants.param_txnAmt, Util.conversionCentAmount(order.getPrice())); params.put("orderDesc", order.getSubject()); - // 订单超时时间。 - // 超过此时间后,除网银交易外,其他交易银联系统会拒绝受理,提示超时。 跳转银行网银交易如果超时后交易成功,会自动退款,大约5个工作日金额返还到持卡人账户。 - // 此时间建议取支付时的北京时间加15分钟。 - // 超过超时时间调查询接口应答origRespCode不是A6或者00的就可以判断为失败。 - if (null != order.getExpirationTime()) { - params.put(SDKConstants.param_payTimeout, DateUtils.formatDate(order.getExpirationTime(), DateUtils.YYYYMMDDHHMMSS)); - } else { - params.put(SDKConstants.param_payTimeout, DateUtils.formatDate(new Timestamp(System.currentTimeMillis() + 30 * 60 * 1000), DateUtils.YYYYMMDDHHMMSS)); - } + params.put(SDKConstants.param_payTimeout, getPayTimeout(order.getExpirationTime())); params.put(SDKConstants.param_frontUrl, payConfigStorage.getReturnUrl()); break; @@ -250,18 +262,15 @@ public Map orderInfo(PayOrder order) { params.put(SDKConstants.param_qrNo, order.getAuthCode()); break; case APPLY_QR_CODE: - if (null != order.getPrice()){ + if (null != order.getPrice()) { params.put(SDKConstants.param_txnAmt, Util.conversionCentAmount(order.getPrice())); } - - if (null != order.getExpirationTime()) { - params.put(SDKConstants.param_payTimeout, DateUtils.formatDate(order.getExpirationTime(), DateUtils.YYYYMMDDHHMMSS)); - } else { - params.put(SDKConstants.param_payTimeout, DateUtils.formatDate(new Timestamp(System.currentTimeMillis() + 30 * 60 * 1000), DateUtils.YYYYMMDDHHMMSS)); - } - + params.put(SDKConstants.param_payTimeout, getPayTimeout(order.getExpirationTime())); break; default: + params.put(SDKConstants.param_txnAmt, Util.conversionCentAmount(order.getPrice())); + params.put(SDKConstants.param_payTimeout, getPayTimeout(order.getExpirationTime())); + params.put("orderDesc", order.getSubject()); } return setSign(params); @@ -370,7 +379,7 @@ public BufferedImage genQrPay(PayOrder order) { } if (this.verify(response)) { if (SDKConstants.OK_RESP_CODE.equals(response.get(SDKConstants.param_respCode))) { - //成功,获取tn号 + //成功 return MatrixToImageWriter.writeInfoToJpgBuff((String) response.get(SDKConstants.param_qrCode)); } throw new PayErrorException(new PayException((String) response.get(SDKConstants.param_respCode), (String) response.get(SDKConstants.param_respMsg), responseStr)); @@ -435,11 +444,11 @@ public PayOutMessage successPayOutMessage(PayMessage payMessage) { } /** - * 获取输出消息,用户返回给支付端, 针对于web端 + * 功能:生成自动跳转的Html表单 * * @param orderInfo 发起支付的订单信息 * @param method 请求方式 "post" "get", - * @return 获取输出消息,用户返回给支付端, 针对于web端 + * @return 生成自动跳转的Html表单返回给支付端, 针对于PC端 * @see MethodType 请求类型 */ @Override @@ -463,6 +472,30 @@ public String buildRequest(Map orderInfo, MethodType method) { return sf.toString(); } + /** + * 功能:将订单信息进行签名并提交请求 + * 业务范围:手机控件支付产品(WAP), + * @param order 订单信息 + * @return 成功:返回支付结果 失败:返回 + */ + public Map sendHttpRequest(PayOrder order){ + Map params = orderInfo(order); + String responseStr = getHttpRequestTemplate().postForObject(this.getBackTransUrl(), params, String.class); + Map response = UriVariables.getParametersToMap(responseStr); + if (response.isEmpty()) { + throw new PayErrorException(new PayException("failure", "响应内容有误!", responseStr)); + } + if (this.verify(response)) { + if (SDKConstants.OK_RESP_CODE.equals(response.get(SDKConstants.param_respCode))) { +// //成功,获取tn号 +// String tn = (String)response.get(SDKConstants.param_tn); +// //TODO + return response; + } + throw new PayErrorException(new PayException((String) response.get(SDKConstants.param_respCode), (String) response.get(SDKConstants.param_respMsg), responseStr)); + } + throw new PayErrorException(new PayException("failure", "验证签名失败", responseStr)); + } /** * 交易查询接口 diff --git a/pay-java-union/src/main/java/com/egzosn/pay/union/bean/UnionTransactionType.java b/pay-java-union/src/main/java/com/egzosn/pay/union/bean/UnionTransactionType.java index fcc30fdf..b37e253c 100644 --- a/pay-java-union/src/main/java/com/egzosn/pay/union/bean/UnionTransactionType.java +++ b/pay-java-union/src/main/java/com/egzosn/pay/union/bean/UnionTransactionType.java @@ -15,35 +15,46 @@ public enum UnionTransactionType implements TransactionType{ /** + * ---尚未接入--- * 苹果支付 + * 官方文档:https://open.unionpay.com/tjweb/acproduct/list?apiservId=460 */ - APPLE("01","01","000802","08"), + APPLE_PAY("01","01","000802","08"), /** * 手机控件 */ APP("01","01","000000","08"), /** - * 手机网页支付(WAP支付) + * 手机控件支付产品(安卓/IOS/ApplePay 对应后台) + * 官方文档:https://open.unionpay.com/tjweb/acproduct/list?apiservId=450 */ WAP("01","01","000201","08"), /** - * 网关支付 + * 网关支付(B2C) + * 官方文档:https://open.unionpay.com/tjweb/acproduct/list?apiservId=448 + * 手机网页支付(WAP支付), + * 官方文档:https://open.unionpay.com/tjweb/acproduct/list?apiservId=453 */ WEB("01","01","000201","07"), /** - * 无跳转支付 + * ---尚未接入--- + * 无跳转支付() + * 官方文档:https://open.unionpay.com/tjweb/acproduct/list?apiservId=449 */ NO_JUMP("01","01","000301","07"), /** * 企业网银支付(B2B支付) + * 官方文档:https://open.unionpay.com/tjweb/acproduct/list?apiservId=452 */ B2B("01","01","000202","07"), /** * 申码(主扫场景) + * 官方文档:https://open.unionpay.com/tjweb/acproduct/list?apiservId=468 */ APPLY_QR_CODE("01","07","000000","08"), /** * 消费(被扫场景) + * 官方文档:同申码(主扫场景) */ CONSUME("01","06","000000","08"), //消费撤销 @@ -61,7 +72,7 @@ public enum UnionTransactionType implements TransactionType{ */ private String txnType; /** - * 交易子类 + * 交易子类型 */ private String txnSubType; @@ -71,7 +82,7 @@ public enum UnionTransactionType implements TransactionType{ private String bizType; /** - * 渠道类型 05:语音07:互联网08:移动 16:数字机顶盒 + * 渠道类型 05:语音 07:PC,平板 08:手机 16:数字机顶盒 */ private String channelType; diff --git a/pay-java-union/src/test/java/PayTest.java b/pay-java-union/src/test/java/PayTest.java index 76b5446e..f64b70b0 100644 --- a/pay-java-union/src/test/java/PayTest.java +++ b/pay-java-union/src/test/java/PayTest.java @@ -12,10 +12,13 @@ import java.util.Map; /** + * * Descrption:银联支付测试 * Author:Actinia * Date:2017/12/19 21:12 + * 移步@see com.egzosn.pay.demo.controller.UnionPayController */ +@Deprecated public class PayTest { public static void main(String[] args) {