新增:牛八哥专用支付回调页面

This commit is contained in:
2024-07-31 03:02:57 +08:00
parent 7f17c4047f
commit e38489e567
10 changed files with 218 additions and 92 deletions
@@ -133,7 +133,7 @@ public class FieldController extends BaseController {
// 订单信息 // 订单信息
final Order order = orderService.getByOutTradeNo(orderNo); final Order order = orderService.getByOutTradeNo(orderNo);
order.setOrderInfo(orderInfoService.list(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderId,order.getOrderId()))); order.setOrderInfo(orderInfoService.list(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderId,order.getOrderId())));
System.out.println("order = " + order); // System.out.println("order = " + order);
if (order.getPayStatus().equals(0)) { if (order.getPayStatus().equals(0)) {
return fail("该订单未支付"); return fail("该订单未支付");
} }
@@ -64,6 +64,8 @@ public class MybatisPlusConfig {
"sys_dictionary", "sys_dictionary",
"sys_dictionary_data", "sys_dictionary_data",
"apps_test_data" "apps_test_data"
// "shop_order_goods",
// "shop_goods"
// "shop_users", // "shop_users",
// "shop_order", // "shop_order",
// "shop_order_info", // "shop_order_info",
@@ -76,6 +78,7 @@ public class MybatisPlusConfig {
// 分页插件配置 // 分页插件配置
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL); PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
paginationInnerInterceptor.setMaxLimit(2000L);
interceptor.addInnerInterceptor(paginationInnerInterceptor); interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor; return interceptor;
@@ -4,12 +4,14 @@ import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.gxwebsoft.common.core.security.JwtUtil; import com.gxwebsoft.common.core.security.JwtUtil;
import com.gxwebsoft.common.core.web.ApiResult; import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.system.entity.Payment;
import com.gxwebsoft.common.system.entity.Role; import com.gxwebsoft.common.system.entity.Role;
import com.gxwebsoft.common.system.entity.User; import com.gxwebsoft.common.system.entity.User;
import com.gxwebsoft.common.system.entity.UserRole; import com.gxwebsoft.common.system.entity.UserRole;
import com.gxwebsoft.common.system.param.RoleParam; import com.gxwebsoft.common.system.param.RoleParam;
import com.gxwebsoft.shop.entity.MerchantAccount; import com.gxwebsoft.shop.entity.MerchantAccount;
import com.gxwebsoft.shop.entity.Order; import com.gxwebsoft.shop.entity.Order;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
import org.springframework.http.*; import org.springframework.http.*;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestClientException;
@@ -34,6 +36,26 @@ public class RequestUtil {
ACCESS_TOKEN = token; ACCESS_TOKEN = token;
} }
// 微信支付通知
public void pushWxPayNotify(Transaction transaction){
System.out.println("transaction = " + transaction);
// 设置租户ID
// setTenantId(payment.getTenantId().toString());
// 推送支付通知地址
// String path = payment.getNotifyUrl();
try {
// 链式构建请求
String result = HttpRequest.post("http://pxf4av.natappfree.cc/api/shop/wx-pay/nbg/paySuccess")
.header("Tenantid", "10158")
.body(JSONUtil.toJSONString(transaction))//表单内容
.timeout(20000)//超时,毫秒
.execute().body();
} catch (Exception e) {
e.printStackTrace();
}
}
public User getUserByPhone(String phone) { public User getUserByPhone(String phone) {
String path = "/system/user/getByPhone/" + phone; String path = "/system/user/getByPhone/" + phone;
try { try {
@@ -153,7 +153,6 @@ public class OrderController extends BaseController {
@ApiOperation("下单") @ApiOperation("下单")
@PostMapping() @PostMapping()
public ApiResult<?> save(@RequestBody Order order, HttpServletRequest request) { public ApiResult<?> save(@RequestBody Order order, HttpServletRequest request) {
System.out.println("order = " + order);
String access_token = JwtUtil.getAccessToken(request); String access_token = JwtUtil.getAccessToken(request);
// 记录当前登录用户id // 记录当前登录用户id
User loginUser = getLoginUser(); User loginUser = getLoginUser();
@@ -253,7 +252,7 @@ public class OrderController extends BaseController {
goods.setExpirationTime(order.getExpirationTime()); goods.setExpirationTime(order.getExpirationTime());
orderGoods.add(goods); orderGoods.add(goods);
}); });
System.out.println("carts = " + carts); // System.out.println("carts = " + carts);
order.setGoodsList(orderGoods); order.setGoodsList(orderGoods);
} }
orderGoodsService.saveBatch(order.getGoodsList()); orderGoodsService.saveBatch(order.getGoodsList());
@@ -82,6 +82,9 @@ public class WxPayNotifyController extends BaseController {
.body(body) .body(body)
.build(); .build();
System.out.println("payment = " + payment);
System.out.println("requestParam = " + requestParam);
// 如果已经初始化了 RSAAutoCertificateConfig,可直接使用 // 如果已经初始化了 RSAAutoCertificateConfig,可直接使用
// 没有的话,则构造一个 // 没有的话,则构造一个
NotificationConfig config = new RSANotificationConfig.Builder() NotificationConfig config = new RSANotificationConfig.Builder()
@@ -0,0 +1,103 @@
package com.gxwebsoft.shop.controller;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.gxwebsoft.common.core.utils.RedisUtil;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.shop.entity.Goods;
import com.gxwebsoft.shop.entity.Order;
import com.gxwebsoft.shop.entity.OrderGoods;
import com.gxwebsoft.shop.entity.OrderInfo;
import com.gxwebsoft.shop.service.*;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 会员特权购买记录表控制器
*
* @author 科技小王子
* @since 2023-06-20 18:07:50
*/
@Api(tags = "微信支付结果通知")
@RestController
@RequestMapping("/api/shop/wx-pay/nbg")
public class WxPayNotifyNbgController extends BaseController {
@Resource
private OrderService orderService;
@Resource
private OrderInfoService orderInfoService;
@Resource
private OrderGoodsService orderGoodsService;
@Resource
private GoodsService goodsService;
@Resource
private UsersService usersService;
@Resource
private RedisUtil redisUtil;
@ApiModelProperty("微信支付通知")
@PostMapping("/notify")
public String demo(@RequestBody Transaction transaction){
System.out.println("支付通知 >>>>> ");
System.out.println("transaction = " + transaction);
// TODO 1.查询订单信息
final Order order = orderService.getByOutTradeNo(transaction.getOutTradeNo());
// TODO 2.更新订单支付状态
order.setPayStatus(1);
order.setTransactionId(transaction.getTransactionId());
order.setPayPrice(new BigDecimal(NumberUtil.decimalFormat("0.00", transaction.getAmount().getTotal() * 0.01)));
order.setPayTime(DateUtil.date());
order.setExpirationTime(DateUtil.offset(DateUtil.date(), DateField.YEAR, 10));
orderService.updateById(order);
// TODO 3.更新订单商品的支付状态
if (order.getType().equals(0)) {
final boolean update = orderGoodsService.update(new LambdaUpdateWrapper<OrderGoods>().eq(OrderGoods::getOrderId, order.getOrderId()).set(OrderGoods::getPayStatus, 1));
System.out.println("update1 = " + update);
// TODO 3.1 更新商品销量、库存数量
final List<OrderGoods> orderGoods = orderGoodsService.list(new LambdaQueryWrapper<OrderGoods>().eq(OrderGoods::getOrderId, order.getOrderId()));
final Set<Integer> goodsIds = orderGoods.stream().map(OrderGoods::getGoodsId).collect(Collectors.toSet());
final Map<Integer, List<OrderGoods>> collectGoods = orderGoods.stream().collect(Collectors.groupingBy(OrderGoods::getGoodsId));
final List<Goods> goods = goodsService.list(new LambdaQueryWrapper<Goods>().in(Goods::getGoodsId, goodsIds));
for (Goods g : goods) {
final List<OrderGoods> goods1 = collectGoods.get(g.getGoodsId());
final OrderGoods goods2 = goods1.get(0);
g.setSales(g.getSales() + goods2.getTotalNum());
if (g.getStock().compareTo(0) >= 0) {
g.setStock(g.getStock() - goods2.getTotalNum());
}
}
final boolean batchById = goodsService.updateBatchById(goods);
System.out.println("batchById = " + batchById);
}
if (order.getType().equals(1)) {
final boolean update = orderInfoService.update(new LambdaUpdateWrapper<OrderInfo>().eq(OrderInfo::getOrderId, order.getOrderId()).set(OrderInfo::getPayStatus, 1));
System.out.println("update2 = " + update);
// TODO 3.2 更新订单类型为预定的关联订单信息
}
// TODO 5.累计会员积分
return "订单已支付";
}
}
@@ -45,7 +45,7 @@ public interface OrderService extends IService<Order> {
Order getByOutTradeNo(String outTradeNo); Order getByOutTradeNo(String outTradeNo);
void updateByOutTradeNo(Order order); Boolean updateByOutTradeNo(Order order);
Boolean payByBalance(Order order); Boolean payByBalance(Order order);
@@ -79,9 +79,13 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
private SettingService settingService; private SettingService settingService;
@Resource @Resource
private RedisUtil redisUtil; private RedisUtil redisUtil;
public static String privateKeyPath = "/Users/gxwebsoft/JAVA/com.gxwebsoft.modules/src/main/resources/cert/apiclient_key.pem"; // public static String privateKeyPath = "/Users/gxwebsoft/JAVA/com.gxwebsoft.modules/src/main/resources/cert/apiclient_key.pem";
// public static String privateCertPath = "/Users/gxwebsoft/JAVA/com.gxwebsoft.core/src/main/resources/cert/apiclient_cert.pem";
// public static String wechatpayCertPath = "/Users/gxwebsoft/JAVA/com.gxwebsoft.modules/src/main/resources/cert/wechatpay_2DD5A0669263BAE55E52BF3F35BF4A4006A2DAA6.pem"; // 平台证书
public static String privateKeyPath = "/Users/gxwebsoft/Downloads/ef7f7e0430cb47019d06b93f885bf95f/apiclient_key.pem";
public static String privateCertPath = "/Users/gxwebsoft/JAVA/com.gxwebsoft.core/src/main/resources/cert/apiclient_cert.pem"; public static String privateCertPath = "/Users/gxwebsoft/JAVA/com.gxwebsoft.core/src/main/resources/cert/apiclient_cert.pem";
public static String wechatpayCertPath = "/Users/gxwebsoft/JAVA/com.gxwebsoft.modules/src/main/resources/cert/wechatpay_2DD5A0669263BAE55E52BF3F35BF4A4006A2DAA6.pem"; // 平台证书 public static String wechatpayCertPath = "/Users/gxwebsoft/Downloads/ef7f7e0430cb47019d06b93f885bf95f/wechatpay_55729BDEC2502C301BA02CDC28E4CEE4DE4D1DB9.pem"; // 平台证书
@Override @Override
@@ -178,12 +182,12 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
// 微信小程序(微信支付) // 微信小程序(微信支付)
String key = "mp-weixin:".concat(order.getTenantId().toString()); String key = "mp-weixin:".concat(order.getTenantId().toString());
final String string = redisUtil.get(key); final String string = redisUtil.get(key);
System.out.println("string = " + string); // System.out.println("string = " + string);
final JSONObject mpWx = JSONObject.parseObject(string); final JSONObject mpWx = JSONObject.parseObject(string);
System.out.println("mpWx = " + mpWx); // System.out.println("mpWx = " + mpWx);
String key2 = "Payment:".concat(order.getPayType().toString()).concat(":").concat(order.getTenantId().toString()); String key2 = "Payment:".concat(order.getPayType().toString()).concat(":").concat(order.getTenantId().toString());
final Payment payment = redisUtil.get(key2, Payment.class); final Payment payment = redisUtil.get(key2, Payment.class);
System.out.println("payment = " + payment); // System.out.println("payment = " + payment);
// 计算金额 // 计算金额
BigDecimal decimal = order.getTotalPrice(); BigDecimal decimal = order.getTotalPrice();
@@ -231,12 +235,12 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
if (active.equals("prod")) { if (active.equals("prod")) {
amount.setTotal(2); amount.setTotal(2);
request.setAmount(amount); request.setAmount(amount);
request.setNotifyUrl("https://modules.gxwebsoft.com/api/shop/wx-pay/notify/" + order.getTenantId()); // 默认回调地址 request.setNotifyUrl("https://server.gxwebsoft.com/api/system/wx-pay/notify/" + order.getTenantId()); // 默认回调地址
} }
if (StrUtil.isNotBlank(payment.getNotifyUrl())) { // if (StrUtil.isNotBlank(payment.getNotifyUrl())) {
// 后台配置的回调地址 // 后台配置的回调地址
request.setNotifyUrl(payment.getNotifyUrl().concat("/").concat(order.getTenantId().toString())); // request.setNotifyUrl(payment.getNotifyUrl().concat("/").concat(order.getTenantId().toString()));
} // }
System.out.println("request = " + request); System.out.println("request = " + request);
PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request); PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);
orderInfo.put("provider", "wxpay"); orderInfo.put("provider", "wxpay");
@@ -258,8 +262,9 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
} }
@Override @Override
public void updateByOutTradeNo(Order order) { public Boolean updateByOutTradeNo(Order order) {
baseMapper.updateByOutTradeNo(order); baseMapper.updateByOutTradeNo(order);
return true;
} }
@Override @Override
@@ -1,75 +0,0 @@
package com.gxwebsoft.shop.task;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.shop.entity.Order;
import com.gxwebsoft.shop.entity.OrderInfo;
import com.gxwebsoft.shop.service.OrderInfoService;
import com.gxwebsoft.shop.service.OrderService;
import io.swagger.annotations.Api;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
/**
* 订单结算任务
*
* @author 科技小王子
* @since 2024-05-14 13:20:04
*/
@Api(tags = "订单结算任务")
@RestController
@RequestMapping("/api/shop/order-info")
public class OrderInfoTask extends BaseController {
@Resource
private OrderService orderService;
@Resource
private OrderInfoService orderInfoService;
/**
* 自动处理过期订单任务
*/
// @Scheduled(cron="*/10 * * * * *")
@Transactional(rollbackFor = {Exception.class})
public void settledExpirationOrder() {
final Order order = new Order();
final int hour = DateUtil.hour(DateUtil.date(), true);
final int minute = DateUtil.minute(DateUtil.date());
final int second = DateUtil.second(DateUtil.date());
final String startTime = String.format("%02d", hour).concat(":").concat(String.format("%02d", minute)).concat(":").concat(String.format("%02d", second));
final List<OrderInfo> list = orderInfoService.list(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderStatus, 0).ne(OrderInfo::getMerchantId,3028).eq(OrderInfo::getDateTime,DateUtil.today()).lt(OrderInfo::getStartTime,startTime));
list.forEach(d -> {
d.setOrderStatus(1);
order.setOrderId(d.getOrderId());
});
orderInfoService.updateBatchById(list);
order.setOrderStatus(1);
orderService.updateById(order);
System.out.println("自动核销订单 = " + list.size());
}
/**
* 自动处理过期订单任务(游泳馆专用)
* Scheduled(cron="0 30 21 * * ?")
*/
// @Scheduled(cron="*/30 * * * * *")
@Transactional(rollbackFor = {Exception.class})
public void settledExpirationOrderBy3028() {
final Order order = new Order();
final List<OrderInfo> list = orderInfoService.list(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getTenantId,10150).eq(OrderInfo::getOrderStatus, 0).eq(OrderInfo::getMerchantId,3028).eq(OrderInfo::getDateTime,DateUtil.today()).lt(OrderInfo::getStartTime,"21:30:00"));
list.forEach(d -> {
d.setOrderStatus(1);
order.setOrderId(d.getOrderId());
});
orderInfoService.updateBatchById(list);
if(!CollectionUtils.isEmpty(list)){
orderService.updateById(order);
}
System.out.println("自动核销订单(游泳馆) = " + list.size());
}
}
@@ -1,12 +1,16 @@
package com.gxwebsoft.shop.task; package com.gxwebsoft.shop.task;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.common.core.web.BaseController; import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.shop.entity.Order; import com.gxwebsoft.shop.entity.Order;
import com.gxwebsoft.shop.entity.OrderInfo;
import com.gxwebsoft.shop.mapper.OrderMapper; import com.gxwebsoft.shop.mapper.OrderMapper;
import com.gxwebsoft.shop.param.OrderParam; import com.gxwebsoft.shop.param.OrderParam;
import com.gxwebsoft.shop.service.OrderInfoService;
import com.gxwebsoft.shop.service.OrderService; import com.gxwebsoft.shop.service.OrderService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
@@ -26,16 +30,39 @@ import java.util.List;
@RestController @RestController
@RequestMapping("/api/shop/order") @RequestMapping("/api/shop/order")
public class OrderTask extends BaseController { public class OrderTask extends BaseController {
@Value("${spring.profiles.active}")
String active;
@Resource @Resource
private OrderService orderService; private OrderService orderService;
@Resource @Resource
private OrderMapper orderMapper; private OrderMapper orderMapper;
@Resource
private OrderInfoService orderInfoService;
/** /**
* 自动处理过期订单任务 * 订单任务列表
*/ */
@Scheduled(fixedDelay = 2000, initialDelay = 2000) @Scheduled(cron = "*/10 * * * * *")
@Transactional(rollbackFor = {Exception.class}) public void orderTask() {
// 自动处理过期的预定订单
// this.settledExpirationOrder();
}
/**
* 自动核销订单
*/
@Scheduled(cron = "*/30 * * * * *")
public void writeOff() {
// 自动核销订单
// this.orderWriteOff();
}
// 自动处理过期订单任务
public void settledExpirationOrder() { public void settledExpirationOrder() {
if (active.equals("dev")) {
return;
}
final OrderParam p = new OrderParam(); final OrderParam p = new OrderParam();
p.setOrderStatus(0); p.setOrderStatus(0);
p.setExpirationTime(DateUtil.date()); p.setExpirationTime(DateUtil.date());
@@ -49,4 +76,43 @@ public class OrderTask extends BaseController {
System.out.println("自动处理过期订单 = " + list.size()); System.out.println("自动处理过期订单 = " + list.size());
} }
} }
public void settledExpirationOrderBy3028() {
if (active.equals("dev")) {
return;
}
final Order order = new Order();
final List<OrderInfo> list = orderInfoService.list(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getTenantId, 10150).eq(OrderInfo::getOrderStatus, 0).eq(OrderInfo::getMerchantId, 3028).eq(OrderInfo::getDateTime, DateUtil.today()).lt(OrderInfo::getStartTime, "21:30:00"));
list.forEach(d -> {
d.setOrderStatus(1);
order.setOrderId(d.getOrderId());
});
orderInfoService.updateBatchById(list);
if (!CollectionUtils.isEmpty(list)) {
orderService.updateById(order);
}
System.out.println("自动核销订单(游泳馆) = " + list.size());
}
// 自动核销订单
public void orderWriteOff() {
if (active.equals("dev")) {
return;
}
final Order order = new Order();
final int hour = DateUtil.hour(DateUtil.date(), true);
final int minute = DateUtil.minute(DateUtil.date());
final int second = DateUtil.second(DateUtil.date());
final String startTime = String.format("%02d", hour).concat(":").concat(String.format("%02d", minute)).concat(":").concat(String.format("%02d", second));
final List<OrderInfo> list = orderInfoService.list(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderStatus, 0).ne(OrderInfo::getMerchantId, 3028).eq(OrderInfo::getDateTime, DateUtil.today()).lt(OrderInfo::getStartTime, startTime));
list.forEach(d -> {
d.setOrderStatus(1);
order.setOrderId(d.getOrderId());
});
orderInfoService.updateBatchById(list);
order.setOrderStatus(1);
orderService.updateById(order);
System.out.println("自动核销订单 = " + list.size());
}
} }