Skip to content

Commit

Permalink
增加支付订单查询接口
Browse files Browse the repository at this point in the history
  • Loading branch information
jmdhappy committed Sep 5, 2017
1 parent 2c1dc9f commit d2dd560
Show file tree
Hide file tree
Showing 8 changed files with 290 additions and 22 deletions.
36 changes: 33 additions & 3 deletions xxpay-shop/src/main/java/org/xxpay/shop/demo/PayOrderDemo.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ public class PayOrderDemo {
// 验签key
static final String repKey = "Hpcl522AV6q613KIi46u6g6XuW8vM1N8bFgyv769770MdYe9u37M4y7rIpl8";

static final String baseUrl = "http://api.xxpay.org/api";
//static final String baseUrl = "http://localhost:3020/api";
//static final String baseUrl = "http://api.xxpay.org/api";
static final String baseUrl = "http://localhost:3020/api";
static final String notifyUrl = "http://www.baidu.com"; // 本地环境测试,可到ngrok.cc网站注册

public static void main(String[] args) {
payOrderTest();
//payOrderTest();
quryPayOrderTest("1494774484058", "P0020170514230805000000");
}

// 统一下单
Expand Down Expand Up @@ -79,4 +80,33 @@ static String payOrderTest() {
return retMap.get("payOrderId")+"";
}

static String quryPayOrderTest(String mchOrderNo, String payOrderId) {
JSONObject paramMap = new JSONObject();
paramMap.put("mchId", mchId); // 商户ID
paramMap.put("mchOrderNo", mchOrderNo); // 商户订单号
paramMap.put("payOrderId", payOrderId); // 支付订单号
paramMap.put("executeNotify", "false"); // 是否执行回调,true或false,如果为true当订单状态为支付成功(2)时,支付中心会再次回调一次业务系统

String reqSign = PayDigestUtil.getSign(paramMap, reqKey);
paramMap.put("sign", reqSign); // 签名
String reqData = "params=" + paramMap.toJSONString();
System.out.println("请求支付中心查单接口,请求数据:" + reqData);
String url = baseUrl + "/pay/query_order?";
String result = XXPayUtil.call4Post(url + reqData);
System.out.println("请求支付中心查单接口,响应数据:" + result);
Map retMap = JSON.parseObject(result);
if("SUCCESS".equals(retMap.get("retCode")) && "SUCCESS".equalsIgnoreCase(retMap.get("resCode").toString())) {
// 验签
String checkSign = PayDigestUtil.getSign(retMap, repKey, "sign", "payParams");
String retSign = (String) retMap.get("sign");
if(checkSign.equals(retSign)) {
System.out.println("=========支付中心查单验签成功=========");
}else {
System.err.println("=========支付中心查单验签失败=========");
return null;
}
}
return retMap.get("payOrderId")+"";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public boolean doPage(PayOrder payOrder, HttpServletResponse response) {
}
return true;
}

/**
* 处理支付结果后台服务器通知
*/
Expand All @@ -111,16 +111,6 @@ public void doNotify(PayOrder payOrder) {
} catch (Exception e) {
_log.error("payOrderId={},sendMessage error.", payOrder != null ? payOrder.getPayOrderId() : "", e);
}
/*// 响应给支付公司
_log.info("payOrderId={},channelId={},响应支付公司结果:{}", payOrder != null ? payOrder.getPayOrderId() : "", payOrder != null ? payOrder.getChannelId() : "", message);
response.setContentType("text/html");
PrintWriter pw;
try {
pw = response.getWriter();
pw.print(message);
} catch (IOException e) {
_log.error("Pay response write exception.", e);
}*/
_log.info(">>>>>> PAY回调通知业务系统完成 <<<<<<");
}

Expand All @@ -129,7 +119,7 @@ public JSONObject createNotifyInfo(PayOrder payOrder) {
object.put("method", "GET");
object.put("url", createNotifyUrl(payOrder, "2"));
object.put("orderId", payOrder.getPayOrderId());
object.put("count", 0);
object.put("count", payOrder.getNotifyCount());
object.put("createTime", System.currentTimeMillis());
return object;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.xxpay.common.constant.PayConstant;
import org.xxpay.common.util.MyBase64;
import org.xxpay.common.util.MyLog;
import org.xxpay.dal.dao.model.PayOrder;
Expand All @@ -20,7 +21,7 @@
* @Copyright: www.xxpay.org
*/
@RestController
public class PayOrderServiceController {
public class PayOrderServiceController extends Notify4BasePay {

private final MyLog _log = MyLog.getLog(PayOrderServiceController.class);

Expand Down Expand Up @@ -48,4 +49,41 @@ public String createPayOrder(@RequestParam String jsonParam) {
return retObj.toJSONString();
}

@RequestMapping(value = "/pay/query")
public String queryPayOrder(@RequestParam String jsonParam) {
_log.info("selectPayOrder << {}", jsonParam);
JSONObject retObj = new JSONObject();
retObj.put("code", "0000");
if(StringUtils.isBlank(jsonParam)) {
retObj.put("code", "0001"); // 参数错误
retObj.put("msg", "缺少参数");
return retObj.toJSONString();
}
JSONObject paramObj = JSON.parseObject(new String(MyBase64.decode(jsonParam)));
String mchId = paramObj.getString("mchId");
String payOrderId = paramObj.getString("payOrderId");
String mchOrderNo = paramObj.getString("mchOrderNo");
PayOrder payOrder;
if(StringUtils.isNotBlank(payOrderId)) {
payOrder = payOrderService.selectPayOrderByMchIdAndPayOrderId(mchId, payOrderId);
}else {
payOrder = payOrderService.selectPayOrderByMchIdAndMchOrderNo(mchId, mchOrderNo);
}
if(payOrder == null) {
retObj.put("code", "0002");
retObj.put("msg", "支付订单不存在");
return retObj.toJSONString();
}

//
boolean executeNotify = paramObj.getBooleanValue("executeNotify");
// 如果选择回调且支付状态为支付成功,则回调业务系统
if(executeNotify && payOrder.getStatus() == PayConstant.PAY_STATUS_SUCCESS) {
this.doNotify(payOrder);
}
retObj.put("result", JSON.toJSON(payOrder));
_log.info("selectPayOrder >> {}", retObj);
return retObj.toJSONString();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -169,17 +169,18 @@ public void receive(String msg) {
// 通知失败,延时再通知
int cnt = count+1;
_log.info("notify count={}", cnt);
if (cnt > 5) {
_log.info("notify count>5 stop. url={}", respUrl);
return ;
}
// 修改通知次数
try {
int result = payOrderService.updateNotify(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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.xxpay.common.constant.PayConstant;
import org.xxpay.dal.dao.mapper.PayOrderMapper;
import org.xxpay.dal.dao.model.PayOrder;
import org.xxpay.dal.dao.model.PayOrderExample;

import java.util.List;

/**
* @Description:
* @author dingzhiwei [email protected]
Expand All @@ -28,6 +31,24 @@ public PayOrder selectPayOrder(String payOrderId) {
return payOrderMapper.selectByPrimaryKey(payOrderId);
}

public PayOrder selectPayOrderByMchIdAndPayOrderId(String mchId, String payOrderId) {
PayOrderExample example = new PayOrderExample();
PayOrderExample.Criteria criteria = example.createCriteria();
criteria.andMchIdEqualTo(mchId);
criteria.andPayOrderIdEqualTo(payOrderId);
List<PayOrder> payOrderList = payOrderMapper.selectByExample(example);
return CollectionUtils.isEmpty(payOrderList) ? null : payOrderList.get(0);
}

public PayOrder selectPayOrderByMchIdAndMchOrderNo(String mchId, String mchOrderNo) {
PayOrderExample example = new PayOrderExample();
PayOrderExample.Criteria criteria = example.createCriteria();
criteria.andMchIdEqualTo(mchId);
criteria.andMchOrderNoEqualTo(mchOrderNo);
List<PayOrder> payOrderList = payOrderMapper.selectByExample(example);
return CollectionUtils.isEmpty(payOrderList) ? null : payOrderList.get(0);
}

public int updateStatus4Ing(String payOrderId, String channelOrderNo) {
PayOrder payOrder = new PayOrder();
payOrder.setStatus(PayConstant.PAY_STATUS_PAYING);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ public String payOrder(@RequestParam String params) {
String logPrefix = "【商户统一下单】";
ServiceInstance instance = client.getLocalServiceInstance();
_log.info("{}/pay/create_order, host:{}, service_id:{}, params:{}", logPrefix, instance.getHost(), instance.getServiceId(), params);
JSONObject po = JSONObject.parseObject(params);
JSONObject payOrder = null;
try {
JSONObject po = JSONObject.parseObject(params);
JSONObject payOrder = null;
// 验证参数有效性
Object object = validateParams(po);
if (object instanceof String) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package org.xxpay.web.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.xxpay.common.constant.PayConstant;
import org.xxpay.common.util.MyLog;
import org.xxpay.common.util.XXPayUtil;
import org.xxpay.web.service.MchInfoServiceClient;
import org.xxpay.web.service.PayOrderServiceClient;

import java.util.Map;

/**
* @Description: 支付订单查询
* @author dingzhiwei [email protected]
* @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 DiscoveryClient client;

@Autowired
private PayOrderServiceClient payOrderServiceClient;

@Autowired
private MchInfoServiceClient mchInfoServiceClient;

/**
* 查询支付订单接口:
* 1)先验证接口参数以及签名信息
* 2)根据参数查询订单
* 3)返回订单数据
* @param params
* @return
*/
@RequestMapping(value = "/pay/query_order")
public String queryPayOrder(@RequestParam String params) {
_log.info("###### 开始接收商户查询支付订单请求 ######");
String logPrefix = "【商户支付订单查询】";
ServiceInstance instance = client.getLocalServiceInstance();
_log.info("{}/pay/query_order, host:{}, service_id:{}, params:{}", logPrefix, instance.getHost(), instance.getServiceId(), params);
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;
String retStr = payOrderServiceClient.queryPayOrder(getJsonParam(new String[]{"mchId", "payOrderId", "mchOrderNo", "executeNotify"}, new Object[]{mchId, payOrderId, mchOrderNo, executeNotify}));
JSONObject retObj = JSON.parseObject(retStr);
_log.info("{}查询支付订单,结果:{}", logPrefix, retObj);
if(!"0000".equals(retObj.getString("code"))) {
return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, retObj.getString("msg"), null, null));
}
payOrder = retObj.getJSONObject("result");
if (payOrder == null) {
return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "支付订单不存在", null, null));
}
Map<String, Object> map = XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null);
map.put("result", payOrder);
_log.info("商户查询订单成功,payOrder={}", 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;
String retStr = mchInfoServiceClient.selectMchInfo(getJsonParam("mchId", mchId));

JSONObject retObj = JSON.parseObject(retStr);
if("0000".equals(retObj.getString("code"))) {
mchInfo = retObj.getJSONObject("result");
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;
}
}else {
errorMessage = "Can't found mchInfo[mchId="+mchId+"] record in db.";
_log.info("查询商户没有正常返回数据,code={},msg={}", retObj.getString("code"), retObj.getString("msg"));
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";
}

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();
}

}
Loading

0 comments on commit d2dd560

Please sign in to comment.