diff --git a/pom.xml b/pom.xml
index 24b1c48..6b8a7b9 100755
--- a/pom.xml
+++ b/pom.xml
@@ -17,6 +17,7 @@
xxpay-shop
xxpay4spring-cloud
xxpay4dubbo
+ xxpay4spring-boot
diff --git a/xxpay4dubbo/xxpay4dubbo-api/src/main/java/org/xxpay/dubbo/api/service/IMchInfoService.java b/xxpay4dubbo/xxpay4dubbo-api/src/main/java/org/xxpay/dubbo/api/service/IMchInfoService.java
index 8d61b21..d166ca2 100644
--- a/xxpay4dubbo/xxpay4dubbo-api/src/main/java/org/xxpay/dubbo/api/service/IMchInfoService.java
+++ b/xxpay4dubbo/xxpay4dubbo-api/src/main/java/org/xxpay/dubbo/api/service/IMchInfoService.java
@@ -9,6 +9,6 @@ import java.util.Map;
*/
public interface IMchInfoService {
- public Map selectMchInfo(String jsonParam);
+ Map selectMchInfo(String jsonParam);
}
diff --git a/xxpay4dubbo/xxpay4dubbo-api/src/main/java/org/xxpay/dubbo/api/service/IPayChannelService.java b/xxpay4dubbo/xxpay4dubbo-api/src/main/java/org/xxpay/dubbo/api/service/IPayChannelService.java
index fffc3d0..8fdbc95 100644
--- a/xxpay4dubbo/xxpay4dubbo-api/src/main/java/org/xxpay/dubbo/api/service/IPayChannelService.java
+++ b/xxpay4dubbo/xxpay4dubbo-api/src/main/java/org/xxpay/dubbo/api/service/IPayChannelService.java
@@ -9,6 +9,6 @@ import java.util.Map;
*/
public interface IPayChannelService {
- public Map selectPayChannel(String jsonParam);
+ Map selectPayChannel(String jsonParam);
}
diff --git a/xxpay4dubbo/xxpay4dubbo-api/src/main/java/org/xxpay/dubbo/api/service/IPayOrderService.java b/xxpay4dubbo/xxpay4dubbo-api/src/main/java/org/xxpay/dubbo/api/service/IPayOrderService.java
index f5734e2..52a378d 100644
--- a/xxpay4dubbo/xxpay4dubbo-api/src/main/java/org/xxpay/dubbo/api/service/IPayOrderService.java
+++ b/xxpay4dubbo/xxpay4dubbo-api/src/main/java/org/xxpay/dubbo/api/service/IPayOrderService.java
@@ -9,20 +9,20 @@ import java.util.Map;
*/
public interface IPayOrderService {
- public Map createPayOrder(String jsonParam);
+ Map createPayOrder(String jsonParam);
- public Map selectPayOrder(String jsonParam);
+ Map selectPayOrder(String jsonParam);
- public Map selectPayOrderByMchIdAndPayOrderId(String jsonParam);
+ Map selectPayOrderByMchIdAndPayOrderId(String jsonParam);
- public Map selectPayOrderByMchIdAndMchOrderNo(String jsonParam);
+ Map selectPayOrderByMchIdAndMchOrderNo(String jsonParam);
- public Map updateStatus4Ing(String jsonParam);
+ Map updateStatus4Ing(String jsonParam);
- public Map updateStatus4Success(String jsonParam);
+ Map updateStatus4Success(String jsonParam);
- public Map updateStatus4Complete(String jsonParam);
+ Map updateStatus4Complete(String jsonParam);
- public Map updateNotify(String jsonParam);
+ Map updateNotify(String jsonParam);
}
diff --git a/xxpay4dubbo/xxpay4dubbo-service/pom.xml b/xxpay4dubbo/xxpay4dubbo-service/pom.xml
index c747764..b58c56c 100755
--- a/xxpay4dubbo/xxpay4dubbo-service/pom.xml
+++ b/xxpay4dubbo/xxpay4dubbo-service/pom.xml
@@ -35,6 +35,10 @@
org.springframework.boot
spring-boot-starter-activemq
+
+ org.apache.activemq
+ activemq-pool
+
org.mybatis.spring.boot
mybatis-spring-boot-starter
diff --git a/xxpay4dubbo/xxpay4dubbo-service/src/main/java/org/xxpay/dubbo/service/channel/alipay/AlipayConfig.java b/xxpay4dubbo/xxpay4dubbo-service/src/main/java/org/xxpay/dubbo/service/channel/alipay/AlipayConfig.java
index 0dbf617..840f86a 100644
--- a/xxpay4dubbo/xxpay4dubbo-service/src/main/java/org/xxpay/dubbo/service/channel/alipay/AlipayConfig.java
+++ b/xxpay4dubbo/xxpay4dubbo-service/src/main/java/org/xxpay/dubbo/service/channel/alipay/AlipayConfig.java
@@ -2,10 +2,8 @@ package org.xxpay.dubbo.service.channel.alipay;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
-import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
-import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
/**
diff --git a/xxpay4dubbo/xxpay4dubbo-service/src/main/java/org/xxpay/dubbo/service/impl/NotifyPayServiceImpl.java b/xxpay4dubbo/xxpay4dubbo-service/src/main/java/org/xxpay/dubbo/service/impl/NotifyPayServiceImpl.java
index 7ccc905..5470a1a 100644
--- a/xxpay4dubbo/xxpay4dubbo-service/src/main/java/org/xxpay/dubbo/service/impl/NotifyPayServiceImpl.java
+++ b/xxpay4dubbo/xxpay4dubbo-service/src/main/java/org/xxpay/dubbo/service/impl/NotifyPayServiceImpl.java
@@ -1,7 +1,6 @@
package org.xxpay.dubbo.service.impl;
import com.alibaba.dubbo.config.annotation.Service;
-import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
@@ -15,7 +14,10 @@ import org.springframework.util.StringUtils;
import org.xxpay.common.constant.PayConstant;
import org.xxpay.common.domain.BaseParam;
import org.xxpay.common.enumm.RetEnum;
-import org.xxpay.common.util.*;
+import org.xxpay.common.util.JsonUtil;
+import org.xxpay.common.util.MyLog;
+import org.xxpay.common.util.ObjectValidUtil;
+import org.xxpay.common.util.RpcUtil;
import org.xxpay.dal.dao.model.PayChannel;
import org.xxpay.dal.dao.model.PayOrder;
import org.xxpay.dubbo.api.service.INotifyPayService;
diff --git a/xxpay4spring-boot/pom.xml b/xxpay4spring-boot/pom.xml
new file mode 100755
index 0000000..48b5ed4
--- /dev/null
+++ b/xxpay4spring-boot/pom.xml
@@ -0,0 +1,95 @@
+
+
+ 4.0.0
+
+ org.xxpay
+ xxpay4spring-boot
+ 1.0.0
+ jar
+ xxpay4spring-boot
+ xxpay4spring-boot
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 1.5.6.RELEASE
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ 1.5.6.RELEASE
+ 1.0.0
+
+
+
+
+ org.xxpay
+ xxpay-dal
+ 1.0.0
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+ 1.3.0
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-starter-freemarker
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+
+
+ org.springframework.boot
+ spring-boot-starter-activemq
+
+
+ org.apache.activemq
+ activemq-pool
+
+
+
+ com.github.binarywang
+ weixin-java-pay
+ 2.8.0
+
+
+
+ com.alipay
+ sdk
+ 1.5
+ system
+ ${basedir}/src/main/webapp/WEB-INF/lib/alipay-sdk-java20170818173712.jar
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ ${project.name}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/XxPayBootAppliaction.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/XxPayBootAppliaction.java
new file mode 100755
index 0000000..8cc697b
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/XxPayBootAppliaction.java
@@ -0,0 +1,16 @@
+package org.xxpay.boot;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.ComponentScan;
+
+/**
+ *
+ */
+@SpringBootApplication
+@ComponentScan(basePackages={"org.xxpay"})
+public class XxPayBootAppliaction {
+ public static void main(String[] args) {
+ SpringApplication.run(XxPayBootAppliaction.class, args);
+ }
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/ctrl/Notify4AliPayController.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/ctrl/Notify4AliPayController.java
new file mode 100644
index 0000000..9ac6478
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/ctrl/Notify4AliPayController.java
@@ -0,0 +1,75 @@
+package org.xxpay.boot.ctrl;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+import org.xxpay.boot.web.NotifyPayService;
+import org.xxpay.common.constant.PayConstant;
+import org.xxpay.common.util.MyLog;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * @Description: 接收处理支付宝通知
+ * @author dingzhiwei jmdhappy@126.com
+ * @date 2017-07-05
+ * @version V1.0
+ * @Copyright: www.xxpay.org
+ */
+@RestController
+public class Notify4AliPayController {
+
+ private static final MyLog _log = MyLog.getLog(Notify4AliPayController.class);
+
+ @Autowired
+ private NotifyPayService notifyPayService;
+
+ /**
+ * 支付宝移动支付后台通知响应
+ * @param request
+ * @return
+ * @throws ServletException
+ * @throws IOException
+ */
+ @RequestMapping(value = "/notify/pay/aliPayNotifyRes.htm")
+ @ResponseBody
+ public String aliPayNotifyRes(HttpServletRequest request) throws ServletException, IOException {
+ _log.info("====== 开始接收支付宝支付回调通知 ======");
+ String notifyRes = doAliPayRes(request);
+ _log.info("响应给支付宝:{}", notifyRes);
+ _log.info("====== 完成接收支付宝支付回调通知 ======");
+ return notifyRes;
+ }
+
+ public String doAliPayRes(HttpServletRequest request) throws ServletException, IOException {
+ String logPrefix = "【支付宝支付回调通知】";
+ //获取支付宝POST过来反馈信息
+ Map params = new HashMap();
+ Map requestParams = request.getParameterMap();
+ for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
+ String name = (String) iter.next();
+ String[] values = (String[]) requestParams.get(name);
+ String valueStr = "";
+ for (int i = 0; i < values.length; i++) {
+ valueStr = (i == values.length - 1) ? valueStr + values[i]
+ : valueStr + values[i] + ",";
+ }
+ //乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
+ //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
+ params.put(name, valueStr);
+ }
+ _log.info("{}通知请求数据:reqStr={}", logPrefix, params);
+ if(params.isEmpty()) {
+ _log.error("{}请求参数为空", logPrefix);
+ return PayConstant.RETURN_ALIPAY_VALUE_FAIL;
+ }
+ return notifyPayService.doAliPayNotify(params);
+ }
+
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/ctrl/Notify4WxPayController.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/ctrl/Notify4WxPayController.java
new file mode 100644
index 0000000..36707ff
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/ctrl/Notify4WxPayController.java
@@ -0,0 +1,54 @@
+package org.xxpay.boot.ctrl;
+
+import org.apache.commons.io.IOUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+import org.xxpay.boot.web.NotifyPayService;
+import org.xxpay.common.util.MyLog;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+
+/**
+ * @Description: 接收处理微信通知
+ * @author dingzhiwei jmdhappy@126.com
+ * @date 2017-07-05
+ * @version V1.0
+ * @Copyright: www.xxpay.org
+ */
+@RestController
+public class Notify4WxPayController {
+
+ private static final MyLog _log = MyLog.getLog(Notify4WxPayController.class);
+
+ @Autowired
+ private NotifyPayService notifyPayService;
+
+ /**
+ * 微信支付(统一下单接口)后台通知响应
+ * @param request
+ * @return
+ * @throws ServletException
+ * @throws IOException
+ */
+ @RequestMapping("/notify/pay/wxPayNotifyRes.htm")
+ @ResponseBody
+ public String wxPayNotifyRes(HttpServletRequest request) throws ServletException, IOException {
+ _log.info("====== 开始接收微信支付回调通知 ======");
+ String notifyRes = doWxPayRes(request);
+ _log.info("响应给微信:{}", notifyRes);
+ _log.info("====== 完成接收微信支付回调通知 ======");
+ return notifyRes;
+ }
+
+ public String doWxPayRes(HttpServletRequest request) throws ServletException, IOException {
+ String logPrefix = "【微信支付回调通知】";
+ String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
+ _log.info("{}通知请求数据:reqStr={}", logPrefix, xmlResult);
+ return notifyPayService.doWxPayNotify(xmlResult);
+ }
+
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/ctrl/PayOrderController.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/ctrl/PayOrderController.java
new file mode 100644
index 0000000..877c0d1
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/ctrl/PayOrderController.java
@@ -0,0 +1,268 @@
+package org.xxpay.boot.ctrl;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.xxpay.boot.web.MchInfoService;
+import org.xxpay.boot.web.PayChannelService;
+import org.xxpay.boot.web.PayOrderService;
+import org.xxpay.common.constant.PayConstant;
+import org.xxpay.common.util.MyLog;
+import org.xxpay.common.util.MySeq;
+import org.xxpay.common.util.XXPayUtil;
+
+/**
+ * @Description: 支付订单,包括:统一下单,订单查询,补单等接口
+ * @author dingzhiwei jmdhappy@126.com
+ * @date 2017-07-05
+ * @version V1.0
+ * @Copyright: www.xxpay.org
+ */
+@RestController
+public class PayOrderController {
+
+ private final MyLog _log = MyLog.getLog(PayOrderController.class);
+
+ @Autowired
+ private PayOrderService payOrderService;
+
+ @Autowired
+ private PayChannelService payChannelService;
+
+ @Autowired
+ private MchInfoService mchInfoService;
+
+ /**
+ * 统一下单接口:
+ * 1)先验证接口参数以及签名信息
+ * 2)验证通过创建支付订单
+ * 3)根据商户选择渠道,调用支付服务进行下单
+ * 4)返回下单数据
+ * @param params
+ * @return
+ */
+ @RequestMapping(value = "/api/pay/create_order")
+ public String payOrder(@RequestParam String params) {
+ _log.info("###### 开始接收商户统一下单请求 ######");
+ String logPrefix = "【商户统一下单】";
+ try {
+ JSONObject po = JSONObject.parseObject(params);
+ JSONObject payContext = new JSONObject();
+ JSONObject payOrder = null;
+ // 验证参数有效性
+ Object object = validateParams(po, payContext);
+ if (object instanceof String) {
+ _log.info("{}参数校验不通过:{}", logPrefix, object);
+ return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, object.toString(), null, null));
+ }
+ if (object instanceof JSONObject) payOrder = (JSONObject) object;
+ if(payOrder == null) return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "支付中心下单失败", null, null));
+ int result = payOrderService.createPayOrder(payOrder);
+ _log.info("{}创建支付订单,结果:{}", logPrefix, result);
+ if(result != 1) {
+ return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "创建支付订单失败", null, null));
+ }
+ String channelId = payOrder.getString("channelId");
+ switch (channelId) {
+ case PayConstant.PAY_CHANNEL_WX_APP :
+ return payOrderService.doWxPayReq(PayConstant.WxConstant.TRADE_TYPE_APP, payOrder, payContext.getString("resKey"));
+ case PayConstant.PAY_CHANNEL_WX_JSAPI :
+ return payOrderService.doWxPayReq(PayConstant.WxConstant.TRADE_TYPE_JSPAI, payOrder, payContext.getString("resKey"));
+ case PayConstant.PAY_CHANNEL_WX_NATIVE :
+ return payOrderService.doWxPayReq(PayConstant.WxConstant.TRADE_TYPE_NATIVE, payOrder, payContext.getString("resKey"));
+ case PayConstant.PAY_CHANNEL_WX_MWEB :
+ return payOrderService.doWxPayReq(PayConstant.WxConstant.TRADE_TYPE_MWEB, payOrder, payContext.getString("resKey"));
+ case PayConstant.PAY_CHANNEL_ALIPAY_MOBILE :
+ return payOrderService.doAliPayReq(channelId, payOrder, payContext.getString("resKey"));
+ case PayConstant.PAY_CHANNEL_ALIPAY_PC :
+ return payOrderService.doAliPayReq(channelId, payOrder, payContext.getString("resKey"));
+ case PayConstant.PAY_CHANNEL_ALIPAY_WAP :
+ return payOrderService.doAliPayReq(channelId, payOrder, payContext.getString("resKey"));
+ case PayConstant.PAY_CHANNEL_ALIPAY_QR :
+ return payOrderService.doAliPayReq(channelId, payOrder, payContext.getString("resKey"));
+ default:
+ return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "不支持的支付渠道类型[channelId="+channelId+"]", null, null));
+ }
+ }catch (Exception e) {
+ _log.error(e, "");
+ return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "支付中心系统异常", null, null));
+ }
+ }
+
+ /**
+ * 验证创建订单请求参数,参数通过返回JSONObject对象,否则返回错误文本信息
+ * @param params
+ * @return
+ */
+ private Object validateParams(JSONObject params, JSONObject payContext) {
+ // 验证请求参数,参数有问题返回错误提示
+ String errorMessage;
+ // 支付参数
+ String mchId = params.getString("mchId"); // 商户ID
+ String mchOrderNo = params.getString("mchOrderNo"); // 商户订单号
+ String channelId = params.getString("channelId"); // 渠道ID
+ String amount = params.getString("amount"); // 支付金额(单位分)
+ String currency = params.getString("currency"); // 币种
+ String clientIp = params.getString("clientIp"); // 客户端IP
+ String device = params.getString("device"); // 设备
+ String extra = params.getString("extra"); // 特定渠道发起时额外参数
+ String param1 = params.getString("param1"); // 扩展参数1
+ String param2 = params.getString("param2"); // 扩展参数2
+ String notifyUrl = params.getString("notifyUrl"); // 支付结果回调URL
+ String sign = params.getString("sign"); // 签名
+ String subject = params.getString("subject"); // 商品主题
+ String body = params.getString("body"); // 商品描述信息
+ // 验证请求参数有效性(必选项)
+ if(StringUtils.isBlank(mchId)) {
+ errorMessage = "request params[mchId] error.";
+ return errorMessage;
+ }
+ if(StringUtils.isBlank(mchOrderNo)) {
+ errorMessage = "request params[mchOrderNo] error.";
+ return errorMessage;
+ }
+ if(StringUtils.isBlank(channelId)) {
+ errorMessage = "request params[channelId] error.";
+ return errorMessage;
+ }
+ if(!NumberUtils.isNumber(amount)) {
+ errorMessage = "request params[amount] error.";
+ return errorMessage;
+ }
+ if(StringUtils.isBlank(currency)) {
+ errorMessage = "request params[currency] error.";
+ return errorMessage;
+ }
+ if(StringUtils.isBlank(notifyUrl)) {
+ errorMessage = "request params[notifyUrl] error.";
+ return errorMessage;
+ }
+ if(StringUtils.isBlank(subject)) {
+ errorMessage = "request params[subject] error.";
+ return errorMessage;
+ }
+ if(StringUtils.isBlank(body)) {
+ errorMessage = "request params[body] error.";
+ return errorMessage;
+ }
+ // 根据不同渠道,判断extra参数
+ if(PayConstant.PAY_CHANNEL_WX_JSAPI.equalsIgnoreCase(channelId)) {
+ if(StringUtils.isEmpty(extra)) {
+ errorMessage = "request params[extra] error.";
+ return errorMessage;
+ }
+ JSONObject extraObject = JSON.parseObject(extra);
+ String openId = extraObject.getString("openId");
+ if(StringUtils.isBlank(openId)) {
+ errorMessage = "request params[extra.openId] error.";
+ return errorMessage;
+ }
+ }else if(PayConstant.PAY_CHANNEL_WX_NATIVE.equalsIgnoreCase(channelId)) {
+ if(StringUtils.isEmpty(extra)) {
+ errorMessage = "request params[extra] error.";
+ return errorMessage;
+ }
+ JSONObject extraObject = JSON.parseObject(extra);
+ String productId = extraObject.getString("productId");
+ if(StringUtils.isBlank(productId)) {
+ errorMessage = "request params[extra.productId] error.";
+ return errorMessage;
+ }
+ }else if(PayConstant.PAY_CHANNEL_WX_MWEB.equalsIgnoreCase(channelId)) {
+ if(StringUtils.isEmpty(extra)) {
+ errorMessage = "request params[extra] error.";
+ return errorMessage;
+ }
+ JSONObject extraObject = JSON.parseObject(extra);
+ String productId = extraObject.getString("sceneInfo");
+ if(StringUtils.isBlank(productId)) {
+ errorMessage = "request params[extra.sceneInfo] error.";
+ return errorMessage;
+ }
+ if(StringUtils.isBlank(clientIp)) {
+ errorMessage = "request params[clientIp] error.";
+ return errorMessage;
+ }
+ }
+
+ // 签名信息
+ if (StringUtils.isEmpty(sign)) {
+ errorMessage = "request params[sign] error.";
+ return errorMessage;
+ }
+
+ // 查询商户信息
+ JSONObject mchInfo = mchInfoService.getByMchId(mchId);
+ if(mchInfo == null) {
+ errorMessage = "Can't found mchInfo[mchId="+mchId+"] record in db.";
+ return errorMessage;
+ }
+ if(mchInfo.getByte("state") != 1) {
+ errorMessage = "mchInfo not available [mchId="+mchId+"] record in db.";
+ return errorMessage;
+ }
+
+ String reqKey = mchInfo.getString("reqKey");
+ if (StringUtils.isBlank(reqKey)) {
+ errorMessage = "reqKey is null[mchId="+mchId+"] record in db.";
+ return errorMessage;
+ }
+ payContext.put("resKey", mchInfo.getString("resKey"));
+
+ // 查询商户对应的支付渠道
+ JSONObject payChannel = payChannelService.getByMchIdAndChannelId(mchId, channelId);
+ if(payChannel == null) {
+ errorMessage = "Can't found payChannel[channelId="+channelId+",mchId="+mchId+"] record in db.";
+ return errorMessage;
+ }
+ if(payChannel.getByte("state") != 1) {
+ errorMessage = "channel not available [channelId="+channelId+",mchId="+mchId+"]";
+ return errorMessage;
+ }
+
+ // 验证签名数据
+ boolean verifyFlag = XXPayUtil.verifyPaySign(params, reqKey);
+ if(!verifyFlag) {
+ errorMessage = "Verify XX pay sign failed.";
+ return errorMessage;
+ }
+ // 验证参数通过,返回JSONObject对象
+ JSONObject payOrder = new JSONObject();
+ payOrder.put("payOrderId", MySeq.getPay());
+ payOrder.put("mchId", mchId);
+ payOrder.put("mchOrderNo", mchOrderNo);
+ payOrder.put("channelId", channelId);
+ payOrder.put("amount", Long.parseLong(amount));
+ payOrder.put("currency", currency);
+ payOrder.put("clientIp", clientIp);
+ payOrder.put("device", device);
+ payOrder.put("subject", subject);
+ payOrder.put("body", body);
+ payOrder.put("extra", extra);
+ payOrder.put("channelMchId", payChannel.getString("channelMchId"));
+ payOrder.put("param1", param1);
+ payOrder.put("param2", param2);
+ payOrder.put("notifyUrl", notifyUrl);
+ return payOrder;
+ }
+
+ String getJsonParam(String[] names, Object[] values) {
+ JSONObject jsonParam = new JSONObject();
+ for (int i = 0; i < names.length; i++) {
+ jsonParam.put(names[i], values[i]);
+ }
+ return jsonParam.toJSONString();
+ }
+
+ String getJsonParam(String name, Object value) {
+ JSONObject jsonParam = new JSONObject();
+ jsonParam.put(name, value);
+ return jsonParam.toJSONString();
+ }
+
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/ctrl/QueryPayOrderController.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/ctrl/QueryPayOrderController.java
new file mode 100644
index 0000000..3ac2424
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/ctrl/QueryPayOrderController.java
@@ -0,0 +1,135 @@
+package org.xxpay.boot.ctrl;
+
+import com.alibaba.fastjson.JSONObject;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.xxpay.boot.web.MchInfoService;
+import org.xxpay.boot.web.PayOrderService;
+import org.xxpay.common.constant.PayConstant;
+import org.xxpay.common.util.MyLog;
+import org.xxpay.common.util.XXPayUtil;
+
+import java.util.Map;
+
+/**
+ * @Description: 支付订单查询
+ * @author dingzhiwei jmdhappy@126.com
+ * @date 2017-08-31
+ * @version V1.0
+ * @Copyright: www.xxpay.org
+ */
+@RestController
+public class QueryPayOrderController {
+
+ private final MyLog _log = MyLog.getLog(QueryPayOrderController.class);
+
+ @Autowired
+ private PayOrderService payOrderService;
+
+ @Autowired
+ private MchInfoService mchInfoService;
+
+ /**
+ * 查询支付订单接口:
+ * 1)先验证接口参数以及签名信息
+ * 2)根据参数查询订单
+ * 3)返回订单数据
+ * @param params
+ * @return
+ */
+ @RequestMapping(value = "/api/pay/query_order")
+ public String queryPayOrder(@RequestParam String params) {
+ _log.info("###### 开始接收商户查询支付订单请求 ######");
+ String logPrefix = "【商户支付订单查询】";
+ try {
+ JSONObject po = JSONObject.parseObject(params);
+ JSONObject payContext = new JSONObject();
+ // 验证参数有效性
+ String errorMessage = validateParams(po, payContext);
+ if (!"success".equalsIgnoreCase(errorMessage)) {
+ _log.warn(errorMessage);
+ return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, errorMessage, null, null));
+ }
+ _log.debug("请求参数及签名校验通过");
+ String mchId = po.getString("mchId"); // 商户ID
+ String mchOrderNo = po.getString("mchOrderNo"); // 商户订单号
+ String payOrderId = po.getString("payOrderId"); // 支付订单号
+ String executeNotify = po.getString("executeNotify"); // 是否执行回调
+ JSONObject payOrder = payOrderService.queryPayOrder(mchId, payOrderId, mchOrderNo, executeNotify);
+ _log.info("{}查询支付订单,结果:{}", logPrefix, payOrder);
+ if (payOrder == null) {
+ return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "支付订单不存在", null, null));
+ }
+ Map map = XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null);
+ map.put("result", payOrder);
+ _log.info("###### 商户查询订单处理完成 ######");
+ return XXPayUtil.makeRetData(map, payContext.getString("resKey"));
+ }catch (Exception e) {
+ _log.error(e, "");
+ return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "支付中心系统异常", null, null));
+ }
+ }
+
+ /**
+ * 验证创建订单请求参数,参数通过返回JSONObject对象,否则返回错误文本信息
+ * @param params
+ * @return
+ */
+ private String validateParams(JSONObject params, JSONObject payContext) {
+ // 验证请求参数,参数有问题返回错误提示
+ String errorMessage;
+ // 支付参数
+ String mchId = params.getString("mchId"); // 商户ID
+ String mchOrderNo = params.getString("mchOrderNo"); // 商户订单号
+ String payOrderId = params.getString("payOrderId"); // 支付订单号
+
+ String sign = params.getString("sign"); // 签名
+
+ // 验证请求参数有效性(必选项)
+ if(StringUtils.isBlank(mchId)) {
+ errorMessage = "request params[mchId] error.";
+ return errorMessage;
+ }
+ if(StringUtils.isBlank(mchOrderNo) && StringUtils.isBlank(payOrderId)) {
+ errorMessage = "request params[mchOrderNo or payOrderId] error.";
+ return errorMessage;
+ }
+
+ // 签名信息
+ if (StringUtils.isEmpty(sign)) {
+ errorMessage = "request params[sign] error.";
+ return errorMessage;
+ }
+
+ // 查询商户信息
+ JSONObject mchInfo = mchInfoService.getByMchId(mchId);
+ if(mchInfo == null) {
+ errorMessage = "Can't found mchInfo[mchId="+mchId+"] record in db.";
+ return errorMessage;
+ }
+ if(mchInfo.getByte("state") != 1) {
+ errorMessage = "mchInfo not available [mchId="+mchId+"] record in db.";
+ return errorMessage;
+ }
+
+ String reqKey = mchInfo.getString("reqKey");
+ if (StringUtils.isBlank(reqKey)) {
+ errorMessage = "reqKey is null[mchId="+mchId+"] record in db.";
+ return errorMessage;
+ }
+ payContext.put("resKey", mchInfo.getString("resKey"));
+
+ // 验证签名数据
+ boolean verifyFlag = XXPayUtil.verifyPaySign(params, reqKey);
+ if(!verifyFlag) {
+ errorMessage = "Verify XX pay sign failed.";
+ return errorMessage;
+ }
+
+ return "success";
+ }
+
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/BaseService.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/BaseService.java
new file mode 100644
index 0000000..89b205e
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/BaseService.java
@@ -0,0 +1,119 @@
+package org.xxpay.boot.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import org.xxpay.common.constant.PayConstant;
+import org.xxpay.dal.dao.mapper.MchInfoMapper;
+import org.xxpay.dal.dao.mapper.PayChannelMapper;
+import org.xxpay.dal.dao.mapper.PayOrderMapper;
+import org.xxpay.dal.dao.model.*;
+
+import java.util.List;
+
+/**
+ * @author: dingzhiwei
+ * @date: 17/9/9
+ * @description:
+ */
+@Service
+public class BaseService {
+
+ @Autowired
+ private PayOrderMapper payOrderMapper;
+
+ @Autowired
+ private MchInfoMapper mchInfoMapper;
+
+ @Autowired
+ private PayChannelMapper payChannelMapper;
+
+
+ public MchInfo baseSelectMchInfo(String mchId) {
+ return mchInfoMapper.selectByPrimaryKey(mchId);
+ }
+
+ public PayChannel baseSelectPayChannel(String mchId, String channelId) {
+ PayChannelExample example = new PayChannelExample();
+ PayChannelExample.Criteria criteria = example.createCriteria();
+ criteria.andChannelIdEqualTo(channelId);
+ criteria.andMchIdEqualTo(mchId);
+ List payChannelList = payChannelMapper.selectByExample(example);
+ if(CollectionUtils.isEmpty(payChannelList)) return null;
+ return payChannelList.get(0);
+ }
+
+ public int baseCreatePayOrder(PayOrder payOrder) {
+ return payOrderMapper.insertSelective(payOrder);
+ }
+
+ public PayOrder baseSelectPayOrder(String payOrderId) {
+ return payOrderMapper.selectByPrimaryKey(payOrderId);
+ }
+
+ public PayOrder baseSelectPayOrderByMchIdAndPayOrderId(String mchId, String payOrderId) {
+ PayOrderExample example = new PayOrderExample();
+ PayOrderExample.Criteria criteria = example.createCriteria();
+ criteria.andMchIdEqualTo(mchId);
+ criteria.andPayOrderIdEqualTo(payOrderId);
+ List payOrderList = payOrderMapper.selectByExample(example);
+ return CollectionUtils.isEmpty(payOrderList) ? null : payOrderList.get(0);
+ }
+
+ public PayOrder baseSelectPayOrderByMchIdAndMchOrderNo(String mchId, String mchOrderNo) {
+ PayOrderExample example = new PayOrderExample();
+ PayOrderExample.Criteria criteria = example.createCriteria();
+ criteria.andMchIdEqualTo(mchId);
+ criteria.andMchOrderNoEqualTo(mchOrderNo);
+ List payOrderList = payOrderMapper.selectByExample(example);
+ return CollectionUtils.isEmpty(payOrderList) ? null : payOrderList.get(0);
+ }
+
+ public int baseUpdateStatus4Ing(String payOrderId, String channelOrderNo) {
+ PayOrder payOrder = new PayOrder();
+ payOrder.setStatus(PayConstant.PAY_STATUS_PAYING);
+ if(channelOrderNo != null) payOrder.setChannelOrderNo(channelOrderNo);
+ payOrder.setPaySuccTime(System.currentTimeMillis());
+ PayOrderExample example = new PayOrderExample();
+ PayOrderExample.Criteria criteria = example.createCriteria();
+ criteria.andPayOrderIdEqualTo(payOrderId);
+ criteria.andStatusEqualTo(PayConstant.PAY_STATUS_INIT);
+ return payOrderMapper.updateByExampleSelective(payOrder, example);
+ }
+
+ public int baseUpdateStatus4Success(String payOrderId) {
+ PayOrder payOrder = new PayOrder();
+ payOrder.setPayOrderId(payOrderId);
+ payOrder.setStatus(PayConstant.PAY_STATUS_SUCCESS);
+ payOrder.setPaySuccTime(System.currentTimeMillis());
+ PayOrderExample example = new PayOrderExample();
+ PayOrderExample.Criteria criteria = example.createCriteria();
+ criteria.andPayOrderIdEqualTo(payOrderId);
+ criteria.andStatusEqualTo(PayConstant.PAY_STATUS_PAYING);
+ return payOrderMapper.updateByExampleSelective(payOrder, example);
+ }
+
+ public int baseUpdateStatus4Complete(String payOrderId) {
+ PayOrder payOrder = new PayOrder();
+ payOrder.setPayOrderId(payOrderId);
+ payOrder.setStatus(PayConstant.PAY_STATUS_COMPLETE);
+ PayOrderExample example = new PayOrderExample();
+ PayOrderExample.Criteria criteria = example.createCriteria();
+ criteria.andPayOrderIdEqualTo(payOrderId);
+ criteria.andStatusEqualTo(PayConstant.PAY_STATUS_SUCCESS);
+ return payOrderMapper.updateByExampleSelective(payOrder, example);
+ }
+
+ public int baseUpdateNotify(String payOrderId, byte count) {
+ PayOrder newPayOrder = new PayOrder();
+ newPayOrder.setNotifyCount(count);
+ newPayOrder.setLastNotifyTime(System.currentTimeMillis());
+ newPayOrder.setPayOrderId(payOrderId);
+ return payOrderMapper.updateByPrimaryKeySelective(newPayOrder);
+ }
+
+ public int baseUpdateNotify(PayOrder payOrder) {
+ return payOrderMapper.updateByPrimaryKeySelective(payOrder);
+ }
+
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IMchInfoService.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IMchInfoService.java
new file mode 100644
index 0000000..80ab116
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IMchInfoService.java
@@ -0,0 +1,14 @@
+package org.xxpay.boot.service;
+
+import java.util.Map;
+
+/**
+ * @author: dingzhiwei
+ * @date: 17/9/8
+ * @description:
+ */
+public interface IMchInfoService {
+
+ Map selectMchInfo(String jsonParam);
+
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/INotifyPayService.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/INotifyPayService.java
new file mode 100644
index 0000000..01fbd1d
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/INotifyPayService.java
@@ -0,0 +1,17 @@
+package org.xxpay.boot.service;
+
+import java.util.Map;
+
+/**
+ * @author: dingzhiwei
+ * @date: 17/9/10
+ * @description:
+ */
+public interface INotifyPayService {
+
+ Map doAliPayNotify(String jsonParam);
+
+ Map doWxPayNotify(String jsonParam);
+
+ Map sendBizPayNotify(String jsonParam);
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IPayChannel4AliService.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IPayChannel4AliService.java
new file mode 100644
index 0000000..535bb0b
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IPayChannel4AliService.java
@@ -0,0 +1,20 @@
+package org.xxpay.boot.service;
+
+import java.util.Map;
+
+/**
+ * @author: dingzhiwei
+ * @date: 17/9/10
+ * @description:
+ */
+public interface IPayChannel4AliService {
+
+ Map doAliPayWapReq(String jsonParam);
+
+ Map doAliPayPcReq(String jsonParam);
+
+ Map doAliPayMobileReq(String jsonParam);
+
+ Map doAliPayQrReq(String jsonParam);
+
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IPayChannel4WxService.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IPayChannel4WxService.java
new file mode 100644
index 0000000..c007803
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IPayChannel4WxService.java
@@ -0,0 +1,14 @@
+package org.xxpay.boot.service;
+
+import java.util.Map;
+
+/**
+ * @author: dingzhiwei
+ * @date: 17/9/9
+ * @description:
+ */
+public interface IPayChannel4WxService {
+
+ Map doWxPayReq(String jsonParam);
+
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IPayChannelService.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IPayChannelService.java
new file mode 100644
index 0000000..3776c0e
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IPayChannelService.java
@@ -0,0 +1,14 @@
+package org.xxpay.boot.service;
+
+import java.util.Map;
+
+/**
+ * @author: dingzhiwei
+ * @date: 17/9/8
+ * @description:
+ */
+public interface IPayChannelService {
+
+ Map selectPayChannel(String jsonParam);
+
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IPayOrderService.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IPayOrderService.java
new file mode 100644
index 0000000..c2a9738
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IPayOrderService.java
@@ -0,0 +1,28 @@
+package org.xxpay.boot.service;
+
+import java.util.Map;
+
+/**
+ * @author: dingzhiwei
+ * @date: 17/9/8
+ * @description:
+ */
+public interface IPayOrderService {
+
+ Map createPayOrder(String jsonParam);
+
+ Map selectPayOrder(String jsonParam);
+
+ Map selectPayOrderByMchIdAndPayOrderId(String jsonParam);
+
+ Map selectPayOrderByMchIdAndMchOrderNo(String jsonParam);
+
+ Map updateStatus4Ing(String jsonParam);
+
+ Map updateStatus4Success(String jsonParam);
+
+ Map updateStatus4Complete(String jsonParam);
+
+ Map updateNotify(String jsonParam);
+
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/Notify4BasePay.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/Notify4BasePay.java
new file mode 100644
index 0000000..f215e2d
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/Notify4BasePay.java
@@ -0,0 +1,120 @@
+package org.xxpay.boot.service;
+
+import com.alibaba.fastjson.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.xxpay.common.constant.PayConstant;
+import org.xxpay.common.util.MyLog;
+import org.xxpay.common.util.PayDigestUtil;
+import org.xxpay.common.util.XXPayUtil;
+import org.xxpay.dal.dao.model.MchInfo;
+import org.xxpay.dal.dao.model.PayOrder;
+import org.xxpay.boot.service.mq.Mq4PayNotify;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Description: 支付通知处理基类
+ * @author dingzhiwei jmdhappy@126.com
+ * @date 2017-07-05
+ * @version V1.0
+ * @Copyright: www.xxpay.org
+ */
+@Component
+public class Notify4BasePay extends BaseService {
+
+ private static final MyLog _log = MyLog.getLog(Notify4BasePay.class);
+
+ @Autowired
+ private Mq4PayNotify mq4PayNotify;
+
+ /**
+ * 创建响应URL
+ * @param payOrder
+ * @param backType 1:前台页面;2:后台接口
+ * @return
+ */
+ public String createNotifyUrl(PayOrder payOrder, String backType) {
+ String mchId = payOrder.getMchId();
+ MchInfo mchInfo = super.baseSelectMchInfo(mchId);
+ String resKey = mchInfo.getResKey();
+ Map paramMap = new HashMap<>();
+ paramMap.put("payOrderId", payOrder.getPayOrderId() == null ? "" : payOrder.getPayOrderId()); // 支付订单号
+ paramMap.put("mchId", payOrder.getMchId() == null ? "" : payOrder.getMchId()); // 商户ID
+ paramMap.put("mchOrderNo", payOrder.getMchOrderNo() == null ? "" : payOrder.getMchOrderNo()); // 商户订单号
+ paramMap.put("channelId", payOrder.getChannelId() == null ? "" : payOrder.getChannelId()); // 渠道ID
+ paramMap.put("amount", payOrder.getAmount() == null ? "" : payOrder.getAmount()); // 支付金额
+ paramMap.put("currency", payOrder.getCurrency() == null ? "" : payOrder.getCurrency()); // 货币类型
+ paramMap.put("status", payOrder.getStatus() == null ? "" : payOrder.getStatus()); // 支付状态
+ paramMap.put("clientIp", payOrder.getClientIp()==null ? "" : payOrder.getClientIp()); // 客户端IP
+ paramMap.put("device", payOrder.getDevice()==null ? "" : payOrder.getDevice()); // 设备
+ paramMap.put("subject", payOrder.getSubject()==null ? "" : payOrder.getSubject()); // 商品标题
+ paramMap.put("channelOrderNo", payOrder.getChannelOrderNo()==null ? "" : payOrder.getChannelOrderNo()); // 渠道订单号
+ paramMap.put("param1", payOrder.getParam1()==null ? "" : payOrder.getParam1()); // 扩展参数1
+ paramMap.put("param2", payOrder.getParam2()==null ? "" : payOrder.getParam2()); // 扩展参数2
+ paramMap.put("paySuccTime", payOrder.getPaySuccTime()==null ? "" : payOrder.getPaySuccTime()); // 支付成功时间
+ paramMap.put("backType", backType==null ? "" : backType);
+ // 先对原文签名
+ String reqSign = PayDigestUtil.getSign(paramMap, resKey);
+ paramMap.put("sign", reqSign); // 签名
+ // 签名后再对有中文参数编码
+ try {
+ paramMap.put("device", URLEncoder.encode(payOrder.getDevice()==null ? "" : payOrder.getDevice(), PayConstant.RESP_UTF8));
+ paramMap.put("subject", URLEncoder.encode(payOrder.getSubject()==null ? "" : payOrder.getSubject(), PayConstant.RESP_UTF8));
+ paramMap.put("param1", URLEncoder.encode(payOrder.getParam1()==null ? "" : payOrder.getParam1(), PayConstant.RESP_UTF8));
+ paramMap.put("param2", URLEncoder.encode(payOrder.getParam2()==null ? "" : payOrder.getParam2(), PayConstant.RESP_UTF8));
+ }catch (UnsupportedEncodingException e) {
+ _log.error("URL Encode exception.", e);
+ return null;
+ }
+ String param = XXPayUtil.genUrlParams(paramMap);
+ StringBuffer sb = new StringBuffer();
+ sb.append(payOrder.getNotifyUrl()).append("?").append(param);
+ return sb.toString();
+ }
+
+ /**
+ * 处理支付结果前台页面跳转
+ */
+ public boolean doPage(PayOrder payOrder) {
+ String redirectUrl = createNotifyUrl(payOrder, "1");
+ _log.info("redirect to respUrl:"+redirectUrl);
+ // 前台跳转业务系统
+ /*try {
+ response.sendRedirect(redirectUrl);
+ } catch (IOException e) {
+ _log.error("XxPay sendRedirect exception. respUrl="+redirectUrl, e);
+ return false;
+ }*/
+ return true;
+ }
+
+ /**
+ * 处理支付结果后台服务器通知
+ */
+ public void doNotify(PayOrder payOrder) {
+ _log.info(">>>>>> PAY开始回调通知业务系统 <<<<<<");
+ // 发起后台通知业务系统
+ JSONObject object = createNotifyInfo(payOrder);
+ try {
+ mq4PayNotify.send(object.toJSONString());
+ } catch (Exception e) {
+ _log.error("payOrderId={},sendMessage error.", payOrder != null ? payOrder.getPayOrderId() : "", e);
+ }
+ _log.info(">>>>>> PAY回调通知业务系统完成 <<<<<<");
+ }
+
+ public JSONObject createNotifyInfo(PayOrder payOrder) {
+ JSONObject object = new JSONObject();
+ object.put("method", "GET");
+ object.put("url", createNotifyUrl(payOrder, "2"));
+ object.put("orderId", payOrder.getPayOrderId());
+ object.put("count", payOrder.getNotifyCount());
+ object.put("createTime", System.currentTimeMillis());
+ return object;
+ }
+
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/channel/alipay/AlipayConfig.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/channel/alipay/AlipayConfig.java
new file mode 100644
index 0000000..e63d27b
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/channel/alipay/AlipayConfig.java
@@ -0,0 +1,115 @@
+package org.xxpay.boot.service.channel.alipay;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
+
+/**
+ * @author: dingzhiwei
+ * @date: 17/8/21
+ * @description:
+ */
+@Component
+@ConfigurationProperties(prefix="config.ali")
+public class AlipayConfig {
+
+ // 商户appid
+ private String app_id;
+ // 私钥 pkcs8格式的
+ private String rsa_private_key;
+ // 服务器异步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
+
+ private String notify_url;
+ // 页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址
+
+ private String return_url;
+ // 请求网关地址
+ private String url = "https://openapi.alipay.com/gateway.do";
+
+ // 编码
+ public static String CHARSET = "UTF-8";
+ // 返回格式
+ public static String FORMAT = "json";
+ // 支付宝公钥
+ public String alipay_public_key;
+ // RSA2
+ public static String SIGNTYPE = "RSA2";
+
+ // 是否沙箱环境,1:沙箱,0:正式环境
+ private Short isSandbox = 0;
+
+ /**
+ * 初始化支付宝配置
+ * @param configParam
+ * @return
+ */
+ public AlipayConfig init(String configParam) {
+ Assert.notNull(configParam, "init alipay config error");
+ JSONObject paramObj = JSON.parseObject(configParam);
+ this.setApp_id(paramObj.getString("appid"));
+ this.setRsa_private_key(paramObj.getString("private_key"));
+ this.setAlipay_public_key(paramObj.getString("alipay_public_key"));
+ this.setIsSandbox(paramObj.getShortValue("isSandbox"));
+ if(this.getIsSandbox() == 1) this.setUrl("https://openapi.alipaydev.com/gateway.do");
+ return this;
+ }
+
+ public String getApp_id() {
+ return app_id;
+ }
+
+ public void setApp_id(String app_id) {
+ this.app_id = app_id;
+ }
+
+ public String getRsa_private_key() {
+ return rsa_private_key;
+ }
+
+ public void setRsa_private_key(String rsa_private_key) {
+ this.rsa_private_key = rsa_private_key;
+ }
+
+ public String getNotify_url() {
+ return notify_url;
+ }
+
+ public void setNotify_url(String notify_url) {
+ this.notify_url = notify_url;
+ }
+
+ public String getReturn_url() {
+ return return_url;
+ }
+
+ public void setReturn_url(String return_url) {
+ this.return_url = return_url;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public Short getIsSandbox() {
+ return isSandbox;
+ }
+
+ public void setIsSandbox(Short isSandbox) {
+ this.isSandbox = isSandbox;
+ }
+
+ public String getAlipay_public_key() {
+ return alipay_public_key;
+ }
+
+ public void setAlipay_public_key(String alipay_public_key) {
+ this.alipay_public_key = alipay_public_key;
+ }
+}
+
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/channel/wechat/WxPayProperties.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/channel/wechat/WxPayProperties.java
new file mode 100755
index 0000000..56d3b42
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/channel/wechat/WxPayProperties.java
@@ -0,0 +1,35 @@
+package org.xxpay.boot.service.channel.wechat;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * User: rizenguo
+ * Date: 2014/10/29
+ * Time: 14:40
+ * 这里放置各种配置数据
+ */
+@Component
+@ConfigurationProperties(prefix="config.wx")
+public class WxPayProperties {
+
+ private String certRootPath;
+
+ private String notifyUrl;
+
+ public String getCertRootPath() {
+ return certRootPath;
+ }
+
+ public void setCertRootPath(String certRootPath) {
+ this.certRootPath = certRootPath;
+ }
+
+ public String getNotifyUrl() {
+ return notifyUrl;
+ }
+
+ public void setNotifyUrl(String notifyUrl) {
+ this.notifyUrl = notifyUrl;
+ }
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/channel/wechat/WxPayUtil.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/channel/wechat/WxPayUtil.java
new file mode 100644
index 0000000..ae598e3
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/channel/wechat/WxPayUtil.java
@@ -0,0 +1,50 @@
+package org.xxpay.boot.service.channel.wechat;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.github.binarywang.wxpay.config.WxPayConfig;
+
+import java.io.File;
+
+/**
+ * @author: dingzhiwei
+ * @date: 17/8/25
+ * @description:
+ */
+public class WxPayUtil {
+
+ /**
+ * 获取微信支付配置
+ * @param configParam
+ * @param tradeType
+ * @param certRootPath
+ * @param notifyUrl
+ * @return
+ */
+ public static WxPayConfig getWxPayConfig(String configParam, String tradeType, String certRootPath, String notifyUrl) {
+ WxPayConfig wxPayConfig = new WxPayConfig();
+ JSONObject paramObj = JSON.parseObject(configParam);
+ wxPayConfig.setMchId(paramObj.getString("mchId"));
+ wxPayConfig.setAppId(paramObj.getString("appId"));
+ wxPayConfig.setKeyPath(certRootPath + File.separator + paramObj.getString("certLocalPath"));
+ wxPayConfig.setMchKey(paramObj.getString("key"));
+ wxPayConfig.setNotifyUrl(notifyUrl);
+ wxPayConfig.setTradeType(tradeType);
+ return wxPayConfig;
+ }
+
+ /**
+ * 获取微信支付配置
+ * @param configParam
+ * @return
+ */
+ public static WxPayConfig getWxPayConfig(String configParam) {
+ WxPayConfig wxPayConfig = new WxPayConfig();
+ JSONObject paramObj = JSON.parseObject(configParam);
+ wxPayConfig.setMchId(paramObj.getString("mchId"));
+ wxPayConfig.setAppId(paramObj.getString("appId"));
+ wxPayConfig.setMchKey(paramObj.getString("key"));
+ return wxPayConfig;
+ }
+
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/MchInfoServiceImpl.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/MchInfoServiceImpl.java
new file mode 100644
index 0000000..4d79efa
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/MchInfoServiceImpl.java
@@ -0,0 +1,44 @@
+package org.xxpay.boot.service.impl;
+
+import org.springframework.stereotype.Service;
+import org.xxpay.boot.service.BaseService;
+import org.xxpay.boot.service.IMchInfoService;
+import org.xxpay.common.domain.BaseParam;
+import org.xxpay.common.enumm.RetEnum;
+import org.xxpay.common.util.JsonUtil;
+import org.xxpay.common.util.MyLog;
+import org.xxpay.common.util.ObjectValidUtil;
+import org.xxpay.common.util.RpcUtil;
+import org.xxpay.dal.dao.model.MchInfo;
+
+import java.util.Map;
+
+/**
+ * @author: dingzhiwei
+ * @date: 17/9/8
+ * @description:
+ */
+@Service
+public class MchInfoServiceImpl extends BaseService implements IMchInfoService {
+
+ private static final MyLog _log = MyLog.getLog(MchInfoServiceImpl.class);
+
+ @Override
+ public Map selectMchInfo(String jsonParam) {
+ BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
+ Map bizParamMap = baseParam.getBizParamMap();
+ if (ObjectValidUtil.isInvalid(bizParamMap)) {
+ _log.warn("查询商户信息失败, {}. jsonParam={}", RetEnum.RET_PARAM_NOT_FOUND.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_NOT_FOUND);
+ }
+ String mchId = baseParam.isNullValue("mchId") ? null : bizParamMap.get("mchId").toString();
+ if (ObjectValidUtil.isInvalid(mchId)) {
+ _log.warn("查询商户信息失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
+ }
+ MchInfo mchInfo = super.baseSelectMchInfo(mchId);
+ if(mchInfo == null) return RpcUtil.createFailResult(baseParam, RetEnum.RET_BIZ_DATA_NOT_EXISTS);
+ String jsonResult = JsonUtil.object2Json(mchInfo);
+ return RpcUtil.createBizResult(baseParam, jsonResult);
+ }
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/NotifyPayServiceImpl.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/NotifyPayServiceImpl.java
new file mode 100644
index 0000000..3003f73
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/NotifyPayServiceImpl.java
@@ -0,0 +1,294 @@
+package org.xxpay.boot.service.impl;
+
+import com.alipay.api.AlipayApiException;
+import com.alipay.api.internal.util.AlipaySignature;
+import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
+import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
+import com.github.binarywang.wxpay.config.WxPayConfig;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+import org.xxpay.boot.service.INotifyPayService;
+import org.xxpay.boot.service.Notify4BasePay;
+import org.xxpay.boot.service.channel.alipay.AlipayConfig;
+import org.xxpay.boot.service.channel.wechat.WxPayUtil;
+import org.xxpay.common.constant.PayConstant;
+import org.xxpay.common.domain.BaseParam;
+import org.xxpay.common.enumm.RetEnum;
+import org.xxpay.common.util.JsonUtil;
+import org.xxpay.common.util.MyLog;
+import org.xxpay.common.util.ObjectValidUtil;
+import org.xxpay.common.util.RpcUtil;
+import org.xxpay.dal.dao.model.PayChannel;
+import org.xxpay.dal.dao.model.PayOrder;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author: dingzhiwei
+ * @date: 17/9/10
+ * @description:
+ */
+@Service
+public class NotifyPayServiceImpl extends Notify4BasePay implements INotifyPayService {
+
+ private static final MyLog _log = MyLog.getLog(NotifyPayServiceImpl.class);
+
+ @Autowired
+ private AlipayConfig alipayConfig;
+
+ @Override
+ public Map doAliPayNotify(String jsonParam) {
+ String logPrefix = "【处理支付宝支付回调】";
+ _log.info("====== 开始处理支付宝支付回调通知 ======");
+ BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
+ Map bizParamMap = baseParam.getBizParamMap();
+ if (ObjectValidUtil.isInvalid(bizParamMap)) {
+ _log.warn("处理支付宝支付回调失败, {}. jsonParam={}", RetEnum.RET_PARAM_NOT_FOUND.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_NOT_FOUND);
+ }
+ Map params = baseParam.isNullValue("params") ? null : (Map) bizParamMap.get("params");
+ if (ObjectValidUtil.isInvalid(params)) {
+ _log.warn("处理支付宝支付回调失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
+ }
+ Map payContext = new HashMap();
+ PayOrder payOrder;
+ payContext.put("parameters", params);
+ if(!verifyAliPayParams(payContext)) {
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_BIZ_PAY_NOTIFY_VERIFY_FAIL);
+ }
+ _log.info("{}验证支付通知数据及签名通过", logPrefix);
+ String trade_status = params.get("trade_status").toString(); // 交易状态
+ // 支付状态成功或者完成
+ if (trade_status.equals(PayConstant.AlipayConstant.TRADE_STATUS_SUCCESS) ||
+ trade_status.equals(PayConstant.AlipayConstant.TRADE_STATUS_FINISHED)) {
+ int updatePayOrderRows;
+ payOrder = (PayOrder)payContext.get("payOrder");
+ byte payStatus = payOrder.getStatus(); // 0:订单生成,1:支付中,-1:支付失败,2:支付成功,3:业务处理完成,-2:订单过期
+ if (payStatus != PayConstant.PAY_STATUS_SUCCESS && payStatus != PayConstant.PAY_STATUS_COMPLETE) {
+ updatePayOrderRows = super.baseUpdateStatus4Success(payOrder.getPayOrderId());
+ if (updatePayOrderRows != 1) {
+ _log.error("{}更新支付状态失败,将payOrderId={},更新payStatus={}失败", logPrefix, payOrder.getPayOrderId(), PayConstant.PAY_STATUS_SUCCESS);
+ _log.info("{}响应给支付宝结果:{}", logPrefix, PayConstant.RETURN_ALIPAY_VALUE_FAIL);
+ return RpcUtil.createBizResult(baseParam, PayConstant.RETURN_ALIPAY_VALUE_FAIL);
+ }
+ _log.info("{}更新支付状态成功,将payOrderId={},更新payStatus={}成功", logPrefix, payOrder.getPayOrderId(), PayConstant.PAY_STATUS_SUCCESS);
+ payOrder.setStatus(PayConstant.PAY_STATUS_SUCCESS);
+ }
+ }else{
+ // 其他状态
+ _log.info("{}支付状态trade_status={},不做业务处理", logPrefix, trade_status);
+ _log.info("{}响应给支付宝结果:{}", logPrefix, PayConstant.RETURN_ALIPAY_VALUE_SUCCESS);
+ return RpcUtil.createBizResult(baseParam, PayConstant.RETURN_ALIPAY_VALUE_SUCCESS);
+ }
+ doNotify(payOrder);
+ _log.info("====== 完成处理支付宝支付回调通知 ======");
+ return RpcUtil.createBizResult(baseParam, PayConstant.RETURN_ALIPAY_VALUE_SUCCESS);
+ }
+
+ @Override
+ public Map doWxPayNotify(String jsonParam) {
+ String logPrefix = "【处理微信支付回调】";
+ _log.info("====== 开始处理微信支付回调通知 ======");
+ BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
+ try {
+ Map bizParamMap = baseParam.getBizParamMap();
+ if (ObjectValidUtil.isInvalid(bizParamMap)) {
+ _log.warn("处理微信支付回调失败, {}. jsonParam={}", RetEnum.RET_PARAM_NOT_FOUND.getMessage(), jsonParam);
+ return RpcUtil.createBizResult(baseParam, WxPayNotifyResponse.fail(RetEnum.RET_PARAM_NOT_FOUND.getMessage()));
+ //return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_NOT_FOUND);
+ }
+ String xmlResult = baseParam.isNullValue("xmlResult") ? null : bizParamMap.get("xmlResult").toString();
+ if (ObjectValidUtil.isInvalid(xmlResult)) {
+ _log.warn("处理微信支付回调失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
+ return RpcUtil.createBizResult(baseParam, WxPayNotifyResponse.fail(RetEnum.RET_PARAM_INVALID.getMessage()));
+ //return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
+ }
+ WxPayService wxPayService = new WxPayServiceImpl();
+ WxPayOrderNotifyResult result = WxPayOrderNotifyResult.fromXML(xmlResult);
+ Map payContext = new HashMap();
+ payContext.put("parameters", result);
+ // 验证业务数据是否正确,验证通过后返回PayOrder和WxPayConfig对象
+ if(!verifyWxPayParams(payContext)) {
+ return RpcUtil.createBizResult(baseParam, WxPayNotifyResponse.fail((String) payContext.get("retMsg")));
+ }
+ PayOrder payOrder = (PayOrder) payContext.get("payOrder");
+ WxPayConfig wxPayConfig = (WxPayConfig) payContext.get("wxPayConfig");
+ wxPayService.setConfig(wxPayConfig);
+ // 这里做了签名校验(这里又做了一次xml转换对象,可以考虑优化)
+ wxPayService.parseOrderNotifyResult(xmlResult);
+ // 处理订单
+ byte payStatus = payOrder.getStatus(); // 0:订单生成,1:支付中,-1:支付失败,2:支付成功,3:业务处理完成,-2:订单过期
+ if (payStatus != PayConstant.PAY_STATUS_SUCCESS && payStatus != PayConstant.PAY_STATUS_COMPLETE) {
+ int updatePayOrderRows = super.baseUpdateStatus4Success(payOrder.getPayOrderId());
+ if (updatePayOrderRows != 1) {
+ _log.error("{}更新支付状态失败,将payOrderId={},更新payStatus={}失败", logPrefix, payOrder.getPayOrderId(), PayConstant.PAY_STATUS_SUCCESS);
+ return RpcUtil.createBizResult(baseParam, WxPayNotifyResponse.fail("处理订单失败"));
+ }
+ _log.error("{}更新支付状态成功,将payOrderId={},更新payStatus={}成功", logPrefix, payOrder.getPayOrderId(), PayConstant.PAY_STATUS_SUCCESS);
+ payOrder.setStatus(PayConstant.PAY_STATUS_SUCCESS);
+ }
+ // 业务系统后端通知
+ doNotify(payOrder);
+ _log.info("====== 完成处理微信支付回调通知 ======");
+ return RpcUtil.createBizResult(baseParam, WxPayNotifyResponse.success("OK"));
+ } catch (WxPayException e) {
+ //出现业务错误
+ _log.error(e, "微信回调结果异常,异常原因");
+ _log.info("{}请求数据result_code=FAIL", logPrefix);
+ _log.info("err_code:", e.getErrCode());
+ _log.info("err_code_des:", e.getErrCodeDes());
+ return RpcUtil.createBizResult(baseParam, WxPayNotifyResponse.fail(e.getMessage()));
+ } catch (Exception e) {
+ _log.error(e, "微信回调结果异常,异常原因");
+ return RpcUtil.createBizResult(baseParam, WxPayNotifyResponse.fail(e.getMessage()));
+ }
+ }
+
+ @Override
+ public Map sendBizPayNotify(String jsonParam) {
+ BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
+ Map bizParamMap = baseParam.getBizParamMap();
+ if (ObjectValidUtil.isInvalid(bizParamMap)) {
+ _log.warn("发送业务支付通知失败, {}. jsonParam={}", RetEnum.RET_PARAM_NOT_FOUND.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_NOT_FOUND);
+ }
+ String payOrderId = baseParam.isNullValue("payOrderId") ? null : bizParamMap.get("payOrderId").toString();
+ if(ObjectValidUtil.isInvalid(payOrderId)) {
+ _log.warn("发送业务支付通知失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
+ }
+ PayOrder payOrder = super.baseSelectPayOrder(payOrderId);
+ if(payOrder == null) return RpcUtil.createFailResult(baseParam, RetEnum.RET_BIZ_DATA_NOT_EXISTS);
+ try {
+ // 发送业务支付通知
+ super.doNotify(payOrder);
+ }catch (Exception e) {
+ return RpcUtil.createBizResult(baseParam, 0);
+ }
+ return RpcUtil.createBizResult(baseParam, 1);
+ }
+
+
+ /**
+ * 验证支付宝支付通知参数
+ * @return
+ */
+ public boolean verifyAliPayParams(Map payContext) {
+ Map params = (Map)payContext.get("parameters");
+ String out_trade_no = params.get("out_trade_no"); // 商户订单号
+ String total_amount = params.get("total_amount"); // 支付金额
+ if (StringUtils.isEmpty(out_trade_no)) {
+ _log.error("AliPay Notify parameter out_trade_no is empty. out_trade_no={}", out_trade_no);
+ payContext.put("retMsg", "out_trade_no is empty");
+ return false;
+ }
+ if (StringUtils.isEmpty(total_amount)) {
+ _log.error("AliPay Notify parameter total_amount is empty. total_fee={}", total_amount);
+ payContext.put("retMsg", "total_amount is empty");
+ return false;
+ }
+ String errorMessage;
+ // 查询payOrder记录
+ String payOrderId = out_trade_no;
+ PayOrder payOrder = super.baseSelectPayOrder(payOrderId);
+ if (payOrder == null) {
+ _log.error("Can't found payOrder form db. payOrderId={}, ", payOrderId);
+ payContext.put("retMsg", "Can't found payOrder");
+ return false;
+ }
+ // 查询payChannel记录
+ String mchId = payOrder.getMchId();
+ String channelId = payOrder.getChannelId();
+ PayChannel payChannel = super.baseSelectPayChannel(mchId, channelId);
+ if(payChannel == null) {
+ _log.error("Can't found payChannel form db. mchId={} channelId={}, ", payOrderId, mchId, channelId);
+ payContext.put("retMsg", "Can't found payChannel");
+ return false;
+ }
+ boolean verify_result = false;
+ try {
+ verify_result = AlipaySignature.rsaCheckV1(params, alipayConfig.init(payChannel.getParam()).getAlipay_public_key(), AlipayConfig.CHARSET, "RSA2");
+ } catch (AlipayApiException e) {
+ _log.error(e, "AlipaySignature.rsaCheckV1 error");
+ }
+
+ // 验证签名
+ if (!verify_result) {
+ errorMessage = "rsaCheckV1 failed.";
+ _log.error("AliPay Notify parameter {}", errorMessage);
+ payContext.put("retMsg", errorMessage);
+ return false;
+ }
+
+ // 核对金额
+ long aliPayAmt = new BigDecimal(total_amount).movePointRight(2).longValue();
+ long dbPayAmt = payOrder.getAmount().longValue();
+ if (dbPayAmt != aliPayAmt) {
+ _log.error("db payOrder record payPrice not equals total_amount. total_amount={},payOrderId={}", total_amount, payOrderId);
+ payContext.put("retMsg", "");
+ return false;
+ }
+ payContext.put("payOrder", payOrder);
+ return true;
+ }
+
+ /**
+ * 验证微信支付通知参数
+ * @return
+ */
+ public boolean verifyWxPayParams(Map payContext) {
+ WxPayOrderNotifyResult params = (WxPayOrderNotifyResult)payContext.get("parameters");
+
+ //校验结果是否成功
+ if (!PayConstant.RETURN_VALUE_SUCCESS.equalsIgnoreCase(params.getResultCode())
+ || !PayConstant.RETURN_VALUE_SUCCESS.equalsIgnoreCase(params.getResultCode())) {
+ _log.error("returnCode={},resultCode={},errCode={},errCodeDes={}", params.getReturnCode(), params.getResultCode(), params.getErrCode(), params.getErrCodeDes());
+ payContext.put("retMsg", "notify data failed");
+ return false;
+ }
+
+ Integer total_fee = params.getTotalFee(); // 总金额
+ String out_trade_no = params.getOutTradeNo(); // 商户系统订单号
+
+ // 查询payOrder记录
+ String payOrderId = out_trade_no;
+ PayOrder payOrder = super.baseSelectPayOrder(payOrderId);
+ if (payOrder==null) {
+ _log.error("Can't found payOrder form db. payOrderId={}, ", payOrderId);
+ payContext.put("retMsg", "Can't found payOrder");
+ return false;
+ }
+
+ // 查询payChannel记录
+ String mchId = payOrder.getMchId();
+ String channelId = payOrder.getChannelId();
+ PayChannel payChannel = super.baseSelectPayChannel(mchId, channelId);
+ if(payChannel == null) {
+ _log.error("Can't found payChannel form db. mchId={} channelId={}, ", payOrderId, mchId, channelId);
+ payContext.put("retMsg", "Can't found payChannel");
+ return false;
+ }
+ payContext.put("wxPayConfig", WxPayUtil.getWxPayConfig(payChannel.getParam()));
+
+ // 核对金额
+ long wxPayAmt = new BigDecimal(total_fee).longValue();
+ long dbPayAmt = payOrder.getAmount().longValue();
+ if (dbPayAmt != wxPayAmt) {
+ _log.error("db payOrder record payPrice not equals total_fee. total_fee={},payOrderId={}", total_fee, payOrderId);
+ payContext.put("retMsg", "total_fee is not the same");
+ return false;
+ }
+
+ payContext.put("payOrder", payOrder);
+ return true;
+ }
+
+
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/PayChannel4AliServiceImpl.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/PayChannel4AliServiceImpl.java
new file mode 100644
index 0000000..63f39f7
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/PayChannel4AliServiceImpl.java
@@ -0,0 +1,287 @@
+package org.xxpay.boot.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.alipay.api.AlipayApiException;
+import com.alipay.api.AlipayClient;
+import com.alipay.api.DefaultAlipayClient;
+import com.alipay.api.domain.AlipayTradeAppPayModel;
+import com.alipay.api.domain.AlipayTradePagePayModel;
+import com.alipay.api.domain.AlipayTradePrecreateModel;
+import com.alipay.api.domain.AlipayTradeWapPayModel;
+import com.alipay.api.request.AlipayTradeAppPayRequest;
+import com.alipay.api.request.AlipayTradePagePayRequest;
+import com.alipay.api.request.AlipayTradePrecreateRequest;
+import com.alipay.api.request.AlipayTradeWapPayRequest;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.xxpay.boot.service.BaseService;
+import org.xxpay.boot.service.IPayChannel4AliService;
+import org.xxpay.boot.service.channel.alipay.AlipayConfig;
+import org.xxpay.common.constant.PayConstant;
+import org.xxpay.common.domain.BaseParam;
+import org.xxpay.common.enumm.RetEnum;
+import org.xxpay.common.util.*;
+import org.xxpay.dal.dao.model.PayChannel;
+import org.xxpay.dal.dao.model.PayOrder;
+
+import java.util.Map;
+
+/**
+ * @author: dingzhiwei
+ * @date: 17/9/10
+ * @description:
+ */
+@Service
+public class PayChannel4AliServiceImpl extends BaseService implements IPayChannel4AliService {
+
+ private static final MyLog _log = MyLog.getLog(PayChannel4AliServiceImpl.class);
+
+ @Autowired
+ private AlipayConfig alipayConfig;
+
+ @Override
+ public Map doAliPayWapReq(String jsonParam) {
+ String logPrefix = "【支付宝WAP支付下单】";
+ BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
+ Map bizParamMap = baseParam.getBizParamMap();
+ if (ObjectValidUtil.isInvalid(bizParamMap)) {
+ _log.warn("{}失败, {}. jsonParam={}", logPrefix, RetEnum.RET_PARAM_NOT_FOUND.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_NOT_FOUND);
+ }
+ JSONObject payOrderObj = baseParam.isNullValue("payOrder") ? null : JSONObject.parseObject(bizParamMap.get("payOrder").toString());
+ PayOrder payOrder = BeanConvertUtils.map2Bean(payOrderObj, PayOrder.class);
+ if (ObjectValidUtil.isInvalid(payOrder)) {
+ _log.warn("{}失败, {}. jsonParam={}", logPrefix, RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
+ }
+ String payOrderId = payOrder.getPayOrderId();
+ String mchId = payOrder.getMchId();
+ String channelId = payOrder.getChannelId();
+ PayChannel payChannel = super.baseSelectPayChannel(mchId, channelId);
+ alipayConfig.init(payChannel.getParam());
+ AlipayClient client = new DefaultAlipayClient(alipayConfig.getUrl(), alipayConfig.getApp_id(), alipayConfig.getRsa_private_key(), AlipayConfig.FORMAT, AlipayConfig.CHARSET, alipayConfig.getAlipay_public_key(), AlipayConfig.SIGNTYPE);
+ AlipayTradeWapPayRequest alipay_request = new AlipayTradeWapPayRequest();
+ // 封装请求支付信息
+ AlipayTradeWapPayModel model=new AlipayTradeWapPayModel();
+ model.setOutTradeNo(payOrderId);
+ model.setSubject(payOrder.getSubject());
+ model.setTotalAmount(AmountUtil.convertCent2Dollar(payOrder.getAmount().toString()));
+ model.setBody(payOrder.getBody());
+ model.setProductCode("QUICK_WAP_PAY");
+ // 获取objParams参数
+ String objParams = payOrder.getExtra();
+ if (StringUtils.isNotEmpty(objParams)) {
+ try {
+ JSONObject objParamsJson = JSON.parseObject(objParams);
+ if(StringUtils.isNotBlank(objParamsJson.getString("quit_url"))) {
+ model.setQuitUrl(objParamsJson.getString("quit_url"));
+ }
+ } catch (Exception e) {
+ _log.error("{}objParams参数格式错误!", logPrefix);
+ }
+ }
+ alipay_request.setBizModel(model);
+ // 设置异步通知地址
+ alipay_request.setNotifyUrl(alipayConfig.getNotify_url());
+ // 设置同步地址
+ alipay_request.setReturnUrl(alipayConfig.getReturn_url());
+ String payUrl = null;
+ try {
+ payUrl = client.pageExecute(alipay_request).getBody();
+ } catch (AlipayApiException e) {
+ e.printStackTrace();
+ }
+ _log.info("{}生成跳转路径:payUrl={}", logPrefix, payUrl);
+ super.baseUpdateStatus4Ing(payOrderId, null);
+ _log.info("{}生成请求支付宝数据,req={}", logPrefix, alipay_request.getBizModel());
+ _log.info("###### 商户统一下单处理完成 ######");
+ Map map = XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null);
+ map.put("payOrderId", payOrderId);
+ map.put("payUrl", payUrl);
+ return RpcUtil.createBizResult(baseParam, map);
+ }
+
+ @Override
+ public Map doAliPayPcReq(String jsonParam) {
+ String logPrefix = "【支付宝PC支付下单】";
+ BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
+ Map bizParamMap = baseParam.getBizParamMap();
+ if (ObjectValidUtil.isInvalid(bizParamMap)) {
+ _log.warn("{}失败, {}. jsonParam={}", logPrefix, RetEnum.RET_PARAM_NOT_FOUND.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_NOT_FOUND);
+ }
+ JSONObject payOrderObj = baseParam.isNullValue("payOrder") ? null : JSONObject.parseObject(bizParamMap.get("payOrder").toString());
+ PayOrder payOrder = BeanConvertUtils.map2Bean(payOrderObj, PayOrder.class);
+ if (ObjectValidUtil.isInvalid(payOrder)) {
+ _log.warn("{}失败, {}. jsonParam={}", logPrefix, RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
+ }
+ String payOrderId = payOrder.getPayOrderId();
+ String mchId = payOrder.getMchId();
+ String channelId = payOrder.getChannelId();
+ PayChannel payChannel = super.baseSelectPayChannel(mchId, channelId);
+ alipayConfig.init(payChannel.getParam());
+ AlipayClient client = new DefaultAlipayClient(alipayConfig.getUrl(), alipayConfig.getApp_id(), alipayConfig.getRsa_private_key(), AlipayConfig.FORMAT, AlipayConfig.CHARSET, alipayConfig.getAlipay_public_key(), AlipayConfig.SIGNTYPE);
+ AlipayTradePagePayRequest alipay_request = new AlipayTradePagePayRequest();
+ // 封装请求支付信息
+ AlipayTradePagePayModel model=new AlipayTradePagePayModel();
+ model.setOutTradeNo(payOrderId);
+ model.setSubject(payOrder.getSubject());
+ model.setTotalAmount(AmountUtil.convertCent2Dollar(payOrder.getAmount().toString()));
+ model.setBody(payOrder.getBody());
+ model.setProductCode("FAST_INSTANT_TRADE_PAY");
+ // 获取objParams参数
+ String objParams = payOrder.getExtra();
+ String qr_pay_mode = "2";
+ String qrcode_width = "200";
+ if (StringUtils.isNotEmpty(objParams)) {
+ try {
+ JSONObject objParamsJson = JSON.parseObject(objParams);
+ qr_pay_mode = ObjectUtils.toString(objParamsJson.getString("qr_pay_mode"), "2");
+ qrcode_width = ObjectUtils.toString(objParamsJson.getString("qrcode_width"), "200");
+ } catch (Exception e) {
+ _log.error("{}objParams参数格式错误!", logPrefix);
+ }
+ }
+ model.setQrPayMode(qr_pay_mode);
+ model.setQrcodeWidth(Long.parseLong(qrcode_width));
+ alipay_request.setBizModel(model);
+ // 设置异步通知地址
+ alipay_request.setNotifyUrl(alipayConfig.getNotify_url());
+ // 设置同步地址
+ alipay_request.setReturnUrl(alipayConfig.getReturn_url());
+ String payUrl = null;
+ try {
+ payUrl = client.pageExecute(alipay_request).getBody();
+ } catch (AlipayApiException e) {
+ e.printStackTrace();
+ }
+ _log.info("{}生成跳转路径:payUrl={}", logPrefix, payUrl);
+ super.baseUpdateStatus4Ing(payOrderId, null);
+ _log.info("{}生成请求支付宝数据,req={}", logPrefix, alipay_request.getBizModel());
+ _log.info("###### 商户统一下单处理完成 ######");
+ Map map = XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null);
+ map.put("payOrderId", payOrderId);
+ map.put("payUrl", payUrl);
+ return RpcUtil.createBizResult(baseParam, map);
+ }
+
+ @Override
+ public Map doAliPayMobileReq(String jsonParam) {
+ String logPrefix = "【支付宝APP支付下单】";
+ BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
+ Map bizParamMap = baseParam.getBizParamMap();
+ if (ObjectValidUtil.isInvalid(bizParamMap)) {
+ _log.warn("{}失败, {}. jsonParam={}", logPrefix, RetEnum.RET_PARAM_NOT_FOUND.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_NOT_FOUND);
+ }
+ JSONObject payOrderObj = baseParam.isNullValue("payOrder") ? null : JSONObject.parseObject(bizParamMap.get("payOrder").toString());
+ PayOrder payOrder = BeanConvertUtils.map2Bean(payOrderObj, PayOrder.class);
+ if (ObjectValidUtil.isInvalid(payOrder)) {
+ _log.warn("{}失败, {}. jsonParam={}", logPrefix, RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
+ }
+ String payOrderId = payOrder.getPayOrderId();
+ String mchId = payOrder.getMchId();
+ String channelId = payOrder.getChannelId();
+ PayChannel payChannel = super.baseSelectPayChannel(mchId, channelId);
+ alipayConfig.init(payChannel.getParam());
+ AlipayClient client = new DefaultAlipayClient(alipayConfig.getUrl(), alipayConfig.getApp_id(), alipayConfig.getRsa_private_key(), AlipayConfig.FORMAT, AlipayConfig.CHARSET, alipayConfig.getAlipay_public_key(), AlipayConfig.SIGNTYPE);
+ AlipayTradeAppPayRequest alipay_request = new AlipayTradeAppPayRequest();
+ // 封装请求支付信息
+ AlipayTradeAppPayModel model=new AlipayTradeAppPayModel();
+ model.setOutTradeNo(payOrderId);
+ model.setSubject(payOrder.getSubject());
+ model.setTotalAmount(AmountUtil.convertCent2Dollar(payOrder.getAmount().toString()));
+ model.setBody(payOrder.getBody());
+ model.setProductCode("QUICK_MSECURITY_PAY");
+ alipay_request.setBizModel(model);
+ // 设置异步通知地址
+ alipay_request.setNotifyUrl(alipayConfig.getNotify_url());
+ // 设置同步地址
+ alipay_request.setReturnUrl(alipayConfig.getReturn_url());
+ String payParams = null;
+ try {
+ payParams = client.sdkExecute(alipay_request).getBody();
+ } catch (AlipayApiException e) {
+ e.printStackTrace();
+ }
+ super.baseUpdateStatus4Ing(payOrderId, null);
+ _log.info("{}生成请求支付宝数据,payParams={}", logPrefix, payParams);
+ _log.info("###### 商户统一下单处理完成 ######");
+ Map map = XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null);
+ map.put("payOrderId", payOrderId);
+ map.put("payParams", payParams);
+ return RpcUtil.createBizResult(baseParam, map);
+ }
+
+ @Override
+ public Map doAliPayQrReq(String jsonParam) {
+ String logPrefix = "【支付宝当面付之扫码支付下单】";
+ BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
+ Map bizParamMap = baseParam.getBizParamMap();
+ if (ObjectValidUtil.isInvalid(bizParamMap)) {
+ _log.warn("{}失败, {}. jsonParam={}", logPrefix, RetEnum.RET_PARAM_NOT_FOUND.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_NOT_FOUND);
+ }
+ JSONObject payOrderObj = baseParam.isNullValue("payOrder") ? null : JSONObject.parseObject(bizParamMap.get("payOrder").toString());
+ PayOrder payOrder = BeanConvertUtils.map2Bean(payOrderObj, PayOrder.class);
+ if (ObjectValidUtil.isInvalid(payOrder)) {
+ _log.warn("{}失败, {}. jsonParam={}", logPrefix, RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
+ }
+ String payOrderId = payOrder.getPayOrderId();
+ String mchId = payOrder.getMchId();
+ String channelId = payOrder.getChannelId();
+ PayChannel payChannel = super.baseSelectPayChannel(mchId, channelId);
+ alipayConfig.init(payChannel.getParam());
+ AlipayClient client = new DefaultAlipayClient(alipayConfig.getUrl(), alipayConfig.getApp_id(), alipayConfig.getRsa_private_key(), AlipayConfig.FORMAT, AlipayConfig.CHARSET, alipayConfig.getAlipay_public_key(), AlipayConfig.SIGNTYPE);
+ AlipayTradePrecreateRequest alipay_request = new AlipayTradePrecreateRequest();
+ // 封装请求支付信息
+ AlipayTradePrecreateModel model=new AlipayTradePrecreateModel();
+ model.setOutTradeNo(payOrderId);
+ model.setSubject(payOrder.getSubject());
+ model.setTotalAmount(AmountUtil.convertCent2Dollar(payOrder.getAmount().toString()));
+ model.setBody(payOrder.getBody());
+ // 获取objParams参数
+ String objParams = payOrder.getExtra();
+ if (StringUtils.isNotEmpty(objParams)) {
+ try {
+ JSONObject objParamsJson = JSON.parseObject(objParams);
+ if(StringUtils.isNotBlank(objParamsJson.getString("discountable_amount"))) {
+ //可打折金额
+ model.setDiscountableAmount(objParamsJson.getString("discountable_amount"));
+ }
+ if(StringUtils.isNotBlank(objParamsJson.getString("undiscountable_amount"))) {
+ //不可打折金额
+ model.setUndiscountableAmount(objParamsJson.getString("undiscountable_amount"));
+ }
+ } catch (Exception e) {
+ _log.error("{}objParams参数格式错误!", logPrefix);
+ }
+ }
+ alipay_request.setBizModel(model);
+ // 设置异步通知地址
+ alipay_request.setNotifyUrl(alipayConfig.getNotify_url());
+ // 设置同步地址
+ alipay_request.setReturnUrl(alipayConfig.getReturn_url());
+ String payUrl = null;
+ try {
+ payUrl = client.execute(alipay_request).getBody();
+ } catch (AlipayApiException e) {
+ e.printStackTrace();
+ }
+ _log.info("{}生成跳转路径:payUrl={}", logPrefix, payUrl);
+ super.baseUpdateStatus4Ing(payOrderId, null);
+ _log.info("{}生成请求支付宝数据,req={}", logPrefix, alipay_request.getBizModel());
+ _log.info("###### 商户统一下单处理完成 ######");
+ Map map = XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null);
+ map.put("payOrderId", payOrderId);
+ map.put("payUrl", payUrl);
+ return RpcUtil.createBizResult(baseParam, map);
+ }
+
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/PayChannel4WxServiceImpl.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/PayChannel4WxServiceImpl.java
new file mode 100644
index 0000000..1e13657
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/PayChannel4WxServiceImpl.java
@@ -0,0 +1,198 @@
+package org.xxpay.boot.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
+import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
+import com.github.binarywang.wxpay.config.WxPayConfig;
+import com.github.binarywang.wxpay.constant.WxPayConstants;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
+import com.github.binarywang.wxpay.util.SignUtils;
+import org.springframework.stereotype.Service;
+import org.xxpay.boot.service.BaseService;
+import org.xxpay.boot.service.IPayChannel4WxService;
+import org.xxpay.boot.service.channel.wechat.WxPayProperties;
+import org.xxpay.boot.service.channel.wechat.WxPayUtil;
+import org.xxpay.common.constant.PayConstant;
+import org.xxpay.common.domain.BaseParam;
+import org.xxpay.common.enumm.RetEnum;
+import org.xxpay.common.util.*;
+import org.xxpay.dal.dao.model.PayChannel;
+import org.xxpay.dal.dao.model.PayOrder;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Description: 支付渠道接口:微信
+ * @author dingzhiwei jmdhappy@126.com
+ * @date 2017-09-05
+ * @version V1.0
+ * @Copyright: www.xxpay.org
+ */
+@Service
+public class PayChannel4WxServiceImpl extends BaseService implements IPayChannel4WxService {
+
+ private final MyLog _log = MyLog.getLog(PayChannel4WxServiceImpl.class);
+
+ @Resource
+ private WxPayProperties wxPayProperties;
+
+ public Map doWxPayReq(String jsonParam) {
+ String logPrefix = "【微信支付统一下单】";
+ BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
+ Map bizParamMap = baseParam.getBizParamMap();
+ try{
+ if (ObjectValidUtil.isInvalid(bizParamMap)) {
+ _log.warn("{}失败, {}. jsonParam={}", logPrefix, RetEnum.RET_PARAM_NOT_FOUND.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_NOT_FOUND);
+ }
+ JSONObject payOrderObj = baseParam.isNullValue("payOrder") ? null : JSONObject.parseObject(bizParamMap.get("payOrder").toString());
+ String tradeType = baseParam.isNullValue("tradeType") ? null : bizParamMap.get("tradeType").toString();
+ PayOrder payOrder = BeanConvertUtils.map2Bean(payOrderObj, PayOrder.class);
+ if (ObjectValidUtil.isInvalid(payOrder, tradeType)) {
+ _log.warn("{}失败, {}. jsonParam={}", logPrefix, RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
+ }
+ String mchId = payOrder.getMchId();
+ String channelId = payOrder.getChannelId();
+ PayChannel payChannel = super.baseSelectPayChannel(mchId, channelId);
+ WxPayConfig wxPayConfig = WxPayUtil.getWxPayConfig(payChannel.getParam(), tradeType, wxPayProperties.getCertRootPath(), wxPayProperties.getNotifyUrl());
+ WxPayService wxPayService = new WxPayServiceImpl();
+ wxPayService.setConfig(wxPayConfig);
+ WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = buildUnifiedOrderRequest(payOrder, wxPayConfig);
+ String payOrderId = payOrder.getPayOrderId();
+ WxPayUnifiedOrderResult wxPayUnifiedOrderResult;
+ try {
+ wxPayUnifiedOrderResult = wxPayService.unifiedOrder(wxPayUnifiedOrderRequest);
+ _log.info("{} >>> 下单成功", logPrefix);
+ Map map = new HashMap<>();
+ map.put("payOrderId", payOrderId);
+ map.put("prepayId", wxPayUnifiedOrderResult.getPrepayId());
+ int result = super.baseUpdateStatus4Ing(payOrderId, wxPayUnifiedOrderResult.getPrepayId());
+ _log.info("更新第三方支付订单号:payOrderId={},prepayId={},result={}", payOrderId, wxPayUnifiedOrderResult.getPrepayId(), result);
+ switch (tradeType) {
+ case PayConstant.WxConstant.TRADE_TYPE_NATIVE : {
+ map.put("codeUrl", wxPayUnifiedOrderResult.getCodeURL()); // 二维码支付链接
+ break;
+ }
+ case PayConstant.WxConstant.TRADE_TYPE_APP : {
+ Map payInfo = new HashMap<>();
+ String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
+ String nonceStr = String.valueOf(System.currentTimeMillis());
+ // APP支付绑定的是微信开放平台上的账号,APPID为开放平台上绑定APP后发放的参数
+ String appId = wxPayConfig.getAppId();
+ Map configMap = new HashMap<>();
+ // 此map用于参与调起sdk支付的二次签名,格式全小写,timestamp只能是10位,格式固定,切勿修改
+ String partnerId = wxPayConfig.getMchId();
+ configMap.put("prepayid", wxPayUnifiedOrderResult.getPrepayId());
+ configMap.put("partnerid", partnerId);
+ String packageValue = "Sign=WXPay";
+ configMap.put("package", packageValue);
+ configMap.put("timestamp", timestamp);
+ configMap.put("noncestr", nonceStr);
+ configMap.put("appid", appId);
+ // 此map用于客户端与微信服务器交互
+ payInfo.put("sign", SignUtils.createSign(configMap, wxPayConfig.getMchKey(), null));
+ payInfo.put("prepayId", wxPayUnifiedOrderResult.getPrepayId());
+ payInfo.put("partnerId", partnerId);
+ payInfo.put("appId", appId);
+ payInfo.put("packageValue", packageValue);
+ payInfo.put("timeStamp", timestamp);
+ payInfo.put("nonceStr", nonceStr);
+ map.put("payParams", payInfo);
+ break;
+ }
+ case PayConstant.WxConstant.TRADE_TYPE_JSPAI : {
+ Map payInfo = new HashMap<>();
+ String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
+ String nonceStr = String.valueOf(System.currentTimeMillis());
+ payInfo.put("appId", wxPayUnifiedOrderResult.getAppid());
+ // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
+ payInfo.put("timeStamp", timestamp);
+ payInfo.put("nonceStr", nonceStr);
+ payInfo.put("package", "prepay_id=" + wxPayUnifiedOrderResult.getPrepayId());
+ payInfo.put("signType", WxPayConstants.SignType.MD5);
+ payInfo.put("paySign", SignUtils.createSign(payInfo, wxPayConfig.getMchKey(), null));
+ map.put("payParams", payInfo);
+ break;
+ }
+ case PayConstant.WxConstant.TRADE_TYPE_MWEB : {
+ map.put("payUrl", wxPayUnifiedOrderResult.getMwebUrl()); // h5支付链接地址
+ break;
+ }
+ }
+ return RpcUtil.createBizResult(baseParam, map);
+ } catch (WxPayException e) {
+ _log.error(e, "下单失败");
+ //出现业务错误
+ _log.info("{}下单返回失败", logPrefix);
+ _log.info("err_code:{}", e.getErrCode());
+ _log.info("err_code_des:{}", e.getErrCodeDes());
+
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_BIZ_WX_PAY_CREATE_FAIL);
+
+ // return XXPayUtil.makeRetData(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_FAIL, "0111", "调用微信支付失败," + e.getErrCode() + ":" + e.getErrCodeDes()), resKey);
+ }
+ }catch (Exception e) {
+ _log.error(e, "微信支付统一下单异常");
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_BIZ_WX_PAY_CREATE_FAIL);
+
+ //return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "", PayConstant.RETURN_VALUE_FAIL, PayEnum.ERR_0001));
+ }
+ }
+
+ /**
+ * 构建微信统一下单请求数据
+ * @param payOrder
+ * @param wxPayConfig
+ * @return
+ */
+ WxPayUnifiedOrderRequest buildUnifiedOrderRequest(PayOrder payOrder, WxPayConfig wxPayConfig) {
+ String tradeType = wxPayConfig.getTradeType();
+ String payOrderId = payOrder.getPayOrderId();
+ Integer totalFee = payOrder.getAmount().intValue();// 支付金额,单位分
+ String deviceInfo = payOrder.getDevice();
+ String body = payOrder.getBody();
+ String detail = null;
+ String attach = null;
+ String outTradeNo = payOrderId;
+ String feeType = "CNY";
+ String spBillCreateIP = payOrder.getClientIp();
+ String timeStart = null;
+ String timeExpire = null;
+ String goodsTag = null;
+ String notifyUrl = wxPayConfig.getNotifyUrl();
+ String productId = null;
+ if(tradeType.equals(PayConstant.WxConstant.TRADE_TYPE_NATIVE)) productId = JSON.parseObject(payOrder.getExtra()).getString("productId");
+ String limitPay = null;
+ String openId = null;
+ if(tradeType.equals(PayConstant.WxConstant.TRADE_TYPE_JSPAI)) openId = JSON.parseObject(payOrder.getExtra()).getString("openId");
+ String sceneInfo = null;
+ if(tradeType.equals(PayConstant.WxConstant.TRADE_TYPE_MWEB)) sceneInfo = JSON.parseObject(payOrder.getExtra()).getString("sceneInfo");
+ // 微信统一下单请求对象
+ WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
+ request.setDeviceInfo(deviceInfo);
+ request.setBody(body);
+ request.setDetail(detail);
+ request.setAttach(attach);
+ request.setOutTradeNo(outTradeNo);
+ request.setFeeType(feeType);
+ request.setTotalFee(totalFee);
+ request.setSpbillCreateIp(spBillCreateIP);
+ request.setTimeStart(timeStart);
+ request.setTimeExpire(timeExpire);
+ request.setGoodsTag(goodsTag);
+ request.setNotifyURL(notifyUrl);
+ request.setTradeType(tradeType);
+ request.setProductId(productId);
+ request.setLimitPay(limitPay);
+ request.setOpenid(openId);
+ request.setSceneInfo(sceneInfo);
+
+ return request;
+ }
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/PayChannelServiceImpl.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/PayChannelServiceImpl.java
new file mode 100644
index 0000000..f6e07df
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/PayChannelServiceImpl.java
@@ -0,0 +1,45 @@
+package org.xxpay.boot.service.impl;
+
+import org.springframework.stereotype.Service;
+import org.xxpay.boot.service.BaseService;
+import org.xxpay.boot.service.IPayChannelService;
+import org.xxpay.common.domain.BaseParam;
+import org.xxpay.common.enumm.RetEnum;
+import org.xxpay.common.util.JsonUtil;
+import org.xxpay.common.util.MyLog;
+import org.xxpay.common.util.ObjectValidUtil;
+import org.xxpay.common.util.RpcUtil;
+import org.xxpay.dal.dao.model.PayChannel;
+
+import java.util.Map;
+
+/**
+ * @author: dingzhiwei
+ * @date: 17/9/8
+ * @description:
+ */
+@Service
+public class PayChannelServiceImpl extends BaseService implements IPayChannelService {
+
+ private static final MyLog _log = MyLog.getLog(PayChannelServiceImpl.class);
+
+ @Override
+ public Map selectPayChannel(String jsonParam) {
+ BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
+ Map bizParamMap = baseParam.getBizParamMap();
+ if (ObjectValidUtil.isInvalid(bizParamMap)) {
+ _log.warn("查询支付渠道信息失败, {}. jsonParam={}", RetEnum.RET_PARAM_NOT_FOUND.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_NOT_FOUND);
+ }
+ String mchId = baseParam.isNullValue("mchId") ? null : bizParamMap.get("mchId").toString();
+ String channelId = baseParam.isNullValue("channelId") ? null : bizParamMap.get("channelId").toString();
+ if (ObjectValidUtil.isInvalid(mchId, channelId)) {
+ _log.warn("查询支付渠道信息失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
+ }
+ PayChannel payChannel = super.baseSelectPayChannel(mchId, channelId);
+ if(payChannel == null) return RpcUtil.createFailResult(baseParam, RetEnum.RET_BIZ_DATA_NOT_EXISTS);
+ String jsonResult = JsonUtil.object2Json(payChannel);
+ return RpcUtil.createBizResult(baseParam, jsonResult);
+ }
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/PayOrderServiceImpl.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/PayOrderServiceImpl.java
new file mode 100644
index 0000000..5c5cf42
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/PayOrderServiceImpl.java
@@ -0,0 +1,174 @@
+package org.xxpay.boot.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import org.springframework.stereotype.Service;
+import org.xxpay.boot.service.BaseService;
+import org.xxpay.boot.service.IPayOrderService;
+import org.xxpay.common.domain.BaseParam;
+import org.xxpay.common.enumm.RetEnum;
+import org.xxpay.common.util.*;
+import org.xxpay.dal.dao.model.PayOrder;
+
+import java.util.Map;
+
+/**
+ * @author: dingzhiwei
+ * @date: 17/9/8
+ * @description:
+ */
+@Service
+public class PayOrderServiceImpl extends BaseService implements IPayOrderService {
+
+ private static final MyLog _log = MyLog.getLog(PayOrderServiceImpl.class);
+
+ @Override
+ public Map createPayOrder(String jsonParam) {
+ BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
+ Map bizParamMap = baseParam.getBizParamMap();
+ if (ObjectValidUtil.isInvalid(bizParamMap)) {
+ _log.warn("新增支付订单失败, {}. jsonParam={}", RetEnum.RET_PARAM_NOT_FOUND.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_NOT_FOUND);
+ }
+ JSONObject payOrderObj = baseParam.isNullValue("payOrder") ? null : JSONObject.parseObject(bizParamMap.get("payOrder").toString());
+ if(payOrderObj == null) {
+ _log.warn("新增支付订单失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
+ }
+ PayOrder payOrder = BeanConvertUtils.map2Bean(payOrderObj, PayOrder.class);
+ if(payOrder == null) {
+ _log.warn("新增支付订单失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
+ }
+ int result = super.baseCreatePayOrder(payOrder);
+ return RpcUtil.createBizResult(baseParam, result);
+ }
+
+ @Override
+ public Map selectPayOrder(String jsonParam) {
+ BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
+ Map bizParamMap = baseParam.getBizParamMap();
+ if (ObjectValidUtil.isInvalid(bizParamMap)) {
+ _log.warn("根据支付订单号查询支付订单失败, {}. jsonParam={}", RetEnum.RET_PARAM_NOT_FOUND.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_NOT_FOUND);
+ }
+ String payOrderId = baseParam.isNullValue("payOrderId") ? null : bizParamMap.get("payOrderId").toString();
+ if (ObjectValidUtil.isInvalid(payOrderId)) {
+ _log.warn("根据支付订单号查询支付订单失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
+ }
+ PayOrder payOrder = super.baseSelectPayOrder(payOrderId);
+ if(payOrder == null) return RpcUtil.createFailResult(baseParam, RetEnum.RET_BIZ_DATA_NOT_EXISTS);
+ String jsonResult = JsonUtil.object2Json(payOrder);
+ return RpcUtil.createBizResult(baseParam, jsonResult);
+ }
+
+ @Override
+ public Map selectPayOrderByMchIdAndPayOrderId(String jsonParam) {
+ BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
+ Map bizParamMap = baseParam.getBizParamMap();
+ if (ObjectValidUtil.isInvalid(bizParamMap)) {
+ _log.warn("根据商户号和支付订单号查询支付订单失败, {}. jsonParam={}", RetEnum.RET_PARAM_NOT_FOUND.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_NOT_FOUND);
+ }
+ String mchId = baseParam.isNullValue("mchId") ? null : bizParamMap.get("mchId").toString();
+ String payOrderId = baseParam.isNullValue("payOrderId") ? null : bizParamMap.get("payOrderId").toString();
+ if (ObjectValidUtil.isInvalid(mchId, payOrderId)) {
+ _log.warn("根据商户号和支付订单号查询支付订单失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
+ }
+ PayOrder payOrder = super.baseSelectPayOrderByMchIdAndPayOrderId(mchId, payOrderId);
+ if(payOrder == null) return RpcUtil.createFailResult(baseParam, RetEnum.RET_BIZ_DATA_NOT_EXISTS);
+ String jsonResult = JsonUtil.object2Json(payOrder);
+ return RpcUtil.createBizResult(baseParam, jsonResult);
+ }
+
+ @Override
+ public Map selectPayOrderByMchIdAndMchOrderNo(String jsonParam) {
+ BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
+ Map bizParamMap = baseParam.getBizParamMap();
+ if (ObjectValidUtil.isInvalid(bizParamMap)) {
+ _log.warn("根据商户号和商户订单号查询支付订单失败, {}. jsonParam={}", RetEnum.RET_PARAM_NOT_FOUND.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_NOT_FOUND);
+ }
+ String mchId = baseParam.isNullValue("mchId") ? null : bizParamMap.get("mchId").toString();
+ String mchOrderNo = baseParam.isNullValue("mchOrderNo") ? null : bizParamMap.get("mchOrderNo").toString();
+ if (ObjectValidUtil.isInvalid(mchId, mchOrderNo)) {
+ _log.warn("根据商户号和商户订单号查询支付订单失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
+ }
+ PayOrder payOrder = super.baseSelectPayOrderByMchIdAndMchOrderNo(mchId, mchOrderNo);
+ if(payOrder == null) return RpcUtil.createFailResult(baseParam, RetEnum.RET_BIZ_DATA_NOT_EXISTS);
+ String jsonResult = JsonUtil.object2Json(payOrder);
+ return RpcUtil.createBizResult(baseParam, jsonResult);
+ }
+
+ @Override
+ public Map updateStatus4Ing(String jsonParam) {
+ BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
+ Map bizParamMap = baseParam.getBizParamMap();
+ if (ObjectValidUtil.isInvalid(bizParamMap)) {
+ _log.warn("修改支付订单状态为支付中失败, {}. jsonParam={}", RetEnum.RET_PARAM_NOT_FOUND.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_NOT_FOUND);
+ }
+ String payOrderId = baseParam.isNullValue("payOrderId") ? null : bizParamMap.get("payOrderId").toString();
+ String channelOrderNo = baseParam.isNullValue("channelOrderNo") ? null : bizParamMap.get("channelOrderNo").toString();
+ if (ObjectValidUtil.isInvalid(payOrderId, channelOrderNo)) {
+ _log.warn("修改支付订单状态为支付中失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
+ }
+ int result = super.baseUpdateStatus4Ing(payOrderId, channelOrderNo);
+ return RpcUtil.createBizResult(baseParam, result);
+ }
+
+ @Override
+ public Map updateStatus4Success(String jsonParam) {
+ BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
+ Map bizParamMap = baseParam.getBizParamMap();
+ if (ObjectValidUtil.isInvalid(bizParamMap)) {
+ _log.warn("修改支付订单状态为支付成功失败, {}. jsonParam={}", RetEnum.RET_PARAM_NOT_FOUND.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_NOT_FOUND);
+ }
+ String payOrderId = baseParam.isNullValue("payOrderId") ? null : bizParamMap.get("payOrderId").toString();
+ if (ObjectValidUtil.isInvalid(payOrderId)) {
+ _log.warn("修改支付订单状态为支付成功失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
+ }
+ int result = super.baseUpdateStatus4Success(payOrderId);
+ return RpcUtil.createBizResult(baseParam, result);
+ }
+
+ @Override
+ public Map updateStatus4Complete(String jsonParam) {
+ BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
+ Map bizParamMap = baseParam.getBizParamMap();
+ if (ObjectValidUtil.isInvalid(bizParamMap)) {
+ _log.warn("修改支付订单状态为支付完成失败, {}. jsonParam={}", RetEnum.RET_PARAM_NOT_FOUND.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_NOT_FOUND);
+ }
+ String payOrderId = baseParam.isNullValue("payOrderId") ? null : bizParamMap.get("payOrderId").toString();
+ if (ObjectValidUtil.isInvalid(payOrderId)) {
+ _log.warn("修改支付订单状态为支付完成失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
+ }
+ int result = super.baseUpdateStatus4Complete(payOrderId);
+ return RpcUtil.createBizResult(baseParam, result);
+ }
+
+ @Override
+ public Map updateNotify(String jsonParam) {
+ BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
+ Map bizParamMap = baseParam.getBizParamMap();
+ if (ObjectValidUtil.isInvalid(bizParamMap)) {
+ _log.warn("修改支付订单通知次数失败, {}. jsonParam={}", RetEnum.RET_PARAM_NOT_FOUND.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_NOT_FOUND);
+ }
+ String payOrderId = baseParam.isNullValue("payOrderId") ? null : bizParamMap.get("payOrderId").toString();
+ Byte count = baseParam.isNullValue("count") ? null : Byte.parseByte(bizParamMap.get("count").toString());
+ if (ObjectValidUtil.isInvalid(payOrderId, count)) {
+ _log.warn("修改支付订单通知次数失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam);
+ return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID);
+ }
+ int result = super.baseUpdateNotify(payOrderId, count);
+ return RpcUtil.createBizResult(baseParam, result);
+ }
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/Mq4PayNotify.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/Mq4PayNotify.java
new file mode 100644
index 0000000..59de5be
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/Mq4PayNotify.java
@@ -0,0 +1,190 @@
+package org.xxpay.boot.service.mq;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import org.apache.activemq.ScheduledMessage;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jms.annotation.JmsListener;
+import org.springframework.jms.core.JmsTemplate;
+import org.springframework.jms.core.MessageCreator;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import org.xxpay.common.util.MyLog;
+import org.xxpay.boot.service.BaseService;
+
+import javax.jms.*;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * @Description: 业务通知MQ实现
+ * @author dingzhiwei jmdhappy@126.com
+ * @date 2017-07-05
+ * @version V1.0
+ * @Copyright: www.xxpay.org
+ */
+@Component
+public class Mq4PayNotify extends BaseService {
+
+ @Autowired
+ private Queue payNotifyQueue;
+
+ @Autowired
+ private JmsTemplate jmsTemplate;
+
+ private static final MyLog _log = MyLog.getLog(Mq4PayNotify.class);
+
+ public void send(String msg) {
+ _log.info("发送MQ消息:msg={}", msg);
+ this.jmsTemplate.convertAndSend(this.payNotifyQueue, msg);
+ }
+
+ /**
+ * 发送延迟消息
+ * @param msg
+ * @param delay
+ */
+ public void send(String msg, long delay) {
+ _log.info("发送MQ延时消息:msg={},delay={}", msg, delay);
+ jmsTemplate.send(this.payNotifyQueue, new MessageCreator() {
+ public Message createMessage(Session session) throws JMSException {
+ TextMessage tm = session.createTextMessage(msg);
+ tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, delay);
+ tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_PERIOD, 1*1000);
+ tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_REPEAT, 1);
+ return tm;
+ }
+ });
+ }
+
+ private static class TrustAnyTrustManager implements X509TrustManager {
+
+ public void checkClientTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException {
+ }
+
+ public void checkServerTrusted(X509Certificate[] chain, String authType)
+ throws CertificateException {
+ }
+
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[] {};
+ }
+ }
+
+ @JmsListener(destination = MqConfig.PAY_NOTIFY_QUEUE_NAME)
+ public void receive(String msg) {
+ _log.info("do notify task, msg={}", msg);
+ JSONObject msgObj = JSON.parseObject(msg);
+ String respUrl = msgObj.getString("url");
+ String orderId = msgObj.getString("orderId");
+ int count = msgObj.getInteger("count");
+ if(StringUtils.isEmpty(respUrl)) {
+ _log.warn("notify url is empty. respUrl={}", respUrl);
+ return;
+ }
+ try {
+ StringBuffer sb = new StringBuffer();
+ URL console = new URL(respUrl);
+ _log.info("==>MQ通知业务系统开始[orderId:{}][count:{}][time:{}]", orderId, count, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
+ if("https".equals(console.getProtocol())) {
+ SSLContext sc = SSLContext.getInstance("SSL");
+ sc.init(null, new TrustManager[] { new TrustAnyTrustManager() },
+ new java.security.SecureRandom());
+ HttpsURLConnection con = (HttpsURLConnection) console.openConnection();
+ con.setSSLSocketFactory(sc.getSocketFactory());
+ con.setRequestMethod("POST");
+ con.setDoInput(true);
+ con.setDoOutput(true);
+ con.setUseCaches(false);
+ con.setConnectTimeout(10 * 1000);
+ con.setReadTimeout(5 * 1000);
+ con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()), 1024*1024);
+ while (true) {
+ String line = in.readLine();
+ if (line == null) {
+ break;
+ }
+ sb.append(line);
+ }
+ in.close();
+ }else if("http".equals(console.getProtocol())) {
+ HttpURLConnection con = (HttpURLConnection) console.openConnection();
+ con.setRequestMethod("POST");
+ con.setDoInput(true);
+ con.setDoOutput(true);
+ con.setUseCaches(false);
+ con.setConnectTimeout(10 * 1000);
+ con.setReadTimeout(5 * 1000);
+ con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()), 1024*1024);
+ while (true) {
+ String line = in.readLine();
+ if (line == null) {
+ break;
+ }
+ sb.append(line);
+ }
+ in.close();
+ }else {
+ _log.error("not do protocol. protocol=%s", console.getProtocol());
+ return;
+ }
+ _log.info("<==MQ通知业务系统结束[orderId:{}][count:{}][time:{}]", orderId, count, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
+ // 验证结果
+ _log.info("notify response , OrderID={}", orderId);
+ if(sb.toString().trim().equalsIgnoreCase("success")){
+ //_log.info("{} notify success, url:{}", _notifyInfo.getBusiId(), respUrl);
+ //修改订单表
+ try {
+ int result = super.baseUpdateStatus4Complete(orderId);
+ _log.info("修改payOrderId={},订单状态为处理完成->{}", orderId, result == 1 ? "成功" : "失败");
+ } catch (Exception e) {
+ _log.error(e, "修改订单状态为处理完成异常");
+ }
+ // 修改通知次数
+ try {
+ int result = super.baseUpdateNotify(orderId, (byte) 1);
+ _log.info("修改payOrderId={},通知业务系统次数->{}", orderId, result == 1 ? "成功" : "失败");
+ }catch (Exception e) {
+ _log.error(e, "修改通知次数异常");
+ }
+ return ; // 通知成功结束
+ }else {
+ // 通知失败,延时再通知
+ int cnt = count+1;
+ _log.info("notify count={}", cnt);
+ // 修改通知次数
+ try {
+ int result = super.baseUpdateNotify(orderId, (byte) cnt);
+ _log.info("修改payOrderId={},通知业务系统次数->{}", orderId, result == 1 ? "成功" : "失败");
+ }catch (Exception e) {
+ _log.error(e, "修改通知次数异常");
+ }
+
+ if (cnt > 5) {
+ _log.info("notify count>5 stop. url={}", respUrl);
+ return ;
+ }
+ msgObj.put("count", cnt);
+ this.send(msgObj.toJSONString(), cnt * 60 * 1000);
+ }
+ _log.warn("notify failed. url:{}, response body:{}", respUrl, sb.toString());
+ } catch(Exception e) {
+ _log.info("<==MQ通知业务系统结束[orderId:{}][count:{}][time:{}]", orderId, count, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
+ _log.error(e, "notify exception. url:%s", respUrl);
+ }
+
+ }
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/MqConfig.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/MqConfig.java
new file mode 100644
index 0000000..de1511e
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/MqConfig.java
@@ -0,0 +1,26 @@
+package org.xxpay.boot.service.mq;
+
+import org.apache.activemq.command.ActiveMQQueue;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.jms.Queue;
+
+/**
+ * @Description:
+ * @author dingzhiwei jmdhappy@126.com
+ * @date 2017-07-05
+ * @version V1.0
+ * @Copyright: www.xxpay.org
+ */
+@Configuration
+public class MqConfig {
+
+ public static final String PAY_NOTIFY_QUEUE_NAME = "pay.notify.queue";
+
+ @Bean
+ public Queue payNotifyQueue() {
+ return new ActiveMQQueue(PAY_NOTIFY_QUEUE_NAME);
+ }
+
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/web/MchInfoService.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/web/MchInfoService.java
new file mode 100644
index 0000000..5b592a3
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/web/MchInfoService.java
@@ -0,0 +1,32 @@
+package org.xxpay.boot.web;
+
+import com.alibaba.fastjson.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.xxpay.common.util.RpcUtil;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author: dingzhiwei
+ * @date: 17/9/9
+ * @description:
+ */
+@Service
+public class MchInfoService {
+
+ @Autowired
+ private RpcCommonService rpcCommonService;
+
+ public JSONObject getByMchId(String mchId) {
+ Map paramMap = new HashMap<>();
+ paramMap.put("mchId", mchId);
+ String jsonParam = RpcUtil.createBaseParam(paramMap);
+ Map result = rpcCommonService.rpcMchInfoService.selectMchInfo(jsonParam);
+ String s = RpcUtil.mkRet(result);
+ if(s==null) return null;
+ return JSONObject.parseObject(s);
+ }
+
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/web/NotifyPayService.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/web/NotifyPayService.java
new file mode 100644
index 0000000..6eced88
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/web/NotifyPayService.java
@@ -0,0 +1,43 @@
+package org.xxpay.boot.web;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.xxpay.common.constant.PayConstant;
+import org.xxpay.common.util.RpcUtil;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author: dingzhiwei
+ * @date: 17/9/10
+ * @description:
+ */
+@Service
+public class NotifyPayService {
+
+ @Autowired
+ private RpcCommonService rpcCommonService;
+
+ public String doAliPayNotify(Map params) {
+ Map paramMap = new HashMap<>();
+ paramMap.put("params", params);
+ String jsonParam = RpcUtil.createBaseParam(paramMap);
+ Map result = rpcCommonService.rpcNotifyPayService.doAliPayNotify(jsonParam);
+ String s = RpcUtil.mkRet(result);
+ if(s == null) {
+ return PayConstant.RETURN_ALIPAY_VALUE_FAIL;
+ }
+ return s;
+ }
+
+ public String doWxPayNotify(String xmlResult) {
+ Map paramMap = new HashMap<>();
+ paramMap.put("xmlResult", xmlResult);
+ String jsonParam = RpcUtil.createBaseParam(paramMap);
+ // 返回给微信的数据格式已经有service处理(包括正确与错误),肯定会返回result
+ Map result = rpcCommonService.rpcNotifyPayService.doWxPayNotify(jsonParam);
+ return RpcUtil.mkRet(result);
+ }
+
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/web/PayChannelService.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/web/PayChannelService.java
new file mode 100644
index 0000000..60939da
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/web/PayChannelService.java
@@ -0,0 +1,33 @@
+package org.xxpay.boot.web;
+
+import com.alibaba.fastjson.JSONObject;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.xxpay.common.util.RpcUtil;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author: dingzhiwei
+ * @date: 17/9/9
+ * @description:
+ */
+@Service
+public class PayChannelService {
+
+ @Autowired
+ private RpcCommonService rpcCommonService;
+
+ public JSONObject getByMchIdAndChannelId(String mchId, String channelId) {
+ Map paramMap = new HashMap<>();
+ paramMap.put("mchId", mchId);
+ paramMap.put("channelId", channelId);
+ String jsonParam = RpcUtil.createBaseParam(paramMap);
+ Map result = rpcCommonService.rpcPayChannelService.selectPayChannel(jsonParam);
+ String s = RpcUtil.mkRet(result);
+ if(s == null) return null;
+ return JSONObject.parseObject(s);
+ }
+
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/web/PayOrderService.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/web/PayOrderService.java
new file mode 100644
index 0000000..fb2eedc
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/web/PayOrderService.java
@@ -0,0 +1,113 @@
+package org.xxpay.boot.web;
+
+import com.alibaba.fastjson.JSONObject;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.xxpay.common.constant.PayConstant;
+import org.xxpay.common.util.MyLog;
+import org.xxpay.common.util.RpcUtil;
+import org.xxpay.common.util.XXPayUtil;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author: dingzhiwei
+ * @date: 17/9/9
+ * @description:
+ */
+@Service
+public class PayOrderService {
+
+ private static final MyLog _log = MyLog.getLog(PayOrderService.class);
+
+ @Autowired
+ private RpcCommonService rpcCommonService;
+
+ public int createPayOrder(JSONObject payOrder) {
+ Map paramMap = new HashMap<>();
+ paramMap.put("payOrder", payOrder);
+ String jsonParam = RpcUtil.createBaseParam(paramMap);
+ Map result = rpcCommonService.rpcPayOrderService.createPayOrder(jsonParam);
+ String s = RpcUtil.mkRet(result);
+ if(s == null) return 0;
+ return Integer.parseInt(s);
+ }
+
+ public JSONObject queryPayOrder(String mchId, String payOrderId, String mchOrderNo, String executeNotify) {
+ Map paramMap = new HashMap<>();
+ Map result;
+ if(StringUtils.isNotBlank(payOrderId)) {
+ paramMap.put("mchId", mchId);
+ paramMap.put("payOrderId", payOrderId);
+ String jsonParam = RpcUtil.createBaseParam(paramMap);
+ result = rpcCommonService.rpcPayOrderService.selectPayOrderByMchIdAndPayOrderId(jsonParam);
+ }else {
+ paramMap.put("mchId", mchId);
+ paramMap.put("mchOrderNo", mchOrderNo);
+ String jsonParam = RpcUtil.createBaseParam(paramMap);
+ result = rpcCommonService.rpcPayOrderService.selectPayOrderByMchIdAndMchOrderNo(jsonParam);
+ }
+ String s = RpcUtil.mkRet(result);
+ if(s == null) return null;
+ boolean isNotify = Boolean.parseBoolean(executeNotify);
+ JSONObject payOrder = JSONObject.parseObject(s);
+ if(isNotify) {
+ paramMap = new HashMap<>();
+ paramMap.put("payOrderId", payOrderId);
+ String jsonParam = RpcUtil.createBaseParam(paramMap);
+ result = rpcCommonService.rpcNotifyPayService.sendBizPayNotify(jsonParam);
+ s = RpcUtil.mkRet(result);
+ _log.info("业务查单完成,并再次发送业务支付通知.发送结果:{}", s);
+ }
+ return payOrder;
+ }
+
+ public String doWxPayReq(String tradeType, JSONObject payOrder, String resKey) {
+ Map paramMap = new HashMap<>();
+ paramMap.put("tradeType", tradeType);
+ paramMap.put("payOrder", payOrder);
+ String jsonParam = RpcUtil.createBaseParam(paramMap);
+ Map result = rpcCommonService.rpcPayChannel4WxService.doWxPayReq(jsonParam);
+ String s = RpcUtil.mkRet(result);
+ if(s == null) {
+ return XXPayUtil.makeRetData(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_FAIL, "0111", "调用微信支付失败"), resKey);
+ }
+ Map map = XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null);
+ map.putAll((Map) result.get("bizResult"));
+ return XXPayUtil.makeRetData(map, resKey);
+ }
+
+ public String doAliPayReq(String channelId, JSONObject payOrder, String resKey) {
+ Map paramMap = new HashMap<>();
+ paramMap.put("payOrder", payOrder);
+ String jsonParam = RpcUtil.createBaseParam(paramMap);
+ Map result;
+ switch (channelId) {
+ case PayConstant.PAY_CHANNEL_ALIPAY_MOBILE :
+ result = rpcCommonService.rpcPayChannel4AliService.doAliPayMobileReq(jsonParam);
+ break;
+ case PayConstant.PAY_CHANNEL_ALIPAY_PC :
+ result = rpcCommonService.rpcPayChannel4AliService.doAliPayPcReq(jsonParam);
+ break;
+ case PayConstant.PAY_CHANNEL_ALIPAY_WAP :
+ result = rpcCommonService.rpcPayChannel4AliService.doAliPayWapReq(jsonParam);
+ break;
+ case PayConstant.PAY_CHANNEL_ALIPAY_QR :
+ result = rpcCommonService.rpcPayChannel4AliService.doAliPayQrReq(jsonParam);
+ break;
+ default:
+ result = null;
+ break;
+ }
+ String s = RpcUtil.mkRet(result);
+ if(s == null) {
+ return XXPayUtil.makeRetData(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_FAIL, "0111", "调用支付宝支付失败"), resKey);
+ }
+ Map map = XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null);
+ map.putAll((Map) result.get("bizResult"));
+ return XXPayUtil.makeRetData(map, resKey);
+ }
+
+}
diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/web/RpcCommonService.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/web/RpcCommonService.java
new file mode 100644
index 0000000..b4ad50a
--- /dev/null
+++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/web/RpcCommonService.java
@@ -0,0 +1,33 @@
+package org.xxpay.boot.web;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.xxpay.boot.service.*;
+
+/**
+ * @author: dingzhiwei
+ * @date: 17/9/10
+ * @description:
+ */
+@Service
+public class RpcCommonService {
+
+ @Autowired
+ public IMchInfoService rpcMchInfoService;
+
+ @Autowired
+ public IPayChannelService rpcPayChannelService;
+
+ @Autowired
+ public IPayOrderService rpcPayOrderService;
+
+ @Autowired
+ public IPayChannel4WxService rpcPayChannel4WxService;
+
+ @Autowired
+ public IPayChannel4AliService rpcPayChannel4AliService;
+
+ @Autowired
+ public INotifyPayService rpcNotifyPayService;
+
+}
diff --git a/xxpay4spring-boot/src/main/webapp/WEB-INF/lib/alipay-sdk-java20170818173712.jar b/xxpay4spring-boot/src/main/webapp/WEB-INF/lib/alipay-sdk-java20170818173712.jar
new file mode 100755
index 0000000..6cc1c44
Binary files /dev/null and b/xxpay4spring-boot/src/main/webapp/WEB-INF/lib/alipay-sdk-java20170818173712.jar differ
diff --git a/xxpay4spring-cloud/xxpay-service/pom.xml b/xxpay4spring-cloud/xxpay-service/pom.xml
index 20019d7..92d8833 100644
--- a/xxpay4spring-cloud/xxpay-service/pom.xml
+++ b/xxpay4spring-cloud/xxpay-service/pom.xml
@@ -27,6 +27,10 @@
org.springframework.boot
spring-boot-starter-activemq
+
+ org.apache.activemq
+ activemq-pool
+
org.mybatis.spring.boot
mybatis-spring-boot-starter