From 511e56d0dd93bf6a8e64d1ba3a83b466330ec7b9 Mon Sep 17 00:00:00 2001 From: lengleng Date: Tue, 5 Jan 2021 11:27:50 +0800 Subject: [PATCH] =?UTF-8?q?:sparkles:=20Introducing=20new=20features.=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9Eyungouos=E6=94=AF=E4=BB=98=E6=B8=A0=E9=81=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pigx-visual/pigx-pay-platform/pom.xml | 5 + .../pigx/pay/config/MergePayConfig.java | 22 +++ .../pigx/pay/config/PayCommonProperties.java | 4 + .../controller/PayGoodsOrderController.java | 39 ++++-- .../controller/PayNotifyRecordController.java | 17 +++ .../YungouosMergePayNotifyCallbakHandler.java | 126 ++++++++++++++++++ .../impl/YungouosMergePayOrderHandler.java | 94 +++++++++++++ .../pay/service/PayGoodsOrderService.java | 3 +- .../impl/PayGoodsOrderServiceImpl.java | 8 +- .../pigx/pay/utils/PayChannelNameEnum.java | 16 ++- .../pigx/pay/utils/PayConstants.java | 10 ++ 11 files changed, 326 insertions(+), 18 deletions(-) create mode 100644 pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/config/MergePayConfig.java create mode 100644 pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/YungouosMergePayNotifyCallbakHandler.java create mode 100644 pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/YungouosMergePayOrderHandler.java diff --git a/pigx-visual/pigx-pay-platform/pom.xml b/pigx-visual/pigx-pay-platform/pom.xml index 1f57a6961..9f5ead40f 100755 --- a/pigx-visual/pigx-pay-platform/pom.xml +++ b/pigx-visual/pigx-pay-platform/pom.xml @@ -94,6 +94,11 @@ com.github.binarywang weixin-java-mp + + com.yungouos.pay + yungouos-pay-sdk + 2.0.4 + org.springframework.boot diff --git a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/config/MergePayConfig.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/config/MergePayConfig.java new file mode 100644 index 000000000..5bb7c8787 --- /dev/null +++ b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/config/MergePayConfig.java @@ -0,0 +1,22 @@ +package com.pig4cloud.pigx.pay.config; + +import lombok.Data; + +/** + * @author lengleng + * @date 2021/1/4 + *

+ * 聚合支付 + */ +@Data +public class MergePayConfig { + /** + * 前端回调地址 + */ + private String returnUrl; + + /** + * 服务端回调地址 + */ + private String notifyUrl; +} diff --git a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/config/PayCommonProperties.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/config/PayCommonProperties.java index f758158fd..44574f4f4 100644 --- a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/config/PayCommonProperties.java +++ b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/config/PayCommonProperties.java @@ -25,4 +25,8 @@ public class PayCommonProperties { */ private WxPayConfig wxPayConfig; + /** + * 聚合支付参数 + */ + private MergePayConfig mergePayConfig; } \ No newline at end of file diff --git a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayGoodsOrderController.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayGoodsOrderController.java index 20cfac8db..0aa70fc55 100755 --- a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayGoodsOrderController.java +++ b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayGoodsOrderController.java @@ -17,8 +17,10 @@ package com.pig4cloud.pigx.pay.controller; +import cn.hutool.http.ContentType; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.fasterxml.jackson.databind.ObjectMapper; import com.ijpay.wxpay.WxPayApiConfigKit; import com.pig4cloud.pigx.common.core.util.R; import com.pig4cloud.pigx.common.log.annotation.SysLog; @@ -41,6 +43,7 @@ import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.util.Map; /** * 商品 @@ -56,18 +59,30 @@ public class PayGoodsOrderController { private final PayGoodsOrderService payGoodsOrderService; + private final ObjectMapper objectMapper; + + /** * 商品订单 - * @param goods 商品 + * + * @param goods 商品 * @param response - * @return R */ @SneakyThrows @Inner(false) - @GetMapping("/buy") + @GetMapping(value = {"/buy", "/merge/buy"}) @SysLog("购买商品") public void buy(PayGoodsOrder goods, HttpServletRequest request, HttpServletResponse response) { String ua = request.getHeader(HttpHeaders.USER_AGENT); + + //服务商 模式 + if ("/goods/merge/buy".equals(request.getRequestURI())) { + Map result = payGoodsOrderService.buy(goods, true); + response.setContentType(ContentType.JSON.getValue()); + response.getWriter().print(objectMapper.writeValueAsString(result)); + return; + } + if (ua.contains(PayConstants.MICRO_MESSENGER)) { String appId = WxPayApiConfigKit.getWxPayApiConfig().getAppId(); String wxUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s" @@ -78,16 +93,17 @@ public class PayGoodsOrderController { } if (ua.contains(PayConstants.ALIPAY)) { - payGoodsOrderService.buy(goods); + payGoodsOrderService.buy(goods, false); } } /** * oauth - * @param goods 商品信息 - * @param state appid - * @param code 回调code + * + * @param goods 商品信息 + * @param state appid + * @param code 回调code * @param modelAndView * @return * @throws WxErrorException @@ -101,13 +117,14 @@ public class PayGoodsOrderController { goods.setUserId(wxMpOAuth2AccessToken.getOpenId()); goods.setAmount(goods.getAmount()); modelAndView.setViewName("pay"); - modelAndView.addAllObjects(payGoodsOrderService.buy(goods)); + modelAndView.addAllObjects(payGoodsOrderService.buy(goods, false)); return modelAndView; } /** * 分页查询 - * @param page 分页对象 + * + * @param page 分页对象 * @param payGoodsOrder 商品订单表 * @return */ @@ -119,6 +136,7 @@ public class PayGoodsOrderController { /** * 通过id查询商品订单表 + * * @param goodsOrderId id * @return R */ @@ -130,6 +148,7 @@ public class PayGoodsOrderController { /** * 新增商品订单表 + * * @param payGoodsOrder 商品订单表 * @return R */ @@ -143,6 +162,7 @@ public class PayGoodsOrderController { /** * 修改商品订单表 + * * @param payGoodsOrder 商品订单表 * @return R */ @@ -156,6 +176,7 @@ public class PayGoodsOrderController { /** * 通过id删除商品订单表 + * * @param goodsOrderId id * @return R */ diff --git a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayNotifyRecordController.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayNotifyRecordController.java index 74c2e6e1b..3f188a7a3 100755 --- a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayNotifyRecordController.java +++ b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/controller/PayNotifyRecordController.java @@ -59,6 +59,8 @@ public class PayNotifyRecordController { private final PayNotifyCallbakHandler weChatCallback; + private final PayNotifyCallbakHandler mergePayCallback; + /** * 分页查询 * @param page 分页对象 @@ -148,4 +150,19 @@ public class PayNotifyRecordController { return weChatCallback.handle(params); } + /** + * 聚合渠道异步回调 + * @param request 渠道请求 + * @return + */ + @Inner(false) + @SneakyThrows + @XssCleanIgnore + @PostMapping("/merge/callbak") + public void mergeCallbak(HttpServletRequest request, HttpServletResponse response) { + // 解析回调信息 + Map params = AliPayApi.toMap(request); + response.getWriter().print(mergePayCallback.handle(params)); + } + } diff --git a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/YungouosMergePayNotifyCallbakHandler.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/YungouosMergePayNotifyCallbakHandler.java new file mode 100644 index 000000000..398392d69 --- /dev/null +++ b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/YungouosMergePayNotifyCallbakHandler.java @@ -0,0 +1,126 @@ +package com.pig4cloud.pigx.pay.handler.impl; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.RandomUtil; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.pig4cloud.pigx.pay.entity.PayGoodsOrder; +import com.pig4cloud.pigx.pay.entity.PayNotifyRecord; +import com.pig4cloud.pigx.pay.entity.PayTradeOrder; +import com.pig4cloud.pigx.pay.handler.MessageDuplicateCheckerHandler; +import com.pig4cloud.pigx.pay.service.PayGoodsOrderService; +import com.pig4cloud.pigx.pay.service.PayNotifyRecordService; +import com.pig4cloud.pigx.pay.service.PayTradeOrderService; +import com.pig4cloud.pigx.pay.utils.OrderStatusEnum; +import com.pig4cloud.pigx.pay.utils.PayConstants; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.util.Map; + +/** + * @author lengleng + * @date 2021/1/4 + *

+ * 聚合支付回调处理 + */ +@Slf4j +@AllArgsConstructor +@Service("mergePayCallback") +public class YungouosMergePayNotifyCallbakHandler extends AbstractPayNotifyCallbakHandler { + + private final MessageDuplicateCheckerHandler duplicateCheckerHandler; + + private final PayNotifyRecordService recordService; + + private final PayTradeOrderService tradeOrderService; + + private final PayGoodsOrderService goodsOrderService; + + /** + * 初始化执行 + * + * @param params + */ + @Override + public void before(Map params) { + + } + + /** + * 去重处理 + * + * @param params 回调报文 + * @return + */ + @Override + public Boolean duplicateChecker(Map params) { + // 判断10秒内是否已经回调处理 + if (duplicateCheckerHandler.isDuplicate(params.get(PayConstants.MERGE_OUT_TRADE_NO))) { + log.info("聚合支付订单重复回调 {} 不做处理", params); + this.saveNotifyRecord(params, "重复回调"); + return true; + } + return false; + } + + /** + * 验签逻辑 + * + * @param params 回调报文 + * @return + */ + @Override + public Boolean verifyNotify(Map params) { + return Boolean.TRUE; + } + + /** + * 解析报文 + * + * @param params + * @return + */ + @Override + public String parse(Map params) { + String mergeCode = params.get(PayConstants.MERGE_CODE); + String orderNo = params.get(PayConstants.MERGE_OUT_TRADE_NO); + PayGoodsOrder goodsOrder = goodsOrderService + .getOne(Wrappers.lambdaQuery().eq(PayGoodsOrder::getPayOrderId, orderNo)); + PayTradeOrder tradeOrder = tradeOrderService + .getOne(Wrappers.lambdaQuery().eq(PayTradeOrder::getOrderId, orderNo)); + + if (OrderStatusEnum.SUCCESS.getStatus().equals(mergeCode)) { + goodsOrder.setStatus(OrderStatusEnum.SUCCESS.getStatus()); + tradeOrder.setStatus(OrderStatusEnum.SUCCESS.getStatus()); + } else { + goodsOrder.setStatus(OrderStatusEnum.FAIL.getStatus()); + tradeOrder.setStatus(OrderStatusEnum.FAIL.getStatus()); + } + + goodsOrderService.updateById(goodsOrder); + + String succTime = MapUtil.getStr(params, "time"); + tradeOrder.setPaySuccTime(DateUtil.parse(succTime, DatePattern.NORM_DATETIME_FORMAT).getTime()); + tradeOrder.setChannelOrderNo(params.get("orderNo")); + tradeOrderService.updateById(tradeOrder); + return "SUCCESS"; + } + + + /** + * 保存回调记录 + * + * @param params 回调报文 + * @param result 处理结果 + */ + @Override + public void saveNotifyRecord(Map params, String result) { + PayNotifyRecord record = new PayNotifyRecord(); + String notifyId = RandomUtil.randomNumbers(12); + MapUtil.renameKey(params, PayConstants.MERGE_OUT_TRADE_NO, PayConstants.OUT_TRADE_NO); + saveRecord(params, result, record, notifyId, recordService); + } +} diff --git a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/YungouosMergePayOrderHandler.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/YungouosMergePayOrderHandler.java new file mode 100644 index 000000000..8c9df2fb6 --- /dev/null +++ b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/handler/impl/YungouosMergePayOrderHandler.java @@ -0,0 +1,94 @@ +package com.pig4cloud.pigx.pay.handler.impl; + +import cn.hutool.core.util.NumberUtil; +import cn.hutool.extra.servlet.ServletUtil; +import com.ijpay.wxpay.WxPayApiConfigKit; +import com.pig4cloud.pigx.pay.config.PayCommonProperties; +import com.pig4cloud.pigx.pay.entity.PayGoodsOrder; +import com.pig4cloud.pigx.pay.entity.PayTradeOrder; +import com.pig4cloud.pigx.pay.mapper.PayGoodsOrderMapper; +import com.pig4cloud.pigx.pay.mapper.PayTradeOrderMapper; +import com.pig4cloud.pigx.pay.utils.OrderStatusEnum; +import com.pig4cloud.pigx.pay.utils.PayChannelNameEnum; +import com.yungouos.pay.merge.MergePay; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletRequest; + +/** + * @author lengleng + * @date 2021/1/4 + *

+ * https://open.pay.yungouos.com/#/api/api/pay/merge/nativePay + * 服务商聚合支付模式 + */ +@Slf4j +@Service("MERGE_PAY") +@RequiredArgsConstructor +public class YungouosMergePayOrderHandler extends AbstractPayOrderHandler { + + private final PayCommonProperties commonProperties; + + private final PayTradeOrderMapper tradeOrderMapper; + + private final PayGoodsOrderMapper goodsOrderMapper; + + private final HttpServletRequest request; + + /** + * 创建交易订单 + * + * @param goodsOrder 商品订单 + * @return + */ + @Override + public PayTradeOrder createTradeOrder(PayGoodsOrder goodsOrder) { + PayTradeOrder tradeOrder = new PayTradeOrder(); + tradeOrder.setOrderId(goodsOrder.getPayOrderId()); + tradeOrder.setAmount(goodsOrder.getAmount()); + tradeOrder.setChannelId(PayChannelNameEnum.MERGE_PAY.getName()); + tradeOrder.setChannelMchId(WxPayApiConfigKit.getWxPayApiConfig().getMchId()); + tradeOrder.setClientIp(ServletUtil.getClientIP(request)); + tradeOrder.setCurrency("CNY"); + tradeOrder.setStatus(OrderStatusEnum.INIT.getStatus()); + tradeOrder.setBody(goodsOrder.getGoodsName()); + tradeOrderMapper.insert(tradeOrder); + return tradeOrder; + } + + /** + * 调起渠道支付 + * + * @param goodsOrder 商品订单 + * @param tradeOrder 交易订单 + * @return obj + */ + @Override + public Object pay(PayGoodsOrder goodsOrder, PayTradeOrder tradeOrder) { + String money = NumberUtil.div(tradeOrder.getAmount(), "100", 2).toString(); + return MergePay.nativePay(tradeOrder.getOrderId(), money, "100106279016" + , tradeOrder.getBody() + , "1" + , tradeOrder.getBody() + , commonProperties.getMergePayConfig().getNotifyUrl() + , commonProperties.getMergePayConfig().getReturnUrl() + , "" + , "" + , "" + , "759492493EBC43B498955E261E1A494F"); + } + + /** + * 更新订单信息 + * + * @param goodsOrder 商品订单 + * @param tradeOrder 交易订单 + */ + @Override + public void updateOrder(PayGoodsOrder goodsOrder, PayTradeOrder tradeOrder) { + tradeOrderMapper.updateById(tradeOrder); + goodsOrderMapper.updateById(goodsOrder); + } +} diff --git a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/PayGoodsOrderService.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/PayGoodsOrderService.java index cbd141abc..cafc64763 100755 --- a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/PayGoodsOrderService.java +++ b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/PayGoodsOrderService.java @@ -33,8 +33,9 @@ public interface PayGoodsOrderService extends IService { /** * 购买商品 * @param goodsOrder goods + * @param isMerge 是否是服务商 * @return */ - Map buy(PayGoodsOrder goodsOrder); + Map buy(PayGoodsOrder goodsOrder, boolean isMerge); } diff --git a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayGoodsOrderServiceImpl.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayGoodsOrderServiceImpl.java index de0fc39a1..611336b89 100755 --- a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayGoodsOrderServiceImpl.java +++ b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/service/impl/PayGoodsOrderServiceImpl.java @@ -50,13 +50,17 @@ public class PayGoodsOrderServiceImpl extends ServiceImpl buy(PayGoodsOrder goodsOrder) { - String ua = request.getHeader(HttpHeaders.USER_AGENT); + public Map buy(PayGoodsOrder goodsOrder, boolean isMerge) { + // 是否聚合支付 + String ua = isMerge ? "MERGE_PAY" : request.getHeader(HttpHeaders.USER_AGENT); + Enum channel = PayChannelNameEnum.getChannel(ua); PayOrderHandler orderHandler = orderHandlerMap.get(channel.name()); goodsOrder.setGoodsName("测试产品"); diff --git a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/utils/PayChannelNameEnum.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/utils/PayChannelNameEnum.java index 71bafdd61..ff7140fc1 100644 --- a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/utils/PayChannelNameEnum.java +++ b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/utils/PayChannelNameEnum.java @@ -25,7 +25,12 @@ public enum PayChannelNameEnum { /** * 微信公众号支付 */ - WEIXIN_MP("WEIXIN_MP", "微信公众号支付"); + WEIXIN_MP("WEIXIN_MP", "微信公众号支付"), + + /** + * 聚合支付 + */ + MERGE_PAY("MERGE_PAY", "yungouos 一码付"); /** * 名称 @@ -40,18 +45,17 @@ public enum PayChannelNameEnum { /** * 通过ua 判断所属渠道 + * * @param ua 浏览器类型 * @return */ public static Enum getChannel(String ua) { if (ua.contains(PayConstants.ALIPAY)) { return PayChannelNameEnum.ALIPAY_WAP; - } - else if (ua.contains(PayConstants.MICRO_MESSENGER)) { + } else if (ua.contains(PayConstants.MICRO_MESSENGER)) { return PayChannelNameEnum.WEIXIN_MP; - } - else { - return PayChannelNameEnum.WEIXIN_WAP; + } else { + return PayChannelNameEnum.MERGE_PAY; } } diff --git a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/utils/PayConstants.java b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/utils/PayConstants.java index db070ff0e..5b08fb519 100644 --- a/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/utils/PayConstants.java +++ b/pigx-visual/pigx-pay-platform/src/main/java/com/pig4cloud/pigx/pay/utils/PayConstants.java @@ -33,4 +33,14 @@ public interface PayConstants { */ String TRADE_STATUS = "trade_status"; + /** + * 聚合支付返回 Code + */ + String MERGE_CODE = "code"; + + /** + * 聚合支付订单号 + */ + String MERGE_OUT_TRADE_NO = "outTradeNo"; + }