121 lines
3.8 KiB
Markdown
121 lines
3.8 KiB
Markdown
# 需求09:C端支付方式限制配置化
|
||
|
||
> 依赖:[系统配置](./基础设施/系统配置.md)
|
||
|
||
---
|
||
|
||
## 背景
|
||
|
||
代码已经写好但被注释,注释原因是**微信支付参数未申请下来**,临时注释。
|
||
|
||
注释位置:
|
||
- `internal/handler/app/client_wallet.go`(钱包充值入口)
|
||
- `internal/service/client_order/service.go`(订单支付入口)
|
||
|
||
两处均有注释:`// 第三方支付方式与资产类型必须匹配:单卡只允许支付宝,设备只允许微信(已暂时注释)`
|
||
|
||
---
|
||
|
||
## 业务规则
|
||
|
||
| 资产类型 | 允许的第三方支付 | 禁止的第三方支付 |
|
||
|---------|----------------|----------------|
|
||
| IoT 卡 | 支付宝、钱包 | 微信 |
|
||
| 设备 | 微信、钱包 | 支付宝 |
|
||
|
||
**钱包支付对所有资产类型均允许。**
|
||
|
||
---
|
||
|
||
## 实现方案
|
||
|
||
### 1. 系统配置初始化(已在系统配置文档中定义)
|
||
|
||
```go
|
||
// tb_system_config 初始数据
|
||
config_key: "c2b.payment.card_allowed_methods" → ["alipay","wallet"]
|
||
config_key: "c2b.payment.device_allowed_methods" → ["wechat","wallet"]
|
||
```
|
||
|
||
### 2. 恢复注释代码,改为读取配置
|
||
|
||
**文件**:`internal/service/client_order/service.go`
|
||
|
||
```go
|
||
// validatePaymentMethod 校验资产类型与支付方式是否匹配
|
||
func (s *Service) validatePaymentMethod(ctx context.Context, assetType string, paymentMethod string) error {
|
||
// 钱包支付始终允许
|
||
if paymentMethod == model.PaymentMethodWallet {
|
||
return nil
|
||
}
|
||
|
||
var configKey string
|
||
switch assetType {
|
||
case model.AssetTypeIotCard: // "iot_card",定义在 internal/model/asset_identifier.go
|
||
configKey = "c2b.payment.card_allowed_methods"
|
||
case model.AssetTypeDevice: // "device",定义在 internal/model/asset_identifier.go
|
||
configKey = "c2b.payment.device_allowed_methods"
|
||
default:
|
||
return nil // 未知资产类型不限制
|
||
}
|
||
|
||
allowedMethods, err := sysconfig.GetStringSlice(ctx, configKey)
|
||
if err != nil || len(allowedMethods) == 0 {
|
||
// 配置读取失败,降级为允许(防止配置问题影响支付)
|
||
s.logger.Warn("读取支付方式配置失败,降级为允许", zap.String("config_key", configKey))
|
||
return nil
|
||
}
|
||
|
||
for _, m := range allowedMethods {
|
||
if m == paymentMethod {
|
||
return nil
|
||
}
|
||
}
|
||
return errors.New(errors.CodeForbidden, "该资产类型不支持此支付方式")
|
||
}
|
||
```
|
||
|
||
在 `client_wallet.go`(充值)和 `client_order/service.go`(订单支付)的对应位置恢复调用。
|
||
|
||
### 3. 错误信息
|
||
|
||
用户端错误提示(友好文案):
|
||
|
||
```go
|
||
// 根据资产类型给出具体提示
|
||
switch assetType {
|
||
case model.AssetTypeIotCard:
|
||
return errors.New(errors.CodeForbidden, "卡资产仅支持支付宝或余额支付")
|
||
case model.AssetTypeDevice:
|
||
return errors.New(errors.CodeForbidden, "设备仅支持微信或余额支付")
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 前端对接
|
||
|
||
### C端支付页面
|
||
|
||
前端在展示支付方式时,根据资产类型**过滤不可用的支付方式**(前端主动隐藏,后端兜底拦截)。
|
||
|
||
前端需要从哪里知道"当前资产是卡还是设备"?登录/初始化时返回 `asset_type`,前端保存上下文。
|
||
|
||
```
|
||
资产类型 = "iot_card" → 展示支付方式:支付宝、余额
|
||
资产类型 = "device" → 展示支付方式:微信、余额
|
||
```
|
||
|
||
### 后台配置页面
|
||
|
||
在系统配置(系统设置 > 系统配置 > `c2b.payment` 模块)中,用 CheckboxGroup 展示:
|
||
|
||
```
|
||
卡资产允许支付方式:☑ 支付宝 ☑ 余额 ☐ 微信
|
||
设备允许支付方式: ☐ 支付宝 ☑ 余额 ☑ 微信
|
||
```
|
||
|
||
修改后调用 `PUT /admin/system/config/c2b.payment.card_allowed_methods`。
|
||
|
||
> 注意:**微信支付参数申请下来后**,直接在系统配置里把对应资产类型勾上微信即可生效,无需改代码。
|