omg-app-integration.md 27 KB

新 OMG 支付 App 对接文档

适用对象:用户端 App(uni-app)前端开发人员 接口版本:specs/020-omg-payment-rebuild 新实现 当前环境:OMG 测试环境 支付方式目标:App 只提供信用卡、Apple Pay,OMG 直接进入所选渠道 更新时间:2026-08-18

本文只描述当前新 OMG 实现。specs/016-omg-payment 中的旧 Controller、旧流水、旧退款和旧前端文档已经退役,不得作为接入依据。

1. 接入结论

OMG 是网页托管式收银台,App 不需要接入 OMG SDK。前端只需要完成以下流程:

  1. 创建订单时把 OMG 支付方式设置为 payType = "2"。
  2. 在 App 自有界面让用户选择信用卡或 Apple Pay,分别使用 paymentMethod = "CREDIT" 或 "APPLE_PAY"。
  3. 调用 POST /pay/omg/create 获取所选渠道的 gatewayUrl 和完整 formFields。
  4. 在当前 App WebView 页面中,把所有 formFields 原样以 HTML Form POST 到 gatewayUrl。
  5. 用户付款后,OMG 将浏览器 POST 到后端 /pay/omg/result;后端验证返回资料后,优先通过 uni-app Bridge 打开支付结果页,Bridge 不可用时再通过 App Scheme 兜底。
  6. App 结果页取得 ddId,调用 POST /pay/omg/query 确认最终支付状态。
  7. 只有 query 返回 status = "PAID" 才能展示支付成功。

App 需要新增“信用卡 / Apple Pay”选择,但不接入原生 Apple Pay SDK。后端只接受两个稳定枚举并生成单渠道签名表单,因此 OMG 页面不会再展示超商快付、AFTEE 或其他渠道选择项。用户可见文案必须接入 App 现有 i18n。

当前测试环境不支持退款。POST /pay/omg/refund 只会返回“测试环境不支持退款”,不会发起真实退款,也不会修改订单。

2. 整体流程

[App 创建订单,payType="2"]
             |
             v
[App 选择 CREDIT / APPLE_PAY]
             |
             | POST /pay/omg/create
             | Header: token
             | Body: {"orderId":"...","paymentMethod":"..."}
             v
[后端返回 gatewayUrl + formFields]
             |
             | 当前 WebView 原样 Form POST
             v
[OMG 测试环境:直接进入所选付款流程]
             |
             +-------------------------------+
             |                               |
             | 服务端付款通知                | 浏览器付款结果返回
             | POST /pay/omg/notify           | POST /pay/omg/result
             | 前端不调用                     | 前端不直接调用
             v                               v
[后端验签并更新付款事实]            [后端安全桥接页打开 App 结果路由]
                                             |
                                             | iOS: 父 uni-app 页面 redirectTo
                                             | 其他环境: uni.webView.redirectTo
                                             | 失败时: App Scheme 兜底
                                             v
                                  [App 支付结果页]
                                             |
                                             | POST /pay/omg/query
                                             v
                                  [PAID 才展示支付成功]

必须注意:

  • create.status = "CREATED" 只表示后端已创建本地支付尝试和签名表单,不表示 OMG 已收单,更不表示已付款。
  • App Scheme 成功打开只表示浏览器返回资料通过后端校验,不表示服务端付款通知已经处理完成。
  • 订单最终支付结果必须以 /pay/omg/query 返回的 data.status 为准。
  • 当前新回调只更新支付事实,不推进订单、配送状态,也不发送 App 推送;App 不得依赖推送判断付款结果。

3. 公共约定

3.1 Base URL

以下接口路径都拼接在 App 当前使用的后端 Base URL 后,例如:

https://foodieapi.waimai-paotui.com/pay/omg/create

3.2 登录鉴权

App 主动调用的 create、query 和 refund 接口都必须携带登录 token:

token: <用户登录 token>

token 只发送给本项目后端,绝对不能放入 OMG Form,也不能发送给 gatewayUrl。

3.3 AjaxResult 外层结构

成功响应:

{
  "code": 200,
  "msg": "操作成功",
  "data": {}
}

业务失败响应:

{
  "code": 500,
  "msg": "已国际化的错误提示",
  "data": {
    "status": "稳定的业务状态码"
  }
}

处理规则:

  • 先判断外层 code。
  • code === 200 时再读取 data。
  • code !== 200 时直接向用户展示后端返回的 msg;msg 已按项目语言国际化。
  • 需要按场景分支时使用 data.status,不要匹配 msg 文本。

3.4 订单号字段

create/retry 请求使用:

{"orderId":"业务订单号","paymentMethod":"CREDIT 或 APPLE_PAY"}

query/refund 请求仍使用 {"orderId":"业务订单号"}。

后端 App Scheme 回跳参数使用:

?ddId=<业务订单号>

App 收到 ddId 后,把它作为 orderId 调用 query。不要把 create/query 的 JSON 字段写成 ddId、orderid 或其他名称。

4. 创建支付

4.1 接口

POST /pay/omg/create
Content-Type: application/json
token: <用户登录 token>

{
  "orderId": "991786433092835",
  "paymentMethod": "CREDIT"
}

前置条件:

  • 订单属于当前登录用户。
  • 必须是单门店父订单;多门店子订单不支持。
  • 订单 payType 必须为字符串 "2"。
  • 订单未付款、金额大于 0,且当前订单状态允许付款。
  • 订单门店已启用有效 OMG 凭证。
  • 同一订单当前不能存在另一个未结束的 OMG 支付尝试。

create/retry 只能传 orderId 与 paymentMethod;paymentMethod 仅允许 CREDIT/APPLE_PAY。query/refund 仍只传 orderId。金额、商户号、回调地址、网关地址、OMG 原始付款参数和签名都由后端决定。

4.2 成功响应

当前测试环境返回示例:

{
  "code": 200,
  "msg": "操作成功",
  "data": {
    "status": "CREATED",
    "gatewayUrl": "https://payment-stage.funpoint.com.tw/Cashier/AioCheckOut/V5",
    "formFields": {
      "MerchantID": "1000031",
      "MerchantTradeNo": "OMGR8K3P7W2M9C4X6A1B",
      "MerchantTradeDate": "2026/08/14 10:30:00",
      "PaymentType": "aio",
      "TotalAmount": "100",
      "TradeDesc": "Foodie order 991786433092835",
      "ItemName": "Order 991786433092835",
      "ReturnURL": "https://foodieapi.waimai-paotui.com/pay/omg/notify",
      "OrderResultURL": "https://foodieapi.waimai-paotui.com/pay/omg/result",
      "ChoosePayment": "Credit",
      "UnionPay": "2",
      "EncryptType": "1",
      "InvoiceMark": "N",
      "NeedExtraPaidInfo": "Y",
      "CheckMacValue": "<64 位十六进制签名>"
    }
  }
}

上例为信用卡响应。Apple Pay 响应的 ChoosePayment 为 ApplePay,且不包含 UnionPay 或 IgnorePayment。后端不会返回 ChoosePayment=ALL。

字段说明:

字段 类型 App 用法
status string 固定为 CREATED;不能当作支付成功
gatewayUrl string HTML Form 的 action,本身不是 Form 字段
formFields object 所有键值都必须原样创建为隐藏 input 并 POST
MerchantTradeNo string 后端生成的 OMG 交易编号;前端只透传,不作为业务订单号
TotalAmount string 后端根据订单金额生成;前端不得修改
ChoosePayment string 后端按 paymentMethod 生成 Credit 或 ApplePay;前端不得修改
UnionPay string 仅信用卡表单存在且固定为 2,用于隐藏银联;Apple Pay 表单不包含该字段
ReturnURL string OMG 服务端付款通知地址;前端不调用
OrderResultURL string OMG 浏览器付款结果地址;前端不直接调用
CheckMacValue string 表单签名;修改任意已签名字段都会导致 OMG 拒绝

后端当前实际返回的字段集合以 formFields 为准。前端不要维护字段白名单,不要自行新增、删除、改名、格式化或重新计算字段。

4.3 Form POST 要求

必须遵守:

  • 使用 POST,不能把字段拼成 GET URL。
  • Content-Type 由浏览器 Form 提交为 application/x-www-form-urlencoded。
  • 在当前完整 WebView 页面中跳转,不使用 iframe,不使用 window.open 新窗口。
  • gatewayUrl 只作为 Form action,不能创建名为 gatewayUrl 的 input。
  • formFields 中的每个键值都创建为隐藏 input,并保持值完全不变。
  • 不把 formFields、CheckMacValue 或 token 写入业务日志、埋点、崩溃上报或远程调试日志。

浏览器侧核心代码:

function submitOmgForm(gatewayUrl, formFields) {
  if (!gatewayUrl || !formFields || typeof formFields !== 'object') {
    throw new Error('OMG payment payload is invalid');
  }

  const form = document.createElement('form');
  form.method = 'POST';
  form.action = gatewayUrl;
  form.acceptCharset = 'UTF-8';

  Object.entries(formFields).forEach(([name, value]) => {
    const input = document.createElement('input');
    input.type = 'hidden';
    input.name = name;
    input.value = value == null ? '' : String(value);
    form.appendChild(input);
  });

  document.body.appendChild(form);
  form.submit();
}

4.4 uni-app 页面传值建议

建议通过页面 eventChannel、内存状态或原生桥接把 create 响应交给收银台页面,再由收银台页面的 renderjs 创建并提交 Form。

不要把整个 formFields 拼入页面 URL query。这样会把 CheckMacValue 和完整支付表单暴露在浏览记录、路由日志或错误上报中。

发起页示例:

async function startOmgPayment(orderId, paymentMethod) {
  if (this.omgSubmitting) return;
  this.omgSubmitting = true;

  try {
    const response = await request({
      url: '/pay/omg/create',
      method: 'POST',
      header: { token: uni.getStorageSync('token') },
      data: { orderId, paymentMethod }
    });

    if (response.code !== 200) {
      uni.showToast({ title: response.msg, icon: 'none' });
      return;
    }

    const payload = response.data;
    uni.navigateTo({
      url: '/pages/pay/omgCheckout/omgCheckout',
      success: ({ eventChannel }) => {
        eventChannel.emit('omgCheckoutPayload', payload);
      }
    });
  } finally {
    this.omgSubmitting = false;
  }
}

收银台页面只需要接收:

{
  status: 'CREATED',
  gatewayUrl: 'https://payment-stage.funpoint.com.tw/Cashier/AioCheckOut/V5',
  formFields: { /* 后端原样返回的全部字段 */ }
}

然后在该页面的 WebView/renderjs 环境调用:

submitOmgForm(payload.gatewayUrl, payload.formFields);

具体页面路径和请求封装按 App 现有结构调整,Form POST 规则不能改变。

4.5 创建错误状态

data.status 含义 App 处理建议
AUTH_REQUIRED token 无法取得登录用户 返回登录页
ORDER_REQUIRED orderId 缺失或格式不合法 提示后返回订单页
ORDER_NOT_AVAILABLE 订单不存在或不属于当前用户 展示后端 msg
MULTI_STORE_ORDER_NOT_SUPPORTED 当前是多门店子订单 展示后端 msg,不可继续支付
ORDER_STATE_NOT_PAYABLE 当前订单状态不可付款 刷新订单数据
ORDER_ALREADY_PAID 订单已经付款 进入订单结果页并刷新状态
ORDER_AMOUNT_INVALID 订单金额异常 展示后端 msg
PAYMENT_TYPE_INVALID 订单 payType 不是 "2" 检查创建订单时的支付方式
PAYMENT_METHOD_INVALID paymentMethod 缺失或不是 CREDIT/APPLE_PAY 停止支付并检查 App 渠道映射
STORE_CREDENTIAL_UNAVAILABLE 门店未启用有效 OMG 凭证 展示后端 msg
PAYMENT_ATTEMPT_EXISTS 已有未结束的支付尝试 用户确认重新支付时调用 /pay/omg/retry,不要循环调用 create
PAYMENT_CONFIGURATION_INVALID 后端测试网关或回调配置不合法 展示后端 msg,通知后端排查
PAYMENT_CREATION_FAILED 本次创建失败 展示后端 msg,稍后重试

同一订单创建成功后,重复点击不会返回旧表单,而是返回 PAYMENT_ATTEMPT_EXISTS。因此支付按钮必须防重复点击;如果用户只是等待支付结果,调用 query;如果用户已经退出支付页并明确再次支付,调用 retry。不要循环调用 create,也不要缓存并重新提交旧表单。

5. 浏览器结果返回与 App Scheme

5.1 /pay/omg/result

POST /pay/omg/result
Content-Type: application/x-www-form-urlencoded

该接口由 OMG 收银台调用,不是 App API。后端会验证返回表单的签名、商户号、OMG 交易编号和金额,然后返回一个禁止缓存的安全桥接页面。

桥接页面的目标路由固定为:

com.twanmsdyh.app://pages/OrderList/paySuccess/paySuccess?ddId=<URL 编码后的业务订单号>

在 uni-app App 的 <web-view> 中,页面先加载后端自托管的 Bridge SDK。iOS App-Plus 环境由支付子 WebView 的父 uni-app 页面执行 uni.redirectTo,避免旧运行时调用不存在的 UniPlusBridge;Android 等其他 App 环境继续使用 uni.webView.redirectTo。上述方式不可用或没有完成页面交接时,页面才使用 com.twanmsdyh.app Scheme 兜底。

页面同时保留“返回 App”按钮,自动跳转失败时用户可手动点击。App 端现有支付 WebView 页面不需要为本次 iOS 修复新增接口或页面,但仍必须保留 Scheme 注册作为兜底。

5.2 App 必须完成的配置

App 必须注册以下 Scheme:

com.twanmsdyh.app

并把以下路由映射到现有支付结果页:

pages/OrderList/paySuccess/paySuccess

结果页读取参数:

ddId=<业务订单号>

收到 Scheme 后的正确处理:

  1. 读取 ddId。
  2. 从 App 本地安全存储读取当前登录 token。
  3. 调用 /pay/omg/query,请求体使用 { "orderId": ddId }。
  4. 根据 query 的 data.status 展示结果。

Scheme 参数可以被外部伪造。禁止因为进入支付结果路由或拿到 ddId 就直接展示付款成功。

6. 查询支付结果

6.1 接口

POST /pay/omg/query
Content-Type: application/json
token: <用户登录 token>

{
  "orderId": "991786433092835"
}

query 不是简单读取本地状态。后端会使用当前支付尝试的凭证快照查询 OMG 测试网关、验证完整响应,并在付款回调丢失时补偿订单付款状态。因此 App 不应高频调用。

6.2 成功响应

已付款示例:

{
  "code": 200,
  "msg": "操作成功",
  "data": {
    "status": "PAID",
    "tradeStatus": "1",
    "merchantTradeNo": "OMGR8K3P7W2M9C4X6A1B",
    "tradeNo": "26081400000000000001",
    "amount": 100,
    "paymentDate": "2026/08/14 10:32:10",
    "tradeDate": "2026/08/14 10:30:00",
    "paymentType": "Credit_CreditCard",
    "handlingCharge": "0",
    "paymentTypeChargeFee": "3"
  }
}

未付款时,tradeNo、paymentDate、paymentType 等字段可能为 null 或空字符串。前端应以 status 为主,不要依赖某个详情字段是否为空判断成功。

字段说明:

字段 类型 说明
status string 前端判断结果的标准化状态
tradeStatus string OMG 原始交易状态,仅用于排查或辅助展示
merchantTradeNo string 后端生成的 OMG 特店交易编号
tradeNo string/null OMG 金流交易编号;始终按字符串处理
amount number 订单金额,整数 TWD
paymentDate string/null OMG 付款时间,台北时区
tradeDate string/null OMG 建单时间,台北时区
paymentType string/null OMG 尚未确认付款渠道时为空;完成渠道选择/付款并在 query 或回调中回传后才有值。信用卡与 Apple Pay 可能同样回传 Credit_CreditCard,App 不用它做二级支付方式选择
handlingCharge string/null 手续费相关原始值
paymentTypeChargeFee string/null 付款方式手续费原始值

6.3 status 处理

status 含义 App 行为
PAID 已确认付款 展示支付成功,刷新订单
UNPAID OMG 当前仍未付款 保持“结果确认中”,按受控频率继续查询
FAILED 当前支付尝试已失败 展示支付未完成,停止本轮轮询
UNKNOWN OMG 返回了当前系统未归一化的状态 不得当作成功;提示确认中并受控重试

OMG 原始 tradeStatus 常见值:

tradeStatus 标准化结果
1 PAID
0 UNPAID
10200095 FAILED
其他 UNKNOWN

6.4 轮询建议

App 从 Scheme 返回后立即查询一次。如果结果是 UNPAID 或 UNKNOWN:

  • 每 3 秒查询一次。
  • 最多再查询 10 次,总计约 30 秒。
  • App 页面进入后台或销毁时停止轮询。
  • 任意一次返回 PAID 或 FAILED 时立即停止。
  • query 返回业务错误时停止自动轮询并展示后端 msg。
  • 达到上限仍未终态时提示“支付结果确认中,请稍后在订单列表查看”,不要展示支付失败。

参考代码:

async function confirmOmgPayment(orderId) {
  const maxAttempts = 10;

  for (let attempt = 0; attempt < maxAttempts; attempt += 1) {
    const response = await request({
      url: '/pay/omg/query',
      method: 'POST',
      header: { token: uni.getStorageSync('token') },
      data: { orderId }
    });

    if (response.code !== 200) {
      uni.showToast({ title: response.msg, icon: 'none' });
      return;
    }

    const status = response.data.status;
    if (status === 'PAID') {
      showPaymentSuccess();
      return;
    }
    if (status === 'FAILED') {
      showPaymentIncomplete();
      return;
    }

    await new Promise(resolve => setTimeout(resolve, 3000));
  }

  showPaymentConfirming();
}

实际代码需要结合页面生命周期取消定时器或异步任务,避免离开页面后继续请求。

6.5 查询错误状态

data.status 含义 App 处理建议
AUTH_REQUIRED 登录信息不可用 返回登录页
ORDER_REQUIRED orderId 缺失或不合法 停止查询并返回订单页
ORDER_NOT_AVAILABLE 订单不存在或不属于当前用户 展示后端 msg
PAYMENT_QUERY_NOT_AVAILABLE 当前没有可查询的 OMG 支付尝试 刷新订单后展示后端 msg
PAYMENT_QUERY_FAILED OMG 查询失败、响应非法或身份校验失败 展示后端 msg,稍后人工重试

6.6 退出支付页后重新支付

App 返回业务页面后原支付 WebView 会销毁,本流程不要求保存或恢复 WebView。旧 gatewayUrl + formFields 也不能当作“继续付款网址”缓存重放:其中的 MerchantTradeNo 只能建单一次,重新提交会被 OMG 以重复订单编号拒绝。

用户点击“重新支付”时调用:

POST /pay/omg/retry
Content-Type: application/json
token: <用户登录 token>

{
  "orderId": "991786433092835",
  "paymentMethod": "APPLE_PAY"
}

后端会先使用旧尝试的凭证快照向 OMG 查询真实状态,然后按以下规则处理:

OMG 查询结果 后端处理
PAID 不创建新支付,返回 ORDER_ALREADY_PAID
FAILED 旧尝试已经结束,生成新的 MerchantTradeNo 和新表单
本地无进行中的尝试(旧尝试已被自动补偿关闭为终态 FAILED/SUPERSEDED,active 指针已释放) 不再查询旧尝试,直接生成新的 MerchantTradeNo 和新表单(等价首次 create;订单已付会被 create 的校验以 ORDER_ALREADY_PAID 拒绝)
UNPAID 且 paymentType 为空 原子地把旧尝试改为 SUPERSEDED,生成新的 MerchantTradeNo 和新表单
UNPAID 且 paymentType 非空 为避免覆盖可能正在授权的交易,返回 PAYMENT_RETRY_NOT_AVAILABLE
UNKNOWN、查询失败或并发状态已改变 不修改旧尝试,返回对应错误

retry 成功响应与 create 完全相同。App 收到后创建新的支付 WebView,将新的全部 formFields 以 Form POST 提交到新的 gatewayUrl:

{
  "code": 200,
  "msg": "操作成功",
  "data": {
    "status": "CREATED",
    "gatewayUrl": "https://payment-stage.funpoint.com.tw/Cashier/AioCheckOut/V5",
    "formFields": {
      "MerchantTradeNo": "OMGR8K3P7W2M9C4X6A1B"
    }
  }
}

paymentType 是 OMG 查询结果,不是 App 传参;paymentMethod 才是 App 本次选择并提交给 create/retry 的受控枚举。用户重新支付时可以重新选择信用卡或 Apple Pay。

App 推荐处理:

async function retryOmgPayment(orderId, paymentMethod) {
  const response = await request({
    url: '/pay/omg/retry',
    method: 'POST',
    header: { token: uni.getStorageSync('token') },
    data: { orderId, paymentMethod }
  });

  if (response.code === 200) {
    openNewOmgWebView(response.data.gatewayUrl, response.data.formFields);
    return;
  }
  if (response.data?.status === 'ORDER_ALREADY_PAID') {
    await confirmOmgPayment(orderId);
    return;
  }
  uni.showToast({ title: response.msg, icon: 'none' });
}

retry 可能返回 query、create 的既有错误,也可能返回:

data.status App 处理建议
PAYMENT_RETRY_NOT_AVAILABLE 不自动循环;刷新订单并调用 query 确认状态
PAYMENT_RETRY_FAILED 提示稍后重试,不复用旧表单

7. 后端专用接口

7.1 付款通知 /pay/omg/notify

POST /pay/omg/notify
Content-Type: application/x-www-form-urlencoded

这是 OMG 到后端的 server-to-server 回调:

  • App 不调用。
  • 不携带用户 token。
  • 后端负责验签、幂等处理和更新付款事实。
  • App 不需要解析其 1|OK 或 0|ERROR 响应。

7.2 浏览器结果 /pay/omg/result

这是 OMG 收银台到后端的浏览器返回接口:

  • App 不主动调用。
  • 后端只验证返回资料并生成 App 路由桥接页;iOS 优先由父 uni-app 页面执行路由,其他环境使用官方 Bridge,失败时才使用 App Scheme。
  • 该接口本身不修改支付状态。

8. 退款接口:当前不可用

8.1 接口形式

POST /pay/omg/refund
Content-Type: application/json
token: <用户登录 token>

{
  "orderId": "991786433092835"
}

8.2 当前固定响应

{
  "code": 500,
  "msg": "OMG 测试环境不支持退款,请在正式环境启用后操作",
  "data": {
    "status": "PAYMENT_REFUND_UNAVAILABLE_IN_TEST_ENVIRONMENT"
  }
}

8.3 必须理解的行为

当前接口只是测试阶段的安全拒绝边界:

  • 不调用 OMG 正式环境退款接口。
  • 不读取或修改订单、支付、退款状态。
  • 不创建退款记录。
  • 不写入付款通知日志。
  • 不支持由 App 传退款金额、OMG 交易号、网关地址或退款动作。

因此当前 App 不应把 /pay/omg/refund 接入订单取消流程,也不能向用户展示“退款成功”。正式环境退款需要后端另行实现并确认契约后,前端才能接入。

9. 安全与易错点

  1. 创建支付请求字段是 orderId,不是 ddId;ddId 只出现在 App Scheme 参数中。
  2. 订单 OMG 支付类型是字符串 "2";LINE Pay 是 "3",不要混用。
  3. CREATED 不是支付成功。
  4. App Scheme 到达不是支付成功。
  5. 只有 query 的 status === "PAID" 才能展示支付成功。
  6. 不修改、过滤或重新计算 formFields;尤其不能修改 TotalAmount、回调地址和 CheckMacValue。
  7. 不把 Form 改成 GET,不使用 iframe,不使用新窗口。
  8. 不把 token 发送给 OMG,也不把 token 放入页面 URL。
  9. 不把完整 formFields 或 CheckMacValue 放入 URL、日志、埋点或错误上报。
  10. tradeNo、merchantTradeNo 始终按字符串处理,不转换为 JavaScript Number。
  11. query 会访问 OMG 网关,不做高频轮询。
  12. PAYMENT_ATTEMPT_EXISTS 不能靠重复调用 create 解决,应进入 query 确认流程。
  13. App 只传 CREDIT/APPLE_PAY;不得传 ChoosePayment、UnionPay、IgnorePayment 等 OMG 原始字段,也不得通过 CSS 或 DOM 修改第三方支付页面。
  14. 当前没有真实退款能力。

10. App 验收清单

10.1 创建与收银台

  • 创建订单时 OMG 使用 payType = "2"。
  • App 只显示信用卡与 Apple Pay,并把选择映射为 CREDIT/APPLE_PAY;用户可见文案使用现有 i18n。
  • create 请求 Header 包含 token,JSON 只传 orderId 与 paymentMethod。
  • 支付按钮有防重复点击处理。
  • create 成功后,当前完整 WebView 使用 Form POST 打开 gatewayUrl。
  • 所有 formFields 原样提交,gatewayUrl 不作为 input。
  • 没有 iframe、GET 跳转或新窗口。
  • CREDIT 直接进入信用卡流程,表单为 ChoosePayment=Credit + UnionPay=2,不显示其他渠道。
  • APPLE_PAY 在门店已开通且设备支持时直接进入 Apple Pay 流程,表单为 ChoosePayment=ApplePay,不显示其他渠道。
  • 两种表单都不包含 ChoosePayment=ALL 或 IgnorePayment,页面不出现超商快付、AFTEE。

10.2 App 返回与状态确认

  • App 已注册 com.twanmsdyh.app Scheme。
  • Scheme 路由可打开 pages/OrderList/paySuccess/paySuccess。
  • iOS 从 OMG 信用卡付款完成后可由支付 WebView 自动进入 pages/OrderList/paySuccess/paySuccess。
  • 结果页能读取 ddId。
  • 结果页把 ddId 作为 orderId 调用 query。
  • PAID 才展示成功。
  • UNPAID/UNKNOWN 受控轮询,不误判为失败或成功。
  • FAILED 停止本轮轮询并展示未完成。
  • 轮询超时展示“确认中”,并引导用户稍后查看订单。
  • 页面离开或进入后台时停止轮询。

10.3 错误与安全

  • 业务错误直接显示后端国际化 msg。
  • 需要分支判断时使用 data.status,不匹配中文文案。
  • PAYMENT_ATTEMPT_EXISTS 不会触发 create 重试循环。
  • token、完整 Form 和 CheckMacValue 不出现在日志、URL、埋点或上报中。
  • 当前订单取消流程没有调用 OMG refund 并宣称退款成功。
  • 所有 App 新增用户可见文字已加入 zh、tw、en、vi 四种语言。

11. 接口速查

用途 Method 路径 token 调用方
创建支付 POST /pay/omg/create 必须 App
查询结果 POST /pay/omg/query 必须 App
重新支付 POST /pay/omg/retry 必须 App
退款安全拒绝 POST /pay/omg/refund 必须 当前 App 不调用
付款结果通知 POST /pay/omg/notify 不需要 OMG 服务器
浏览器结果返回 POST /pay/omg/result 不需要 OMG 收银台

12. 当前后端配置依赖

后端当前配置为:

omgpay:
  return-url: https://foodieapi.waimai-paotui.com/pay/omg/notify
  order-result-url: https://foodieapi.waimai-paotui.com/pay/omg/result
  app-return-url: com.twanmsdyh.app://pages/OrderList/paySuccess/paySuccess

App 接入人员只需要确保 Scheme 和结果页路由与 app-return-url 一致。return-url 和 order-result-url 是后端与 OMG 的配置,前端不得覆盖。