【同步】BOOT 和 CLOUD 的功能(PAY 相关功能)
This commit is contained in:
@@ -7,6 +7,9 @@ package cn.iocoder.yudao.module.trade.enums;
|
||||
*/
|
||||
public interface DictTypeConstants {
|
||||
|
||||
String BROKERAGE_RECORD_STATUS = "brokerage_record_status"; // 佣金记录状态
|
||||
|
||||
String BROKERAGE_WITHDRAW_TYPE = "brokerage_withdraw_type"; // 佣金提现类型
|
||||
String BROKERAGE_WITHDRAW_STATUS = "brokerage_withdraw_status"; // 佣金提现状态
|
||||
|
||||
}
|
||||
|
||||
@@ -36,8 +36,10 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode ORDER_UPDATE_ADDRESS_FAIL_STATUS_NOT_DELIVERED = new ErrorCode(1_011_000_031, "交易订单修改收货地址失败,原因:订单不是【待发货】状态");
|
||||
ErrorCode ORDER_CREATE_FAIL_EXIST_UNPAID = new ErrorCode(1_011_000_032, "交易订单创建失败,原因:存在未付款订单");
|
||||
ErrorCode ORDER_CANCEL_PAID_FAIL = new ErrorCode(1_011_000_033, "交易订单取消支付失败,原因:订单不是【{}】状态");
|
||||
ErrorCode ORDER_PICK_UP_FAIL_NOT_VERIFY_USER = new ErrorCode(1_011_000_034, "交易订单自提失败,原因:你没有核销该门店订单的权限");
|
||||
ErrorCode ORDER_CREATE_FAIL_INSUFFICIENT_USER_POINTS = new ErrorCode(1_011_000_035, "交易订单创建失败,原因:用户积分不足");
|
||||
ErrorCode ORDER_UPDATE_PAID_ORDER_REFUNDED_FAIL_REFUND_NOT_FOUND = new ErrorCode(1_011_000_034, "交易订单更新支付订单退款状态失败,原因:退款单不存在");
|
||||
ErrorCode ORDER_UPDATE_PAID_ORDER_REFUNDED_FAIL_REFUND_STATUS_NOT_SUCCESS = new ErrorCode(1_011_000_035, "交易订单更新支付订单退款状态失败,原因:退款单状态不是【退款成功】");
|
||||
ErrorCode ORDER_PICK_UP_FAIL_NOT_VERIFY_USER = new ErrorCode(1_011_000_036, "交易订单自提失败,原因:你没有核销该门店订单的权限");
|
||||
ErrorCode ORDER_CREATE_FAIL_INSUFFICIENT_USER_POINTS = new ErrorCode(1_011_000_037, "交易订单创建失败,原因:用户积分不足");
|
||||
|
||||
// ========== After Sale 模块 1-011-000-100 ==========
|
||||
ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1_011_000_100, "售后单不存在");
|
||||
@@ -51,9 +53,13 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode AFTER_SALE_DELIVERY_FAIL_STATUS_NOT_SELLER_AGREE = new ErrorCode(1_011_000_108, "退货失败,售后单状态不处于【待买家退货】");
|
||||
ErrorCode AFTER_SALE_CONFIRM_FAIL_STATUS_NOT_BUYER_DELIVERY = new ErrorCode(1_011_000_109, "确认收货失败,售后单状态不处于【待确认收货】");
|
||||
ErrorCode AFTER_SALE_REFUND_FAIL_STATUS_NOT_WAIT_REFUND = new ErrorCode(1_011_000_110, "退款失败,售后单状态不是【待退款】");
|
||||
ErrorCode AFTER_SALE_REFUND_FAIL_REFUND_NOT_FOUND = new ErrorCode(1_011_000_111, "退款失败,退款单不存在");
|
||||
ErrorCode AFTER_SALE_REFUND_FAIL_REFUND_NOT_SUCCESS_OR_FAILURE = new ErrorCode(1_011_000_112, "退款失败,退款单未退款");
|
||||
ErrorCode AFTER_SALE_REFUND_FAIL_REFUND_PRICE_NOT_MATCH = new ErrorCode(1_011_000_113, "退款失败,退款金额不匹配");
|
||||
ErrorCode AFTER_SALE_REFUND_FAIL_REFUND_ORDER_ID_ERROR = new ErrorCode(1_011_000_114, "退款失败,退款单不匹配");
|
||||
ErrorCode AFTER_SALE_CANCEL_FAIL_STATUS_NOT_APPLY_OR_AGREE_OR_BUYER_DELIVERY =
|
||||
new ErrorCode(1_011_000_111, "取消售后单失败,售后单状态不是【待审核】或【卖家同意】或【商家待收货】");
|
||||
ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_COMBINATION_IN_PROGRESS = new ErrorCode(1_011_000_112, "订单拼团中,无法申请售后");
|
||||
new ErrorCode(1_011_000_115, "取消售后单失败,售后单状态不是【待审核】或【卖家同意】或【商家待收货】");
|
||||
ErrorCode AFTER_SALE_CREATE_FAIL_ORDER_STATUS_COMBINATION_IN_PROGRESS = new ErrorCode(1_011_000_116, "订单拼团中,无法申请售后");
|
||||
|
||||
// ========== Cart 模块 1-011-002-000 ==========
|
||||
ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1_011_002_000, "购物车项不存在");
|
||||
@@ -101,5 +107,10 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING = new ErrorCode(1_011_008_001, "佣金提现记录状态不是审核中");
|
||||
ErrorCode BROKERAGE_WITHDRAW_MIN_PRICE = new ErrorCode(1_011_008_002, "提现金额不能低于 {} 元");
|
||||
ErrorCode BROKERAGE_WITHDRAW_USER_BALANCE_NOT_ENOUGH = new ErrorCode(1_011_008_003, "您当前最多可提现 {} 元");
|
||||
ErrorCode BROKERAGE_WITHDRAW_UPDATE_STATUS_FAIL_PAY_TRANSFER_ID_ERROR = new ErrorCode(1_011_008_005, "提现单更新转账状态失败,转账单不匹配");
|
||||
ErrorCode BROKERAGE_WITHDRAW_UPDATE_STATUS_FAIL_PAY_TRANSFER_STATUS_NOT_SUCCESS_OR_CLOSED = new ErrorCode(1_011_008_006, "提现单更新转账状态失败,转账单状态不是成功或关闭状态");
|
||||
ErrorCode BROKERAGE_WITHDRAW_UPDATE_STATUS_FAIL_PAY_PRICE_NOT_MATCH = new ErrorCode(1_011_008_007, "提现单更新转账状态失败,转账单金额不匹配");
|
||||
ErrorCode BROKERAGE_WITHDRAW_UPDATE_STATUS_FAIL_PAY_MERCHANT_EXISTS = new ErrorCode(1_011_008_008, "提现单更新转账状态失败,转账单的商户订单不匹配");
|
||||
ErrorCode BROKERAGE_WITHDRAW_UPDATE_STATUS_FAIL_PAY_CHANNEL_NOT_MATCH = new ErrorCode(1_011_008_009, "提现单更新转账状态失败,转账渠道不匹配");
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,9 @@ public enum AfterSaleOperateTypeEnum {
|
||||
MEMBER_DELIVERY(20, "会员填写退货物流信息,快递公司:{deliveryName},快递单号:{logisticsNo}"),
|
||||
ADMIN_AGREE_RECEIVE(21, "商家收货"),
|
||||
ADMIN_DISAGREE_RECEIVE(22, "商家拒绝收货,原因:{reason}"),
|
||||
ADMIN_REFUND(30, "商家退款"),
|
||||
ADMIN_REFUND(30, "商家发起退款"),
|
||||
SYSTEM_REFUND_SUCCESS(31, "退款成功"),
|
||||
SYSTEM_REFUND_FAIL(32, "退款失败"),
|
||||
MEMBER_CANCEL(40, "会员取消退款"),
|
||||
;
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
// TODO 芋艿:提现的打通,在纠结下;
|
||||
/**
|
||||
* 佣金提现状态枚举
|
||||
*
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.module.trade.enums.brokerage;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@@ -17,9 +18,10 @@ public enum BrokerageWithdrawTypeEnum implements ArrayValuable<Integer> {
|
||||
|
||||
WALLET(1, "钱包"),
|
||||
BANK(2, "银行卡"),
|
||||
WECHAT(3, "微信"), // 手动打款
|
||||
ALIPAY(4, "支付宝"),
|
||||
WECHAT_QR(3, "微信收款码"), // 手动打款
|
||||
ALIPAY_QR(4, "支付宝收款码"), // 手动打款
|
||||
WECHAT_API(5, "微信零钱"), // 自动打款,通过微信转账 API
|
||||
ALIPAY_API(6, "支付宝余额"), // 自动打款,通过支付宝转账 API
|
||||
;
|
||||
|
||||
public static final Integer[] ARRAYS = Arrays.stream(values()).map(BrokerageWithdrawTypeEnum::getType).toArray(Integer[]::new);
|
||||
@@ -45,7 +47,7 @@ public enum BrokerageWithdrawTypeEnum implements ArrayValuable<Integer> {
|
||||
* @return 是否
|
||||
*/
|
||||
public static boolean isApi(Integer type) {
|
||||
return WECHAT_API.getType().equals(type);
|
||||
return ObjectUtils.equalsAny(type, WALLET.getType(), ALIPAY_API.getType(), WECHAT_API.getType());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.module.trade.controller.admin.aftersale;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||
@@ -15,10 +16,12 @@ import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
|
||||
import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleLogService;
|
||||
import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleService;
|
||||
import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
|
||||
import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
@@ -46,6 +49,8 @@ public class AfterSaleController {
|
||||
@Resource
|
||||
private TradeOrderQueryService tradeOrderQueryService;
|
||||
@Resource
|
||||
private TradeOrderUpdateService tradeOrderUpdateService;
|
||||
@Resource
|
||||
private AfterSaleLogService afterSaleLogService;
|
||||
@Resource
|
||||
private MemberUserApi memberUserApi;
|
||||
@@ -133,11 +138,19 @@ public class AfterSaleController {
|
||||
|
||||
@PostMapping("/update-refunded")
|
||||
@Operation(summary = "更新售后订单为已退款") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob
|
||||
@PermitAll // 无需登录,安全由 PayDemoOrderService 内部校验实现
|
||||
public CommonResult<Boolean> updateAfterRefund(@RequestBody PayRefundNotifyReqDTO notifyReqDTO) {
|
||||
// 目前业务逻辑,不需要做任何事情
|
||||
// 当然,退款会有小概率会失败的情况,可以监控失败状态,进行告警
|
||||
@PermitAll // 无需登录,安全由 AfterSaleService 内部校验实现
|
||||
public CommonResult<Boolean> updateAfterSaleRefunded(@RequestBody PayRefundNotifyReqDTO notifyReqDTO) {
|
||||
log.info("[updateAfterRefund][notifyReqDTO({})]", notifyReqDTO);
|
||||
if (StrUtil.startWithAny(notifyReqDTO.getMerchantRefundId(), "order-")) {
|
||||
tradeOrderUpdateService.updatePaidOrderRefunded(
|
||||
Long.parseLong(notifyReqDTO.getMerchantRefundId()),
|
||||
notifyReqDTO.getPayRefundId());
|
||||
} else {
|
||||
afterSaleService.updateAfterSaleRefunded(
|
||||
Long.parseLong(notifyReqDTO.getMerchantRefundId()),
|
||||
Long.parseLong(notifyReqDTO.getMerchantOrderId()),
|
||||
notifyReqDTO.getPayRefundId());
|
||||
}
|
||||
return success(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -82,10 +82,9 @@ public class BrokerageWithdrawController {
|
||||
return success(BrokerageWithdrawConvert.INSTANCE.convertPage(pageResult, userMap));
|
||||
}
|
||||
|
||||
// TODO @luchi:update-transferred,url 改成这个。和 update-paid 、update-refunded 保持一致
|
||||
@PostMapping("/update-transfer")
|
||||
@Operation(summary = "更新转账订单为转账成功") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob
|
||||
@PermitAll // 无需登录,安全由 PayDemoOrderService 内部校验实现
|
||||
@PostMapping("/update-transferred")
|
||||
@Operation(summary = "更新佣金提现的转账结果") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob
|
||||
@PermitAll // 无需登录,安全由 BrokerageWithdrawService 内部校验实现
|
||||
public CommonResult<Boolean> updateBrokerageWithdrawTransferred(@RequestBody PayTransferNotifyReqDTO notifyReqDTO) {
|
||||
log.info("[updateAfterRefund][notifyReqDTO({})]", notifyReqDTO);
|
||||
brokerageWithdrawService.updateBrokerageWithdrawTransferred(
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
/**
|
||||
* 佣金提现 Base VO,提供给添加、修改、详细的子 VO 使用
|
||||
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
|
||||
*/
|
||||
@Data
|
||||
public class BrokerageWithdrawBaseVO {
|
||||
|
||||
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11436")
|
||||
@NotNull(message = "用户编号不能为空")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "提现金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "18781")
|
||||
@NotNull(message = "提现金额不能为空")
|
||||
private Integer price;
|
||||
|
||||
@Schema(description = "提现手续费", requiredMode = Schema.RequiredMode.REQUIRED, example = "11417")
|
||||
@NotNull(message = "提现手续费不能为空")
|
||||
private Integer feePrice;
|
||||
|
||||
@Schema(description = "当前总佣金", requiredMode = Schema.RequiredMode.REQUIRED, example = "18576")
|
||||
@NotNull(message = "当前总佣金不能为空")
|
||||
private Integer totalPrice;
|
||||
|
||||
@Schema(description = "提现类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "提现类型不能为空")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "真实姓名", example = "赵六")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "账号", example = "88677912132")
|
||||
private String accountNo;
|
||||
|
||||
@Schema(description = "银行名称", example = "1")
|
||||
private String bankName;
|
||||
|
||||
@Schema(description = "开户地址", example = "海淀支行")
|
||||
private String bankAddress;
|
||||
|
||||
@Schema(description = "收款码", example = "https://www.iocoder.cn")
|
||||
private String accountQrCodeUrl;
|
||||
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@NotNull(message = "状态不能为空")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "审核驳回原因", example = "不对")
|
||||
private String auditReason;
|
||||
|
||||
@Schema(description = "审核时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime auditTime;
|
||||
|
||||
@Schema(description = "备注", example = "随便")
|
||||
private String remark;
|
||||
|
||||
}
|
||||
@@ -28,10 +28,10 @@ public class BrokerageWithdrawPageReqVO extends PageParam {
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "真实姓名", example = "赵六")
|
||||
private String name;
|
||||
private String userName;
|
||||
|
||||
@Schema(description = "账号", example = "886779132")
|
||||
private String accountNo;
|
||||
private String userAccount;
|
||||
|
||||
@Schema(description = "银行名称", example = "1")
|
||||
private String bankName;
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import lombok.ToString;
|
||||
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
@Schema(description = "管理后台 - 驳回申请 Request VO")
|
||||
@Data
|
||||
@ToString(callSuper = true)
|
||||
|
||||
@@ -2,24 +2,68 @@ package cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 佣金提现 Response VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class BrokerageWithdrawRespVO extends BrokerageWithdrawBaseVO {
|
||||
public class BrokerageWithdrawRespVO {
|
||||
|
||||
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "7161")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11436")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
|
||||
private String userNickname;
|
||||
|
||||
@Schema(description = "提现金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "18781")
|
||||
private Integer price;
|
||||
|
||||
@Schema(description = "提现手续费", requiredMode = Schema.RequiredMode.REQUIRED, example = "11417")
|
||||
private Integer feePrice;
|
||||
|
||||
@Schema(description = "当前总佣金", requiredMode = Schema.RequiredMode.REQUIRED, example = "18576")
|
||||
private Integer totalPrice;
|
||||
|
||||
@Schema(description = "提现类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "真实姓名", example = "赵六")
|
||||
private String userName;
|
||||
|
||||
@Schema(description = "收款账号", example = "88677912132")
|
||||
private String userAccount;
|
||||
|
||||
@Schema(description = "银行名称", example = "1")
|
||||
private String bankName;
|
||||
|
||||
@Schema(description = "开户地址", example = "海淀支行")
|
||||
private String bankAddress;
|
||||
|
||||
@Schema(description = "收款码", example = "https://www.iocoder.cn")
|
||||
private String qrCodeUrl;
|
||||
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "审核驳回原因", example = "不对")
|
||||
private String auditReason;
|
||||
|
||||
@Schema(description = "审核时间")
|
||||
private LocalDateTime auditTime;
|
||||
|
||||
@Schema(description = "备注", example = "随便")
|
||||
private String remark;
|
||||
|
||||
@Schema(description = "转账单编号", example = "1024")
|
||||
private Long payTransferId;
|
||||
|
||||
@Schema(description = "转账错误提示", example = "余额不足")
|
||||
private String transferErrorMsg;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
}
|
||||
|
||||
@@ -3,14 +3,18 @@ package cn.iocoder.yudao.module.trade.controller.app.brokerage;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record.BrokerageRecordPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageProductPriceRespVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordRespVO;
|
||||
import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageRecordConvert;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO;
|
||||
import cn.iocoder.yudao.module.trade.enums.DictTypeConstants;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -18,9 +22,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
|
||||
|
||||
@@ -38,8 +39,9 @@ public class AppBrokerageRecordController {
|
||||
@Operation(summary = "获得分销记录分页")
|
||||
public CommonResult<PageResult<AppBrokerageRecordRespVO>> getBrokerageRecordPage(@Valid AppBrokerageRecordPageReqVO pageReqVO) {
|
||||
PageResult<BrokerageRecordDO> pageResult = brokerageRecordService.getBrokerageRecordPage(
|
||||
BrokerageRecordConvert.INSTANCE.convert(pageReqVO, getLoginUserId()));
|
||||
return success(BeanUtils.toBean(pageResult, AppBrokerageRecordRespVO.class));
|
||||
BeanUtils.toBean(pageReqVO, BrokerageRecordPageReqVO.class).setUserId(getLoginUserId()));
|
||||
return success(BeanUtils.toBean(pageResult, AppBrokerageRecordRespVO.class, recordVO ->
|
||||
recordVO.setStatusName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.BROKERAGE_RECORD_STATUS, recordVO.getStatus()))));
|
||||
}
|
||||
|
||||
@GetMapping("/get-product-brokerage-price")
|
||||
@@ -48,4 +50,4 @@ public class AppBrokerageRecordController {
|
||||
return success(brokerageRecordService.calculateProductBrokeragePrice(getLoginUserId(), spuId));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,31 @@
|
||||
package cn.iocoder.yudao.module.trade.controller.app.brokerage;
|
||||
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.PayTransferApi;
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawCreateReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawRespVO;
|
||||
import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageWithdrawConvert;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO;
|
||||
import cn.iocoder.yudao.module.trade.enums.DictTypeConstants;
|
||||
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageWithdrawService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import java.util.Objects;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
|
||||
@@ -30,12 +40,39 @@ public class AppBrokerageWithdrawController {
|
||||
@Resource
|
||||
private BrokerageWithdrawService brokerageWithdrawService;
|
||||
|
||||
@Resource
|
||||
private PayTransferApi payTransferApi;
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得分销提现分页")
|
||||
public CommonResult<PageResult<AppBrokerageWithdrawRespVO>> getBrokerageWithdrawPage(AppBrokerageWithdrawPageReqVO pageReqVO) {
|
||||
PageResult<BrokerageWithdrawDO> pageResult = brokerageWithdrawService.getBrokerageWithdrawPage(
|
||||
BrokerageWithdrawConvert.INSTANCE.convert(pageReqVO, getLoginUserId()));
|
||||
return success(BrokerageWithdrawConvert.INSTANCE.convertPage03(pageResult));
|
||||
BeanUtils.toBean(pageReqVO, BrokerageWithdrawPageReqVO.class).setUserId(getLoginUserId()));
|
||||
return success(BeanUtils.toBean(pageResult, AppBrokerageWithdrawRespVO.class, withdrawVO ->
|
||||
withdrawVO.setTypeName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.BROKERAGE_WITHDRAW_TYPE, withdrawVO.getType()))
|
||||
.setStatusName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.BROKERAGE_WITHDRAW_STATUS, withdrawVO.getStatus()))));
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得佣金提现")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
public CommonResult<AppBrokerageWithdrawRespVO> getBrokerageWithdraw(@RequestParam("id") Long id) {
|
||||
BrokerageWithdrawDO withdraw = brokerageWithdrawService.getBrokerageWithdraw(id);
|
||||
if (withdraw == null || ObjUtil.notEqual(withdraw.getUserId(), getLoginUserId())) {
|
||||
return success(null);
|
||||
}
|
||||
// 审核中(转账中),并且是微信转账,需要返回 mchId 用于确认收款
|
||||
AppBrokerageWithdrawRespVO withdrawVO = BeanUtils.toBean(withdraw, AppBrokerageWithdrawRespVO.class);
|
||||
if (Objects.equals(withdraw.getStatus(), BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.getStatus())
|
||||
&& Objects.equals(withdraw.getType(), BrokerageWithdrawTypeEnum.WECHAT_API.getType())
|
||||
&& withdraw.getPayTransferId() != null) {
|
||||
PayTransferRespDTO transfer = payTransferApi.getTransfer(withdraw.getPayTransferId()).getCheckedData();
|
||||
if (transfer != null) {
|
||||
withdrawVO.setTransferChannelPackageInfo(transfer.getChannelPackageInfo())
|
||||
.setTransferChannelMchId(transfer.getChannelMchId());
|
||||
}
|
||||
}
|
||||
return success(withdrawVO);
|
||||
}
|
||||
|
||||
@PostMapping("/create")
|
||||
|
||||
@@ -20,11 +20,11 @@ public class AppBrokerageRecordPageReqVO extends PageParam {
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
@Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@Schema(description = "业务类型", example = "1")
|
||||
@InEnum(value = BrokerageRecordBizTypeEnum.class, message = "业务类型必须是 {value}")
|
||||
private Integer bizType;
|
||||
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@Schema(description = "状态", example = "1")
|
||||
@InEnum(value = BrokerageRecordStatusEnum.class, message = "状态必须是 {value}")
|
||||
private Integer status;
|
||||
|
||||
|
||||
@@ -24,6 +24,9 @@ public class AppBrokerageRecordRespVO {
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "状态名", requiredMode = Schema.RequiredMode.REQUIRED, example = "待结算")
|
||||
private String statusName;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
|
||||
@@ -2,8 +2,10 @@ package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.PayChannelEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.URL;
|
||||
|
||||
@@ -22,42 +24,49 @@ public class AppBrokerageWithdrawCreateReqVO {
|
||||
|
||||
@Schema(description = "提现金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
|
||||
@PositiveOrZero(message = "提现金额不能小于 0")
|
||||
@Min(value = 30, message = "微信提现金额不能小于 0.3", groups = {WechatApi.class})
|
||||
@NotNull(message = "提现金额不能为空")
|
||||
private Integer price;
|
||||
|
||||
// ========== 银行卡、微信、支付宝 提现相关字段 ==========
|
||||
|
||||
@Schema(description = "提现账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456789")
|
||||
@NotBlank(message = "提现账号不能为空", groups = {Bank.class, Wechat.class, Alipay.class})
|
||||
private String accountNo;
|
||||
@NotBlank(message = "提现账号不能为空", groups = {Bank.class, WechatApi.class, AlipayApi.class})
|
||||
private String userAccount;
|
||||
|
||||
// ========== 微信、支付宝 提现相关字段 ==========
|
||||
@Schema(description = "提现姓名", example = "张三")
|
||||
@NotBlank(message = "提现姓名不能为空", groups = {Bank.class, WechatApi.class, AlipayApi.class})
|
||||
private String userName;
|
||||
|
||||
@Schema(description = "收款码的图片", example = "https://www.iocoder.cn/1.png")
|
||||
@URL(message = "收款码的图片,必须是一个 URL")
|
||||
private String accountQrCodeUrl;
|
||||
@URL(message = "收款码的图片,必须是一个 URL", groups = {WechatQR.class, AlipayQR.class})
|
||||
private String qrCodeUrl;
|
||||
|
||||
// ========== 银行卡 提现相关字段 ==========
|
||||
|
||||
@Schema(description = "持卡人姓名", example = "张三")
|
||||
@NotBlank(message = "持卡人姓名不能为空", groups = {Bank.class})
|
||||
private String name;
|
||||
@Schema(description = "提现银行", example = "1")
|
||||
@NotNull(message = "提现银行不能为空", groups = {Bank.class})
|
||||
private String bankName;
|
||||
@Schema(description = "开户地址", example = "海淀支行")
|
||||
private String bankAddress;
|
||||
|
||||
@Schema(description = "转账渠道", example = "wx_lite")
|
||||
@NotNull(message = "转账渠道不能为空", groups = {WechatApi.class})
|
||||
@InEnum(PayChannelEnum.class)
|
||||
private String transferChannelCode;
|
||||
|
||||
public interface Wallet {
|
||||
}
|
||||
|
||||
public interface Bank {
|
||||
}
|
||||
|
||||
public interface Wechat {
|
||||
public interface WechatQR {
|
||||
}
|
||||
|
||||
public interface Alipay {
|
||||
public interface WechatApi {
|
||||
}
|
||||
|
||||
public interface AlipayQR {
|
||||
}
|
||||
|
||||
public interface AlipayApi {
|
||||
}
|
||||
|
||||
public void validate(Validator validator) {
|
||||
@@ -65,10 +74,14 @@ public class AppBrokerageWithdrawCreateReqVO {
|
||||
ValidationUtils.validate(validator, this, Wallet.class);
|
||||
} else if (BrokerageWithdrawTypeEnum.BANK.getType().equals(type)) {
|
||||
ValidationUtils.validate(validator, this, Bank.class);
|
||||
} else if (BrokerageWithdrawTypeEnum.WECHAT.getType().equals(type)) {
|
||||
ValidationUtils.validate(validator, this, Wechat.class);
|
||||
} else if (BrokerageWithdrawTypeEnum.ALIPAY.getType().equals(type)) {
|
||||
ValidationUtils.validate(validator, this, Alipay.class);
|
||||
} else if (BrokerageWithdrawTypeEnum.WECHAT_QR.getType().equals(type)) {
|
||||
ValidationUtils.validate(validator, this, WechatQR.class);
|
||||
} else if (BrokerageWithdrawTypeEnum.WECHAT_API.getType().equals(type)) {
|
||||
ValidationUtils.validate(validator, this, WechatApi.class);
|
||||
} else if (BrokerageWithdrawTypeEnum.ALIPAY_QR.getType().equals(type)) {
|
||||
ValidationUtils.validate(validator, this, AlipayQR.class);
|
||||
} else if (BrokerageWithdrawTypeEnum.ALIPAY_API.getType().equals(type)) {
|
||||
ValidationUtils.validate(validator, this, AlipayApi.class);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
package cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "应用 App - 分销提现分页 Request VO")
|
||||
@Data
|
||||
public class AppBrokerageWithdrawPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@InEnum(value = BrokerageWithdrawTypeEnum.class, message = "类型必须是 {value}")
|
||||
private Integer type;
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
@InEnum(value = BrokerageWithdrawStatusEnum.class, message = "状态必须是 {value}")
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
|
||||
@@ -12,6 +12,12 @@ public class AppBrokerageWithdrawRespVO {
|
||||
@Schema(description = "提现编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "提现类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "提现类型名", requiredMode = Schema.RequiredMode.REQUIRED, example = "微信")
|
||||
private String typeName;
|
||||
|
||||
@Schema(description = "提现状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
private Integer status;
|
||||
|
||||
@@ -24,4 +30,15 @@ public class AppBrokerageWithdrawRespVO {
|
||||
@Schema(description = "提现时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
// ========== 微信转账专属 ==========
|
||||
|
||||
@Schema(description = "转账单编号", example = "1024")
|
||||
private Long payTransferId;
|
||||
|
||||
@Schema(description = "渠道 package 信息")
|
||||
private String transferChannelPackageInfo;
|
||||
|
||||
@Schema(description = "渠道商户号")
|
||||
private String transferChannelMchId;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
package cn.iocoder.yudao.module.trade.convert.brokerage;
|
||||
|
||||
import cn.hutool.core.math.Money;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
|
||||
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record.BrokerageRecordPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.record.BrokerageRecordRespVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.record.AppBrokerageRecordRespVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.user.AppBrokerageUserRankByPriceRespVO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageRecordDO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageUserDO;
|
||||
@@ -68,8 +64,6 @@ public interface BrokerageRecordConvert {
|
||||
return result;
|
||||
}
|
||||
|
||||
BrokerageRecordPageReqVO convert(AppBrokerageRecordPageReqVO pageReqVO, Long userId);
|
||||
|
||||
default PageResult<AppBrokerageUserRankByPriceRespVO> convertPage03(PageResult<AppBrokerageUserRankByPriceRespVO> pageResult, Map<Long, MemberUserRespDTO> userMap) {
|
||||
for (AppBrokerageUserRankByPriceRespVO vo : pageResult.getList()) {
|
||||
copyTo(userMap.get(vo.getId()), vo);
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
package cn.iocoder.yudao.module.trade.convert.brokerage;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
|
||||
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawRespVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawCreateReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawRespVO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO;
|
||||
import cn.iocoder.yudao.module.trade.enums.DictTypeConstants;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@@ -27,8 +21,6 @@ public interface BrokerageWithdrawConvert {
|
||||
|
||||
BrokerageWithdrawConvert INSTANCE = Mappers.getMapper(BrokerageWithdrawConvert.class);
|
||||
|
||||
BrokerageWithdrawDO convert(AppBrokerageWithdrawCreateReqVO createReqVO, Long userId, Integer feePrice);
|
||||
|
||||
BrokerageWithdrawRespVO convert(BrokerageWithdrawDO bean);
|
||||
|
||||
List<BrokerageWithdrawRespVO> convertList(List<BrokerageWithdrawDO> list);
|
||||
@@ -43,15 +35,4 @@ public interface BrokerageWithdrawConvert {
|
||||
return result;
|
||||
}
|
||||
|
||||
PageResult<AppBrokerageWithdrawRespVO> convertPage02(PageResult<BrokerageWithdrawDO> pageResult);
|
||||
|
||||
default PageResult<AppBrokerageWithdrawRespVO> convertPage03(PageResult<BrokerageWithdrawDO> pageResult) {
|
||||
PageResult<AppBrokerageWithdrawRespVO> result = convertPage02(pageResult);
|
||||
for (AppBrokerageWithdrawRespVO vo : result.getList()) {
|
||||
vo.setStatusName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.BROKERAGE_WITHDRAW_STATUS, vo.getStatus()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
BrokerageWithdrawPageReqVO convert(AppBrokerageWithdrawPageReqVO pageReqVO, Long userId);
|
||||
}
|
||||
|
||||
@@ -57,13 +57,25 @@ public class BrokerageWithdrawDO extends BaseDO {
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 真实姓名
|
||||
* 提现姓名
|
||||
* 1. {@link BrokerageWithdrawTypeEnum#BANK}:银行开户人
|
||||
* 2. {@link BrokerageWithdrawTypeEnum#WECHAT_API}:微信真名
|
||||
* 3. {@link BrokerageWithdrawTypeEnum#ALIPAY_API}:支付宝真名
|
||||
*/
|
||||
private String name;
|
||||
private String userName;
|
||||
/**
|
||||
* 账号
|
||||
* 提现账号
|
||||
* 1. {@link BrokerageWithdrawTypeEnum#BANK}:银行账号
|
||||
* 2. {@link BrokerageWithdrawTypeEnum#WECHAT_API}:微信 openid
|
||||
* 3. {@link BrokerageWithdrawTypeEnum#ALIPAY_API}:支付宝账号
|
||||
*/
|
||||
private String accountNo;
|
||||
private String userAccount;
|
||||
|
||||
/**
|
||||
* 收款码
|
||||
*/
|
||||
private String qrCodeUrl;
|
||||
|
||||
/**
|
||||
* 银行名称
|
||||
*/
|
||||
@@ -72,10 +84,7 @@ public class BrokerageWithdrawDO extends BaseDO {
|
||||
* 开户地址
|
||||
*/
|
||||
private String bankAddress;
|
||||
/**
|
||||
* 收款码
|
||||
*/
|
||||
private String accountQrCodeUrl;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
* <p>
|
||||
@@ -95,4 +104,27 @@ public class BrokerageWithdrawDO extends BaseDO {
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
// ========== 转账相关字段 ==========
|
||||
|
||||
/**
|
||||
* 转账单编号
|
||||
*
|
||||
* 关联 {@link cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO#getId()}
|
||||
*/
|
||||
private Long payTransferId;
|
||||
/**
|
||||
* 转账渠道
|
||||
*
|
||||
* 枚举 {@link cn.iocoder.yudao.module.pay.enums.PayChannelEnum}
|
||||
*/
|
||||
private String transferChannelCode;
|
||||
/**
|
||||
* 转账成功时间
|
||||
*/
|
||||
private LocalDateTime transferTime;
|
||||
/**
|
||||
* 转账错误提示
|
||||
*/
|
||||
private String transferErrorMsg;
|
||||
|
||||
}
|
||||
|
||||
@@ -27,18 +27,18 @@ public interface BrokerageWithdrawMapper extends BaseMapperX<BrokerageWithdrawDO
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<BrokerageWithdrawDO>()
|
||||
.eqIfPresent(BrokerageWithdrawDO::getUserId, reqVO.getUserId())
|
||||
.eqIfPresent(BrokerageWithdrawDO::getType, reqVO.getType())
|
||||
.likeIfPresent(BrokerageWithdrawDO::getName, reqVO.getName())
|
||||
.eqIfPresent(BrokerageWithdrawDO::getAccountNo, reqVO.getAccountNo())
|
||||
.likeIfPresent(BrokerageWithdrawDO::getUserName, reqVO.getUserName())
|
||||
.likeIfPresent(BrokerageWithdrawDO::getUserAccount, reqVO.getUserAccount())
|
||||
.likeIfPresent(BrokerageWithdrawDO::getBankName, reqVO.getBankName())
|
||||
.eqIfPresent(BrokerageWithdrawDO::getStatus, reqVO.getStatus())
|
||||
.betweenIfPresent(BrokerageWithdrawDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByAsc(BrokerageWithdrawDO::getStatus).orderByDesc(BrokerageWithdrawDO::getId));
|
||||
.orderByDesc(BrokerageWithdrawDO::getId));
|
||||
}
|
||||
|
||||
default int updateByIdAndStatus(Long id, Integer status, BrokerageWithdrawDO updateObj) {
|
||||
default int updateByIdAndStatus(Long id, Integer whereStatus, BrokerageWithdrawDO updateObj) {
|
||||
return update(updateObj, new LambdaUpdateWrapper<BrokerageWithdrawDO>()
|
||||
.eq(BrokerageWithdrawDO::getId, id)
|
||||
.eq(BrokerageWithdrawDO::getStatus, status));
|
||||
.eq(BrokerageWithdrawDO::getStatus, whereStatus));
|
||||
}
|
||||
|
||||
default List<BrokerageWithdrawSummaryRespBO> selectCountAndSumPriceByUserIdAndStatus(Collection<Long> userIds,
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
package cn.iocoder.yudao.module.trade.framework.aftersale.core.aop;
|
||||
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderLogDO;
|
||||
import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleOperateTypeEnum;
|
||||
import cn.iocoder.yudao.module.trade.framework.aftersale.core.annotations.AfterSaleLog;
|
||||
import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleLogService;
|
||||
import cn.iocoder.yudao.module.trade.service.aftersale.bo.AfterSaleLogCreateReqBO;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.AfterReturning;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
|
||||
@@ -50,6 +52,10 @@ public class AfterSaleLogAspect {
|
||||
* 操作后的状态
|
||||
*/
|
||||
private static final ThreadLocal<Integer> AFTER_STATUS = new ThreadLocal<>();
|
||||
/**
|
||||
* 操作类型(仅“动态场景”需要使用)
|
||||
*/
|
||||
private static final ThreadLocal<AfterSaleOperateTypeEnum> OPERATE_TYPE = new ThreadLocal<>();
|
||||
/**
|
||||
* 拓展参数 Map,用于格式化操作内容
|
||||
*/
|
||||
@@ -69,6 +75,7 @@ public class AfterSaleLogAspect {
|
||||
if (afterSaleId == null) { // 如果未设置,只有注解,说明不需要记录日志
|
||||
return;
|
||||
}
|
||||
AfterSaleOperateTypeEnum operateType = ObjUtil.defaultIfNull(OPERATE_TYPE.get(), afterSaleLog.operateType());
|
||||
Integer beforeStatus = BEFORE_STATUS.get();
|
||||
Integer afterStatus = AFTER_STATUS.get();
|
||||
Map<String, Object> exts = ObjectUtil.defaultIfNull(EXTS.get(), emptyMap());
|
||||
@@ -78,7 +85,7 @@ public class AfterSaleLogAspect {
|
||||
AfterSaleLogCreateReqBO createBO = new AfterSaleLogCreateReqBO()
|
||||
.setUserId(userId).setUserType(userType)
|
||||
.setAfterSaleId(afterSaleId).setBeforeStatus(beforeStatus).setAfterStatus(afterStatus)
|
||||
.setOperateType(afterSaleLog.operateType().getType()).setContent(content);
|
||||
.setOperateType(operateType.getType()).setContent(content);
|
||||
afterSaleLogService.createAfterSaleLog(createBO);
|
||||
} catch (Exception exception) {
|
||||
log.error("[doAfterReturning][afterSaleLog({}) 日志记录错误]", toJsonString(afterSaleLog), exception);
|
||||
@@ -116,6 +123,10 @@ public class AfterSaleLogAspect {
|
||||
EXTS.set(exts);
|
||||
}
|
||||
|
||||
public static void setAfterSaleOperateType(AfterSaleOperateTypeEnum operateType) {
|
||||
OPERATE_TYPE.set(operateType);
|
||||
}
|
||||
|
||||
public static void setUserInfo(Long userId, Integer userType) {
|
||||
USER_ID.set(userId);
|
||||
USER_TYPE.set(userType);
|
||||
@@ -127,6 +138,7 @@ public class AfterSaleLogAspect {
|
||||
AFTER_SALE_ID.remove();
|
||||
BEFORE_STATUS.remove();
|
||||
AFTER_STATUS.remove();
|
||||
OPERATE_TYPE.remove();
|
||||
EXTS.remove();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.module.trade.framework.aftersale.core.utils;
|
||||
|
||||
|
||||
import cn.iocoder.yudao.module.trade.enums.aftersale.AfterSaleOperateTypeEnum;
|
||||
import cn.iocoder.yudao.module.trade.framework.aftersale.core.aop.AfterSaleLogAspect;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -13,6 +14,10 @@ import java.util.Map;
|
||||
*/
|
||||
public class AfterSaleLogUtils {
|
||||
|
||||
public static void setAfterSaleOperateType(AfterSaleOperateTypeEnum operateType) {
|
||||
AfterSaleLogAspect.setAfterSaleOperateType(operateType);
|
||||
}
|
||||
|
||||
public static void setAfterSaleInfo(Long id, Integer beforeStatus, Integer afterStatus) {
|
||||
setAfterSaleInfo(id, beforeStatus, afterStatus, null);
|
||||
}
|
||||
|
||||
@@ -108,6 +108,15 @@ public interface AfterSaleService {
|
||||
*/
|
||||
void refundAfterSale(Long userId, String userIp, Long id);
|
||||
|
||||
/**
|
||||
* 更新售后订单为已退款
|
||||
*
|
||||
* @param id 售后编号
|
||||
* @param orderId 订单编号
|
||||
* @param payRefundId 支付退款编号
|
||||
*/
|
||||
void updateAfterSaleRefunded(Long id, Long orderId, Long payRefundId);
|
||||
|
||||
/**
|
||||
* 【会员】取消售后
|
||||
*
|
||||
|
||||
@@ -7,6 +7,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi;
|
||||
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
|
||||
import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi;
|
||||
import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum;
|
||||
@@ -41,13 +43,12 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.TransactionSynchronization;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
|
||||
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
@@ -184,8 +185,6 @@ public class AfterSaleServiceImpl implements AfterSaleService {
|
||||
// 记录售后日志
|
||||
AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), null,
|
||||
AfterSaleStatusEnum.APPLY.getStatus());
|
||||
|
||||
// TODO 发送售后消息
|
||||
return afterSale;
|
||||
}
|
||||
|
||||
@@ -206,8 +205,6 @@ public class AfterSaleServiceImpl implements AfterSaleService {
|
||||
|
||||
// 记录售后日志
|
||||
AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(), newStatus);
|
||||
|
||||
// TODO 发送售后消息
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -226,8 +223,6 @@ public class AfterSaleServiceImpl implements AfterSaleService {
|
||||
// 记录售后日志
|
||||
AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(), newStatus);
|
||||
|
||||
// TODO 发送售后消息
|
||||
|
||||
// 更新交易订单项的售后状态为【未申请】
|
||||
tradeOrderUpdateService.updateOrderItemWhenAfterSaleCancel(afterSale.getOrderItemId());
|
||||
}
|
||||
@@ -281,8 +276,6 @@ public class AfterSaleServiceImpl implements AfterSaleService {
|
||||
AfterSaleStatusEnum.BUYER_DELIVERY.getStatus(),
|
||||
MapUtil.<String, Object>builder().put("deliveryName", express.getName())
|
||||
.put("logisticsNo", deliveryReqVO.getLogisticsNo()).build());
|
||||
|
||||
// TODO 发送售后消息
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -299,8 +292,6 @@ public class AfterSaleServiceImpl implements AfterSaleService {
|
||||
// 记录售后日志
|
||||
AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(),
|
||||
AfterSaleStatusEnum.WAIT_REFUND.getStatus());
|
||||
|
||||
// TODO 发送售后消息
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -326,8 +317,6 @@ public class AfterSaleServiceImpl implements AfterSaleService {
|
||||
AfterSaleStatusEnum.SELLER_REFUSE.getStatus(),
|
||||
MapUtil.of("reason", refuseReqVO.getRefuseMemo()));
|
||||
|
||||
// TODO 发送售后消息
|
||||
|
||||
// 更新交易订单项的售后状态为【未申请】
|
||||
tradeOrderUpdateService.updateOrderItemWhenAfterSaleCancel(afterSale.getOrderItemId());
|
||||
}
|
||||
@@ -365,33 +354,90 @@ public class AfterSaleServiceImpl implements AfterSaleService {
|
||||
// 发起退款单。注意,需要在事务提交后,再进行发起,避免重复发起
|
||||
createPayRefund(userIp, afterSale);
|
||||
|
||||
// 更新售后单的状态为【已完成】
|
||||
updateAfterSaleStatus(afterSale.getId(), AfterSaleStatusEnum.WAIT_REFUND.getStatus(), new AfterSaleDO()
|
||||
.setStatus(AfterSaleStatusEnum.COMPLETE.getStatus()).setRefundTime(LocalDateTime.now()));
|
||||
|
||||
// 记录售后日志
|
||||
AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(),
|
||||
AfterSaleStatusEnum.COMPLETE.getStatus());
|
||||
|
||||
// TODO 发送售后消息
|
||||
|
||||
// 更新交易订单项的售后状态为【已完成】
|
||||
tradeOrderUpdateService.updateOrderItemWhenAfterSaleSuccess(afterSale.getOrderItemId(), afterSale.getRefundPrice());
|
||||
afterSale.getStatus()); // 特殊:这里状态不变,而是最终 updateAfterSaleRefunded 处理!!!
|
||||
}
|
||||
|
||||
private void createPayRefund(String userIp, AfterSaleDO afterSale) {
|
||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
||||
// 创建退款单
|
||||
PayRefundCreateReqDTO createReqDTO = AfterSaleConvert.INSTANCE.convert(userIp, afterSale, tradeOrderProperties)
|
||||
.setReason(StrUtil.format("退款【{}】", afterSale.getSpuName()));
|
||||
Long payRefundId = payRefundApi.createRefund(createReqDTO).getCheckedData();
|
||||
|
||||
@Override
|
||||
public void afterCommit() {
|
||||
// 创建退款单
|
||||
PayRefundCreateReqDTO createReqDTO = AfterSaleConvert.INSTANCE.convert(userIp, afterSale, tradeOrderProperties)
|
||||
.setReason(StrUtil.format("退款【{}】", afterSale.getSpuName()));
|
||||
Long payRefundId = payRefundApi.createRefund(createReqDTO).getCheckedData();
|
||||
// 更新售后单的退款单号
|
||||
tradeAfterSaleMapper.updateById(new AfterSaleDO().setId(afterSale.getId()).setPayRefundId(payRefundId));
|
||||
}
|
||||
});
|
||||
// 更新售后单的退款单号
|
||||
tradeAfterSaleMapper.updateById(new AfterSaleDO().setId(afterSale.getId()).setPayRefundId(payRefundId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@AfterSaleLog(operateType = AfterSaleOperateTypeEnum.SYSTEM_REFUND_SUCCESS)
|
||||
public void updateAfterSaleRefunded(Long id, Long orderId, Long payRefundId) {
|
||||
// 1. 校验售后单的状态,并状态待退款
|
||||
AfterSaleDO afterSale = tradeAfterSaleMapper.selectById(id);
|
||||
if (afterSale == null) {
|
||||
throw exception(AFTER_SALE_NOT_FOUND);
|
||||
}
|
||||
if (ObjectUtil.notEqual(afterSale.getStatus(), AfterSaleStatusEnum.WAIT_REFUND.getStatus())) {
|
||||
throw exception(AFTER_SALE_REFUND_FAIL_STATUS_NOT_WAIT_REFUND);
|
||||
}
|
||||
|
||||
// 2. 校验退款单
|
||||
PayRefundRespDTO payRefund = validatePayRefund(afterSale, payRefundId);
|
||||
|
||||
// 3. 处理退款结果
|
||||
if (PayRefundStatusEnum.isSuccess(payRefund.getStatus())) {
|
||||
// 【情况一:退款成功】
|
||||
updateAfterSaleStatus(afterSale.getId(), AfterSaleStatusEnum.WAIT_REFUND.getStatus(), new AfterSaleDO()
|
||||
.setStatus(AfterSaleStatusEnum.COMPLETE.getStatus()).setRefundTime(LocalDateTime.now()));
|
||||
|
||||
// 记录售后日志
|
||||
AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(), AfterSaleStatusEnum.COMPLETE.getStatus());
|
||||
|
||||
// 更新交易订单项的售后状态为【已完成】
|
||||
tradeOrderUpdateService.updateOrderItemWhenAfterSaleSuccess(afterSale.getOrderItemId(), afterSale.getRefundPrice());
|
||||
// 【情况二:退款失败】
|
||||
} else if (PayRefundStatusEnum.isFailure(payRefund.getStatus())) {
|
||||
// 记录售后日志
|
||||
AfterSaleLogUtils.setAfterSaleOperateType(AfterSaleOperateTypeEnum.SYSTEM_REFUND_FAIL);
|
||||
AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(), afterSale.getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验退款单的合法性
|
||||
*
|
||||
* @param afterSale 售后单
|
||||
* @param payRefundId 退款单编号
|
||||
* @return 退款单
|
||||
*/
|
||||
private PayRefundRespDTO validatePayRefund(AfterSaleDO afterSale, Long payRefundId) {
|
||||
// 1. 校验退款单是否存在
|
||||
PayRefundRespDTO payRefund = payRefundApi.getRefund(payRefundId).getCheckedData();
|
||||
if (payRefund == null) {
|
||||
log.error("[validatePayRefund][afterSale({}) payRefund({}) 不存在,请进行处理!]", afterSale.getId(), payRefundId);
|
||||
throw exception(AFTER_SALE_REFUND_FAIL_REFUND_NOT_FOUND);
|
||||
}
|
||||
// 2.1 校验退款单无退款结果(成功、失败)
|
||||
if (!PayRefundStatusEnum.isSuccess(payRefund.getStatus())
|
||||
&& !PayRefundStatusEnum.isFailure(payRefund.getStatus())) {
|
||||
log.error("[validatePayRefund][afterSale({}) payRefund({}) 无退款结果,请进行处理!payRefund 数据是:{}]",
|
||||
afterSale.getId(), payRefundId, toJsonString(payRefund));
|
||||
throw exception(AFTER_SALE_REFUND_FAIL_REFUND_NOT_SUCCESS_OR_FAILURE);
|
||||
}
|
||||
// 2.2 校验退款金额一致
|
||||
if (ObjectUtil.notEqual(payRefund.getRefundPrice(), afterSale.getRefundPrice())) {
|
||||
log.error("[validatePayRefund][afterSale({}) payRefund({}) 退款金额不匹配,请进行处理!afterSale 数据是:{},payRefund 数据是:{}]",
|
||||
afterSale.getId(), payRefundId, toJsonString(afterSale), toJsonString(payRefund));
|
||||
throw exception(AFTER_SALE_REFUND_FAIL_REFUND_PRICE_NOT_MATCH);
|
||||
}
|
||||
// 2.3 校验退款订单匹配(二次)
|
||||
if (ObjectUtil.notEqual(payRefund.getMerchantRefundId(), afterSale.getId().toString())) {
|
||||
log.error("[validatePayRefund][afterSale({}) 退款单不匹配({}),请进行处理!payRefund 数据是:{}]",
|
||||
afterSale.getId(), payRefundId, toJsonString(payRefund));
|
||||
throw exception(AFTER_SALE_REFUND_FAIL_REFUND_ORDER_ID_ERROR);
|
||||
}
|
||||
return payRefund;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -417,8 +463,6 @@ public class AfterSaleServiceImpl implements AfterSaleService {
|
||||
AfterSaleLogUtils.setAfterSaleInfo(afterSale.getId(), afterSale.getStatus(),
|
||||
AfterSaleStatusEnum.BUYER_CANCEL.getStatus());
|
||||
|
||||
// TODO 发送售后消息
|
||||
|
||||
// 更新交易订单项的售后状态为【未申请】
|
||||
tradeOrderUpdateService.updateOrderItemWhenAfterSaleCancel(afterSale.getOrderItemId());
|
||||
}
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
package cn.iocoder.yudao.module.trade.service.brokerage;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.PayTransferApi;
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferCreateRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.transfer.dto.PayTransferRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.wallet.PayWalletApi;
|
||||
import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletAddBalanceReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.wallet.dto.PayWalletRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.enums.PayChannelEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferStatusEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.transfer.PayTransferTypeEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum;
|
||||
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi;
|
||||
import cn.iocoder.yudao.module.system.api.social.SocialUserApi;
|
||||
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
|
||||
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
|
||||
import cn.iocoder.yudao.module.trade.controller.admin.brokerage.vo.withdraw.BrokerageWithdrawPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.brokerage.vo.withdraw.AppBrokerageWithdrawCreateReqVO;
|
||||
import cn.iocoder.yudao.module.trade.convert.brokerage.BrokerageWithdrawConvert;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.brokerage.BrokerageWithdrawDO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.config.TradeConfigDO;
|
||||
import cn.iocoder.yudao.module.trade.dal.mysql.brokerage.BrokerageWithdrawMapper;
|
||||
@@ -29,6 +28,7 @@ import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawTypeEnum;
|
||||
import cn.iocoder.yudao.module.trade.framework.order.config.TradeOrderProperties;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSummaryRespBO;
|
||||
import cn.iocoder.yudao.module.trade.service.config.TradeConfigService;
|
||||
import com.google.common.base.Objects;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Validator;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -40,10 +40,12 @@ import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
|
||||
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_TRANSFER_NOT_FOUND;
|
||||
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
@@ -64,13 +66,9 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
||||
@Resource
|
||||
private TradeConfigService tradeConfigService;
|
||||
|
||||
@Resource
|
||||
private NotifyMessageSendApi notifyMessageSendApi;
|
||||
@Resource
|
||||
private PayTransferApi payTransferApi;
|
||||
@Resource
|
||||
private SocialUserApi socialUserApi;
|
||||
@Resource
|
||||
private PayWalletApi payWalletApi;
|
||||
|
||||
@Resource
|
||||
@@ -84,15 +82,24 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
||||
public void auditBrokerageWithdraw(Long id, BrokerageWithdrawStatusEnum status, String auditReason, String userIp) {
|
||||
// 1.1 校验存在
|
||||
BrokerageWithdrawDO withdraw = validateBrokerageWithdrawExists(id);
|
||||
// 1.2 特殊:【重新转账】如果是提现失败,并且状态是审核中,那么更新状态为审核中,并且清空 transferErrorMsg
|
||||
if (BrokerageWithdrawStatusEnum.WITHDRAW_FAIL.getStatus().equals(withdraw.getStatus())) {
|
||||
int updateCount = brokerageWithdrawMapper.updateByIdAndStatus(id, withdraw.getStatus(),
|
||||
new BrokerageWithdrawDO().setStatus(BrokerageWithdrawStatusEnum.AUDITING.getStatus()).setTransferErrorMsg(""));
|
||||
if (updateCount == 0) {
|
||||
throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING);
|
||||
}
|
||||
withdraw.setStatus(BrokerageWithdrawStatusEnum.AUDITING.getStatus()).setTransferErrorMsg("");
|
||||
}
|
||||
// 1.2 校验状态为审核中
|
||||
if (ObjectUtil.notEqual(BrokerageWithdrawStatusEnum.AUDITING.getStatus(), withdraw.getStatus())) {
|
||||
throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING);
|
||||
}
|
||||
|
||||
// 2. 更新状态
|
||||
int rows = brokerageWithdrawMapper.updateByIdAndStatus(id, BrokerageWithdrawStatusEnum.AUDITING.getStatus(),
|
||||
int updateCount = brokerageWithdrawMapper.updateByIdAndStatus(id, withdraw.getStatus(),
|
||||
new BrokerageWithdrawDO().setStatus(status.getStatus()).setAuditReason(auditReason).setAuditTime(LocalDateTime.now()));
|
||||
if (rows == 0) {
|
||||
if (updateCount == 0) {
|
||||
throw exception(BROKERAGE_WITHDRAW_STATUS_NOT_AUDITING);
|
||||
}
|
||||
|
||||
@@ -109,44 +116,48 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
||||
}
|
||||
|
||||
private void auditBrokerageWithdrawSuccess(BrokerageWithdrawDO withdraw) {
|
||||
// 1.1 钱包
|
||||
if (BrokerageWithdrawTypeEnum.WALLET.getType().equals(withdraw.getType())) {
|
||||
payWalletApi.addWalletBalance(new PayWalletAddBalanceReqDTO()
|
||||
.setUserId(withdraw.getUserId()).setUserType(UserTypeEnum.MEMBER.getValue())
|
||||
.setBizType(PayWalletBizTypeEnum.BROKERAGE_WITHDRAW.getType()).setBizId(withdraw.getId().toString())
|
||||
.setPrice(withdraw.getPrice())).checkError();
|
||||
// 1.2 微信 API
|
||||
} else if (BrokerageWithdrawTypeEnum.WECHAT_API.getType().equals(withdraw.getType())) {
|
||||
// TODO @luchi:这里,要加个转账单号的记录;另外,调用 API 转账,是立马成功,还是有延迟的哈?
|
||||
Long payTransferId = createPayTransfer(withdraw);
|
||||
// 1.3 剩余类型,都是手动打款,所以不处理
|
||||
} else {
|
||||
// TODO 可优化:未来可以考虑,接入支付宝、银联等 API 转账,实现自动打款
|
||||
log.info("[auditBrokerageWithdrawSuccess][withdraw({}) 类型({}) 手动打款,无需处理]", withdraw.getId(), withdraw.getType());
|
||||
// 情况一:通过 API 转账
|
||||
if (BrokerageWithdrawTypeEnum.isApi(withdraw.getType())) {
|
||||
createPayTransfer(withdraw);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 非支付 API,则直接体现成功
|
||||
if (!BrokerageWithdrawTypeEnum.isApi(withdraw.getType())) {
|
||||
brokerageWithdrawMapper.updateByIdAndStatus(withdraw.getId(), BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.getStatus(),
|
||||
new BrokerageWithdrawDO().setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_SUCCESS.getStatus()));
|
||||
}
|
||||
// 情况二:非 API 转账(手动打款)
|
||||
brokerageWithdrawMapper.updateByIdAndStatus(withdraw.getId(), BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.getStatus(),
|
||||
new BrokerageWithdrawDO().setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_SUCCESS.getStatus()));
|
||||
}
|
||||
|
||||
private Long createPayTransfer(BrokerageWithdrawDO withdraw) {
|
||||
// 1.1 获取微信 openid
|
||||
SocialUserRespDTO socialUser = socialUserApi.getSocialUserByUserId(
|
||||
UserTypeEnum.MEMBER.getValue(), withdraw.getUserId(), SocialTypeEnum.WECHAT_MINI_PROGRAM.getType()).getCheckedData();
|
||||
// TODO @luchi:这里,需要校验非空。如果空的话,要有业务异常哈;
|
||||
private void createPayTransfer(BrokerageWithdrawDO withdraw) {
|
||||
// 1.1 获取基础信息
|
||||
String userAccount = withdraw.getUserAccount();
|
||||
String userName = withdraw.getUserName();
|
||||
String channelCode = null;
|
||||
Map<String, String> channelExtras = null;
|
||||
if (Objects.equal(withdraw.getType(), BrokerageWithdrawTypeEnum.ALIPAY_API.getType())) {
|
||||
channelCode = PayChannelEnum.ALIPAY_PC.getCode();
|
||||
} else if (Objects.equal(withdraw.getType(), BrokerageWithdrawTypeEnum.WECHAT_API.getType())) {
|
||||
channelCode = withdraw.getTransferChannelCode();
|
||||
userAccount = withdraw.getUserAccount();
|
||||
// 特殊:微信需要有报备信息
|
||||
channelExtras = PayTransferCreateReqDTO.buildWeiXinChannelExtra1000("佣金提现", "佣金提现");
|
||||
} else if (Objects.equal(withdraw.getType(), BrokerageWithdrawTypeEnum.WALLET.getType())) {
|
||||
PayWalletRespDTO wallet = payWalletApi.getOrCreateWallet(withdraw.getUserId(), UserTypeEnum.MEMBER.getValue()).getCheckedData();
|
||||
Assert.notNull(wallet, "钱包不存在");
|
||||
channelCode = PayChannelEnum.WALLET.getCode();
|
||||
userAccount = wallet.getId().toString();
|
||||
}
|
||||
// 1.2 构建请求
|
||||
PayTransferCreateReqDTO payTransferCreateReqDTO = new PayTransferCreateReqDTO()
|
||||
.setAppKey(tradeOrderProperties.getPayAppKey())
|
||||
.setChannelCode("wx_lite").setType(PayTransferTypeEnum.WX_BALANCE.getType())
|
||||
.setMerchantTransferId(withdraw.getId().toString())
|
||||
.setPrice(withdraw.getPrice())
|
||||
.setSubject("佣金提现")
|
||||
.setOpenid(socialUser.getOpenid()).setUserIp(getClientIP());
|
||||
// 2. 发起请求
|
||||
return payTransferApi.createTransfer(payTransferCreateReqDTO).getCheckedData();
|
||||
PayTransferCreateReqDTO transferReqDTO = new PayTransferCreateReqDTO()
|
||||
.setAppKey(tradeOrderProperties.getPayAppKey()).setChannelCode(channelCode)
|
||||
.setMerchantTransferId(withdraw.getId().toString()).setSubject("佣金提现").setPrice(withdraw.getPrice())
|
||||
.setUserAccount(userAccount).setUserName(userName).setUserIp(getClientIP())
|
||||
.setChannelExtras(channelExtras);
|
||||
// 1.3 发起请求
|
||||
PayTransferCreateRespDTO transferRespDTO = payTransferApi.createTransfer(transferReqDTO).getCheckedData();
|
||||
|
||||
// 2. 更新提现记录
|
||||
brokerageWithdrawMapper.updateById(new BrokerageWithdrawDO().setId(withdraw.getId())
|
||||
.setPayTransferId(transferRespDTO.getId()).setTransferChannelCode(channelCode));
|
||||
}
|
||||
|
||||
private BrokerageWithdrawDO validateBrokerageWithdrawExists(Long id) {
|
||||
@@ -178,7 +189,8 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
||||
// 2.1 计算手续费
|
||||
Integer feePrice = calculateFeePrice(createReqVO.getPrice(), tradeConfig.getBrokerageWithdrawFeePercent());
|
||||
// 2.2 创建佣金提现记录
|
||||
BrokerageWithdrawDO withdraw = BrokerageWithdrawConvert.INSTANCE.convert(createReqVO, userId, feePrice);
|
||||
BrokerageWithdrawDO withdraw = BeanUtils.toBean(createReqVO, BrokerageWithdrawDO.class)
|
||||
.setUserId(userId).setFeePrice(feePrice);
|
||||
brokerageWithdrawMapper.insert(withdraw);
|
||||
|
||||
// 3. 创建用户佣金记录
|
||||
@@ -220,22 +232,71 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateBrokerageWithdrawTransferred(Long id, Long payTransferId) {
|
||||
BrokerageWithdrawDO withdraw = validateBrokerageWithdrawExists(id);
|
||||
PayTransferRespDTO transfer = payTransferApi.getTransfer(payTransferId).getCheckedData();
|
||||
// TODO @luchi:建议参考支付那,即使成功的情况下,也要各种校验;金额是否匹配、转账单号是否匹配、是否重复调用;
|
||||
if (PayTransferStatusEnum.isSuccess(transfer.getStatus())) {
|
||||
withdraw.setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_SUCCESS.getStatus());
|
||||
// TODO @luchi:发送站内信
|
||||
} else if (PayTransferStatusEnum.isPendingStatus(transfer.getStatus())) {
|
||||
// TODO @luchi:这里,是不是不用更新哈?
|
||||
withdraw.setStatus(BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.getStatus());
|
||||
} else {
|
||||
withdraw.setStatus(BrokerageWithdrawStatusEnum.WITHDRAW_FAIL.getStatus());
|
||||
// 3.2 驳回时需要退还用户佣金
|
||||
brokerageRecordService.addBrokerage(withdraw.getUserId(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT,
|
||||
String.valueOf(withdraw.getId()), withdraw.getPrice(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT.getTitle());
|
||||
// 1.1 校验提现单是否存在
|
||||
BrokerageWithdrawDO withdraw = brokerageWithdrawMapper.selectById(id);
|
||||
if (withdraw == null) {
|
||||
log.error("[updateBrokerageWithdrawTransferred][withdraw({}) payTransfer({}) 不存在提现单,请进行处理!]", id, payTransferId);
|
||||
throw exception(BROKERAGE_WITHDRAW_NOT_EXISTS);
|
||||
}
|
||||
brokerageWithdrawMapper.updateById(withdraw);
|
||||
// 1.2 校验提现单已经结束(成功或失败)
|
||||
if (ObjectUtils.equalsAny(withdraw.getStatus(), BrokerageWithdrawStatusEnum.WITHDRAW_SUCCESS.getStatus(),
|
||||
BrokerageWithdrawStatusEnum.WITHDRAW_FAIL.getStatus())) {
|
||||
// 特殊:转账单编号相同,直接返回,说明重复回调
|
||||
if (ObjectUtil.equal(withdraw.getPayTransferId(), payTransferId)) {
|
||||
log.warn("[updateBrokerageWithdrawTransferred][withdraw({}) 已结束,且转账单编号相同({}),直接返回]", withdraw, payTransferId);
|
||||
return;
|
||||
}
|
||||
// 异常:转账单编号不同,说明转账单编号错误
|
||||
log.error("[updateBrokerageWithdrawTransferred][withdraw({}) 转账单不匹配({}),请进行处理!]", withdraw, payTransferId);
|
||||
throw exception(BROKERAGE_WITHDRAW_UPDATE_STATUS_FAIL_PAY_TRANSFER_ID_ERROR);
|
||||
}
|
||||
|
||||
// 2. 校验转账单的合法性
|
||||
PayTransferRespDTO payTransfer = validateBrokerageTransferStatusCanUpdate(withdraw, payTransferId);
|
||||
|
||||
// 3. 更新提现单状态
|
||||
Integer newStatus = PayTransferStatusEnum.isSuccess(payTransfer.getStatus()) ? BrokerageWithdrawStatusEnum.WITHDRAW_SUCCESS.getStatus() :
|
||||
PayTransferStatusEnum.isClosed(payTransfer.getStatus()) ? BrokerageWithdrawStatusEnum.WITHDRAW_FAIL.getStatus() : null;
|
||||
Assert.notNull(newStatus, "转账单状态({}) 不合法", payTransfer.getStatus());
|
||||
brokerageWithdrawMapper.updateByIdAndStatus(withdraw.getId(), withdraw.getStatus(),
|
||||
new BrokerageWithdrawDO().setStatus(newStatus)
|
||||
.setTransferTime(payTransfer.getSuccessTime())
|
||||
.setTransferErrorMsg(payTransfer.getChannelErrorMsg()));
|
||||
}
|
||||
|
||||
private PayTransferRespDTO validateBrokerageTransferStatusCanUpdate(BrokerageWithdrawDO withdraw, Long payTransferId) {
|
||||
// 1. 校验转账单是否存在
|
||||
PayTransferRespDTO payTransfer = payTransferApi.getTransfer(payTransferId).getCheckedData();
|
||||
if (payTransfer == null) {
|
||||
log.error("[validateBrokerageTransferStatusCanUpdate][withdraw({}) payTransfer({}) 不存在,请进行处理!]", withdraw.getId(), payTransferId);
|
||||
throw exception(PAY_TRANSFER_NOT_FOUND);
|
||||
}
|
||||
|
||||
// 2.1 校验转账单已成功或关闭
|
||||
if (!PayTransferStatusEnum.isSuccessOrClosed(payTransfer.getStatus())) {
|
||||
log.error("[validateBrokerageTransferStatusCanUpdate][withdraw({}) payTransfer({}) 未结束,请进行处理!payTransfer 数据是:{}]",
|
||||
withdraw.getId(), payTransferId, JsonUtils.toJsonString(payTransfer));
|
||||
throw exception(BROKERAGE_WITHDRAW_UPDATE_STATUS_FAIL_PAY_TRANSFER_STATUS_NOT_SUCCESS_OR_CLOSED);
|
||||
}
|
||||
// 2.2 校验转账金额一致
|
||||
if (ObjectUtil.notEqual(payTransfer.getPrice(), withdraw.getPrice())) {
|
||||
log.error("[validateBrokerageTransferStatusCanUpdate][withdraw({}) payTransfer({}) 转账金额不匹配,请进行处理!withdraw 数据是:{},payTransfer 数据是:{}]",
|
||||
withdraw.getId(), payTransferId, JsonUtils.toJsonString(withdraw), JsonUtils.toJsonString(payTransfer));
|
||||
throw exception(BROKERAGE_WITHDRAW_UPDATE_STATUS_FAIL_PAY_PRICE_NOT_MATCH);
|
||||
}
|
||||
// 2.3 校验转账订单匹配
|
||||
if (ObjectUtil.notEqual(payTransfer.getMerchantTransferId(), withdraw.getId().toString())) {
|
||||
log.error("[validateBrokerageTransferStatusCanUpdate][withdraw({}) 转账单不匹配({}),请进行处理!payTransfer 数据是:{}]",
|
||||
withdraw.getId(), payTransferId, JsonUtils.toJsonString(payTransfer));
|
||||
throw exception(BROKERAGE_WITHDRAW_UPDATE_STATUS_FAIL_PAY_MERCHANT_EXISTS);
|
||||
}
|
||||
// 2.4 校验转账渠道一致
|
||||
if (ObjectUtil.notEqual(payTransfer.getChannelCode(), withdraw.getTransferChannelCode())) {
|
||||
log.error("[validateBrokerageTransferStatusCanUpdate][withdraw({}) payTransfer({}) 转账渠道不匹配,请进行处理!withdraw 数据是:{},payTransfer 数据是:{}]",
|
||||
withdraw.getId(), payTransferId, JsonUtils.toJsonString(withdraw), JsonUtils.toJsonString(payTransfer));
|
||||
throw exception(BROKERAGE_WITHDRAW_UPDATE_STATUS_FAIL_PAY_CHANNEL_NOT_MATCH);
|
||||
}
|
||||
return payTransfer;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -209,6 +209,14 @@ public interface TradeOrderUpdateService {
|
||||
*/
|
||||
void cancelPaidOrder(Long userId, Long orderId, Integer cancelType);
|
||||
|
||||
/**
|
||||
* 取消支付订单的退款回调
|
||||
*
|
||||
* @param id 订单编号
|
||||
* @param payRefundId 支付退款编号
|
||||
*/
|
||||
void updatePaidOrderRefunded(Long id, Long payRefundId);
|
||||
|
||||
/**
|
||||
* 更新下单赠送的优惠券编号到订单
|
||||
*
|
||||
|
||||
@@ -20,7 +20,9 @@ import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi;
|
||||
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.pay.api.refund.dto.PayRefundRespDTO;
|
||||
import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
|
||||
import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
|
||||
import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi;
|
||||
import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.social.SocialClientApi;
|
||||
@@ -280,7 +282,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
|
||||
TradeOrderDO order = validateOrderExists(id);
|
||||
// 1.2 校验订单已支付
|
||||
if (!TradeOrderStatusEnum.isUnpaid(order.getStatus()) || order.getPayStatus()) {
|
||||
// 特殊:如果订单已支付,且支付单号相同,直接返回,说明重复回调
|
||||
// 特殊:支付单号相同,直接返回,说明重复回调
|
||||
if (ObjectUtil.equals(order.getPayOrderId(), payOrderId)) {
|
||||
log.warn("[updateOrderPaid][order({}) 已支付,且支付单号相同({}),直接返回]", order, payOrderId);
|
||||
return;
|
||||
@@ -420,7 +422,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
|
||||
.addMessage("phrase6", TradeOrderStatusEnum.DELIVERED.getName()) // 订单状态
|
||||
.addMessage("date4", LocalDateTimeUtil.formatNormal(LocalDateTime.now()))// 发货时间
|
||||
.addMessage("character_string5", StrUtil.blankToDefault(deliveryReqVO.getLogisticsNo(), "-")) // 快递单号
|
||||
.addMessage("thing9", order.getReceiverDetailAddress())).checkError(); // 收货地址
|
||||
.addMessage("thing9", order.getReceiverDetailAddress())).getCheckedData(); // 收货地址
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -938,10 +940,24 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
|
||||
.setAppKey(tradeOrderProperties.getPayAppKey()) // 支付应用
|
||||
.setUserIp(NetUtil.getLocalhostStr()) // 使用本机 IP,因为是服务器发起退款的
|
||||
.setMerchantOrderId(String.valueOf(order.getId())) // 支付单号
|
||||
.setMerchantRefundId(String.valueOf(order.getId()))
|
||||
// 特殊:因为订单支持 AfterSale 单个售后退款,也支持整单退款,所以需要通过 order- 进行下区分
|
||||
// 具体可见 AfterSaleController 的 updateAfterSaleRefunded 方法
|
||||
.setMerchantRefundId("order-" + order.getId())
|
||||
.setReason(TradeOrderCancelTypeEnum.COMBINATION_CLOSE.getName()).setPrice(order.getPayPrice())).checkError(); // 价格信息
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePaidOrderRefunded(Long id, Long payRefundId) {
|
||||
PayRefundRespDTO payRefund = payRefundApi.getRefund(payRefundId).getCheckedData();
|
||||
if (payRefund == null) {
|
||||
throw exception(ORDER_UPDATE_PAID_ORDER_REFUNDED_FAIL_REFUND_NOT_FOUND);
|
||||
}
|
||||
// 特殊:因为在 cancelPaidOrder 已经进行订单的取消,所以这里必须退款成功!!!
|
||||
if (!PayRefundStatusEnum.isSuccess(payRefund.getStatus())) {
|
||||
throw exception(ORDER_UPDATE_PAID_ORDER_REFUNDED_FAIL_REFUND_STATUS_NOT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateOrderGiveCouponIds(Long userId, Long orderId, List<Long> giveCouponIds) {
|
||||
// 1. 检验订单存在
|
||||
|
||||
Reference in New Issue
Block a user