✨ Introducing new features. 新增yungouos支付渠道

This commit is contained in:
lengleng committed 2021-01-05 11:27:50 +08:00
1 parent dbbba889c0
commit 511e56d0dd
11 files changed
+326 -18

No files matched your search

+5
View File
@@ -94,6 +94,11 @@
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
</dependency>
<dependency>
<groupId>com.yungouos.pay</groupId>
<artifactId>yungouos-pay-sdk</artifactId>
<version>2.0.4</version>
</dependency>
<!--web 模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
@@ -0,0 +1,22 @@
package com.pig4cloud.pigx.pay.config;
import lombok.Data;
/**
* @author lengleng
* @date 2021/1/4
* <p>
* 聚合支付
*/
@Data
public class MergePayConfig {
/**
* 前端回调地址
*/
private String returnUrl;
/**
* 服务端回调地址
*/
private String notifyUrl;
}
@@ -25,4 +25,8 @@ public class PayCommonProperties {
*/
private WxPayConfig wxPayConfig;
/**
* 聚合支付参数
*/
private MergePayConfig mergePayConfig;
}
@@ -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<String, Object> 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
*/
@@ -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<String, String> params = AliPayApi.toMap(request);
response.getWriter().print(mergePayCallback.handle(params));
}
}
@@ -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
* <p>
* 聚合支付回调处理
*/
@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<String, String> params) {
}
/**
* 去重处理
*
* @param params 回调报文
* @return
*/
@Override
public Boolean duplicateChecker(Map<String, String> 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<String, String> params) {
return Boolean.TRUE;
}
/**
* 解析报文
*
* @param params
* @return
*/
@Override
public String parse(Map<String, String> params) {
String mergeCode = params.get(PayConstants.MERGE_CODE);
String orderNo = params.get(PayConstants.MERGE_OUT_TRADE_NO);
PayGoodsOrder goodsOrder = goodsOrderService
.getOne(Wrappers.<PayGoodsOrder>lambdaQuery().eq(PayGoodsOrder::getPayOrderId, orderNo));
PayTradeOrder tradeOrder = tradeOrderService
.getOne(Wrappers.<PayTradeOrder>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<String, String> 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);
}
}
@@ -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
* <p>
* 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);
}
}
@@ -33,8 +33,9 @@ public interface PayGoodsOrderService extends IService<PayGoodsOrder> {
/**
* 购买商品
* @param goodsOrder goods
* @param isMerge 是否是服务商
* @return
*/
Map<String, Object> buy(PayGoodsOrder goodsOrder);
Map<String, Object> buy(PayGoodsOrder goodsOrder, boolean isMerge);
}
@@ -50,13 +50,17 @@ public class PayGoodsOrderServiceImpl extends ServiceImpl<PayGoodsOrderMapper, P
/**
* 下单购买
*
* @param goodsOrder
* @param isMerge
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> buy(PayGoodsOrder goodsOrder) {
String ua = request.getHeader(HttpHeaders.USER_AGENT);
public Map<String, Object> 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("测试产品");
@@ -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;
}
}
@@ -33,4 +33,14 @@ public interface PayConstants {
*/
String TRADE_STATUS = "trade_status";
/**
* 聚合支付返回 Code
*/
String MERGE_CODE = "code";
/**
* 聚合支付订单号
*/
String MERGE_OUT_TRADE_NO = "outTradeNo";
}