添加微信支付相关 回调处理
This commit is contained in:
@@ -7,14 +7,10 @@ import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.jiayunet.exception.BusinessException;
|
import org.jiayunet.exception.BusinessException;
|
||||||
import org.jiayunet.exception.BusinessExpCodeEnum;
|
import org.jiayunet.exception.BusinessExpCodeEnum;
|
||||||
import org.jiayunet.mapper.MemberOrderMapper;
|
import org.jiayunet.mapper.*;
|
||||||
import org.jiayunet.mapper.MemberProductMapper;
|
|
||||||
import org.jiayunet.mapper.PayWechatFlowMapper;
|
|
||||||
import org.jiayunet.pojo.dto.memberProduct.CreateOrderDto;
|
import org.jiayunet.pojo.dto.memberProduct.CreateOrderDto;
|
||||||
import org.jiayunet.pojo.dto.memberProduct.OrderDetailDto;
|
import org.jiayunet.pojo.dto.memberProduct.OrderDetailDto;
|
||||||
import org.jiayunet.pojo.po.MemberOrder;
|
import org.jiayunet.pojo.po.*;
|
||||||
import org.jiayunet.pojo.po.MemberProduct;
|
|
||||||
import org.jiayunet.pojo.po.PayWechatFlow;
|
|
||||||
import org.jiayunet.tool.UserSecurityTool;
|
import org.jiayunet.tool.UserSecurityTool;
|
||||||
import org.jiayunet.wxPay.WxNativePayAbility;
|
import org.jiayunet.wxPay.WxNativePayAbility;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -23,12 +19,14 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 会员商品服务
|
* 会员商品服务
|
||||||
* <p>依赖:WxNativePayAbility(微信Native支付下单)</p>
|
* <p>依赖:WxNativePayAbility(微信Native支付下单)、FuncPermissionService(功能权限发放)、RouteMenuService(菜单权限发放)</p>
|
||||||
* <p>使用表:bg_member_product(查询商品)、bg_member_order(创建/查询订单)、bg_pay_wechat_flow(创建支付流水)</p>
|
* <p>使用表:bg_member_product(查询商品)、bg_member_order(创建/查询订单)、bg_pay_wechat_flow(支付流水)、bg_member_user(会员状态)、bg_member_func_item(会员功能配置)、bg_member_route_item(会员菜单配置)</p>
|
||||||
*
|
*
|
||||||
* @author zk
|
* @author zk
|
||||||
*/
|
*/
|
||||||
@@ -45,6 +43,21 @@ public class MemberProductService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private PayWechatFlowMapper payWechatFlowMapper;
|
private PayWechatFlowMapper payWechatFlowMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MemberUserMapper memberUserMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MemberFuncItemMapper memberFuncItemMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MemberRouteItemMapper memberRouteItemMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private FuncPermissionService funcPermissionService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RouteMenuService routeMenuService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private WxNativePayAbility wxNativePayAbility;
|
private WxNativePayAbility wxNativePayAbility;
|
||||||
|
|
||||||
@@ -99,7 +112,6 @@ public class MemberProductService {
|
|||||||
// 4. 调支付渠道下单,拿二维码URL
|
// 4. 调支付渠道下单,拿二维码URL
|
||||||
String codeUrl;
|
String codeUrl;
|
||||||
if (payChannel == 1) {
|
if (payChannel == 1) {
|
||||||
// 微信Native支付
|
|
||||||
codeUrl = prepayWechat(orderNo, product);
|
codeUrl = prepayWechat(orderNo, product);
|
||||||
} else {
|
} else {
|
||||||
// TODO 支付宝当面付
|
// TODO 支付宝当面付
|
||||||
@@ -113,11 +125,79 @@ public class MemberProductService {
|
|||||||
return dto;
|
return dto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付成功回调公共处理
|
||||||
|
* <p>微信回调和支付宝回调统一调用此方法</p>
|
||||||
|
* <p>1. 查订单校验待支付(幂等) 2. 更新订单已支付 3. 续费会员+发放权限</p>
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void handlePaySuccess(String orderNo) {
|
||||||
|
// 查订单,幂等校验
|
||||||
|
MemberOrder order = memberOrderMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<MemberOrder>().eq(MemberOrder::getOrderNo, orderNo)
|
||||||
|
);
|
||||||
|
if (order == null) {
|
||||||
|
log.warn("支付回调订单不存在 orderNo:{}", orderNo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (order.getStatus() != 0) {
|
||||||
|
log.info("订单已处理,跳过 orderNo:{} status:{}", orderNo, order.getStatus());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新订单为已支付
|
||||||
|
memberOrderMapper.update(null, new LambdaUpdateWrapper<MemberOrder>()
|
||||||
|
.eq(MemberOrder::getId, order.getId())
|
||||||
|
.eq(MemberOrder::getStatus, 0)
|
||||||
|
.set(MemberOrder::getStatus, 1)
|
||||||
|
.set(MemberOrder::getPayTime, Instant.now()));
|
||||||
|
|
||||||
|
// 查商品拿 durationDays
|
||||||
|
MemberProduct product = memberProductMapper.selectById(order.getProductId());
|
||||||
|
int durationDays = product.getDurationDays();
|
||||||
|
Long userId = order.getUserId();
|
||||||
|
Instant expireTime = Instant.now().plus(durationDays, ChronoUnit.DAYS);
|
||||||
|
|
||||||
|
// 续费会员
|
||||||
|
MemberUser memberUser = memberUserMapper.selectOne(
|
||||||
|
new LambdaQueryWrapper<MemberUser>().eq(MemberUser::getUserId, userId)
|
||||||
|
);
|
||||||
|
if (memberUser == null) {
|
||||||
|
MemberUser newMember = new MemberUser();
|
||||||
|
newMember.setUserId(userId);
|
||||||
|
newMember.setExpireTime(expireTime);
|
||||||
|
memberUserMapper.insert(newMember);
|
||||||
|
} else {
|
||||||
|
Instant baseTime = memberUser.getExpireTime().isAfter(Instant.now()) ? memberUser.getExpireTime() : Instant.now();
|
||||||
|
memberUserMapper.update(null, new LambdaUpdateWrapper<MemberUser>()
|
||||||
|
.eq(MemberUser::getId, memberUser.getId())
|
||||||
|
.set(MemberUser::getExpireTime, baseTime.plus(durationDays, ChronoUnit.DAYS)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发放功能权限
|
||||||
|
List<MemberFuncItem> funcItems = memberFuncItemMapper.selectList(null);
|
||||||
|
for (MemberFuncItem item : funcItems) {
|
||||||
|
funcPermissionService.addTimeStock(userId, item.getFuncCode(), 1, expireTime);
|
||||||
|
if (item.getCountLimit() != null && item.getCountLimit() == 1) {
|
||||||
|
funcPermissionService.addCountStock(userId, item.getFuncCode(), 1, item.getAddCount());
|
||||||
|
} else {
|
||||||
|
funcPermissionService.addCountStock(userId, item.getFuncCode(), 0, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发放菜单权限
|
||||||
|
List<MemberRouteItem> routeItems = memberRouteItemMapper.selectList(null);
|
||||||
|
for (MemberRouteItem item : routeItems) {
|
||||||
|
routeMenuService.addTimeStock(userId, item.getRouteId(), 1, expireTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("会员支付成功处理完成 orderNo:{} userId:{} durationDays:{}", orderNo, userId, durationDays);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信Native支付下单
|
* 微信Native支付下单
|
||||||
*/
|
*/
|
||||||
private String prepayWechat(String orderNo, MemberProduct product) {
|
private String prepayWechat(String orderNo, MemberProduct product) {
|
||||||
// 创建微信支付流水
|
|
||||||
PayWechatFlow flow = new PayWechatFlow();
|
PayWechatFlow flow = new PayWechatFlow();
|
||||||
flow.setOrderType("member");
|
flow.setOrderType("member");
|
||||||
flow.setOrderNo(orderNo);
|
flow.setOrderNo(orderNo);
|
||||||
@@ -125,7 +205,6 @@ public class MemberProductService {
|
|||||||
flow.setStatus(0);
|
flow.setStatus(0);
|
||||||
payWechatFlowMapper.insert(flow);
|
payWechatFlowMapper.insert(flow);
|
||||||
|
|
||||||
// 调微信Native下单
|
|
||||||
PrepayRequest request = new PrepayRequest();
|
PrepayRequest request = new PrepayRequest();
|
||||||
request.setAppid(appId);
|
request.setAppid(appId);
|
||||||
request.setMchid(merchantId);
|
request.setMchid(merchantId);
|
||||||
|
|||||||
@@ -1,18 +1,24 @@
|
|||||||
package org.jiayunet.service;
|
package org.jiayunet.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
import com.wechat.pay.java.service.partnerpayments.nativepay.model.Transaction;
|
import com.wechat.pay.java.service.partnerpayments.nativepay.model.Transaction;
|
||||||
import com.wechat.pay.java.service.refund.model.RefundNotification;
|
import com.wechat.pay.java.service.refund.model.RefundNotification;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.jiayunet.mapper.PayWechatFlowMapper;
|
||||||
|
import org.jiayunet.pojo.po.PayWechatFlow;
|
||||||
import org.jiayunet.wxPay.WxPayNotifyMessageAbstract;
|
import org.jiayunet.wxPay.WxPayNotifyMessageAbstract;
|
||||||
import org.springframework.context.annotation.Primary;
|
import org.springframework.context.annotation.Primary;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信支付回调实现
|
* 微信支付回调实现
|
||||||
* <p>依赖:WxPayNotifyMessageAbstract(common模块支付回调抽象)</p>
|
* <p>依赖:MemberProductService(会员订单处理)、PayWechatFlowMapper(更新支付流水)</p>
|
||||||
* <p>使用表:待对接商品订单表</p>
|
* <p>使用表:bg_pay_wechat_flow(更新流水状态)、bg_member_order(通过MemberProductService处理)</p>
|
||||||
*
|
*
|
||||||
* @author zk
|
* @author zk
|
||||||
*/
|
*/
|
||||||
@@ -22,25 +28,58 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class WxPayNotifyMessageAbstractImpl implements WxPayNotifyMessageAbstract {
|
public class WxPayNotifyMessageAbstractImpl implements WxPayNotifyMessageAbstract {
|
||||||
|
|
||||||
|
private final MemberProductService memberProductService;
|
||||||
|
private final PayWechatFlowMapper payWechatFlowMapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付回调
|
* 支付回调
|
||||||
*
|
* <p>1. 判断流水状态防重复处理 2. 更新微信支付流水 3. 调用公共订单处理逻辑</p>
|
||||||
* @param transaction 支付回调消息
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
@Transactional(rollbackFor = Exception.class)
|
||||||
public void payMessageHandle(Transaction transaction) {
|
public void payMessageHandle(Transaction transaction) {
|
||||||
String outTradeNo = transaction.getOutTradeNo();
|
String outTradeNo = transaction.getOutTradeNo();
|
||||||
|
String transactionId = transaction.getTransactionId();
|
||||||
|
String tradeState = transaction.getTradeState().name();
|
||||||
|
|
||||||
|
log.info("微信支付回调 outTradeNo:{} transactionId:{} tradeState:{}", outTradeNo, transactionId, tradeState);
|
||||||
|
|
||||||
|
// 只处理支付成功
|
||||||
|
if (!"SUCCESS".equals(tradeState)) {
|
||||||
|
log.info("微信支付回调非成功状态,跳过 outTradeNo:{} tradeState:{}", outTradeNo, tradeState);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 查流水,已处理则直接返回(防重复回调)
|
||||||
|
PayWechatFlow flow = payWechatFlowMapper.selectOne(new LambdaQueryWrapper<PayWechatFlow>().eq(PayWechatFlow::getOrderNo, outTradeNo));
|
||||||
|
if (flow == null) {
|
||||||
|
log.warn("微信支付回调流水不存在 outTradeNo:{}", outTradeNo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (flow.getStatus() != 0) {
|
||||||
|
log.info("微信支付流水已处理,跳过 outTradeNo:{} status:{}", outTradeNo, flow.getStatus());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 更新微信支付流水
|
||||||
|
payWechatFlowMapper.update(null, new LambdaUpdateWrapper<PayWechatFlow>()
|
||||||
|
.eq(PayWechatFlow::getId, flow.getId())
|
||||||
|
.eq(PayWechatFlow::getStatus, 0)
|
||||||
|
.set(PayWechatFlow::getStatus, 1)
|
||||||
|
.set(PayWechatFlow::getTransactionId, transactionId)
|
||||||
|
.set(PayWechatFlow::getSuccessTime, Instant.now())
|
||||||
|
.set(PayWechatFlow::getNotifyData, transaction.toString()));
|
||||||
|
|
||||||
|
// 3. 调用公共订单处理(更新订单状态 + 发放权限)
|
||||||
|
memberProductService.handlePaySuccess(outTradeNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 退款回调
|
* 退款回调
|
||||||
*
|
* TODO 暂不支持退款
|
||||||
* @param refundNotification 退款回调消息
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void refundMessageHandle(RefundNotification refundNotification) {
|
public void refundMessageHandle(RefundNotification refundNotification) {
|
||||||
|
log.info("微信退款回调 refundId:{}", refundNotification.getOutRefundNo());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user