From 6631dab53049690b965022ebe2fe0b2bd402f6a5 Mon Sep 17 00:00:00 2001 From: yangyz Date: Fri, 20 Apr 2018 15:29:20 +0800 Subject: [PATCH] =?UTF-8?q?springboot=E7=89=88=E6=9B=B4=E6=96=B0=E5=88=97?= =?UTF-8?q?=E8=A1=A8=201.=E6=B7=BB=E5=8A=A0=E9=80=80=E6=AC=BE=E6=94=AF?= =?UTF-8?q?=E6=8C=81=202.=E6=B7=BB=E5=8A=A0=E6=94=AF=E4=BB=98=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=95=86=E6=88=B7=E9=80=9A=E7=9F=A5=203.=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E5=95=86=E6=88=B7=E9=80=9A=E7=9F=A5=E6=89=8B=E5=8A=A8?= =?UTF-8?q?=E5=8F=91=E9=80=81=E6=8E=A5=E5=8F=A3=204.=E6=B7=BB=E5=8A=A0logb?= =?UTF-8?q?ack=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 +- .../boot/ctrl/ManualSendNotifyController.java | 76 +++++ .../boot/ctrl/RefundOrderController.java | 228 +++++++++++++++ .../org/xxpay/boot/service/BaseService.java | 171 ++++++++++- .../xxpay/boot/service/IMchNotifyService.java | 14 + .../boot/service/IPayChannel4AliService.java | 2 + .../boot/service/IPayChannel4WxService.java | 2 + .../xxpay/boot/service/IPayOrderService.java | 6 + .../boot/service/IRefundOrderService.java | 33 +++ .../xxpay/boot/service/Notify4BasePay.java | 37 ++- .../xxpay/boot/service/Notify4BaseRefund.java | 118 ++++++++ .../boot/service/impl/MchInfoServiceImpl.java | 42 +-- .../service/impl/MchNotifyServiceImpl.java | 56 ++++ .../service/impl/NotifyPayServiceImpl.java | 6 +- .../impl/PayChannel4AliServiceImpl.java | 91 +++++- .../impl/PayChannel4WxServiceImpl.java | 106 ++++++- .../service/impl/PayOrderServiceImpl.java | 69 +++++ .../service/impl/RefundOrderServiceImpl.java | 270 ++++++++++++++++++ .../boot/service/mq/Mq4MchRefundNotify.java | 159 +++++++++++ .../xxpay/boot/service/mq/Mq4PayNotify.java | 15 +- .../boot/service/mq/Mq4RefundNotify.java | 105 +++++++ .../org/xxpay/boot/service/mq/MqConfig.java | 32 ++- .../mq/impl/ActiveMq4MuchReundNotify.java | 58 ++++ .../service/mq/impl/ActiveMq4PayNotify.java | 5 - .../mq/impl/ActiveMq4RefundNotify.java | 58 ++++ .../mq/impl/RabbitMq4MuchRefundNotify.java | 64 +++++ .../mq/impl/RabbitMq4RefundNotify.java | 64 +++++ .../src/main/resources/logback.xml | 154 ++++++++++ 28 files changed, 1948 insertions(+), 97 deletions(-) create mode 100644 xxpay4spring-boot/src/main/java/org/xxpay/boot/ctrl/ManualSendNotifyController.java create mode 100644 xxpay4spring-boot/src/main/java/org/xxpay/boot/ctrl/RefundOrderController.java create mode 100644 xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IMchNotifyService.java create mode 100644 xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IRefundOrderService.java create mode 100644 xxpay4spring-boot/src/main/java/org/xxpay/boot/service/Notify4BaseRefund.java create mode 100644 xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/MchNotifyServiceImpl.java create mode 100644 xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/RefundOrderServiceImpl.java create mode 100644 xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/Mq4MchRefundNotify.java create mode 100644 xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/Mq4RefundNotify.java create mode 100644 xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/impl/ActiveMq4MuchReundNotify.java create mode 100644 xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/impl/ActiveMq4RefundNotify.java create mode 100644 xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/impl/RabbitMq4MuchRefundNotify.java create mode 100644 xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/impl/RabbitMq4RefundNotify.java create mode 100644 xxpay4spring-boot/src/main/resources/logback.xml diff --git a/.gitignore b/.gitignore index ad9bb13d..23b0c51d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ /log/ target/ *.project +*log/ +*logs/ ### STS ### @@ -11,4 +13,4 @@ target/ .factorypath .project .settings -.springBeans \ No newline at end of file +.springBeans diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/ctrl/ManualSendNotifyController.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/ctrl/ManualSendNotifyController.java new file mode 100644 index 00000000..aa388e23 --- /dev/null +++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/ctrl/ManualSendNotifyController.java @@ -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 jmdhappy@126.com + * @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)); + } + +} diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/ctrl/RefundOrderController.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/ctrl/RefundOrderController.java new file mode 100644 index 00000000..bbcf37f6 --- /dev/null +++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/ctrl/RefundOrderController.java @@ -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 jmdhappy@126.com + * @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 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; + } + +} 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 index 05322918..759bb3eb 100644 --- a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/BaseService.java +++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/BaseService.java @@ -1,15 +1,28 @@ package org.xxpay.boot.service; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; 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.MchNotifyMapper; import org.xxpay.dal.dao.mapper.PayChannelMapper; import org.xxpay.dal.dao.mapper.PayOrderMapper; -import org.xxpay.dal.dao.model.*; - -import java.util.List; +import org.xxpay.dal.dao.mapper.RefundOrderMapper; +import org.xxpay.dal.dao.model.MchInfo; +import org.xxpay.dal.dao.model.MchNotify; +import org.xxpay.dal.dao.model.MchNotifyExample; +import org.xxpay.dal.dao.model.PayChannel; +import org.xxpay.dal.dao.model.PayChannelExample; +import org.xxpay.dal.dao.model.PayOrder; +import org.xxpay.dal.dao.model.PayOrderExample; +import org.xxpay.dal.dao.model.RefundOrder; +import org.xxpay.dal.dao.model.RefundOrderExample; /** * @author: dingzhiwei @@ -27,6 +40,12 @@ public class BaseService { @Autowired private PayChannelMapper payChannelMapper; + + @Autowired + private RefundOrderMapper refundOrderMapper; + + @Autowired + private MchNotifyMapper mchNotifyMapper; public MchInfo baseSelectMchInfo(String mchId) { @@ -116,5 +135,151 @@ public int baseUpdateNotify(String payOrderId, byte count) { public int baseUpdateNotify(PayOrder payOrder) { return payOrderMapper.updateByPrimaryKeySelective(payOrder); } + + public int baseCreateRefundOrder(RefundOrder refundOrder) { + return refundOrderMapper.insertSelective(refundOrder); + } + + public RefundOrder baseSelectRefundOrder(String refundOrderId) { + return refundOrderMapper.selectByPrimaryKey(refundOrderId); + } + + public RefundOrder baseSelectByMchIdAndRefundOrderId(String mchId, String refundOrderId) { + RefundOrderExample example = new RefundOrderExample(); + RefundOrderExample.Criteria criteria = example.createCriteria(); + criteria.andMchIdEqualTo(mchId); + criteria.andRefundOrderIdEqualTo(refundOrderId); + List refundOrderList = refundOrderMapper.selectByExample(example); + return CollectionUtils.isEmpty(refundOrderList) ? null : refundOrderList.get(0); + } + + public RefundOrder baseSelectByMchIdAndMchRefundNo(String mchId, String mchRefundNo) { + RefundOrderExample example = new RefundOrderExample(); + RefundOrderExample.Criteria criteria = example.createCriteria(); + criteria.andMchIdEqualTo(mchId); + criteria.andMchRefundNoEqualTo(mchRefundNo); + List refundOrderList = refundOrderMapper.selectByExample(example); + return CollectionUtils.isEmpty(refundOrderList) ? null : refundOrderList.get(0); + } + + public int baseUpdateStatus4IngByRefund(String refundOrderId, String channelOrderNo) { + RefundOrder refundOrder = new RefundOrder(); + refundOrder.setStatus(PayConstant.REFUND_STATUS_REFUNDING); + if(channelOrderNo != null) refundOrder.setChannelOrderNo(channelOrderNo); + refundOrder.setRefundSuccTime(new Date()); + RefundOrderExample example = new RefundOrderExample(); + RefundOrderExample.Criteria criteria = example.createCriteria(); + criteria.andRefundOrderIdEqualTo(refundOrderId); + criteria.andStatusEqualTo(PayConstant.REFUND_STATUS_INIT); + return refundOrderMapper.updateByExampleSelective(refundOrder, example); + } + public int baseUpdateStatus4SuccessByRefund(String refundOrderId) { + return baseUpdateStatus4Success(refundOrderId, null); + } + + public int baseUpdateStatus4SuccessByRefund(String refundOrderId, String channelOrderNo) { + RefundOrder refundOrder = new RefundOrder(); + refundOrder.setRefundOrderId(refundOrderId); + refundOrder.setStatus(PayConstant.REFUND_STATUS_SUCCESS); + refundOrder.setResult(PayConstant.REFUND_RESULT_SUCCESS); + refundOrder.setRefundSuccTime(new Date()); + if(StringUtils.isNotBlank(channelOrderNo)) refundOrder.setChannelOrderNo(channelOrderNo); + RefundOrderExample example = new RefundOrderExample(); + RefundOrderExample.Criteria criteria = example.createCriteria(); + criteria.andRefundOrderIdEqualTo(refundOrderId); + criteria.andStatusEqualTo(PayConstant.REFUND_STATUS_REFUNDING); + return refundOrderMapper.updateByExampleSelective(refundOrder, example); + } + + public int baseUpdateStatus4CompleteByRefund(String refundOrderId) { + RefundOrder refundOrder = new RefundOrder(); + refundOrder.setRefundOrderId(refundOrderId); + refundOrder.setStatus(PayConstant.REFUND_STATUS_COMPLETE); + RefundOrderExample example = new RefundOrderExample(); + RefundOrderExample.Criteria criteria = example.createCriteria(); + criteria.andRefundOrderIdEqualTo(refundOrderId); + List values = CollectionUtils.arrayToList(new Byte[] { + PayConstant.REFUND_STATUS_SUCCESS, PayConstant.REFUND_STATUS_FAIL + }); + criteria.andStatusIn(values); + return refundOrderMapper.updateByExampleSelective(refundOrder, example); + } + + public int baseUpdateStatus4FailByRefund(String refundOrderId, String channelErrCode, String channelErrMsg) { + RefundOrder refundOrder = new RefundOrder(); + refundOrder.setStatus(PayConstant.REFUND_STATUS_FAIL); + refundOrder.setResult(PayConstant.REFUND_RESULT_FAIL); + if(channelErrCode != null) refundOrder.setChannelErrCode(channelErrCode); + if(channelErrMsg != null) refundOrder.setChannelErrMsg(channelErrMsg); + RefundOrderExample example = new RefundOrderExample(); + RefundOrderExample.Criteria criteria = example.createCriteria(); + criteria.andRefundOrderIdEqualTo(refundOrderId); + criteria.andStatusEqualTo(PayConstant.REFUND_STATUS_REFUNDING); + return refundOrderMapper.updateByExampleSelective(refundOrder, example); + } + + public PayOrder baseSelectByMchIdAndPayOrderId(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 baseSelectByMchIdAndMchOrderNo(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 baseInsertMchNotify(String orderId, String mchId, String mchOrderNo, String orderType, String notifyUrl) { + MchNotify mchNotify = new MchNotify(); + mchNotify.setOrderId(orderId); + mchNotify.setMchId(mchId); + mchNotify.setMchOrderNo(mchOrderNo); + mchNotify.setOrderType(orderType); + mchNotify.setNotifyUrl(notifyUrl); + return mchNotifyMapper.insertSelectiveOnDuplicateKeyUpdate(mchNotify); + } + + public MchNotify baseSelectMchNotify(String orderId) { + return mchNotifyMapper.selectByPrimaryKey(orderId); + } + + public int baseUpdateMchNotifySuccess(String orderId, String result, byte notifyCount) { + MchNotify mchNotify = new MchNotify(); + mchNotify.setStatus(PayConstant.MCH_NOTIFY_STATUS_SUCCESS); + mchNotify.setResult(result); + mchNotify.setNotifyCount(notifyCount); + mchNotify.setLastNotifyTime(new Date()); + MchNotifyExample example = new MchNotifyExample(); + MchNotifyExample.Criteria criteria = example.createCriteria(); + criteria.andOrderIdEqualTo(orderId); + List values = new LinkedList<>(); + values.add(PayConstant.MCH_NOTIFY_STATUS_NOTIFYING); + values.add(PayConstant.MCH_NOTIFY_STATUS_FAIL); + criteria.andStatusIn(values); + return mchNotifyMapper.updateByExampleSelective(mchNotify, example); + } + + public int baseUpdateMchNotifyFail(String orderId, String result, byte notifyCount) { + MchNotify mchNotify = new MchNotify(); + mchNotify.setStatus(PayConstant.MCH_NOTIFY_STATUS_FAIL); + mchNotify.setResult(result); + mchNotify.setNotifyCount(notifyCount); + mchNotify.setLastNotifyTime(new Date()); + MchNotifyExample example = new MchNotifyExample(); + MchNotifyExample.Criteria criteria = example.createCriteria(); + criteria.andOrderIdEqualTo(orderId); + List values = new LinkedList<>(); + values.add(PayConstant.MCH_NOTIFY_STATUS_NOTIFYING); + values.add(PayConstant.MCH_NOTIFY_STATUS_FAIL); + return mchNotifyMapper.updateByExampleSelective(mchNotify, example); + } + } diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IMchNotifyService.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IMchNotifyService.java new file mode 100644 index 00000000..2f2beecd --- /dev/null +++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IMchNotifyService.java @@ -0,0 +1,14 @@ +package org.xxpay.boot.service; + +import org.xxpay.dal.dao.model.MchNotify; + +/** + * @author: dingzhiwei + * @date: 17/9/8 + * @description: + */ +public interface IMchNotifyService { + + MchNotify baseSelectMchNotify(String orderId); + +} 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 index 535bb0bb..d652be2a 100644 --- a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IPayChannel4AliService.java +++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IPayChannel4AliService.java @@ -16,5 +16,7 @@ public interface IPayChannel4AliService { Map doAliPayMobileReq(String jsonParam); Map doAliPayQrReq(String jsonParam); + + Map doAliRefundReq(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 index c0078030..4b1cfd30 100644 --- a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IPayChannel4WxService.java +++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IPayChannel4WxService.java @@ -11,4 +11,6 @@ public interface IPayChannel4WxService { Map doWxPayReq(String jsonParam); + Map doWxRefundReq(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 index 690de23c..5580f467 100644 --- a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IPayOrderService.java +++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IPayOrderService.java @@ -34,5 +34,11 @@ public interface IPayOrderService { String doWxPayReq(String tradeType, JSONObject payOrder, String resKey); String doAliPayReq(String channelId, JSONObject payOrder, String resKey); + + Map selectByMchIdAndPayOrderId(String jsonParam); + + Map selectByMchIdAndMchOrderNo(String jsonParam); + + JSONObject query(String mchId, String payOrderId, String mchOrderNo, String executeNotify); } diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IRefundOrderService.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IRefundOrderService.java new file mode 100644 index 00000000..6f459303 --- /dev/null +++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/IRefundOrderService.java @@ -0,0 +1,33 @@ +package org.xxpay.boot.service; + +import java.util.Map; + +import com.alibaba.fastjson.JSONObject; + +/** + * @author: dingzhiwei + * @date: 17/10/26 + * @description: 退款业务 + */ +public interface IRefundOrderService { + + Map create(String jsonParam); + + Map select(String jsonParam); + + Map selectByMchIdAndRefundOrderId(String jsonParam); + + Map selectByMchIdAndMchRefundNo(String jsonParam); + + Map updateStatus4Ing(String jsonParam); + + Map updateStatus4Success(String jsonParam); + + Map updateStatus4Complete(String jsonParam); + + // Map sendRefundNotify(String jsonParam); + void sendRefundNotify(String refundOrderId, String channelName); + + int createRefundOrder(JSONObject refundOrder); + +} 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 index f215e2d4..98de73c2 100644 --- a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/Notify4BasePay.java +++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/Notify4BasePay.java @@ -1,20 +1,22 @@ package org.xxpay.boot.service; -import com.alibaba.fastjson.JSONObject; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Map; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.xxpay.boot.service.mq.Mq4PayNotify; 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.MchNotify; 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; +import com.alibaba.fastjson.JSONObject; /** * @Description: 支付通知处理基类 @@ -95,10 +97,10 @@ public boolean doPage(PayOrder payOrder) { /** * 处理支付结果后台服务器通知 */ - public void doNotify(PayOrder payOrder) { + public void doNotify(PayOrder payOrder, boolean isFirst) { _log.info(">>>>>> PAY开始回调通知业务系统 <<<<<<"); // 发起后台通知业务系统 - JSONObject object = createNotifyInfo(payOrder); + JSONObject object = createNotifyInfo(payOrder, isFirst); try { mq4PayNotify.send(object.toJSONString()); } catch (Exception e) { @@ -107,13 +109,26 @@ public void doNotify(PayOrder payOrder) { _log.info(">>>>>> PAY回调通知业务系统完成 <<<<<<"); } - public JSONObject createNotifyInfo(PayOrder payOrder) { + public JSONObject createNotifyInfo(PayOrder payOrder,boolean isFirst) { + + String url = createNotifyUrl(payOrder, "2"); JSONObject object = new JSONObject(); object.put("method", "GET"); - object.put("url", createNotifyUrl(payOrder, "2")); + object.put("url", url); object.put("orderId", payOrder.getPayOrderId()); - object.put("count", payOrder.getNotifyCount()); + object.put("count", 0); object.put("createTime", System.currentTimeMillis()); + + if(isFirst) { + int result = baseInsertMchNotify(payOrder.getPayOrderId(), payOrder.getMchId(), payOrder.getMchOrderNo(), PayConstant.MCH_NOTIFY_TYPE_PAY, object.toString()); + _log.info("增加商户通知记录,orderId={},result:{}", payOrder.getPayOrderId(), result); + } + /*int count = 0; + if(!isFirst) { + MchNotify mchNotify = baseSelectMchNotify(payOrder.getPayOrderId()); + if(mchNotify != null) count = mchNotify.getNotifyCount(); + }*/ + return object; } diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/Notify4BaseRefund.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/Notify4BaseRefund.java new file mode 100644 index 00000000..6f82ad43 --- /dev/null +++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/Notify4BaseRefund.java @@ -0,0 +1,118 @@ +package org.xxpay.boot.service; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.lang3.ObjectUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.xxpay.boot.service.mq.Mq4MchRefundNotify; +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.MchNotify; +import org.xxpay.dal.dao.model.RefundOrder; + +import com.alibaba.fastjson.JSONObject; + +/** + * @Description: 商户转账通知处理基类 + * @author dingzhiwei jmdhappy@126.com + * @date 2017-11-01 + * @version V1.0 + * @Copyright: www.xxpay.org + */ +@Component +public class Notify4BaseRefund extends BaseService { + + private static final MyLog _log = MyLog.getLog(Notify4BaseRefund.class); + + @Autowired + private Mq4MchRefundNotify mq4MchRefundNotify; + + /** + * 创建响应URL + * @param refundOrder + * @param backType 1:前台页面;2:后台接口 + * @return + */ + public String createNotifyUrl(RefundOrder refundOrder, String backType) { + String mchId = refundOrder.getMchId(); + MchInfo mchInfo = super.baseSelectMchInfo(mchId); + String resKey = mchInfo.getResKey(); + Map paramMap = new HashMap<>(); + paramMap.put("refundOrderId", ObjectUtils.defaultIfNull(refundOrder.getRefundOrderId(), "")); // 退款订单号 + paramMap.put("mchId", ObjectUtils.defaultIfNull(refundOrder.getMchId(), "")); // 商户ID + paramMap.put("mchOrderNo", ObjectUtils.defaultIfNull(refundOrder.getMchRefundNo(), "")); // 商户订单号 + paramMap.put("channelId", ObjectUtils.defaultIfNull(refundOrder.getChannelId(), "")); // 渠道ID + paramMap.put("refundAmount", ObjectUtils.defaultIfNull(refundOrder.getRefundAmount(), "")); // 退款金额 + paramMap.put("currency", ObjectUtils.defaultIfNull(refundOrder.getCurrency(), "")); // 货币类型 + paramMap.put("status", ObjectUtils.defaultIfNull(refundOrder.getStatus(), "")); // 退款状态 + paramMap.put("result", ObjectUtils.defaultIfNull(refundOrder.getResult(), "")); // 退款结果 + paramMap.put("clientIp", ObjectUtils.defaultIfNull(refundOrder.getClientIp(), "")); // 客户端IP + paramMap.put("device", ObjectUtils.defaultIfNull(refundOrder.getDevice(), "")); // 设备 + paramMap.put("channelOrderNo", ObjectUtils.defaultIfNull(refundOrder.getChannelOrderNo(), "")); // 渠道订单号 + paramMap.put("param1", ObjectUtils.defaultIfNull(refundOrder.getParam1(), "")); // 扩展参数1 + paramMap.put("param2", ObjectUtils.defaultIfNull(refundOrder.getParam2(), "")); // 扩展参数2 + paramMap.put("refundSuccTime", ObjectUtils.defaultIfNull(refundOrder.getRefundSuccTime(), "")); // 退款成功时间 + paramMap.put("backType", backType==null ? "" : backType); + // 先对原文签名 + String reqSign = PayDigestUtil.getSign(paramMap, resKey); + paramMap.put("sign", reqSign); // 签名 + // 签名后再对有中文参数编码 + try { + paramMap.put("device", URLEncoder.encode(ObjectUtils.defaultIfNull(refundOrder.getDevice(), ""), PayConstant.RESP_UTF8)); + paramMap.put("param1", URLEncoder.encode(ObjectUtils.defaultIfNull(refundOrder.getParam1(), ""), PayConstant.RESP_UTF8)); + paramMap.put("param2", URLEncoder.encode(ObjectUtils.defaultIfNull(refundOrder.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(refundOrder.getNotifyUrl()).append("?").append(param); + return sb.toString(); + } + + /** + * 处理商户退款后台服务器通知 + */ + public void doNotify(RefundOrder refundOrder, boolean isFirst) { + _log.info(">>>>>> REFUND开始回调通知业务系统 <<<<<<"); + // 发起后台通知业务系统 + JSONObject object = createNotifyInfo(refundOrder, isFirst); + try { + mq4MchRefundNotify.send(object.toJSONString()); + } catch (Exception e) { + _log.error(e, "refundOrderId=%s,sendMessage error.", ObjectUtils.defaultIfNull(refundOrder.getRefundOrderId(), "")); + } + _log.info(">>>>>> REFUND回调通知业务系统完成 <<<<<<"); + } + + public JSONObject createNotifyInfo(RefundOrder refundOrder, boolean isFirst) { + + String url = createNotifyUrl(refundOrder, "2"); + JSONObject object = new JSONObject(); + object.put("method", "GET"); + object.put("url", url); + object.put("orderId", refundOrder.getRefundOrderId()); + object.put("count", 0); + object.put("createTime", System.currentTimeMillis()); + if(isFirst) { + int result = baseInsertMchNotify(refundOrder.getRefundOrderId(), refundOrder.getMchId(), refundOrder.getMchRefundNo(), PayConstant.MCH_NOTIFY_TYPE_REFUND, object.toString()); + _log.info("增加商户通知记录,orderId={},result:{}", refundOrder.getRefundOrderId(), result); + } + /*int count = 0; + if(!isFirst) { + MchNotify mchNotify = baseSelectMchNotify(refundOrder.getRefundOrderId()); + if(mchNotify != null) count = mchNotify.getNotifyCount(); + }*/ + + return object; + } + +} 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 index 2304f5a1..d0da9dd9 100644 --- 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 @@ -1,19 +1,9 @@ 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.IMchInfoService; -import org.xxpay.common.domain.BaseParam; -import org.xxpay.common.enumm.RetEnum; -import org.xxpay.common.util.JsonUtil; +import org.xxpay.boot.service.IMchNotifyService; 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.HashMap; -import java.util.Map; /** * @author: dingzhiwei @@ -21,36 +11,8 @@ * @description: */ @Service -public class MchInfoServiceImpl extends BaseService implements IMchInfoService { +public class MchInfoServiceImpl extends BaseService implements IMchNotifyService { 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); - } - - public JSONObject getByMchId(String mchId) { - Map paramMap = new HashMap<>(); - paramMap.put("mchId", mchId); - String jsonParam = RpcUtil.createBaseParam(paramMap); - Map result = 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/service/impl/MchNotifyServiceImpl.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/MchNotifyServiceImpl.java new file mode 100644 index 00000000..ed28fa17 --- /dev/null +++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/MchNotifyServiceImpl.java @@ -0,0 +1,56 @@ +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.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.HashMap; +import java.util.Map; + +/** + * @author: dingzhiwei + * @date: 17/9/8 + * @description: + */ +@Service +public class MchNotifyServiceImpl extends BaseService implements IMchInfoService { + + private static final MyLog _log = MyLog.getLog(MchNotifyServiceImpl.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); + } + + public JSONObject getByMchId(String mchId) { + Map paramMap = new HashMap<>(); + paramMap.put("mchId", mchId); + String jsonParam = RpcUtil.createBaseParam(paramMap); + Map result = 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/service/impl/NotifyPayServiceImpl.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/NotifyPayServiceImpl.java index 110e616a..977b793d 100644 --- 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 @@ -89,7 +89,7 @@ public Map doAliPayNotify(String jsonParam) { _log.info("{}响应给支付宝结果:{}", logPrefix, PayConstant.RETURN_ALIPAY_VALUE_SUCCESS); return RpcUtil.createBizResult(baseParam, PayConstant.RETURN_ALIPAY_VALUE_SUCCESS); } - doNotify(payOrder); + doNotify(payOrder,true); _log.info("====== 完成处理支付宝支付回调通知 ======"); return RpcUtil.createBizResult(baseParam, PayConstant.RETURN_ALIPAY_VALUE_SUCCESS); } @@ -138,7 +138,7 @@ public Map doWxPayNotify(String jsonParam) { payOrder.setChannelOrderNo(result.getTransactionId()); } // 业务系统后端通知 - doNotify(payOrder); + doNotify(payOrder,true); _log.info("====== 完成处理微信支付回调通知 ======"); return RpcUtil.createBizResult(baseParam, WxPayNotifyResponse.success("OK")); } catch (WxPayException e) { @@ -171,7 +171,7 @@ public Map sendBizPayNotify(String jsonParam) { if(payOrder == null) return RpcUtil.createFailResult(baseParam, RetEnum.RET_BIZ_DATA_NOT_EXISTS); try { // 发送业务支付通知 - super.doNotify(payOrder); + super.doNotify(payOrder,true); }catch (Exception e) { return RpcUtil.createBizResult(baseParam, 0); } 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 index 63f39f7d..5a549396 100644 --- 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 @@ -1,18 +1,8 @@ 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 java.util.HashMap; +import java.util.Map; + import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -23,11 +13,33 @@ 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.AmountUtil; +import org.xxpay.common.util.BeanConvertUtils; +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.common.util.XXPayUtil; import org.xxpay.dal.dao.model.PayChannel; import org.xxpay.dal.dao.model.PayOrder; +import org.xxpay.dal.dao.model.RefundOrder; -import java.util.Map; +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.AlipayTradeRefundModel; +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.AlipayTradeRefundRequest; +import com.alipay.api.request.AlipayTradeWapPayRequest; +import com.alipay.api.response.AlipayTradeRefundResponse; /** * @author: dingzhiwei @@ -283,5 +295,54 @@ public Map doAliPayQrReq(String jsonParam) { map.put("payUrl", payUrl); return RpcUtil.createBizResult(baseParam, map); } + + @Override + public Map doAliRefundReq(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 refundOrderObj = baseParam.isNullValue("refundOrder") ? null : JSONObject.parseObject(bizParamMap.get("refundOrder").toString()); + RefundOrder refundOrder = JSON.toJavaObject(refundOrderObj, RefundOrder.class); + if (ObjectValidUtil.isInvalid(refundOrder)) { + _log.warn("{}失败, {}. jsonParam={}", logPrefix, RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam); + return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID); + } + String refundOrderId = refundOrder.getRefundOrderId(); + String mchId = refundOrder.getMchId(); + String channelId = refundOrder.getChannelId(); + PayChannel payChannel = 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); + AlipayTradeRefundRequest request = new AlipayTradeRefundRequest(); + AlipayTradeRefundModel model = new AlipayTradeRefundModel(); + model.setOutTradeNo(refundOrder.getPayOrderId()); + model.setTradeNo(refundOrder.getChannelPayOrderNo()); + model.setOutRequestNo(refundOrderId); + model.setRefundAmount(AmountUtil.convertCent2Dollar(refundOrder.getRefundAmount().toString())); + model.setRefundReason("正常退款"); + request.setBizModel(model); + Map map = new HashMap<>(); + map.put("refundOrderId", refundOrderId); + map.put("isSuccess", false); + try { + AlipayTradeRefundResponse response = client.execute(request); + if(response.isSuccess()){ + map.put("isSuccess", true); + map.put("channelOrderNo", response.getTradeNo()); + }else { + _log.info("{}返回失败", logPrefix); + _log.info("sub_code:{},sub_msg:{}", response.getSubCode(), response.getSubMsg()); + map.put("channelErrCode", response.getSubCode()); + map.put("channelErrMsg", response.getSubMsg()); + } + } catch (AlipayApiException e) { + _log.error(e, ""); + } + 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 index 5cb27366..9369da2b 100644 --- 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 @@ -1,15 +1,10 @@ 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 java.util.HashMap; +import java.util.Map; + +import javax.annotation.Resource; + import org.springframework.stereotype.Service; import org.xxpay.boot.service.BaseService; import org.xxpay.boot.service.IPayChannel4WxService; @@ -18,13 +13,27 @@ 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.BeanConvertUtils; +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.dal.dao.model.RefundOrder; -import javax.annotation.Resource; -import java.util.HashMap; -import java.util.Map; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest; +import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; +import com.github.binarywang.wxpay.bean.result.WxPayRefundResult; +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; /** * @Description: 支付渠道接口:微信 @@ -195,4 +204,73 @@ WxPayUnifiedOrderRequest buildUnifiedOrderRequest(PayOrder payOrder, WxPayConfig return request; } + + @Override + public Map doWxRefundReq(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 refundOrderObj = baseParam.isNullValue("refundOrder") ? null : JSONObject.parseObject(bizParamMap.get("refundOrder").toString()); + RefundOrder refundOrder = JSON.toJavaObject(refundOrderObj, RefundOrder.class); + if (ObjectValidUtil.isInvalid(refundOrder)) { + _log.warn("{}失败, {}. jsonParam={}", logPrefix, RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam); + return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID); + } + String mchId = refundOrder.getMchId(); + String channelId = refundOrder.getChannelId(); + PayChannel payChannel = super.baseSelectPayChannel(mchId, channelId); + WxPayConfig wxPayConfig = WxPayUtil.getWxPayConfig(payChannel.getParam(), "", wxPayProperties.getCertRootPath(), wxPayProperties.getNotifyUrl()); + WxPayService wxPayService = new WxPayServiceImpl(); + wxPayService.setConfig(wxPayConfig); + WxPayRefundRequest wxPayRefundRequest = buildWxPayRefundRequest(refundOrder, wxPayConfig); + String refundOrderId = refundOrder.getRefundOrderId(); + Map map = new HashMap<>(); + WxPayRefundResult result; + try { + result = wxPayService.refund(wxPayRefundRequest); + _log.info("{} >>> 下单成功", logPrefix); + map.put("isSuccess", true); + map.put("refundOrderId", refundOrderId); + map.put("channelOrderNo", result.getRefundId()); + } catch (WxPayException e) { + _log.error(e, "下单失败"); + //出现业务错误 + _log.info("{}下单返回失败", logPrefix); + _log.info("err_code:{}", e.getErrCode()); + _log.info("err_code_des:{}", e.getErrCodeDes()); + map.put("isSuccess", false); + map.put("channelErrCode", e.getErrCode()); + map.put("channelErrMsg", e.getErrCodeDes()); + } + return RpcUtil.createBizResult(baseParam, map); + }catch (Exception e) { + _log.error(e, "微信退款异常"); + return RpcUtil.createFailResult(baseParam, RetEnum.RET_BIZ_WX_PAY_CREATE_FAIL); + } + } + + /** + * 构建微信退款请求数据 + * @param refundOrder + * @param wxPayConfig + * @return + */ + WxPayRefundRequest buildWxPayRefundRequest(RefundOrder refundOrder, WxPayConfig wxPayConfig) { + // 微信退款请求对象 + WxPayRefundRequest request = new WxPayRefundRequest(); + request.setTransactionId(refundOrder.getChannelPayOrderNo()); + request.setOutTradeNo(refundOrder.getPayOrderId()); + request.setDeviceInfo(refundOrder.getDevice()); + request.setOutRefundNo(refundOrder.getRefundOrderId()); + request.setRefundDesc(refundOrder.getRemarkInfo()); + request.setRefundFee(refundOrder.getRefundAmount().intValue()); + request.setRefundFeeType("CNY"); + request.setTotalFee(refundOrder.getPayAmount().intValue()); + return request; + } } 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 index eefa30fa..145b6138 100644 --- 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 @@ -268,4 +268,73 @@ public Map updateNotify(String jsonParam) { int result = super.baseUpdateNotify(payOrderId, count); return RpcUtil.createBizResult(baseParam, result); } + + public JSONObject query(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 = selectByMchIdAndPayOrderId(jsonParam); + }else { + paramMap.put("mchId", mchId); + paramMap.put("mchOrderNo", mchOrderNo); + String jsonParam = RpcUtil.createBaseParam(paramMap); + result = selectByMchIdAndMchOrderNo(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 = notifyPayService.sendBizPayNotify(jsonParam); + s = RpcUtil.mkRet(result); + _log.info("业务查单完成,并再次发送业务支付通知.发送结果:{}", s); + } + return payOrder; + } + + @Override + public Map selectByMchIdAndPayOrderId(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.baseSelectByMchIdAndPayOrderId(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 selectByMchIdAndMchOrderNo(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.baseSelectByMchIdAndMchOrderNo(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); + } } diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/RefundOrderServiceImpl.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/RefundOrderServiceImpl.java new file mode 100644 index 00000000..ee7b2023 --- /dev/null +++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/impl/RefundOrderServiceImpl.java @@ -0,0 +1,270 @@ +package org.xxpay.boot.service.impl; + +import java.util.HashMap; +import java.util.Map; + +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.INotifyPayService; +import org.xxpay.boot.service.IPayChannel4AliService; +import org.xxpay.boot.service.IPayChannel4WxService; +import org.xxpay.boot.service.IRefundOrderService; +import org.xxpay.boot.service.mq.Mq4RefundNotify; +import org.xxpay.common.constant.PayConstant; +import org.xxpay.common.domain.BaseParam; +import org.xxpay.common.enumm.RetEnum; +import org.xxpay.common.util.BeanConvertUtils; +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.common.util.XXPayUtil; +import org.xxpay.dal.dao.model.RefundOrder; + +import com.alibaba.fastjson.JSONObject; + +/** + * @author: dingzhiwei + * @date: 17/10/30 + * @description: + */ +@Service +public class RefundOrderServiceImpl extends BaseService implements IRefundOrderService { + + private static final MyLog _log = MyLog.getLog(RefundOrderServiceImpl.class); + + @Autowired + private Mq4RefundNotify mq4RefundNotify; + + @Autowired + private INotifyPayService notifyPayService; + + @Autowired + private IPayChannel4WxService payChannel4WxService; + + @Autowired + private IPayChannel4AliService payChannel4AliService; + + @Override + public int createRefundOrder(JSONObject refundOrder) { + Map paramMap = new HashMap<>(); + paramMap.put("refundOrder", refundOrder); + String jsonParam = RpcUtil.createBaseParam(paramMap); + Map result = create(jsonParam); + String s = RpcUtil.mkRet(result); + if(s == null) return 0; + return Integer.parseInt(s); + } + @Override + public void sendRefundNotify(String refundOrderId, String channelName) { + JSONObject object = new JSONObject(); + object.put("refundOrderId", refundOrderId); + object.put("channelName", channelName); + Map paramMap = new HashMap<>(); + paramMap.put("msg", object); + String jsonParam = RpcUtil.createBaseParam(paramMap); + sendRefundNotify(jsonParam); + } + + public JSONObject query(String mchId, String refundOrderId, String mchRefundNo, String executeNotify) { + Map paramMap = new HashMap<>(); + Map result; + if(StringUtils.isNotBlank(refundOrderId)) { + paramMap.put("mchId", mchId); + paramMap.put("refundOrderId", refundOrderId); + String jsonParam = RpcUtil.createBaseParam(paramMap); + result = selectByMchIdAndRefundOrderId(jsonParam); + }else { + paramMap.put("mchId", mchId); + paramMap.put("mchRefundNo", mchRefundNo); + String jsonParam = RpcUtil.createBaseParam(paramMap); + result = selectByMchIdAndMchRefundNo(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("refundOrderId", refundOrderId); + String jsonParam = RpcUtil.createBaseParam(paramMap); + result = notifyPayService.sendBizPayNotify(jsonParam); + s = RpcUtil.mkRet(result); + _log.info("业务查单完成,并再次发送业务支付通知.发送结果:{}", s); + } + return payOrder; + } + + /* public String doWxRefundReq(String tradeType, JSONObject refundOrder, String resKey) { + Map paramMap = new HashMap<>(); + paramMap.put("tradeType", tradeType); + paramMap.put("refundOrder", refundOrder); + String jsonParam = RpcUtil.createBaseParam(paramMap); + Map result = payChannel4AliService.doAliRefundReq(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); + }*/ + + @Override + public Map create(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 refundOrderObj = baseParam.isNullValue("refundOrder") ? null : JSONObject.parseObject(bizParamMap.get("refundOrder").toString()); + if(refundOrderObj == null) { + _log.warn("新增退款订单失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam); + return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID); + } + RefundOrder refundOrder = BeanConvertUtils.map2Bean(refundOrderObj, RefundOrder.class); + if(refundOrder == null) { + _log.warn("新增退款订单失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam); + return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID); + } + int result = super.baseCreateRefundOrder(refundOrder); + return RpcUtil.createBizResult(baseParam, result); + } + + @Override + public Map select(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 refundOrderId = baseParam.isNullValue("refundOrderId") ? null : bizParamMap.get("refundOrderId").toString(); + if (ObjectValidUtil.isInvalid(refundOrderId)) { + _log.warn("根据退款订单号查询退款订单失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam); + return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID); + } + RefundOrder refundOrder = super.baseSelectRefundOrder(refundOrderId); + if(refundOrder == null) return RpcUtil.createFailResult(baseParam, RetEnum.RET_BIZ_DATA_NOT_EXISTS); + String jsonResult = JsonUtil.object2Json(refundOrder); + return RpcUtil.createBizResult(baseParam, jsonResult); + } + + @Override + public Map selectByMchIdAndRefundOrderId(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 refundOrderId = baseParam.isNullValue("refundOrderId") ? null : bizParamMap.get("refundOrderId").toString(); + if (ObjectValidUtil.isInvalid(mchId, refundOrderId)) { + _log.warn("根据商户号和退款订单号查询退款订单失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam); + return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID); + } + RefundOrder refundOrder = super.baseSelectByMchIdAndRefundOrderId(mchId, refundOrderId); + if(refundOrder == null) return RpcUtil.createFailResult(baseParam, RetEnum.RET_BIZ_DATA_NOT_EXISTS); + String jsonResult = JsonUtil.object2Json(refundOrder); + return RpcUtil.createBizResult(baseParam, jsonResult); + } + + @Override + public Map selectByMchIdAndMchRefundNo(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 mchRefundNo = baseParam.isNullValue("mchRefundNo") ? null : bizParamMap.get("mchRefundNo").toString(); + if (ObjectValidUtil.isInvalid(mchId, mchRefundNo)) { + _log.warn("根据商户号和商户订单号查询支付订单失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam); + return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID); + } + RefundOrder refundOrder = super.baseSelectByMchIdAndMchRefundNo(mchId, mchRefundNo); + if(refundOrder == null) return RpcUtil.createFailResult(baseParam, RetEnum.RET_BIZ_DATA_NOT_EXISTS); + String jsonResult = JsonUtil.object2Json(refundOrder); + 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 refundOrderId = baseParam.isNullValue("refundOrderId") ? null : bizParamMap.get("refundOrderId").toString(); + String channelOrderNo = baseParam.isNullValue("channelOrderNo") ? null : bizParamMap.get("channelOrderNo").toString(); + if (ObjectValidUtil.isInvalid(refundOrderId)) { + _log.warn("修改退款订单状态失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam); + return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID); + } + int result = super.baseUpdateStatus4Ing(refundOrderId, 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 refundOrderId = baseParam.isNullValue("refundOrderId") ? null : bizParamMap.get("refundOrderId").toString(); + if (ObjectValidUtil.isInvalid(refundOrderId)) { + _log.warn("修改退款订单状态失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam); + return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID); + } + int result = super.baseUpdateStatus4SuccessByRefund(refundOrderId); + 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 refundOrderId = baseParam.isNullValue("refundOrderId") ? null : bizParamMap.get("refundOrderId").toString(); + if (ObjectValidUtil.isInvalid(refundOrderId)) { + _log.warn("修改退款订单状态失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam); + return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID); + } + int result = super.baseUpdateStatus4Complete(refundOrderId); + return RpcUtil.createBizResult(baseParam, result); + } + + private Map sendRefundNotify(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 msg = baseParam.isNullValue("msg") ? null : bizParamMap.get("msg").toString(); + if (ObjectValidUtil.isInvalid(msg)) { + _log.warn("发送退款订单处理失败, {}. jsonParam={}", RetEnum.RET_PARAM_INVALID.getMessage(), jsonParam); + return RpcUtil.createFailResult(baseParam, RetEnum.RET_PARAM_INVALID); + } + int result = 1; + try { + mq4RefundNotify.send(msg); + }catch (Exception e) { + _log.error(e, ""); + result = 0; + } + return RpcUtil.createBizResult(baseParam, result); + } + +} diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/Mq4MchRefundNotify.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/Mq4MchRefundNotify.java new file mode 100644 index 00000000..da0cd783 --- /dev/null +++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/Mq4MchRefundNotify.java @@ -0,0 +1,159 @@ +package org.xxpay.boot.service.mq; + +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 javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.springframework.jms.annotation.JmsListener; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.xxpay.boot.service.BaseService; +import org.xxpay.common.util.MyLog; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; + +/** + * @Description: 商户通知MQ统一处理 + * @author dingzhiwei jmdhappy@126.com + * @date 2017-10-31 + * @version V1.0 + * @Copyright: www.xxpay.org + */ +@Component +public abstract class Mq4MchRefundNotify extends BaseService { + + + protected static final MyLog _log = MyLog.getLog(Mq4MchRefundNotify.class); + + public abstract void send(String msg); + /** + * 发送延迟消息 + * @param msg + * @param delay + */ + public abstract void send(String msg, long delay); + + @JmsListener(destination = MqConfig.MCH_REFUND_NOTIFY_QUEUE_NAME) + public void receive(String msg) { + String logPrefix = "【商户退款通知】"; + _log.info("{}接收消息:msg={}", logPrefix, 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("{}商户通知URL为空,respUrl={}", logPrefix, respUrl); + return; + } + String httpResult = httpPost(respUrl); + int cnt = count + 1; + _log.info("{}notifyCount={}", logPrefix, cnt); + if("success".equalsIgnoreCase(httpResult)){ + // 修改退款订单表 + try { + int result = baseUpdateStatus4CompleteByRefund(orderId); + _log.info("{}修改payOrderId={},退款订单状态为处理完成->{}", logPrefix, orderId, result == 1 ? "成功" : "失败"); + } catch (Exception e) { + _log.error(e, "修改订单状态为处理完成异常"); + } + // 修改通知 + try { + int result = super.baseUpdateMchNotifySuccess(orderId, httpResult, (byte) cnt); + _log.info("{}订单退款修改商户通知,orderId={},result={},notifyCount={},结果:{}", logPrefix, orderId, httpResult, cnt, result == 1 ? "成功" : "失败"); + }catch (Exception e) { + _log.error(e, "订单退款修改商户支付通知异常"); + } + return ; // 通知成功结束 + }else { + // 修改通知次数 + try { + int result = super.baseUpdateMchNotifyFail(orderId, httpResult, (byte) cnt); + _log.info("{}订单退款修改商户通知,orderId={},result={},notifyCount={},结果:{}", logPrefix, orderId, httpResult, cnt, result == 1 ? "成功" : "失败"); + }catch (Exception e) { + _log.error(e, "订单退款修改商户支付通知异常"); + } + if (cnt > 5) { + _log.info("{}订单退款通知次数notifyCount()>5,停止通知", respUrl, cnt); + return ; + } + // 通知失败,延时再通知 + msgObj.put("count", cnt); + this.send(msgObj.toJSONString(), cnt * 60 * 1000); + _log.info("{}发送延时通知完成,通知次数:{},{}秒后执行通知", respUrl, cnt, cnt * 60); + } + } + + 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[] {}; + } + } + + public String httpPost(String url) { + StringBuffer sb = new StringBuffer(); + try { + URL console = new URL(url); + 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(30 * 1000); + con.setReadTimeout(60 * 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(30 * 1000); + con.setReadTimeout(60 * 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()); + } + } catch(Exception e) { + _log.error(e, "httpPost exception. url:%s", url); + } + return sb.toString(); + } +} 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 index 40f71c4e..3de9488c 100644 --- 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 @@ -47,6 +47,7 @@ public void receive(String msg) { } try { String notifyResult = ""; + int cnt = count + 1; _log.info("==>MQ通知业务系统开始[orderId:{}][count:{}][time:{}]", orderId, count, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); try { URI uri = new URI(respUrl); @@ -68,20 +69,26 @@ public void receive(String msg) { } // 修改通知次数 try { - int result = super.baseUpdateNotify(orderId, (byte) 1); - _log.info("修改payOrderId={},通知业务系统次数->{}", orderId, result == 1 ? "成功" : "失败"); + int result = super.baseUpdateNotify(orderId, (byte) cnt); + _log.info("修改【支付订单表】payOrderId={},通知业务系统次数->{}", orderId, result == 1 ? "成功" : "失败"); + //添加 修改【商户通知表】 + int result2 = super.baseUpdateMchNotifySuccess(orderId, notifyResult, (byte) cnt); + _log.info("修改【商户通知表】payOrderId={},通知业务系统次数->{}", orderId, result2 == 1 ? "成功" : "失败"); }catch (Exception e) { _log.error(e, "修改通知次数异常"); } return ; // 通知成功结束 }else { // 通知失败,延时再通知 - int cnt = count+1; + // int cnt = count+1; _log.info("notify count={}", cnt); // 修改通知次数 try { int result = super.baseUpdateNotify(orderId, (byte) cnt); - _log.info("修改payOrderId={},通知业务系统次数->{}", orderId, result == 1 ? "成功" : "失败"); + _log.info("修改【支付订单表】payOrderId={},通知业务系统次数->{}", orderId, result == 1 ? "成功" : "失败"); + //添加 修改【商户通知表】 + int result2 = super.baseUpdateMchNotifyFail(orderId, notifyResult, (byte) cnt); + _log.info("修改【商户通知表】payOrderId={},通知业务系统次数->{}", orderId, result2 == 1 ? "成功" : "失败"); }catch (Exception e) { _log.error(e, "修改通知次数异常"); } diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/Mq4RefundNotify.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/Mq4RefundNotify.java new file mode 100644 index 00000000..b02354c7 --- /dev/null +++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/Mq4RefundNotify.java @@ -0,0 +1,105 @@ +package org.xxpay.boot.service.mq; + +import java.util.HashMap; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.xxpay.boot.service.BaseService; +import org.xxpay.boot.service.IPayChannel4AliService; +import org.xxpay.boot.service.IPayChannel4WxService; +import org.xxpay.boot.service.Notify4BaseRefund; +import org.xxpay.common.constant.PayConstant; +import org.xxpay.common.util.MyLog; +import org.xxpay.common.util.RpcUtil; +import org.xxpay.common.util.StrUtil; +import org.xxpay.dal.dao.model.RefundOrder; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; + +/** + * @Description: MQ通知 调用第三方退款业务处理 + * @author dingzhiwei jmdhappy@126.com + * @date 2017-07-05 + * @version V1.0 + * @Copyright: www.xxpay.org + */ +public abstract class Mq4RefundNotify extends BaseService { + + @Autowired + private IPayChannel4WxService payChannel4WxService; + + @Autowired + private IPayChannel4AliService payChannel4AliService; + + @Autowired + private Notify4BaseRefund notify4BaseRefund; + + protected static final MyLog _log = MyLog.getLog(Mq4RefundNotify.class); + + public abstract void send(String msg); + + /** + * 发送延迟消息 + * @param msg + * @param delay + */ + public abstract void send(String msg, long delay); + + public void receive(String msg) { + _log.info("处理退款任务.msg={}", msg); + JSONObject msgObj = JSON.parseObject(msg); + String refundOrderId = msgObj.getString("refundOrderId"); + String channelName = msgObj.getString("channelName"); + RefundOrder refundOrder = baseSelectRefundOrder(refundOrderId); + if(refundOrder == null) { + _log.warn("查询退款订单为空,不能退款.refundOrderId={}", refundOrderId); + return; + } + if(refundOrder.getStatus() != PayConstant.REFUND_STATUS_INIT) { + _log.warn("退款状态不是初始({})或失败({}),不能退款.refundOrderId={}", PayConstant.REFUND_STATUS_INIT, PayConstant.REFUND_STATUS_FAIL, refundOrderId); + return; + } + int result = this.baseUpdateStatus4IngByRefund(refundOrderId, ""); + if(result != 1) { + _log.warn("更改退款为退款中({})失败,不能退款.refundOrderId={}", PayConstant.REFUND_STATUS_REFUNDING, refundOrderId); + return; + } + Map paramMap = new HashMap<>(); + paramMap.put("refundOrder", refundOrder); + String jsonParam = RpcUtil.createBaseParam(paramMap); + Map resultMap; + if(PayConstant.CHANNEL_NAME_WX.equalsIgnoreCase(channelName)) { + resultMap = payChannel4WxService.doWxRefundReq(jsonParam); + }else if(PayConstant.CHANNEL_NAME_ALIPAY.equalsIgnoreCase(channelName)) { + resultMap = payChannel4AliService.doAliRefundReq(jsonParam); + }else { + _log.warn("不支持的退款渠道,停止退款处理.refundOrderId={},channelName={}", refundOrderId, channelName); + return; + } + if(!RpcUtil.isSuccess(resultMap)) { + _log.warn("发起退款返回异常,停止退款处理.refundOrderId={}", refundOrderId); + return; + } + Map bizResult = (Map) resultMap.get("bizResult"); + Boolean isSuccess = false; + if(bizResult.get("isSuccess") != null) isSuccess = Boolean.parseBoolean(bizResult.get("isSuccess").toString()); + if(isSuccess) { + // 更新退款状态为成功 + String channelOrderNo = StrUtil.toString(bizResult.get("channelOrderNo")); + result = baseUpdateStatus4SuccessByRefund(refundOrderId, channelOrderNo); + _log.info("更新退款订单状态为成功({}),refundOrderId={},返回结果:{}", PayConstant.REFUND_STATUS_SUCCESS, refundOrderId, result); + // 发送商户通知 + notify4BaseRefund.doNotify(refundOrder, true); + }else { + // 更新退款状态为失败 + String channelErrCode = StrUtil.toString(bizResult.get("channelErrCode")); + String channelErrMsg = StrUtil.toString(bizResult.get("channelErrMsg")); + result = baseUpdateStatus4FailByRefund(refundOrderId, channelErrCode, channelErrMsg); + _log.info("更新退款订单状态为失败({}),refundOrderId={},返回结果:{}", PayConstant.REFUND_STATUS_FAIL, refundOrderId, result); + // 发送商户通知 + notify4BaseRefund.doNotify(refundOrder, true); + } + + } +} 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 index 7b001db8..7272f51b 100644 --- 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 @@ -1,6 +1,11 @@ package org.xxpay.boot.service.mq; +import javax.jms.Queue; + +import org.apache.activemq.command.ActiveMQQueue; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; /** @@ -13,9 +18,34 @@ @Configuration public class MqConfig { + public static final String PAY_NOTIFY_EXCHANGE_NAME = "pay.notify.exchange"; + + //public static final String REFUND_NOTIFY_EXCHANGE_NAME = "refund.notify.exchange"; + public static final String PAY_NOTIFY_QUEUE_NAME = "pay.notify.queue"; - public static final String PAY_NOTIFY_EXCHANGE_NAME = "pay.notify.exchange"; + public static final String REFUND_NOTIFY_QUEUE_NAME = "refund.notify.queue"; + + public static final String MCH_REFUND_NOTIFY_QUEUE_NAME ="mch_refund_notify_queue"; + + @Bean + @Profile(MqConfig.Impl.ACTIVE_MQ) + public Queue refundNotifyQueue() { + return new ActiveMQQueue(MqConfig.REFUND_NOTIFY_QUEUE_NAME); + } + + @Bean + @Profile(MqConfig.Impl.ACTIVE_MQ) + public Queue mchRefundNotifyQueue() { + return new ActiveMQQueue(MqConfig.MCH_REFUND_NOTIFY_QUEUE_NAME); + } + + @Bean + @Profile(MqConfig.Impl.ACTIVE_MQ) + public Queue payNotifyQueue() { + return new ActiveMQQueue(MqConfig.PAY_NOTIFY_QUEUE_NAME); + } + public static class Impl{ public static final String ACTIVE_MQ = "activeMQ"; diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/impl/ActiveMq4MuchReundNotify.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/impl/ActiveMq4MuchReundNotify.java new file mode 100644 index 00000000..6fe32551 --- /dev/null +++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/impl/ActiveMq4MuchReundNotify.java @@ -0,0 +1,58 @@ +package org.xxpay.boot.service.mq.impl; + +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; + +import org.apache.activemq.ScheduledMessage; +import org.apache.activemq.command.ActiveMQQueue; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Profile; +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.xxpay.boot.service.mq.Mq4MchRefundNotify; +import org.xxpay.boot.service.mq.MqConfig; + +@Component +@Profile(MqConfig.Impl.ACTIVE_MQ) +public class ActiveMq4MuchReundNotify extends Mq4MchRefundNotify{ + + + @Autowired + private Queue mchRefundNotifyQueue; + + @Autowired + private JmsTemplate jmsTemplate; + + + @Override + public void send(String msg) { + _log.info("发送MQ消息:msg={}", msg); + jmsTemplate.convertAndSend(mchRefundNotifyQueue, msg); + } + + @Override + public void send(String msg, long delay) { + _log.info("发送MQ延时消息:msg={},delay={}", msg, delay); + jmsTemplate.send(this.mchRefundNotifyQueue, 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; + } + }); + } + + @JmsListener(destination = MqConfig.MCH_REFUND_NOTIFY_QUEUE_NAME) + public void onMessage(String msg) { + receive(msg); + } + +} diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/impl/ActiveMq4PayNotify.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/impl/ActiveMq4PayNotify.java index d3c0475b..8ddaebe7 100644 --- a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/impl/ActiveMq4PayNotify.java +++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/impl/ActiveMq4PayNotify.java @@ -20,11 +20,6 @@ @Profile(MqConfig.Impl.ACTIVE_MQ) public class ActiveMq4PayNotify extends Mq4PayNotify{ - @Bean - public Queue payNotifyQueue() { - return new ActiveMQQueue(PAY_NOTIFY_QUEUE_NAME); - } - @Autowired private Queue payNotifyQueue; diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/impl/ActiveMq4RefundNotify.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/impl/ActiveMq4RefundNotify.java new file mode 100644 index 00000000..812ce1ae --- /dev/null +++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/impl/ActiveMq4RefundNotify.java @@ -0,0 +1,58 @@ +package org.xxpay.boot.service.mq.impl; + +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; + +import org.apache.activemq.ScheduledMessage; +import org.apache.activemq.command.ActiveMQQueue; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Profile; +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.xxpay.boot.service.mq.Mq4RefundNotify; +import org.xxpay.boot.service.mq.MqConfig; + +@Component +@Profile(MqConfig.Impl.ACTIVE_MQ) +public class ActiveMq4RefundNotify extends Mq4RefundNotify{ + + + @Autowired + private Queue refundNotifyQueue; + + @Autowired + private JmsTemplate jmsTemplate; + + + @Override + public void send(String msg) { + _log.info("发送MQ消息:msg={}", msg); + jmsTemplate.convertAndSend(refundNotifyQueue, msg); + } + + @Override + public void send(String msg, long delay) { + _log.info("发送MQ延时消息:msg={},delay={}", msg, delay); + jmsTemplate.send(this.refundNotifyQueue, 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; + } + }); + } + + @JmsListener(destination = MqConfig.REFUND_NOTIFY_QUEUE_NAME) + public void onMessage(String msg) { + receive(msg); + } + +} diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/impl/RabbitMq4MuchRefundNotify.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/impl/RabbitMq4MuchRefundNotify.java new file mode 100644 index 00000000..e48c00e7 --- /dev/null +++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/impl/RabbitMq4MuchRefundNotify.java @@ -0,0 +1,64 @@ +package org.xxpay.boot.service.mq.impl; + +import javax.annotation.PostConstruct; + +import org.springframework.amqp.AmqpException; +import org.springframework.amqp.core.AmqpAdmin; +import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.DirectExchange; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.core.MessagePostProcessor; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Component; +import org.xxpay.boot.service.mq.Mq4MchRefundNotify; +import org.xxpay.boot.service.mq.MqConfig; + +@Component +@Profile(MqConfig.Impl.RABBIT_MQ) +public class RabbitMq4MuchRefundNotify extends Mq4MchRefundNotify { + + @Autowired + private AmqpAdmin amqpAdmin; + + @PostConstruct + public void init() { + DirectExchange exchange = new DirectExchange(MqConfig.PAY_NOTIFY_EXCHANGE_NAME); + exchange.setDelayed(true); + Queue queue = new Queue(MqConfig.MCH_REFUND_NOTIFY_QUEUE_NAME); + Binding binding = BindingBuilder.bind(queue).to(exchange).withQueueName(); + amqpAdmin.declareExchange(exchange); + amqpAdmin.declareQueue(queue); + amqpAdmin.declareBinding(binding); + } + + @Autowired + private AmqpTemplate rabbitTemplate; + + @Override + public void send(String msg) { + _log.info("发送MQ消息:msg={}", msg); + rabbitTemplate.convertAndSend(MqConfig.MCH_REFUND_NOTIFY_QUEUE_NAME, msg); + } + + @Override + public void send(String msg, long delay) { + _log.info("发送MQ延时消息:msg={},delay={}", msg, delay); + rabbitTemplate.convertAndSend(MqConfig.PAY_NOTIFY_EXCHANGE_NAME, MqConfig.MCH_REFUND_NOTIFY_QUEUE_NAME, msg, new MessagePostProcessor() { + public Message postProcessMessage(Message message) throws AmqpException { + message.getMessageProperties().setDelay((int) delay); + return message; + } + }); + } + + @RabbitListener(queues = MqConfig.MCH_REFUND_NOTIFY_QUEUE_NAME) + public void onMessage(String msg) { + receive(msg); + } + +} diff --git a/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/impl/RabbitMq4RefundNotify.java b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/impl/RabbitMq4RefundNotify.java new file mode 100644 index 00000000..82f46832 --- /dev/null +++ b/xxpay4spring-boot/src/main/java/org/xxpay/boot/service/mq/impl/RabbitMq4RefundNotify.java @@ -0,0 +1,64 @@ +package org.xxpay.boot.service.mq.impl; + +import javax.annotation.PostConstruct; + +import org.springframework.amqp.AmqpException; +import org.springframework.amqp.core.AmqpAdmin; +import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.amqp.core.Binding; +import org.springframework.amqp.core.BindingBuilder; +import org.springframework.amqp.core.DirectExchange; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.core.MessagePostProcessor; +import org.springframework.amqp.core.Queue; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Component; +import org.xxpay.boot.service.mq.Mq4RefundNotify; +import org.xxpay.boot.service.mq.MqConfig; + +@Component +@Profile(MqConfig.Impl.RABBIT_MQ) +public class RabbitMq4RefundNotify extends Mq4RefundNotify { + + @Autowired + private AmqpAdmin amqpAdmin; + + @PostConstruct + public void init() { + DirectExchange exchange = new DirectExchange(MqConfig.PAY_NOTIFY_EXCHANGE_NAME); + exchange.setDelayed(true); + Queue queue = new Queue(MqConfig.REFUND_NOTIFY_QUEUE_NAME); + Binding binding = BindingBuilder.bind(queue).to(exchange).withQueueName(); + amqpAdmin.declareExchange(exchange); + amqpAdmin.declareQueue(queue); + amqpAdmin.declareBinding(binding); + } + + @Autowired + private AmqpTemplate rabbitTemplate; + + @Override + public void send(String msg) { + _log.info("发送MQ消息:msg={}", msg); + rabbitTemplate.convertAndSend(MqConfig.REFUND_NOTIFY_QUEUE_NAME, msg); + } + + @Override + public void send(String msg, long delay) { + _log.info("发送MQ延时消息:msg={},delay={}", msg, delay); + rabbitTemplate.convertAndSend(MqConfig.PAY_NOTIFY_EXCHANGE_NAME, MqConfig.REFUND_NOTIFY_QUEUE_NAME, msg, new MessagePostProcessor() { + public Message postProcessMessage(Message message) throws AmqpException { + message.getMessageProperties().setDelay((int) delay); + return message; + } + }); + } + + @RabbitListener(queues = MqConfig.REFUND_NOTIFY_QUEUE_NAME) + public void onMessage(String msg) { + receive(msg); + } + +} diff --git a/xxpay4spring-boot/src/main/resources/logback.xml b/xxpay4spring-boot/src/main/resources/logback.xml new file mode 100644 index 00000000..2134ad96 --- /dev/null +++ b/xxpay4spring-boot/src/main/resources/logback.xml @@ -0,0 +1,154 @@ + + + + + + + + + %d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] %-5level %logger{35} - %msg %n + + + + + DEBUG + + ${LOG_PATH}/${APP_ID}/access.log + + + ${LOG_PATH}/${APP_ID}/access.log.%d{yyyy-MM-dd}.zip + + 10 + + + + %d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] %-5level %logger{35} - %msg%n + + + + + + DEBUG + ACCEPT + DENY + + ${LOG_PATH}/${APP_ID}/access_debug.log + + ${LOG_PATH}/${APP_ID}/access_debug.log.%d{yyyy-MM-dd}.zip + + 10 + + + %d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] %-5level %logger{35} - %msg%n + + + + + INFO + ACCEPT + DENY + + ${LOG_PATH}/${APP_ID}/access_info.log + + ${LOG_PATH}/${APP_ID}/access_info.log.%d{yyyy-MM-dd}.zip + + 10 + + + %d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] %-5level %logger{35} - %msg%n + + + + + + WARN + ACCEPT + DENY + + ${LOG_PATH}/${APP_ID}/access_warn.log + + ${LOG_PATH}/${APP_ID}/access_warn.log.%d{yyyy-MM-dd}.zip + + 10 + + + %d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] %-5level %logger{35} - %msg%n + + + + + ERROR + ACCEPT + DENY + + ${LOG_PATH}/${APP_ID}/access_error.log + + ${LOG_PATH}/${APP_ID}/access_error.log.%d{yyyy-MM-dd}.zip + + 10 + + + %d{yyyy-MM-dd HH:mm:ss} %-4relative [%thread] %-5level %logger{35} - %msg%n + + + + + + + 0 + + 512 + + + + + 0 + + 512 + + + + + 0 + + 512 + + + + + 0 + + 512 + + + + + 0 + + 512 + + + + + 0 + + 512 + + + + + + + + + + + + + +