Commit 6856d847 by 郑云飞

支付回调,退款,退款回调功能完成

parent c47aeba4
......@@ -176,7 +176,8 @@ wx:
subAppId: #服务商模式下的子商户公众账号ID
subMchId: #服务商模式下的子商户号
keyPath: C:\\ProgramData\\certKey\xinrenli\\apiclient_cert.p12 # p12证书的位置,可以指定绝对路径,也可以指定类路径(以classpath:开头)
notifyUrl: http://xinrenli.nyinhong.com/api//xinrenli/order/notify # 微信支付回调接口
notifyUrl: http://xinrenli.nyinhong.com/api/xinrenli/order/notify # 微信支付回调接口
refundNotifyUrl: http://xinrenli.nyinhong.com/api/xinrenli/order/refundNotify # 微信t退款回调接口
# mp:
# useRedis: false
# redisConfig:
......
......@@ -31,7 +31,6 @@ public class WxPayConfiguration {
payConfig.setSubAppId(StringUtils.trimToNull(this.properties.getSubAppId()));
payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId()));
payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));
payConfig.setNotifyUrl(StringUtils.trimToNull(this.properties.getNotifyUrl()));
// 可以指定是否使用沙箱环境
payConfig.setUseSandboxEnv(false);
......
......@@ -41,9 +41,4 @@ public class WxPayProperties {
*/
private String keyPath;
/**
* 支付回调接口
*/
private String notifyUrl;
}
package com.yongqi.xinrenli.controller;
import java.math.BigDecimal;
import java.util.List;
import java.util.Arrays;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.yongqi.common.core.domain.model.LoginUser;
import com.yongqi.common.helper.LoginHelper;
import com.yongqi.common.utils.ip.AddressUtils;
......@@ -144,10 +146,14 @@ public class DbOrderController extends BaseController {
/**
* 下单
* @param orderId 订单id
* @param couponId 优惠券id
* @param request
* @return
*/
@SaCheckPermission("xinrenli:order:pay")
@Log(title = "下单", businessType = BusinessType.DELETE)
@RequestMapping("/orderPay")
@Log(title = "下单", businessType = BusinessType.OTHER)
@GetMapping("/orderPay")
public R orderPay(@NotNull(message = "主键不能为空") @RequestParam("id") Long orderId
, @RequestParam(value = "id", required = false) Long couponId
, HttpServletRequest request) {
......@@ -157,16 +163,41 @@ public class DbOrderController extends BaseController {
}
/**
* 下单
* 下单回调
*/
@SaCheckPermission("xinrenli:order:notify")
@Log(title = "下单", businessType = BusinessType.DELETE)
@RequestMapping("/notify")
public R payCallback(@RequestBody String xmlData) {
@Log(title = "下单回调", businessType = BusinessType.OTHER)
@PostMapping("/notify")
public String payCallback(@RequestBody String xmlData) throws WxPayException {
return iDbOrderService.payCallback(xmlData);
}
/**
* 退款
* @param orderId 订单id
* @param refundAmount 退款金额
* @return
*/
@SaCheckPermission("xinrenli:order:refund")
@Log(title = "退款", businessType = BusinessType.OTHER)
@GetMapping("/refund")
public R refund(@NotNull(message = "订单id不能为空") @RequestParam("orderId") Long orderId,
@NotNull(message = "退款金额不能为空")@RequestParam("refundeAmount")BigDecimal refundAmount) {
LoginUser loginUser = LoginHelper.getLoginUser();
return iDbOrderService.refund(orderId, refundAmount, loginUser);
}
/**
* 退款回调
*/
@SaCheckPermission("xinrenli:order:refundNotify")
@Log(title = "退款回调", businessType = BusinessType.OTHER)
@PostMapping("/refundNotify")
public String refundNotify(@RequestBody String xmlData) throws WxPayException {
return iDbOrderService.refundNotify(xmlData);
}
/**
* 报表
*/
@SaCheckPermission("xinrenli:order:reportForms")
......
......@@ -33,6 +33,10 @@ public class DbOrder {
*/
private String wxOrderNo;
/**
* 退款单号
*/
private String refundNo;
/**
* 用户id
*/
private Long userId;
......@@ -69,6 +73,10 @@ public class DbOrder {
*/
private BigDecimal payAmount;
/**
* 退款金额
*/
private BigDecimal refundAmount;
/**
* 使用优惠券id
*/
private Long useCouponId;
......
......@@ -5,6 +5,7 @@ import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import java.util.Date;
/**
......@@ -39,6 +40,6 @@ public class WxPayOrderResult {
*/
@DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss")
@JsonFormat(pattern = "yyyy/MM/dd HH:mm:ss")
private LocalDateTime createTime;
private Date createTime;
}
......@@ -10,6 +10,7 @@ import com.yongqi.common.core.page.TableDataInfo;
import com.yongqi.common.core.domain.PageQuery;
import com.yongqi.xinrenli.domain.vo.ReportFormsVo;
import java.math.BigDecimal;
import java.util.List;
/**
......@@ -85,5 +86,21 @@ public interface IDbOrderService {
* @param xmlData
* @return
*/
R payCallback(String xmlData) throws WxPayException;
String payCallback(String xmlData) throws WxPayException;
/**
* 退款
* @param orderId
* @param refundAmount
* @param loginUser
* @return
*/
R refund(Long orderId, BigDecimal refundAmount, LoginUser loginUser);
/**
* 退款回调
* @param xmlData
* @return
*/
String refundNotify(String xmlData) throws WxPayException;
}
......@@ -3,8 +3,12 @@ package com.yongqi.xinrenli.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
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.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
......@@ -19,6 +23,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yongqi.common.utils.redis.CodeUtils;
import com.yongqi.xinrenli.domain.DbCoupon;
import com.yongqi.xinrenli.domain.DbFile;
import com.yongqi.xinrenli.domain.DbUserCoupon;
import com.yongqi.xinrenli.domain.bo.DbOrderEditBo;
import com.yongqi.xinrenli.domain.vo.DbFileVo;
import com.yongqi.xinrenli.domain.vo.ReportFormsVo;
......@@ -28,9 +33,11 @@ import com.yongqi.xinrenli.enums.FileEnumServiceType;
import com.yongqi.xinrenli.enums.OrderStatusEnum;
import com.yongqi.xinrenli.mapper.DbCouponMapper;
import com.yongqi.xinrenli.mapper.DbFileMapper;
import com.yongqi.xinrenli.mapper.DbUserCouponMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.yongqi.xinrenli.domain.bo.DbOrderBo;
import com.yongqi.xinrenli.domain.vo.DbOrderVo;
......@@ -59,6 +66,12 @@ public class DbOrderServiceImpl implements IDbOrderService {
private DbCouponMapper couponMapper;
@Autowired
private WxPayService wxPayService;
@Autowired
private DbUserCouponMapper userCouponMapper;
@Value("${wx.pay.notifyUrl}")
private String payNotifyUrl;
@Value("${wx.pay.refundNotifyUrl}")
private String refundNotifyUrl;
/**
* 查询订单
......@@ -288,6 +301,7 @@ public class DbOrderServiceImpl implements IDbOrderService {
* @return
*/
@Override
@Transactional
public R orderPay(Long orderId, Long couponId, LoginUser loginUser, String ipAddr) {
// 1.根据订单id获取订单信息
DbOrder dbOrder = this.baseMapper.selectById(orderId);
......@@ -297,11 +311,26 @@ public class DbOrderServiceImpl implements IDbOrderService {
if (dbCoupon.getMinUsed().compareTo(dbOrder.getActualAmount()) > 0){
throw new RuntimeException("未达到此优惠券的最低消费金额");
}
// 查询用户优惠券关联信息
DbUserCoupon userCoupon = userCouponMapper.selectOne(Wrappers.<DbUserCoupon>lambdaQuery()
.eq(DbUserCoupon::getCouponId, couponId)
.eq(DbUserCoupon::getUserId, loginUser.getUserId()));
// 判断用户是否有此优惠券
if (ObjectUtils.isEmpty(userCoupon)) {
log.error("该用户没有此优惠券:userId:{},couponId:{}",loginUser.getUserId(), couponId);
return R.fail("没有此优惠券");
}
if (Objects.equals(userCoupon.getUseStatus(), DeleteStatusEnum.DELETED.getCode())){
log.error("此优惠券已经使用过了:userId:{},couponId:{}",loginUser.getUserId(), couponId);
return R.fail("此优惠券已经使用过了");
}
BigDecimal payAmount = dbOrder.getActualAmount().subtract(dbCoupon.getFullSubtraction());
dbOrder.setPayAmount(payAmount);
dbOrder.setUseCouponId(couponId);
String orderNo = CodeUtils.createSerialNumber("XQ");
dbOrder.setOrderNo(orderNo);
dbOrder.setPayTime(new Date());
baseMapper.updateById(dbOrder);
// 4.组装支付数据
WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
// 需求标题
......@@ -324,17 +353,121 @@ public class DbOrderServiceImpl implements IDbOrderService {
request.setSignType(WxPayConstants.SignType.MD5);
// 用户标识
request.setOpenid(loginUser.getOpenId());
request.setNotifyUrl(payNotifyUrl);
// 5.调用微信统一下单接口
try {
Object order = wxPayService.createOrder(request);
// 6.返回支付所需数据
String json = JSON.toJSONString(order);
WxPayOrderResult result = JSON.parseObject(json, WxPayOrderResult.class);
// 6.返回支付所需数据
return R.ok(result);
} catch (WxPayException e) {
throw new RuntimeException(e);
throw new RuntimeException(e.getMessage());
}
}
/**
* 支付回调
* @param xmlData
* @return
*/
@Override
@Transactional
public String payCallback(String xmlData) throws WxPayException {
final WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
log.info("支付回调参数解析:{}", notifyResult);
String resultCode = notifyResult.getResultCode();
if (!"SUCCESS".equals(resultCode)) {
return WxPayNotifyResponse.fail("订单未支付,无需处理");
}
// 1.查询订单信息 修改订单状态为已接单
DbOrder dbOrder = baseMapper.selectOne(Wrappers.<DbOrder>lambdaQuery().eq(DbOrder::getOrderNo, notifyResult.getOutTradeNo()));
if (ObjectUtils.isEmpty(dbOrder)){
return WxPayNotifyResponse.fail("订单不存在");
}
dbOrder.setStatus(OrderStatusEnum.RECEIVED_ORDER.getCode());
dbOrder.setWxOrderNo(notifyResult.getTransactionId());
baseMapper.updateById(dbOrder);
// 2.修改用户优惠券使用状态
DbUserCoupon userCoupon = userCouponMapper.selectOne(Wrappers.<DbUserCoupon>lambdaQuery()
.eq(DbUserCoupon::getCouponId, dbOrder.getUseCouponId())
.eq(DbUserCoupon::getUserId, dbOrder.getUserId()));
if (ObjectUtils.isEmpty(userCoupon)) {
log.error("该用户没有此优惠券:userId:{},couponId:{}",dbOrder.getUserId(), dbOrder.getUseCouponId());
return WxPayNotifyResponse.fail("失败");
}
if (Objects.equals(userCoupon.getUseStatus(), DeleteStatusEnum.DELETED.getCode())){
log.error("此优惠券已经使用过了:userId:{},couponId:{}",dbOrder.getUserId(), dbOrder.getUseCouponId());
return WxPayNotifyResponse.fail("失败");
}
userCoupon.setUseStatus(DeleteStatusEnum.DELETED.getCode());
userCouponMapper.updateById(userCoupon);
return WxPayNotifyResponse.success("成功");
}
/**
* 退款
* @param orderId
* @param refundAmount
* @param loginUser
* @return
*/
@Override
@Transactional
public R refund(Long orderId, BigDecimal refundAmount, LoginUser loginUser) {
// 查询订单
DbOrder order = baseMapper.selectById(orderId);
if (ObjectUtils.isEmpty(order)) {
return R.fail("订单不存在");
}
String refundNo = CodeUtils.createSerialNumber("TK");
// 修改订单
order.setRefundNo(refundNo);
order.setRefundAmount(refundAmount);
baseMapper.updateById(order);
// 组装退款参数
WxPayRefundRequest request = new WxPayRefundRequest();
request.setTransactionId(order.getWxOrderNo());
request.setTotalFee(order.getPayAmount().multiply(BigDecimal.valueOf(100L)).intValue());
request.setRefundFee(refundAmount.multiply(BigDecimal.valueOf(100L)).intValue());
request.setOutRefundNo(refundNo);
request.setNotifyUrl(refundNotifyUrl);
// 发起退款
try {
WxPayRefundResult refund = wxPayService.refund(request);
if ("SUCCESS".equals(refund.getReturnCode())) {
return R.ok("退款申请成功");
}
} catch (WxPayException e) {
log.error("退款报错:{}", e.getMessage());
return R.fail(e.getMessage());
}
return R.fail("退款申请失败,请稍后重试");
}
/**
* 退款回调
* @param xmlData
* @return
*/
@Override
public String refundNotify(String xmlData) throws WxPayException {
final WxPayRefundNotifyResult result = wxPayService.parseRefundNotifyResult(xmlData);
log.info("退款回调解析结果:{}", result);
// 查询订单
DbOrder order = baseMapper.selectOne(Wrappers.<DbOrder>lambdaQuery().eq(DbOrder::getRefundNo, result.getReqInfo().getOutRefundNo()));
if (ObjectUtils.isEmpty(order)) {
log.error("订单不存在:{}",result.getReqInfo().getOutRefundNo());
return WxPayNotifyResponse.fail("订单不存在");
}
if (Objects.equals(order.getStatus(), OrderStatusEnum.REFUNDED.getCode())){
log.error("订单已退款:{}", result.getReqInfo().getOutRefundNo());
return WxPayNotifyResponse.fail("订单已退款");
}
// 修改订单
order.setStatus(OrderStatusEnum.REFUNDED.getCode());
baseMapper.updateById(order);
return WxPayNotifyResponse.success("成功");
}
/**
......@@ -359,16 +492,5 @@ public class DbOrderServiceImpl implements IDbOrderService {
return baseMapper.unpaidJob();
}
/**
* 支付回调
* @param xmlData
* @return
*/
@Override
public R payCallback(String xmlData) throws WxPayException {
final WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
log.info("支付回调参数解析:{}", notifyResult);
// 1.查询订单信息
return null;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment