refactor(商城): 优化支付方式

master
wayn 4 years ago
parent f140175312
commit 810489a53b

@ -6,7 +6,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.4</version>
<version>2.5.2</version>
</parent>
<modules>
<module>waynboot-common</module>
@ -38,7 +38,7 @@
<maven.compiler.target>${java.version}</maven.compiler.target>
<spring-boot.version>2.4.4</spring-boot.version>
<mysql.connector.java.version>8.0.19</mysql.connector.java.version>
<lettuce.version>6.1.2.RELEASE</lettuce.version>
<lettuce.version>6.1.3.RELEASE</lettuce.version>
<elasticsearch.version>7.12.1</elasticsearch.version>
<lombok.version>1.18.6</lombok.version>
<mybatis-plus.version>3.4.2</mybatis-plus.version>
@ -81,11 +81,6 @@
<artifactId>lettuce-core</artifactId>
<version>${lettuce.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>

@ -136,11 +136,12 @@ private static String encryptUserId(String userId, int num) {
```
### 5. 下单流程处理过程通过rabbitMQ异步生成订单提高系统下单处理能力
1. 用户点击提交订单按钮后台生成订单编号和订单金额跳转到订单支付页面并将订单编号等信息发送rabbitMQ消息生产订单
2. 订单消费者接受到订单消息后,获取订单编号生成订单记录(用户待支付)
3. 用户点击支付按钮时,前端根据订单编号轮询订单信息查询接口,如果订单编号记录已经入库则进行后续支付操作,如果订单编号未入库则返回错误信息(订单异常)
4. 前端调用微信/支付宝完成支付操作
5. 用户支付完成后在回调通知里更新订单状态为已支付(已成功)
1. 用户点击提交订单按钮后台生成订单编号和订单金额跳转到订单支付页面并将订单编号等信息发送rabbitMQ消息生成订单编号还未生成订单
2. 订单消费者接受到订单消息后,获取订单编号生成订单记录(订单创建成功,用户待支付)
3. 下单页面,前端根据订单编号轮询订单接口,订单已创建则跳转支付页面,否则提示下单失败(订单创建失败)
4. 支付页面,用户点击支付按钮时,后台调用微信/支付宝下单接口后,前端唤醒微信/支付宝支付,用户输入密码
5. 用户支付完成后在微信/支付宝下回调通知里更新订单状态为已支付(订单已支付)
6. 用户支付完成后,返回支付状态查看页面。
### 6. 金刚区跳转使用策略模式
```java

@ -111,9 +111,14 @@ public class Order extends ShopBaseEntity implements Serializable {
private String payId;
/**
*
* 1 2
*/
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
private Integer payType;
/**
*
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime payTime;
/**
@ -129,7 +134,7 @@ public class Order extends ShopBaseEntity implements Serializable {
/**
*
*/
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime shipTime;
/**
@ -150,13 +155,13 @@ public class Order extends ShopBaseEntity implements Serializable {
/**
* 退
*/
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime refundTime;
/**
*
*/
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime confirmTime;
/**
@ -167,7 +172,7 @@ public class Order extends ShopBaseEntity implements Serializable {
/**
*
*/
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime orderEndTime;
/**

@ -31,4 +31,9 @@ public class OrderVO {
private Long addressId;
private String message;
/**
* 1 2
*/
private Integer payType;
}

@ -0,0 +1,23 @@
package com.wayn.common.enums;
/**
*
*/
public enum PayTypeEnum {
WX(1),
ALI(2);
private int code;
PayTypeEnum(int code) {
this.code = code;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}

@ -2,11 +2,13 @@ package com.wayn.common.util;
import org.apache.commons.lang3.builder.ToStringBuilder;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
public class R {
public class R implements Serializable {
private static final long serialVersionUID = -5316597326293972581L;
private int code;
private String msg;
private Map<String, Object> map = new HashMap<>();

@ -21,10 +21,6 @@
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
</dependencies>
</project>

@ -26,6 +26,11 @@ public class OrderController extends BaseController {
return iOrderService.selectListPage(page, showType);
}
@PostMapping("info")
public R info(@RequestBody OrderVO orderVO) {
return R.success().add("data", iOrderService.getById(orderVO.getOrderSn()));
}
@PostMapping("statusCount")
public R statusCount() {
return iOrderService.statusCount();
@ -36,19 +41,26 @@ public class OrderController extends BaseController {
return iOrderService.asyncSubmit(orderVO);
}
@PostMapping("info")
public R info(@RequestBody OrderVO orderVO) {
return R.success().add("data", iOrderService.getById(orderVO.getOrderSn()));
}
/**
* JSAPI
*
* @param orderVO
* @return
*/
@PostMapping("prepay")
public R prepay(@RequestBody OrderVO orderVO) {
return iOrderService.prepay(orderVO.getOrderSn(), request);
return iOrderService.prepay(orderVO.getOrderSn(), orderVO.getPayType(), request);
}
/**
* H5
*
* @param orderVO
* @return
*/
@PostMapping("h5pay")
public R h5pay(@RequestBody OrderVO orderVO) {
return iOrderService.h5pay(orderVO.getOrderSn(), request);
return iOrderService.h5pay(orderVO.getOrderSn(), orderVO.getPayType(), request);
}
@PostMapping("payNotify")
@ -56,9 +68,9 @@ public class OrderController extends BaseController {
return iOrderService.payNotify(request, response);
}
@GetMapping("testPayNotify/{orderSn}")
public R payNotify(@PathVariable String orderSn) {
return iOrderService.testPayNotify(orderSn);
@GetMapping("searchResult/{orderSn}")
public R searchResult(@PathVariable String orderSn) {
return iOrderService.searchResult(orderSn);
}
@PostMapping("cancel/{orderId}")

@ -43,7 +43,7 @@ public interface IOrderService extends IService<Order> {
* @param request
* @return r
*/
R h5pay(String orderSn, HttpServletRequest request);
R h5pay(String orderSn, Integer payType, HttpServletRequest request);
/**
*
@ -56,7 +56,7 @@ public interface IOrderService extends IService<Order> {
* @param request
* @return r
*/
R prepay(String orderSn, HttpServletRequest request);
R prepay(String orderSn, Integer payType, HttpServletRequest request);
/**
*
@ -82,7 +82,7 @@ public interface IOrderService extends IService<Order> {
* @param orderSn
* @return r
*/
R testPayNotify(String orderSn);
R searchResult(String orderSn);
/**
*

@ -22,6 +22,7 @@ import com.wayn.common.core.domain.vo.OrderVO;
import com.wayn.common.core.service.shop.*;
import com.wayn.common.core.util.OrderHandleOption;
import com.wayn.common.core.util.OrderUtil;
import com.wayn.common.enums.PayTypeEnum;
import com.wayn.common.exception.BusinessException;
import com.wayn.common.task.TaskService;
import com.wayn.common.util.IdUtil;
@ -355,7 +356,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
@Override
@Transactional(rollbackFor = Exception.class)
public R prepay(String orderSn, HttpServletRequest request) {
public R prepay(String orderSn, Integer payType, HttpServletRequest request) {
// 获取订单详情
Order order = getOne(new QueryWrapper<Order>().eq("order_sn", orderSn));
String checkMsg = checkOrderOperator(order);
@ -367,36 +368,42 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
if (!handleOption.isPay()) {
return R.error("订单不能支付");
}
Member member = iMemberService.getById(MobileSecurityUtils.getUserId());
String openid = member.getWeixinOpenid();
if (openid == null) {
return R.error("订单不能支付");
}
WxPayMpOrderResult result;
try {
WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
orderRequest.setOutTradeNo(order.getOrderSn());
orderRequest.setOpenid(openid);
orderRequest.setBody("订单:" + order.getOrderSn());
// 元转成分
int fee;
BigDecimal actualPrice = order.getActualPrice();
fee = actualPrice.multiply(new BigDecimal(100)).intValue();
orderRequest.setTotalFee(fee);
orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(request));
result = wxPayService.createOrder(orderRequest);
} catch (Exception e) {
e.printStackTrace();
return R.error("订单不能支付");
// 设置支付方式
order.setPayType(payType);
if (PayTypeEnum.WX.getCode() == payType) {
Member member = iMemberService.getById(MobileSecurityUtils.getUserId());
String openid = member.getWeixinOpenid();
if (openid == null) {
return R.error("订单不能支付");
}
WxPayMpOrderResult result;
try {
WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
orderRequest.setOutTradeNo(order.getOrderSn());
orderRequest.setOpenid(openid);
orderRequest.setBody("订单:" + order.getOrderSn());
// 元转成分
int fee;
BigDecimal actualPrice = order.getActualPrice();
fee = actualPrice.multiply(new BigDecimal(100)).intValue();
orderRequest.setTotalFee(fee);
orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(request));
result = wxPayService.createOrder(orderRequest);
return R.success().add("result", result);
} catch (Exception e) {
e.printStackTrace();
return R.error("订单不能支付");
}
} else {
return R.success();
}
return R.success().add("result", result);
}
@Override
@Transactional(rollbackFor = Exception.class)
public R h5pay(String orderSn, HttpServletRequest request) {
public R h5pay(String orderSn, Integer payType, HttpServletRequest request) {
// 获取订单详情
Order order = getOne(new QueryWrapper<Order>().eq("order_sn", orderSn));
String checkMsg = checkOrderOperator(order);
@ -408,24 +415,48 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
if (!handleOption.isPay()) {
return R.error("订单不能支付");
}
// 设置支付方式
order.setPayType(payType);
if (PayTypeEnum.WX.getCode() == payType) {
WxPayMwebOrderResult result;
try {
WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
orderRequest.setOutTradeNo(order.getOrderSn());
orderRequest.setTradeType("MWEB");
orderRequest.setBody("订单:" + order.getOrderSn());
// 元转成分
int fee;
BigDecimal actualPrice = order.getActualPrice();
fee = actualPrice.multiply(new BigDecimal(100)).intValue();
orderRequest.setTotalFee(fee);
orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(request));
result = wxPayService.createOrder(orderRequest);
return R.success().add("data", result);
} catch (Exception e) {
log.error(e.getMessage(), e);
return R.error("支付失败");
}
} else {
// todo 暂时没有实现支付宝支付,直接更新支付状态为已支付
order.setPayId("xxxxx0987654321-ali");
order.setPayTime(LocalDateTime.now());
order.setOrderStatus(OrderUtil.STATUS_PAY);
order.setUpdateTime(new Date());
if (!updateById(order)) {
return R.error("更新数据已失效");
}
WxPayMwebOrderResult result;
try {
WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
orderRequest.setOutTradeNo(order.getOrderSn());
orderRequest.setTradeType("MWEB");
orderRequest.setBody("订单:" + order.getOrderSn());
// 元转成分
int fee;
BigDecimal actualPrice = order.getActualPrice();
fee = actualPrice.multiply(new BigDecimal(100)).intValue();
orderRequest.setTotalFee(fee);
orderRequest.setSpbillCreateIp(IpUtils.getIpAddr(request));
result = wxPayService.createOrder(orderRequest);
return R.success().add("data", result);
} catch (Exception e) {
log.error(e.getMessage(), e);
return R.error("支付失败");
// 订单支付成功以后,会发送短信给用户,以及发送邮件给管理员
String email = iMemberService.getById(order.getUserId()).getEmail();
if (StringUtils.isNotBlank(email)) {
iMailService.sendEmail("新订单通知", order.toString(), email, WaynConfig.getMobileUrl() + "/message/email");
}
// 删除redis中订单id
redisCache.deleteZsetObject("order_zset", order.getId());
// 取消订单超时未支付任务
taskService.removeTask(new OrderUnpaidTask(order.getId()));
return R.success();
}
}
@ -495,36 +526,17 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
}
@Override
public R testPayNotify(String orderSn) {
public R searchResult(String orderSn) {
Order order = getOne(new QueryWrapper<Order>().eq("order_sn", orderSn));
if (order == null) {
return R.error(ErrorCode.ORDER_NOT_EXISTS_ERROR, "订单不存在,编号:" + orderSn);
}
// 检查这个订单是否已经处理过
if (OrderUtil.hasPayed(order)) {
return R.error("订单已经处理成功!");
if (!OrderUtil.isCreateStatus(order)) {
return R.error(ErrorCode.ORDER_NOT_EXISTS_ERROR, "订单创建失败!");
}
order.setPayId("xxxxx0987654321-wx");
order.setPayTime(LocalDateTime.now());
order.setOrderStatus(OrderUtil.STATUS_PAY);
order.setUpdateTime(new Date());
if (!updateById(order)) {
return R.error("更新数据已失效");
}
// 订单支付成功以后,会发送短信给用户,以及发送邮件给管理员
String email = iMemberService.getById(order.getUserId()).getEmail();
if (StringUtils.isNotBlank(email)) {
iMailService.sendEmail("新订单通知", order.toString(), email, WaynConfig.getMobileUrl() + "/message/email");
}
// 删除redis中订单id
redisCache.deleteZsetObject("order_zset", order.getId());
// 取消订单超时未支付任务
taskService.removeTask(new OrderUnpaidTask(order.getId()));
return R.success("处理成功!");
return R.success("订单创建成功!");
}
@Override

@ -21,6 +21,7 @@
<result column="order_price" property="orderPrice" />
<result column="actual_price" property="actualPrice" />
<result column="pay_id" property="payId" />
<result column="pay_type" property="payType" />
<result column="pay_time" property="payTime" />
<result column="ship_sn" property="shipSn" />
<result column="ship_channel" property="shipChannel" />
@ -40,7 +41,10 @@
<!-- 通用查询结果列 -->
<sql id="selectOrderVo">
select id,
user_id, order_sn, order_status, aftersale_status, consignee, mobile, address, message, goods_price, freight_price, coupon_price, integral_price, groupon_price, order_price, actual_price, pay_id, pay_time, ship_sn, ship_channel, ship_time, refund_amount, refund_type, refund_content, refund_time, confirm_time, comments, order_end_time, create_time, update_time, del_flag
user_id, order_sn, order_status, aftersale_status, consignee, mobile, address, message,
goods_price, freight_price, coupon_price, integral_price, groupon_price, order_price,
actual_price, pay_id, pay_time, ship_sn, ship_channel, ship_time, refund_amount, refund_type, pay_type,
refund_content, refund_time, confirm_time, comments, order_end_time, create_time, update_time, del_flag
from shop_order
</sql>
@ -51,6 +55,9 @@
<if test="order.orderStatus != null">
AND order_status = #{order.orderStatus}
</if>
<if test="order.payType != null">
AND pay_type = #{order.payType}
</if>
<if test="order.userId != null">
AND user_id = #{order.userId}
</if>

Loading…
Cancel
Save