Skip to content

Commit

Permalink
Merge pull request jeequan#4 in SOUNDPAYMENT/xxpay from feature/refun…
Browse files Browse the repository at this point in the history
…d to master

* commit '01b9e56e61ed23e4e8450221654742b13ec7fdf5':
  修改MCH_REFUND_NOTIFY_QUEUE_NAME 为 mch.refund.notify.queue
  springboot版更新列表 1.添加退款支持 2.添加支付添加商户通知 3.添加商户通知手动发送接口 4.添加logback日志
  • Loading branch information
崔博雯 committed Apr 20, 2018
2 parents 801fb66 + 01b9e56 commit d7d8c17
Show file tree
Hide file tree
Showing 28 changed files with 1,948 additions and 97 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
/log/
target/
*.project
*log/
*logs/


### STS ###
Expand All @@ -11,4 +13,4 @@ target/
.factorypath
.project
.settings
.springBeans
.springBeans
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package org.xxpay.boot.ctrl;

import java.io.IOException;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

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.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.xxpay.boot.service.impl.MchInfoServiceImpl;
import org.xxpay.boot.service.mq.Mq4PayNotify;
import org.xxpay.boot.service.mq.Mq4RefundNotify;
import org.xxpay.common.constant.PayConstant;
import org.xxpay.common.util.MyLog;
import org.xxpay.common.util.XXPayUtil;
import org.xxpay.dal.dao.model.MchNotify;

import com.alibaba.fastjson.JSON;

/**
* @Description: 手动发送通知
* @author dingzhiwei [email protected]
* @date 2017-07-05
* @version V1.0
* @Copyright: www.xxpay.org
*/
@RestController
public class ManualSendNotifyController {

private static final MyLog _log = MyLog.getLog(ManualSendNotifyController.class);

@Autowired
private Mq4PayNotify mq4PayNotify;

@Autowired
private Mq4RefundNotify mq4RefundNotify;

@Autowired
private MchInfoServiceImpl mchInfoServiceImpl;

/**
* 统一手动发送通知
* @param request
* @param orderId
* @return
* @throws ServletException
* @throws IOException
*/
@RequestMapping("/manual/send/notify")
@ResponseBody
public String manualSendNotify(HttpServletRequest request, String orderId, Long count) throws ServletException, IOException {
_log.info("====== 开始手动发送通知 ======");
MchNotify mchNotify = mchInfoServiceImpl.baseSelectMchNotify(orderId);
if (mchNotify == null) {
return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "商户通知不存在", null, null));
}
if(StringUtils.isBlank(mchNotify.getNotifyUrl())){
return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "商户通知NotiryUrl不能为空", null, null));
}
Map notifyUrlMap = JSON.parseObject(mchNotify.getNotifyUrl());
notifyUrlMap.put("count", (count-2) < 0 ? 0 : (count-2));
if(PayConstant.MCH_NOTIFY_TYPE_PAY.equals(mchNotify.getOrderType())) {
mq4PayNotify.send(notifyUrlMap.toString());
}
if(PayConstant.MCH_NOTIFY_TYPE_REFUND.equals(mchNotify.getOrderType())) {
mq4RefundNotify.send(notifyUrlMap.toString());
}
_log.info("====== 完成手动发送通知 ======");
return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "手动通知发送成功", null, null));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
package org.xxpay.boot.ctrl;

import java.util.Map;

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.service.IMchInfoService;
import org.xxpay.boot.service.IPayChannelService;
import org.xxpay.boot.service.IPayOrderService;
import org.xxpay.boot.service.IRefundOrderService;
import org.xxpay.common.constant.PayConstant;
import org.xxpay.common.util.MyLog;
import org.xxpay.common.util.MySeq;
import org.xxpay.common.util.XXPayUtil;

import com.alibaba.fastjson.JSONObject;

/**
* @Description: 订单退款
* @author dingzhiwei [email protected]
* @date 2017-10-30
* @version V1.0
* @Copyright: www.xxpay.org
*/
@RestController
public class RefundOrderController {

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

@Autowired
private IRefundOrderService refundOrderService;

@Autowired
private IPayOrderService payOrderService;

@Autowired
private IPayChannelService payChannelService;

@Autowired
private IMchInfoService mchInfoService;

/**
* 统一退款接口:
* 1)先验证接口参数以及签名信息
* 2)验证通过创建退款订单
* 3)根据商户选择渠道,调用退款服务进行退单
* 4)返回退单数据
* @param params
* @return
*/
@RequestMapping(value = "/api/refund/create_order")
public String payOrder(@RequestParam String params) {
_log.info("###### 开始接收商户统一退款请求 ######");
String logPrefix = "【商户统一退款】";
try {
JSONObject po = JSONObject.parseObject(params);
JSONObject refundContext = new JSONObject();
JSONObject refundOrder = null;
// 验证参数有效性
Object object = validateParams(po, refundContext);
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) refundOrder = (JSONObject) object;
if(refundOrder == null) return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "支付中心退款失败", null, null));
int result = refundOrderService.createRefundOrder(refundOrder);
_log.info("{}创建退款订单,结果:{}", logPrefix, result);
if(result != 1) {
return XXPayUtil.makeRetFail(XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_FAIL, "创建退款订单失败", null, null));
}
// 发送异步退款消息
String refundOrderId = refundOrder.getString("refundOrderId");
String channelName = refundContext.getString("channelName");
refundOrderService.sendRefundNotify(refundOrderId, channelName);
_log.info("{}发送退款任务完成,transOrderId={}", logPrefix, refundOrderId);

Map<String, Object> map = XXPayUtil.makeRetMap(PayConstant.RETURN_VALUE_SUCCESS, "", PayConstant.RETURN_VALUE_SUCCESS, null);
map.put("refundOrderId", refundOrder.getString("refundOrderId"));
return XXPayUtil.makeRetData(map, refundContext.getString("resKey"));
}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 refundContext) {
// 验证请求参数,参数有问题返回错误提示
String errorMessage;
// 退款参数
String mchId = params.getString("mchId"); // 商户ID
String payOrderId = params.getString("payOrderId"); // 支付订单号
String mchOrderNo = params.getString("mchOrderNo"); // 商户支付单号
String mchRefundNo = params.getString("mchRefundNo"); // 商户退款单号
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 channelUser = params.getString("channelUser"); // 渠道用户标识,如微信openId,支付宝账号
String userName = params.getString("userName"); // 用户姓名
String remarkInfo = params.getString("remarkInfo"); // 备注
// 验证请求参数有效性(必选项)
if(StringUtils.isBlank(mchId)) {
errorMessage = "request params[mchId] error.";
return errorMessage;
}
if(StringUtils.isBlank(payOrderId) && StringUtils.isBlank(mchOrderNo)) {
errorMessage = "request params[payOrderId,mchOrderNo] error.";
return errorMessage;
}
if(StringUtils.isBlank(mchRefundNo)) {
errorMessage = "request params[mchRefundNo] 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(channelUser)) {
errorMessage = "request params[channelUser] 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;
}
refundContext.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;
}
refundContext.put("channelName", payChannel.getString("channelName"));

// 验证签名数据
boolean verifyFlag = XXPayUtil.verifyPaySign(params, reqKey);
if(!verifyFlag) {
errorMessage = "Verify XX refund sign failed.";
return errorMessage;
}

// 验证支付订单是否存在
JSONObject payOrder = payOrderService.query(mchId, payOrderId, mchOrderNo, "false");
if(payOrder == null) {
errorMessage = "payOrder is not exist.";
return errorMessage;
}

String channelPayOrderNo = payOrder.getString("channelOrderNo"); // 渠道测支付单号
Long payAmount = payOrder.getLong("amount");

// 验证参数通过,返回JSONObject对象
JSONObject refundOrder = new JSONObject();
refundOrder.put("refundOrderId", MySeq.getRefund());
refundOrder.put("payOrderId", payOrderId);
refundOrder.put("channelPayOrderNo", channelPayOrderNo);
refundOrder.put("mchId", mchId);
refundOrder.put("mchRefundNo", mchRefundNo);
refundOrder.put("channelId", channelId);
refundOrder.put("refundAmount", Long.parseLong(amount)); // 退款金额
refundOrder.put("payAmount", payAmount); // 退款金额
refundOrder.put("currency", currency);
refundOrder.put("clientIp", clientIp);
refundOrder.put("device", device);
refundOrder.put("channelUser", channelUser);
refundOrder.put("userName", userName);
refundOrder.put("remarkInfo", remarkInfo);
refundOrder.put("extra", extra);
refundOrder.put("channelMchId", payChannel.getString("channelMchId"));
refundOrder.put("param1", param1);
refundOrder.put("param2", param2);
refundOrder.put("notifyUrl", notifyUrl);
return refundOrder;
}

}
Loading

0 comments on commit d7d8c17

Please sign in to comment.