diff --git a/pay-java-ali/src/main/java/com/egzosn/pay/ali/api/AliPayService.java b/pay-java-ali/src/main/java/com/egzosn/pay/ali/api/AliPayService.java index 952df782..db8e0773 100644 --- a/pay-java-ali/src/main/java/com/egzosn/pay/ali/api/AliPayService.java +++ b/pay-java-ali/src/main/java/com/egzosn/pay/ali/api/AliPayService.java @@ -6,10 +6,7 @@ import com.egzosn.pay.common.api.BasePayService; import com.egzosn.pay.common.api.Callback; import com.egzosn.pay.common.api.PayConfigStorage; -import com.egzosn.pay.common.bean.MethodType; -import com.egzosn.pay.common.bean.PayOrder; -import com.egzosn.pay.common.bean.PayOutMessage; -import com.egzosn.pay.common.bean.TransactionType; +import com.egzosn.pay.common.bean.*; import com.egzosn.pay.common.bean.result.PayException; import com.egzosn.pay.common.exception.PayErrorException; import com.egzosn.pay.common.http.HttpConfigStorage; @@ -36,11 +33,11 @@ public class AliPayService extends BasePayService { protected final Log log = LogFactory.getLog(AliPayService.class); //正式测试环境 - private String httpsReqUrl = "https://openapi.alipay.com/gateway.do"; + private final static String httpsReqUrl = "https://openapi.alipay.com/gateway.do"; //沙箱测试环境账号 - private String devReqUrl = "https://openapi.alipaydev.com/gateway.do"; + private final static String devReqUrl = "https://openapi.alipaydev.com/gateway.do"; //兼容上一版本即时收款 - private String httpsReqUrlBefore = "https://mapi.alipay.com/gateway.do"; + private final static String httpsReqUrlBefore = "https://mapi.alipay.com/gateway.do"; /** @@ -297,6 +294,17 @@ public PayOutMessage getPayOutMessage(String code, String message) { return PayOutMessage.TEXT().content(code.toLowerCase()).build(); } + /** + * 获取成功输出消息,用户返回给支付端 + * 主要用于拦截器中返回 + * @param payMessage 支付回调消息 + * @return 返回输出消息 + */ + @Override + public PayOutMessage successPayOutMessage(PayMessage payMessage) { + return PayOutMessage.TEXT().content("success").build(); + } + /** * * @param orderInfo 发起支付的订单信息 @@ -305,7 +313,6 @@ public PayOutMessage getPayOutMessage(String code, String message) { */ @Override public String buildRequest(Map orderInfo, MethodType method) { - StringBuffer formHtml = new StringBuffer(); formHtml.append("
orderInfo, MethodType method) { formHtml.append(""); } - - - - //submit按钮控件请不要含有name属性 -// formHtml.append(""); formHtml.append("
"); formHtml.append(""); diff --git a/pay-java-ali/src/main/java/com/egzosn/pay/ali/before/api/AliPayService.java b/pay-java-ali/src/main/java/com/egzosn/pay/ali/before/api/AliPayService.java index cab9021b..36f91d8a 100644 --- a/pay-java-ali/src/main/java/com/egzosn/pay/ali/before/api/AliPayService.java +++ b/pay-java-ali/src/main/java/com/egzosn/pay/ali/before/api/AliPayService.java @@ -85,7 +85,7 @@ public boolean verify(Map params) { */ @Override public boolean verifySource(String id) { - return "true".equals(requestTemplate.getForObject( getHttpsVerifyUrl() + "partner=" + payConfigStorage.getPid() + "¬ify_id=" + id, String.class)); + return "true".equals(requestTemplate.getForObject( getHttpsVerifyUrl() + "&partner=" + payConfigStorage.getPid() + "¬ify_id=" + id, String.class)); } /** @@ -228,6 +228,15 @@ public Map getParameter2Map(Map parameterMap, } //乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化 //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk"); + if (!valueStr.matches("\\w+")){ + try { + if(valueStr.equals(new String(valueStr.getBytes("iso8859-1"), "iso8859-1"))){ + valueStr=new String(valueStr.getBytes("iso8859-1"), payConfigStorage.getInputCharset()); + } + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } params.put(name, valueStr); } diff --git a/pay-java-common/src/main/java/com/egzosn/pay/common/api/PayMessageRouterRule.java b/pay-java-common/src/main/java/com/egzosn/pay/common/api/PayMessageRouterRule.java index d97a9638..7c45d8b0 100644 --- a/pay-java-common/src/main/java/com/egzosn/pay/common/api/PayMessageRouterRule.java +++ b/pay-java-common/src/main/java/com/egzosn/pay/common/api/PayMessageRouterRule.java @@ -288,7 +288,8 @@ protected PayOutMessage service(PayMessage payMessage, // 如果拦截器不通过 for (PayMessageInterceptor interceptor : this.interceptors) { if (!interceptor.intercept(payMessage, context, payService)) { - return null; + //这里直接返回成功,解决外层判断问题 + return payService.successPayOutMessage(payMessage); } } diff --git a/pay-java-common/src/main/java/com/egzosn/pay/common/api/PayService.java b/pay-java-common/src/main/java/com/egzosn/pay/common/api/PayService.java index b2371215..afd21d2a 100644 --- a/pay-java-common/src/main/java/com/egzosn/pay/common/api/PayService.java +++ b/pay-java-common/src/main/java/com/egzosn/pay/common/api/PayService.java @@ -1,9 +1,6 @@ package com.egzosn.pay.common.api; -import com.egzosn.pay.common.bean.MethodType; -import com.egzosn.pay.common.bean.PayOrder; -import com.egzosn.pay.common.bean.PayOutMessage; -import com.egzosn.pay.common.bean.TransactionType; +import com.egzosn.pay.common.bean.*; import com.egzosn.pay.common.exception.PayErrorException; import com.egzosn.pay.common.http.HttpConfigStorage; import com.egzosn.pay.common.http.HttpRequestTemplate; @@ -126,6 +123,14 @@ public interface PayService { */ PayOutMessage getPayOutMessage(String code, String message); + /** + * 获取成功输出消息,用户返回给支付端 + * 主要用于拦截器中返回 + * @param payMessage 支付回调消息 + * @return 返回输出消息 + */ + PayOutMessage successPayOutMessage(PayMessage payMessage); + /** * 获取输出消息,用户返回给支付端, 针对于web端 * diff --git a/pay-java-common/src/main/java/com/egzosn/pay/common/bean/PayOrder.java b/pay-java-common/src/main/java/com/egzosn/pay/common/bean/PayOrder.java index 6e1cb0a7..26b46de2 100644 --- a/pay-java-common/src/main/java/com/egzosn/pay/common/bean/PayOrder.java +++ b/pay-java-common/src/main/java/com/egzosn/pay/common/bean/PayOrder.java @@ -26,6 +26,8 @@ public class PayOrder { private String deviceInfo; //付款条码串 与设备号类似??? private String authCode; + // + private String openid; //交易类型 private TransactionType transactionType; //支付币种 @@ -145,8 +147,11 @@ public PayOrder(String subject, String body, BigDecimal price, String outTradeNo this.transactionType = transactionType; } + public String getOpenid() { + return openid; + } - - - + public void setOpenid(String openid) { + this.openid = openid; + } } diff --git a/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/PayController.java b/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/PayController.java index 135ca560..ae1c74db 100644 --- a/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/PayController.java +++ b/pay-java-demo/src/main/java/com/egzosn/pay/demo/controller/PayController.java @@ -84,6 +84,29 @@ public String toPay(Integer payId, String transactionType, String bankType, BigD } + /** + * 公众号支付 + * + * + * @param payId 账户id + * @param openid openid + * @return 跳到支付页面 + */ + @RequestMapping(value = "jsapi" ) + public Map toPay(Integer payId, String openid, BigDecimal price) { + //获取对应的支付账户操作工具(可根据账户id) + PayResponse payResponse = service.getPayResponse(payId); + + PayOrder order = new PayOrder("订单title", "摘要", null == price ? new BigDecimal(0.01) : price, UUID.randomUUID().toString().replace("-", ""), PayType.valueOf(payResponse.getStorage().getPayType()).getTransactionType("JSAPI")); + order.setOpenid(openid); + + Map orderInfo = payResponse.getService().orderInfo(order); + orderInfo.put("code", 0); + + return orderInfo; + } + + /** * 刷卡付,pos主动扫码付款(条码付) * diff --git a/pay-java-demo/src/main/java/com/egzosn/pay/demo/dao/ApyAccountRepository.java b/pay-java-demo/src/main/java/com/egzosn/pay/demo/dao/ApyAccountRepository.java index c470817a..b582cb8f 100644 --- a/pay-java-demo/src/main/java/com/egzosn/pay/demo/dao/ApyAccountRepository.java +++ b/pay-java-demo/src/main/java/com/egzosn/pay/demo/dao/ApyAccountRepository.java @@ -34,7 +34,7 @@ public class ApyAccountRepository { // TODO 2017/2/9 16:20 author: egan sign_type只有单一key时public_key与private_key相等,比如sign_type=MD5的情况 apyAccount1.setPublicKey("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDIgHnOn7LLILlKETd6BFRJ0GqgS2Y3mn1wMQmyh9zEyWlz5p1zrahRahbXAfCfSqshSNfqOmAQzSHRVjCqjsAw1jyqrXaPdKBmr90DIpIxmIyKXv4GGAkPyJ/6FTFY99uhpiq0qadD/uSzQsefWo0aTvP/65zi3eof7TcZ32oWpwIDAQAB"); apyAccount1.setPrivateKey("MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKroe/8h5vC4L6T+B2WdXiVwGsMvUKgb2XsKix6VY3m2wcf6tyzpNRDCNykbIwGtaeo7FshN+qZxdXHLiIam9goYncBit/8ojfLGy2gLxO/PXfzGxYGs0KsDZ+ryVPPmE34ZZ8jiJpR0ygzCFl8pN3QJPJRGTJn5+FTT9EF/9zyZAgMBAAECgYAktngcYC35u7cQXDk+jMVyiVhWYU2ULxdSpPspgLGzrZyG1saOcTIi/XVX8Spd6+B6nmLQeF/FbU3rOeuD8U2clzul2Z2YMbJ0FYay9oVZFfp5gTEFpFRTVfzqUaZQBIjJe/xHL9kQVqc5xHlE/LVA27/Kx3dbC35Y7B4EVBDYAQJBAOhsX8ZreWLKPhXiXHTyLmNKhOHJc+0tFH7Ktise/0rNspojU7o9prOatKpNylp9v6kux7migcMRdVUWWiVe+4ECQQC8PqsuEz7B0yqirQchRg1DbHjh64bw9Kj82EN1/NzOUd53tP9tg+SO97EzsibK1F7tOcuwqsa7n2aY48mQ+y0ZAkBndA2xcRcnvOOjtAz5VO8G7R12rse181HjGfG6AeMadbKg30aeaGCyIxN1loiSfNR5xsPJwibGIBg81mUrqzqBAkB+K6rkaPXJR9XtzvdWb/N3235yPkDlw7Z4MiOVM3RzvR/VMDV7m8lXoeDde2zQyeMOMYy6ztwA6WgE1bhGOnQRAkEAouUBv1sVdSBlsexX15qphOmAevzYrpufKgJIRLFWQxroXMS7FTesj+f+FmGrpPCxIde1dqJ8lqYLTyJmbzMPYw==\n"); - apyAccount1.setNotifyUrl("http://pay.egan.in/payBack2.json"); + apyAccount1.setNotifyUrl("http://pay.egan.in/payBack1.json"); // 无需同步回调可不填 // apyAccount1.setReturnUrl(""); apyAccount1.setInputCharset("UTF-8"); diff --git a/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/PayResponse.java b/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/PayResponse.java index 738e5b9f..49f45fd5 100644 --- a/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/PayResponse.java +++ b/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/PayResponse.java @@ -16,6 +16,7 @@ import com.egzosn.pay.common.api.PayMessageHandler; import com.egzosn.pay.common.api.PayService; import com.egzosn.pay.common.bean.MsgType; +import com.egzosn.pay.demo.service.interceptor.YoudianPayMessageInterceptor; import org.springframework.beans.factory.config.AutowireCapableBeanFactory; import javax.annotation.Resource; @@ -85,8 +86,7 @@ private void buildRouter(Integer payId) { .async(false) .msgType(MsgType.text.name()) //消息类型 .payType(PayType.aliPay.name()) //支付账户事件类型 -// .transactionType(AliTransactionType.UNAWARE.name())//交易类型,有关回调的可在这处理 - .interceptor(new AliPayMessageInterceptor(payId)) //拦截器 + .interceptor(new AliPayMessageInterceptor()) //拦截器 .handler(autowire(new AliPayMessageHandler(payId))) //处理器 .end() .rule() @@ -99,6 +99,7 @@ private void buildRouter(Integer payId) { .async(false) .msgType(MsgType.json.name()) .payType(PayType.youdianPay.name()) + .interceptor(new YoudianPayMessageInterceptor()) //拦截器 .handler(autowire(new YouDianPayMessageHandler(payId))) .end() .rule() diff --git a/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/handler/AliPayMessageHandler.java b/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/handler/AliPayMessageHandler.java index a45089a6..80ec804b 100644 --- a/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/handler/AliPayMessageHandler.java +++ b/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/handler/AliPayMessageHandler.java @@ -5,6 +5,7 @@ import com.egzosn.pay.common.bean.PayOutMessage; import com.egzosn.pay.common.exception.PayErrorException; +import java.math.BigDecimal; import java.util.Map; /** @@ -22,26 +23,25 @@ public AliPayMessageHandler(Integer payId) { @Override public PayOutMessage handle(PayMessage payMessage, Map context, PayService payService) throws PayErrorException { + + Map message = payMessage.getPayMessage(); //交易状态 - String trade_status = (String) payMessage.getPayMessage().get("trade_status"); - - if ("TRADE_SUCCESS".equals(trade_status)){ - //判断该笔订单是否在商户网站中已经做过处理 - //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 - //如果有做过处理,不执行商户的业务程序 - //注意: - //付款完成后,支付宝系统发送该交易状态通知 - - } else if("TRADE_FINISHED".equals(trade_status)) { - //判断该笔订单是否在商户网站中已经做过处理 - //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 - //如果有做过处理,不执行商户的业务程序 - //注意: - //退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知 - } else if ("WAIT_BUYER_PAY".equals(trade_status) || "TRADE_CLOSED".equals(trade_status)) { - - } - - return payService.getPayOutMessage("success", "成功"); + String trade_status = (String) message.get("trade_status"); + + //上下文对象中获取账单 +// AmtApply amtApply = (AmtApply)context.get("amtApply"); + //日志存储 +// amtPaylogService.createAmtPaylogByCallBack(amtApply, message.toString()); + //交易完成 + if ("TRADE_SUCCESS".equals(trade_status) || "TRADE_FINISHED".equals(trade_status)) { + + BigDecimal payAmount = new BigDecimal((String) message.get("total_fee")); + + return payService.getPayOutMessage("success", "成功"); + + }/* else if ("WAIT_BUYER_PAY".equals(trade_status) || "TRADE_CLOSED".equals(trade_status)) { + + }*/ + return payService.getPayOutMessage("fail", "失败"); } } diff --git a/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/handler/FuiouPayMessageHandler.java b/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/handler/FuiouPayMessageHandler.java index e454788c..a027c075 100644 --- a/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/handler/FuiouPayMessageHandler.java +++ b/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/handler/FuiouPayMessageHandler.java @@ -26,9 +26,9 @@ public PayOutMessage handle(PayMessage payMessage, Map context, if ("0000".equals(payMessage.getPayMessage().get("order_pay_code"))){ /////这里进行成功的处理 - return PayOutMessage.JSON().content("order_pay_error","成功").build(); + return PayOutMessage.JSON().content("success","成功").build(); } - return PayOutMessage.JSON().content("order_pay_error",payMessage.getPayMessage().get("order_pay_error")).build(); + return PayOutMessage.JSON().content("fail", "失败").build(); } } diff --git a/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/handler/YouDianPayMessageHandler.java b/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/handler/YouDianPayMessageHandler.java index da83ade1..3270f0d2 100644 --- a/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/handler/YouDianPayMessageHandler.java +++ b/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/handler/YouDianPayMessageHandler.java @@ -1,5 +1,6 @@ package com.egzosn.pay.demo.service.handler; +import com.alibaba.fastjson.JSON; import com.egzosn.pay.common.api.PayService; import com.egzosn.pay.common.bean.PayMessage; import com.egzosn.pay.common.bean.PayOutMessage; @@ -23,12 +24,17 @@ public YouDianPayMessageHandler(Integer payId) { @Override public PayOutMessage handle(PayMessage payMessage, Map context, PayService payService) throws PayErrorException { //交易状态 - if ("0000".equals(payMessage.getPayMessage().get("order_pay_code"))){ - /////这里进行成功的处理 + Map message = payMessage.getPayMessage(); + //上下文对象中获取账单 +// AmtApply amtApply = (AmtApply)context.get("amtApply"); + //日志存储 +// amtPaylogService.createAmtPaylogByCallBack(amtApply, message.toString()); + + if ("SUCCESS".equals(message.get("return_code"))){ + /////这里进行成功的处理,因没有返回金额 - return PayOutMessage.JSON().content("order_pay_error","成功").build(); } - return PayOutMessage.JSON().content("order_pay_error",payMessage.getPayMessage().get("order_pay_error")).build(); + return PayOutMessage.TEXT().content(JSON.toJSONString(message)).build(); } } diff --git a/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/interceptor/AliPayMessageInterceptor.java b/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/interceptor/AliPayMessageInterceptor.java index 7f27f51b..3308ad64 100644 --- a/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/interceptor/AliPayMessageInterceptor.java +++ b/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/interceptor/AliPayMessageInterceptor.java @@ -17,13 +17,6 @@ */ public class AliPayMessageInterceptor implements PayMessageInterceptor { - //支付账户id - private Integer payId; - public AliPayMessageInterceptor(Integer payId) { - - this.payId = payId; - } - /** * 拦截支付消息 * @@ -37,6 +30,26 @@ public AliPayMessageInterceptor(Integer payId) { public boolean intercept(PayMessage payMessage, Map context, PayService payService) throws PayErrorException { //这里进行拦截器处理,自行实现 + String outTradeNo = payMessage.getOutTradeNo(); + // 设置外部单号 +// amtApplyService.fillApplyoutId(outTradeNo, (String) payMessage.getPayMessage().get("trade_no")); + + + //获取账单 +// AmtApply amtApply = amtApplyService.getAmtApplyByApplyId(outTradeNo); +// if (null == amtApply){ +// Log4jUtil.info("app 阿里pay:" + outTradeNo); +// return false; +// } +// +// 重复回调不进行处理 +// if(amtApply.getApplyState().shortValue()== ApplyStateEnum.success.getCode()){ +// return false; +// } + //将账单存储至上下文对象中 +// context.put("amtApply", amtApply); + + return true; } } diff --git a/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/interceptor/YoudianPayMessageInterceptor.java b/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/interceptor/YoudianPayMessageInterceptor.java new file mode 100644 index 00000000..0387ecf2 --- /dev/null +++ b/pay-java-demo/src/main/java/com/egzosn/pay/demo/service/interceptor/YoudianPayMessageInterceptor.java @@ -0,0 +1,61 @@ + +package com.egzosn.pay.demo.service.interceptor; + +import com.egzosn.pay.common.api.PayMessageHandler; +import com.egzosn.pay.common.api.PayMessageInterceptor; +import com.egzosn.pay.common.api.PayService; +import com.egzosn.pay.common.bean.PayMessage; +import com.egzosn.pay.common.exception.PayErrorException; + +import java.util.Map; + +/** + * 回调信息拦截器 + * @author: egan + * email egzosn@gmail.com + * date 2017/1/18 19:28 + */ +public class YoudianPayMessageInterceptor implements PayMessageInterceptor { + +// @Autowired +// private AmtApplyService amtApplyService; + + /** + * 拦截支付消息 + * + * @param payMessage 支付回调消息 + * @param context 上下文,如果handler或interceptor之间有信息要传递,可以用这个 + * @param payService + * @return true代表OK,false代表不OK并直接中断对应的支付处理器 + * @see PayMessageHandler 支付处理器 + */ + @Override + public boolean intercept(PayMessage payMessage, Map context, PayService payService) throws PayErrorException { + + //这里进行拦截器处理,自行实现 + + Map message = payMessage.getPayMessage(); + + // 设置外部单号 + String outId = payMessage.getOutTradeNo(); + + //根据outId获取账单 +// AmtApply amtApply = amtApplyService.getAmtApplyByApplyOutid(outId); +// if (null == amtApply){ +// Log4jUtil.info("友店outId:" + outId); +// +// return false; +// } + + //重复回调不进行处理 +// if(amtApply.getApplyState().shortValue()== ApplyStateEnum.success.getCode()){ +// return false; +// } + //将账单存储至上下文对象中 +// context.put("amtApply", amtApply); + + +// amtPaylogService.createAmtPaylogByCheckFail(amtApply, payMessage.getPayMessage()); + return true; + } +} diff --git a/pay-java-demo/src/main/resources/apy_account.sql b/pay-java-demo/src/main/resources/apy_account.sql index dc183ad3..429b2bfd 100644 --- a/pay-java-demo/src/main/resources/apy_account.sql +++ b/pay-java-demo/src/main/resources/apy_account.sql @@ -1,25 +1,26 @@ /*Table structure for table `apy_account` */ -DROP TABLE IF EXISTS `apy_account`; - -CREATE TABLE `apy_account` ( - `pay_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '支付账号id', - `partner` varchar(32) DEFAULT NULL COMMENT '支付合作id,商户id,差不多是支付平台的账号或id', - `appid` varchar(32) DEFAULT NULL COMMENT '应用id', - `public_key` varchar(1204) DEFAULT NULL COMMENT '支付公钥,sign_type只有单一key时public_key与private_key相等,比如sign_type=MD5的情况', - `private_key` varchar(2048) DEFAULT NULL COMMENT '支付私钥', - `notify_url` varchar(1024) DEFAULT NULL COMMENT '异步回调地址', - `return_url` varchar(1024) DEFAULT NULL COMMENT '同步回调地址', - `seller` varchar(256) DEFAULT NULL COMMENT '收款账号, 针对支付宝', - `sign_type` varchar(16) DEFAULT NULL COMMENT '签名类型', - `input_charset` varchar(16) DEFAULT NULL COMMENT '枚举值,字符编码 utf-8,gbk等等', - `pay_type` char(16) DEFAULT NULL COMMENT '支付类型,aliPay:支付宝,wxPay:微信, youdianPay: 友店微信,此处开发者自定义对应com.egzosn.pay.demo.entity.PayType枚举值', - `msg_type` char(8) DEFAULT NULL COMMENT '消息类型,text,xml,json', - `create_by` char(32) DEFAULT NULL COMMENT '创建人', - `create_time` timestamp NULL DEFAULT NULL COMMENT '创建时间', +DROP TABLE IF EXISTS `pay_account`; + +CREATE TABLE `pay_account` ( + `pay_id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '支付账号id', + `partner` VARCHAR(32) DEFAULT NULL COMMENT '支付合作id,商户id,差不多是支付平台的账号或id', + `appid` VARCHAR(32) DEFAULT NULL COMMENT '应用id', + `public_key` VARCHAR(1204) DEFAULT NULL COMMENT '支付公钥,sign_type只有单一key时public_key与private_key相等,比如sign_type=MD5的情况', + `private_key` VARCHAR(2048) DEFAULT NULL COMMENT '支付私钥', + `notify_url` VARCHAR(1024) DEFAULT NULL COMMENT '异步回调地址', + `return_url` VARCHAR(1024) DEFAULT NULL COMMENT '同步回调地址', + `seller` VARCHAR(256) DEFAULT NULL COMMENT '收款账号, 针对支付宝', + `sign_type` VARCHAR(16) DEFAULT NULL COMMENT '签名类型', + `input_charset` VARCHAR(16) DEFAULT NULL COMMENT '枚举值,字符编码 utf-8,gbk等等', + `pay_type` CHAR(16) DEFAULT NULL COMMENT '支付类型,aliPay:支付宝,wxPay:微信, youdianPay: 友店微信,此处开发者自定义对应com.egzosn.pay.demo.entity.PayType枚举值', + `msg_type` CHAR(8) DEFAULT NULL COMMENT '消息类型,text,xml,json', + `is_test` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否为测试环境', + `create_by` CHAR(32) DEFAULT NULL COMMENT '创建人', + `create_time` TIMESTAMP NULL DEFAULT NULL COMMENT '创建时间', PRIMARY KEY (`pay_id`) -) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8; +) ENGINE=INNODB DEFAULT CHARSET=utf8; /*Data for the table `apy_account` */ diff --git a/pay-java-demo/src/main/webapp/index.html b/pay-java-demo/src/main/webapp/index.html index 910fadb7..d1132933 100644 --- a/pay-java-demo/src/main/webapp/index.html +++ b/pay-java-demo/src/main/webapp/index.html @@ -87,6 +87,17 @@
+
+公众号支付(请用微信访问) +
+ 账户id +
+ 金额 +
+ openid +
+ +

二维码 @@ -193,9 +204,57 @@ alert("服务器异常") } }) + }) ; + $("#js_submit").click(function () { + $.ajax({ + url : "jsapi", + type : "post", + async: true, + data : $("#jsapi").serialize(), + dataType : 'json', + success : function(data) { + if (data.code == 0){ + if (typeof WeixinJSBridge == "undefined"){ + if( document.addEventListener ){ + document.addEventListener('WeixinJSBridgeReady', onBridgeReady(data), false); + }else if (document.attachEvent){ + document.attachEvent('WeixinJSBridgeReady', onBridgeReady(data)); + document.attachEvent('onWeixinJSBridgeReady', onBridgeReady(data)); + } + }else{ + onBridgeReady(data); + } + return; + } + alert("保存失败"); + }, + error : function(edata) { + alert("服务器异常") + } + }) }) }); + function onBridgeReady(data){ + WeixinJSBridge.invoke( + 'getBrandWCPayRequest', { + "appId": data.appid, //公众号名称,由商户传入 + "timeStamp": data.timestamp, //时间戳,自1970年以来的秒数 + "nonceStr": data.noncestr, //随机串 + "package": data.package, + "signType": data.signType, //微信签名方式: + "paySign": data.sign //微信签名 + }, + function(res){ + // 使用以断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。 + if(res.err_msg == "get_brand_wcpay_request:ok" ) { + alert("支付成功") + + } + } + ); + } + diff --git a/pay-java-fuiou/src/main/java/com/egzosn/pay/fuiou/api/FuiouPayService.java b/pay-java-fuiou/src/main/java/com/egzosn/pay/fuiou/api/FuiouPayService.java index e977604f..93550dfa 100644 --- a/pay-java-fuiou/src/main/java/com/egzosn/pay/fuiou/api/FuiouPayService.java +++ b/pay-java-fuiou/src/main/java/com/egzosn/pay/fuiou/api/FuiouPayService.java @@ -1,12 +1,10 @@ package com.egzosn.pay.fuiou.api; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.egzosn.pay.common.api.BasePayService; import com.egzosn.pay.common.api.Callback; import com.egzosn.pay.common.api.PayConfigStorage; -import com.egzosn.pay.common.bean.MethodType; -import com.egzosn.pay.common.bean.PayOrder; -import com.egzosn.pay.common.bean.PayOutMessage; -import com.egzosn.pay.common.bean.TransactionType; +import com.egzosn.pay.common.bean.*; import com.egzosn.pay.common.exception.PayErrorException; import com.egzosn.pay.common.http.HttpConfigStorage; import com.egzosn.pay.common.util.sign.SignUtils; @@ -33,19 +31,28 @@ public class FuiouPayService extends BasePayService { //正式域名 public final static String URL_FuiouBaseDomain = "https://pay.fuiou.com/"; //测试域名 -// public final static String URL_FuiouBaseDomain = "http://www-1.fuiou.com:8888/wg1_run/"; + public final static String DEV_URL_FUIOUBASEDOMAIN = "http://www-1.fuiou.com:8888/wg1_run/"; + //B2C/B2B支付 - public final static String URL_FuiouSmpGate = URL_FuiouBaseDomain + "smpGate.do"; + public final static String URL_FuiouSmpGate = "smpGate.do"; //B2C/B2B支付(跨境支付) - public final static String URL_FuiouNewSmpGate = URL_FuiouBaseDomain + "newSmpGate.do"; + public final static String URL_FuiouNewSmpGate = "newSmpGate.do"; //订单退款 - public final static String URL_FuiouSmpRefundGate = URL_FuiouBaseDomain + "newSmpRefundGate.do"; + public final static String URL_FuiouSmpRefundGate = "newSmpRefundGate.do"; //3.2 支付结果查询 - public final static String URL_FuiouSmpQueryGate = URL_FuiouBaseDomain + "smpQueryGate.do"; + public final static String URL_FuiouSmpQueryGate = "smpQueryGate.do"; //3.3 支付结果查询(直接返回) - public final static String URL_FuiouSmpAQueryGate = URL_FuiouBaseDomain + "smpAQueryGate.do"; + public final static String URL_FuiouSmpAQueryGate = "smpAQueryGate.do"; //3.4订单退款 - public final static String URL_NewSmpRefundGate = URL_FuiouBaseDomain + "newSmpRefundGate.do"; + public final static String URL_NewSmpRefundGate = "newSmpRefundGate.do"; + + /** + * 获取对应的请求地址 + * @return 请求地址 + */ + public String getReqUrl(){ + return payConfigStorage.isTest() ? DEV_URL_FUIOUBASEDOMAIN : URL_FuiouBaseDomain; + } /** * 构造函数,初始化时候使用 @@ -128,7 +135,7 @@ public boolean verifySource (String order_id) { params.put("mchnt_cd",payConfigStorage.getPid()); params.put("order_id",order_id); params.put("md5",createSign(SignUtils.parameters2MD5Str(params,"|"),payConfigStorage.getInputCharset())); - JSONObject resultJson = getHttpRequestTemplate().postForObject(URL_FuiouSmpAQueryGate,params,JSONObject.class); + JSONObject resultJson = getHttpRequestTemplate().postForObject(getReqUrl() + URL_FuiouSmpAQueryGate,params,JSONObject.class); return resultJson.getString("order_pay_code").equals("0000"); } @@ -153,7 +160,7 @@ public Map orderInfo(PayOrder order) { private LinkedHashMap getOrderInfo(PayOrder order) { LinkedHashMap parameters = new LinkedHashMap(); parameters.put("mchnt_cd", payConfigStorage.getPartner());//商户代码 - parameters.put("order_id", order.getTradeNo());//商户订单号 + parameters.put("order_id", order.getOutTradeNo());//商户订单号 parameters.put("order_amt", order.getPrice());//交易金额 // parameters.put("cur_type", null == order.getCurType() ? FuiouCurType.CNY:order.getCurType());//交易币种 parameters.put("order_pay_type", order.getTransactionType());//支付类型 @@ -201,6 +208,16 @@ public Map getParameter2Map(Map parameterMap, public PayOutMessage getPayOutMessage(String code, String message) { return PayOutMessage.TEXT().content(code.toLowerCase()).build(); } + /** + * 获取成功输出消息,用户返回给支付端 + * 主要用于拦截器中返回 + * @param payMessage 支付回调消息 + * @return 返回输出消息 + */ + @Override + public PayOutMessage successPayOutMessage(PayMessage payMessage) { + return PayOutMessage.JSON().content("success","成功").build(); + } /** * 发送支付请求(form表单) @@ -211,7 +228,7 @@ public PayOutMessage getPayOutMessage(String code, String message) { @Override public String buildRequest(Map orderInfo, MethodType method) { - return getFormString(orderInfo, method,URL_FuiouSmpGate ); + return getFormString(orderInfo, method,getReqUrl() + URL_FuiouSmpGate ); } /** @@ -337,7 +354,7 @@ public Map refund (String tradeNo, String outTradeNo, BigDecimal params.put("refund_amt",refundAmount);//退款金额 params.put("rem","");//备注 params.put("md5",createSign(SignUtils.parameters2MD5Str(params,"|"),payConfigStorage.getInputCharset())); - JSONObject resultJson = getHttpRequestTemplate().postForObject(URL_FuiouSmpRefundGate,params,JSONObject.class); + JSONObject resultJson = getHttpRequestTemplate().postForObject(getReqUrl() + URL_FuiouSmpRefundGate,params,JSONObject.class); //5341标识退款成功 return resultJson; diff --git a/pay-java-wx-youdian/src/main/java/com/egzosn/pay/wx/youdian/api/WxYouDianPayService.java b/pay-java-wx-youdian/src/main/java/com/egzosn/pay/wx/youdian/api/WxYouDianPayService.java index b1b90183..41b08e98 100644 --- a/pay-java-wx-youdian/src/main/java/com/egzosn/pay/wx/youdian/api/WxYouDianPayService.java +++ b/pay-java-wx-youdian/src/main/java/com/egzosn/pay/wx/youdian/api/WxYouDianPayService.java @@ -1,13 +1,11 @@ package com.egzosn.pay.wx.youdian.api; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.egzosn.pay.common.api.BasePayService; import com.egzosn.pay.common.api.Callback; import com.egzosn.pay.common.api.PayConfigStorage; -import com.egzosn.pay.common.bean.MethodType; -import com.egzosn.pay.common.bean.PayOrder; -import com.egzosn.pay.common.bean.PayOutMessage; -import com.egzosn.pay.common.bean.TransactionType; +import com.egzosn.pay.common.bean.*; import com.egzosn.pay.common.bean.outbuilder.JsonBuilder; import com.egzosn.pay.common.bean.result.PayError; import com.egzosn.pay.common.exception.PayErrorException; @@ -178,10 +176,17 @@ public boolean verifySource(String id) { data.put("order_sn", id); String sign = createSign(SignUtils.parameterText(data, "") + apbNonce, payConfigStorage.getInputCharset()); String queryParam = SignUtils.parameterText(data) + "&apb_nonce=" + apbNonce + "&sign=" + sign; + try { + JSONObject jsonObject = execute(getHttpsVerifyUrl() + "?" + queryParam, MethodType.GET, null); - JSONObject jsonObject = execute(getHttpsVerifyUrl() + "?" + queryParam, MethodType.GET, null); + return 0 == jsonObject.getIntValue("errorcode"); + }catch (PayErrorException e){ + if (Integer.parseInt(e.getPayError().getErrorCode()) >= 400){ + throw e; + } + return false; + } - return 0 == jsonObject.getIntValue("errorcode"); } @@ -327,6 +332,18 @@ public PayOutMessage getPayOutMessage(String code, String message) { return builder.content("sign", SignUtils.valueOf(payConfigStorage.getSignType()).sign(builder.getJson(), "&key=" + payConfigStorage.getKeyPrivate(), payConfigStorage.getInputCharset())).build(); } + + /** + * 获取成功输出消息,用户返回给支付端 + * 主要用于拦截器中返回 + * @param payMessage 支付回调消息 + * @return 返回输出消息 + */ + @Override + public PayOutMessage successPayOutMessage(PayMessage payMessage) { + return PayOutMessage.TEXT().content(JSON.toJSONString(payMessage.getPayMessage())).build(); + } + /** * 针对web端的即时付款 * 暂未实现或无此功能 diff --git a/pay-java-wx/src/main/java/com/egzosn/pay/wx/api/WxPayService.java b/pay-java-wx/src/main/java/com/egzosn/pay/wx/api/WxPayService.java index ff9b8b2b..82f77b00 100644 --- a/pay-java-wx/src/main/java/com/egzosn/pay/wx/api/WxPayService.java +++ b/pay-java-wx/src/main/java/com/egzosn/pay/wx/api/WxPayService.java @@ -1,13 +1,11 @@ package com.egzosn.pay.wx.api; +import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.egzosn.pay.common.api.BasePayService; import com.egzosn.pay.common.api.Callback; import com.egzosn.pay.common.api.PayConfigStorage; -import com.egzosn.pay.common.bean.MethodType; -import com.egzosn.pay.common.bean.PayOrder; -import com.egzosn.pay.common.bean.PayOutMessage; -import com.egzosn.pay.common.bean.TransactionType; +import com.egzosn.pay.common.bean.*; import com.egzosn.pay.common.bean.result.PayException; import com.egzosn.pay.common.exception.PayErrorException; import com.egzosn.pay.common.http.HttpConfigStorage; @@ -156,7 +154,10 @@ public JSONObject unifiedOrder(PayOrder order) { parameters.put("attach", order.getBody()); if (WxTransactionType.NATIVE == order.getTransactionType()) { parameters.put("product_id", order.getOutTradeNo()); + }else if (WxTransactionType.JSAPI == order.getTransactionType()) { + parameters.put("openid", order.getOpenid()); } + String sign = createSign(SignUtils.parameterText(parameters), payConfigStorage.getInputCharset()); parameters.put("sign", sign); @@ -264,6 +265,18 @@ public PayOutMessage getPayOutMessage(String code, String message) { } + /** + * 获取成功输出消息,用户返回给支付端 + * 主要用于拦截器中返回 + * @param payMessage 支付回调消息 + * @return 返回输出消息 + */ + @Override + public PayOutMessage successPayOutMessage(PayMessage payMessage) { + return PayOutMessage.XML().code("Success").content("成功").build(); + } + + /** * 获取输出消息,用户返回给支付端, 针对于web端 *