From 5932ee98f530f93c93c759b8947f95e366e32894 Mon Sep 17 00:00:00 2001 From: zhanglin8526 <852614290@qq.com> Date: 星期六, 05 八月 2023 18:15:42 +0800 Subject: [PATCH] 1、定时任务 商户进件状态查询 2、小程序下单统一支付提交 3、订单核销分账 4、订单退款 5、支付、退款回调 6、分账回调 --- ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/dict/IDict.java | 170 ++++++ ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/OrderPayment.java | 6 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/OrderPaymentService.java | 2 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/PaymentMessageService.java | 2 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/BackMessage.java | 8 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/OrderPaymentServiceImpl.java | 3 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/vo/ProfitSharingNotifyNewResult.java | 23 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/RefundStatusEnum.java | 19 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/ProfitSharingServiceImpl.java | 34 + ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/order/OrderService.java | 17 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/PaymentMessageServiceImpl.java | 2 ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/poji/shop/ShopProportionVo.java | 27 + ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/order/OrderServiceImpl.java | 822 ++++++++++++++++++++------------ ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/dict/DictBean.java | 15 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/WxPayNotifyEventTypeEnum.java | 22 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/miniapp/NotifyController.java | 219 +++++--- ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/OrderRefund.java | 16 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/PaymentMessage.java | 2 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/ProfitSharing.java | 12 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/ProfitSharingService.java | 11 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/BackMessageService.java | 6 ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/BackMessageServiceImpl.java | 11 22 files changed, 1,031 insertions(+), 418 deletions(-) diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/poji/shop/ShopProportionVo.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/poji/shop/ShopProportionVo.java index fc3d659..b8a42de 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/poji/shop/ShopProportionVo.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/poji/shop/ShopProportionVo.java @@ -1,4 +1,31 @@ package com.ruoyi.system.api.domain.poji.shop; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +@Data public class ShopProportionVo { + /** + * 分成id + */ + private Long proportionId; + + /** + * 商户id + */ + private Long shopId; + /** + * 商户类型 + */ + private Integer shopType; + /** + * 分成比例 + */ + private BigDecimal proportionPercent; + } diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/miniapp/NotifyController.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/miniapp/NotifyController.java index 5dc6de6..775d9da 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/miniapp/NotifyController.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/controller/miniapp/NotifyController.java @@ -1,38 +1,34 @@ package com.ruoyi.order.controller.miniapp; -import com.ruoyi.common.core.domain.R; +import com.github.binarywang.wxpay.bean.ecommerce.*; +import com.github.binarywang.wxpay.bean.notify.WxPayNotifyV3Response; +import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingNotifyData; +import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingNotifyResult; +import com.github.binarywang.wxpay.exception.WxPayException; +import com.github.binarywang.wxpay.service.ProfitSharingV3Service; +import com.github.binarywang.wxpay.service.WxPayService; +import com.github.binarywang.wxpay.v3.auth.Verifier; +import com.github.binarywang.wxpay.v3.util.AesUtils; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import com.ruoyi.common.core.web.controller.BaseController; -import com.ruoyi.order.domain.dto.AppSureOrderDto; -import com.ruoyi.order.domain.dto.WXPayNotifyDto; -import com.ruoyi.order.domain.vo.AppSureOrderVo; +import com.ruoyi.order.domain.vo.ProfitSharingNotifyNewResult; +import com.ruoyi.order.enums.WxPayNotifyEventTypeEnum; +import com.ruoyi.order.service.account.BackMessageService; import com.ruoyi.order.service.order.OrderService; -import com.wechat.pay.contrib.apache.httpclient.notification.Notification; -import com.wechat.pay.contrib.apache.httpclient.notification.NotificationHandler; -import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest; -import com.wechat.pay.java.core.Config; -import com.wechat.pay.java.core.RSAAutoCertificateConfig; -import com.wechat.pay.java.core.RSAConfig; -import com.wechat.pay.java.core.cipher.PrivacyEncryptor; -import com.wechat.pay.java.core.notification.NotificationConfig; -import com.wechat.pay.java.core.notification.NotificationParser; -import com.wechat.pay.java.core.notification.RequestParam; -import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; -import net.bytebuddy.asm.Advice; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import java.io.BufferedReader; import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.util.HashMap; +import java.security.GeneralSecurityException; import java.util.Map; +import java.util.Objects; /** * @program: ruoyi @@ -44,88 +40,82 @@ @RestController @RequestMapping("/app/notify") public class NotifyController extends BaseController { - /** 商户号 */ - public static String merchantId = ""; - /** 商户API私钥路径 */ - public static String privateKeyPath = ""; - /** 商户证书序列号 */ - public static String merchantSerialNumber = ""; - /** 微信支付平台证书路径 */ - public static String wechatPayCertificatePath = ""; - /** 商户APIV3密钥 */ - public static String apiV3key = "..."; + + public static final String WECHAT_PAY_SERIAL = "Wechatpay-Serial"; + public static final String WECHAT_PAY_SIGNATURE = "Wechatpay-Signature"; + public static final String WECHAT_PAY_TIMESTAMP = "Wechatpay-Timestamp"; + public static final String WECHAT_PAY_NONCE = "Wechatpay-Nonce"; + + private static final Gson GSON = new GsonBuilder().create(); @Resource private OrderService orderService; - @RequestMapping(value = "/payNotify", method = RequestMethod.POST) - @ApiOperation(value = "微信支付通知") - public Map payNotify(HttpServletRequest request, HttpServletResponse response) { - Config config = - new RSAConfig.Builder() - .merchantId(merchantId) - .privateKeyFromPath(privateKeyPath) - .merchantSerialNumber(merchantSerialNumber) - .wechatPayCertificatesFromPath(wechatPayCertificatePath) - .build(); + @Autowired + private WxPayService wxService; + @Resource + private BackMessageService backMessageService; - PrivacyEncryptor encryptor = config.createEncryptor(); - String wechatPayCertificateSerialNumber = encryptor.getWechatpaySerial(); + @PostMapping(value = "/payNotify") + @ApiOperation(value = "微信支付/退款通知") + public String payNotify(@RequestBody String notifyData, HttpServletRequest request, HttpServletResponse response) throws WxPayException { + // 获取请求头 + SignatureHeader signatureHeader = getSignatureHeader(response); - String nonoc=request.getHeader("Wechatpay-Nonce"); - String signature=request.getHeader("Wechatpay-Signature"); - String timestamp=request.getHeader("Wechatpay-Timestamp"); - String serial=request.getHeader("Wechatpay-Serial"); - String signatureType=request.getHeader("Wechatpay-Signature-Type"); + NotifyResponse responseData = GSON.fromJson(notifyData, NotifyResponse.class); + String eventType = responseData.getEventType(); - String requestBody=""; - - try { - BufferedReader reader = request.getReader(); - String line = ""; - StringBuffer inputString = new StringBuffer(); - while ( (line = reader.readLine()) != null ) { - inputString.append(line); + int resultType = 1; + String resultMessage = ""; + if(WxPayNotifyEventTypeEnum.TRANSACTION_SUCCESS.getCode().equals(eventType)){ + PartnerTransactionsNotifyResult notifyResult = wxService.getEcommerceService().parsePartnerNotifyResult(notifyData, signatureHeader); + PartnerTransactionsResult result = notifyResult.getResult(); + // 支付通知回调 + if("SUCCESS".equals(result.getTradeState())){ + orderService.payBack(result); } - if(inputString!=null && !"".equals(inputString)) { - requestBody = inputString.toString(); - } - reader.close(); - } catch (IOException e) { - e.printStackTrace(); + resultMessage = GSON.toJson(notifyResult); + } else if(WxPayNotifyEventTypeEnum.REFUND_SUCCESS.getCode().equals(eventType) + || WxPayNotifyEventTypeEnum.REFUND_ABNORMAL.getCode().equals(eventType) + || WxPayNotifyEventTypeEnum.REFUND_CLOSED.getCode().equals(eventType)){ + + RefundNotifyResult result = wxService.getEcommerceService().parseRefundNotifyResult(notifyData, signatureHeader); + orderService.orderRefundBack(result); + resultType = 2; + resultMessage = GSON.toJson(result); + } + // 保存支付/退款回调信息 + backMessageService.saveBackMessage(resultType, resultMessage); + + + return WxPayNotifyV3Response.success("成功"); + } + + @PostMapping(value = "/profitSharingNotify") + @ApiOperation(value = "微信分账通知") + public String profitSharingNotify(@RequestBody String notifyData, HttpServletRequest request, HttpServletResponse response) throws WxPayException { + ProfitSharingV3Service sharingV3Service = wxService.getProfitSharingV3Service(); + // ProfitSharingNotifyResult + + // 获取请求头 + SignatureHeader signatureHeader = getSignatureHeader(response); + + + ProfitSharingNotifyNewResult notifyResult = getProfitSharingNotifyData(notifyData, signatureHeader); + ProfitSharingNotifyResult result = notifyResult.getResult(); + + String eventType = notifyResult.getRawData().getEventType(); + if(WxPayNotifyEventTypeEnum.PROFIT_SHARING_SUCCESS.getCode().equals(eventType)){ + // 分账通知回调 + orderService.profitSharingBack(result); } - RequestParam requestParam = new RequestParam.Builder() - .serialNumber(wechatPayCertificateSerialNumber) - .nonce(nonoc) - .signature(signature) - .timestamp(timestamp) - .body(requestBody) - .build(); + String resultMessage = GSON.toJson(notifyResult); + // 保存记录分账回调信息 + backMessageService.saveBackMessage(3, resultMessage); - NotificationConfig notifiConfig = new RSAAutoCertificateConfig.Builder() - .merchantId(merchantId) - .privateKeyFromPath(privateKeyPath) - .merchantSerialNumber(merchantSerialNumber) - .apiV3Key(apiV3key) - .build(); - - NotificationParser parser = new NotificationParser(notifiConfig); - - Transaction transaction = parser.parse(requestParam, Transaction.class); - - - String tradeStateEnum=transaction.getTradeState().toString(); - if(tradeStateEnum.equals("success")){ - orderService.payBack(transaction); - } - - Map map=new HashMap(); - map.put("code","SUCCESS"); - map.put("message","成功"); - - return map; + return WxPayNotifyV3Response.success("成功"); } @RequestMapping(value = "/shareNotify", method = RequestMethod.POST) @@ -135,4 +125,49 @@ return null; } + public ProfitSharingNotifyNewResult getProfitSharingNotifyData(String notifyData, SignatureHeader header) throws WxPayException { + if (Objects.nonNull(header) && !this.verifyNotifySign(header, notifyData)) { + throw new WxPayException("非法请求,头部信息验证失败"); + } + ProfitSharingNotifyData response = GSON.fromJson(notifyData, ProfitSharingNotifyData.class); + + ProfitSharingNotifyData.Resource resource = response.getResource(); + String cipherText = resource.getCipherText(); + String associatedData = resource.getAssociatedData(); + String nonce = resource.getNonce(); + String apiV3Key = this.wxService.getConfig().getApiV3Key(); + try { + String result = AesUtils.decryptToString(associatedData, nonce, cipherText, apiV3Key); + ProfitSharingNotifyResult profitSharingResult = GSON.fromJson(result, ProfitSharingNotifyResult.class); + + ProfitSharingNotifyNewResult notifyResult = new ProfitSharingNotifyNewResult(); + notifyResult.setRawData(response); + notifyResult.setResult(profitSharingResult); + return notifyResult; + } catch (GeneralSecurityException | IOException e) { + throw new WxPayException("解析报文异常!", e); + } + } + + private boolean verifyNotifySign(SignatureHeader header, String data) throws WxPayException { + String beforeSign = String.format("%s\n%s\n%s\n", + header.getTimeStamp(), + header.getNonce(), + data); + Verifier verifier = this.wxService.getConfig().getVerifier(); + if (verifier == null) { + throw new WxPayException("证书检验对象为空"); + } + return verifier.verify(header.getSerialNo(), + beforeSign.getBytes(StandardCharsets.UTF_8), header.getSigned()); + } + + private SignatureHeader getSignatureHeader(HttpServletResponse response){ + SignatureHeader signatureHeader = new SignatureHeader(); + signatureHeader.setSerialNo(response.getHeader(WECHAT_PAY_SERIAL)); + signatureHeader.setSigned(response.getHeader(WECHAT_PAY_SIGNATURE)); + signatureHeader.setNonce(response.getHeader(WECHAT_PAY_NONCE)); + signatureHeader.setTimeStamp(response.getHeader(WECHAT_PAY_TIMESTAMP)); + return signatureHeader; + } } diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/BackMessage.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/BackMessage.java index 9094dc2..26c7e38 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/BackMessage.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/BackMessage.java @@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.activerecord.Model; import com.baomidou.mybatisplus.annotation.TableName; import java.io.Serializable; +import java.util.Date; import lombok.Data; import lombok.EqualsAndHashCode; @@ -38,7 +39,7 @@ @TableField("del_flag") private String delFlag; /** - * 回调类型1支付回调2退款回调 + * 回调类型 1支付回调 2退款回调 3、分账 */ @TableField("result_type") private Integer resultType; @@ -47,6 +48,11 @@ */ @TableField("result_message") private String resultMessage; + /** + * 回调时间 + */ + @TableField("create_time") + private Date createTime; @Override diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/OrderPayment.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/OrderPayment.java index bfc24aa..93d22e0 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/OrderPayment.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/OrderPayment.java @@ -49,6 +49,12 @@ @TableField("shop_id") private Long shopId; /** + * 订单二级商户号 + */ + @TableField("sub_mch_id") + private String subMchId; + + /** * 订单id */ @TableField("order_id") diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/OrderRefund.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/OrderRefund.java index 4cfa669..906c44a 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/OrderRefund.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/OrderRefund.java @@ -99,7 +99,21 @@ * 回调时间 */ @TableField("back_time") - private Date backTime; + private String backTime; + + /** + * 微信退款订单id + */ + @TableField("wx_refund_id") + private String wxRefundId; + + /** + * 1、发起退款 2、已退款 + */ + @TableField("refund_status") + private Integer refundStatus; + + @Override diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/PaymentMessage.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/PaymentMessage.java index 179d46e..ee2d709 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/PaymentMessage.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/PaymentMessage.java @@ -47,7 +47,7 @@ * 发起关联id */ @TableField("send_id") - private Long sendId; + private String sendId; /** * 发送报文 */ diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/ProfitSharing.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/ProfitSharing.java index ad038c8..f45be82 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/ProfitSharing.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/pojo/account/ProfitSharing.java @@ -40,7 +40,7 @@ private Integer delFlag; /** * 1:PROCESSING:处理中 -2:FINISHED:分账完成 + 2:FINISHED:分账完成 */ @TableField("share_status") private Integer shareStatus; @@ -93,7 +93,15 @@ * 完成时间 */ @TableField("finish_time") - private Date finishTime; + private String finishTime; + + /** + * 微信分账/回退单号 + */ + @TableField("wx_order_id") + private String wxOrderId; + + /** * 分账失败原因 1、ACCOUNT_ABNORMAL : 分账接收账户异常 diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/vo/ProfitSharingNotifyNewResult.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/vo/ProfitSharingNotifyNewResult.java new file mode 100644 index 0000000..2ee8dc4 --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/domain/vo/ProfitSharingNotifyNewResult.java @@ -0,0 +1,23 @@ +package com.ruoyi.order.domain.vo; + +import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingNotifyData; +import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingNotifyResult; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@NoArgsConstructor +public class ProfitSharingNotifyNewResult implements Serializable { + private static final long serialVersionUID = -6602962275015706689L; + /** + * 源数据 + */ + private ProfitSharingNotifyData rawData; + + /** + * 解密后的数据 + */ + private ProfitSharingNotifyResult result; +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/RefundStatusEnum.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/RefundStatusEnum.java new file mode 100644 index 0000000..9f04cf3 --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/RefundStatusEnum.java @@ -0,0 +1,19 @@ +package com.ruoyi.order.enums; + +import com.ruoyi.order.enums.dict.IDict; + +public enum RefundStatusEnum implements IDict<Integer> { + /** + * 退款状态,枚举值: + * SUCCESS:退款成功 + * CLOSE:退款关闭 + * ABNORMAL:退款异常 + */ + SUCCESS(2, "SUCCESS"), + CLOSE(3, "CLOSE"), + ABNORMAL(4, "ABNORMAL"); + + RefundStatusEnum(Integer code, String text){ + init(code, text); + } +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/WxPayNotifyEventTypeEnum.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/WxPayNotifyEventTypeEnum.java new file mode 100644 index 0000000..31f456e --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/WxPayNotifyEventTypeEnum.java @@ -0,0 +1,22 @@ +package com.ruoyi.order.enums; + + +import com.ruoyi.order.enums.dict.IDict; + +public enum WxPayNotifyEventTypeEnum implements IDict<String> { + /** + * 微信回调通知 + 支付成功通知的类型为 TRANSACTION.SUCCESS + 分账 PROFITSHARING.SUCCESS + */ + TRANSACTION_SUCCESS("TRANSACTION.SUCCESS", "TRANSACTION.SUCCESS"), + PROFIT_SHARING_SUCCESS("PROFITSHARING.SUCCESS", "PROFITSHARING.SUCCESS"), + REFUND_SUCCESS("REFUND.SUCCESS", "REFUND.SUCCESS"), + REFUND_ABNORMAL("REFUND.ABNORMAL", "REFUND.ABNORMAL"), + REFUND_CLOSED("REFUND.CLOSED", "REFUND.CLOSED"); + + WxPayNotifyEventTypeEnum(String code, String text){ + init(code, text); + } + +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/dict/DictBean.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/dict/DictBean.java new file mode 100644 index 0000000..235c8f8 --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/dict/DictBean.java @@ -0,0 +1,15 @@ +package com.ruoyi.order.enums.dict; + +import lombok.Data; + +/** + * 字典bean + * 只有code和text,可用于展示下拉框 + * + * @author luozhan + */ +@Data +public class DictBean<T> implements IDict<T> { + private final T code; + private final String text; +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/dict/IDict.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/dict/IDict.java new file mode 100644 index 0000000..fd87547 --- /dev/null +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/enums/dict/IDict.java @@ -0,0 +1,170 @@ +package com.ruoyi.order.enums.dict; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + + +/** + * 字典接口 + * <p> + * 自定义的字典枚举类实现本接口后可省略属性code和text,以及对应的get方法 + * 在构造方法中只需调用init方法即可初始化 + * + * @author luozhan + * @date 2021-12 + */ +public interface IDict<T> { + /** + * 通过code获取value + * + * @param clazz 枚举class + * @param code code + * @return text + */ + static <T> String getTextByCode(Class<? extends IDict<T>> clazz, T code) { + return Stream.of(clazz.getEnumConstants()) + .filter((IDict<T> e) -> e.getCode().equals(code)) + .map(IDict::getText) + .findAny().orElse(""); + } + + /** + * 通过text获取code + * + * @param clazz 枚举class + * @param text text + * @return code + */ + static <T> T getCodeByText(Class<? extends IDict<T>> clazz, String text) { + return Stream.of(clazz.getEnumConstants()) + .filter((IDict<T> e) -> e.getText().equals(text)) + .map(IDict::getCode) + .findAny().orElse(null); + } + + /** + * 通过code获取字典枚举实例 + * + * @param clazz 枚举class + * @param code code + * @param <T> 字典code类型 + * @param <R> 枚举类型 + * @return 字典枚举实例 + */ + @SuppressWarnings("unchecked") + static <T, R extends IDict<T>> R getByCode(Class<? extends IDict<T>> clazz, T code) { + return Stream.of(clazz.getEnumConstants()) + .filter((IDict<T> e) -> (e.getCode().equals(code))) + .map(v -> (R) v) + .findAny() + .orElse(null); + } + + /** + * 获取给定的字典枚举项(常用下拉框数据请求) + * + * @param enums 可指定需要哪些项 + * @return List + */ + @SafeVarargs + static <T, E extends IDict<T>> List<IDict<T>> getItems(E... enums) { + return Stream.of(enums) + .map(DictPool::getDict) + .collect(Collectors.toList()); + } + + /** + * 获取所有字典枚举项,除开指定的枚举 + * + * @param exclude 指定排除的枚举 + * @return List + */ + @SafeVarargs + @SuppressWarnings("unchecked") + static <T, E extends IDict<T>> List<IDict<T>> getItemsExclude(E... exclude) { + Class<IDict<T>> clazz = (Class<IDict<T>>) exclude.getClass().getComponentType(); + IDict<T>[] allEnum = clazz.getEnumConstants(); + List<IDict<T>> excludeList = Arrays.asList(exclude); + return Stream.of(allEnum) + .filter(e -> !excludeList.contains(e)) + .map(DictPool::getDict) + .collect(Collectors.toList()); + } + + /** + * 获取所有字典枚举项(常用下拉框数据请求) + * 枚举值上标记@Deprecated的不会返回 + * + * @param clazz 字典枚举类 + * @return List + */ + static <T> List<IDict<T>> getAll(Class<? extends IDict<T>> clazz) { + Map<String, Field> fieldCache = Arrays.stream(clazz.getDeclaredFields()). + filter(Field::isEnumConstant). + collect(Collectors.toMap(Field::getName, Function.identity())); + IDict<T>[] allEnum = clazz.getEnumConstants(); + return Stream.of(allEnum) + .filter(e -> !fieldCache.get(((Enum<?>) e).name()).isAnnotationPresent(Deprecated.class)) + .map(DictPool::getDict) + .collect(Collectors.toList()); + } + + /** + * 初始化 + * + * @param code 字典编码 + * @param text 字典文本 + */ + default void init(T code, String text) { + DictPool.putDict(this, code, text); + } + + /** + * 获取编码 + * + * @return 编码 + */ + default T getCode() { + return DictPool.getDict(this).getCode(); + } + + /** + * 获取文本 + * + * @return 文本 + */ + default String getText() { + return DictPool.getDict(this).getText(); + } + + + @SuppressWarnings("all") + class DictPool { + private static final Map<IDict, DictBean> DICT_MAP = new ConcurrentHashMap<>(); + + private static final Map<String, Class<? extends IDict>> DICT_NAME_CLASS_MAP = new ConcurrentHashMap<>(); + + static <T> void putDict(IDict<T> dict, T code, String text) { + DICT_NAME_CLASS_MAP.put(dict.getClass().getName(), dict.getClass()); + DICT_MAP.put(dict, new DictBean<>(code, text)); + } + + public static List<IDict<Object>> getDict(String dictName) { + Class<? extends IDict> aClass = DICT_NAME_CLASS_MAP.get(dictName); + return IDict.getAll((Class<? extends IDict<Object>>) aClass); + } + + static <K extends IDict<T>, T> DictBean<T> getDict(K dict) { + return DICT_MAP.get(dict); + } + + + } + +} diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/BackMessageService.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/BackMessageService.java index 182e5bb..dd7ce33 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/BackMessageService.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/BackMessageService.java @@ -13,4 +13,10 @@ */ public interface BackMessageService extends IService<BackMessage> { + /** + * 保存回调记录 + * @param resultType + * @param resultMessage + */ + void saveBackMessage(int resultType, String resultMessage); } diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/OrderPaymentService.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/OrderPaymentService.java index 7a74366..fbd9709 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/OrderPaymentService.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/OrderPaymentService.java @@ -28,7 +28,7 @@ * @param goodsNames * @param prepayId */ - void saveOrderPayment(Long userId, Long shopId, String orderId, BigDecimal payMoney, Date endTime, String profitSharing, String openid, String goodsNames, String prepayId); + void saveOrderPayment(Long userId, Long shopId, String subMchId, String orderId, BigDecimal payMoney, Date endTime, String profitSharing, String openid, String goodsNames, String prepayId); /** * diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/PaymentMessageService.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/PaymentMessageService.java index 41a7898..f000a53 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/PaymentMessageService.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/PaymentMessageService.java @@ -20,5 +20,5 @@ * @param sendMessage * @param resultMessage */ - void savePaymentMessage(String sendType, Long sendId, String sendMessage, String resultMessage); + void savePaymentMessage(String sendType, String sendId, String sendMessage, String resultMessage); } diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/ProfitSharingService.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/ProfitSharingService.java index f58ec5e..bc97e93 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/ProfitSharingService.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/account/ProfitSharingService.java @@ -1,7 +1,10 @@ package com.ruoyi.order.service.account; +import com.github.binarywang.wxpay.bean.ecommerce.ProfitSharingResult; import com.ruoyi.order.domain.pojo.account.ProfitSharing; import com.baomidou.mybatisplus.extension.service.IService; + +import java.math.BigDecimal; /** * <p> @@ -13,4 +16,12 @@ */ public interface ProfitSharingService extends IService<ProfitSharing> { + /** + * 创建按分账记录 + * @param shopId + * @param orderId + * @param orderMoney + * @param result + */ + void saveProfitSharing(Long shopId, String orderId, BigDecimal orderMoney, ProfitSharingResult result); } diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/BackMessageServiceImpl.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/BackMessageServiceImpl.java index ca18dad..5b8dd8d 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/BackMessageServiceImpl.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/BackMessageServiceImpl.java @@ -6,6 +6,8 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; +import java.util.Date; + /** * <p> * 回调报文 服务实现类 @@ -17,4 +19,13 @@ @Service public class BackMessageServiceImpl extends ServiceImpl<BackMessageMapper, BackMessage> implements BackMessageService { + @Override + public void saveBackMessage(int resultType, String resultMessage) { + BackMessage backMessage = new BackMessage(); + backMessage.setDelFlag("0"); + backMessage.setResultType(resultType); + backMessage.setResultMessage(resultMessage); + backMessage.setCreateTime(new Date()); + this.saveOrUpdate(backMessage); + } } diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/OrderPaymentServiceImpl.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/OrderPaymentServiceImpl.java index 66b6acd..dcc4174 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/OrderPaymentServiceImpl.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/OrderPaymentServiceImpl.java @@ -24,7 +24,7 @@ public class OrderPaymentServiceImpl extends ServiceImpl<OrderPaymentMapper, OrderPayment> implements OrderPaymentService { @Override - public void saveOrderPayment(Long userId, Long shopId, String orderId, BigDecimal payMoney, Date endTime, + public void saveOrderPayment(Long userId, Long shopId, String subMchId, String orderId, BigDecimal payMoney, Date endTime, String profitSharing, String openid, String goodsNames, String prepayId) { OrderPayment payment = new OrderPayment(); payment.setPaymentId(IdUtils.simpleUUID()); @@ -33,6 +33,7 @@ payment.setOrderId(orderId); payment.setPayMoney(payMoney); payment.setTimeExpire(endTime); + payment.setSubMchId(subMchId); // 0 否 1、是 payment.setProfitSharing("Y".equals(profitSharing) ? 1 : 0); payment.setUserOpenId(openid); diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/PaymentMessageServiceImpl.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/PaymentMessageServiceImpl.java index 93b5287..2866872 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/PaymentMessageServiceImpl.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/PaymentMessageServiceImpl.java @@ -20,7 +20,7 @@ public class PaymentMessageServiceImpl extends ServiceImpl<PaymentMessageMapper, PaymentMessage> implements PaymentMessageService { @Override - public void savePaymentMessage(String sendType, Long sendId, String sendMessage, String resultMessage) { + public void savePaymentMessage(String sendType, String sendId, String sendMessage, String resultMessage) { PaymentMessage paymentMessage = new PaymentMessage(); paymentMessage.setDelFlag("0"); paymentMessage.setSendType(sendType); diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/ProfitSharingServiceImpl.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/ProfitSharingServiceImpl.java index bd2bd4a..799915d 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/ProfitSharingServiceImpl.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/account/ProfitSharingServiceImpl.java @@ -1,10 +1,17 @@ package com.ruoyi.order.service.impl.account; +import com.github.binarywang.wxpay.bean.ecommerce.ProfitSharingResult; +import com.ruoyi.common.core.utils.uuid.IdUtils; import com.ruoyi.order.domain.pojo.account.ProfitSharing; import com.ruoyi.order.mapper.account.ProfitSharingMapper; import com.ruoyi.order.service.account.ProfitSharingService; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Date; +import java.util.List; /** * <p> @@ -17,4 +24,31 @@ @Service public class ProfitSharingServiceImpl extends ServiceImpl<ProfitSharingMapper, ProfitSharing> implements ProfitSharingService { + @Override + public void saveProfitSharing(Long shopId, String orderId, BigDecimal orderMoney, ProfitSharingResult result) { + ProfitSharing profitSharing = new ProfitSharing(); + profitSharing.setShareId(result.getOutOrderNo()); + profitSharing.setDelFlag(0); + profitSharing.setShareStatus("FINISHED".equals(result.getStatus()) ? 2 : 1); + profitSharing.setShopId(shopId); + profitSharing.setOrderId(orderId); + profitSharing.setOrderMoney(orderMoney); + + List<ProfitSharingResult.Receiver> receivers = result.getReceivers(); + if(null != receivers && !receivers.isEmpty()){ + ProfitSharingResult.Receiver receiver = receivers.get(0); + profitSharing.setReceiverAccount(receiver.getReceiverMchid()); + BigDecimal receiverAmount = new BigDecimal(receiver.getAmount()); + receiverAmount = receiverAmount.divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP); + profitSharing.setReceiverAmount(receiverAmount); + profitSharing.setSurpMoney(orderMoney.subtract(receiverAmount)); + profitSharing.setReceiverDescription(receiver.getDescription()); + profitSharing.setFinishFlag(0); + profitSharing.setFailReason(receiver.getFailReason()); + profitSharing.setDetailId(receiver.getDetailId()); + } + profitSharing.setCreateTime(new Date()); + + this.saveOrUpdate(profitSharing); + } } diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/order/OrderServiceImpl.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/order/OrderServiceImpl.java index 6303951..9d12bd4 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/order/OrderServiceImpl.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/order/OrderServiceImpl.java @@ -1,16 +1,16 @@ package com.ruoyi.order.service.impl.order; +import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult; -import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingReceiver; -import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingRequest; -import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; +import com.github.binarywang.wxpay.bean.ecommerce.*; +import com.github.binarywang.wxpay.bean.ecommerce.ProfitSharingRequest.Receiver; +import com.github.binarywang.wxpay.bean.ecommerce.enums.TradeTypeEnum; +import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingNotifyResult; import com.github.binarywang.wxpay.config.WxPayConfig; -import com.github.binarywang.wxpay.constant.WxPayConstants; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.service.WxPayService; import com.google.common.base.Joiner; @@ -27,14 +27,19 @@ import com.ruoyi.order.domain.dto.*; import com.ruoyi.order.domain.pojo.account.OrderPayment; import com.ruoyi.order.domain.pojo.account.OrderRefund; +import com.ruoyi.order.domain.pojo.account.ProfitSharing; import com.ruoyi.order.domain.pojo.order.ConsumerGoods; import com.ruoyi.order.domain.pojo.order.Order; import com.ruoyi.order.domain.pojo.order.OrderGoods; import com.ruoyi.order.domain.pojo.order.PayRecord; import com.ruoyi.order.domain.vo.*; +import com.ruoyi.order.enums.RefundStatusEnum; +import com.ruoyi.order.enums.dict.IDict; import com.ruoyi.order.mapper.order.OrderMapper; import com.ruoyi.order.service.account.OrderPaymentService; +import com.ruoyi.order.service.account.OrderRefundService; import com.ruoyi.order.service.account.PaymentMessageService; +import com.ruoyi.order.service.account.ProfitSharingService; import com.ruoyi.order.service.order.*; import com.ruoyi.system.api.constant.AppErrorConstant; import com.ruoyi.system.api.constant.DelayTaskEnum; @@ -53,7 +58,7 @@ import com.ruoyi.system.api.domain.poji.sys.SysUser; import com.ruoyi.system.api.domain.vo.*; import com.ruoyi.system.api.service.*; -import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction; +import lombok.extern.slf4j.Slf4j; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; @@ -62,6 +67,7 @@ import javax.annotation.Resource; import java.math.BigDecimal; +import java.math.RoundingMode; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.*; @@ -78,6 +84,7 @@ * @since 2023-04-25 */ @Service +@Slf4j public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService { @Resource @@ -134,7 +141,13 @@ @Resource private OrderPaymentService orderPaymentService; - /** + @Resource + private ProfitSharingService profitSharingService; + + @Resource + private OrderRefundService orderRefundService; + + /** * @description: buyGoods * @param: appSureOrderDto * @return: AppSureOrderVo @@ -160,8 +173,8 @@ Map<String, Goods> goodsMap = goodsList.stream() .collect(Collectors.toMap(Goods::getGoodsId, Function.identity())); Boolean haveDeposit = false; - for(Goods goods : goodsList){ - if(goods.getSubscription()!=null&&goods.getSubscription().compareTo(BigDecimal.ZERO)>0){ + for (Goods goods : goodsList) { + if (goods.getSubscription() != null && goods.getSubscription().compareTo(BigDecimal.ZERO) > 0) { haveDeposit = true; } } @@ -181,7 +194,7 @@ // 将优惠券列表转换为Map,以优惠券ID为键 Map<String, AppMemberCouponVo> appMemberCouponVoMap = new HashMap<>(); - if(appMemberCouponVoList!=null&&!appMemberCouponVoList.isEmpty()){ + if (appMemberCouponVoList != null && !appMemberCouponVoList.isEmpty()) { appMemberCouponVoMap = appMemberCouponVoList.stream().collect(Collectors.toMap(AppMemberCouponVo::getMemberCouponId, Function.identity())); } AppMemberCouponVo appMemberCouponVo; @@ -208,7 +221,7 @@ memberCouponId = appBuyGoodsDto.getMemberCouponId(); // 获取商品信息 goods = goodsMap.get(goodsId); - if(goods.getGoodsStatus()!=1){ + if (goods.getGoodsStatus() != 1) { throw new ServiceException(AppErrorConstant.GOODS_DOWN); } // 设置订单商品信息 @@ -241,7 +254,7 @@ if (couponType == 1 && appMemberCouponVo.getMoneyThreshold() != null && appMemberCouponVo.getDiscountMoney() != null) { moneyThreshold = appMemberCouponVo.getMoneyThreshold(); discountMoney = appMemberCouponVo.getDiscountMoney(); - if (goodsTotalPrice.compareTo(moneyThreshold) >= 0 && goodsTotalPrice.compareTo(discountMoney)>0) { + if (goodsTotalPrice.compareTo(moneyThreshold) >= 0 && goodsTotalPrice.compareTo(discountMoney) > 0) { goodsRealPrice = goodsTotalPrice.subtract(discountMoney); useCoupon = 1; userCouponIdSet.add(memberCouponId); @@ -249,16 +262,16 @@ } } else if (couponType == 2 && appMemberCouponVo.getDiscountPercent() != null) { discountPercent = appMemberCouponVo.getDiscountPercent(); - goodsRealPrice = goodsTotalPrice.multiply(discountPercent).divide(BigDecimal.TEN,2,BigDecimal.ROUND_HALF_UP); + goodsRealPrice = goodsTotalPrice.multiply(discountPercent).divide(BigDecimal.TEN, 2, BigDecimal.ROUND_HALF_UP); discountMoney = goodsTotalPrice.subtract(goodsRealPrice); useCoupon = 1; userCouponIdSet.add(memberCouponId); appSureOrderGoodsVo.setMemberCouponId(memberCouponId); } else if (couponType == 3 && appMemberCouponVo.getDiscountMoney() != null) { discountMoney = appMemberCouponVo.getDiscountMoney(); - if(goodsTotalPrice.compareTo(discountMoney)>0){ + if (goodsTotalPrice.compareTo(discountMoney) > 0) { goodsRealPrice = goodsTotalPrice.subtract(discountMoney); - if(goodsRealPrice.compareTo(BigDecimal.ZERO)<0){ + if (goodsRealPrice.compareTo(BigDecimal.ZERO) < 0) { goodsRealPrice = BigDecimal.ZERO; } useCoupon = 1; @@ -274,12 +287,12 @@ appSureOrderGoodsVo.setGoodsRealPrice(goodsRealPrice); // 获取商品押金 goodsDeposit = goods.getSubscription(); - if (goodsDeposit != null && goodsDeposit.compareTo(BigDecimal.ZERO)>0) { + if (goodsDeposit != null && goodsDeposit.compareTo(BigDecimal.ZERO) > 0) { goodsDeposit = goodsDeposit.multiply(buyNumBig); - }else{ - if(haveDeposit){ + } else { + if (haveDeposit) { goodsDeposit = goodsRealPrice; - }else{ + } else { goodsDeposit = new BigDecimal("0.00"); } } @@ -294,9 +307,9 @@ //处理优惠券列表 if (appMemberCouponVoList != null && !appMemberCouponVoList.isEmpty()) { for (AppMemberCouponVo entity : appMemberCouponVoList) { - if(userCouponIdSet!=null&&userCouponIdSet.contains(entity.getMemberCouponId())){ + if (userCouponIdSet != null && userCouponIdSet.contains(entity.getMemberCouponId())) { entity.setUseFlag(1); - }else{ + } else { entity.setUseFlag(0); } @@ -304,18 +317,18 @@ } // 过滤商品优惠券列表 List<AppMemberCouponVo> appGoodsMemberCouponVoList; - for(AppSureOrderGoodsVo sureOrderGoodsVo : appSureOrderGoodsVoList) { + for (AppSureOrderGoodsVo sureOrderGoodsVo : appSureOrderGoodsVoList) { appGoodsMemberCouponVoList = new ArrayList<>(); - for(AppMemberCouponVo entity : appMemberCouponVoList){ - if(StringUtils.isBlank(entity.getRelGoodsIds())||entity.getRelGoodsIds().contains(sureOrderGoodsVo.getGoodsId())){ - if(entity.getCouponType()==1){ - if(entity.getMoneyThreshold().compareTo(sureOrderGoodsVo.getGoodsTotalPrice())<0&&entity.getDiscountMoney().compareTo(sureOrderGoodsVo.getGoodsTotalPrice())<0){ + for (AppMemberCouponVo entity : appMemberCouponVoList) { + if (StringUtils.isBlank(entity.getRelGoodsIds()) || entity.getRelGoodsIds().contains(sureOrderGoodsVo.getGoodsId())) { + if (entity.getCouponType() == 1) { + if (entity.getMoneyThreshold().compareTo(sureOrderGoodsVo.getGoodsTotalPrice()) < 0 && entity.getDiscountMoney().compareTo(sureOrderGoodsVo.getGoodsTotalPrice()) < 0) { appGoodsMemberCouponVoList.add(entity); } - }else if(entity.getCouponType()==2){ + } else if (entity.getCouponType() == 2) { appGoodsMemberCouponVoList.add(entity); - }else if(entity.getCouponType()==3){ - if(entity.getDiscountMoney().compareTo(sureOrderGoodsVo.getGoodsTotalPrice())<0){ + } else if (entity.getCouponType() == 3) { + if (entity.getDiscountMoney().compareTo(sureOrderGoodsVo.getGoodsTotalPrice()) < 0) { appGoodsMemberCouponVoList.add(entity); } } @@ -422,8 +435,8 @@ if (activityGoodsGetVo.getActivityStatus() == 2) { throw new ServiceException(AppErrorConstant.ACTIVITY_END); } - Integer surpNum = redisService.getCacheObject(SecurityConstant.ACTIVITY_GOODS+"-"+activityId+"-"+goodsId); - if(surpNum==null||surpNum<1){ + Integer surpNum = redisService.getCacheObject(SecurityConstant.ACTIVITY_GOODS + "-" + activityId + "-" + goodsId); + if (surpNum == null || surpNum < 1) { throw new ServiceException(AppErrorConstant.ACTIVITY_GOODS_NULL); } if (activityGoodsGetVo.getAvailableBuyNum() < 1) { @@ -433,7 +446,7 @@ throw new ServiceException(AppErrorConstant.ACTIVITY_GOODS_BEYOND); } Goods goods = remoteGoodsService.getGoods(goodsId).getData(); - if(goods.getGoodsStatus()!=1){ + if (goods.getGoodsStatus() != 1) { throw new ServiceException(AppErrorConstant.GOODS_DOWN); } appPanicBuyVo.setActivityId(activityId); @@ -463,9 +476,9 @@ appPanicBuyVo.setGoodsTotalPrice(goodsTotalPrice); appPanicBuyVo.setGoodsRealPrice(goodsRealPrice); goodsDeposit = activityGoodsGetVo.getActivitySubscription(); - if (goodsDeposit == null || goodsDeposit.compareTo(BigDecimal.ZERO)==0) { + if (goodsDeposit == null || goodsDeposit.compareTo(BigDecimal.ZERO) == 0) { goodsDeposit = new BigDecimal("0.00"); - }else{ + } else { goodsDeposit = goodsDeposit.multiply(buyNumBig); } appPanicBuyVo.setGoodsDeposit(goodsDeposit); @@ -505,8 +518,8 @@ Map<String, Goods> goodsMap = goodsList.stream() .collect(Collectors.toMap(Goods::getGoodsId, Function.identity())); Boolean haveDeposit = false; - for(Goods goods : goodsList){ - if(goods.getSubscription()!=null&&goods.getSubscription().compareTo(BigDecimal.ZERO)>0){ + for (Goods goods : goodsList) { + if (goods.getSubscription() != null && goods.getSubscription().compareTo(BigDecimal.ZERO) > 0) { haveDeposit = true; } } @@ -605,7 +618,7 @@ } } else if (couponType == 2 && appMemberCouponVo.getDiscountPercent() != null) { discountPercent = appMemberCouponVo.getDiscountPercent(); - goodsRealPrice = goodsTotalPrice.multiply(discountPercent).divide(BigDecimal.TEN,2, BigDecimal.ROUND_HALF_UP); + goodsRealPrice = goodsTotalPrice.multiply(discountPercent).divide(BigDecimal.TEN, 2, BigDecimal.ROUND_HALF_UP); discountMoney = goodsTotalPrice.subtract(goodsRealPrice); useCoupon = 1; } else if (couponType == 3 && appMemberCouponVo.getDiscountMoney() != null) { @@ -622,12 +635,12 @@ appSureOrderGoodsVo.setGoodsRealPrice(goodsRealPrice); // 获取商品押金 goodsDeposit = goods.getSubscription(); - if (goodsDeposit != null && goodsDeposit.compareTo(BigDecimal.ZERO)>0) { + if (goodsDeposit != null && goodsDeposit.compareTo(BigDecimal.ZERO) > 0) { goodsDeposit = goodsDeposit.multiply(buyNumBig); - }else{ - if(haveDeposit){ + } else { + if (haveDeposit) { goodsDeposit = goodsRealPrice; - }else{ + } else { goodsDeposit = new BigDecimal("0.00"); } } @@ -723,47 +736,105 @@ appPlaceOrderVo.setOrderId(orderId); appPlaceOrderVo.setOrderNo(orderNo); + String goodsName = ""; + if (null != goods) { + goodsName = goods.getGoodsName(); + } + + // 小程序微信下单支付 + createWxPayInfo(appPlaceOrderVo, userId, order.getShopId(), goodsName, orderNo, + orderId, order.getPayMoney(), appPlaceOrderDto.getOpenid(), + appPlaceOrderDto.getSpbillCreateIp(), goodsNameList); + + + //减去优惠券 + if (StringUtils.isNotBlank(memberCouponSJ.toString())) { + remoteCouponService.useMemberCoupon(memberCouponSJ.toString()); + } + //生成自动取消订单延时任务 + Integer delayTime = 30; + if (redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)) { + delayTime = redisService.getCacheObject(SecurityConstant.AUTO_CANCEL_ORDER_TIME); + } + redisService.setCacheObject(DelayTaskEnum.ORDER_AUTOMATIC_CANCEL.getCode() + "-" + orderId, orderId, delayTime.longValue(), TimeUnit.MINUTES); + DelayTask delayTask = new DelayTask(); + delayTask.setDelFlag(0); + delayTask.setCreateTime(new Date()); + delayTask.setEndTime(DateUtils.addMinutes(new Date(), delayTime)); + delayTask.setRedisKey(DelayTaskEnum.ORDER_AUTOMATIC_CANCEL.getCode() + "-" + orderId); + remoteConfigService.addDelayTask(delayTask); + appPlaceOrderVo.setEndTime(DateUtils.addMinutes(order.getCreateTime(), delayTime)); + + return appPlaceOrderVo; + } + + /** + * 小程序支付下单API + * @param appPlaceOrderVo + * @param userId + * @param shopId + * @param goodsName + * @param orderNo + * @param orderId + * @param payMoney + * @param openid + * @param payerClientIp + * @param goodsNameList + */ + private void createWxPayInfo(AppPlaceOrderVo appPlaceOrderVo, Long userId, Long shopId, + String goodsName, String orderNo, + String orderId, BigDecimal payMoney, + String openid, String payerClientIp, List<String> goodsNameList){ try { // 创建支付订单 - Long shopId = appPlaceOrderDto.getShopId(); R<String> resultMch = remoteShopService.getShopSubMchId(shopId); String subMchId = resultMch.getData(); - if(StringUtils.isEmpty(subMchId)){ + if (StringUtils.isEmpty(subMchId)) { throw new ServiceException("获取微信商户号失败"); } - WxPayConfig config = wxService.getConfig(); config.setSubMchId(subMchId); - WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest(); - request.setTradeType(WxPayConstants.TradeType.JSAPI); - request.setSubMchId(subMchId); - // 商户订单号 - request.setOutTradeNo(orderNo); - // 订单总金额 - Integer totalFee = order.getPayMoney().multiply(new BigDecimal(100)).intValue(); - request.setTotalFee(totalFee); - request.setProductId(orderNo); - request.setNotifyUrl(config.getNotifyUrl()); - request.setProfitSharing("Y"); - request.setOpenid(appPlaceOrderDto.getOpenid()); - request.setSpbillCreateIp(appPlaceOrderDto.getSpbillCreateIp()); - // 商品描述 body - String body = "商品购买"; - if(null != goods){ - body = goods.getGoodsName() + "-" + body; - } - request.setBody(body); + PartnerTransactionsRequest request = new PartnerTransactionsRequest(); + request.setSpAppid(config.getAppId()); + request.setSpMchid(config.getMchId()); + request.setSubMchid(config.getSubMchId()); + // 商品描述 body + String description = goodsName + "-商品购买"; - request.checkAndSign(config); + request.setDescription(description); + request.setOutTradeNo(orderNo); + request.setNotifyUrl(config.getNotifyUrl()); + // 结算信息 + PartnerTransactionsRequest.SettleInfo settleInfo = new PartnerTransactionsRequest.SettleInfo(); + settleInfo.setProfitSharing(true); + settleInfo.setSubsidyAmount(BigDecimal.ZERO); + request.setSettleInfo(settleInfo); + + // 订单总金额 + Integer totalFee = payMoney.multiply(new BigDecimal(100)).intValue(); + PartnerTransactionsRequest.Amount amount = new PartnerTransactionsRequest.Amount(); + amount.setTotal(totalFee); + amount.setCurrency("CNY"); + request.setAmount(amount); + + // 支付者 + PartnerTransactionsRequest.Payer payer = new PartnerTransactionsRequest.Payer(); + payer.setSpOpenid(openid); + request.setPayer(payer); + + // 场景信息 + PartnerTransactionsRequest.SceneInfo sceneInfo = new PartnerTransactionsRequest.SceneInfo(); + sceneInfo.setPayerClientIp(payerClientIp); + request.setSceneInfo(sceneInfo); + + TransactionsResult.JsapiResult result = wxService.getEcommerceService().partnerTransactions(TradeTypeEnum.JSAPI, request); // 请求参数 Gson gson = new Gson(); String payRequestJson = gson.toJson(request); - - WxPayMpOrderResult result = wxService.createOrder(request); - - String payResponseJson = gson.toJson(request); + // 返回参数 + String payResponseJson = gson.toJson(result); // 支付相关信息返回 appPlaceOrderVo.setAppId(result.getAppId()); @@ -775,35 +846,14 @@ appPlaceOrderVo.setPaySign(result.getPaySign()); appPlaceOrderVo.setPrepayId(result.getPackageValue()); - //减去优惠券 - if(StringUtils.isNotBlank(memberCouponSJ.toString())){ - remoteCouponService.useMemberCoupon(memberCouponSJ.toString()); - } - //生成自动取消订单延时任务 - Integer delayTime = 30; - if(redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)){ - delayTime = redisService.getCacheObject(SecurityConstant.AUTO_CANCEL_ORDER_TIME); - } - redisService.setCacheObject(DelayTaskEnum.ORDER_AUTOMATIC_CANCEL.getCode() + "-" + orderId, orderId, delayTime.longValue(), TimeUnit.MINUTES); - DelayTask delayTask = new DelayTask(); - delayTask.setDelFlag(0); - delayTask.setCreateTime(new Date()); - delayTask.setEndTime(DateUtils.addMinutes(new Date(),delayTime)); - delayTask.setRedisKey(DelayTaskEnum.ORDER_AUTOMATIC_CANCEL.getCode() + "-" + orderId); - remoteConfigService.addDelayTask(delayTask); - appPlaceOrderVo.setEndTime(DateUtils.addMinutes(order.getCreateTime(),delayTime)); - - // 保存支付订单统一下单日志 - paymentMessageService.savePaymentMessage("1", 0L, payRequestJson, payResponseJson); + paymentMessageService.savePaymentMessage("1", orderId, payRequestJson, payResponseJson); // 保存支付订单统一下单支付记录 - orderPaymentService.saveOrderPayment(userId, shopId, orderId, order.getPayMoney(), - appPlaceOrderVo.getEndTime(), "Y", appPlaceOrderDto.getOpenid(), - Joiner.on(";").join(goodsNameList),result.getPackageValue()); - - return appPlaceOrderVo; - } catch (WxPayException e){ + orderPaymentService.saveOrderPayment(userId, shopId, subMchId, orderId, payMoney, + appPlaceOrderVo.getEndTime(), "Y", openid, + Joiner.on(";").join(goodsNameList), result.getPackageValue()); + } catch (WxPayException e) { throw new ServiceException(e.getMessage()); } } @@ -829,17 +879,17 @@ String goodsId = appPlaceActivityDto.getGoodsId(); Integer buyNum = appPlaceActivityDto.getBuyNum(); //redis库存控制极简版 - String goodsLock = "goods_lock_"+activityId+"_"+goodsId; + String goodsLock = "goods_lock_" + activityId + "_" + goodsId; RLock redissonLock = redissonClient.getLock(goodsLock); - try{ + try { redissonLock.lock(30, TimeUnit.SECONDS); - Integer surpNum = redisService.getCacheObject(SecurityConstant.ACTIVITY_GOODS+"-"+activityId+"-"+goodsId); - if(surpNum==null||surpNum<buyNum){ + Integer surpNum = redisService.getCacheObject(SecurityConstant.ACTIVITY_GOODS + "-" + activityId + "-" + goodsId); + if (surpNum == null || surpNum < buyNum) { throw new ServiceException(AppErrorConstant.ACTIVITY_GOODS_NULL); - }else{ - redisService.setCacheObject(SecurityConstant.ACTIVITY_GOODS+"-"+activityId+"-"+goodsId,surpNum-buyNum); + } else { + redisService.setCacheObject(SecurityConstant.ACTIVITY_GOODS + "-" + activityId + "-" + goodsId, surpNum - buyNum); } - }finally{ + } finally { redissonLock.unlock(); } // 定义购买数量,服务数量,商品数量 @@ -919,9 +969,9 @@ appSureOrderGoodsVo.setGoodsRealPrice(goodsRealPrice); // 获取商品押金 goodsDeposit = activityGoodsGetVo.getActivitySubscription(); - if (goodsDeposit == null || goodsDeposit.compareTo(BigDecimal.ZERO)==0) { + if (goodsDeposit == null || goodsDeposit.compareTo(BigDecimal.ZERO) == 0) { goodsDeposit = new BigDecimal("0.00"); - }else{ + } else { goodsDeposit = goodsDeposit.multiply(buyNumBig); } appSureOrderGoodsVo.setGoodsDeposit(goodsDeposit); @@ -967,9 +1017,9 @@ goodsTypeSet.add("单品"); } String goodsNurse = goods.getGoodsNurses(); - if(StringUtils.isNotBlank(goodsNurse)){ + if (StringUtils.isNotBlank(goodsNurse)) { String[] goodsNurseArr = goodsNurse.split(","); - for(String str : goodsNurseArr){ + for (String str : goodsNurseArr) { goodsNurseSet.add(str); } } @@ -1013,7 +1063,7 @@ // 保存订单 this.save(order); // 更新用户商品类型 - if (goodsTypeSet != null || goodsNurseSet!= null) { + if (goodsTypeSet != null || goodsNurseSet != null) { AppMemberGoodsTypeDto appMemberGoodsTypeDto = new AppMemberGoodsTypeDto(); appMemberGoodsTypeDto.setUserId(userId); appMemberGoodsTypeDto.setGoodsTypeSet(goodsTypeSet); @@ -1081,17 +1131,17 @@ remoteActivityService.addActivityRecord(activityRecord); //生成自动取消订单延时任务 Integer delayTime = 30; - if(redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)){ + if (redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)) { delayTime = redisService.getCacheObject(SecurityConstant.AUTO_CANCEL_ORDER_TIME); } redisService.setCacheObject(DelayTaskEnum.ORDER_AUTOMATIC_CANCEL.getCode() + "-" + orderId, orderId, delayTime.longValue(), TimeUnit.MINUTES); DelayTask delayTask = new DelayTask(); delayTask.setDelFlag(0); delayTask.setCreateTime(new Date()); - delayTask.setEndTime(DateUtils.addMinutes(new Date(),delayTime)); + delayTask.setEndTime(DateUtils.addMinutes(new Date(), delayTime)); delayTask.setRedisKey(DelayTaskEnum.ORDER_AUTOMATIC_CANCEL.getCode() + "-" + orderId); remoteConfigService.addDelayTask(delayTask); - appPlaceOrderVo.setEndTime(DateUtils.addMinutes(order.getCreateTime(),delayTime)); + appPlaceOrderVo.setEndTime(DateUtils.addMinutes(order.getCreateTime(), delayTime)); return appPlaceOrderVo; } @@ -1120,7 +1170,7 @@ shopMap.put(shopIdLong, shopTemp); }); Integer delayTime = 30; - if(redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)){ + if (redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)) { delayTime = redisService.getCacheObject(SecurityConstant.AUTO_CANCEL_ORDER_TIME); } for (AppUserOrderPageVo appUserOrderPageVo : appUserOrderPageVoList) { @@ -1133,7 +1183,7 @@ appUserOrderPageVo.setSameShop(0); } appUserOrderPageVo.setVerifyCode("1-" + appUserOrderPageVo.getOrderId()); - appUserOrderPageVo.setEndTime(DateUtils.addMinutes(appUserOrderPageVo.getCreateTime(),delayTime)); + appUserOrderPageVo.setEndTime(DateUtils.addMinutes(appUserOrderPageVo.getCreateTime(), delayTime)); } } return appUserOrderPageVoList; @@ -1174,10 +1224,10 @@ appUserOrderGetVo.setVerifyCode("1-" + orderId); //生成自动取消订单延时任务 Integer delayTime = 30; - if(redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)){ + if (redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)) { delayTime = redisService.getCacheObject(SecurityConstant.AUTO_CANCEL_ORDER_TIME); } - appUserOrderGetVo.setEndTime(DateUtils.addMinutes(order.getCreateTime(),delayTime)); + appUserOrderGetVo.setEndTime(DateUtils.addMinutes(order.getCreateTime(), delayTime)); return appUserOrderGetVo; } @@ -1189,13 +1239,15 @@ @Override public void cancelOrder(String orderId) { Order order = this.getById(orderId); + // 订单状态-1.删除 0.已取消 1.待支付 2.待核销 3.已完成 if (order.getOrderStatus() == 0) { throw new ServiceException(AppErrorConstant.CANCEL_CANCEL_ORDER); - }else if (order.getOrderStatus() == 1) { + } else if (order.getOrderStatus() == 1) { this.autoCancelOrder(orderId); - }else if(order.getOrderStatus() == 2){ + } else if (order.getOrderStatus() == 2) { + // 2.待核销 -> 订单退款 this.refundOrder(orderId); - }else{ + } else { throw new ServiceException(AppErrorConstant.CANCEL_ERROR_ORDER); } } @@ -1299,7 +1351,7 @@ } ShopRelUserVo shopRelUserVo = remoteShopService.getShopByUserId(merVerifyOrderDto.getUserId()).getData(); - if(!shopRelUserVo.getShopId().equals(order.getShopId())){ + if (!shopRelUserVo.getShopId().equals(order.getShopId())) { throw new ServiceException(AppErrorConstant.VERIFY_SHOP_ERROR); } order.setOrderStatus(3); @@ -1309,9 +1361,9 @@ order.setOffPayTime(nowTime); order.setPayMoney(order.getPayMoney().add(relPayMoney)); order.setChangeReceivableMoney(relReceiveMoney); - if(order.getPayMoney().compareTo(order.getChangeReceivableMoney())>=0){ + if (order.getPayMoney().compareTo(order.getChangeReceivableMoney()) >= 0) { order.setCloseFlag(1); - }else{ + } else { order.setCloseFlag(0); } this.saveOrUpdate(order); @@ -1331,7 +1383,7 @@ List<ConsumerGoods> consumerGoodsList = new ArrayList<>(); for (AppUserOrderGoodsPageVo appUserOrderGoodsPageVo : appUserOrderGoodsPageVoList) { Integer buyNum = appUserOrderGoodsPageVo.getBuyNum(); - if(appUserOrderGoodsPageVo.getCycleNumFlag()==0){ + if (appUserOrderGoodsPageVo.getCycleNumFlag() == 0) { consumerGoods = new ConsumerGoods(); goods = goodsMap.get(appUserOrderGoodsPageVo.getGoodsId()); consumerGoodsId = IdUtils.simpleUUID(); @@ -1355,8 +1407,8 @@ consumerGoods.setSourceFrom(1); consumerGoods.setSureNum(buyNum); consumerGoodsList.add(consumerGoods); - }else{ - for(int i=0;i<buyNum;i++){ + } else { + for (int i = 0; i < buyNum; i++) { consumerGoods = new ConsumerGoods(); goods = goodsMap.get(appUserOrderGoodsPageVo.getGoodsId()); consumerGoodsId = IdUtils.simpleUUID(); @@ -1404,7 +1456,7 @@ merVerifyOrderVo.setUserMobile(member.getMobile()); merVerifyOrderVo.setCloseFlag(order.getCloseFlag()); // - if(order.getOrderFrom() == 2){ + if (order.getOrderFrom() == 2) { // profitsSharingService.applyProfitSharing(); } @@ -1417,38 +1469,85 @@ payRecord.setPayType(2); payRecordService.save(payRecord); - // TODO 核销完成 开始分账(平台收取服务费) - OrderPayment payment = orderPaymentService.getByOrderId(orderId); - String transactionId = payment.getTransactionId(); - - String platformTyMacId = MyWxPayConfig.getPlatformTyMacId(); - - R<String> resultMch = remoteShopService.getShopSubMchId(order.getShopId()); - String subMchId = resultMch.getData(); - if(StringUtils.isEmpty(subMchId)){ - throw new ServiceException("获取微信商户号失败"); - } - - R<ShopProportionVo> resultShopProportion = remoteShopService.getShopProportion(order.getShopId()); - ShopProportionVo shopProportion = resultShopProportion.getData(); - if(null == shopProportion){ - throw new ServiceException("获取商户分成失败"); - } - - ProfitSharingRequest request = new ProfitSharingRequest(); - request.setSubMchId(subMchId); - request.setTransactionId(transactionId); - request.setOutOrderNo(order.getOrderNo()); - List<ProfitSharingReceiver> receiverList = new ArrayList<>(); - ProfitSharingReceiver receiver = new ProfitSharingReceiver(); - // TODO 分账 - // receiver.set - // request.setReceivers(); - - // platformTyMacId - // wxService.getProfitSharingV3Service().profitSharing() + submitProfitSharing(orderId, order.getOrderNo(), order.getShopId(), order.getOrderMoney()); return merVerifyOrderVo; + } + + private void submitProfitSharing(String orderId, String orderNo, Long shopId, BigDecimal orderMoney) { + String sendMessage = ""; + String resultMessage = ""; + try { + // TODO 核销完成 开始分账(平台收取服务费) + OrderPayment payment = orderPaymentService.getByOrderId(orderId); + String transactionId = payment.getTransactionId(); + + String platformTyMacId = MyWxPayConfig.getPlatformTyMacId(); + + R<String> resultMch = remoteShopService.getShopSubMchId(shopId); + String subMchId = resultMch.getData(); + if (!StringUtils.isEmpty(subMchId)) { + + + R<ShopProportionVo> resultShopProportion = remoteShopService.getShopProportion(shopId); + ShopProportionVo shopProportion = resultShopProportion.getData(); + if (null != shopProportion) { + ProfitSharingRequest request = new ProfitSharingRequest(); + request.setSubMchid(subMchId); + request.setTransactionId(transactionId); + request.setOutOrderNo(orderNo); + List<Receiver> receiverList = new ArrayList<>(); + + String description = "订单:" + orderNo + " 平台抽取佣金"; + BigDecimal proportionPercent = shopProportion.getProportionPercent(); + if (null == proportionPercent) { + proportionPercent = BigDecimal.ZERO; + } + + ProfitSharingResult result = new ProfitSharingResult(); + result.setOutOrderNo(orderNo); + result.setStatus("FINISHED"); + + // 计算分成金额 + int amount = orderMoney.multiply(proportionPercent).setScale(0, RoundingMode.UP).intValue(); + log.info("订单分账:{} 分账金额: {}", orderNo, amount); + if (amount > 0) { + // 分账创建 + Receiver receiver = new Receiver(); + receiver.setType("MERCHANT_ID"); + receiver.setReceiverAccount(platformTyMacId); + receiver.setAmount(amount); + receiver.setDescription(description); + + receiverList.add(receiver); + request.setReceivers(receiverList); + // 分账完成 + request.setFinish(true); + result = wxService.getEcommerceService().profitSharing(request); + } + + // 创建分账记录 + profitSharingService.saveProfitSharing(shopId, orderId, orderMoney, result); + + // 保存请求信息 + sendMessage = JSONObject.toJSONString(request); + resultMessage = JSONObject.toJSONString(result); + } else { + resultMessage = String.format("订单分账:%s 获取商户分成失败", orderNo); + log.info(resultMessage); + } + } else { + resultMessage = String.format("订单分账:%s 获取微信商户号失败", orderNo); + log.info(resultMessage); + } + } catch (WxPayException e) { + resultMessage = String.format("订单分账:%s 分账失败:%s", orderNo, e.getMessage()); + log.info(resultMessage); + e.printStackTrace(); + } + + // 保存分账信息 + paymentMessageService.savePaymentMessage("4", orderId, sendMessage, resultMessage); } /** @@ -1463,7 +1562,7 @@ public MerVerifyCouponVo sureVerifyCoupon(MerVerifyCouponDto merVerifyCouponDto) { MerVerifyCouponGetVo verifyCouponGetVo = remoteCouponService.getVerifyCoupon(merVerifyCouponDto.getMemberCouponId()).getData(); ShopRelUserVo shopRelUserVo = remoteShopService.getShopByUserId(merVerifyCouponDto.getUserId()).getData(); - if(!shopRelUserVo.getShopId().equals(verifyCouponGetVo.getMemberCoupon().getShopId())){ + if (!shopRelUserVo.getShopId().equals(verifyCouponGetVo.getMemberCoupon().getShopId())) { throw new ServiceException(AppErrorConstant.VERIFY_SHOP_ERROR); } // 创建MerVerifyCouponVo对象 @@ -1526,7 +1625,7 @@ appShopGoodsGetDto.setShopId(memberCoupon.getShopId()); //获取商户服务次数 shopGoods = remoteGoodsService.getShopGoods(appShopGoodsGetDto).getData(); - if(shopGoods!=null){ + if (shopGoods != null) { consumerGoods.setServiceNum(shopGoods.getServiceNum()); } consumerGoods.setUsedNum(0); @@ -1546,36 +1645,36 @@ /** - * @description 确认核销奖品 - * @author jqs - * @date 2023/7/9 9:54 * @param merVerifyPrizeDto - * @return MerVerifyAwardVo + * @return MerVerifyAwardVo + * @description 确认核销奖品 + * @author jqs + * @date 2023/7/9 9:54 */ @Override @Transactional - public MerVerifyAwardVo sureVerifyPrize(MerVerifyPrizeDto merVerifyPrizeDto){ + public MerVerifyAwardVo sureVerifyPrize(MerVerifyPrizeDto merVerifyPrizeDto) { MerVerifyAwardVo merVerifyAwardVo = new MerVerifyAwardVo(); MemberGiftRecord memberGiftRecord = remoteMemberService.getVerifyPrize(merVerifyPrizeDto.getPrizeId()).getData(); - if(memberGiftRecord==null||memberGiftRecord.getVerifyStatus()!=1){ + if (memberGiftRecord == null || memberGiftRecord.getVerifyStatus() != 1) { throw new ServiceException(AppErrorConstant.COUPON_USED); } ShopRelUserVo shopRelUserVo = remoteShopService.getShopByUserId(merVerifyPrizeDto.getUserId()).getData(); - if(!shopRelUserVo.getShopId().equals(memberGiftRecord.getShopId())){ + if (!shopRelUserVo.getShopId().equals(memberGiftRecord.getShopId())) { throw new ServiceException(AppErrorConstant.VERIFY_SHOP_ERROR); } Member member = remoteMemberService.getMember(memberGiftRecord.getUserId()).getData(); merVerifyAwardVo.setUserName(member.getRealName()); merVerifyAwardVo.setUserMobile(member.getMobile()); - if(memberGiftRecord.getGiftFrom()==1){ + if (memberGiftRecord.getGiftFrom() == 1) { merVerifyAwardVo.setGiftFrom("平台生日卡"); - }else{ + } else { merVerifyAwardVo.setGiftFrom("商户生日卡"); } merVerifyAwardVo.setGiftType(memberGiftRecord.getGiftType()); List<BirthdayGiftSendDto> giftSendDtoList = new ArrayList<>(); BirthdayGiftSendDto birthdayGiftSendDto = new BirthdayGiftSendDto(); - switch(memberGiftRecord.getGiftType()){ + switch (memberGiftRecord.getGiftType()) { case 1: merVerifyAwardVo.setGiftName(memberGiftRecord.getCouponName()); merVerifyAwardVo.setGiftNumber(Double.valueOf(memberGiftRecord.getCouponNumber())); @@ -1624,7 +1723,7 @@ merVerifyAwardVo.setCreateTime(memberGiftRecord.getCreateTime()); memberGiftRecord.setVerifyStatus(2); memberGiftRecord.setVerifyTime(new Date()); - if(member.getBindingFlag()!=1){ + if (member.getBindingFlag() != 1) { AppMemberBindingDto appMemberBindingDto = new AppMemberBindingDto(); appMemberBindingDto.setBindingFlag(1); appMemberBindingDto.setShopId(merVerifyPrizeDto.getShopId()); @@ -1672,9 +1771,9 @@ order.setOfflinePayMoney(order.getOfflinePayMoney().add(merCloseOrderDto.getPayMoney())); order.setOffPayTime(new Date()); order.setPayMoney(order.getPayMoney().add(merCloseOrderDto.getPayMoney())); - if(order.getPayMoney().compareTo(order.getChangeReceivableMoney())>=0){ + if (order.getPayMoney().compareTo(order.getChangeReceivableMoney()) >= 0) { order.setCloseFlag(0); - }else{ + } else { order.setCloseFlag(1); } this.saveOrUpdate(order); @@ -1805,7 +1904,7 @@ } } else if (couponType == 2 && appMemberCouponVo.getDiscountPercent() != null) { discountPercent = appMemberCouponVo.getDiscountPercent(); - goodsRealPrice = goodsTotalPrice.multiply(discountPercent).divide(BigDecimal.TEN,2, BigDecimal.ROUND_HALF_UP); + goodsRealPrice = goodsTotalPrice.multiply(discountPercent).divide(BigDecimal.TEN, 2, BigDecimal.ROUND_HALF_UP); discountMoney = goodsRealPrice.subtract(goodsTotalPrice); } else if (couponType == 3 && appMemberCouponVo.getDiscountMoney() != null) { discountMoney = appMemberCouponVo.getDiscountMoney(); @@ -1815,9 +1914,9 @@ } goodsDeposit = goods.getSubscription(); - if (goodsDeposit == null || goodsDeposit.compareTo(BigDecimal.ZERO)==0) { + if (goodsDeposit == null || goodsDeposit.compareTo(BigDecimal.ZERO) == 0) { goodsDeposit = new BigDecimal("0.00"); - }else{ + } else { goodsDeposit = goodsDeposit.multiply(buyNumBig); } goodsNum = goodsNum + buyNum; @@ -1897,9 +1996,9 @@ order.setOfflinePayMoney(merNewOrderDto.getPayMoney()); order.setOffPayTime(nowTime); order.setPayType(1); - if(order.getPayMoney().compareTo(order.getChangeReceivableMoney())>=0){ + if (order.getPayMoney().compareTo(order.getChangeReceivableMoney()) >= 0) { order.setCloseFlag(0); - }else{ + } else { order.setCloseFlag(1); } this.save(order); @@ -1910,7 +2009,7 @@ List<ConsumerGoods> consumerGoodsList = new ArrayList<>(); for (AppUserOrderGoodsPageVo appUserOrderGoodsPageVo : appUserOrderGoodsPageVoList) { Integer buyGoodsNum = appUserOrderGoodsPageVo.getBuyNum(); - if(appUserOrderGoodsPageVo.getCycleNumFlag()==0){ + if (appUserOrderGoodsPageVo.getCycleNumFlag() == 0) { consumerGoods = new ConsumerGoods(); goods = remoteGoodsService.getGoods(appUserOrderGoodsPageVo.getGoodsId()).getData(); consumerGoodsId = IdUtils.simpleUUID(); @@ -1934,8 +2033,8 @@ consumerGoods.setSourceFrom(1); consumerGoods.setSureNum(buyGoodsNum); consumerGoodsList.add(consumerGoods); - }else{ - for(int i=0;i<buyGoodsNum;i++) { + } else { + for (int i = 0; i < buyGoodsNum; i++) { consumerGoods = new ConsumerGoods(); goods = remoteGoodsService.getGoods(appUserOrderGoodsPageVo.getGoodsId()).getData(); consumerGoodsId = IdUtils.simpleUUID(); @@ -1997,11 +2096,11 @@ */ @Override public List<MerOrderPageVo> pageMerOrder(Page page, MerOrderPageDto merOrderPageDto) { - if(StringUtils.isNotBlank(merOrderPageDto.getKeyword())){ + if (StringUtils.isNotBlank(merOrderPageDto.getKeyword())) { MgtUserIdByKeywordDto userIdByKeywordDto = new MgtUserIdByKeywordDto(); userIdByKeywordDto.setKeyword(merOrderPageDto.getKeyword()); MgtUserIdByKeywordVo userIdByKeywordVo = remoteMemberService.getUserIdByKeyword(userIdByKeywordDto).getData(); - if(StringUtils.isNotBlank(userIdByKeywordVo.getUserIds())){ + if (StringUtils.isNotBlank(userIdByKeywordVo.getUserIds())) { List<Long> userIdList = Arrays.stream(userIdByKeywordVo.getUserIds().split(",")) .map(Long::parseLong) .collect(Collectors.toList()); @@ -2042,12 +2141,12 @@ Map<Long, MgtSimpleMemberVo> userMap = simpleMemberVoList.stream() .collect(Collectors.toMap(MgtSimpleMemberVo::getUserId, Function.identity())); for (MerOrderPageVo merOrderPageVo : merOrderPageVoList) { - if(merOrderPageVo.getUserId()!=null&&userMap.get(merOrderPageVo.getUserId())!=null){ + if (merOrderPageVo.getUserId() != null && userMap.get(merOrderPageVo.getUserId()) != null) { merOrderPageVo.setUserName(userMap.get(merOrderPageVo.getUserId()).getRealName()); merOrderPageVo.setNickName(userMap.get(merOrderPageVo.getUserId()).getNickName()); merOrderPageVo.setUserMobile(userMap.get(merOrderPageVo.getUserId()).getUserMobile()); - }else{ - log.debug("订单merOrderPageVo"+merOrderPageVo.getOrderId()+"缺少用户"); + } else { + log.debug("订单merOrderPageVo" + merOrderPageVo.getOrderId() + "缺少用户"); } } } @@ -2414,9 +2513,9 @@ mgtOrderDetailVo.setCancelTime(order.getCancelTime()); mgtOrderDetailVo.setOrderRemark(order.getOrderRemark()); mgtOrderDetailVo.setShopId(order.getShopId()); - if(shop!=null){ + if (shop != null) { mgtOrderDetailVo.setShopName(shop.getShopName()); - }else{ + } else { mgtOrderDetailVo.setShopName("商户已被删除"); } mgtOrderDetailVo.setVerifyTime(order.getUseTime()); @@ -3006,11 +3105,11 @@ } else if (couponStatus != 1) { throw new ServiceException(AppErrorConstant.COUPON_NO_FIND); } - if (memberCoupon.getCouponFrom()==2&&!memberCoupon.getShopId().equals(shopId)) { + if (memberCoupon.getCouponFrom() == 2 && !memberCoupon.getShopId().equals(shopId)) { throw new ServiceException(AppErrorConstant.VERIFY_SHOP_ERROR); } //如果是平台优惠券 - if(memberCoupon.getCouponFrom()==1&&memberCoupon.getShopId()==null){ + if (memberCoupon.getCouponFrom() == 1 && memberCoupon.getShopId() == null) { memberCoupon.setShopId(shopId); } List<Goods> goodsList = verifyCouponGetVo.getGoodsList(); @@ -3048,34 +3147,34 @@ } /** - * @description 获取核销奖品 - * @author jqs - * @date 2023/7/8 17:46 * @param verifyCode * @param shopId - * @return MerVerifyAwardVo + * @return MerVerifyAwardVo + * @description 获取核销奖品 + * @author jqs + * @date 2023/7/8 17:46 */ @Override - public MerVerifyAwardVo verifyPrize(String verifyCode,Long shopId){ + public MerVerifyAwardVo verifyPrize(String verifyCode, Long shopId) { MerVerifyAwardVo merVerifyAwardVo = new MerVerifyAwardVo(); MemberGiftRecord memberGiftRecord = remoteMemberService.getVerifyPrize(verifyCode).getData(); - if(memberGiftRecord==null||memberGiftRecord.getVerifyStatus()!=1){ + if (memberGiftRecord == null || memberGiftRecord.getVerifyStatus() != 1) { throw new ServiceException(AppErrorConstant.COUPON_USED); } - if(memberGiftRecord.getGiftFrom()==2&&!memberGiftRecord.getShopId().equals(shopId)){ + if (memberGiftRecord.getGiftFrom() == 2 && !memberGiftRecord.getShopId().equals(shopId)) { throw new ServiceException(AppErrorConstant.VERIFY_SHOP_ERROR); } Member member = remoteMemberService.getMember(memberGiftRecord.getUserId()).getData(); merVerifyAwardVo.setUserName(member.getRealName()); merVerifyAwardVo.setUserMobile(member.getMobile()); - if(memberGiftRecord.getGiftFrom()==1){ + if (memberGiftRecord.getGiftFrom() == 1) { merVerifyAwardVo.setGiftFrom("平台生日卡"); - }else{ + } else { merVerifyAwardVo.setGiftFrom("商户生日卡"); } merVerifyAwardVo.setGiftType(memberGiftRecord.getGiftType()); - switch(memberGiftRecord.getGiftType()){ + switch (memberGiftRecord.getGiftType()) { case 1: merVerifyAwardVo.setGiftName(memberGiftRecord.getCouponName()); merVerifyAwardVo.setGiftNumber(Double.valueOf(memberGiftRecord.getCouponNumber())); @@ -3215,22 +3314,22 @@ orderMoneyValue[i] = BigDecimal.ZERO; } }*/ - List<MgtMapTotalPlusVo> mgtMapTotalPlusVoList = orderMapper.listMerOrderDistributionTotal(merTotalDto); - if(mgtMapTotalPlusVoList!=null&&!mgtMapTotalPlusVoList.isEmpty()) { - String[] orderTotalKey = new String[mgtMapTotalPlusVoList.size()]; - Integer[] orderTotalValue = new Integer[mgtMapTotalPlusVoList.size()]; - BigDecimal[] orderMoneyValue = new BigDecimal[mgtMapTotalPlusVoList.size()]; - MgtMapTotalPlusVo mgtMapTotalPlusVo; - for (int i = 0; i < mgtMapTotalPlusVoList.size(); i++) { - mgtMapTotalPlusVo = mgtMapTotalPlusVoList.get(i); - orderTotalKey[i] = mgtMapTotalPlusVo.getMapKey(); - orderTotalValue[i] = mgtMapTotalPlusVo.getMapValueFirst(); - orderMoneyValue[i] = mgtMapTotalPlusVo.getMapValueSecond(); - } - orderDistributionTotalVo.setOrderTotalKey(orderTotalKey); - orderDistributionTotalVo.setOrderTotalValue(orderTotalValue); - orderDistributionTotalVo.setOrderMoneyValue(orderMoneyValue); + List<MgtMapTotalPlusVo> mgtMapTotalPlusVoList = orderMapper.listMerOrderDistributionTotal(merTotalDto); + if (mgtMapTotalPlusVoList != null && !mgtMapTotalPlusVoList.isEmpty()) { + String[] orderTotalKey = new String[mgtMapTotalPlusVoList.size()]; + Integer[] orderTotalValue = new Integer[mgtMapTotalPlusVoList.size()]; + BigDecimal[] orderMoneyValue = new BigDecimal[mgtMapTotalPlusVoList.size()]; + MgtMapTotalPlusVo mgtMapTotalPlusVo; + for (int i = 0; i < mgtMapTotalPlusVoList.size(); i++) { + mgtMapTotalPlusVo = mgtMapTotalPlusVoList.get(i); + orderTotalKey[i] = mgtMapTotalPlusVo.getMapKey(); + orderTotalValue[i] = mgtMapTotalPlusVo.getMapValueFirst(); + orderMoneyValue[i] = mgtMapTotalPlusVo.getMapValueSecond(); } + orderDistributionTotalVo.setOrderTotalKey(orderTotalKey); + orderDistributionTotalVo.setOrderTotalValue(orderTotalValue); + orderDistributionTotalVo.setOrderMoneyValue(orderMoneyValue); + } // 返回订单分布总数对象 return orderDistributionTotalVo; } @@ -3335,20 +3434,20 @@ } /** - * @description 商户端订单管理统计 - * @author jqs - * @date 2023/7/31 10:53 * @param merOrderPageDto - * @return MerTotalOrderVo + * @return MerTotalOrderVo + * @description 商户端订单管理统计 + * @author jqs + * @date 2023/7/31 10:53 */ @Override public MerTotalOrderVo totalMerOrder(MerOrderPageDto merOrderPageDto) { MerTotalOrderVo merTotalOrderVo = new MerTotalOrderVo(); - if(StringUtils.isNotBlank(merOrderPageDto.getKeyword())){ + if (StringUtils.isNotBlank(merOrderPageDto.getKeyword())) { MgtUserIdByKeywordDto userIdByKeywordDto = new MgtUserIdByKeywordDto(); userIdByKeywordDto.setKeyword(merOrderPageDto.getKeyword()); MgtUserIdByKeywordVo userIdByKeywordVo = remoteMemberService.getUserIdByKeyword(userIdByKeywordDto).getData(); - if(StringUtils.isNotBlank(userIdByKeywordVo.getUserIds())){ + if (StringUtils.isNotBlank(userIdByKeywordVo.getUserIds())) { List<Long> userIdList = Arrays.stream(userIdByKeywordVo.getUserIds().split(",")) .map(Long::parseLong) .collect(Collectors.toList()); @@ -3419,33 +3518,33 @@ } /** - * @description 自动取消订单 - * @author jqs - * @date 2023/7/13 17:15 * @param orderId - * @return void + * @return void + * @description 自动取消订单 + * @author jqs + * @date 2023/7/13 17:15 */ @Override @Transactional - public void autoCancelOrder(String orderId){ + public void autoCancelOrder(String orderId) { //更新订单信息 Order order = this.getById(orderId); order.setOrderStatus(0); order.setCancelTime(new Date()); this.saveOrUpdate(order); //活动订单回退库存 - if(order.getOrderFrom()==2){ + if (order.getOrderFrom() == 2) { List<OrderGoods> orderGoodsList = orderGoodsService.listByOrderId(orderId); - if(orderGoodsList!=null&&!orderGoodsList.isEmpty()){ - for(OrderGoods orderGoods : orderGoodsList){ + if (orderGoodsList != null && !orderGoodsList.isEmpty()) { + for (OrderGoods orderGoods : orderGoodsList) { //redis库存控制极简版 - String goodsLock = "goods_lock_"+order.getActivityId()+"_"+orderGoods.getGoodsId(); + String goodsLock = "goods_lock_" + order.getActivityId() + "_" + orderGoods.getGoodsId(); RLock redissonLock = redissonClient.getLock(goodsLock); - try{ + try { redissonLock.lock(30, TimeUnit.SECONDS); - Integer surpNum = redisService.getCacheObject(SecurityConstant.ACTIVITY_GOODS+"-"+order.getActivityId()+"-"+orderGoods.getGoodsId()); - redisService.setCacheObject(SecurityConstant.ACTIVITY_GOODS+"-"+order.getActivityId()+"-"+orderGoods.getGoodsId(),surpNum+orderGoods.getBuyNum()); - }finally{ + Integer surpNum = redisService.getCacheObject(SecurityConstant.ACTIVITY_GOODS + "-" + order.getActivityId() + "-" + orderGoods.getGoodsId()); + redisService.setCacheObject(SecurityConstant.ACTIVITY_GOODS + "-" + order.getActivityId() + "-" + orderGoods.getGoodsId(), surpNum + orderGoods.getBuyNum()); + } finally { redissonLock.unlock(); } //改变活动库存 @@ -3466,16 +3565,16 @@ remoteActivityService.delActivityRecord(activityRecord); } } - }else{ - if(order.getCouponMoney().compareTo(BigDecimal.ZERO)>0){ + } else { + if (order.getCouponMoney().compareTo(BigDecimal.ZERO) > 0) { //回退优惠券 List<OrderGoods> orderGoodsList = orderGoodsService.listByOrderId(orderId); - if(orderGoodsList!=null&&!orderGoodsList.isEmpty()) { + if (orderGoodsList != null && !orderGoodsList.isEmpty()) { StringJoiner memberCouponSJ = new StringJoiner(","); for (OrderGoods orderGoods : orderGoodsList) { memberCouponSJ.add(orderGoods.getCouponId()); } - if(memberCouponSJ!=null){ + if (memberCouponSJ != null) { remoteCouponService.backMemberCoupon(memberCouponSJ.toString()); } @@ -3485,17 +3584,17 @@ } /** - * @description 订单支付回调 - * @author jqs - * @date 2023/7/13 17:57 * @param transaction - * @return void + * @return void + * @description 订单支付回调 + * @author jqs + * @date 2023/7/13 17:57 */ @Override @Transactional - public void payBack(Transaction transaction) { + public void payBack(PartnerTransactionsResult transaction) { // 更新订单状态 - String orderId=transaction.getOutTradeNo(); + String orderId = transaction.getOutTradeNo(); Order order = this.getById(orderId); order.setOrderStatus(2); order.setPayTime(new Date()); @@ -3541,8 +3640,8 @@ goodsTotalChangeDto.setChangeType(1); goodsTotalChangeDto.setChangeNum(orderGoods.getBuyNum()); goodsTotalChangeDto.setMoney(orderGoods.getGoodsReceivableMoney()); - Integer bugGoodsNum = orderMapper.countUserBuyGoodsNum(order.getUserId(),orderGoods.getGoodsId()); - if(bugGoodsNum==null||bugGoodsNum<1){ + Integer bugGoodsNum = orderMapper.countUserBuyGoodsNum(order.getUserId(), orderGoods.getGoodsId()); + if (bugGoodsNum == null || bugGoodsNum < 1) { goodsTotalChangeDto.setPersonNum(1); } goodsTotalChangeDtoList.add(goodsTotalChangeDto); @@ -3623,16 +3722,16 @@ } /** - * @description 订单退款 - * @author jqs - * @date 2023/7/13 18:36 * @param orderId - * @return void + * @return void + * @description 订单退款 + * @author jqs + * @date 2023/7/13 18:36 */ @Override @Transactional - public void refundOrder(String orderId){ - //更新订单信息 + public void refundOrder(String orderId) { + // 更新订单信息 Order order = this.getById(orderId); order.setOrderStatus(0); order.setCancelTime(new Date()); @@ -3645,7 +3744,7 @@ orderRefund.setOrderId(order.getOrderId()); orderRefund.setUserId(order.getUserId()); orderRefund.setShopId(order.getShopId()); - orderRefund.setRefundMoney(order.getPayMoney()); + orderRefund.setRefundMoney(order.getOnlinePayMoney()); orderRefund.setOrderMoney(order.getPayMoney()); orderRefund.setCreateTime(new Date()); // 初始化各类商品的收款金额 @@ -3659,19 +3758,19 @@ Boolean haveExperience = false; Boolean haveGoods = false; List<OrderGoods> orderGoodsList = orderGoodsService.listByOrderId(orderId); - if(orderGoodsList!=null&&!orderGoodsList.isEmpty()){ + if (orderGoodsList != null && !orderGoodsList.isEmpty()) { StringJoiner memberCouponSJ = new StringJoiner(","); - for(OrderGoods orderGoods : orderGoodsList){ - if(order.getOrderFrom()==2){ + for (OrderGoods orderGoods : orderGoodsList) { + if (order.getOrderFrom() == 2) { //redis库存控制极简版 //活动订单回退库存 - String goodsLock = "goods_lock_"+order.getActivityId()+"_"+orderGoods.getGoodsId(); + String goodsLock = "goods_lock_" + order.getActivityId() + "_" + orderGoods.getGoodsId(); RLock redissonLock = redissonClient.getLock(goodsLock); - try{ + try { redissonLock.lock(30, TimeUnit.SECONDS); - Integer surpNum = redisService.getCacheObject(SecurityConstant.ACTIVITY_GOODS+"-"+order.getActivityId()+"-"+orderGoods.getGoodsId()); - redisService.setCacheObject(SecurityConstant.ACTIVITY_GOODS+"-"+order.getActivityId()+"-"+orderGoods.getGoodsId(),surpNum+orderGoods.getBuyNum()); - }finally{ + Integer surpNum = redisService.getCacheObject(SecurityConstant.ACTIVITY_GOODS + "-" + order.getActivityId() + "-" + orderGoods.getGoodsId()); + redisService.setCacheObject(SecurityConstant.ACTIVITY_GOODS + "-" + order.getActivityId() + "-" + orderGoods.getGoodsId(), surpNum + orderGoods.getBuyNum()); + } finally { redissonLock.unlock(); } //改变活动库存 @@ -3690,7 +3789,7 @@ activityRecord.setUserId(order.getUserId()); activityRecord.setOrderTime(order.getCreateTime()); remoteActivityService.delActivityRecord(activityRecord); - }else{ + } else { memberCouponSJ.add(orderGoods.getCouponId()); } switch (orderGoods.getGoodsType()) { @@ -3715,7 +3814,7 @@ } } //回退优惠券 - if(memberCouponSJ!=null){ + if (memberCouponSJ != null) { remoteCouponService.backMemberCoupon(memberCouponSJ.toString()); } } @@ -3774,43 +3873,97 @@ activityTotalChangeDto.setUserId(order.getUserId()); remoteActivityService.changeActivityTotal(activityTotalChangeDto); } + + // 用户取消订单退款 + BigDecimal onlinePayMoney = order.getOnlinePayMoney(); + if(BigDecimal.ZERO.compareTo(onlinePayMoney) < 0){ + // 订单支付金额大于0,可发起退款 + orderWxApplyRefund(orderId, refundId, onlinePayMoney, orderRefund); + } + + orderRefund.setRefundStatus(1); + orderRefundService.saveOrUpdate(orderRefund); } /** - * @description 员工端活动订单统计 - * @author jqs - * @date 2023/7/17 15:25 + * 申请退款API + */ + private void orderWxApplyRefund(String orderId, String outRefundNo, BigDecimal payMoney, OrderRefund orderRefund){ + try { + // 创建支付订单 + OrderPayment orderPayment = orderPaymentService.getByOrderId(orderId); + if (null == orderPayment) { + return; + } + String subMchId = orderPayment.getSubMchId(); + WxPayConfig config = wxService.getConfig(); + + RefundsRequest request = new RefundsRequest(); + request.setSpAppid(config.getAppId()); + request.setSubMchid(subMchId); + request.setTransactionId(orderPayment.getTransactionId()); + request.setOutRefundNo(outRefundNo); + request.setReason("用户取消订单"); + // 订单金额 + int total = payMoney.multiply(new BigDecimal(100)).intValue(); + RefundsRequest.Amount amount = RefundsRequest.Amount.builder().refund(total).total(total).currency("CNY").build(); + request.setAmount(amount); + request.setNotifyUrl(config.getNotifyUrl()); + + RefundsResult result = wxService.getEcommerceService().refunds(request); + + // 微信退款id + orderRefund.setWxRefundId(result.getRefundId()); + + // 请求参数 + Gson gson = new Gson(); + String refundRequestJson = gson.toJson(request); + // 返回参数 + String refundResponseJson = gson.toJson(result); + + // 保存支付订单统一下单日志 + paymentMessageService.savePaymentMessage("3", orderId, refundRequestJson, refundResponseJson); + + } catch (WxPayException e) { + throw new ServiceException(e.getMessage()); + } + } + + /** * @param staffTotalDto - * @return StaffActivityOrderTotalVo + * @return StaffActivityOrderTotalVo + * @description 员工端活动订单统计 + * @author jqs + * @date 2023/7/17 15:25 */ @Override - public StaffActivityOrderTotalVo getStaffActivityOrderTotal(StaffTotalDto staffTotalDto){ + public StaffActivityOrderTotalVo getStaffActivityOrderTotal(StaffTotalDto staffTotalDto) { StaffActivityOrderTotalVo staffActivityOrderTotalVo = orderMapper.getStaffActivityOrderTotal(staffTotalDto); return staffActivityOrderTotalVo; } /** - * @description 员工端活动统计 - * @author jqs - * @date 2023/7/17 15:51 * @param staffTotalDto - * @return StaffActivityTotalVo + * @return StaffActivityTotalVo + * @description 员工端活动统计 + * @author jqs + * @date 2023/7/17 15:51 */ @Override - public StaffActivityTotalVo getStaffActivityTotal(StaffTotalDto staffTotalDto){ + public StaffActivityTotalVo getStaffActivityTotal(StaffTotalDto staffTotalDto) { StaffActivityTotalVo staffActivityTotalVo = orderMapper.getStaffActivityTotal(staffTotalDto); return staffActivityTotalVo; } /** - * @description 员工端活动统计订单分布 - * @author jqs - * @date 2023/7/17 16:16 * @param staffTotalDto - * @return MerOrderDistributionTotalVo + * @return MerOrderDistributionTotalVo + * @description 员工端活动统计订单分布 + * @author jqs + * @date 2023/7/17 16:16 */ @Override - public MerOrderDistributionTotalVo getStaffOrderDistributionTotal(StaffTotalDto staffTotalDto){ + public MerOrderDistributionTotalVo getStaffOrderDistributionTotal(StaffTotalDto staffTotalDto) { MerOrderDistributionTotalVo orderDistributionTotalVo = new MerOrderDistributionTotalVo(); // 获取订单年龄用户列表 MerTotalDto merTotalDto = new MerTotalDto(); @@ -3851,7 +4004,7 @@ } // 如果用户ID列表不为空 if (userIdList != null && !userIdList.isEmpty()) { - mgtMapTotalPlusVo = orderMapper.listStaffActivityOrderDistributionTotal(userIdList,staffTotalDto.getShopId(),staffTotalDto.getActivityId()); + mgtMapTotalPlusVo = orderMapper.listStaffActivityOrderDistributionTotal(userIdList, staffTotalDto.getShopId(), staffTotalDto.getActivityId()); orderTotalValue[i] = mgtMapTotalPlusVo.getMapValueFirst(); orderMoneyValue[i] = mgtMapTotalPlusVo.getMapValueSecond(); } else { @@ -3870,14 +4023,14 @@ /** - * @description 员工端活动统计销售占比 - * @author jqs - * @date 2023/7/17 17:03 * @param staffTotalDto - * @return MerOrderTypeTotalVo + * @return MerOrderTypeTotalVo + * @description 员工端活动统计销售占比 + * @author jqs + * @date 2023/7/17 17:03 */ @Override - public MerOrderTypeTotalVo getStaffOrderTypeTotal(StaffTotalDto staffTotalDto){ + public MerOrderTypeTotalVo getStaffOrderTypeTotal(StaffTotalDto staffTotalDto) { MerOrderTypeTotalVo orderTypeTotalVo = new MerOrderTypeTotalVo(); //获取商品分类销售数据 List<MgtMapTotalPlusVo> MgtMapIntTotalVoGoodsType = orderMapper.listStaffOrderTotalGoodsType(staffTotalDto); @@ -3915,11 +4068,11 @@ } /** - * @description 员工端获客人数 - * @author jqs - * @date 2023/7/17 18:42 * @param staffTotalDto - * @return StaffActivityDateMemberTotalVo + * @return StaffActivityDateMemberTotalVo + * @description 员工端获客人数 + * @author jqs + * @date 2023/7/17 18:42 */ @Override public StaffActivityDateMemberTotalVo getStaffActivityGetMemberTotal(StaffTotalDto staffTotalDto) { @@ -3956,11 +4109,11 @@ } /** - * @description 员工端获客人数 - * @author jqs - * @date 2023/7/17 18:42 * @param staffTotalDto - * @return StaffActivityDateMemberTotalVo + * @return StaffActivityDateMemberTotalVo + * @description 员工端获客人数 + * @author jqs + * @date 2023/7/17 18:42 */ @Override public StaffActivityDateMemberTotalVo getStaffActivityMemberTotal(StaffTotalDto staffTotalDto) { @@ -3997,12 +4150,12 @@ } /** - * @description 获取时间段日期 - * @author jqs - * @date 2023/7/17 19:11 * @param startDate * @param endDate - * @return List<String> + * @return List<String> + * @description 获取时间段日期 + * @author jqs + * @date 2023/7/17 19:11 */ public static List<String> getDateRange(String startDate, String endDate) { List<String> dateList = new ArrayList<>(); @@ -4016,50 +4169,87 @@ } /** - * @description 检查订单状态定时任务 - * @author jqs - * @date 2023/7/25 14:40 * @param - * @return void + * @return void + * @description 检查订单状态定时任务 + * @author jqs + * @date 2023/7/25 14:40 */ @Override - public void checkOrderStatus(){ + public void checkOrderStatus() { Integer delayTime = 30; - if(redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)){ + if (redisService.hasKey(SecurityConstant.AUTO_CANCEL_ORDER_TIME)) { delayTime = redisService.getCacheObject(SecurityConstant.AUTO_CANCEL_ORDER_TIME); } delayTime = delayTime + 5; - Date checkTime = DateUtils.addMinutes(new Date(),-delayTime); + Date checkTime = DateUtils.addMinutes(new Date(), -delayTime); LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(Order::getDelFlag,0); - queryWrapper.lt(Order::getCreateTime,checkTime); - queryWrapper.eq(Order::getOrderStatus,1); + queryWrapper.eq(Order::getDelFlag, 0); + queryWrapper.lt(Order::getCreateTime, checkTime); + queryWrapper.eq(Order::getOrderStatus, 1); List<Order> orderList = this.list(queryWrapper); - if(orderList!=null&&!orderList.isEmpty()){ - for(Order order: orderList){ + if (orderList != null && !orderList.isEmpty()) { + for (Order order : orderList) { autoTimeCancelOrder(order); } } } - private void autoTimeCancelOrder(Order order){ + @Override + public void profitSharingBack(ProfitSharingNotifyResult result) { + + try { + String outOrderNo = result.getOutOrderNo(); + ProfitSharing profitSharing = profitSharingService.getById(outOrderNo); + if(null != profitSharing){ + profitSharing.setWxOrderId(result.getOrderId()); + profitSharing.setFinishTime(result.getSuccessTime()); + profitSharing.setFinishFlag(1); + + profitSharingService.saveOrUpdate(profitSharing); + } + } catch (Exception e){ + + log.error("==分账回成功回调操作====【{}】========={}", result.getOutOrderNo(), e.getMessage()); + } + } + + @Override + public void orderRefundBack(RefundNotifyResult result) { + try { + String outRefundNo = result.getOutRefundNo(); + String refundStatus = result.getRefundStatus(); + OrderRefund orderRefund = orderRefundService.getById(outRefundNo); + if(null != orderRefund){ + orderRefund.setWxRefundId(result.getRefundId()); + orderRefund.setBackTime(result.getSuccessTime()); + orderRefund.setRefundStatus(IDict.getCodeByText(RefundStatusEnum.class, refundStatus)); + orderRefundService.saveOrUpdate(orderRefund); + } + } catch (Exception e){ + + log.error("==退款回成功回调操作====【{}】========={}", result.getOutRefundNo(), e.getMessage()); + } + } + + private void autoTimeCancelOrder(Order order) { String orderId = order.getOrderId(); order.setOrderStatus(0); order.setCancelTime(new Date()); this.saveOrUpdate(order); //活动订单回退库存 - if(order.getOrderFrom()==2){ + if (order.getOrderFrom() == 2) { List<OrderGoods> orderGoodsList = orderGoodsService.listByOrderId(orderId); - if(orderGoodsList!=null&&!orderGoodsList.isEmpty()){ - for(OrderGoods orderGoods : orderGoodsList){ + if (orderGoodsList != null && !orderGoodsList.isEmpty()) { + for (OrderGoods orderGoods : orderGoodsList) { //redis库存控制极简版 - String goodsLock = "goods_lock_"+order.getActivityId()+"_"+orderGoods.getGoodsId(); + String goodsLock = "goods_lock_" + order.getActivityId() + "_" + orderGoods.getGoodsId(); RLock redissonLock = redissonClient.getLock(goodsLock); - try{ + try { redissonLock.lock(30, TimeUnit.SECONDS); - Integer surpNum = redisService.getCacheObject(SecurityConstant.ACTIVITY_GOODS+"-"+order.getActivityId()+"-"+orderGoods.getGoodsId()); - redisService.setCacheObject(SecurityConstant.ACTIVITY_GOODS+"-"+order.getActivityId()+"-"+orderGoods.getGoodsId(),surpNum+orderGoods.getBuyNum()); - }finally{ + Integer surpNum = redisService.getCacheObject(SecurityConstant.ACTIVITY_GOODS + "-" + order.getActivityId() + "-" + orderGoods.getGoodsId()); + redisService.setCacheObject(SecurityConstant.ACTIVITY_GOODS + "-" + order.getActivityId() + "-" + orderGoods.getGoodsId(), surpNum + orderGoods.getBuyNum()); + } finally { redissonLock.unlock(); } //改变活动库存 @@ -4080,16 +4270,16 @@ remoteActivityService.delActivityRecord(activityRecord); } } - }else{ - if(order.getCouponMoney().compareTo(BigDecimal.ZERO)>0){ + } else { + if (order.getCouponMoney().compareTo(BigDecimal.ZERO) > 0) { //回退优惠券 List<OrderGoods> orderGoodsList = orderGoodsService.listByOrderId(orderId); - if(orderGoodsList!=null&&!orderGoodsList.isEmpty()) { + if (orderGoodsList != null && !orderGoodsList.isEmpty()) { StringJoiner memberCouponSJ = new StringJoiner(","); for (OrderGoods orderGoods : orderGoodsList) { memberCouponSJ.add(orderGoods.getCouponId()); } - if(memberCouponSJ!=null){ + if (memberCouponSJ != null) { remoteCouponService.backMemberCoupon(memberCouponSJ.toString()); } diff --git a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/order/OrderService.java b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/order/OrderService.java index 43878d1..1bf4cba 100644 --- a/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/order/OrderService.java +++ b/ruoyi-modules/ruoyi-order/src/main/java/com/ruoyi/order/service/order/OrderService.java @@ -2,6 +2,9 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; +import com.github.binarywang.wxpay.bean.ecommerce.PartnerTransactionsResult; +import com.github.binarywang.wxpay.bean.ecommerce.RefundNotifyResult; +import com.github.binarywang.wxpay.bean.profitsharingV3.ProfitSharingNotifyResult; import com.ruoyi.order.domain.dto.*; import com.ruoyi.order.domain.pojo.order.Order; import com.ruoyi.order.domain.vo.*; @@ -416,7 +419,7 @@ * @param Transaction transaction * @return void */ - void payBack(Transaction transaction); + void payBack(PartnerTransactionsResult transaction); /** * 取消订单 @@ -489,4 +492,16 @@ * @return void */ void checkOrderStatus(); + + /** + * 分账通知回调 + * @param result + */ + void profitSharingBack(ProfitSharingNotifyResult result); + + /** + * 订单退款回调 + * @param result + */ + void orderRefundBack(RefundNotifyResult result); } -- Gitblit v1.7.1