This commit is contained in:
63
openspec/changes/update-july-h5-c-iteration/design.md
Normal file
63
openspec/changes/update-july-h5-c-iteration/design.md
Normal file
@@ -0,0 +1,63 @@
|
||||
## Context
|
||||
|
||||
本次迭代同时调整认证入口、资产初始化、套餐购买、钱包充值、订单查询和站内通知入口。后端已经通过资产信息、充值校验、订单和通知接口返回策略与业务状态,H5/C 端需要消费这些结果,而不是复制后端规则。当前仓库已经存在部分支付、实名和通知页面,因此提案以增量收敛行为为主。
|
||||
|
||||
接口约定以 `docs/所需接口文档/new-api.md` 为准;登录限制接口和通知接口的调用路径同时以 `docs/产品迭代7月份/七月迭代H5_C端改动说明.md` 中列出的既有路径为准。
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
- Goals: 让登录限制、实名策略、支付方式、强充约束、下架套餐续费、预计到期时间、临期/换货通知及订单标识展示均以后端返回为准。
|
||||
- Goals: 保持现有 H5/C API 路径和支付入口,完成前端参数和展示规则收敛。
|
||||
- Non-Goals: 不新增后端接口,不修改订单历史快照,不由 H5/C 调用企微审批回调,也不实现七月说明中列出的排除项。
|
||||
|
||||
## Decisions
|
||||
|
||||
### 1. Backend is the source of truth
|
||||
|
||||
资产初始化统一读取 `effective_realname_policy`、`realname_required`、`real_name_status`、`allowed_payment_methods`、`estimated_final_expires_at`、`days_until_final_expiry`、`expiry_estimate_status` 和 `is_expiring`。前端不再根据 `asset_type`、卡/设备组合或本地枚举推导实名和支付规则;设备是否已实名也以服务端最终状态为准。
|
||||
|
||||
### 2. Keep login failure before token persistence
|
||||
|
||||
`POST /api/c/v1/auth/verify-asset` 成功后才允许进入后续微信登录,并保存本次返回的 `asset_token`。业务失败时直接展示后端 `msg`,当前登录尝试不得继续获取或覆盖资产 Token;Token 的签发和吊销仍由服务端负责。
|
||||
|
||||
### 3. Normalize payment payloads at the API boundary
|
||||
|
||||
订单和充值页面只提交用户从后端允许列表中选择的 `payment_method`。仅在 `payment_method = wechat` 时提交接口要求的 `app_type`;钱包和支付宝不添加无关的微信字段。金额在 UI 层转换为元,在请求层保持整数分。
|
||||
|
||||
支付创建成功后,根据 `pay_config` 或 `payment_link` 进入既有支付处理;返回页面或支付完成后使用订单详情/状态查询确认结果,不能仅凭前端跳转成功判定已支付。
|
||||
|
||||
### 4. Separate catalog visibility from renewal eligibility
|
||||
|
||||
普通套餐列表继续只展示可售套餐。老客户续费使用资产信息中的 `current_package_id` 或历史订单中的 `package_ids` 作为已知套餐 ID,复用 `POST /api/c/v1/orders/create`,不创建“下架套餐续费”专用接口。前端不得修改历史订单数据或把下架套餐重新放入普通新客购买列表。
|
||||
|
||||
### 5. Display the final expiry estimate
|
||||
|
||||
资产页面优先展示 `estimated_final_expires_at`,并用 `expiry_estimate_status` 判断其是否可展示,用 `days_until_final_expiry` 和 `is_expiring` 控制剩余天数及临期样式。前端不根据当前套餐到期时间自行累加计算最终日期;无可用估算时显示明确的空状态。
|
||||
|
||||
### 6. Reuse the existing customer notification entry
|
||||
|
||||
首页或通知入口读取未读数,通知页面读取列表,用户查看/点击通知后调用单条已读接口。套餐临期的 15/7/3 天触发和 0~3 天的优先级由后端通知数据表达,前端只负责按等级排序/展示和更新未读数。换货通知沿用同一套入口,不新增营销、ERP 或业务员提醒通道。
|
||||
|
||||
本提案依赖进行中的 `add-personal-notifications` 变更提供通知数据的可见性、分页和幂等已读语义;本提案只定义 H5/C 的消费方式。
|
||||
|
||||
### 7. Preserve server snapshots in order views
|
||||
|
||||
订单列表和详情使用后端返回的 `purchase_role` 与 `asset_identifier`。设备显示优先使用 `virtual_no`,为空时使用 `imei`,绝不以 `sn` 代替;缺失数据保持空占位,不由前端伪造。金额继续按分转元展示。
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- 后端字段缺失或为空时,页面可能无法给出策略或到期日期;通过统一空状态和错误提示避免前端猜测。
|
||||
- 同一支付入口可能同时收到 `pay_config` 与 `payment_link` 为空的结果;前端必须保留既有错误处理并允许通过订单状态查询恢复。
|
||||
- `add-personal-notifications` 与本提案同时推进时,需要先确认通知 API 的返回字段和分页参数一致;本提案不重复修改该服务契约。
|
||||
- 下架套餐续费依赖资产或历史订单提供合法的套餐 ID;若两者均不存在,应明确提示不可续费,而不是从普通列表猜测套餐。
|
||||
|
||||
## Migration Plan
|
||||
|
||||
1. 先更新 API 封装和数据归一化,再逐个接入登录、资产、支付、套餐、通知和订单页面。
|
||||
2. 使用接口模拟数据覆盖策略冲突、支付方式变化、强充、临期等级、下架套餐和空标识场景。
|
||||
3. 联调确认支付结果查询、通知已读幂等性及历史订单快照后发布。
|
||||
4. 若任一后端字段未上线,回退对应 UI 展示入口,不回退到前端硬编码业务规则。
|
||||
|
||||
## Open Questions
|
||||
|
||||
- None. The proposal follows the July change description and the provided API document; backend response details not listed there remain opaque to the client and are displayed through existing generic error handling.
|
||||
41
openspec/changes/update-july-h5-c-iteration/proposal.md
Normal file
41
openspec/changes/update-july-h5-c-iteration/proposal.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Change: Update July H5/C iteration behavior
|
||||
|
||||
## Why
|
||||
|
||||
七月迭代要求 H5/C 端将登录、实名、支付、套餐续费、到期提醒、站内通知和订单展示统一切换为以后端业务结果为准。当前页面和 API 封装仍存在按资产类型或前端本地规则判断的逻辑,部分订单提交也没有始终传递用户选择的支付方式,容易造成错误引导、支付参数不完整和订单信息展示失真。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 在资产校验登录流程中处理店铺 C 端登录限制;被限制时展示后端业务错误,不保存或继续使用本次登录的资产 Token。
|
||||
- 使用资产信息接口返回的 `effective_realname_policy`、`realname_required` 和 `real_name_status` 驱动实名状态展示及下单前后的实名流程。
|
||||
- 使用 `allowed_payment_methods` 渲染支付方式,并在套餐下单、强充校验和钱包充值时按后端规则提交 `payment_method`;微信支付按要求提交 `app_type`。
|
||||
- 普通套餐列表隐藏下架套餐,同时允许正在使用下架套餐的老客户通过 `current_package_id` 或历史订单 `package_ids` 复用 `/api/c/v1/orders/create` 续费。
|
||||
- 在资产详情、资产列表等页面展示后端计算的 `estimated_final_expires_at`,并使用临期字段进行高亮。
|
||||
- 接入 C 端站内通知的未读数、列表和单条已读接口,展示套餐临期和换货通知,并按后端临期等级处理提醒优先级。
|
||||
- 在订单列表和详情展示后端返回的 `purchase_role` 与 `asset_identifier`;设备标识按 `virtual_no` 优先、`imei` 兜底,不使用 SN 冒充。
|
||||
- 保持金额接口以分传输、页面以元展示,并在支付参数或支付链接返回后通过订单状态查询确认支付结果。
|
||||
|
||||
本提案不包含首页隐藏设备 ICCID、行业卡未实名复机、状态同步/运营商回调、企微审批回调、原路退款、跨品类换货、分销码或佣金提现等明确排除项。H5/C 端不调用企微审批回调接口。
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `c-login-access`: Enforce the shop-level C-end login restriction during asset verification
|
||||
- `asset-realname-flow`: Drive real-name behavior from backend asset policy and status
|
||||
- `asset-expiry-display`: Display the estimated final package expiry and expiry state
|
||||
- `backend-driven-payment`: Render and submit payment methods from backend policy
|
||||
- `legacy-package-renewal`: Allow eligible existing customers to renew discontinued packages
|
||||
- `c-notification-reminders`: Surface expiry and exchange notifications in the H5/C client
|
||||
- `order-display-fields`: Render order role and server-provided asset identifier snapshots
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `personal-notifications`: This change consumes the notification endpoints and does not redefine their backend visibility, pagination, or read-state contract. Coordinate with the existing `add-personal-notifications` change.
|
||||
|
||||
## Impact
|
||||
|
||||
- Affected code: `pages/login/login.vue`, `pages/index/index.vue`, `pages/auth/auth.vue`, `pages/switch/switch.vue`, `pages/package-order/package-order.vue`, `pages/my-wallet/my-wallet.vue`, `pages/order-list/order-list.vue`, `pages/notifications/notifications.vue`, related notification/payment components, and `api/modules/{auth,asset,order,wallet,notification}.js`
|
||||
- Affected APIs: `/api/c/v1/auth/verify-asset`, `/api/c/v1/asset/info`, `/api/c/v1/wallet/recharge-check`, `/api/c/v1/orders/create`, `/api/c/v1/wallet/recharge`, `/api/c/v1/orders`, `/api/c/v1/orders/{id}`, `/api/c/v1/notifications/unread-count`, `/api/c/v1/notifications`, and `/api/c/v1/notifications/{id}/read`
|
||||
- No new backend endpoint is required; the client adopts the response fields and request rules described in `docs/所需接口文档/new-api.md` and the July H5/C change description.
|
||||
- Existing WeChat payment parameter handling, Alipay payment-link handling, wallet payment, payment submit guards, and notification list APIs must remain compatible.
|
||||
@@ -0,0 +1,23 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Asset views SHALL display the estimated final package expiry
|
||||
|
||||
Asset detail and summary views using `/api/c/v1/asset/info` SHALL prefer `estimated_final_expires_at` over `current_package_expires_at` for the user-facing final expiry. The client SHALL use `expiry_estimate_status`, `days_until_final_expiry`, and `is_expiring` when those fields are returned, and SHALL NOT calculate a replacement final expiry locally.
|
||||
|
||||
#### Scenario: Exact final expiry is available
|
||||
|
||||
- **WHEN** `expiry_estimate_status = exact` and `estimated_final_expires_at` is present
|
||||
- **THEN** the client SHALL display the estimated final expiry date
|
||||
- **AND** the client SHALL display the returned remaining-day value when available
|
||||
|
||||
#### Scenario: Asset is approaching final expiry
|
||||
|
||||
- **WHEN** `is_expiring = true` or the backend returns an applicable expiry level
|
||||
- **THEN** the client SHALL apply the existing expiry highlight/reminder presentation
|
||||
- **AND** the client SHALL use the backend value rather than recalculating the threshold
|
||||
|
||||
#### Scenario: Final expiry cannot be estimated
|
||||
|
||||
- **WHEN** `expiry_estimate_status` is `none`, `waiting_activation`, or `invalid_data`, or the estimated date is null
|
||||
- **THEN** the client SHALL show the corresponding empty/pending state
|
||||
- **AND** the client SHALL not present `current_package_expires_at` as if it were the final calculated expiry
|
||||
@@ -0,0 +1,29 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Real-name behavior SHALL use the effective backend asset policy
|
||||
|
||||
The H5/C client SHALL use `GET /api/c/v1/asset/info?identifier=...` as the source of truth for real-name behavior. It SHALL consume `effective_realname_policy`, `realname_required`, and `real_name_status` and SHALL NOT infer policy or final device real-name status from asset type, card type, device type, or frontend-only rules.
|
||||
|
||||
#### Scenario: Asset does not require real name
|
||||
|
||||
- **WHEN** asset information returns `effective_realname_policy = none` or `realname_required = false`
|
||||
- **THEN** the client SHALL show the asset as not requiring real-name completion
|
||||
- **AND** the client SHALL not block the normal order flow for real-name completion
|
||||
|
||||
#### Scenario: Real name is required before ordering
|
||||
|
||||
- **WHEN** asset information returns `effective_realname_policy = before_order`, `realname_required = true`, and `real_name_status` as not completed
|
||||
- **THEN** the client SHALL show the real-name requirement
|
||||
- **AND** the client SHALL prevent package order submission until the existing real-name flow completes
|
||||
|
||||
#### Scenario: Real name is required after ordering
|
||||
|
||||
- **WHEN** asset information returns `effective_realname_policy = after_order`
|
||||
- **THEN** the client SHALL allow the policy-defined post-order flow to proceed without applying a before-order block
|
||||
- **AND** the client SHALL display the returned real-name status and retain the existing real-name action entry when completion is needed
|
||||
|
||||
#### Scenario: Device status is resolved from server output
|
||||
|
||||
- **WHEN** a device has cards with different local-looking real-name states but the asset info response returns the effective device `real_name_status`
|
||||
- **THEN** the client SHALL display and use that returned effective status
|
||||
- **AND** the client SHALL not replace it with a card/device inference
|
||||
@@ -0,0 +1,70 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Payment options SHALL be rendered from backend permissions
|
||||
|
||||
The H5/C client SHALL use `allowed_payment_methods` from asset information and the recharge-check response to determine which payment methods are visible and selectable. It SHALL support the backend values `wallet`, `wechat`, and `alipay` where returned, and SHALL not hard-code a card/device payment-method matrix.
|
||||
|
||||
#### Scenario: Asset payment methods are returned
|
||||
|
||||
- **WHEN** asset information returns a non-empty `allowed_payment_methods` list
|
||||
- **THEN** the package payment UI SHALL render exactly the methods allowed by that list
|
||||
- **AND** the client SHALL not offer a method absent from the list
|
||||
|
||||
#### Scenario: Recharge permissions differ from asset permissions
|
||||
|
||||
- **WHEN** `/api/c/v1/wallet/recharge-check` returns its own `allowed_payment_methods` value
|
||||
- **THEN** the wallet recharge UI SHALL use the recharge-check value for that recharge attempt
|
||||
- **AND** the client SHALL not reuse a stale package-payment method list
|
||||
|
||||
### Requirement: Payment creation SHALL submit the selected method and the required WeChat app type
|
||||
|
||||
The client SHALL submit `identifier`, the relevant package or amount fields, and the user-selected `payment_method` to the applicable creation endpoint. It SHALL submit `app_type` only when `payment_method = wechat`, using the endpoint-defined value `official_account` or `miniapp`.
|
||||
|
||||
#### Scenario: Create a package order
|
||||
|
||||
- **WHEN** the user submits an allowed package payment method
|
||||
- **THEN** the client SHALL call `POST /api/c/v1/orders/create` with `identifier`, `package_ids`, and the selected `payment_method`
|
||||
- **AND** the client SHALL include `app_type` for WeChat payment as required
|
||||
|
||||
#### Scenario: Create a wallet recharge
|
||||
|
||||
- **WHEN** the user submits an allowed recharge method and an amount within backend limits
|
||||
- **THEN** the client SHALL call `POST /api/c/v1/wallet/recharge` with the integer amount in cents, identifier, and selected payment method
|
||||
- **AND** the client SHALL include `app_type` only for WeChat payment
|
||||
|
||||
#### Scenario: User-facing currency conversion
|
||||
|
||||
- **WHEN** an amount is returned by an API in cents
|
||||
- **THEN** the client SHALL display the corresponding yuan value
|
||||
- **AND** the client SHALL submit the original integer-cent representation to the API
|
||||
|
||||
### Requirement: Recharge submission SHALL honor the backend pre-check
|
||||
|
||||
The client SHALL call `GET /api/c/v1/wallet/recharge-check?identifier=...` before starting a recharge. When `need_force_recharge = true`, it SHALL use `force_recharge_amount`, `min_amount`, `max_amount`, and `message` from the response to guide or block the recharge flow.
|
||||
|
||||
#### Scenario: Force recharge is required
|
||||
|
||||
- **WHEN** recharge-check returns `need_force_recharge = true`
|
||||
- **THEN** the client SHALL present the backend force-recharge amount and message
|
||||
- **AND** the client SHALL not submit a normal recharge that violates the returned requirement
|
||||
|
||||
#### Scenario: Recharge is permitted normally
|
||||
|
||||
- **WHEN** recharge-check returns `need_force_recharge = false` and the amount is within the returned range
|
||||
- **THEN** the client SHALL allow the user to select an allowed method and submit the recharge order
|
||||
|
||||
### Requirement: Payment results SHALL be confirmed by backend order state
|
||||
|
||||
After order creation, the client SHALL preserve existing handling for `pay_config` and `payment_link`, and SHALL use an order or recharge status query to confirm completion. A successful frontend redirect or payment-link return alone SHALL not be treated as proof of payment.
|
||||
|
||||
#### Scenario: Backend returns WeChat payment parameters
|
||||
|
||||
- **WHEN** a creation response contains `pay_config`
|
||||
- **THEN** the client SHALL invoke the existing WeChat payment flow
|
||||
- **AND** the client SHALL refresh backend payment status after the flow returns
|
||||
|
||||
#### Scenario: Backend returns a web payment link
|
||||
|
||||
- **WHEN** a creation response contains `payment_link`
|
||||
- **THEN** the client SHALL use the existing payment-link presentation/handling
|
||||
- **AND** the client SHALL confirm the resulting order or recharge state through the backend
|
||||
@@ -0,0 +1,23 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: C-end login SHALL honor asset verification access decisions
|
||||
|
||||
The H5/C client SHALL call `POST /api/c/v1/auth/verify-asset` before continuing the asset login flow. A business failure or C-end login restriction returned by the endpoint SHALL be shown using the backend business message, and the client SHALL NOT continue to obtain, persist, or use an asset token for that login attempt.
|
||||
|
||||
#### Scenario: Asset verification allows login
|
||||
|
||||
- **WHEN** asset verification succeeds and returns an asset token
|
||||
- **THEN** the client SHALL persist the identifier and returned asset token and continue the existing login flow
|
||||
|
||||
#### Scenario: Shop forbids a new C-end login
|
||||
|
||||
- **WHEN** asset verification returns a business failure indicating that the shop has forbidden C-end login
|
||||
- **THEN** the client SHALL display the backend error message
|
||||
- **AND** the client SHALL stop the current login flow before WeChat authorization or token persistence
|
||||
- **AND** the client SHALL not revoke an already-issued token as a side effect
|
||||
|
||||
#### Scenario: Asset verification fails without a usable token
|
||||
|
||||
- **WHEN** the verification request returns an error response or no usable asset token
|
||||
- **THEN** the client SHALL display the existing request/business error
|
||||
- **AND** the client SHALL leave the current login attempt unauthenticated
|
||||
@@ -0,0 +1,55 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: H5/C SHALL surface unread customer notifications
|
||||
|
||||
The H5/C client SHALL use `GET /api/c/v1/notifications/unread-count` for the homepage or notification-entry badge and `GET /api/c/v1/notifications` for the notification list. It SHALL consume the existing personal-notification contract and SHALL not add a separate API for expiry or exchange reminders.
|
||||
|
||||
#### Scenario: Unread notifications exist
|
||||
|
||||
- **WHEN** the unread-count endpoint returns a positive count
|
||||
- **THEN** the homepage or notification entry SHALL display the unread indicator using that count
|
||||
- **AND** the notification list entry SHALL remain available
|
||||
|
||||
#### Scenario: No unread notifications exist
|
||||
|
||||
- **WHEN** the unread-count endpoint returns zero
|
||||
- **THEN** the client SHALL clear the unread indicator
|
||||
- **AND** the notification entry SHALL not show a stale count
|
||||
|
||||
### Requirement: Expiry and exchange notices SHALL use the shared notification channel
|
||||
|
||||
The client SHALL display package-expiry and exchange-related notifications returned for the authenticated customer through the shared notification list or reminder popup. The backend notification data SHALL determine the expiry trigger and severity; the client SHALL not create independent timers that send business notifications.
|
||||
|
||||
#### Scenario: Package reaches a reminder threshold
|
||||
|
||||
- **WHEN** the notification service returns an unread package-expiry notice for the 15-day, 7-day, or 3-day threshold
|
||||
- **THEN** the client SHALL display it through the existing H5/C notification entry or popup
|
||||
- **AND** the client SHALL use the returned expiry level for presentation
|
||||
|
||||
#### Scenario: Critical expiry notice has highest priority
|
||||
|
||||
- **WHEN** unread expiry notices include a notice for 0 to 3 remaining days
|
||||
- **THEN** the client SHALL give that notice the highest reminder priority
|
||||
- **AND** the client SHALL not downgrade it based on a client-side date calculation
|
||||
|
||||
#### Scenario: Exchange notification is returned
|
||||
|
||||
- **WHEN** an exchange-related unread notice is returned after an exchange is created
|
||||
- **THEN** the notification entry/list SHALL display the notice
|
||||
- **AND** the client SHALL not call a separate marketing, ERP, or salesperson notification endpoint
|
||||
|
||||
### Requirement: Viewing a notification SHALL support marking it read
|
||||
|
||||
When the user views or activates a notification, the client SHALL call `PUT /api/c/v1/notifications/{id}/read` for that notification and reconcile the local unread count after a successful response. Repeated read actions SHALL remain safe according to the existing notification API contract.
|
||||
|
||||
#### Scenario: User reads an unread notice
|
||||
|
||||
- **WHEN** the user opens or advances to an unread expiry or exchange notification
|
||||
- **THEN** the client SHALL mark that notification read through the existing endpoint
|
||||
- **AND** the badge/list state SHALL reflect the read result
|
||||
|
||||
#### Scenario: Notification read request fails
|
||||
|
||||
- **WHEN** marking a notification read fails
|
||||
- **THEN** the client SHALL retain the unread state or refresh it from the backend
|
||||
- **AND** the failure SHALL not prevent the user from viewing other asset or notification content
|
||||
@@ -0,0 +1,38 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Discontinued packages SHALL remain renewable only for eligible existing customers
|
||||
|
||||
The H5/C client SHALL keep discontinued packages out of the ordinary package catalog shown to new customers and agents. An eligible existing customer SHALL be able to use a valid `current_package_id` from asset info or `package_ids` from a historical order to continue a package renewal.
|
||||
|
||||
#### Scenario: New customer opens the package catalog
|
||||
|
||||
- **WHEN** the package catalog contains a discontinued package that is not the customer's current package
|
||||
- **THEN** the client SHALL not display that package as an ordinary purchase option
|
||||
|
||||
#### Scenario: Existing customer is using a discontinued current package
|
||||
|
||||
- **WHEN** asset info returns a discontinued package through `current_package_id`
|
||||
- **THEN** the client SHALL expose that ID only in the eligible renewal context
|
||||
- **AND** the client SHALL allow the customer to continue through the existing package-order flow
|
||||
|
||||
#### Scenario: Existing customer renews from a historical order
|
||||
|
||||
- **WHEN** a historical order returns one or more valid `package_ids`
|
||||
- **THEN** the client SHALL use those IDs for the renewal selection when the existing renewal flow provides that entry
|
||||
- **AND** the client SHALL preserve the historical order data unchanged
|
||||
|
||||
### Requirement: Renewal SHALL reuse the standard order creation contract
|
||||
|
||||
The client SHALL create a renewal by calling `POST /api/c/v1/orders/create` with the selected package ID or IDs, the asset `identifier`, and a currently allowed `payment_method`. It SHALL not invent or call a dedicated discontinued-package renewal endpoint.
|
||||
|
||||
#### Scenario: Submit a discontinued-package renewal
|
||||
|
||||
- **WHEN** an eligible customer confirms a renewal with an allowed payment method
|
||||
- **THEN** the client SHALL submit the selected package IDs, identifier, and payment method to the standard order endpoint
|
||||
- **AND** the client SHALL follow the standard payment response handling
|
||||
|
||||
#### Scenario: No eligible package ID is available
|
||||
|
||||
- **WHEN** neither asset info nor the relevant historical order supplies a valid package ID
|
||||
- **THEN** the client SHALL show that renewal is unavailable
|
||||
- **AND** the client SHALL not guess an ID from the ordinary package catalog
|
||||
@@ -0,0 +1,47 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Order views SHALL display backend role and asset snapshots
|
||||
|
||||
The H5/C client SHALL use `GET /api/c/v1/orders` and `GET /api/c/v1/orders/{id}` as the source of truth for order display. Order list and detail views SHALL display the backend `purchase_role` and `asset_identifier` values when present.
|
||||
|
||||
#### Scenario: Order includes a purchase role
|
||||
|
||||
- **WHEN** an order response returns `purchase_role`
|
||||
- **THEN** the order list and detail view SHALL render that role
|
||||
- **AND** the client SHALL not infer the role from the current user or asset type
|
||||
|
||||
#### Scenario: Card order includes an asset identifier
|
||||
|
||||
- **WHEN** a card order returns an `asset_identifier` snapshot
|
||||
- **THEN** the client SHALL display the returned card identifier, such as ICCID, without replacing it with a current asset lookup
|
||||
|
||||
### Requirement: Device order identifiers SHALL prefer virtual number over IMEI
|
||||
|
||||
For device orders, the client SHALL display `virtual_no`/`VirtualNo` when it is non-empty, and SHALL use `imei` only when the virtual number is empty. The client SHALL not use `sn` as a substitute for the order asset identifier.
|
||||
|
||||
#### Scenario: Device has a virtual number
|
||||
|
||||
- **WHEN** a device order response contains a non-empty virtual number and an IMEI
|
||||
- **THEN** the client SHALL display the virtual number
|
||||
- **AND** the client SHALL not display SN as the order device identifier
|
||||
|
||||
#### Scenario: Device virtual number is empty
|
||||
|
||||
- **WHEN** a device order response has an empty virtual number and a non-empty IMEI
|
||||
- **THEN** the client SHALL display the IMEI
|
||||
|
||||
#### Scenario: Historical identifier data is empty
|
||||
|
||||
- **WHEN** both the virtual number and IMEI are absent or empty
|
||||
- **THEN** the client SHALL show the existing empty placeholder
|
||||
- **AND** the client SHALL not fabricate an identifier from SN or a new asset-info request
|
||||
|
||||
### Requirement: Order amounts SHALL use the common currency display rule
|
||||
|
||||
Order list and detail views SHALL display `total_amount` and package prices converted from integer cents to yuan while preserving the integer-cent values in API requests and response state.
|
||||
|
||||
#### Scenario: Display an order amount
|
||||
|
||||
- **WHEN** an order response returns an amount in cents
|
||||
- **THEN** the client SHALL render the corresponding yuan value
|
||||
- **AND** the client SHALL not expose the raw cent value as the user-facing amount
|
||||
49
openspec/changes/update-july-h5-c-iteration/tasks.md
Normal file
49
openspec/changes/update-july-h5-c-iteration/tasks.md
Normal file
@@ -0,0 +1,49 @@
|
||||
## 1. API adapters and shared rules
|
||||
|
||||
- [x] 1.1 Update asset/auth adapters and login handling for `verify-asset` business failures before asset-token persistence
|
||||
- [x] 1.2 Normalize asset response fields for real-name policy/status, allowed payment methods, expiry estimate, and device/card identifiers
|
||||
- [x] 1.3 Update order and wallet adapters so every create request includes the selected `payment_method`, and only WeChat requests include `app_type`
|
||||
- [x] 1.4 Preserve cent-based request payloads and provide one shared yuan display formatter for amounts
|
||||
- [x] 1.5 Confirm notification adapter parameters and response handling against the pending `add-personal-notifications` change
|
||||
|
||||
## 2. Login and asset state
|
||||
|
||||
- [x] 2.1 Show the backend business error and stop the current login flow when C-end login is forbidden
|
||||
- [x] 2.2 Drive real-name prompts, status labels, and order gates from `effective_realname_policy`, `realname_required`, and `real_name_status`
|
||||
- [x] 2.3 Remove local card/device real-name policy inference while preserving the existing real-name link flow
|
||||
- [x] 2.4 Replace current-package-only expiry display with `estimated_final_expires_at` and apply backend expiry status/highlight fields
|
||||
|
||||
## 3. Package purchase and renewal
|
||||
|
||||
- [x] 3.1 Render payment options from `allowed_payment_methods` on package purchase and prevent unavailable methods from being selected
|
||||
- [x] 3.2 Keep discontinued packages out of the ordinary package catalog for new customers and agents
|
||||
- [x] 3.3 Add the eligible existing-customer renewal path using `current_package_id` or historical `package_ids`
|
||||
- [x] 3.4 Reuse `POST /api/c/v1/orders/create` for renewal and preserve selected identifier, package IDs, payment method, and existing payment result handling
|
||||
|
||||
## 4. Wallet recharge and payment completion
|
||||
|
||||
- [x] 4.1 Call `/api/c/v1/wallet/recharge-check` before recharge and enforce backend force-recharge/min/max guidance in the UI
|
||||
- [x] 4.2 Render recharge payment methods from the recharge-check response and submit the selected method
|
||||
- [x] 4.3 Preserve existing WeChat `pay_config`, Alipay/other `payment_link`, wallet payment, and submit-guard behaviors
|
||||
- [x] 4.4 Refresh and confirm order/recharge status from the backend after payment return or link completion
|
||||
|
||||
## 5. Customer notifications
|
||||
|
||||
- [x] 5.1 Refresh unread count at the homepage or notification entry using `/api/c/v1/notifications/unread-count`
|
||||
- [x] 5.2 Display expiry and exchange notifications from `/api/c/v1/notifications`, including backend severity/expiry level
|
||||
- [x] 5.3 Mark an item read with `/api/c/v1/notifications/{id}/read` when the user views or activates it, then reconcile the unread badge
|
||||
- [x] 5.4 Keep notification failures non-blocking for asset loading and do not add WeCom, marketing, or ERP calls
|
||||
|
||||
## 6. Order display
|
||||
|
||||
- [x] 6.1 Render `purchase_role` from order list/detail responses
|
||||
- [x] 6.2 Render `asset_identifier` snapshots, using device `virtual_no` first and `imei` second, never SN as a substitute
|
||||
- [x] 6.3 Preserve blank historical data as an empty-state placeholder and format order amounts from cents to yuan
|
||||
|
||||
## 7. Verification
|
||||
|
||||
- [ ] 7.1 Add or update tests for login denial, all real-name policies, backend payment-method variations, and WeChat `app_type`
|
||||
- [ ] 7.2 Add or update tests for force recharge, discontinued-package renewal, expiry estimate states, notification priority/read flow, and order identifier fallback
|
||||
- [x] 7.3 Run the H5 compiler build and repository consistency checks; manual API fixture verification remains an integration follow-up
|
||||
|
||||
> Note: This H5 repository has no test script or test suite. Tasks 7.1 and 7.2 remain unchecked and require adding a test harness or backend/API fixture environment before they can be completed.
|
||||
Reference in New Issue
Block a user