|
|
@@ -0,0 +1,607 @@
|
|
|
+# OMG 支付方案讨论记录
|
|
|
+
|
|
|
+## 记录信息
|
|
|
+
|
|
|
+- 会话 ID:`019fe942-4fb3-7701-b8d6-70f141f7774d`
|
|
|
+- 讨论日期:2026-08-10
|
|
|
+- 讨论主题:OMG 多店铺、夜市摊位、平台商模式、LINE Pay 扩展及店铺端收款设置
|
|
|
+- 名称说明:早期讨论中多次写作 `OGM`,实际支付渠道名称为 `OMG`
|
|
|
+
|
|
|
+## 当前最终决策
|
|
|
+
|
|
|
+经过完整讨论后,当前阶段采用最简单的店铺级支付配置方案:
|
|
|
+
|
|
|
+1. Foodie 平台不代收、不分账,款项由支付渠道直接结算给商户。
|
|
|
+2. 支付设置直接放在店铺管理中,不额外抽象通用的支付账户和店铺绑定体系。
|
|
|
+3. OMG 继续使用现有店铺级配置表 `pos_store_omg`;以后接入 LINE Pay 时,可增加店铺级的 `pos_store_linepay`。
|
|
|
+4. 暂不实现 `PlatformID`、平台商、子商户、平台结算主体及二次结算逻辑。
|
|
|
+5. 多店铺场景较少,不为少量场景预先增加复杂架构。
|
|
|
+6. 如果少量多店铺需要共用同一个 OMG 商户:各店保存相同的 `MerchantID / HashKey / HashIV`,使用不同的 OMG `StoreID`;回调通过 `MerchantTradeNo` 定位订单和店铺。
|
|
|
+7. `HashKey / HashIV / Channel Secret` 等敏感凭证必须加密保存,管理页面只显示掩码。
|
|
|
+
|
|
|
+当前简化关系:
|
|
|
+
|
|
|
+```text
|
|
|
+店铺
|
|
|
+ └─ 店铺收款设置
|
|
|
+ ├─ OMG 配置
|
|
|
+ └─ LINE Pay 配置(后续)
|
|
|
+
|
|
|
+支付渠道
|
|
|
+ └─ 款项直接结算给商户
|
|
|
+
|
|
|
+Foodie
|
|
|
+ ├─ 发起支付
|
|
|
+ ├─ 校验支付回调
|
|
|
+ ├─ 更新订单状态
|
|
|
+ └─ 提供查询、退款等技术功能
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 第一轮:一个商户有多个店铺时,OMG 如何区分
|
|
|
+
|
|
|
+### 用户问题
|
|
|
+
|
|
|
+> ogm 支付不能再后台自己管理店铺新增多个店铺吗?我们的系统现在一个商户可能会有多个店铺,ogm怎么区分
|
|
|
+
|
|
|
+### 分析过程
|
|
|
+
|
|
|
+- 检查项目现有 OMG 支付实现和数据库设计。
|
|
|
+- 确认当前代码按 `pos_store.id` 读取 OMG 凭证。
|
|
|
+- 确认当前回调按 OMG `MerchantID` 反查店铺。
|
|
|
+- 核对 OMG 是否允许同一 `MerchantID` 下使用多个门店标识。
|
|
|
+
|
|
|
+### 结论
|
|
|
+
|
|
|
+OMG 提供 `StoreID` 区分同一商户旗下的多个店铺:
|
|
|
+
|
|
|
+- `MerchantID`:OMG 特店编号,代表收款商户或结算主体。
|
|
|
+- `StoreID`:该特店旗下的分店代号,最长 20 位,只能使用英文字母和数字。
|
|
|
+- 支付成功回调会原样返回 `StoreID`,可用于核对订单所属门店。
|
|
|
+
|
|
|
+官方文档:
|
|
|
+
|
|
|
+- [OMG 产生订单文档](https://developers-stage.omg.com.tw/payment/aio/api/01_order.html)
|
|
|
+- [OMG 付款通知文档](https://developers-stage.omg.com.tw/payment/aio/api/03_payment_notify.html)
|
|
|
+
|
|
|
+示例:
|
|
|
+
|
|
|
+```text
|
|
|
+商户 user_id = 88
|
|
|
+OMG MerchantID = 2000132
|
|
|
+
|
|
|
+门店 1001 → StoreID = S1001
|
|
|
+门店 1002 → StoreID = S1002
|
|
|
+门店 1003 → StoreID = S1003
|
|
|
+```
|
|
|
+
|
|
|
+发起门店 1002 的订单时:
|
|
|
+
|
|
|
+```text
|
|
|
+MerchantID=2000132
|
|
|
+StoreID=S1002
|
|
|
+MerchantTradeNo=OMGxxxxxxxxxxxxxxxxx
|
|
|
+```
|
|
|
+
|
|
|
+当时发现的当前实现问题:
|
|
|
+
|
|
|
+- 下单只传 `MerchantID`,没有传 `StoreID`。
|
|
|
+- `pos_store_omg` 按门店保存整套凭证。
|
|
|
+- `merchant_id` 设置了唯一索引。
|
|
|
+- 回调直接使用 `MerchantID` 反查唯一门店。
|
|
|
+
|
|
|
+因此,当时的实现实际上强制“一店一个 MerchantID”。如果同一商户的多个门店共用一个 `MerchantID`,第二个门店会遇到唯一索引冲突。
|
|
|
+
|
|
|
+当时建议的完整模型是“一商户一套 OMG 凭证,多门店各自使用一个 StoreID”;最终方案后来根据业务规模进一步简化为店铺级配置。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 第二轮:StoreID 是否需要在 OMG 后台管理
|
|
|
+
|
|
|
+### 用户问题
|
|
|
+
|
|
|
+> 但是omg 后台管理没有店铺管理,传人storeId是可以自定义吗?还是需要在omg 那边管理?
|
|
|
+
|
|
|
+### 分析过程
|
|
|
+
|
|
|
+- 核对 OMG 官方文档中 `StoreID` 的填写与回传规则。
|
|
|
+- 重点确认是否需要预先在 OMG 后台登记门店。
|
|
|
+- 区分“交易归属标识”与“独立结算账户”。
|
|
|
+
|
|
|
+### 结论
|
|
|
+
|
|
|
+`StoreID` 可以由 Foodie 自行定义并随订单传入,不需要先在 OMG 后台新增门店。
|
|
|
+
|
|
|
+OMG 对 `StoreID` 的限制:
|
|
|
+
|
|
|
+- 最长 20 位。
|
|
|
+- 只能使用大小写英文字母和数字。
|
|
|
+- 付款回调会原样返回 `StoreID`。
|
|
|
+
|
|
|
+官方文档没有说明需要预先登记,也没有提供新增门店 API。
|
|
|
+
|
|
|
+建议生成方式:
|
|
|
+
|
|
|
+```text
|
|
|
+pos_store.id = 123
|
|
|
+OMG StoreID = S123
|
|
|
+```
|
|
|
+
|
|
|
+发起支付:
|
|
|
+
|
|
|
+```text
|
|
|
+MerchantID=2000132
|
|
|
+StoreID=S123
|
|
|
+MerchantTradeNo=OMGxxxxxxxxxxxxxxxxx
|
|
|
+```
|
|
|
+
|
|
|
+需要注意:`StoreID` 只是交易归属标识,不是 OMG 的独立子商户账户。使用同一个 OMG 商户账户的所有店铺仍然:
|
|
|
+
|
|
|
+- 共用 `MerchantID / HashKey / HashIV`。
|
|
|
+- 共用结算账户和费率。
|
|
|
+- 在 OMG 层属于同一个特店。
|
|
|
+
|
|
|
+如果要求每个门店分别结算或绑定不同银行账户,则需要各自申请 `MerchantID`,不能只依赖 `StoreID`。
|
|
|
+
|
|
|
+OMG 后台是否支持按 `StoreID` 筛选或导出报表,公开文档没有保证,需要向 OMG 商务确认;但支付接口本身支持使用 `StoreID` 区分门店。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 第三轮:平台商和子商户模式是什么
|
|
|
+
|
|
|
+### 用户问题
|
|
|
+
|
|
|
+> 平台商/子商户模式又是什么
|
|
|
+
|
|
|
+### 分析过程
|
|
|
+
|
|
|
+- 按 OMG 对 `PlatformID` 的定义,区分平台商模式和普通的 `MerchantID + StoreID` 模式。
|
|
|
+- 讨论代收、结算、商户审核和平台责任。
|
|
|
+- 确认不能只根据接口字段推断平台是否具有代收或分账权限。
|
|
|
+
|
|
|
+### 结论
|
|
|
+
|
|
|
+平台商/子商户模式面向 Foodie 这种聚合多个独立商家的平台,不等同于同一商户的多门店。
|
|
|
+
|
|
|
+可以理解为三级:
|
|
|
+
|
|
|
+| 层级 | OMG 字段 | 示例 |
|
|
|
+|---|---|---|
|
|
|
+| Foodie 平台 | `PlatformID` | Foodie |
|
|
|
+| 独立餐饮商户 | `MerchantID` | 王记餐饮公司 |
|
|
|
+| 商户旗下门店 | `StoreID` | 台北店、桃园店 |
|
|
|
+
|
|
|
+支付请求示例:
|
|
|
+
|
|
|
+```text
|
|
|
+PlatformID = Foodie 的平台商编号
|
|
|
+MerchantID = 王记餐饮的 OMG 特店编号
|
|
|
+StoreID = 王记台北店的自定义门店代号
|
|
|
+```
|
|
|
+
|
|
|
+字段含义:
|
|
|
+
|
|
|
+- `PlatformID`:OMG 审核后提供给专案合作平台,不能自行生成;普通特店应留空。
|
|
|
+- `MerchantID`:每个独立收款商户的特店编号。
|
|
|
+- `StoreID`:商户内部自行定义的门店标识,不是独立收款账户。
|
|
|
+
|
|
|
+示例:
|
|
|
+
|
|
|
+```text
|
|
|
+Foodie PlatformID = P00001
|
|
|
+
|
|
|
+商户 A:
|
|
|
+ MerchantID = M10001
|
|
|
+ 门店 A1 → StoreID = S101
|
|
|
+ 门店 A2 → StoreID = S102
|
|
|
+
|
|
|
+商户 B:
|
|
|
+ MerchantID = M10002
|
|
|
+ 门店 B1 → StoreID = S201
|
|
|
+```
|
|
|
+
|
|
|
+平台商模式通常需要:
|
|
|
+
|
|
|
+- Foodie 与 OMG 签约并开通平台商资格。
|
|
|
+- OMG 分配 `PlatformID`。
|
|
|
+- 每个子商户按照合作方案开户、审核、绑定银行卡并取得 `MerchantID`。
|
|
|
+- 分账、直接结算和平台抽佣能力需要 OMG 通过合同和接口明确支持。
|
|
|
+
|
|
|
+如果只是一个商户经营多个门店,使用 `MerchantID + StoreID` 即可,不需要平台商模式。
|
|
|
+
|
|
|
+最终业务已明确 Foodie 不代收、不分账,因此当前阶段不采用平台商/子商户模式。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 第四轮:夜市每个摊位是否都需要申请商户
|
|
|
+
|
|
|
+### 用户问题
|
|
|
+
|
|
|
+> 现在有个问题是,夜市有很多摊位,每个摊位也要也能申请一个商户吗?开一个商户会不会门槛比较高?
|
|
|
+
|
|
|
+### 分析过程
|
|
|
+
|
|
|
+- 将问题从接口字段提升到实际收款主体和结算责任。
|
|
|
+- 核对 OMG 当时公开的申请材料、审核要求和费用。
|
|
|
+- 对比摊位独立收款、夜市统一收款以及平台子商户三种方案。
|
|
|
+
|
|
|
+### 结论
|
|
|
+
|
|
|
+如果每个摊位由不同老板经营,并且款项需要进入不同银行账户,那么每个摊位原则上应使用独立 OMG 商户账户。
|
|
|
+
|
|
|
+OMG 当时公开支持自然人和公司户申请,但仍需提交收款资料并经过审核,不是注册账号后就能自动开通。
|
|
|
+
|
|
|
+当时查询到的公开费用(截至 2026-08-10):
|
|
|
+
|
|
|
+- 设置费:NT$1,000/次。
|
|
|
+- 年费:NT$5,000/年。
|
|
|
+- 信用卡/Apple Pay:2.95%,最低 NT$5/笔。
|
|
|
+- ATM:1%,最低 NT$15/笔。
|
|
|
+- 超商代码:NT$38/笔。
|
|
|
+- 30 日收款额度:最高 NT$200,000。
|
|
|
+
|
|
|
+相关资料:
|
|
|
+
|
|
|
+- [OMG 注册页面](https://www.funpoint.com.tw/member/register)
|
|
|
+- [OMG 收款服务规范](https://www.funpoint.com.tw/terms/provisionlogistics)
|
|
|
+- [OMG 费用说明](https://www.funpoint.com.tw/info/fee)
|
|
|
+
|
|
|
+100 个独立摊位按公开价格各开一个普通商户的示例:
|
|
|
+
|
|
|
+```text
|
|
|
+首年固定费用:
|
|
|
+100 × (1,000 + 5,000) = NT$600,000
|
|
|
+
|
|
|
+以后每年:
|
|
|
+100 × 5,000 = NT$500,000
|
|
|
+```
|
|
|
+
|
|
|
+因此,大量小摊位逐个开户的经济和运营门槛较高。
|
|
|
+
|
|
|
+讨论中曾考虑:
|
|
|
+
|
|
|
+| 夜市场景 | 方案 |
|
|
|
+|---|---|
|
|
|
+| 所有摊位由同一家公司经营、统一收款和报税 | 一个 `MerchantID`,不同摊位使用不同 `StoreID` |
|
|
|
+| 每个摊位是独立老板,款项直接给各摊位 | 每摊位独立 `MerchantID` |
|
|
|
+| 每个摊位独立,平台统一技术接入和批量开户 | 与 OMG 商谈 `PlatformID + 子商户` |
|
|
|
+| 夜市统一代收后再给摊位结算 | 必须取得 OMG 对代收、分账方案的明确认可 |
|
|
|
+
|
|
|
+最终业务已明确 Foodie 不参与收款。因此平台不会使用自己的 `MerchantID` 代收再结算;每个店铺或摊位应绑定最终实际收款商户的支付配置。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 第五轮:为了灵活性,支付信息是否应该放在店铺管理
|
|
|
+
|
|
|
+### 用户问题
|
|
|
+
|
|
|
+> 现在使用哪种商户方案没不能确定,为了保持最好的灵活度,支付信息是不是还是应该放在店铺来管理?
|
|
|
+
|
|
|
+### 分析过程
|
|
|
+
|
|
|
+- 区分“门店操作入口”和“支付凭证归属”。
|
|
|
+- 评估当前 `pos_store_omg` 是否会把系统限制为“一店一 MerchantID”。
|
|
|
+- 研究通过支付账户和门店绑定关系支持多种商户方案的可能性。
|
|
|
+
|
|
|
+### 当时结论
|
|
|
+
|
|
|
+当时建议把数据拆为两层:
|
|
|
+
|
|
|
+```text
|
|
|
+OMG支付账户 pos_omg_account
|
|
|
+ ├─ 账户模式
|
|
|
+ ├─ PlatformID
|
|
|
+ ├─ MerchantID
|
|
|
+ ├─ HashKey/HashIV
|
|
|
+ ├─ 所属收款主体
|
|
|
+ └─ 申请、审核、环境、状态
|
|
|
+
|
|
|
+门店绑定 pos_store_omg
|
|
|
+ ├─ store_id
|
|
|
+ ├─ omg_account_id
|
|
|
+ ├─ omg_store_id
|
|
|
+ ├─ is_enabled
|
|
|
+ └─ enabled_payments
|
|
|
+```
|
|
|
+
|
|
|
+该设计可以覆盖:
|
|
|
+
|
|
|
+```text
|
|
|
+一店一商户:
|
|
|
+门店A → OMG账户A
|
|
|
+
|
|
|
+一个商户多店:
|
|
|
+门店A ─┐
|
|
|
+门店B ─┼→ 同一个OMG账户,不同StoreID
|
|
|
+门店C ─┘
|
|
|
+
|
|
|
+平台子商户:
|
|
|
+门店A → 子商户账户A
|
|
|
+门店B → 子商户账户B
|
|
|
+```
|
|
|
+
|
|
|
+当时形成的原则是:门店管理支付开关和账户绑定,支付账户管理商户身份、结算关系和敏感凭证。
|
|
|
+
|
|
|
+### 后续取舍
|
|
|
+
|
|
|
+在明确 Foodie 不代收且多店铺场景较少之后,决定不实施上述账户绑定抽象。当前阶段直接使用店铺级 `pos_store_omg` 配置,优先降低实现和操作复杂度。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 第六轮:普通商家店铺与夜市摊位的归属差异
|
|
|
+
|
|
|
+### 用户问题
|
|
|
+
|
|
|
+> 但是摊位的时候,用户关联摊位的逻辑跟商家用户关联店铺的逻辑不太一样。你先看看他们之间的局别
|
|
|
+
|
|
|
+### 分析过程
|
|
|
+
|
|
|
+- 只分析现有关系,不修改代码。
|
|
|
+- 对比普通商家、夜市和摊位主的用户类型、关联字段、创建流程、查询权限和订单归属。
|
|
|
+- 核对摊位创建、摊位主管理、钱包和订单入账代码。
|
|
|
+
|
|
|
+### 结论
|
|
|
+
|
|
|
+普通商家和摊位是两套不同的归属模型,不能统一通过 `pos_store.user_id` 判断实际收款主体。
|
|
|
+
|
|
|
+| 对比项 | 普通商家店铺 | 夜市摊位 |
|
|
|
+|---|---|---|
|
|
|
+| 用户类型 | 商家 `userType=1` | 夜市 `userType=3`、摊位主 `userType=4` |
|
|
|
+| 店铺归属 | `PosStore.user_id = 商家ID` | `PosStore.user_id = 夜市ID` |
|
|
|
+| 摊位标识 | `is_stall=0` | `is_stall=1` |
|
|
|
+| 操作账号 | 商家本人管理多个店铺 | 多个摊位主共同管理一个摊位 |
|
|
|
+| 操作账号关联 | 用户 → 多店铺 | `InfoUser.store_id → 摊位ID` |
|
|
|
+| 钱包归属 | `UserWallet.user_id = 商家ID` | `UserWallet.store_id = 摊位ID` |
|
|
|
+| 收入主体 | 商家用户 | 摊位本身 |
|
|
|
+
|
|
|
+普通商家关系:
|
|
|
+
|
|
|
+```text
|
|
|
+InfoUser(type=1)
|
|
|
+ └─ 1:N PosStore(user_id=商家ID)
|
|
|
+ └─ 收入进入商家用户钱包
|
|
|
+```
|
|
|
+
|
|
|
+夜市摊位关系:
|
|
|
+
|
|
|
+```text
|
|
|
+InfoUser(type=3,夜市)
|
|
|
+ └─ 1:N PosStore(is_stall=1,user_id=夜市ID)
|
|
|
+ ├─ 1:N InfoUser(type=4,store_id=摊位ID)
|
|
|
+ └─ 1:1 UserWallet(store_id=摊位ID)
|
|
|
+```
|
|
|
+
|
|
|
+关键结论:
|
|
|
+
|
|
|
+> 对普通店铺,`pos_store.user_id` 是商家;对摊位,`pos_store.user_id` 是夜市管理者,不一定是实际摊位收款人。
|
|
|
+
|
|
|
+一个摊位可以有多个 `userType=4` 账号,目前系统没有标记哪个账号是法人、OMG 申请人或结算负责人。
|
|
|
+
|
|
|
+在当前简化方案下,支付配置仍直接挂在 `store_id`,由店铺或摊位明确填写最终实际收款商户的 OMG 凭证,不再通过 `pos_store.user_id` 自动推断支付商户身份。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 第七轮:后续接入 LINE Pay 是否有足够灵活度
|
|
|
+
|
|
|
+### 用户问题
|
|
|
+
|
|
|
+> 还要考虑后续接入line pay,这样是否对于接入新的支付存在灵活度
|
|
|
+
|
|
|
+### 分析过程
|
|
|
+
|
|
|
+- 将 OMG 和后续 LINE Pay 放入统一支付域模型进行评估。
|
|
|
+- 区分支付渠道 `provider` 与支付方式 `payment_method`。
|
|
|
+- 确认当前代码中的 `LINEPAY` 是蓝新金流提供的付款选项,不是 LINE Pay 直连。
|
|
|
+- 核对 LINE Pay 的 `Channel ID`、`Channel Secret`、HMAC 签名和交易流程。
|
|
|
+
|
|
|
+### 当时结论
|
|
|
+
|
|
|
+当时建议设计四层通用支付模型:
|
|
|
+
|
|
|
+```text
|
|
|
+店铺/摊位
|
|
|
+ ↓
|
|
|
+store_payment_binding
|
|
|
+ ↓
|
|
|
+payment_account
|
|
|
+ ↓
|
|
|
+OMG / LINE Pay 渠道凭证与适配器
|
|
|
+
|
|
|
+订单
|
|
|
+ ↓
|
|
|
+payment_attempt
|
|
|
+```
|
|
|
+
|
|
|
+该模型可支持:
|
|
|
+
|
|
|
+- 一个普通商户账户绑定多个店铺。
|
|
|
+- 一个夜市账户绑定多个摊位。
|
|
|
+- 某个摊位单独切换支付账户。
|
|
|
+- 同一个店铺同时启用 OMG 和 LINE Pay。
|
|
|
+- 不同渠道使用不同结算主体。
|
|
|
+- 将来新增其他支付渠道。
|
|
|
+
|
|
|
+LINE Pay 相关资料:
|
|
|
+
|
|
|
+- [LINE Pay 官方凭证说明](https://developers-pay.line.me/online/prerequisites)
|
|
|
+- [LINE Pay Online API v4](https://developers-pay.line.me/online-api-v4)
|
|
|
+- [LINE Pay 官方变更记录](https://developers-pay.line.me/api-change-log)
|
|
|
+
|
|
|
+### 后续取舍
|
|
|
+
|
|
|
+由于当前已明确:
|
|
|
+
|
|
|
+- Foodie 不代收、不分账。
|
|
|
+- 多店铺场景较少。
|
|
|
+- 当前首要目标是操作和实现简单。
|
|
|
+
|
|
|
+因此暂不建设通用四层支付模型。OMG 继续使用店铺级 `pos_store_omg`;将来真正接入 LINE Pay 时新增店铺级 `pos_store_linepay`,并在出现第三个以上支付渠道或大量账户复用需求时,再评估抽象公共支付模型。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 第八轮:店铺进入收款设置后如何简单操作
|
|
|
+
|
|
|
+### 用户问题
|
|
|
+
|
|
|
+> 我还是不够明白,通过店铺进入管理入口,应该是怎么操作的,操作起来应该简单明了
|
|
|
+
|
|
|
+### 分析过程
|
|
|
+
|
|
|
+- 隐藏底层账户、渠道、绑定和技术凭证概念。
|
|
|
+- 从门店经营者角度,只展示支付方式、收款归属和开通状态。
|
|
|
+- 将操作流程收敛为店铺列表入口和收款设置页面。
|
|
|
+
|
|
|
+### 结论
|
|
|
+
|
|
|
+当时形成的界面原则:
|
|
|
+
|
|
|
+> 从用户角度,支付属于店铺;底层如何保存和调用凭证由系统处理。
|
|
|
+
|
|
|
+店铺列表入口:
|
|
|
+
|
|
|
+```text
|
|
|
+店铺列表
|
|
|
+┌──────────┬────────┬──────────┐
|
|
|
+│ 店铺名称 │ 营业状态 │ 操作 │
|
|
|
+├──────────┼────────┼──────────┤
|
|
|
+│ 王记一店 │ 营业中 │ 编辑|收款设置 │
|
|
|
+│ 王记二店 │ 营业中 │ 编辑|收款设置 │
|
|
|
+└──────────┴────────┴──────────┘
|
|
|
+```
|
|
|
+
|
|
|
+点击“收款设置”进入当前店铺的收款页面:
|
|
|
+
|
|
|
+```text
|
|
|
+王记一店 · 收款设置
|
|
|
+
|
|
|
+当前状态:正常收款
|
|
|
+收款商户:王记餐饮有限公司
|
|
|
+已开通:OMG
|
|
|
+```
|
|
|
+
|
|
|
+支付渠道卡片:
|
|
|
+
|
|
|
+```text
|
|
|
+┌─────────────────────────────┐
|
|
|
+│ OMG │
|
|
|
+│ 状态:已开通 │
|
|
|
+│ 收款商户:王记餐饮有限公司 │
|
|
|
+│ [编辑配置] [停用] │
|
|
|
+└─────────────────────────────┘
|
|
|
+
|
|
|
+┌─────────────────────────────┐
|
|
|
+│ LINE Pay │
|
|
|
+│ 状态:未开通 │
|
|
|
+│ [开通 LINE Pay] │
|
|
|
+└─────────────────────────────┘
|
|
|
+```
|
|
|
+
|
|
|
+普通商户不需要看到 `payment_account_id`、`holder_type` 等内部字段。`MerchantID`、`StoreID`、`Channel ID` 等可以放入“技术信息”区域或仅允许平台运营人员编辑。
|
|
|
+
|
|
|
+页面只需让用户明确三件事:
|
|
|
+
|
|
|
+1. 当前店铺能使用哪些支付方式。
|
|
|
+2. 款项直接结算给哪个商户。
|
|
|
+3. 当前渠道是否已开通。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 第九轮:确认平台不参与收款后是否需要简化
|
|
|
+
|
|
|
+### 用户问题
|
|
|
+
|
|
|
+> 这个会不会太复杂了,现在明确平台不管收款,支付直接进入商户
|
|
|
+
|
|
|
+### 讨论结论
|
|
|
+
|
|
|
+确认此前包含平台商、子商户、平台结算主体和通用支付账户的设计对于当前范围过于复杂。
|
|
|
+
|
|
|
+业务关系简化为:
|
|
|
+
|
|
|
+```text
|
|
|
+店铺
|
|
|
+ ↓ 配置支付渠道
|
|
|
+OMG / LINE Pay
|
|
|
+ ↓ 直接结算
|
|
|
+商户银行账户
|
|
|
+```
|
|
|
+
|
|
|
+Foodie 只负责技术处理,不接触结算资金:
|
|
|
+
|
|
|
+- 发起支付。
|
|
|
+- 接收并验证回调。
|
|
|
+- 更新订单支付状态。
|
|
|
+- 提供交易查询和退款能力。
|
|
|
+
|
|
|
+因此暂不实现:
|
|
|
+
|
|
|
+- `PlatformID`。
|
|
|
+- 平台商/子商户模型。
|
|
|
+- 平台代收和分账。
|
|
|
+- 平台资金账户。
|
|
|
+- 二次结算逻辑。
|
|
|
+
|
|
|
+夜市摊位遵循同一原则:摊位绑定谁的支付商户账户,支付渠道就直接把钱结算给谁,Foodie 不参与后续款项再分配。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 第十轮:最终选择店铺级简单配置
|
|
|
+
|
|
|
+### 用户决定
|
|
|
+
|
|
|
+> 我们还是简单一点直接在店铺设置就行了,多店铺的情况也不多
|
|
|
+
|
|
|
+### 最终结论
|
|
|
+
|
|
|
+当前阶段不建立独立的 `payment_account`、`store_payment_binding` 或通用支付域模型,直接按店铺配置。
|
|
|
+
|
|
|
+OMG 使用:
|
|
|
+
|
|
|
+```text
|
|
|
+pos_store_omg
|
|
|
+- store_id
|
|
|
+- merchant_id
|
|
|
+- omg_store_id
|
|
|
+- hash_key
|
|
|
+- hash_iv
|
|
|
+- enabled_payments
|
|
|
+- is_enabled
|
|
|
+- status
|
|
|
+```
|
|
|
+
|
|
|
+管理入口:
|
|
|
+
|
|
|
+```text
|
|
|
+店铺管理 → 收款设置 → OMG
|
|
|
+```
|
|
|
+
|
|
|
+少量多店铺需要共用同一个 OMG 商户时:
|
|
|
+
|
|
|
+- 每个店铺分别保存相同的 `MerchantID / HashKey / HashIV`。
|
|
|
+- 每个店铺使用不同的 OMG `StoreID`。
|
|
|
+- 数据库不能继续强制 `merchant_id` 全局唯一。
|
|
|
+- 回调必须通过 `MerchantTradeNo` 找到订单和店铺,不能只使用 `MerchantID` 反查唯一店铺。
|
|
|
+
|
|
|
+后续接入 LINE Pay 时,再增加店铺级 `pos_store_linepay` 配置;不为尚未发生的大规模支付账户复用需求提前增加抽象。
|
|
|
+
|
|
|
+## 实施时必须保留的安全要求
|
|
|
+
|
|
|
+即使采用简单方案,以下要求仍不能省略:
|
|
|
+
|
|
|
+1. `HashKey / HashIV / Channel Secret` 加密保存,前端和普通管理接口只显示掩码。
|
|
|
+2. 支付回调必须校验签名、金额、订单状态和渠道商户编号。
|
|
|
+3. 支付流水记录当次使用的 `store_id`、`MerchantID`、`StoreID` 和渠道交易编号。
|
|
|
+4. 回调以 `MerchantTradeNo` 或平台唯一支付流水定位订单,不能依赖 `MerchantID` 与店铺一对一。
|
|
|
+5. 重复回调必须幂等处理,不能重复更新订单或触发重复业务动作。
|
|
|
+
|
|
|
+## 后续重新评估架构的触发条件
|
|
|
+
|
|
|
+只有出现以下任一情况时,再考虑抽象支付账户和店铺绑定模型:
|
|
|
+
|
|
|
+- 大量商户需要多个店铺共用同一套支付凭证。
|
|
|
+- 同一店铺需要同时管理多个独立结算账户。
|
|
|
+- 接入三个以上直连支付渠道,店铺级表出现大量重复逻辑。
|
|
|
+- Foodie 的业务模式改变,需要平台商、子商户、代收或分账。
|
|
|
+- 凭证管理需要统一迁移到外部密钥管理服务。
|
|
|
+
|