# Data Model: OMG（歐買尬/FunPoint）AIO 支付接入

**Feature**: specs/016-omg-payment/spec.md
**Date**: 2026-07-29

本文定义新增实体与建表 DDL（DDL 同步写入 `updatesql/sql.md`，不直接执行）。

> **约束**：OMG 全部独立实现，**不复用蓝新建的 `pos_store_newebpay` / `pos_order_payment`**（见 research.md §0）。故凭证表、流水表、退款表均为 OMG 专属新建。

---

## 新增实体

### 1. PosStoreOmg（门店 OMG 凭证）— `pos_store_omg`

与 `pos_store` 一对一。记录门店 OMG 申请状态、启用开关、凭证、启用支付方式。状态机沿用 009/011 模式（0 未申请 / 1 申请中 / 2 已开通 + is_enabled）。

| 字段 | 类型 | 说明 |
|------|------|------|
| id | BIGINT PK AUTO | 主键 |
| store_id | BIGINT UK | 关联 pos_store.id（门店），唯一 |
| omg_status | INT | 申请状态: 0 未申请/1 申请中/2 已开通 |
| is_enabled | INT | 启用开关: 0 停用/1 启用（仅 status=2 有意义） |
| merchant_id | VARCHAR(10) UK | OMG 商店代号 MerchantID；回调反查门店凭证，非空时唯一 |
| hash_key | VARCHAR(64) | OMG HashKey |
| hash_iv | VARCHAR(64) | OMG HashIV |
| enabled_payments | VARCHAR(50) | 历史配置字段（运行时固定 Credit，不再决定收银台方式） |
| apply_time | DATETIME | 提交申请时间（0→1） |
| approved_time | DATETIME | 开通时间（→2） |
| last_verify_result | VARCHAR(240) | 最近一次凭证验证结果 |
| remark | VARCHAR(255) | 备注 |
| create_time / update_time | DATETIME | 审计时间 |
| create_by / update_by | VARCHAR(64) | 审计人 |

**状态机**：`0 未申请 --apply--> 1 申请中 --saveCredentials(验证通过)--> 2 已开通 <--reset--> 1 申请中`；`2 已开通` 下 `toggleEnable` 切换 is_enabled。门店无此行即视为未申请。

---

### 2. PosOrderOmgPayment（OMG 支付流水）— `pos_order_omg_payment`

每笔 OMG 交易一条。承载幂等（按 trade_no）与对账明细。**不复用** `pos_order_payment`。

| 字段 | 类型 | 说明 |
|------|------|------|
| id | BIGINT PK AUTO | 主键 |
| dd_id | VARCHAR(64) | 系统订单号（关联 pos_order.dd_id），索引 |
| merchant_trade_no | VARCHAR(20) | 商店交易编号 MerchantTradeNo（发起生成），唯一索引 |
| trade_no | VARCHAR(20) | OMG 交易编号 TradeNo（回调获得），唯一索引（幂等键） |
| store_id | BIGINT | 门店ID |
| merchant_id | VARCHAR(10) | OMG 商店代号（发起时门店凭证） |
| choose_payment | VARCHAR(20) | 发起方式：ALL |
| pay_type | VARCHAR(32) | 回覆 PaymentType: Credit_CreditCard/BarcodeATM_CHINATRUST/ATM_*/CVS_*/AFTEE_AFTEE |
| amount | INT | 交易金额（整数元 = 订单 amount） |
| rtn_code | INT | 回调 RtnCode（1=成功） |
| rtn_msg | VARCHAR(200) | 回调 RtnMsg |
| pay_status | INT | 0 未支付/1 已支付/2 失败/3 已退款/4 退款中 |
| auth_code | VARCHAR(20) | 授权码（信用卡回调） |
| pay_time | DATETIME | 支付完成时间（回调 PaymentDate） |
| trade_date | DATETIME | 订单创建时间（回调 TradeDate） |
| callback_raw | TEXT | 回调原始报文（调试/对账） |
| create_time / update_time | DATETIME | 审计时间 |

**幂等规则**：回调按 `trade_no` 查重——已存在且 `pay_status=1` 则跳过更新（仍回 `1|OK`）；不存在则新增/更新。
**唯一性**：`merchant_trade_no` 和 `trade_no` 均为唯一索引（MySQL 允许 `trade_no` 存在多个 NULL，发起时尚无 trade_no）；同一订单多次发起产生多行，但每个网关交易号只能关联一笔发起记录。

---

### 3. PosOrderOmgRefund（OMG 退款记录）— `pos_order_omg_refund`

每次 DoAction 调用一条，与流水解耦，支持多次动作与对账。

| 字段 | 类型 | 说明 |
|------|------|------|
| id | BIGINT PK AUTO | 主键 |
| payment_id | BIGINT | 关联 pos_order_omg_payment.id，索引 |
| dd_id | VARCHAR(64) | 系统订单号，索引 |
| trade_no | VARCHAR(20) | OMG 交易编号 TradeNo |
| action | CHAR(1) | DoAction 动作: C/R/E/N |
| amount | INT | 退款/操作金额 |
| rtn_code | INT | 响应 RtnCode（1=成功） |
| rtn_msg | VARCHAR(200) | 响应 RtnMsg |
| callback_raw | TEXT | 响应原始报文 |
| create_time | DATETIME | 操作时间 |

---

## 现有实体扩展

### 4. PosOrder（订单）— `pos_order`（不改表结构）

| 字段 | 现状 | 本期用法 |
|------|------|----------|
| dd_id | 订单号 | 与支付流水关联；MerchantTradeNo 独立生成且不可复用 |
| amount | 订单合计金额(Integer 元) | OMG 支付金额（含运费；与发票 amount−freight 不同） |
| pay_type | 支付方式字符串 | 取值 `"2"` = OMG 在线支付（发起时写入） |
| pay_status | 0 未支付/1 已支付/2 已退款 | 回调成功置 1（沿用）；退款置 2 |
| pay_url | 支付地址 | 存 OMG gatewayUrl（兜底/记录） |
| md_id | 门店ID | 决定用哪个门店的 OMG 凭证发起交易 |

**不改表结构**，无 DDL。payType 取值扩展在代码层（常量）体现。

---

## DDL（写入 updatesql/sql.md，不直接执行）

```sql
-- 2026-07-29 OMG(歐買尬)支付接入 - 门店OMG凭证表
CREATE TABLE pos_store_omg (
  id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
  store_id BIGINT NOT NULL COMMENT '关联 pos_store.id(门店)',
  omg_status INT NOT NULL DEFAULT 0 COMMENT '申请状态:0未申请/1申请中/2已开通',
  is_enabled INT NOT NULL DEFAULT 1 COMMENT '启用开关:0停用/1启用',
  merchant_id VARCHAR(10) DEFAULT NULL COMMENT 'OMG商店代号 MerchantID',
  hash_key VARCHAR(64) DEFAULT NULL COMMENT 'OMG HashKey',
  hash_iv VARCHAR(64) DEFAULT NULL COMMENT 'OMG HashIV',
  enabled_payments VARCHAR(50) DEFAULT 'ALL' COMMENT '启用支付方式(本期ALL)',
  apply_time DATETIME DEFAULT NULL COMMENT '申请时间',
  approved_time DATETIME DEFAULT NULL COMMENT '开通时间',
  last_verify_result VARCHAR(240) DEFAULT NULL COMMENT '最近验证结果',
  remark VARCHAR(255) DEFAULT NULL COMMENT '备注',
  create_time DATETIME DEFAULT NULL COMMENT '创建时间',
  update_time DATETIME DEFAULT NULL COMMENT '更新时间',
  create_by VARCHAR(64) DEFAULT NULL COMMENT '创建人',
  update_by VARCHAR(64) DEFAULT NULL COMMENT '更新人',
  PRIMARY KEY (id),
  UNIQUE KEY uk_store_id (store_id),
  UNIQUE KEY uk_merchant_id (merchant_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='门店OMG(歐買尬)支付凭证';

-- 2026-07-29 OMG支付接入 - OMG支付交易流水表
CREATE TABLE pos_order_omg_payment (
  id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
  dd_id VARCHAR(64) NOT NULL COMMENT '系统订单号(关联 pos_order.dd_id)',
  merchant_trade_no VARCHAR(20) NOT NULL COMMENT '商店交易编号 MerchantTradeNo',
  trade_no VARCHAR(20) DEFAULT NULL COMMENT 'OMG交易编号 TradeNo(幂等键)',
  store_id BIGINT NOT NULL COMMENT '门店ID',
  merchant_id VARCHAR(10) NOT NULL COMMENT 'OMG商店代号',
  choose_payment VARCHAR(20) DEFAULT 'ALL' COMMENT '发起方式',
  pay_type VARCHAR(32) DEFAULT NULL COMMENT '回覆PaymentType:Credit_CreditCard/ATM_*/CVS_*/AFTEE_AFTEE/BarcodeATM_CHINATRUST',
  amount INT NOT NULL COMMENT '交易金额(整数元)',
  rtn_code INT DEFAULT NULL COMMENT '回调RtnCode(1=成功)',
  rtn_msg VARCHAR(200) DEFAULT NULL COMMENT '回调RtnMsg',
  pay_status INT NOT NULL DEFAULT 0 COMMENT '0未支付/1已支付/2失败/3已退款/4退款中',
  auth_code VARCHAR(20) DEFAULT NULL COMMENT '授权码',
  pay_time DATETIME DEFAULT NULL COMMENT '支付完成时间',
  trade_date DATETIME DEFAULT NULL COMMENT '订单创建时间',
  callback_raw TEXT COMMENT '回调原始报文',
  create_time DATETIME DEFAULT NULL COMMENT '创建时间',
  update_time DATETIME DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (id),
  UNIQUE KEY uk_trade_no (trade_no),
  UNIQUE KEY uk_merchant_trade_no (merchant_trade_no),
  KEY idx_dd_id (dd_id),
  KEY idx_dd_id_pay_status_id (dd_id, pay_status, id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='OMG支付交易流水';

-- 2026-07-29 OMG支付接入 - OMG退款记录表
CREATE TABLE pos_order_omg_refund (
  id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
  payment_id BIGINT DEFAULT NULL COMMENT '关联 pos_order_omg_payment.id',
  dd_id VARCHAR(64) DEFAULT NULL COMMENT '系统订单号',
  trade_no VARCHAR(20) DEFAULT NULL COMMENT 'OMG交易编号 TradeNo',
  action CHAR(1) DEFAULT NULL COMMENT 'DoAction动作:C/R/E/N',
  amount INT DEFAULT NULL COMMENT '操作金额',
  rtn_code INT DEFAULT NULL COMMENT '响应RtnCode(1=成功)',
  rtn_msg VARCHAR(200) DEFAULT NULL COMMENT '响应RtnMsg',
  callback_raw TEXT COMMENT '响应原始报文',
  create_time DATETIME DEFAULT NULL COMMENT '操作时间',
  PRIMARY KEY (id),
  KEY idx_payment_id (payment_id),
  KEY idx_dd_id (dd_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='OMG退款记录';
```

注：`uk_trade_no` 唯一索引在 MySQL 下允许多个 NULL（发起时 trade_no 为空），回调写入时保证唯一。

---

## 实体关系

```
pos_store 1 ──── 1 pos_store_omg            (门店 OMG 凭证)
pos_store 1 ──── ∞ pos_order                 (门店订单)
pos_order 1 ──── ∞ pos_order_omg_payment     (一订单多次发起,每发起一行)
                                   ↑
                        trade_no 唯一(回调幂等)
pos_order_omg_payment 1 ──── ∞ pos_order_omg_refund  (一次支付多次退款动作)
```
