# Quickstart: 蓝新金流(NewebPay)线上支付接入

**Feature**: specs/011-newebpay-payment/spec.md
**Date**: 2026-06-22

端到端验证指南。实现完成后按此验证「下单 → 付款 → 订单已支付」主链路与回调安全。

---

## 前置条件

1. **数据库**: 已执行 `updatesql/sql.md` 中本期两段 DDL（`pos_store_newebpay`、`pos_order_payment`）。
2. **配置**: `ruoyi-admin/src/main/resources/application.yml` 已加 `newebpay` 段：
   - `base-url`: 测试环境用 `https://ccore.newebpay.com`
   - `notify-url` / `return-url`: 本机开发需用内网穿透（ngrok/frp）映射到本地 8082 端口的公网域名，如 `https://xxx.ngrok-free.app/pay/newebpay/notify`。
3. **蓝新测试商店**: 在蓝新测试区（ccore）申请测试商店，取得 `MerchantID` / `HashKey` / `HashIV`。
4. **测试卡**: 蓝新测试区信用卡测试卡号（NDNF 附录1），如 `4000-2211-1111-1111`（成功卡）、有效日期/安全码按附录。

---

## 场景 1：门店开通蓝新凭证

1. 平台后台进「门店蓝新支付开通」列表 → 选门店 → 发起申请（状态→申请中）。
2. 录入测试 `MerchantID/HashKey/HashIV` + 勾选启用支付方式（CREDIT/LINEPAY/APPLEPAY）→ 保存。
3. **预期**: 系统调 QueryTradeInfo 探测，凭证有效 → 状态「已开通」、`last_verify_result=PASS`；无效 → 提示「凭证无效」、状态不变。
4. **验证**: `SELECT newebpay_status,is_enabled,enabled_payments FROM pos_store_newebpay WHERE store_id=?` → status=2, is_enabled=1。

---

## 场景 2：信用卡支付主链路（核心 P1）

1. C 端用户对「已开通蓝新」的门店下一笔订单（任意类型）。
2. 调发起支付: `POST /pay/newebpay/create?orderid={ddId}`（带用户 token）。
   - **预期 200**: 返回 `data.gatewayUrl/MerchantID/TradeInfo/TradeSha/Version/EncryptType`。
   - **DB**: `pos_order_payment` 新增一行（merchant_order_no=NB+ddId, pay_status=0）；`pos_order.pay_type=6`、`pay_url=gatewayUrl`。
3. 前端用返回字段构建隐藏 form 自动 submit → 跳转蓝新 MPG 付款页。
4. 在蓝新付款页选**信用卡**，输入测试卡号 + 有效期 + 安全码 → 送出。
5. **预期**: 付款成功后蓝新跳回 ReturnURL（重定向到前端结果页）；蓝新同时 POST 到 NotifyURL。
6. **NotifyURL 处理**:
   - 解密 TradeInfo、验签 TradeSha 通过。
   - 金额 == 订单 amount。
   - `pos_order.pay_status` 由 0 → 1。
   - `pos_order_payment` 写入 trade_no、pay_type=CREDIT、auth_code、pay_time、pay_status=1。
   - 订单日志记录「系统收到支付成功回调」。
7. **验证**: 订单列表/详情显示「已支付」，商家端/骑手收到新订单推送。

---

## 场景 3：回调安全（幂等 + 金额不符 + 伪造）

1. **幂等**: 把场景2的成功回调报文（含 trade_no）再 POST 到 `/pay/newebpay/notify` 一次。
   - **预期**: 订单状态不变（不重复推送、不重复记账），仍返回成功应答。
2. **金额不符**: 构造一笔 TradeInfo 中 Amt 与订单 amount 不一致的合法签名回调。
   - **预期**: 订单 pay_status 不变，`pos_order_payment`/日志记录「金额不一致」告警。
3. **伪造签名**: 篡改 TradeSha 后 POST。
   - **预期**: 验签失败，订单不变，记录告警。

---

## 场景 4：LINE Pay / Apple Pay（P2）

1. 发起支付同场景2（门店 enabled_payments 含 LINEPAY/APPLEPAY）。
2. 蓝新付款页选 **LINE Pay**（跳转 LINE 测试环境完成）或 **Apple Pay**（需 Apple Pay 环境/设备）。
3. **预期**: 回调到达后订单已支付，`pos_order_payment.pay_type` 分别为 LINEPAY / APPLEPAY。

> 注：Apple Pay 需 Apple Developer 配置与 HTTPS 域名验证；测试环境受限时可先验证信用卡 + LINE Pay，Apple Pay 在具备条件时补测。

---

## 场景 5：单笔查询补单（P3）

1. 模拟回调丢失：付款成功但人为不触发 NotifyURL（订单 pay_status 仍 0）。
2. 商家/运营调 `POST /pay/newebpay/query?orderid={ddId}`。
3. **预期**: 系统调蓝新 QueryTradeInfo 返回 TradeStatus=1，检测到订单未支付 → 补单（pay_status→1、写流水、推送）。
4. **验证**: 订单变为已支付。

---

## 场景 6：未开通/停用门店

1. 对未开通蓝新（无 pos_store_newebpay 行 / status≠2）或已停用（is_enabled=0）的门店下单。
2. 调发起支付。
3. **预期**: 返回错误「该门店暂不支持在线支付」，不生成交易。

---

## 加密自测（无需联网）

运行 `NewebPayEncryptUtil.main`（实现时加入），用 NDNF §4.1 官方示例数据验证：
- AES-256-CBC/PKCS7 加解密 round-trip。
- TradeSha 规则: `SHA256("HashKey={key}&{tradeInfoHex}&HashIV={iv}")` 大写。
- 明文示例 `MerchantID=MS127874575&RespondType=String&TimeStamp=...&Version=2.3&...` 加密后 hex 可被蓝新测试环境接受（场景2 即端到端验证）。

全部通过后方可进入场景1。
