让 C 端在续费前展示当前应付价格
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m11s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m11s
Constraint: 续费展示价必须与当前销售渠道的生效零售价一致 Rejected: 新增专用续费报价接口 | 现有资产信息已承载续费入口上下文 Confidence: high Scope-risk: narrow Directive: 下单时仍须重新校验续费资格和最终价格 Tested: go build ./internal/handler/app Not-tested: 按用户要求未添加或运行测试
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
## 功能文档
|
||||
|
||||
- [全局审计当前实现进度](docs/tech-global-audit/当前实现进度.md)
|
||||
- [C 端资产续费价格](docs/client-asset-renewal-price/功能总结.md)
|
||||
|
||||
## 系统简介
|
||||
|
||||
|
||||
7
docs/client-asset-renewal-price/功能总结.md
Normal file
7
docs/client-asset-renewal-price/功能总结.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# C 端资产续费价格
|
||||
|
||||
`GET /api/c/v1/asset/info` 在当前套餐信息中返回 `renewal_price`,单位为分;无当前主套餐时返回 `0`。
|
||||
|
||||
- 平台自营资产:返回套餐当前生效零售价。
|
||||
- 代理渠道资产:返回该代理套餐分配记录的当前生效零售价。
|
||||
- 续费下单仍由原订单创建接口重新校验资格和最终价格,前端展示值不作为下单价格凭证。
|
||||
@@ -191,6 +191,10 @@ func (h *ClientAssetHandler) GetAssetInfo(c *fiber.Ctx) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
renewalPrice, err := h.getRenewalPrice(resolved.SkipPermissionCtx, currentPackageID, resolved.SellerShopID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if h.paymentMethodPolicy == nil {
|
||||
return errors.New(errors.CodeNoPaymentConfig)
|
||||
}
|
||||
@@ -239,6 +243,7 @@ func (h *ClientAssetHandler) GetAssetInfo(c *fiber.Ctx) error {
|
||||
ActivatedAt: resolved.Asset.ActivatedAt,
|
||||
CurrentPackage: resolved.Asset.CurrentPackage,
|
||||
CurrentPackageID: currentPackageID,
|
||||
RenewalPrice: renewalPrice,
|
||||
CurrentPackageUsageID: resolved.Asset.CurrentPackageUsageID,
|
||||
CurrentPackageActivatedAt: resolved.Asset.CurrentPackageActivatedAt,
|
||||
CurrentPackageExpiresAt: resolved.Asset.CurrentPackageExpiresAt,
|
||||
@@ -302,6 +307,26 @@ func (h *ClientAssetHandler) getCurrentPackageID(ctx context.Context, usageID *u
|
||||
return usage.PackageID, nil
|
||||
}
|
||||
|
||||
func (h *ClientAssetHandler) getRenewalPrice(ctx context.Context, packageID, sellerShopID uint) (int64, error) {
|
||||
if packageID == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
pkg, err := h.packageStore.GetByID(ctx, packageID)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(errors.CodeDatabaseError, err, "查询续费套餐失败")
|
||||
}
|
||||
if sellerShopID == 0 {
|
||||
return packageprice.PackageEffectiveRetailPrice(pkg), nil
|
||||
}
|
||||
|
||||
allocation, err := h.shopPackageAllocationStore.GetByShopAndPackageForSystem(ctx, sellerShopID, packageID)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(errors.CodeDatabaseError, err, "查询续费套餐价格失败")
|
||||
}
|
||||
return packageprice.AllocationEffectiveRetailPrice(allocation), nil
|
||||
}
|
||||
|
||||
func (h *ClientAssetHandler) dispatchAssetReadObservations(ctx context.Context, asset *dto.AssetResolveResponse) {
|
||||
if h.observationSeries == nil || asset == nil {
|
||||
return
|
||||
|
||||
@@ -41,6 +41,7 @@ type AssetInfoResponse struct {
|
||||
// === 套餐信息(通用) ===
|
||||
CurrentPackage string `json:"current_package" description:"当前套餐名称(无套餐时为空)"`
|
||||
CurrentPackageID uint `json:"current_package_id" description:"当前主套餐ID,无主套餐时为0,可用于发起续费"`
|
||||
RenewalPrice int64 `json:"renewal_price" description:"当前主套餐续费价格(分,按当前销售渠道的生效零售价计算;无主套餐时为0)"`
|
||||
CurrentPackageUsageID *uint `json:"current_package_usage_id" description:"当前主套餐的套餐使用记录ID,无主套餐时为 null"`
|
||||
CurrentPackageActivatedAt *time.Time `json:"current_package_activated_at,omitempty" description:"当前主套餐开始时间"`
|
||||
CurrentPackageExpiresAt *time.Time `json:"current_package_expires_at,omitempty" description:"当前主套餐过期时间"`
|
||||
|
||||
Reference in New Issue
Block a user