diff --git a/Cpop-Mall/Cpop-Mall-Web/src/main/resources/application-dev.yml b/Cpop-Mall/Cpop-Mall-Web/src/main/resources/application-dev.yml index 7ca37c9..c828842 100644 --- a/Cpop-Mall/Cpop-Mall-Web/src/main/resources/application-dev.yml +++ b/Cpop-Mall/Cpop-Mall-Web/src/main/resources/application-dev.yml @@ -119,4 +119,6 @@ wx: #支付通知地址 notifyUrl: https://frp-oak.top:11899/Cpop-Mall/wxPay/callback/notify/order #退款通知地址 - notifyRefund: https://frp-oak.top:11899/Cpop-Mall/wxPay/callback/notify/refund \ No newline at end of file + notifyRefund: https://frp-oak.top:11899/Cpop-Mall/wxPay/callback/notify/refund + #分账通知地址 + notifySharing: https://frp-oak.top:11899/Cpop-Mall/wxPay/callback/notify/profitSharing \ No newline at end of file diff --git a/Cpop-Mall/Cpop-Mall-Web/src/main/resources/application.yml b/Cpop-Mall/Cpop-Mall-Web/src/main/resources/application.yml index 82ec1b6..fe5bc9e 100644 --- a/Cpop-Mall/Cpop-Mall-Web/src/main/resources/application.yml +++ b/Cpop-Mall/Cpop-Mall-Web/src/main/resources/application.yml @@ -106,7 +106,7 @@ task: # 设置空闲线程存活时间(秒 keepAliveSeconds: 300 # 设置队列容量 - queueCapacity: 10240 + queueCapacity: 1024 # 设置线程名称前缀 threadNamePrefix: "Cpop-Mall-AsyncNotify-" # 设置线程池等待终止时间(秒) diff --git a/Cpop-Mall/Cpop-Mall-Web/src/test/java/com/cpop/mall/web/CpopWxPayTests.java b/Cpop-Mall/Cpop-Mall-Web/src/test/java/com/cpop/mall/web/CpopWxPayTests.java index a6c8a9c..21610e7 100644 --- a/Cpop-Mall/Cpop-Mall-Web/src/test/java/com/cpop/mall/web/CpopWxPayTests.java +++ b/Cpop-Mall/Cpop-Mall-Web/src/test/java/com/cpop/mall/web/CpopWxPayTests.java @@ -1,20 +1,29 @@ package com.cpop.mall.web; +import com.alibaba.fastjson.JSONObject; import com.cpop.core.utils.SpringUtils; import com.cpop.core.utils.uuid.IdUtils; import com.cpop.mall.business.entity.Order; import com.cpop.mall.business.service.OrderService; import com.cpop.mall.framework.config.wxPay.WxPayProperties; import com.cpop.system.business.entity.Brand; +import com.cpop.system.business.entity.ProfitSharing; import com.cpop.system.business.service.BrandService; +import com.cpop.system.business.service.ProfitSharingService; +import com.github.binarywang.wxpay.bean.profitsharing.ProfitSharingReceiverRequest; +import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingReturnRequest; import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request; import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result; +import com.github.binarywang.wxpay.config.WxPayConfig; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.service.WxPayService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import java.util.HashMap; +import java.util.Map; + /** * @author DB * @createTime 2023/11/01 18:15 @@ -38,7 +47,7 @@ public class CpopWxPayTests { @Test public void refund() throws WxPayException { Brand brand = SpringUtils.getBean(BrandService.class).getById("75140168047210496"); - Order order = SpringUtils.getBean(OrderService.class).getById("77602361596874752"); + Order order = SpringUtils.getBean(OrderService.class).getById("78954327589658624"); WxPayRefundV3Request request = new WxPayRefundV3Request(); WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount(); //退款金额(单位分) @@ -57,4 +66,49 @@ public class CpopWxPayTests { WxPayRefundV3Result result = wxPayService.refundV3(request); System.out.println(result); } + + /** + * @descriptions 分账退款 + * @author DB + * @date 2023/11/03 9:57 + * @return: void + */ + @Test + public void profitSharingRefund() throws WxPayException { + ProfitSharingReturnRequest profitSharingReturnRequest = new ProfitSharingReturnRequest(); + //ProfitSharing profitSharing = SpringUtils.getBean(ProfitSharingService.class).getById("77860920238751744"); + //profitSharingReturnRequest.setOrderId(profitSharing.getOutProfitSharingId()); + //profitSharingReturnRequest.setOutReturnNo(profitSharing.getId()); + profitSharingReturnRequest.setOrderId("30001200512023110656192114311"); + profitSharingReturnRequest.setOutReturnNo("4200002030202311064693113248"); + profitSharingReturnRequest.setDescription("分账退款"); + profitSharingReturnRequest.setSubMchId("1650816616"); + profitSharingReturnRequest.setReturnMchid("1618884922"); + //profitSharingReturnRequest.setAmount(profitSharing.getAmount()); + profitSharingReturnRequest.setAmount(1L); + wxPayService.getProfitSharingV3Service().profitSharingReturn(profitSharingReturnRequest); + } + + /** + * @descriptions 添加分账接收方 + * @author DB + * @date 2023/11/03 10:17 + * @param + * @return: void + */ + @Test + public void addReceiver() throws WxPayException { + //固定商户信息 + Map mapReceiver = new HashMap<>(4); + mapReceiver.put("type", "MERCHANT_ID"); + //mapReceiver.put("sub_mchid", "1650816616"); + mapReceiver.put("sub_mchid", "1618884922"); + mapReceiver.put("account", "1618884922"); + mapReceiver.put("relation_type", "SERVICE_PROVIDER"); + mapReceiver.put("name","果酱盒子"); + //添加分账接收方 + ProfitSharingReceiverRequest profitSharingReceiver = new ProfitSharingReceiverRequest(); + profitSharingReceiver.setReceiver(JSONObject.toJSONString(mapReceiver)); + wxPayService.getProfitSharingService().addReceiver(profitSharingReceiver); + } } diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/AdvanceOrderBo.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/AdvanceOrderBo.java new file mode 100644 index 0000000..bdd528e --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/AdvanceOrderBo.java @@ -0,0 +1,72 @@ +package com.cpop.mall.business.bo; + +import com.cpop.core.annontation.StringArrayConvert; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.List; + +/** + * @author DB + * @createTime 2023/11/06 11:13 + * @description + */ +@Data +@Accessors(chain = true) +@ApiModel(value = "商城预订单对象") +public class AdvanceOrderBo implements Serializable { + + /** + * 主键 + */ + @ApiModelProperty("主键") + private String id; + + /** + * 总金额 + */ + @NotNull(message = "总金额不能为空") + @ApiModelProperty(value = "总金额",required = true) + private BigDecimal totalAmount; + + /** + * 总积分 + */ + @NotNull(message = "总积分不能为空") + @ApiModelProperty(value = "总积分",required = true) + private Long totalPoint; + + /** + * 当前订单所有产品名 + */ + @StringArrayConvert + @ApiModelProperty(value = "当前订单所有产品名") + private String productNames; + + /** + * 支付类型 + */ + @NotNull(message = "支付类型不能为空") + @ApiModelProperty(value = "支付方式(0:微信支付;1:积分支付)",required = true) + private Integer payType; + + /** + * 支付用户名 + */ + @ApiModelProperty(value = "支付用户名") + private String payUserName; + + /** + * 订单详情 + */ + @NotEmpty(message = "订单详情不能为空") + @ApiModelProperty(value = "订单详情",required = true) + private List orderDetailList; +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/OrderDetailBo.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/OrderDetailBo.java new file mode 100644 index 0000000..854f245 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/OrderDetailBo.java @@ -0,0 +1,55 @@ +package com.cpop.mall.business.bo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.math.BigDecimal; + +/** + * @author DB + * @createTime 2023/11/06 11:21 + * @description + */ +@Data +@ApiModel(value = "商城订单下单详情请求对象") +public class OrderDetailBo implements Serializable { + + /** + * 商品记录id + */ + @NotBlank(message = "商品规格记录id不能为空") + @ApiModelProperty(value = "商品规格记录id",required = true) + private String productRecordId; + + /** + * 金额 + */ + @NotNull(message = "金额不能为空") + @ApiModelProperty(value = "金额",required = true) + private BigDecimal amount; + + /** + * 积分 + */ + @NotNull(message = "积分不能为空") + @ApiModelProperty(value = "积分",required = true) + private Integer point; + + /** + * 下单数量 + */ + @NotNull(message = "下单数量不能为空") + @ApiModelProperty(value = "下单数量",required = true) + private Integer number; + + /** + * 店铺(校区)id + */ + @NotBlank(message = "店铺(校区)id不能为空") + @ApiModelProperty(value = "店铺(校区)id",required = true) + private String storeId; +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/PlaceOrderBo.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/PlaceOrderBo.java index 2c330be..75a5f17 100644 --- a/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/PlaceOrderBo.java +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/bo/PlaceOrderBo.java @@ -29,26 +29,6 @@ public class PlaceOrderBo implements Serializable { @ApiModelProperty("主键") private String id; - /** - * 总金额 - */ - @NotNull(message = "总金额不能为空") - @ApiModelProperty(value = "总金额",required = true) - private BigDecimal totalAmount; - - /** - * 总积分 - */ - @NotNull(message = "总积分不能为空") - @ApiModelProperty(value = "总积分",required = true) - private Long totalPoint; - - /** - * 下单人真实姓名 - */ - @ApiModelProperty("下单人真实姓名") - private String payUserName; - /** * 收货人名 */ @@ -63,13 +43,6 @@ public class PlaceOrderBo implements Serializable { @ApiModelProperty(value = "收货人电话",required = true) private String receivePhone; - /** - * 当前订单所有产品名 - */ - @StringArrayConvert - @ApiModelProperty(value = "当前订单所有产品名") - private String productNames; - /** * 收货地址 */ @@ -90,53 +63,4 @@ public class PlaceOrderBo implements Serializable { @ApiModelProperty(value = "支付方式(0:微信支付;1:积分支付)",required = true) private Integer payType; - /** - * 订单详情 - */ - @NotEmpty(message = "订单详情不能为空") - @ApiModelProperty(value = "订单详情",required = true) - private List placeOrderDetailList; - - /** - * 下单详情 - */ - @Data - @ApiModel(value = "商城订单下单详情请求对象") - public static class PlaceOrderDetail implements Serializable{ - - /** - * 商品记录id - */ - @NotBlank(message = "商品规格记录id不能为空") - @ApiModelProperty(value = "商品规格记录id",required = true) - private String productRecordId; - - /** - * 金额 - */ - @NotNull(message = "金额不能为空") - @ApiModelProperty(value = "金额",required = true) - private BigDecimal amount; - - /** - * 积分 - */ - @NotNull(message = "积分不能为空") - @ApiModelProperty(value = "积分",required = true) - private Integer point; - - /** - * 下单数量 - */ - @NotNull(message = "下单数量不能为空") - @ApiModelProperty(value = "下单数量",required = true) - private Integer number; - - /** - * 店铺(校区)id - */ - //TODO:@NotBlank(message = "店铺(校区)id不能为空") - @ApiModelProperty(value = "店铺(校区)id",required = true) - private String storeId; - } } diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/callback/WxPayCallbackController.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/callback/WxPayCallbackController.java index 4730a60..aeeb5c4 100644 --- a/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/callback/WxPayCallbackController.java +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/callback/WxPayCallbackController.java @@ -52,4 +52,17 @@ public class WxPayCallbackController { return WxPayNotifyResponse.success("成功"); } + /** + * @descriptions 微信支付分账通知 + * @author DB + * @date 2023/10/27 16:04 + * @param xmlData 数据 + * @return: java.lang.String + */ + @PostMapping("/notify/profitSharing") + public String parseProfitSharingNotifyResult(@RequestBody String xmlData){ + orderService.parseProfitSharingNotifyResult(xmlData); + return WxPayNotifyResponse.success("成功"); + } + } diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/mini/MiniOrderController.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/mini/MiniOrderController.java index 6b7c58f..862de55 100644 --- a/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/mini/MiniOrderController.java +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/controller/mini/MiniOrderController.java @@ -3,13 +3,11 @@ package com.cpop.mall.business.controller.mini; import com.cpop.common.utils.bean.BeanUtils; import com.cpop.core.base.R; import com.cpop.core.utils.SpringUtils; -import com.cpop.mall.business.bo.OrderApplyRefundBo; -import com.cpop.mall.business.bo.OrderEvaluateBo; -import com.cpop.mall.business.bo.OrderPageBo; -import com.cpop.mall.business.bo.PlaceOrderBo; +import com.cpop.mall.business.bo.*; import com.cpop.mall.business.entity.OrderEvaluate; import com.cpop.mall.business.service.OrderEvaluateService; import com.cpop.mall.business.service.OrderService; +import com.cpop.mall.business.vo.OrderInfoVo; import com.cpop.mall.business.vo.OrderPageVo; import com.mybatisflex.core.paginate.Page; import io.swagger.annotations.Api; @@ -49,6 +47,19 @@ public class MiniOrderController { return R.ok(page); } + /** + * @descriptions 生成预订单 + * @author DB + * @date 2023/11/06 11:12 + * @param bo 请求参数 + * @return: com.cpop.core.base.R + */ + @PostMapping("/createAdvanceOrder") + @ApiOperation("商城-订单-生成预订单") + public R createAdvanceOrder(@RequestBody @Validated @ApiParam("商城-预订单参数") AdvanceOrderBo bo) { + return R.ok(orderService.createAdvanceOrder(bo)); + } + /** * @descriptions 商城-订单-下单 * @author DB @@ -103,9 +114,24 @@ public class MiniOrderController { */ @PutMapping("/cancelOrder") @ApiOperation("取消订单") - public R cancelOrder(@RequestParam("orderId") @ApiParam("商城-订单Id") String orderId) { + public R cancelOrder(@RequestParam("orderId") @ApiParam("商城-订单Id") String orderId) { orderService.cancelOrder(orderId); return R.ok(); } + /** + * @descriptions 小程序-重新支付订单 + * @author DB + * @date 2023/11/03 15:53 + * @param orderId 订单id + * @return: com.cpop.core.base.R> + */ + @GetMapping("/rePayOrder/{orderId}") + @ApiOperation("小程序-重新支付订单") + public R rePayOrder(@PathVariable @ApiParam(value = "订单id", required = true) String orderId) { + return R.ok(orderService.rePayOrder(orderId)); + } + + + } diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/dto/ProductAndRecordDto.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/dto/ProductAndRecordDto.java new file mode 100644 index 0000000..daa01a5 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/dto/ProductAndRecordDto.java @@ -0,0 +1,33 @@ +package com.cpop.mall.business.dto; + +import com.mybatisflex.annotation.Id; +import lombok.Data; + +/** + * @author DB + * @createTime 2023/11/03 12:56 + * @description + */ +@Data +public class ProductAndRecordDto { + + /** + * 主键 + */ + private String id; + + /** + * 商品名 + */ + private String productName; + + /** + * 产品描述 + */ + private String description; + + /** + * 产品记录id + */ + private String productRecordId; +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/entity/Order.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/entity/Order.java index dc49dd3..b1e1cfc 100644 --- a/Cpop-Mall/src/main/java/com/cpop/mall/business/entity/Order.java +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/entity/Order.java @@ -34,12 +34,12 @@ public class Order extends BaseEntity implements Serializable { private String id; /** - * 订单状态(0:待付款;1:待发货;2:待确认;3:已完成;4:退款/售后中) + * 订单状态(0:待付款;1:待发货;2:待确认;3:已完成;4:退款/售后中:5:订单取消;6:过期) */ private Integer orderStatus; /** - * 上一个状态(0:待付款;1:待发货;2:待确认;3:已完成;4:退款/售后中:5:订单取消) + * 上一个状态(0:待付款;1:待发货;2:待确认;3:已完成;4:退款/售后中:5:订单取消;6:过期) */ private Integer previousStatus; diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/service/OrderService.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/OrderService.java index 302d983..44ebc7b 100644 --- a/Cpop-Mall/src/main/java/com/cpop/mall/business/service/OrderService.java +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/OrderService.java @@ -1,10 +1,8 @@ package com.cpop.mall.business.service; -import com.cpop.mall.business.bo.LogisticsOrderBo; -import com.cpop.mall.business.bo.OrderApplyRefundBo; -import com.cpop.mall.business.bo.OrderPageBo; -import com.cpop.mall.business.bo.PlaceOrderBo; +import com.cpop.mall.business.bo.*; import com.cpop.mall.business.entity.Order; +import com.cpop.mall.business.vo.OrderInfoVo; import com.cpop.mall.business.vo.OrderPageVo; import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.service.IService; @@ -26,6 +24,15 @@ public interface OrderService extends IService { */ Page getOrderPage(OrderPageBo bo); + /** + * @descriptions 生成预订单 + * @author DB + * @date 2023/11/06 11:17 + * @param bo 请求参数 + * @return: java.lang.Object + */ + String createAdvanceOrder(AdvanceOrderBo bo); + /** * @descriptions 商城-订单-下单 * @author DB @@ -53,6 +60,15 @@ public interface OrderService extends IService { */ void wxPayNotifyOrder(String xmlData); + /** + * @descriptions 分账结果通知 + * @author DB + * @date 2023/11/03 9:50 + * @param xmlData 加密数据 + * @return: void + */ + void parseProfitSharingNotifyResult(String xmlData); + /** * @descriptions 取消订单 * @author DB @@ -69,4 +85,14 @@ public interface OrderService extends IService { * @Date: 2023/10/28 15:27 */ void inputLogisticsOrder(LogisticsOrderBo bo); + + /** + * @descriptions 小程序-重新支付订单 + * @author DB + * @date 2023/11/03 16:14 + * @param orderId 订单id + * @return: java.lang.Object + */ + Object rePayOrder(String orderId); + } diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/OrderRefundServiceImpl.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/OrderRefundServiceImpl.java index 8d1d499..d847420 100644 --- a/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/OrderRefundServiceImpl.java +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/service/impl/OrderRefundServiceImpl.java @@ -5,6 +5,7 @@ import com.cpop.core.base.enums.OrderSource; import com.cpop.core.base.exception.ServiceException; import com.cpop.core.utils.SpringUtils; import com.cpop.core.utils.sql.SqlUtils; +import com.cpop.core.utils.uuid.IdUtils; import com.cpop.mall.business.bo.OrderRefundPageBo; import com.cpop.mall.business.bo.OrderRejectRefundBo; import com.cpop.mall.business.entity.Order; @@ -15,9 +16,13 @@ import com.cpop.mall.business.service.OrderService; import com.cpop.mall.business.vo.OrderRefundPageVo; import com.cpop.mall.framework.config.wxPay.WxPayProperties; import com.cpop.mall.framework.handler.WxPayHandler; +import com.cpop.system.business.entity.Brand; import com.cpop.system.business.entity.ProfitSharing; +import com.cpop.system.business.service.BrandService; import com.cpop.system.business.service.ProfitSharingService; import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult; +import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyV3Result; +import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingReturnRequest; import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request; import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result; import com.github.binarywang.wxpay.exception.WxPayException; @@ -63,17 +68,26 @@ public class OrderRefundServiceImpl extends ServiceImpl implements private WxPayHandler wxPayHandler; @Autowired - private WxPayProperties wxPayProperties; + private Scheduler scheduler; + + @Autowired + private WxPayAsyncTask wxPayAsyncTask; /** * @descriptions 分页查询商城-订单 @@ -96,6 +97,12 @@ public class OrderServiceImpl extends ServiceImpl implements //查询此用户订单 queryWrapper.where(ORDER.PAY_USER_ID.eq(loginUserInfo.getString("userId"))); } + //订单状态 + if (null != bo.getOrderStatus()) { + queryWrapper.and(ORDER.ORDER_STATUS.eq(bo.getOrderStatus())); + } else { + queryWrapper.and(ORDER.ORDER_STATUS.ne(6)); + } PageDomain pageDomain = SqlUtils.getInstance().getPageDomain(); return this.mapper.paginateAs(Page.of(pageDomain.getPageNum(),pageDomain.getPageSize()), queryWrapper @@ -105,8 +112,6 @@ public class OrderServiceImpl extends ServiceImpl implements .and(ORDER.PAY_USER_NAME.like(bo.getPayUserName())) .and(ORDER.RECEIVE_PHONE.like(bo.getReceivePhone())) .and(ORDER.PRODUCT_NAMES.like(bo.getProductName())) - //订单状态 - .and(ORDER.ORDER_STATUS.eq(bo.getOrderStatus())) .orderBy(ORDER.CREATE_TIME.desc()), OrderPageVo.class, //子查询 @@ -128,27 +133,26 @@ public class OrderServiceImpl extends ServiceImpl implements } /** - * @descriptions 商城-订单-下单 + * @descriptions 生成预订单 * @author DB - * @date 2023/10/25 9:32 - * @param bo 下单请求对象 - * @return: void + * @date 2023/11/06 11:17 + * @param bo 请求参数 + * @return: java.lang.Object */ @Override - @Transactional(rollbackFor = Exception.class) - public Object placeOrder(PlaceOrderBo bo) { + public String createAdvanceOrder(AdvanceOrderBo bo) { RedisService redisService = SpringUtils.getBean(RedisService.class); //获取当前下单用户信息 JSONObject loginUserInfo = SecurityUtils.getInstance().getLoginUserInfo(); //分布式锁进行幂等处理 - Lock userIdLock = redisService.distributedLock(MallRedisConstant.IDEMPOTENT_LOCK_USER_PAY + loginUserInfo.getString("userId")); + Lock userIdLock = redisService.distributedLock(MallRedisConstant.IDEMPOTENT_LOCK_CREATE_ADVANCE_ORDER + loginUserInfo.getString("userId")); if (userIdLock.tryLock()) { //检查库存 Map recordNumIsEnough = null; try { - recordNumIsEnough= recordNumIsEnough(bo.getPlaceOrderDetailList()); Order order = BeanUtils.mapToClass(bo, Order.class); - List orderDetails = BeanUtils.mapToList(bo.getPlaceOrderDetailList(), OrderDetail.class); + List orderDetails = BeanUtils.mapToList(bo.getOrderDetailList(), OrderDetail.class); + recordNumIsEnough= recordNumIsEnough(orderDetails); //规格记录ids Set recordIds = orderDetails.stream().map(OrderDetail::getProductRecordId).collect(Collectors.toSet()); //获取涉及到的商品 @@ -170,11 +174,76 @@ public class OrderServiceImpl extends ServiceImpl implements order.setPayUserName(loginUserInfo.getString("nickName")); } this.save(order); + // 通过JobBuilder构建JobDetail实例,JobDetail规定其job只能是实现Job接口的实例 + JobDetail jobDetail = JobBuilder.newJob(OrderOverTimeUnPayTask.class).withIdentity(QuartzEnums.ORDER_OVERTIME_UN_PAY_TASK.getName() + order.getId(), + QuartzEnums.ORDER_OVERTIME_UN_PAY_TASK.getGroup()) + .usingJobData("orderId", order.getId()) + .build(); + //添加定时修改订单状态任务 + QuartzUtils quartzUtils = SpringUtils.getBean(QuartzUtils.class); + //设置15分钟后 + String cron = quartzUtils.convertToCron(DateUtils.addMinutes(new Date(), 15)); + CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(cron); + // CronTrigger表达式触发器 继承于Trigger。TriggerBuilder 用于构建触发器实例 + CronTrigger cronTrigger = TriggerBuilder.newTrigger().withIdentity(QuartzEnums.ORDER_OVERTIME_UN_PAY_TASK.getName() + order.getId(), + QuartzEnums.ORDER_OVERTIME_UN_PAY_TASK.getGroup()) + .withSchedule(cronScheduleBuilder).build(); + scheduler.scheduleJob(jobDetail, cronTrigger); //保存订单详情 orderDetails.forEach(item -> { item.setOrderId(order.getId()); }); SpringUtils.getBean(OrderDetailService.class).saveBatch(orderDetails); + return order.getId(); + } catch (Exception e) { + //回滚库存 + if (recordNumIsEnough != null){ + recordNumIsEnough.forEach((key, value) -> { + redisService.longIncrement(MallRedisConstant.STOCK_RECORD_NUM + key, value.longValue()); + }); + } + throw new ServiceException(e.getMessage()); + } finally { + //释放锁 + userIdLock.unlock(); + } + }else { + //获取锁失败,直接返回空 + throw new ServiceException("请勿重复下单"); + } + } + + /** + * @descriptions 商城-订单-下单 + * @author DB + * @date 2023/10/25 9:32 + * @param bo 下单请求对象 + * @return: void + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Object placeOrder(PlaceOrderBo bo) { + //获取当前下单用户信息 + JSONObject loginUserInfo = SecurityUtils.getInstance().getLoginUserInfo(); + //分布式锁进行幂等处理 + RedisService redisService = SpringUtils.getBean(RedisService.class); + //分布式锁进行幂等处理 + Lock userIdLock = redisService.distributedLock(MallRedisConstant.IDEMPOTENT_LOCK_USER_PAY + loginUserInfo.getString("userId")); + if (userIdLock.tryLock()){ + try { + //获取订单信息 + Order order = this.getById(bo.getId()); + //获取预订单详情信息 + OrderDetailService orderDetailService = SpringUtils.getBean(OrderDetailService.class); + List orderDetails = orderDetailService.queryChain().where(ORDER_DETAIL.ORDER_ID.eq(order.getId())).list(); + //获取涉及到的商品 + ProductService productService = SpringUtils.getBean(ProductService.class); + List productList = productService.queryChain() + .select(PRODUCT.ID, PRODUCT.PRODUCT_NAME, PRODUCT.DESCRIPTION) + .from(PRODUCT) + .leftJoin(PRODUCT_RECORD).on(PRODUCT_RECORD.PRODUCT_ID.eq(PRODUCT.ID)) + .where(PRODUCT_RECORD.ID.in(orderDetails.stream().map(OrderDetail::getProductRecordId).collect(Collectors.toSet()))) + .list(); //微信支付 if (bo.getPayType() == 0) { //微信支付统一下单 @@ -191,31 +260,37 @@ public class OrderServiceImpl extends ServiceImpl implements .setOpenid(loginUserInfo.getString("openId")) //商品描述 .setBody(productList.stream().map(Product::getDescription).collect(Collectors.joining(","))) - //商品详情 - .setDetail(JSONObject.toJSONString(BeanUtils.mapToList(bo.getPlaceOrderDetailList(), WxPayGoodsDetailDto.class))) + //商品详情,如果涉及到商品优惠需要重新涉及 + .setDetail(JSONObject.toJSONString(BeanUtils.mapToList(orderDetails, WxPayGoodsDetailDto.class))) .setOutTradeNo(order.getId()) //元转分 - .setTotalFee(bo.getTotalAmount().scaleByPowerOfTen(2).intValue()) + .setTotalFee(order.getTotalAmount().scaleByPowerOfTen(2).intValue()) .setTradeType("JSAPI"); - return wxPayService.createOrder(orderRequest); + Object result = wxPayService.createOrder(orderRequest); + //删除定时器任务 + QuartzUtils quartzUtils = SpringUtils.getBean(QuartzUtils.class); + quartzUtils.deleteJob(QuartzEnums.ORDER_OVERTIME_UN_PAY_TASK.getName() + order.getId(), + QuartzEnums.ORDER_OVERTIME_UN_PAY_TASK.getGroup()); + return result; } else { - return pointPay(recordNumIsEnough, order.getId()); + //统计支付商品情况 + Map recordNumIsEnough = orderDetails.stream().collect(Collectors.toMap(OrderDetail::getProductRecordId, OrderDetail::getNumber)); + Object result = pointPay(recordNumIsEnough, order.getId()); + //删除定时器任务 + QuartzUtils quartzUtils = SpringUtils.getBean(QuartzUtils.class); + quartzUtils.deleteJob(QuartzEnums.ORDER_OVERTIME_UN_PAY_TASK.getName() + order.getId(), + QuartzEnums.ORDER_OVERTIME_UN_PAY_TASK.getGroup()); + return result; } } catch (Exception e) { - //回滚库存 - if (recordNumIsEnough != null){ - recordNumIsEnough.forEach((key, value) -> { - redisService.longIncrement(MallRedisConstant.STOCK_RECORD_NUM + key, value.longValue()); - }); - } throw new ServiceException(e.getMessage()); } finally { //释放锁 userIdLock.unlock(); } - }else { + } else { //获取锁失败,直接返回空 - throw new ServiceException("请勿重复下单"); + throw new ServiceException("请勿重复支付"); } } @@ -246,7 +321,7 @@ public class OrderServiceImpl extends ServiceImpl implements * @param list 订单详情 * @return: Map 预库存记录 */ - private Map recordNumIsEnough(List list) throws ServiceException { + private Map recordNumIsEnough(List list) throws ServiceException { RedisService redisService = SpringUtils.getBean(RedisService.class); Map stockNumMap = new HashMap<>(); //遍历库存 @@ -334,7 +409,7 @@ public class OrderServiceImpl extends ServiceImpl implements Brand brand = SpringUtils.getBean(BrandService.class).getById(order.getBrandId()); if (StringUtils.isBlank(brand.getWxAppId()) || !StringUtils.equals(brand.getWxAppId(), wxPayService.getConfig().getAppId())) { //需要分账 - wxPayProfitSharing(orderId, notifyResult, wxPayService); + wxPayAsyncTask.asyncWxPayProfitSharing(orderId, notifyResult, wxPayService); } //异步更新 SpringUtils.getBean(ProductRecordSyncStockTask.class).asyncUpdateRecords(orderNumMap); @@ -344,48 +419,28 @@ public class OrderServiceImpl extends ServiceImpl implements } /** - * @descriptions 微信支付分账 + * @descriptions 分账结果通知 * @author DB - * @date 2023/11/02 15:26 - * @param orderId 订单id - * @param notifyResult 微信支付结果 - * @param wxPayService 微信支付 + * @date 2023/11/03 9:50 + * @param xmlData 加密数据 * @return: void */ - private void wxPayProfitSharing(String orderId, WxPayOrderNotifyResult notifyResult, WxPayService wxPayService) throws WxPayException { - ProfitSharing profitSharing = new ProfitSharing(); - profitSharing.setOrderId(orderId) - .setProfitSharingStatus(0) - .setOrderSource(OrderSource.MALL.toString()); - ProfitSharingService profitSharingService = SpringUtils.getBean(ProfitSharingService.class); - profitSharingService.save(profitSharing); - Double ceil = Math.ceil(notifyResult.getTotalFee() * OrderSource.MALL.getRate()); - //固定商户信息 - Map mapReceiver = new HashMap<>(4); - mapReceiver.put("type", "MERCHANT_ID"); - mapReceiver.put("account", wxPayProperties.getSharingAccount()); - mapReceiver.put("relation_type", "SERVICE_PROVIDER"); - mapReceiver.put("amount", ceil.longValue()); - mapReceiver.put("name","果酱盒子"); - mapReceiver.put("description", "分账到服务商"); - /* - //添加分账接收方 - ProfitSharingReceiverRequest profitSharingReceiver = new ProfitSharingReceiverRequest(); - profitSharingReceiver.setReceiver(JSONObject.toJSONString(mapReceiver)); - wxPayService.getProfitSharingService().addReceiver(profitSharingReceiver);*/ - //分账 - ProfitSharingRequest profitSharingRequest = new ProfitSharingRequest(); - List> receivers = new ArrayList<>(1); - receivers.add(mapReceiver); - profitSharingRequest.setReceivers(JSONObject.toJSONString(receivers)); - profitSharingRequest.setSignType("HMAC-SHA256"); - profitSharingRequest.setOutOrderNo(profitSharing.getId()); - profitSharingRequest.setTransactionId(notifyResult.getTransactionId()); - ProfitSharingResult profitSharingResult = wxPayService.getProfitSharingService().profitSharing(profitSharingRequest); - //更新分账订单 - profitSharingService.updateChain().set(PROFIT_SHARING.OUT_PROFIT_SHARING_ID, profitSharingResult.getOrderId()) - .set(PROFIT_SHARING.AMOUNT, ceil.longValue()).set(PROFIT_SHARING.PROFIT_SHARING_STATUS, 1).set(PROFIT_SHARING.PAY_ACCOUNT, wxPayProperties.getSharingAccount()) - .where(PROFIT_SHARING.ID.eq(profitSharing.getId())).update(); + @Override + public void parseProfitSharingNotifyResult(String xmlData) { + WxPayService wxPayService = wxPayHandler.getWxPayService(); + try { + WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData); + //更新分账订单 + SpringUtils.getBean(ProfitSharingService.class).updateChain().set(PROFIT_SHARING.OUT_PROFIT_SHARING_ID, notifyResult.getTransactionId()) + .set(PROFIT_SHARING.AMOUNT, notifyResult.getTotalFee()) + .set(PROFIT_SHARING.PROFIT_SHARING_STATUS, 1) + //当前分账账户 + .set(PROFIT_SHARING.PAY_ACCOUNT, wxPayService.getConfig().getSubMchId()) + .where(PROFIT_SHARING.ID.eq(notifyResult.getOutTradeNo())) + .update(); + } catch (WxPayException e) { + throw new ServiceException(e.getMessage()); + } } /** @@ -423,4 +478,77 @@ public class OrderServiceImpl extends ServiceImpl implements .set(ORDER.LOGISTICS_ORDER, bo.getLogisticsOrder()) .where(ORDER.ID.eq(bo.getId())).update(); } + + /** + * @descriptions 小程序-重新支付订单 + * @author DB + * @date 2023/11/03 16:14 + * @param orderId 订单id + * @return: java.lang.Object + */ + @Override + public Object rePayOrder(String orderId) { + Order order = this.getById(orderId); + //获取订单详情 + List orderDetails = SpringUtils.getBean(OrderDetailService.class).queryChain().where(ORDER_DETAIL.ORDER_ID.eq(orderId)).list(); + //获取当前下单用户信息 + JSONObject loginUserInfo = SecurityUtils.getInstance().getLoginUserInfo(); + List productList = SpringUtils.getBean(ProductService.class).queryChain() + .select(PRODUCT.ID, PRODUCT.PRODUCT_NAME, PRODUCT.DESCRIPTION) + .from(PRODUCT) + .leftJoin(PRODUCT_RECORD).on(PRODUCT_RECORD.PRODUCT_ID.eq(PRODUCT.ID)) + .where(PRODUCT_RECORD.ID.in(orderDetails.stream().map(OrderDetail::getProductRecordId).collect(Collectors.toSet()))) + .list(); + //分布式锁进行幂等处理 + RedisService redisService = SpringUtils.getBean(RedisService.class); + Lock userIdLock = redisService.distributedLock(MallRedisConstant.IDEMPOTENT_LOCK_USER_PAY + loginUserInfo.getString("userId")); + if (userIdLock.tryLock()) { + //检查库存 + Map recordNumIsEnough = null; + try { + recordNumIsEnough= recordNumIsEnough(orderDetails); + //微信支付 + if (order.getPayType() == 0) { + //微信支付统一下单 + WxPayService wxPayService = wxPayHandler.getWxPayService(); + WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest(); + //查询是否是服务商系品牌 + String brandId = loginUserInfo.getString("brandId"); + Brand brand = SpringUtils.getBean(BrandService.class).getById(brandId); + if (StringUtils.isBlank(brand.getWxAppId()) || !StringUtils.equals(brand.getWxAppId(), wxPayService.getConfig().getAppId())) { + //需要分账 + orderRequest.setProfitSharing("Y"); + } + orderRequest.setSpbillCreateIp(IpUtils.getHostIp()) + .setOpenid(loginUserInfo.getString("openId")) + //商品描述 + .setBody(productList.stream().map(Product::getDescription).collect(Collectors.joining(","))) + //商品详情,如果涉及到商品优惠需要重新涉及 + .setDetail(JSONObject.toJSONString(BeanUtils.mapToList(orderDetails, WxPayGoodsDetailDto.class))) + .setOutTradeNo(order.getId()) + //元转分 + .setTotalFee(order.getTotalAmount().scaleByPowerOfTen(2).intValue()) + .setTradeType("JSAPI"); + + return wxPayService.createOrder(orderRequest); + } else { + return pointPay(recordNumIsEnough, order.getId()); + } + } catch (Exception e){ + //回滚库存 + if (recordNumIsEnough != null){ + recordNumIsEnough.forEach((key, value) -> { + redisService.longIncrement(MallRedisConstant.STOCK_RECORD_NUM + key, value.longValue()); + }); + } + throw new ServiceException(e.getMessage()); + }finally { + userIdLock.unlock(); + } + }else { + //获取锁失败,直接返回空 + throw new ServiceException("请勿重复下单"); + } + } + } diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/task/OrderOverTimeUnPayTask.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/task/OrderOverTimeUnPayTask.java new file mode 100644 index 0000000..956acf1 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/task/OrderOverTimeUnPayTask.java @@ -0,0 +1,32 @@ +package com.cpop.mall.business.task; + +import com.cpop.core.utils.SpringUtils; +import com.cpop.mall.business.entity.Order; +import com.cpop.mall.business.service.OrderService; +import org.quartz.Job; +import org.quartz.JobDataMap; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +import static com.cpop.mall.business.entity.table.OrderTableDef.ORDER; + +/** + * @author DB + * @createTime 2023/11/03 14:56 + * @description 订单超时未支付任务 + */ +public class OrderOverTimeUnPayTask implements Job { + + @Override + public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { + //获取工单id + JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap(); + String orderId = jobDataMap.getString("orderId"); + OrderService orderService = SpringUtils.getBean(OrderService.class); + Order order = orderService.getById(orderId); + //订单存在并且订单仍然是未支付,修改订单为超时 + if (null != order && order.getOrderStatus() == 0) { + orderService.updateChain().set(ORDER.ORDER_STATUS, 6).set(ORDER.PREVIOUS_STATUS, 0).where(ORDER.ID.eq(orderId)).update(); + } + } +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/task/ProductRecordSyncStockTask.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/task/ProductRecordSyncStockTask.java index 34695b5..9fca3f3 100644 --- a/Cpop-Mall/src/main/java/com/cpop/mall/business/task/ProductRecordSyncStockTask.java +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/task/ProductRecordSyncStockTask.java @@ -12,9 +12,7 @@ import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Transactional; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; import static com.cpop.mall.business.entity.table.ProductRecordTableDef.PRODUCT_RECORD; @@ -41,7 +39,7 @@ public class ProductRecordSyncStockTask { RedisService redisService = SpringUtils.getBean(RedisService.class); productRecords.forEach(item->{ redisService.setCacheObject(MallRedisConstant.STOCK_RECORD_NUM + item.getId(), item.getRecordNum()); - log.info("商品记录id为:{};商品库存为:{}", item.getProductId(), item.getRecordNum()); + log.info("商品记录id为:{};商品库存为:{}", item.getId(), item.getRecordNum()); }); log.info("===============================结束<--库存信息结束-->结束==============================="); } diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/task/WxPayAsyncTask.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/task/WxPayAsyncTask.java new file mode 100644 index 0000000..89671e9 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/task/WxPayAsyncTask.java @@ -0,0 +1,137 @@ +package com.cpop.mall.business.task; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.cpop.core.base.enums.OrderSource; +import com.cpop.core.base.exception.ServiceException; +import com.cpop.core.base.exception.UtilException; +import com.cpop.core.utils.SpringUtils; +import com.cpop.mall.framework.config.wxPay.WxPayProperties; +import com.cpop.system.business.entity.ProfitSharing; +import com.cpop.system.business.service.ProfitSharingService; +import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; +import com.github.binarywang.wxpay.bean.profitsharing.ProfitSharingReceiverRequest; +import com.github.binarywang.wxpay.bean.profitsharing.ProfitSharingRequest; +import com.github.binarywang.wxpay.bean.profitsharing.ProfitSharingResult; +import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingReceiver; +import com.github.binarywang.wxpay.config.WxPayConfig; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.service.WxPayService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.cpop.system.business.entity.table.ProfitSharingTableDef.PROFIT_SHARING; + +/** + * @author DB + * @createTime 2023/11/03 11:13 + * @description 微信支付异步处理类 + */ +@Component +public class WxPayAsyncTask { + + @Autowired + private WxPayProperties wxPayProperties; + + /** + * @descriptions 异步分账 + * @author DB + * @date 2023/11/03 11:14 + * @param orderId 订单id + * @param notifyResult 通知结果 + * @param wxPayService 微信支付处理类 + * @return: void + */ + @Async("customAsyncThreadPool") + public void asyncWxPayProfitSharing(String orderId, WxPayOrderNotifyResult notifyResult, WxPayService wxPayService) { + ProfitSharingRequest profitSharingRequest = buildProfitSharingRequest(orderId, notifyResult); + try { + Thread.sleep(5000); + wxPayProfitSharing(profitSharingRequest, wxPayService, 0); + } catch (InterruptedException e) { + throw new ServiceException(e.getMessage()); + } + } + + /** + * @descriptions 构建分账请求参数 + * @author DB + * @date 2023/11/03 11:12 + * @param orderId 订单号 + * @param notifyResult 通知结果 + * @return: com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingRequest + */ + private ProfitSharingRequest buildProfitSharingRequest(String orderId, WxPayOrderNotifyResult notifyResult) { + Double ceil = Math.ceil(notifyResult.getTotalFee() * OrderSource.MALL.getRate()); + ProfitSharing profitSharing = new ProfitSharing(); + profitSharing.setOrderId(orderId) + .setProfitSharingStatus(0) + .setOrderSource(OrderSource.MALL.toString()) + .setAmount(ceil.longValue()) + .setPayAccount(notifyResult.getSubMchId()); + ProfitSharingService profitSharingService = SpringUtils.getBean(ProfitSharingService.class); + profitSharingService.save(profitSharing); + //固定商户信息 + Map mapReceiver = new HashMap<>(4); + mapReceiver.put("type", "MERCHANT_ID"); + mapReceiver.put("account", wxPayProperties.getSharingAccount()); + mapReceiver.put("amount", ceil.longValue()); + mapReceiver.put("description","分账到服务商"); + //TODO:V3版本目前发送失败 + /* + ProfitSharingReceiverRequest profitSharingReceiver = new ProfitSharingReceiverRequest(); + profitSharingReceiver.setReceiver(); + ProfitSharingReceiver profitSharingReceiver = new ProfitSharingReceiver(); + profitSharingReceiver.setType("MERCHANT_ID"); + profitSharingReceiver.setAccount(wxPayProperties.getSharingAccount()); + profitSharingReceiver.setRelationType("SERVICE_PROVIDER"); + profitSharingReceiver.setAmount(ceil.longValue()); + profitSharingReceiver.setName("果酱盒子"); + profitSharingReceiver.setDescription("分账到服务商"); + */ + List> receivers = new ArrayList<>(); + receivers.add(mapReceiver); + //分账请求参数 + ProfitSharingRequest profitSharingRequest = new ProfitSharingRequest(); + profitSharingRequest.setReceivers(JSONObject.toJSONString(receivers)); + profitSharingRequest.setOutOrderNo(profitSharing.getId()); + profitSharingRequest.setTransactionId(notifyResult.getTransactionId()); + profitSharingRequest.setSubMchId(notifyResult.getSubMchId()); + return profitSharingRequest; + } + + /** + * @descriptions 微信支付分账 + * @author DB + * @date 2023/11/03 11:09 + * @param profitSharingRequest 请求参数 + * @param wxPayService 微信服务类 + * @param flag 标记 + * @return: void + */ + private void wxPayProfitSharing(ProfitSharingRequest profitSharingRequest, WxPayService wxPayService, Integer flag) { + try { + ProfitSharingResult profitSharingResult = wxPayService.getProfitSharingService().profitSharing(profitSharingRequest); + //存入系统 + SpringUtils.getBean(ProfitSharingService.class).updateChain() + .set(PROFIT_SHARING.OUT_PROFIT_SHARING_ID,profitSharingResult.getOrderId()) + .set(PROFIT_SHARING.PROFIT_SHARING_STATUS,1) + .where(PROFIT_SHARING.ID.eq(profitSharingResult.getOutOrderNo())) + .update(); + } catch (WxPayException e) { + if (flag > 5) { + throw new ServiceException(e.getMessage()); + } else { + //重复调用 + flag = flag + 1; + wxPayProfitSharing(profitSharingRequest, wxPayService, flag); + } + } + } +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/OrderInfoVo.java b/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/OrderInfoVo.java new file mode 100644 index 0000000..1230b6c --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/business/vo/OrderInfoVo.java @@ -0,0 +1,102 @@ +package com.cpop.mall.business.vo; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +/** + * @author DB + * @createTime 2023/11/03 15:54 + * @description + */ +@Data +@Accessors(chain = true) +@ApiModel(value = "商城订单详情返回对象") +public class OrderInfoVo implements Serializable { + + /** + * 主键 + */ + @ApiModelProperty("主键") + private String id; + + /** + * 订单状态(0:待付款;1:待发货;2:待确认;3:已完成;4:退款/售后中) + */ + @ApiModelProperty("订单状态(0:待付款;1:待发货;2:待确认;3:已完成;4:退款/售后中)") + private Integer orderStatus; + + /** + * 总金额 + */ + @ApiModelProperty("总金额") + private BigDecimal totalAmount; + + /** + * 总积分 + */ + @ApiModelProperty("总积分") + private Long totalPoint; + + /** + * 支付类型 + */ + @ApiModelProperty("支付类型") + private Integer payType; + + /** + * 下单用户名 + */ + @ApiModelProperty("下单用户名") + private String payUserName; + + /** + * 收货人名 + */ + @ApiModelProperty("收货人名") + private String receiveName; + + /** + * 收货人电话 + */ + @ApiModelProperty("收货人电话") + private String receivePhone; + + /** + * 收货地址 + */ + @ApiModelProperty("收货地址") + private String receiveAddress; + + /** + * 商品名 + */ + @ApiModelProperty("商品名") + private String productNames; + + /** + * 备注 + */ + @ApiModelProperty("备注") + private String remarks; + + /** + * 下单时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss" , timezone = "GMT+8") + @ApiModelProperty("下单时间") + private LocalDateTime createTime; + + /** + * 订单详情vo + */ + @ApiModelProperty("订单详情") + private List detailList; +} diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/framework/config/wxPay/WxPayProperties.java b/Cpop-Mall/src/main/java/com/cpop/mall/framework/config/wxPay/WxPayProperties.java index a5e2724..bd28bc5 100644 --- a/Cpop-Mall/src/main/java/com/cpop/mall/framework/config/wxPay/WxPayProperties.java +++ b/Cpop-Mall/src/main/java/com/cpop/mall/framework/config/wxPay/WxPayProperties.java @@ -65,4 +65,9 @@ public class WxPayProperties { * 分账账号 */ private String sharingAccount; + + /** + * 分账通知 + */ + private String notifySharing; } diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/framework/constant/MallRedisConstant.java b/Cpop-Mall/src/main/java/com/cpop/mall/framework/constant/MallRedisConstant.java index fb7bd1a..ffce9d5 100644 --- a/Cpop-Mall/src/main/java/com/cpop/mall/framework/constant/MallRedisConstant.java +++ b/Cpop-Mall/src/main/java/com/cpop/mall/framework/constant/MallRedisConstant.java @@ -10,6 +10,11 @@ public interface MallRedisConstant { */ String STOCK_RECORD_NUM = "mall:stock:recordNum:"; + /** + * 用户创建预订单(用户id) + */ + String IDEMPOTENT_LOCK_CREATE_ADVANCE_ORDER = "mall:idempotentLock:createAdvanceOrder:"; + /** * 用户下单幂等锁(用户id) */ diff --git a/Cpop-Mall/src/main/java/com/cpop/mall/framework/enums/QuartzEnums.java b/Cpop-Mall/src/main/java/com/cpop/mall/framework/enums/QuartzEnums.java new file mode 100644 index 0000000..a3f0785 --- /dev/null +++ b/Cpop-Mall/src/main/java/com/cpop/mall/framework/enums/QuartzEnums.java @@ -0,0 +1,35 @@ +package com.cpop.mall.framework.enums; + +import lombok.Getter; + +@Getter +public enum QuartzEnums { + + /** + * 订单超时未支付过期定时任务 + */ + ORDER_OVERTIME_UN_PAY_TASK("OrderOvertimeUnPayTask:", "Order"); + + QuartzEnums(String name, String group) { + this.name = name; + this.group = group; + } + + /** + * 名 + */ + private String name; + + /** + * 组 + */ + private String group; + + public void setName(String name) { + this.name = name; + } + + public void setGroup(String group) { + this.group = group; + } +}