微信支付宝退款

This commit is contained in:
wuchunlei
2023-12-19 17:04:05 +08:00
parent 032cfc9266
commit 229ce39c5e
18 changed files with 617 additions and 159 deletions

View File

@@ -58,6 +58,7 @@ public class ShiroConfig {
filterMap.put("book/task/list","anon"); // 网站接口
filterMap.put("/pay/aliPay/notify","anon"); // 支付宝回调接口
filterMap.put("/pay/payNotify","anon"); // 微信回调接口
filterMap.put("/pay/refundNotify","anon"); // 微信退款回调接口
filterMap.put("/weChat/**","anon");
filterMap.put("/book/baseArea/getAllBaseArea","anon");//登录前获取全部区域
// filterMap.put("/book/bookchaptercontent/**","anon");

View File

@@ -47,8 +47,8 @@ public class OrderCancelConsumer {
shopProduct.setProductStock(shopProduct.getProductStock()+b.getQuantity());
shopProductDao.updateById(shopProduct);
}
}
buyOrderService.updateById(buyOrder);
buyOrderService.removeById(buyOrder);
}
}

View File

@@ -102,7 +102,8 @@ public class AliPayUtil {
// 退款原因
model.setRefundReason(reFundDTO.getRefundReason());
}
model.setOutRequestNo(UUID.randomUUID().toString().substring(0, 6));
//退款请求号。标识一次退款请求,需要保证在交易号下唯一,如需部分退款,则此参数必传。
model.setOutRequestNo(reFundDTO.getOutRequestNo());
request.setBizModel(model);
AlipayTradeRefundResponse response = null;

View File

@@ -50,8 +50,8 @@ public class AliPayController {
* 支付宝退款
*/
@RequestMapping("/refund")
public R refund(@RequestBody ReFundDTO reFundDTO) {
String refund = aliPayService.refund(reFundDTO);
public R refund(@RequestBody Map<String,Object> params) {
String refund = aliPayService.refund(params);
return R.ok().put("msg",refund);
}

View File

@@ -35,4 +35,9 @@ public class ReFundDTO {
*/
private String customerId;
/**
* 退款请求号 标识一次退款请求,需要保证在交易号下唯一,如需部分退款,则此参数必传。
*/
private String outRequestNo;
}

View File

@@ -5,6 +5,7 @@ package com.peanut.modules.pay.alipay.service;
import com.peanut.modules.pay.alipay.dto.AlipayDTO;
import com.peanut.modules.pay.alipay.dto.ReFundDTO;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
public interface AliPayService {
@@ -26,10 +27,8 @@ public interface AliPayService {
/**
* 支付宝退款
* @param reFundDTO
* @return
*/
String refund(ReFundDTO reFundDTO);
String refund(Map<String,Object> params);
}

View File

@@ -6,6 +6,7 @@ import com.alibaba.fastjson.JSONObject;
import com.alipay.api.internal.util.AlipaySignature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.peanut.common.utils.CopyUtils;
import com.peanut.common.utils.OrderUtils;
import com.peanut.modules.book.dao.BuyOrderProductDao;
@@ -18,6 +19,8 @@ import com.peanut.modules.pay.alipay.config.AliPayUtil;
import com.peanut.modules.pay.alipay.dto.AlipayDTO;
import com.peanut.modules.pay.alipay.dto.ReFundDTO;
import com.peanut.modules.pay.alipay.service.AliPayService;
import com.peanut.modules.pay.refund.entity.PayRefundOrder;
import com.peanut.modules.pay.refund.service.PayRefundOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -54,6 +57,8 @@ public class AliPayServiceImpl implements AliPayService {
private ShopProductBookDao shopProductBookDao;
@Autowired
private UserEbookBuyDao userEbookBuyDao;
@Autowired
private PayRefundOrderService refundOrderService;
@Override
public String pay(AlipayDTO payDto) {
@@ -248,8 +253,20 @@ public class AliPayServiceImpl implements AliPayService {
}
@Override
public String refund(ReFundDTO reFundDTO) {
@Transactional
public String refund(Map<String,Object> params) {
log.info(">>>>>>>>>>App请求支付宝退款接口");
LambdaQueryWrapper<PayZfbOrderEntity> wrapper = new LambdaQueryWrapper();
wrapper.eq(PayZfbOrderEntity::getRelevanceoid,params.get("orderSn").toString());
PayZfbOrderEntity payZfbOrder = payZfbOrderService.getOne(wrapper);
ReFundDTO reFundDTO = new ReFundDTO();
reFundDTO.setOutTrandeNo(payZfbOrder.getOutTradeNo());
reFundDTO.setTradeNo(payZfbOrder.getTradeNo());
reFundDTO.setCustomerId(payZfbOrder.getCustomerid());
reFundDTO.setRefundReason(params.get("reason").toString());
reFundDTO.setRefundAmount(new BigDecimal(params.get("refundFee").toString()));
// reFundDTO.setOutRequestNo(params.get("outRequestNo").toString());
reFundDTO.setOutRequestNo(UUID.randomUUID().toString());
Map<String, Object> map = aliPayUtil.aliPayRefund(reFundDTO);
Object obj = map.get("msg");
String resJson = obj.toString();
@@ -260,23 +277,26 @@ public class AliPayServiceImpl implements AliPayService {
"Y".equals(((Map)res.get("alipay_trade_refund_response")).get("fund_change"))){
log.info(">>>>>>>>>>>支付宝退款成功!<<<<<<<<<<<<<");
//表操作
MPJLambdaWrapper<BuyOrder> w = new MPJLambdaWrapper();
w.leftJoin(PayZfbOrderEntity.class,PayZfbOrderEntity::getRelevanceoid, BuyOrder::getOrderSn);
w.eq("trade_no",((Map)res.get("alipay_trade_refund_response")).get("trade_no"));
BuyOrder order = buyOrderService.getOne(w);
PayRefundOrder refund = new PayRefundOrder();
refund.setPayType("2");
refund.setOrderId(order.getOrderId());
refund.setTradeNo(((Map)res.get("alipay_trade_refund_response")).get("trade_no").toString());
refund.setOutTradeNo(((Map)res.get("alipay_trade_refund_response")).get("out_trade_no").toString());
refund.setRefundFee(((Map)res.get("alipay_trade_refund_response")).get("refund_fee").toString());
refundOrderService.save(refund);
refundOrderService.businessOpt(order);
}
return resJson;
}
//TODO 更新订单状态
//TODO 更新用户优惠券状态
//TODO 推送一路健康优惠券
}

View File

@@ -0,0 +1,30 @@
package com.peanut.modules.pay.refund.controller;
import com.peanut.common.utils.R;
import com.peanut.modules.pay.refund.service.PayRefundOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
@RequestMapping("/refund")
@Slf4j
public class RefundController {
@Autowired
private PayRefundOrderService refundOrderService;
/**
* 花生币退款
*/
@RequestMapping("/refundPeanutCoin")
public R pay(@RequestBody Map<String,Object> map) {
return refundOrderService.refundPeanutCoin(map);
}
}

View File

@@ -0,0 +1,9 @@
package com.peanut.modules.pay.refund.dao;
import com.github.yulichang.base.MPJBaseMapper;
import com.peanut.modules.pay.refund.entity.PayRefundOrder;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface PayRefundOrderDao extends MPJBaseMapper<PayRefundOrder> {
}

View File

@@ -0,0 +1,57 @@
package com.peanut.modules.pay.refund.entity;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 退款信息
*/
@Data
@TableName("pay_refund_order")
public class PayRefundOrder implements Serializable {
private static final long serialVersionUID = 1L;
@TableId
private Integer refundId;
/**
* 支付方式 1微信2支付宝3虚拟币
*/
private String payType;
/**
* BuyOrder
*/
private Integer orderId;
/**
* 微信支付宝订单号
*/
private String tradeNo;
/**
* 商户订单号
*/
private String outTradeNo;
/**
* 退款总金额
*/
private String refundFee;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)//创建注解
private Date createTime;
}

View File

@@ -0,0 +1,16 @@
package com.peanut.modules.pay.refund.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.peanut.common.utils.R;
import com.peanut.modules.book.entity.BuyOrder;
import com.peanut.modules.pay.refund.entity.PayRefundOrder;
import java.util.Map;
public interface PayRefundOrderService extends IService<PayRefundOrder> {
R refundPeanutCoin(Map<String,Object> map);
void businessOpt(BuyOrder order);
}

View File

@@ -0,0 +1,190 @@
package com.peanut.modules.pay.refund.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.peanut.common.utils.R;
import com.peanut.modules.book.entity.*;
import com.peanut.modules.book.service.*;
import com.peanut.modules.pay.refund.dao.PayRefundOrderDao;
import com.peanut.modules.pay.refund.entity.PayRefundOrder;
import com.peanut.modules.pay.refund.service.PayRefundOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
public class PayRefundOrderServiceImpl extends ServiceImpl<PayRefundOrderDao, PayRefundOrder> implements PayRefundOrderService {
@Autowired
private BuyOrderService buyOrderService;
@Autowired
private CouponHistoryService couponHistoryService;
@Autowired
private BuyOrderProductService buyOrderProductService;
@Autowired
private ShopProductService shopProductService;
@Autowired
private UserEbookBuyService userEbookBuyService;
@Autowired
private MyUserService userService;
@Autowired
private PayRefundOrderService refundOrderService;
@Autowired
private TransactionDetailsService transactionDetailsService;
@Override
@Transactional
public R refundPeanutCoin(Map<String,Object> map) {
log.info(">>>>>>>>>>>花生币退款<<<<<<<<<<<<<");
MPJLambdaWrapper<BuyOrder> w = new MPJLambdaWrapper();
w.eq("order_id",map.get("orderId"));
BuyOrder order = buyOrderService.getOne(w);
//退款详细
PayRefundOrder refund = new PayRefundOrder();
refund.setPayType("3");
refund.setOrderId(order.getOrderId());
refund.setRefundFee(map.get("refundFee").toString());
refundOrderService.save(refund);
//权限回退
refundOrderService.businessOpt(order);
//修改用户花生币
MyUserEntity byId = userService.getById(order.getUserId());
int i = byId.getPeanutCoin().intValue() + Integer.valueOf(map.get("refundFee").toString());
byId.setPeanutCoin(new BigDecimal(i));
userService.updateById(byId);
//插入花生比交易明细
TransactionDetailsEntity transactionDetailsEntity = new TransactionDetailsEntity();
transactionDetailsEntity.setUserId(order.getUserId());
transactionDetailsEntity.setOrderType("退款");
transactionDetailsEntity.setTel(byId.getTel());
transactionDetailsEntity.setUserName(byId.getNickname());
transactionDetailsEntity.setNote(map.get("note").toString());
transactionDetailsEntity.setChangeAmount(new BigDecimal(map.get("refundFee").toString()));
transactionDetailsEntity.setRemark("退款");
BigDecimal balance = new BigDecimal(i);
transactionDetailsEntity.setUserBalance(balance);
transactionDetailsService.save(transactionDetailsEntity);
log.info(">>>>>>>>>>>花生币退款成功<<<<<<<<<<<<<");
return R.ok();
}
@Override
public void businessOpt(BuyOrder order) {
//优惠卷回滚
if (order.getCouponId() != null) {
Integer couponId = order.getCouponId();
CouponHistoryEntity couponHistory = couponHistoryService.getById(couponId);
couponHistory.setUseStatus(0);
couponHistoryService.updateById(couponHistory);
}
//查询订单所有商品
QueryWrapper<BuyOrderProduct> w1 = new QueryWrapper<>();
w1.eq("order_id", order.getOrderId());
List<BuyOrderProduct> buyOrderProductList = buyOrderProductService.list(w1);
for (BuyOrderProduct buyOrderProduct : buyOrderProductList) {
//查询用户之前是否拥有书籍,如没有删除电子书
QueryWrapper<ShopProduct> w2 = new QueryWrapper<>();
w2.eq("product_id",buyOrderProduct.getProductId());
ShopProduct sp = shopProductService.getOne(w2);
if (sp!=null){
if (!"".equals(sp.getBookId())) {
String bookids[] = sp.getBookId().split(",");
if (bookids.length > 0){
for (int i=0;i < bookids.length; i++){
//查询这本书在哪些商品里
QueryWrapper<ShopProduct> w3 = new QueryWrapper<>();
w3.eq("book_ids",bookids[i])
.or().like("book_ids",","+bookids[i]+",")
.or().likeLeft("book_ids",","+bookids[i])
.or().likeRight("book_ids",bookids[i]+",");
List<ShopProduct> list = shopProductService.list(w3);
//查询此用户之前是否买过这些商品,并且剔除当前订单
if (list.size() > 0){
int flag = 0;
for (ShopProduct item : list) {
String arr[] = {item.getProductId().toString()};
if (isBought(order,arr)){
flag++;
}
}
//如果用户之前没买过此书,删除电子书权限
if (flag==0){
QueryWrapper<UserEbookBuyEntity> w5 = new QueryWrapper<>();
w5.eq("book_id",bookids[i]);
w5.eq("user_id",order.getUserId());
userEbookBuyService.remove(w5);
}
}
}
}
}
}
//查询用户之前是否拥有权限
//脉穴的权限0无权1有权
MyUserEntity userInfo = userService.getById(order.getUserId());
if (buyOrderProduct.getProductId()==128||buyOrderProduct.getProductId()==129 ||buyOrderProduct.getProductId()==130
||buyOrderProduct.getProductId()==131||buyOrderProduct.getProductId()==136){
String arr[] = {"128","129","130","131","136"};
if (!isBought(order,arr)){
userInfo.setPointPower(0);
userService.updateById(userInfo);
}
}
//时辰取穴权限 0没有1有
if (buyOrderProduct.getProductId()==133||buyOrderProduct.getProductId()==134
||buyOrderProduct.getProductId()==135){
String arr[] = {"133","134","135"};
if (!isBought(order,arr)){
userInfo.setTgdzPower(0);
userService.updateById(userInfo);
}
}
//五运六气的权限0无权1有权
if (buyOrderProduct.getProductId()==39||buyOrderProduct.getProductId()==62
||buyOrderProduct.getProductId()==123||buyOrderProduct.getProductId()==127){
String arr[] = {"39","62","123","127"};
if (!isBought(order, arr)){
userInfo.setWylqPower(0);
userService.updateById(userInfo);
}
}
//库存回滚
Integer productId = buyOrderProduct.getProductId();
ShopProduct product = shopProductService.getById(productId);
product.setProductStock(product.getProductStock() + buyOrderProduct.getQuantity());
shopProductService.updateById(product);
}
//订单设置交易失败状态并删除
order.setOrderStatus("4");
buyOrderService.saveOrUpdate(order);
buyOrderService.removeById(order.getOrderId());
}
//本订单的用户之前是否买过当前商品
public boolean isBought(BuyOrder order,String[] productId){
MPJLambdaWrapper<BuyOrder> w4 = new MPJLambdaWrapper<>();
w4.selectAll(BuyOrder.class);
w4.leftJoin(BuyOrderProduct.class,BuyOrderProduct::getOrderId,BuyOrder::getOrderId);
w4.in(BuyOrderProduct::getProductId,productId);
w4.eq(BuyOrder::getUserId,order.getUserId());
w4.ne(BuyOrder::getOrderId,order.getOrderId());
w4.in(BuyOrder::getOrderStatus,"1","2","3");
return buyOrderService.list(w4).size() > 0 ? true : false;
}
}

View File

@@ -53,6 +53,11 @@ public class WechatPayConfig implements Serializable {
*/
@Value("${wxpay.payUrl}")
private String payUrl;
/**
* pay url
*/
@Value("${wxpay.refundUrl}")
private String refundUrl;
/**
* 回调地址
*/

View File

@@ -1,5 +1,6 @@
package com.peanut.modules.pay.weChatPay.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -10,6 +11,7 @@ import com.peanut.modules.book.entity.*;
import com.peanut.modules.book.service.*;
import com.peanut.modules.pay.weChatPay.config.WechatPayConfig;
import com.peanut.modules.pay.weChatPay.dto.WechatPaymentInfo;
import com.peanut.modules.pay.weChatPay.service.WxpayService;
import com.peanut.modules.pay.weChatPay.util.HttpUtils;
import com.peanut.modules.pay.weChatPay.util.WechatPayValidator;
import com.peanut.modules.pay.weChatPay.util.WxPayUtil;
@@ -31,41 +33,26 @@ import java.util.stream.Collectors;
@CrossOrigin
@RequestMapping("/pay")
@Configuration
@Transactional(rollbackFor = Exception.class)
public class WeChatPayController {
@Autowired
private MyUserService userService;
@Autowired
private BuyOrderService buyOrderService;
@Autowired
private BuyOrderProductDao buyOrderProductDao;
@Autowired
@Lazy
private WechatPayConfig wechatPayConfig;
@Autowired
private BookBuyConfigService bookBuyConfigService;
@Autowired
private PayWechatOrderService payWechatOrderService;
@Autowired
private PayPaymentOrderService payPaymentOrderService;
@Autowired
private TransactionDetailsService transactionDetailsService;
@Autowired
private ShopProductBookService shopProductBookService;
@Autowired
private UserEbookBuyService userEbookBuyService;
@Autowired
private WxPayUtil wxPayUtil;
@Autowired
private WxpayService wxpayService;
/**
* 生成预订单
*
@@ -74,8 +61,7 @@ public class WeChatPayController {
* @throws Exception
*/
@RequestMapping(value = "/placeAnOrder/shoppingPay")
@Transactional(rollbackFor = Exception.class)
public R newShoppingPay(@RequestBody WechatPaymentInfo paymentInfo) {
public R newShoppingPay(@RequestBody WechatPaymentInfo paymentInfo){
QueryWrapper<BuyOrder> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("order_sn", paymentInfo.getOrderSn());
BuyOrder order = buyOrderService.getOne(queryWrapper);
@@ -114,122 +100,28 @@ public class WeChatPayController {
*/
@PostMapping("/payNotify")
@Transactional
public R payNotify(HttpServletRequest request, HttpServletResponse response) {
log.info("微信支付回调");
// 处理通知参数
Map<String, Object> bodyMap = getNotifyBody(request);
if (bodyMap == null) {
return null;
}
// 解密resource中的通知数据
String resource = bodyMap.get("resource").toString();
Map<String, Object> resourceMap = WechatPayValidator.decryptFromResource(resource, wechatPayConfig.getApiV3Key(), 1);
String orderNo = resourceMap.get("out_trade_no").toString();
// 根据订单号,做幂等处理,并且在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱
BuyOrder order = this.buyOrderService.getOne(new QueryWrapper<BuyOrder>().eq("order_sn", orderNo));
// 1.根据订单id获取订单信息
if ("order".equals(order.getOrderType())) {
BuyOrder orderEntity = buyOrderService.getBaseMapper().selectOne(new QueryWrapper<BuyOrder>().eq("order_sn", orderNo));
BigDecimal realMoney = orderEntity.getRealMoney();
// 查询订单的所有 book_id
List<Integer> orderBookIdList = shopProductBookService.getOrderBookId(order.getOrderSn());
// 去重
Set<Integer> set = new HashSet<>(orderBookIdList);
orderBookIdList.clear();
orderBookIdList.addAll(set);
// 查询用户的所有 book_id
List<Integer> userBookIdList = userEbookBuyService.getUserBookId(order.getUserId());
// 取差集
orderBookIdList.removeAll(userBookIdList);
// 为用户添加书籍
List<UserEbookBuyEntity> userEbookBuyEntities = new ArrayList<>();
for (Integer bookId : orderBookIdList) {
UserEbookBuyEntity entity = new UserEbookBuyEntity();
entity.setUserId(order.getUserId());
entity.setBookId(bookId);
userEbookBuyEntities.add(entity);
}
userEbookBuyService.saveBatch(userEbookBuyEntities);
//手摸脚模购买后会开启用户的脉穴的功能
List<Integer> collect = buyOrderProductDao.selectList(new LambdaQueryWrapper<BuyOrderProduct>().eq(BuyOrderProduct::getOrderId, order.getOrderId())).stream().map(BuyOrderProduct::getProductId).collect(Collectors.toList());
if(collect.contains(128)||collect.contains(129)||collect.contains(130)||collect.contains(131)||collect.contains(136)){
MyUserEntity userInfo = userService.getById(order.getUserId());
userInfo.setPointPower(1);
userService.updateById(userInfo);
}
if(collect.contains(133)||collect.contains(134)||collect.contains(135)){
MyUserEntity userInfo = userService.getById(order.getUserId());
userInfo.setTgdzPower(1);
userService.updateById(userInfo);
}
if(collect.contains(39)||collect.contains(62)||collect.contains(123)||collect.contains(127)){
MyUserEntity userInfo = userService.getById(order.getUserId());
userInfo.setWylqPower(1);
userService.updateById(userInfo);
}
public void payNotify(HttpServletRequest request, HttpServletResponse response){
wxpayService.payNotify(request);
}
/**
* 微信退款申请
*/
@RequestMapping("/refund" )
public R refund(@RequestBody Map<String,Object> map){
return R.ok(wxpayService.refund(map));
}
buyOrderService.updateOrderStatus(order.getUserId(), order.getOrderSn(), "0");
}
if ("point".equals(order.getOrderType())) {
PayWechatOrderEntity buy_order_id = payWechatOrderService.getBaseMapper().selectOne(new QueryWrapper<PayWechatOrderEntity>().eq("order_sn", order.getOrderSn()));
Integer buyorder = buy_order_id.getBuyOrderId();
BookBuyConfigEntity bookBuyConfigEntity = bookBuyConfigService.getById(buyorder);
String realMoney = bookBuyConfigEntity.getRealMoney();
int money = Integer.parseInt(realMoney);
userService.rechargeHSPoint(order.getUserId(), money);
TransactionDetailsEntity transactionDetailsEntity = new TransactionDetailsEntity();
transactionDetailsEntity.setUserId(order.getUserId());
transactionDetailsEntity.setChangeAmount(new BigDecimal(money));
transactionDetailsEntity.setOrderType("充值");
transactionDetailsEntity.setRelationId(buy_order_id.getId().intValue());
transactionDetailsEntity.setRemark("充值");
MyUserEntity user = userService.getById(order.getUserId());
BigDecimal peanutCoin = user.getPeanutCoin();
transactionDetailsEntity.setUserBalance(peanutCoin);
transactionDetailsEntity.setUserName(user.getNickname());
transactionDetailsEntity.setTel(user.getTel());
transactionDetailsService.save(transactionDetailsEntity);
// 插入 花生币 充值记录
PayPaymentOrderEntity payPaymentOrderEntity = new PayPaymentOrderEntity();
payPaymentOrderEntity.setUserId(order.getUserId());
payPaymentOrderEntity.setOrderId(String.valueOf(buy_order_id.getId()));
payPaymentOrderEntity.setRealAmount(new BigDecimal(bookBuyConfigEntity.getRealMoney()));
payPaymentOrderEntity.setRechargeAmount(new BigDecimal(bookBuyConfigEntity.getMoney()));
payPaymentOrderEntity.setRechargeChannel(bookBuyConfigEntity.getQudao());
payPaymentOrderEntity.setRechargeStatus("success");
payPaymentOrderEntity.setSuccessTime(new Date());
payPaymentOrderEntity.setUserName(user.getNickname());
payPaymentOrderEntity.setTel(user.getTel());
payPaymentOrderService.save(payPaymentOrderEntity);
buyOrderService.updateOrderStatus(order.getUserId(), order.getOrderSn(), "2");
}
// 成功应答
return R.ok();
/**
* 微信退款回调
* @return R
*/
@PostMapping("/refundNotify")
public void refundNotify(HttpServletRequest request){
wxpayService.refundNotify(request);
}
private Map<String, Object> getNotifyBody(HttpServletRequest request) {
// 处理通知参数
String body = HttpUtils.readData(request);
log.info("支付回调参数:{}", body);
// 转换为Map
Map<String, Object> bodyMap = JSONObject.parseObject(body, new TypeReference<Map<String, Object>>() {
});
// 微信的通知ID通知的唯一ID
String notifyId = bodyMap.get("id").toString();
// 验证签名信息
try {
WechatPayValidator wechatPayValidator = new WechatPayValidator(wechatPayConfig.getVerifier(), notifyId, body);
if (!wechatPayValidator.validate(request)) {
log.error("通知验签失败");
return null;
}
log.info("通知验签成功");
} catch (Exception e) {
log.error(e.getMessage());
}
return bodyMap;
}
}

View File

@@ -5,13 +5,19 @@ import com.peanut.modules.book.entity.PayWechatOrderEntity;
import com.peanut.modules.pay.weChatPay.dto.WechatPaymentInfo;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Map;
@Service
public interface WxpayService extends IService<PayWechatOrderEntity> {
void prepay(WechatPaymentInfo wechatDto) throws IOException;
void prepay(WechatPaymentInfo wechatDto);
void payNotify(HttpServletRequest request);
String refund(Map<String,Object> map);
void refundNotify(HttpServletRequest request);
}

View File

@@ -2,22 +2,34 @@ package com.peanut.modules.pay.weChatPay.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.peanut.common.exception.RRException;
import com.peanut.modules.book.dao.BuyOrderProductDao;
import com.peanut.modules.book.dao.PayWechatOrderDao;
import com.peanut.modules.book.entity.PayWechatOrderEntity;
import com.peanut.modules.book.service.PayWechatOrderService;
import com.peanut.modules.book.entity.*;
import com.peanut.modules.book.service.*;
import com.peanut.modules.pay.refund.entity.PayRefundOrder;
import com.peanut.modules.pay.refund.service.PayRefundOrderService;
import com.peanut.modules.pay.weChatPay.config.WechatPayConfig;
import com.peanut.modules.pay.weChatPay.dto.WechatPaymentInfo;
import com.peanut.modules.pay.weChatPay.service.WxpayService;
import com.peanut.modules.pay.weChatPay.util.HttpUtils;
import com.peanut.modules.pay.weChatPay.util.WechatPayValidator;
import com.peanut.modules.pay.weChatPay.util.WxPayUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Service
@@ -32,8 +44,33 @@ public class WxpayServiceImpl extends ServiceImpl<PayWechatOrderDao, PayWechatOr
@Autowired
private PayWechatOrderService payWechatOrderService;
@Autowired
private MyUserService userService;
@Autowired
private BuyOrderProductDao buyOrderProductDao;
@Autowired
private BookBuyConfigService bookBuyConfigService;
@Autowired
private PayPaymentOrderService payPaymentOrderService;
@Autowired
private TransactionDetailsService transactionDetailsService;
@Autowired
private ShopProductBookService shopProductBookService;
@Autowired
private UserEbookBuyService userEbookBuyService;
@Autowired
private BuyOrderService buyOrderService;
@Autowired
private PayRefundOrderService refundOrderService;
@Override
public void prepay(WechatPaymentInfo paymentInfo) throws IOException {
public void prepay(WechatPaymentInfo paymentInfo){
Map<String, Object> paramMap = new HashMap<>();
// app id
paramMap.put("appid", wechatPayConfig.getAppId());
@@ -65,4 +102,191 @@ public class WxpayServiceImpl extends ServiceImpl<PayWechatOrderDao, PayWechatOr
}
}
@Override
public void payNotify(HttpServletRequest request){
log.info("微信支付回调");
// 处理通知参数
Map<String, Object> bodyMap = getNotifyBody(request);
// 解密resource中的通知数据
String resource = bodyMap.get("resource").toString();
Map<String, Object> resourceMap = WechatPayValidator.decryptFromResource(resource, wechatPayConfig.getApiV3Key(), 1);
String orderNo = resourceMap.get("out_trade_no").toString();
//修改微信订单表
MPJLambdaWrapper<PayWechatOrderEntity> wrapper = new MPJLambdaWrapper();
wrapper.eq(PayWechatOrderEntity::getOrderSn,orderNo);
PayWechatOrderEntity payWechatOrderEntity = payWechatOrderService.getOne(wrapper);
payWechatOrderEntity.setOrderId(resourceMap.get("transaction_id").toString());
payWechatOrderService.updateById(payWechatOrderEntity);
// 根据订单号,做幂等处理,并且在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱
BuyOrder order = this.buyOrderService.getOne(new QueryWrapper<BuyOrder>().eq("order_sn", orderNo));
// 1.根据订单id获取订单信息
if ("order".equals(order.getOrderType())) {
BuyOrder orderEntity = buyOrderService.getBaseMapper().selectOne(new QueryWrapper<BuyOrder>().eq("order_sn", orderNo));
BigDecimal realMoney = orderEntity.getRealMoney();
// 查询订单的所有 book_id
List<Integer> orderBookIdList = shopProductBookService.getOrderBookId(order.getOrderSn());
// 去重
Set<Integer> set = new HashSet<>(orderBookIdList);
orderBookIdList.clear();
orderBookIdList.addAll(set);
// 查询用户的所有 book_id
List<Integer> userBookIdList = userEbookBuyService.getUserBookId(order.getUserId());
// 取差集
orderBookIdList.removeAll(userBookIdList);
// 为用户添加书籍
List<UserEbookBuyEntity> userEbookBuyEntities = new ArrayList<>();
for (Integer bookId : orderBookIdList) {
UserEbookBuyEntity entity = new UserEbookBuyEntity();
entity.setUserId(order.getUserId());
entity.setBookId(bookId);
userEbookBuyEntities.add(entity);
}
userEbookBuyService.saveBatch(userEbookBuyEntities);
//手摸脚模购买后会开启用户的脉穴的功能
List<Integer> collect = buyOrderProductDao.selectList(new LambdaQueryWrapper<BuyOrderProduct>().eq(BuyOrderProduct::getOrderId, order.getOrderId())).stream().map(BuyOrderProduct::getProductId).collect(Collectors.toList());
if(collect.contains(128)||collect.contains(129)||collect.contains(130)||collect.contains(131)||collect.contains(136)){
MyUserEntity userInfo = userService.getById(order.getUserId());
userInfo.setPointPower(1);
userService.updateById(userInfo);
}
if(collect.contains(133)||collect.contains(134)||collect.contains(135)){
MyUserEntity userInfo = userService.getById(order.getUserId());
userInfo.setTgdzPower(1);
userService.updateById(userInfo);
}
if(collect.contains(39)||collect.contains(62)||collect.contains(123)||collect.contains(127)){
MyUserEntity userInfo = userService.getById(order.getUserId());
userInfo.setWylqPower(1);
userService.updateById(userInfo);
}
buyOrderService.updateOrderStatus(order.getUserId(), order.getOrderSn(), "0");
}
if ("point".equals(order.getOrderType())) {
PayWechatOrderEntity buy_order_id = payWechatOrderService.getBaseMapper().selectOne(new QueryWrapper<PayWechatOrderEntity>().eq("order_sn", order.getOrderSn()));
Integer buyorder = buy_order_id.getBuyOrderId();
BookBuyConfigEntity bookBuyConfigEntity = bookBuyConfigService.getById(buyorder);
String realMoney = bookBuyConfigEntity.getRealMoney();
int money = Integer.parseInt(realMoney);
userService.rechargeHSPoint(order.getUserId(), money);
TransactionDetailsEntity transactionDetailsEntity = new TransactionDetailsEntity();
transactionDetailsEntity.setUserId(order.getUserId());
transactionDetailsEntity.setChangeAmount(new BigDecimal(money));
transactionDetailsEntity.setOrderType("充值");
transactionDetailsEntity.setRelationId(buy_order_id.getId().intValue());
transactionDetailsEntity.setRemark("充值");
MyUserEntity user = userService.getById(order.getUserId());
BigDecimal peanutCoin = user.getPeanutCoin();
transactionDetailsEntity.setUserBalance(peanutCoin);
transactionDetailsEntity.setUserName(user.getNickname());
transactionDetailsEntity.setTel(user.getTel());
transactionDetailsService.save(transactionDetailsEntity);
// 插入 花生币 充值记录
PayPaymentOrderEntity payPaymentOrderEntity = new PayPaymentOrderEntity();
payPaymentOrderEntity.setUserId(order.getUserId());
payPaymentOrderEntity.setOrderId(String.valueOf(buy_order_id.getId()));
payPaymentOrderEntity.setRealAmount(new BigDecimal(bookBuyConfigEntity.getRealMoney()));
payPaymentOrderEntity.setRechargeAmount(new BigDecimal(bookBuyConfigEntity.getMoney()));
payPaymentOrderEntity.setRechargeChannel(bookBuyConfigEntity.getQudao());
payPaymentOrderEntity.setRechargeStatus("success");
payPaymentOrderEntity.setSuccessTime(new Date());
payPaymentOrderEntity.setUserName(user.getNickname());
payPaymentOrderEntity.setTel(user.getTel());
payPaymentOrderService.save(payPaymentOrderEntity);
buyOrderService.updateOrderStatus(order.getUserId(), order.getOrderSn(), "2");
}
}
@Override
public String refund(Map<String,Object> map){
LambdaQueryWrapper<PayWechatOrderEntity> wrapper = new LambdaQueryWrapper();
wrapper.eq(PayWechatOrderEntity::getOrderSn,map.get("orderSn").toString());
PayWechatOrderEntity order = payWechatOrderService.getOne(wrapper);
Map<String, Object> paramMap = new HashMap<>();
//构建订单金额信息
//退款金额
BigDecimal refund = new BigDecimal(map.get("refundFee").toString());
//原订单总金额
BigDecimal total = order.getTotalAmount();
// 这里 * 100微信支付单位为 ‘分’
BigDecimal hand = new BigDecimal("100");
Map<String, Object> amountMap = new HashMap<>();
amountMap.put("refund", refund.multiply(hand));
amountMap.put("total", total.multiply(hand).intValue());
amountMap.put("currency", "CNY");
paramMap.put("amount", amountMap);
//商户退款单号 商户系统内 部的退款单号商户系统内部唯一只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔。
// paramMap.put("out_refund_no", map.get("outRefundNo").toString());
paramMap.put("out_refund_no", UUID.randomUUID().toString());
//微信支付订单号
paramMap.put("transaction_id", order.getOrderId());
//退款原因
paramMap.put("reason", map.get("reason").toString());
// 微信退款回调地址
paramMap.put("notify_url", wechatPayConfig.getRefundNotifyUrl());
JSONObject json = JSONObject.parseObject(JSON.toJSONString(paramMap));
log.info("微信退款申请请求参数:{}", paramMap);
log.info(">>>>>>>>>>App请求微信退款申请接口");
JSONObject responseJson = wxPayUtil.doPostWexinV3(wechatPayConfig.getRefundUrl(), json.toJSONString());
log.info(">>>>>>>>>>>微信退款返回的信息是 resJson = {}", responseJson.toJSONString());
if ("SUCCESS".equals(responseJson.get("status"))){
//退款申请成功,等待到账
}
return responseJson.toJSONString();
}
@Override
@Transactional
public void refundNotify(HttpServletRequest request){
log.info("微信退款回调");
// 处理通知参数
Map<String, Object> bodyMap = getNotifyBody(request);
// 解密resource中的通知数据
String resource = bodyMap.get("resource").toString();
Map<String, Object> resourceMap = WechatPayValidator.decryptFromResource(resource, wechatPayConfig.getApiV3Key(), 2);
log.info("微信退款回调结果 msg={}",resourceMap);
if ("SUCCESS".equals(resourceMap.get("refund_status").toString())){
log.info(">>>>>>>>>>>微信退款成功!<<<<<<<<<<<<<");
MPJLambdaWrapper<BuyOrder> w = new MPJLambdaWrapper();
w.selectAll(BuyOrder.class);
w.leftJoin(PayWechatOrderEntity.class,PayWechatOrderEntity::getOrderSn, BuyOrder::getOrderSn);
w.eq("t1.order_id",resourceMap.get("transaction_id").toString());
BuyOrder order = buyOrderService.getOne(w);
PayRefundOrder refund = new PayRefundOrder();
refund.setPayType("1");
refund.setOrderId(order.getOrderId());
refund.setTradeNo(resourceMap.get("transaction_id").toString());
refund.setOutTradeNo(resourceMap.get("out_trade_no").toString());
refund.setRefundFee(((Map)resourceMap.get("amount")).get("refund").toString());
refundOrderService.save(refund);
refundOrderService.businessOpt(order);
}
}
private Map<String, Object> getNotifyBody(HttpServletRequest request) {
// 处理通知参数
String body = HttpUtils.readData(request);
log.info("支付回调参数:{}", body);
// 转换为Map
Map<String, Object> bodyMap = JSONObject.parseObject(body, new TypeReference<Map<String, Object>>() {
});
// 微信的通知ID通知的唯一ID
String notifyId = bodyMap.get("id").toString();
// 验证签名信息
try {
WechatPayValidator wechatPayValidator = new WechatPayValidator(wechatPayConfig.getVerifier(), notifyId, body);
if (!wechatPayValidator.validate(request)) {
log.error("通知验签失败");
return null;
}
log.info("通知验签成功");
} catch (Exception e) {
log.error(e.getMessage());
}
return bodyMap;
}
}

View File

@@ -80,7 +80,8 @@ wxpay:
mchId: 1612860909
payUrl: https://api.mch.weixin.qq.com/v3/pay/transactions/app
notifyUrl: https://testapi.nuttyreading.com/pay/payNotify
refundNotifyUrl: http://pjm6m9.natappfree.cc/pay/refundNotify
refundUrl: https://api.mch.weixin.qq.com/v3/refund/domestic/refunds
refundNotifyUrl: https://testapi.nuttyreading.com/pay/refundNotify
keyPemPath: D:/hs/nuttyreading-java/src/main/resources/cent/apiclient_key.pem
serialNo: 679AECB2F7AC4183033F713828892BA640E4EEE3
apiV3Key: 4aYFklzaULeGlr7oJPZ6rHWKcxjihZUF

View File

@@ -36,6 +36,8 @@ spring:
pool:
core-size: 5
max-size: 50
main:
allow-circular-references: true
#mybatis
mybatis-plus: