商城预订单;分账与分账退款;添加微信支付异步任务类
This commit is contained in:
parent
5984409601
commit
212110afc8
@ -120,3 +120,5 @@ wx:
|
|||||||
notifyUrl: https://frp-oak.top:11899/Cpop-Mall/wxPay/callback/notify/order
|
notifyUrl: https://frp-oak.top:11899/Cpop-Mall/wxPay/callback/notify/order
|
||||||
#退款通知地址
|
#退款通知地址
|
||||||
notifyRefund: https://frp-oak.top:11899/Cpop-Mall/wxPay/callback/notify/refund
|
notifyRefund: https://frp-oak.top:11899/Cpop-Mall/wxPay/callback/notify/refund
|
||||||
|
#分账通知地址
|
||||||
|
notifySharing: https://frp-oak.top:11899/Cpop-Mall/wxPay/callback/notify/profitSharing
|
||||||
@ -106,7 +106,7 @@ task:
|
|||||||
# 设置空闲线程存活时间(秒
|
# 设置空闲线程存活时间(秒
|
||||||
keepAliveSeconds: 300
|
keepAliveSeconds: 300
|
||||||
# 设置队列容量
|
# 设置队列容量
|
||||||
queueCapacity: 10240
|
queueCapacity: 1024
|
||||||
# 设置线程名称前缀
|
# 设置线程名称前缀
|
||||||
threadNamePrefix: "Cpop-Mall-AsyncNotify-"
|
threadNamePrefix: "Cpop-Mall-AsyncNotify-"
|
||||||
# 设置线程池等待终止时间(秒)
|
# 设置线程池等待终止时间(秒)
|
||||||
|
|||||||
@ -1,20 +1,29 @@
|
|||||||
package com.cpop.mall.web;
|
package com.cpop.mall.web;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.cpop.core.utils.SpringUtils;
|
import com.cpop.core.utils.SpringUtils;
|
||||||
import com.cpop.core.utils.uuid.IdUtils;
|
import com.cpop.core.utils.uuid.IdUtils;
|
||||||
import com.cpop.mall.business.entity.Order;
|
import com.cpop.mall.business.entity.Order;
|
||||||
import com.cpop.mall.business.service.OrderService;
|
import com.cpop.mall.business.service.OrderService;
|
||||||
import com.cpop.mall.framework.config.wxPay.WxPayProperties;
|
import com.cpop.mall.framework.config.wxPay.WxPayProperties;
|
||||||
import com.cpop.system.business.entity.Brand;
|
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.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.request.WxPayRefundV3Request;
|
||||||
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
|
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.exception.WxPayException;
|
||||||
import com.github.binarywang.wxpay.service.WxPayService;
|
import com.github.binarywang.wxpay.service.WxPayService;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author DB
|
* @author DB
|
||||||
* @createTime 2023/11/01 18:15
|
* @createTime 2023/11/01 18:15
|
||||||
@ -38,7 +47,7 @@ public class CpopWxPayTests {
|
|||||||
@Test
|
@Test
|
||||||
public void refund() throws WxPayException {
|
public void refund() throws WxPayException {
|
||||||
Brand brand = SpringUtils.getBean(BrandService.class).getById("75140168047210496");
|
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 request = new WxPayRefundV3Request();
|
||||||
WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount();
|
WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount();
|
||||||
//退款金额(单位分)
|
//退款金额(单位分)
|
||||||
@ -57,4 +66,49 @@ public class CpopWxPayTests {
|
|||||||
WxPayRefundV3Result result = wxPayService.refundV3(request);
|
WxPayRefundV3Result result = wxPayService.refundV3(request);
|
||||||
System.out.println(result);
|
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<String, Object> 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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<OrderDetailBo> orderDetailList;
|
||||||
|
}
|
||||||
@ -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;
|
||||||
|
}
|
||||||
@ -29,26 +29,6 @@ public class PlaceOrderBo implements Serializable {
|
|||||||
@ApiModelProperty("主键")
|
@ApiModelProperty("主键")
|
||||||
private String id;
|
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)
|
@ApiModelProperty(value = "收货人电话",required = true)
|
||||||
private String receivePhone;
|
private String receivePhone;
|
||||||
|
|
||||||
/**
|
|
||||||
* 当前订单所有产品名
|
|
||||||
*/
|
|
||||||
@StringArrayConvert
|
|
||||||
@ApiModelProperty(value = "当前订单所有产品名")
|
|
||||||
private String productNames;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 收货地址
|
* 收货地址
|
||||||
*/
|
*/
|
||||||
@ -90,53 +63,4 @@ public class PlaceOrderBo implements Serializable {
|
|||||||
@ApiModelProperty(value = "支付方式(0:微信支付;1:积分支付)",required = true)
|
@ApiModelProperty(value = "支付方式(0:微信支付;1:积分支付)",required = true)
|
||||||
private Integer payType;
|
private Integer payType;
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单详情
|
|
||||||
*/
|
|
||||||
@NotEmpty(message = "订单详情不能为空")
|
|
||||||
@ApiModelProperty(value = "订单详情",required = true)
|
|
||||||
private List<PlaceOrderDetail> 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -52,4 +52,17 @@ public class WxPayCallbackController {
|
|||||||
return WxPayNotifyResponse.success("成功");
|
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("成功");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,13 +3,11 @@ package com.cpop.mall.business.controller.mini;
|
|||||||
import com.cpop.common.utils.bean.BeanUtils;
|
import com.cpop.common.utils.bean.BeanUtils;
|
||||||
import com.cpop.core.base.R;
|
import com.cpop.core.base.R;
|
||||||
import com.cpop.core.utils.SpringUtils;
|
import com.cpop.core.utils.SpringUtils;
|
||||||
import com.cpop.mall.business.bo.OrderApplyRefundBo;
|
import com.cpop.mall.business.bo.*;
|
||||||
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.entity.OrderEvaluate;
|
import com.cpop.mall.business.entity.OrderEvaluate;
|
||||||
import com.cpop.mall.business.service.OrderEvaluateService;
|
import com.cpop.mall.business.service.OrderEvaluateService;
|
||||||
import com.cpop.mall.business.service.OrderService;
|
import com.cpop.mall.business.service.OrderService;
|
||||||
|
import com.cpop.mall.business.vo.OrderInfoVo;
|
||||||
import com.cpop.mall.business.vo.OrderPageVo;
|
import com.cpop.mall.business.vo.OrderPageVo;
|
||||||
import com.mybatisflex.core.paginate.Page;
|
import com.mybatisflex.core.paginate.Page;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
@ -49,6 +47,19 @@ public class MiniOrderController {
|
|||||||
return R.ok(page);
|
return R.ok(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @descriptions 生成预订单
|
||||||
|
* @author DB
|
||||||
|
* @date 2023/11/06 11:12
|
||||||
|
* @param bo 请求参数
|
||||||
|
* @return: com.cpop.core.base.R<java.lang.Object>
|
||||||
|
*/
|
||||||
|
@PostMapping("/createAdvanceOrder")
|
||||||
|
@ApiOperation("商城-订单-生成预订单")
|
||||||
|
public R<String> createAdvanceOrder(@RequestBody @Validated @ApiParam("商城-预订单参数") AdvanceOrderBo bo) {
|
||||||
|
return R.ok(orderService.createAdvanceOrder(bo));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @descriptions 商城-订单-下单
|
* @descriptions 商城-订单-下单
|
||||||
* @author DB
|
* @author DB
|
||||||
@ -103,9 +114,24 @@ public class MiniOrderController {
|
|||||||
*/
|
*/
|
||||||
@PutMapping("/cancelOrder")
|
@PutMapping("/cancelOrder")
|
||||||
@ApiOperation("取消订单")
|
@ApiOperation("取消订单")
|
||||||
public R<Object> cancelOrder(@RequestParam("orderId") @ApiParam("商城-订单Id") String orderId) {
|
public R<Void> cancelOrder(@RequestParam("orderId") @ApiParam("商城-订单Id") String orderId) {
|
||||||
orderService.cancelOrder(orderId);
|
orderService.cancelOrder(orderId);
|
||||||
return R.ok();
|
return R.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @descriptions 小程序-重新支付订单
|
||||||
|
* @author DB
|
||||||
|
* @date 2023/11/03 15:53
|
||||||
|
* @param orderId 订单id
|
||||||
|
* @return: com.cpop.core.base.R<com.mybatisflex.core.paginate.Page<com.cpop.mall.business.vo.OrderPageVo>>
|
||||||
|
*/
|
||||||
|
@GetMapping("/rePayOrder/{orderId}")
|
||||||
|
@ApiOperation("小程序-重新支付订单")
|
||||||
|
public R<Object> rePayOrder(@PathVariable @ApiParam(value = "订单id", required = true) String orderId) {
|
||||||
|
return R.ok(orderService.rePayOrder(orderId));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
}
|
||||||
@ -34,12 +34,12 @@ public class Order extends BaseEntity implements Serializable {
|
|||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 订单状态(0:待付款;1:待发货;2:待确认;3:已完成;4:退款/售后中)
|
* 订单状态(0:待付款;1:待发货;2:待确认;3:已完成;4:退款/售后中:5:订单取消;6:过期)
|
||||||
*/
|
*/
|
||||||
private Integer orderStatus;
|
private Integer orderStatus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上一个状态(0:待付款;1:待发货;2:待确认;3:已完成;4:退款/售后中:5:订单取消)
|
* 上一个状态(0:待付款;1:待发货;2:待确认;3:已完成;4:退款/售后中:5:订单取消;6:过期)
|
||||||
*/
|
*/
|
||||||
private Integer previousStatus;
|
private Integer previousStatus;
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
package com.cpop.mall.business.service;
|
package com.cpop.mall.business.service;
|
||||||
|
|
||||||
import com.cpop.mall.business.bo.LogisticsOrderBo;
|
import com.cpop.mall.business.bo.*;
|
||||||
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.entity.Order;
|
import com.cpop.mall.business.entity.Order;
|
||||||
|
import com.cpop.mall.business.vo.OrderInfoVo;
|
||||||
import com.cpop.mall.business.vo.OrderPageVo;
|
import com.cpop.mall.business.vo.OrderPageVo;
|
||||||
import com.mybatisflex.core.paginate.Page;
|
import com.mybatisflex.core.paginate.Page;
|
||||||
import com.mybatisflex.core.service.IService;
|
import com.mybatisflex.core.service.IService;
|
||||||
@ -26,6 +24,15 @@ public interface OrderService extends IService<Order> {
|
|||||||
*/
|
*/
|
||||||
Page<OrderPageVo> getOrderPage(OrderPageBo bo);
|
Page<OrderPageVo> getOrderPage(OrderPageBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @descriptions 生成预订单
|
||||||
|
* @author DB
|
||||||
|
* @date 2023/11/06 11:17
|
||||||
|
* @param bo 请求参数
|
||||||
|
* @return: java.lang.Object
|
||||||
|
*/
|
||||||
|
String createAdvanceOrder(AdvanceOrderBo bo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @descriptions 商城-订单-下单
|
* @descriptions 商城-订单-下单
|
||||||
* @author DB
|
* @author DB
|
||||||
@ -53,6 +60,15 @@ public interface OrderService extends IService<Order> {
|
|||||||
*/
|
*/
|
||||||
void wxPayNotifyOrder(String xmlData);
|
void wxPayNotifyOrder(String xmlData);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @descriptions 分账结果通知
|
||||||
|
* @author DB
|
||||||
|
* @date 2023/11/03 9:50
|
||||||
|
* @param xmlData 加密数据
|
||||||
|
* @return: void
|
||||||
|
*/
|
||||||
|
void parseProfitSharingNotifyResult(String xmlData);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @descriptions 取消订单
|
* @descriptions 取消订单
|
||||||
* @author DB
|
* @author DB
|
||||||
@ -69,4 +85,14 @@ public interface OrderService extends IService<Order> {
|
|||||||
* @Date: 2023/10/28 15:27
|
* @Date: 2023/10/28 15:27
|
||||||
*/
|
*/
|
||||||
void inputLogisticsOrder(LogisticsOrderBo bo);
|
void inputLogisticsOrder(LogisticsOrderBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @descriptions 小程序-重新支付订单
|
||||||
|
* @author DB
|
||||||
|
* @date 2023/11/03 16:14
|
||||||
|
* @param orderId 订单id
|
||||||
|
* @return: java.lang.Object
|
||||||
|
*/
|
||||||
|
Object rePayOrder(String orderId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import com.cpop.core.base.enums.OrderSource;
|
|||||||
import com.cpop.core.base.exception.ServiceException;
|
import com.cpop.core.base.exception.ServiceException;
|
||||||
import com.cpop.core.utils.SpringUtils;
|
import com.cpop.core.utils.SpringUtils;
|
||||||
import com.cpop.core.utils.sql.SqlUtils;
|
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.OrderRefundPageBo;
|
||||||
import com.cpop.mall.business.bo.OrderRejectRefundBo;
|
import com.cpop.mall.business.bo.OrderRejectRefundBo;
|
||||||
import com.cpop.mall.business.entity.Order;
|
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.business.vo.OrderRefundPageVo;
|
||||||
import com.cpop.mall.framework.config.wxPay.WxPayProperties;
|
import com.cpop.mall.framework.config.wxPay.WxPayProperties;
|
||||||
import com.cpop.mall.framework.handler.WxPayHandler;
|
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.entity.ProfitSharing;
|
||||||
|
import com.cpop.system.business.service.BrandService;
|
||||||
import com.cpop.system.business.service.ProfitSharingService;
|
import com.cpop.system.business.service.ProfitSharingService;
|
||||||
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
|
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.request.WxPayRefundV3Request;
|
||||||
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
|
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
|
||||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||||
@ -63,17 +68,26 @@ public class OrderRefundServiceImpl extends ServiceImpl<OrderRefundMapper, Order
|
|||||||
OrderRefund orderRefund = this.queryChain().where(ORDER_REFUND.ID.eq(id)).one();
|
OrderRefund orderRefund = this.queryChain().where(ORDER_REFUND.ID.eq(id)).one();
|
||||||
Order order = SpringUtils.getBean(OrderService.class).queryChain().where(ORDER.ID.eq(orderRefund.getOrderId())).one();
|
Order order = SpringUtils.getBean(OrderService.class).queryChain().where(ORDER.ID.eq(orderRefund.getOrderId())).one();
|
||||||
//分账记录
|
//分账记录
|
||||||
ProfitSharing profitSharing = SpringUtils.getBean(ProfitSharingService.class).queryChain().where(PROFIT_SHARING.ORDER_ID.eq(order.getId()))
|
ProfitSharingService profitSharingService = SpringUtils.getBean(ProfitSharingService.class);
|
||||||
.and(PROFIT_SHARING.ORDER_SOURCE.eq(OrderSource.MALL.toString())).one();
|
ProfitSharing profitSharing = profitSharingService.queryChain().where(PROFIT_SHARING.ORDER_ID.eq(order.getId()))
|
||||||
//TODO:可能还需要先从分账退款
|
.and(PROFIT_SHARING.ORDER_SOURCE.eq(OrderSource.MALL.toString()))
|
||||||
/*ProfitSharingReturnRequest profitSharingReturnRequest = new ProfitSharingReturnRequest();
|
.and(PROFIT_SHARING.PROFIT_SHARING_STATUS.eq(1))
|
||||||
profitSharingReturnRequest.setOrderId(profitSharing.getOutProfitSharingId());
|
.one();
|
||||||
profitSharingReturnRequest.setReturnMchid(profitSharing.getPayAccount());
|
if (null != profitSharing){
|
||||||
profitSharingReturnRequest.setAmount(profitSharing.getAmount());
|
ProfitSharingReturnRequest profitSharingReturnRequest = new ProfitSharingReturnRequest();
|
||||||
profitSharingReturnRequest.setOutOrderNo(profitSharing.getId());
|
profitSharingReturnRequest.setOrderId(profitSharing.getOutProfitSharingId());
|
||||||
profitSharingReturnRequest.setDescription("订单退款");
|
profitSharingReturnRequest.setOutReturnNo(profitSharing.getId());
|
||||||
profitSharingReturnRequest.setSubMchId("1618436087");
|
profitSharingReturnRequest.setDescription("分账退款");
|
||||||
ProfitSharingReturnResult profitSharingReturnResult = wxPayService.getProfitSharingV3Service().profitSharingReturn(profitSharingReturnRequest);*/
|
profitSharingReturnRequest.setSubMchId(profitSharing.getPayAccount());
|
||||||
|
profitSharingReturnRequest.setReturnMchid(wxPayProperties.getSharingAccount());
|
||||||
|
profitSharingReturnRequest.setAmount(profitSharing.getAmount());
|
||||||
|
wxPayService.getProfitSharingV3Service().profitSharingReturn(profitSharingReturnRequest);
|
||||||
|
//分账退款记录设置退款
|
||||||
|
profitSharingService.updateChain()
|
||||||
|
.set(PROFIT_SHARING.PROFIT_SHARING_STATUS, 2)
|
||||||
|
.where(PROFIT_SHARING.ID.eq(profitSharing.getId()))
|
||||||
|
.update();
|
||||||
|
}
|
||||||
WxPayRefundV3Request request = new WxPayRefundV3Request();
|
WxPayRefundV3Request request = new WxPayRefundV3Request();
|
||||||
WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount();
|
WxPayRefundV3Request.Amount amount = new WxPayRefundV3Request.Amount();
|
||||||
//退款金额(单位分)
|
//退款金额(单位分)
|
||||||
@ -87,8 +101,7 @@ public class OrderRefundServiceImpl extends ServiceImpl<OrderRefundMapper, Order
|
|||||||
.setOutRefundNo(id)
|
.setOutRefundNo(id)
|
||||||
.setReason(orderRefund.getRefundReason())
|
.setReason(orderRefund.getRefundReason())
|
||||||
.setAmount(amount);
|
.setAmount(amount);
|
||||||
WxPayRefundV3Result result = wxPayService.refundV3(request);
|
wxPayService.refundV3(request);
|
||||||
this.updateChain().set(ORDER_REFUND.REFUND_STATUS, 1).where(ORDER_REFUND.OUT_REFUND_ID.eq(result.getRefundId())).update();
|
|
||||||
} catch (WxPayException e) {
|
} catch (WxPayException e) {
|
||||||
throw new ServiceException(e.getMessage());
|
throw new ServiceException(e.getMessage());
|
||||||
}
|
}
|
||||||
@ -156,12 +169,13 @@ public class OrderRefundServiceImpl extends ServiceImpl<OrderRefundMapper, Order
|
|||||||
@Override
|
@Override
|
||||||
public void wxPayNotifyRefund(String xmlData) {
|
public void wxPayNotifyRefund(String xmlData) {
|
||||||
try {
|
try {
|
||||||
WxPayRefundNotifyResult result = wxPayHandler.getWxPayService().parseRefundNotifyResult(xmlData);
|
WxPayRefundNotifyV3Result result = wxPayHandler.getWxPayService().parseRefundNotifyV3Result(xmlData, null);
|
||||||
WxPayRefundNotifyResult.ReqInfo reqInfo = result.getReqInfo();
|
WxPayRefundNotifyV3Result.DecryptNotifyResult reqInfo = result.getResult();
|
||||||
|
//获取退款单号
|
||||||
this.updateChain().set(ORDER_REFUND.REFUND_STATUS, 1)
|
this.updateChain().set(ORDER_REFUND.REFUND_STATUS, 1)
|
||||||
.set(ORDER_REFUND.OUT_REFUND_ID, reqInfo.getRefundId())
|
.set(ORDER_REFUND.OUT_REFUND_ID, reqInfo.getRefundId())
|
||||||
.where(ORDER_REFUND.ID.eq(reqInfo.getOutRefundNo())).update();
|
.where(ORDER_REFUND.ID.eq(reqInfo.getOutRefundNo()))
|
||||||
//TODO:回滚库存
|
.update();
|
||||||
} catch (WxPayException e) {
|
} catch (WxPayException e) {
|
||||||
throw new ServiceException(e.getMessage());
|
throw new ServiceException(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,45 +1,43 @@
|
|||||||
package com.cpop.mall.business.service.impl;
|
package com.cpop.mall.business.service.impl;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.cpop.common.utils.DateUtils;
|
||||||
import com.cpop.common.utils.StringUtils;
|
import com.cpop.common.utils.StringUtils;
|
||||||
import com.cpop.common.utils.bean.BeanUtils;
|
import com.cpop.common.utils.bean.BeanUtils;
|
||||||
import com.cpop.common.utils.ip.IpUtils;
|
import com.cpop.common.utils.ip.IpUtils;
|
||||||
import com.cpop.core.base.entity.PageDomain;
|
import com.cpop.core.base.entity.PageDomain;
|
||||||
import com.cpop.core.base.enums.OrderSource;
|
|
||||||
import com.cpop.core.base.enums.UserType;
|
import com.cpop.core.base.enums.UserType;
|
||||||
import com.cpop.core.base.exception.ServiceException;
|
import com.cpop.core.base.exception.ServiceException;
|
||||||
import com.cpop.core.service.RedisService;
|
import com.cpop.core.service.RedisService;
|
||||||
|
import com.cpop.core.utils.QuartzUtils;
|
||||||
import com.cpop.core.utils.SecurityUtils;
|
import com.cpop.core.utils.SecurityUtils;
|
||||||
import com.cpop.core.utils.SpringUtils;
|
import com.cpop.core.utils.SpringUtils;
|
||||||
import com.cpop.core.utils.sql.SqlUtils;
|
import com.cpop.core.utils.sql.SqlUtils;
|
||||||
import com.cpop.mall.business.bo.LogisticsOrderBo;
|
import com.cpop.mall.business.bo.*;
|
||||||
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.dto.WxPayGoodsDetailDto;
|
import com.cpop.mall.business.dto.WxPayGoodsDetailDto;
|
||||||
import com.cpop.mall.business.entity.*;
|
import com.cpop.mall.business.entity.*;
|
||||||
import com.cpop.mall.business.mapper.OrderMapper;
|
import com.cpop.mall.business.mapper.OrderMapper;
|
||||||
import com.cpop.mall.business.service.*;
|
import com.cpop.mall.business.service.*;
|
||||||
|
import com.cpop.mall.business.task.OrderOverTimeUnPayTask;
|
||||||
import com.cpop.mall.business.task.ProductRecordSyncStockTask;
|
import com.cpop.mall.business.task.ProductRecordSyncStockTask;
|
||||||
|
import com.cpop.mall.business.task.WxPayAsyncTask;
|
||||||
|
import com.cpop.mall.business.vo.OrderInfoVo;
|
||||||
import com.cpop.mall.business.vo.OrderPageVo;
|
import com.cpop.mall.business.vo.OrderPageVo;
|
||||||
import com.cpop.mall.framework.config.wxPay.WxPayProperties;
|
|
||||||
import com.cpop.mall.framework.constant.MallRedisConstant;
|
import com.cpop.mall.framework.constant.MallRedisConstant;
|
||||||
|
import com.cpop.mall.framework.enums.QuartzEnums;
|
||||||
import com.cpop.mall.framework.handler.WxPayHandler;
|
import com.cpop.mall.framework.handler.WxPayHandler;
|
||||||
import com.cpop.system.business.entity.Brand;
|
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.BrandService;
|
||||||
import com.cpop.system.business.service.ProfitSharingService;
|
import com.cpop.system.business.service.ProfitSharingService;
|
||||||
|
|
||||||
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
|
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.bean.request.WxPayUnifiedOrderRequest;
|
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
|
||||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||||
import com.github.binarywang.wxpay.service.WxPayService;
|
import com.github.binarywang.wxpay.service.WxPayService;
|
||||||
import com.mybatisflex.core.paginate.Page;
|
import com.mybatisflex.core.paginate.Page;
|
||||||
import com.mybatisflex.core.query.QueryWrapper;
|
import com.mybatisflex.core.query.QueryWrapper;
|
||||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||||
|
import org.quartz.*;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
@ -71,7 +69,10 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
|||||||
private WxPayHandler wxPayHandler;
|
private WxPayHandler wxPayHandler;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private WxPayProperties wxPayProperties;
|
private Scheduler scheduler;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WxPayAsyncTask wxPayAsyncTask;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @descriptions 分页查询商城-订单
|
* @descriptions 分页查询商城-订单
|
||||||
@ -96,6 +97,12 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
|||||||
//查询此用户订单
|
//查询此用户订单
|
||||||
queryWrapper.where(ORDER.PAY_USER_ID.eq(loginUserInfo.getString("userId")));
|
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();
|
PageDomain pageDomain = SqlUtils.getInstance().getPageDomain();
|
||||||
return this.mapper.paginateAs(Page.of(pageDomain.getPageNum(),pageDomain.getPageSize()),
|
return this.mapper.paginateAs(Page.of(pageDomain.getPageNum(),pageDomain.getPageSize()),
|
||||||
queryWrapper
|
queryWrapper
|
||||||
@ -105,8 +112,6 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
|||||||
.and(ORDER.PAY_USER_NAME.like(bo.getPayUserName()))
|
.and(ORDER.PAY_USER_NAME.like(bo.getPayUserName()))
|
||||||
.and(ORDER.RECEIVE_PHONE.like(bo.getReceivePhone()))
|
.and(ORDER.RECEIVE_PHONE.like(bo.getReceivePhone()))
|
||||||
.and(ORDER.PRODUCT_NAMES.like(bo.getProductName()))
|
.and(ORDER.PRODUCT_NAMES.like(bo.getProductName()))
|
||||||
//订单状态
|
|
||||||
.and(ORDER.ORDER_STATUS.eq(bo.getOrderStatus()))
|
|
||||||
.orderBy(ORDER.CREATE_TIME.desc()),
|
.orderBy(ORDER.CREATE_TIME.desc()),
|
||||||
OrderPageVo.class,
|
OrderPageVo.class,
|
||||||
//子查询
|
//子查询
|
||||||
@ -128,27 +133,26 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @descriptions 商城-订单-下单
|
* @descriptions 生成预订单
|
||||||
* @author DB
|
* @author DB
|
||||||
* @date 2023/10/25 9:32
|
* @date 2023/11/06 11:17
|
||||||
* @param bo 下单请求对象
|
* @param bo 请求参数
|
||||||
* @return: void
|
* @return: java.lang.Object
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
public String createAdvanceOrder(AdvanceOrderBo bo) {
|
||||||
public Object placeOrder(PlaceOrderBo bo) {
|
|
||||||
RedisService redisService = SpringUtils.getBean(RedisService.class);
|
RedisService redisService = SpringUtils.getBean(RedisService.class);
|
||||||
//获取当前下单用户信息
|
//获取当前下单用户信息
|
||||||
JSONObject loginUserInfo = SecurityUtils.getInstance().getLoginUserInfo();
|
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()) {
|
if (userIdLock.tryLock()) {
|
||||||
//检查库存
|
//检查库存
|
||||||
Map<String, Integer> recordNumIsEnough = null;
|
Map<String, Integer> recordNumIsEnough = null;
|
||||||
try {
|
try {
|
||||||
recordNumIsEnough= recordNumIsEnough(bo.getPlaceOrderDetailList());
|
|
||||||
Order order = BeanUtils.mapToClass(bo, Order.class);
|
Order order = BeanUtils.mapToClass(bo, Order.class);
|
||||||
List<OrderDetail> orderDetails = BeanUtils.mapToList(bo.getPlaceOrderDetailList(), OrderDetail.class);
|
List<OrderDetail> orderDetails = BeanUtils.mapToList(bo.getOrderDetailList(), OrderDetail.class);
|
||||||
|
recordNumIsEnough= recordNumIsEnough(orderDetails);
|
||||||
//规格记录ids
|
//规格记录ids
|
||||||
Set<String> recordIds = orderDetails.stream().map(OrderDetail::getProductRecordId).collect(Collectors.toSet());
|
Set<String> recordIds = orderDetails.stream().map(OrderDetail::getProductRecordId).collect(Collectors.toSet());
|
||||||
//获取涉及到的商品
|
//获取涉及到的商品
|
||||||
@ -170,11 +174,76 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
|||||||
order.setPayUserName(loginUserInfo.getString("nickName"));
|
order.setPayUserName(loginUserInfo.getString("nickName"));
|
||||||
}
|
}
|
||||||
this.save(order);
|
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 -> {
|
orderDetails.forEach(item -> {
|
||||||
item.setOrderId(order.getId());
|
item.setOrderId(order.getId());
|
||||||
});
|
});
|
||||||
SpringUtils.getBean(OrderDetailService.class).saveBatch(orderDetails);
|
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<OrderDetail> orderDetails = orderDetailService.queryChain().where(ORDER_DETAIL.ORDER_ID.eq(order.getId())).list();
|
||||||
|
//获取涉及到的商品
|
||||||
|
ProductService productService = SpringUtils.getBean(ProductService.class);
|
||||||
|
List<Product> 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) {
|
if (bo.getPayType() == 0) {
|
||||||
//微信支付统一下单
|
//微信支付统一下单
|
||||||
@ -191,31 +260,37 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
|||||||
.setOpenid(loginUserInfo.getString("openId"))
|
.setOpenid(loginUserInfo.getString("openId"))
|
||||||
//商品描述
|
//商品描述
|
||||||
.setBody(productList.stream().map(Product::getDescription).collect(Collectors.joining(",")))
|
.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())
|
.setOutTradeNo(order.getId())
|
||||||
//元转分
|
//元转分
|
||||||
.setTotalFee(bo.getTotalAmount().scaleByPowerOfTen(2).intValue())
|
.setTotalFee(order.getTotalAmount().scaleByPowerOfTen(2).intValue())
|
||||||
.setTradeType("JSAPI");
|
.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 {
|
} else {
|
||||||
return pointPay(recordNumIsEnough, order.getId());
|
//统计支付商品情况
|
||||||
|
Map<String, Integer> 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) {
|
} catch (Exception e) {
|
||||||
//回滚库存
|
|
||||||
if (recordNumIsEnough != null){
|
|
||||||
recordNumIsEnough.forEach((key, value) -> {
|
|
||||||
redisService.longIncrement(MallRedisConstant.STOCK_RECORD_NUM + key, value.longValue());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
throw new ServiceException(e.getMessage());
|
throw new ServiceException(e.getMessage());
|
||||||
} finally {
|
} finally {
|
||||||
//释放锁
|
//释放锁
|
||||||
userIdLock.unlock();
|
userIdLock.unlock();
|
||||||
}
|
}
|
||||||
}else {
|
} else {
|
||||||
//获取锁失败,直接返回空
|
//获取锁失败,直接返回空
|
||||||
throw new ServiceException("请勿重复下单");
|
throw new ServiceException("请勿重复支付");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,7 +321,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
|||||||
* @param list 订单详情
|
* @param list 订单详情
|
||||||
* @return: Map<String, Integer> 预库存记录
|
* @return: Map<String, Integer> 预库存记录
|
||||||
*/
|
*/
|
||||||
private Map<String, Integer> recordNumIsEnough(List<PlaceOrderBo.PlaceOrderDetail> list) throws ServiceException {
|
private Map<String, Integer> recordNumIsEnough(List<OrderDetail> list) throws ServiceException {
|
||||||
RedisService redisService = SpringUtils.getBean(RedisService.class);
|
RedisService redisService = SpringUtils.getBean(RedisService.class);
|
||||||
Map<String, Integer> stockNumMap = new HashMap<>();
|
Map<String, Integer> stockNumMap = new HashMap<>();
|
||||||
//遍历库存
|
//遍历库存
|
||||||
@ -334,7 +409,7 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
|||||||
Brand brand = SpringUtils.getBean(BrandService.class).getById(order.getBrandId());
|
Brand brand = SpringUtils.getBean(BrandService.class).getById(order.getBrandId());
|
||||||
if (StringUtils.isBlank(brand.getWxAppId()) || !StringUtils.equals(brand.getWxAppId(), wxPayService.getConfig().getAppId())) {
|
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);
|
SpringUtils.getBean(ProductRecordSyncStockTask.class).asyncUpdateRecords(orderNumMap);
|
||||||
@ -344,48 +419,28 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @descriptions 微信支付分账
|
* @descriptions 分账结果通知
|
||||||
* @author DB
|
* @author DB
|
||||||
* @date 2023/11/02 15:26
|
* @date 2023/11/03 9:50
|
||||||
* @param orderId 订单id
|
* @param xmlData 加密数据
|
||||||
* @param notifyResult 微信支付结果
|
|
||||||
* @param wxPayService 微信支付
|
|
||||||
* @return: void
|
* @return: void
|
||||||
*/
|
*/
|
||||||
private void wxPayProfitSharing(String orderId, WxPayOrderNotifyResult notifyResult, WxPayService wxPayService) throws WxPayException {
|
@Override
|
||||||
ProfitSharing profitSharing = new ProfitSharing();
|
public void parseProfitSharingNotifyResult(String xmlData) {
|
||||||
profitSharing.setOrderId(orderId)
|
WxPayService wxPayService = wxPayHandler.getWxPayService();
|
||||||
.setProfitSharingStatus(0)
|
try {
|
||||||
.setOrderSource(OrderSource.MALL.toString());
|
WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
|
||||||
ProfitSharingService profitSharingService = SpringUtils.getBean(ProfitSharingService.class);
|
//更新分账订单
|
||||||
profitSharingService.save(profitSharing);
|
SpringUtils.getBean(ProfitSharingService.class).updateChain().set(PROFIT_SHARING.OUT_PROFIT_SHARING_ID, notifyResult.getTransactionId())
|
||||||
Double ceil = Math.ceil(notifyResult.getTotalFee() * OrderSource.MALL.getRate());
|
.set(PROFIT_SHARING.AMOUNT, notifyResult.getTotalFee())
|
||||||
//固定商户信息
|
.set(PROFIT_SHARING.PROFIT_SHARING_STATUS, 1)
|
||||||
Map<String, Object> mapReceiver = new HashMap<>(4);
|
//当前分账账户
|
||||||
mapReceiver.put("type", "MERCHANT_ID");
|
.set(PROFIT_SHARING.PAY_ACCOUNT, wxPayService.getConfig().getSubMchId())
|
||||||
mapReceiver.put("account", wxPayProperties.getSharingAccount());
|
.where(PROFIT_SHARING.ID.eq(notifyResult.getOutTradeNo()))
|
||||||
mapReceiver.put("relation_type", "SERVICE_PROVIDER");
|
.update();
|
||||||
mapReceiver.put("amount", ceil.longValue());
|
} catch (WxPayException e) {
|
||||||
mapReceiver.put("name","果酱盒子");
|
throw new ServiceException(e.getMessage());
|
||||||
mapReceiver.put("description", "分账到服务商");
|
}
|
||||||
/*
|
|
||||||
//添加分账接收方
|
|
||||||
ProfitSharingReceiverRequest profitSharingReceiver = new ProfitSharingReceiverRequest();
|
|
||||||
profitSharingReceiver.setReceiver(JSONObject.toJSONString(mapReceiver));
|
|
||||||
wxPayService.getProfitSharingService().addReceiver(profitSharingReceiver);*/
|
|
||||||
//分账
|
|
||||||
ProfitSharingRequest profitSharingRequest = new ProfitSharingRequest();
|
|
||||||
List<Map<String, Object>> 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -423,4 +478,77 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
|
|||||||
.set(ORDER.LOGISTICS_ORDER, bo.getLogisticsOrder())
|
.set(ORDER.LOGISTICS_ORDER, bo.getLogisticsOrder())
|
||||||
.where(ORDER.ID.eq(bo.getId())).update();
|
.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<OrderDetail> orderDetails = SpringUtils.getBean(OrderDetailService.class).queryChain().where(ORDER_DETAIL.ORDER_ID.eq(orderId)).list();
|
||||||
|
//获取当前下单用户信息
|
||||||
|
JSONObject loginUserInfo = SecurityUtils.getInstance().getLoginUserInfo();
|
||||||
|
List<Product> 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<String, Integer> 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("请勿重复下单");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,9 +12,7 @@ import org.springframework.stereotype.Component;
|
|||||||
import org.springframework.transaction.annotation.Isolation;
|
import org.springframework.transaction.annotation.Isolation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static com.cpop.mall.business.entity.table.ProductRecordTableDef.PRODUCT_RECORD;
|
import static com.cpop.mall.business.entity.table.ProductRecordTableDef.PRODUCT_RECORD;
|
||||||
|
|
||||||
@ -41,7 +39,7 @@ public class ProductRecordSyncStockTask {
|
|||||||
RedisService redisService = SpringUtils.getBean(RedisService.class);
|
RedisService redisService = SpringUtils.getBean(RedisService.class);
|
||||||
productRecords.forEach(item->{
|
productRecords.forEach(item->{
|
||||||
redisService.setCacheObject(MallRedisConstant.STOCK_RECORD_NUM + item.getId(), item.getRecordNum());
|
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("===============================结束<--库存信息结束-->结束===============================");
|
log.info("===============================结束<--库存信息结束-->结束===============================");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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<String, Object> 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<Map<String, Object>> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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<OrderDetailVo> detailList;
|
||||||
|
}
|
||||||
@ -65,4 +65,9 @@ public class WxPayProperties {
|
|||||||
* 分账账号
|
* 分账账号
|
||||||
*/
|
*/
|
||||||
private String sharingAccount;
|
private String sharingAccount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分账通知
|
||||||
|
*/
|
||||||
|
private String notifySharing;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,11 @@ public interface MallRedisConstant {
|
|||||||
*/
|
*/
|
||||||
String STOCK_RECORD_NUM = "mall:stock:recordNum:";
|
String STOCK_RECORD_NUM = "mall:stock:recordNum:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户创建预订单(用户id)
|
||||||
|
*/
|
||||||
|
String IDEMPOTENT_LOCK_CREATE_ADVANCE_ORDER = "mall:idempotentLock:createAdvanceOrder:";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户下单幂等锁(用户id)
|
* 用户下单幂等锁(用户id)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user