"vscode:/vscode.git/clone" did not exist on "5295f90990a57b43bd5f9b08a99345acc474345b"
Commit 516d19da authored by Junling Bu's avatar Junling Bu
Browse files

update[litemall-wx-api]: 小商场后台服务支付微信支付。

1. 根据小程序端请求,和微信支付平台交互,生产预支付会话ID并返回给小程序端。
2. 微信支付平台支付成功以后,向小商场后台服务确认,进行响应处理。
parent c4d3009a
...@@ -62,6 +62,7 @@ public class LitemallOrderService { ...@@ -62,6 +62,7 @@ public class LitemallOrderService {
return (int)orderMapper.countByExample(example); return (int)orderMapper.countByExample(example);
} }
// TODO 这里应该产生一个唯一的订单,但是实际上这里仍然存在两个订单相同的可能性
public String generateOrderSn(Integer userId) { public String generateOrderSn(Integer userId) {
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMdd"); DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMdd");
String now = df.format(LocalDate.now()); String now = df.format(LocalDate.now());
...@@ -160,4 +161,10 @@ public class LitemallOrderService { ...@@ -160,4 +161,10 @@ public class LitemallOrderService {
example.or().andOrderStatusEqualTo(OrderUtil.STATUS_SHIP).andShipEndTimeIsNotNull().andDeletedEqualTo(false); example.or().andOrderStatusEqualTo(OrderUtil.STATUS_SHIP).andShipEndTimeIsNotNull().andDeletedEqualTo(false);
return orderMapper.selectByExample(example); return orderMapper.selectByExample(example);
} }
public LitemallOrder findBySn(String orderSn) {
LitemallOrderExample example = new LitemallOrderExample();
example.or().andOrderSnEqualTo(orderSn).andDeletedEqualTo(false);
return orderMapper.selectOneByExample(example);
}
} }
package org.linlinjava.litemall.wx.web; package org.linlinjava.litemall.wx.web;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult;
import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.BaseWxPayResult;
import com.github.binarywang.wxpay.service.WxPayService;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.db.domain.*; import org.linlinjava.litemall.db.domain.*;
...@@ -18,6 +27,8 @@ import org.springframework.transaction.support.DefaultTransactionDefinition; ...@@ -18,6 +27,8 @@ import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.LocalDateTime; import java.time.LocalDateTime;
...@@ -52,6 +63,8 @@ public class WxOrderController { ...@@ -52,6 +63,8 @@ public class WxOrderController {
@Autowired @Autowired
private PlatformTransactionManager txManager; private PlatformTransactionManager txManager;
@Autowired
private LitemallUserService userService;
@Autowired @Autowired
private LitemallOrderService orderService; private LitemallOrderService orderService;
@Autowired @Autowired
...@@ -65,6 +78,9 @@ public class WxOrderController { ...@@ -65,6 +78,9 @@ public class WxOrderController {
@Autowired @Autowired
private LitemallProductService productService; private LitemallProductService productService;
@Autowired
private WxPayService wxPayService;
public WxOrderController() { public WxOrderController() {
} }
...@@ -290,9 +306,10 @@ public class WxOrderController { ...@@ -290,9 +306,10 @@ public class WxOrderController {
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = txManager.getTransaction(def); TransactionStatus status = txManager.getTransaction(def);
Integer orderId = null; Integer orderId = null;
LitemallOrder order = null;
try { try {
// 订单 // 订单
LitemallOrder order = new LitemallOrder(); order = new LitemallOrder();
order.setUserId(userId); order.setUserId(userId);
order.setOrderSn(orderService.generateOrderSn(userId)); order.setOrderSn(orderService.generateOrderSn(userId));
order.setAddTime(LocalDateTime.now()); order.setAddTime(LocalDateTime.now());
...@@ -356,50 +373,6 @@ public class WxOrderController { ...@@ -356,50 +373,6 @@ public class WxOrderController {
return ResponseUtil.ok(data); return ResponseUtil.ok(data);
} }
/**
* 付款订单
*
* 1. 检测当前订单是否能够付款
* 2. 微信支付平台返回支付订单ID
* 3. 设置订单付款状态
* TODO 与微信后台交互产生付款订单ID,以及不同的付款状态
* 目前这里直接设置订单已付款状态模拟支付成功
*
* @param userId 用户ID
* @param body 订单信息,{ orderId:xxx }
* @return 订单操作结果
* 成功则 { errno: 0, errmsg: '模拟付款支付成功' }
* 失败则 { errno: XXX, errmsg: XXX }
*/
@RequestMapping("pay")
public Object payPrepay(@LoginUser Integer userId, @RequestBody String body) {
if(userId == null){
return ResponseUtil.unlogin();
}
Integer orderId = JacksonUtil.parseInteger(body, "orderId");
if (orderId == null) {
return ResponseUtil.badArgument();
}
LitemallOrder order = orderService.findById(orderId);
if (order == null) {
return ResponseUtil.badArgumentValue();
}
if (!order.getUserId().equals(userId)) {
return ResponseUtil.badArgumentValue();
}
// 检测是否能够取消
OrderHandleOption handleOption = OrderUtil.build(order);
if (!handleOption.isPay()) {
return ResponseUtil.fail(403, "订单不能支付");
}
order.setPayStatus(OrderUtil.STATUS_PAY);
orderService.updateById(order);
return ResponseUtil.ok("模拟付款支付成功");
}
/** /**
* 取消订单 * 取消订单
* 1. 检测当前订单是否能够取消 * 1. 检测当前订单是否能够取消
...@@ -466,20 +439,21 @@ public class WxOrderController { ...@@ -466,20 +439,21 @@ public class WxOrderController {
} }
/** /**
* 付款 * 付款订单的预支付会话标识
*
* 1. 检测当前订单是否能够付款 * 1. 检测当前订单是否能够付款
* 2. 设置订单付款状态 * 2. 微信支付平台返回支付订单ID
* 3. TODO 微信后台申请支付,同时设置付款状态 * 3. 设置订单付款状态
* *
* @param userId 用户ID * @param userId 用户ID
* @param body 订单信息,{ orderId:xxx } * @param body 订单信息,{ orderId:xxx }
* @return 订单操作结果 * @return 订单操作结果
* 成功则 { errno: 0, errmsg: '成功' } * 成功则 { errno: 0, errmsg: '模拟付款支付成功' }
* 失败则 { errno: XXX, errmsg: XXX } * 失败则 { errno: XXX, errmsg: XXX }
*/ */
@PostMapping("pay") @PostMapping("prepay")
public Object pay(@LoginUser Integer userId, @RequestBody String body) { public Object prepay(@LoginUser Integer userId, @RequestBody String body) {
if (userId == null) { if(userId == null){
return ResponseUtil.unlogin(); return ResponseUtil.unlogin();
} }
Integer orderId = JacksonUtil.parseInteger(body, "orderId"); Integer orderId = JacksonUtil.parseInteger(body, "orderId");
...@@ -489,78 +463,102 @@ public class WxOrderController { ...@@ -489,78 +463,102 @@ public class WxOrderController {
LitemallOrder order = orderService.findById(orderId); LitemallOrder order = orderService.findById(orderId);
if (order == null) { if (order == null) {
return ResponseUtil.badArgument(); return ResponseUtil.badArgumentValue();
} }
if (!order.getUserId().equals(userId)) { if (!order.getUserId().equals(userId)) {
return ResponseUtil.badArgumentValue(); return ResponseUtil.badArgumentValue();
} }
// 检测是否能够付款 // 检测是否能够取消
OrderHandleOption handleOption = OrderUtil.build(order); OrderHandleOption handleOption = OrderUtil.build(order);
if (!handleOption.isPay()) { if (!handleOption.isPay()) {
return ResponseUtil.fail(403, "订单不能付"); return ResponseUtil.fail(403, "订单不能付");
} }
// 微信后台申请微信支付订单号 LitemallUser user = userService.findById(userId);
String payId = ""; String openid = user.getWeixinOpenid();
// 微信支付订单号生产未支付 if(openid == null){
Short payStatus = 1; return ResponseUtil.fail(403, "订单不能支付");
}
WxPayMpOrderResult result = null;
try {
WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
orderRequest.setOutTradeNo(order.getOrderSn());
orderRequest.setOpenid(openid);
// TODO 更有意义的显示名称
orderRequest.setBody("litemall小商场-订单测试支付");
// 元转成分
// 这里仅支付1分
// TODO 这里1分钱需要改成实际订单金额
orderRequest.setTotalFee(1);
// TODO 用户IP地址
orderRequest.setSpbillCreateIp("123.12.12.123");
result = wxPayService.createOrder(orderRequest);
} catch (Exception e) {
e.printStackTrace();
return ResponseUtil.fail(403, "订单不能支付");
}
order.setOrderStatus(OrderUtil.STATUS_PAY); order.setOrderStatus(OrderUtil.STATUS_PAY);
order.setPayId(payId); // 0 初始,1 预支付,2 支付成功
order.setPayStatus(payStatus); order.setPayStatus((short)1);
orderService.update(order); orderService.updateById(order);
return ResponseUtil.ok(result);
return ResponseUtil.ok();
} }
/** /**
* 付款成功回调接口 * 付款成功回调接口
* 1. 检测当前订单是否是付款状态 * 1. 检测当前订单是否是付款状态
* 2. 设置订单付款成功状态相关信息 * 2. 设置订单付款成功状态相关信息
* 3. 响应微信支付平台
* *
* @param userId 用户ID * @param request
* @param body 订单信息,{ orderId:xxx, payId: xxx } * @param response
* @return 订单操作结果 * @return 订单操作结果
* 成功则 { errno: 0, errmsg: '成功' } * 成功则 WxPayNotifyResponse.success的XML内容
* 失败则 { errno: XXX, errmsg: XXX } * 失败则 WxPayNotifyResponse.fail的XML内容
* <p> *
* 注意,这里pay_notify是示例地址,开发者应该设立一个隐蔽的回调地址 * 注意,这里pay-notify是示例地址,开发者应该设立一个隐蔽的回调地址
* TODO 这里需要根据微信支付文档设计
*/ */
@PostMapping("pay_notify") @PostMapping("pay-notify")
public Object pay_notify(@LoginUser Integer userId, @RequestBody String body) { public Object payNotify(HttpServletRequest request, HttpServletResponse response) {
if (userId == null) { try {
return ResponseUtil.unlogin(); String xmlResult = IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
} WxPayOrderNotifyResult result = wxPayService.parseOrderNotifyResult(xmlResult);
Integer orderId = JacksonUtil.parseInteger(body, "orderId");
Integer payId = JacksonUtil.parseInteger(body, "payId");
if (orderId == null || payId == null) {
return ResponseUtil.badArgument();
}
LitemallOrder order = orderService.findById(orderId); String orderSn = result.getOutTradeNo();
if (order == null) { String payId = result.getTransactionId();
return ResponseUtil.badArgument(); // 分转化成元
} String totalFee = BaseWxPayResult.feeToYuan(result.getTotalFee());
if (!order.getUserId().equals(userId)) {
return ResponseUtil.badArgumentValue();
}
// 检测是否是付款状态 LitemallOrder order = orderService.findBySn(orderSn);
if (!order.getOrderStatus().equals(OrderUtil.STATUS_PAY)) { if(order == null){
logger.error("系统内部错误"); throw new Exception("订单不存在 sn=" + orderSn);
} }
if (!order.getPayId().equals(String.valueOf(payId))) {
logger.error("系统内部错误");
}
Short payStatus = (short) 2; // 检查这个订单是否已经处理过
order.setPayStatus(payStatus); if(OrderUtil.isPayStatus(order) && order.getPayId() != null){
order.setPayTime(LocalDateTime.now()); return WxPayNotifyResponse.success("处理成功!");
orderService.update(order); }
return ResponseUtil.ok(); // 检查支付订单金额
// TODO 这里1分钱需要改成实际订单金额
if(!totalFee.equals("0.01")){
throw new Exception("支付金额不符合 totalFee=" + totalFee);
}
order.setPayId(payId);
// 0 初始,1 预支付,2 支付成功
order.setPayStatus((short)2);
order.setPayTime(LocalDateTime.now());
orderService.updateById(order);
return WxPayNotifyResponse.success("处理成功!");
} catch (Exception e) {
logger.error("微信回调结果异常,异常原因 " + e.getMessage());
return WxPayNotifyResponse.fail(e.getMessage());
}
} }
......
Supports Markdown
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