Merge remote-tracking branch 'origin/feature/mall_product' into feature/mall_product

This commit is contained in:
owen
2023-09-30 22:09:49 +08:00
33 changed files with 182 additions and 160 deletions

View File

@ -11,7 +11,7 @@ import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert;
import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO;
import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO;
import cn.iocoder.yudao.module.pay.framework.pay.wallet.WalletPayClient;
import cn.iocoder.yudao.module.pay.framework.pay.core.WalletPayClient;
import cn.iocoder.yudao.module.pay.service.app.PayAppService;
import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
import com.google.common.collect.Maps;

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.controller.admin.wallet;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
import cn.iocoder.yudao.module.pay.api.notify.dto.PayRefundNotifyReqDTO;
import cn.iocoder.yudao.module.pay.service.wallet.PayWalletRechargeService;
import io.swagger.v3.oas.annotations.Operation;
@ -13,6 +14,7 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
@ -27,12 +29,22 @@ public class PayWalletRechargeController {
@Resource
private PayWalletRechargeService walletRechargeService;
@PostMapping("/update-paid")
@Operation(summary = "更新钱包充值为已充值") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob
@PermitAll // 无需登录, 内部校验实现
@OperateLog(enable = false) // 禁用操作日志,因为没有操作人
public CommonResult<Boolean> updateWalletRechargerPaid(@Valid @RequestBody PayOrderNotifyReqDTO notifyReqDTO) {
walletRechargeService.updateWalletRechargerPaid(Long.valueOf(notifyReqDTO.getMerchantOrderId()),
notifyReqDTO.getPayOrderId());
return success(true);
}
// TODO @jason发起退款要 post 操作哈;
@GetMapping("/refund")
@Operation(summary = "发起钱包充值退款")
@Parameter(name = "id", description = "编号", required = true, example = "1024")
public CommonResult<Boolean> refundWalletRecharge(@RequestParam("id") Long id) {
walletRechargeService.refundWalletRecharge(id,getClientIP());
walletRechargeService.refundWalletRecharge(id, getClientIP());
return success(true);
}

View File

@ -1,12 +1,15 @@
package cn.iocoder.yudao.module.pay.controller.app.order;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderRespVO;
import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderSubmitRespVO;
import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitReqVO;
import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitRespVO;
import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert;
import cn.iocoder.yudao.module.pay.framework.pay.core.WalletPayClient;
import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
import com.google.common.collect.Maps;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
@ -16,8 +19,13 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserType;
@Tag(name = "用户 APP - 支付订单")
@RestController
@ -40,6 +48,16 @@ public class AppPayOrderController {
@PostMapping("/submit")
@Operation(summary = "提交支付订单")
public CommonResult<AppPayOrderSubmitRespVO> submitPayOrder(@RequestBody AppPayOrderSubmitReqVO reqVO) {
// 1. 钱包支付事,需要额外传 user_id 和 user_type
if (Objects.equals(reqVO.getChannelCode(), PayChannelEnum.WALLET.getCode())) {
Map<String, String> channelExtras = reqVO.getChannelExtras() == null ?
Maps.newHashMapWithExpectedSize(2) : reqVO.getChannelExtras();
channelExtras.put(WalletPayClient.USER_ID_KEY, String.valueOf(getLoginUserId()));
channelExtras.put(WalletPayClient.USER_TYPE_KEY, String.valueOf(getLoginUserType()));
reqVO.setChannelExtras(channelExtras);
}
// 2. 提交支付
PayOrderSubmitRespVO respVO = payOrderService.submitOrder(reqVO, getClientIP());
return success(PayOrderConvert.INSTANCE.convert3(respVO));
}

View File

@ -1,8 +1,6 @@
package cn.iocoder.yudao.module.pay.controller.app.wallet;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.recharge.AppPayWalletRechargeCreateReqVO;
import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.recharge.AppPayWalletRechargeCreateRespVO;
import cn.iocoder.yudao.module.pay.convert.wallet.PayWalletRechargeConvert;
@ -18,7 +16,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -44,13 +41,4 @@ public class AppPayWalletRechargeController {
return success(PayWalletRechargeConvert.INSTANCE.convert(walletRecharge));
}
@PostMapping("/update-paid")
@Operation(summary = "更新钱包充值为已充值") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob
@PermitAll // 无需登录,安全由 内部校验实现
@OperateLog(enable = false) // 禁用操作日志,因为没有操作人
public CommonResult<Boolean> updateWalletRechargerPaid(@Valid @RequestBody PayOrderNotifyReqDTO notifyReqDTO) {
walletRechargeService.updateWalletRechargerPaid(Long.valueOf(notifyReqDTO.getMerchantOrderId()),
notifyReqDTO.getPayOrderId());
return success(true);
}
}

View File

@ -0,0 +1,35 @@
package cn.iocoder.yudao.module.pay.controller.app.wallet;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.pay.controller.app.wallet.vo.recharge.AppPayWalletPackageRespVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "用户 APP - 钱包充值套餐")
@RestController
@RequestMapping("/pay/wallet-recharge-package")
@Validated
@Slf4j
public class AppPayWalletRechargePackageController {
@GetMapping("/list")
@Operation(summary = "获得钱包充值套餐列表")
public CommonResult<List<AppPayWalletPackageRespVO>> getWalletRechargePackageList() {
// 只查询开启;需要按照 payPrice 排序;
List<AppPayWalletPackageRespVO> list = new ArrayList<>();
list.add(new AppPayWalletPackageRespVO().setId(1L).setName("土豆").setPayPrice(10).setBonusPrice(2));
list.add(new AppPayWalletPackageRespVO().setId(2L).setName("番茄").setPayPrice(20).setBonusPrice(5));
return success(list);
}
}

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.pay.controller.app.wallet.vo.recharge;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "用户 APP - 用户充值套餐 Response VO")
@Data
public class AppPayWalletPackageRespVO {
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "套餐名", requiredMode = Schema.RequiredMode.REQUIRED, example = "小套餐")
private String name;
@Schema(description = "支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer payPrice;
@Schema(description = "赠送金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
private Integer bonusPrice;
}

View File

@ -3,24 +3,27 @@ package cn.iocoder.yudao.module.pay.controller.app.wallet.vo.recharge;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.DecimalMin;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
@Schema(description = "用户 APP - 创建钱包充值 Request VO")
@Data
public class AppPayWalletRechargeCreateReqVO {
@Schema(description = "支付金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
@NotNull(message = "支付金额不能为空")
// @NotNull(message = "支付金额不能为空")
@Min(value = 1, message = "支付金额必须大于零")
private Integer payPrice;
// TODO @jason这个是不是后端计算出来呀不然前端可以直接搞了。。。
// TOTO 那是不是搞一个充值模板
@Schema(description = "钱包赠送金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1000")
@NotNull(message = "钱包赠送金额不能为空")
@DecimalMin(value = "0", message = "钱包赠送金额必须大于等于零")
private Integer bonusPrice;
// @NotNull(message = "钱包赠送金额不能为空")
// @DecimalMin(value = "0", message = "钱包赠送金额必须大于等于零")
private Integer bonusPrice = 0;
@Schema(description = "充值套餐编号", example = "1024")
private Long packageId;
// TODO @jason可以改成 payPrice 和 packageId 两个至少一个不为空;
}

View File

@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.pay.controller.app.wallet.vo.wallet;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "用户 APP - 获取用户钱包 Response VO")
@Schema(description = "用户 APP - 用户钱包 Response VO")
@Data
public class AppPayWalletRespVO {

View File

@ -47,6 +47,7 @@ public class PayWalletRechargeDO extends BaseDO {
* 钱包赠送金额
*/
private Integer bonusPrice;
// TODO @jason如果有赠送金额需要关联下 PayWalletPackageDO 的 id 字段
/**
* 是否已支付

View File

@ -0,0 +1,46 @@
package cn.iocoder.yudao.module.pay.dal.dataobject.wallet;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 会员钱包充值套餐 DO
*
* 通过套餐充值时,可以赠送一定金额;
*
* @author 芋道源码
*/
@TableName(value ="pay_wallet_recharge_package")
@KeySequence("pay_wallet_recharge_package_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
public class PayWalletRechargePackageDO {
/**
* 编号
*/
@TableId
private Long id;
/**
* 套餐名
*/
private String name;
/**
* 支付金额
*/
private Integer payPrice;
/**
* 赠送金额
*/
private Integer bonusPrice;
/**
* 状态
*
* 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum}
*/
private Integer status;
}

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.pay.framework.pay.wallet;
package cn.iocoder.yudao.module.pay.framework.pay.core;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;

View File

@ -1,4 +0,0 @@
/**
* 占位,无实际作用
*/
package cn.iocoder.yudao.module.pay.framework.pay.core;

View File

@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.pay.controller.admin.channel.vo.PayChannelUpdateR
import cn.iocoder.yudao.module.pay.convert.channel.PayChannelConvert;
import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
import cn.iocoder.yudao.module.pay.dal.mysql.channel.PayChannelMapper;
import cn.iocoder.yudao.module.pay.framework.pay.core.WalletPayClient;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import lombok.Getter;
@ -20,6 +21,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.validation.Validator;
import java.time.Duration;
@ -68,6 +70,14 @@ public class PayChannelServiceImpl implements PayChannelService {
@Resource
private Validator validator;
/**
* 初始化,为了注册钱包
*/
@PostConstruct
public void init() {
payClientFactory.registerPayClientClass(PayChannelEnum.WALLET, WalletPayClient.class);
}
@Override
public Long createChannel(PayChannelCreateReqVO reqVO) {
// 断言是否有重复的

View File

@ -40,6 +40,7 @@ import static cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum.*;
@Service
@Slf4j
public class PayWalletRechargeServiceImpl implements PayWalletRechargeService {
/**
* TODO 放到 配置文件中
*/

View File

@ -1,54 +0,0 @@
package cn.iocoder.yudao.module.pay.util;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import java.time.LocalDateTime;
import java.util.concurrent.atomic.AtomicLong;
/**
* 支付相关编号的生产
*/
// TODO @jason需要改造基于 db
public class PaySeqUtils {
private static final AtomicLong REFUND_REQ_NO_SEQ = new AtomicLong(0L);
private static final AtomicLong MER_REFUND_NO_SEQ = new AtomicLong(0L);
private static final AtomicLong MER_ORDER_NO_SEQ = new AtomicLong(0L);
// TODO 芋艿:需要看看
/**
* 生成商户退款单号,用于测试,应该由商户系统生成
* @return 商户退款单
*/
public static String genMerchantRefundNo() {
return String.format("%s%s%04d", "MR",
DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_MS_PATTERN),
(int) MER_REFUND_NO_SEQ.getAndIncrement() % 10000);
}
// TODO 芋艿:需要看看
/**
* 生成退款请求号
* @return 退款请求号
*/
public static String genRefundReqNo() {
return String.format("%s%s%04d", "RR",
DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_MS_PATTERN),
(int) REFUND_REQ_NO_SEQ.getAndIncrement() % 10000);
}
/**
* 生成商户订单编号号 用于测试,应该由商户系统生成
* @return 商户订单编号
*/
public static String genMerchantOrderNo() {
return String.format("%s%s%04d", "MO",
DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_MS_PATTERN),
(int) MER_ORDER_NO_SEQ.getAndIncrement() % 10000);
}
}