api.md 8.3 KB

Contracts: OMG(歐買尬/FunPoint)AIO 支付接入

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

约束:OMG 全部独立实现,零 newebpay 依赖(见 research.md §0)。签名统一用 CheckMacValue(SHA256, EncryptType=1),无 AES、无解密。


A. OMG 外部接口(我方 → 盘合)

A1. 幕前下单 — Cashier/AioCheckOut/V5(US1)

  • URL:测试 https://payment-stage.funpoint.com.tw/Cashier/AioCheckOut/V5;正式 https://payment.funpoint.com.tw/Cashier/AioCheckOut/V5
  • Method/CTPOSTapplication/x-www-form-urlencoded
  • 方式:后端组参 + 计算 CheckMacValue 返回 form 字段,前端 Form Post 跳转 OMG 收银台(不可 iframe;iOS 不可另开窗)
  • 必填请求参数MerchantIDMerchantTradeNo(=OMG+ddId)、MerchantTradeDate(yyyy/MM/dd HH:mm:ss)、PaymentType=aioTotalAmount(整数元)、ReturnURLChoosePayment=ALLCheckMacValueEncryptType=1
  • 常用可选TradeDescItemName(# 分隔)、OrderResultURLPaymentInfoURLClientRedirectURLNeedExtraPaidInfo(建议 Y,供退款查 gwsr)、CustomField1–4Language
  • 固定InvoiceMark=N(发票走 ezPay);ReturnURL ≠ OrderResultURLMerchantTradeNo 全平台唯一

A2. 付款结果回调 — ReturnURL(盘合 → 我方,US2)

  • 盘合服务端 POST 我方 /pay/omg/notify(CT text/html
  • 参数MerchantIDMerchantTradeNoStoreIDRtnCode(1=成功,其余勿发货)、RtnMsgTradeNo(OMG 交易号,须存并与 MerchantTradeNo 关联)、TradeAmtPaymentDatePaymentTypeTradeDateSimulatePaid(1=模拟,勿发货)、CustomField1–4CheckMacValue
  • 我方响应:纯字符串 1|OK(首字符 1=成功);未收到 5–15 分重试,当天最多 4 次
  • 核销校验顺序:CheckMacValue 验签 → RtnCode==1SimulatePaid!=1TradeAmt==订单 amounttrade_no 幂等

A3. ATM/超商 取号回调 — PaymentInfoURL(US3)

  • 盘合服务端 POST 我方 /pay/omg/paymentInfo,返回虚帐/缴费码(BankCode/vAccount/ExpireDatePaymentNo/ExpireDate 等,详见文档 02 页),带 CheckMacValue 需验签
  • 我方落库展示并回 1|OK

A4. 订单查询 — Cashier/QueryTradeInfo/V5(凭证验证 / 补单)

  • URL:测试 https://payment-stage.funpoint.com.tw/Cashier/QueryTradeInfo/V5;正式 https://payment.funpoint.com.tw/Cashier/QueryTradeInfo/V5
  • 请求MerchantIDMerchantTradeNoTimeStamp(3 分钟内)、PlatformID?CheckMacValue
  • 响应(text/html,k=v):TradeStatus(0 未付/1 已付/10200095 失败)、TradeNoTradeAmtPaymentDatePaymentTypeTradeDateCheckMacValue
  • 用途:录入凭证探测金钥 + 回调漏收时补单

A5. 信用卡退款/取消 — CreditDetail/DoAction(US4)

  • URL:正式 https://payment.funpoint.com.tw/CreditDetail/DoActionstage 不可用
  • 请求MerchantIDMerchantTradeNoTradeNoAction(C 關帳/R 退刷/E 取消/N 放棄)、TotalAmountCheckMacValuePlatformID?
  • 响应(k=v):RtnCode(1=成功)、RtnMsg
  • 规则已關帳→R已授權→N要關帳→E 再 N 或 R;分期必须全额;ATM/CVS/BarcodeATM 不适用(走人工);自动关帳开启时避开 20:15–20:30

B. 平台内部接口(暴露给前端/管理端)

B1. 发起 OMG 支付 — POST /pay/omg/create(US1,@Anonymous @Auth,Header token)

  • 入参:orderid(= ddId)
  • 逻辑:校验订单归属/金额/未支付 → 查门店启用凭证 → 生成 MerchantTradeNo → 组参 + CheckMacValue → 落 pos_order_omg_payment(pay_status=0) + 更新 pos_order.pay_type="7"/pay_url
  • 返回:form 字段 { gatewayUrl, MerchantID, MerchantTradeNo, MerchantTradeDate, PaymentType=aio, TotalAmount, ReturnURL, ChoosePayment=ALL, EncryptType=1, ItemName, CheckMacValue, ... },前端构建隐藏 form 自动 submit 到 gatewayUrl

B2. OMG 支付结果回调 — POST /pay/omg/notify(US2,@Anonymous

  • 处理 A2:collectForm → IpnLog → 凭证(MerchantID) → 验签 CheckMacValue → 幂等(trade_no) → 金额校验 → RtnCode==1 && SimulatePaid!=1 → markSuccess → 更新订单(state=0, payStatus=1) + 订单日志 + 推送用户/商家/骑手 + sendAcceptRiderPush → 回纯串 1|OK

B3. 支付完成返回页 — GET|POST /pay/omg/return(US2,@Anonymous

  • 仅引导回前端结果页(带 ddId),不改订单状态(以 notify 为准)

B4. ATM/超商 取号回调 — POST /pay/omg/paymentInfo(US3,@Anonymous

  • 处理 A3:验签 → 落虚帐/缴费码 + 期限 → 回 1|OK

B5. 订单查询/补单 — POST /pay/omg/query(US2 补单,可选)

  • 入参 orderid → 调 A4 → 据 TradeStatus 补单/查状态

B6. 订单取消退款(US4)

  • 触发点:订单取消链路(PosOrderShOprate 商家取消 / UserOrderController 用户取消)内,对 OMG 已支付订单调 A5 DoAction;或 POST /pay/omg/refund?orderid=(落点 tasks 定)
  • pos_order_omg_refund;成功置 pos_order_omg_payment.pay_status=3pos_order.pay_status=2

B7. 门店 OMG 凭证管理 — /system/storeOmg/*(US5,@PreAuthorize

  • GET /list(分页筛选)、GET /{storeId}PUT /apply/{storeId}PUT /saveCredentials(录入+QueryTradeInfo 探测验证)、PUT /toggleEnable/{storeId}PUT /reset/{storeId}PUT /enabledPayments/{storeId}
  • 镜像 011 PosStoreNewebpayController 模式,但独立 Controller/Service/实体/表

C. 代码表与枚举(OMG reference 02–05,2026-07-29 补读)

C1. ChoosePayment(请求参数,US1)

本期固定 ALL(聚合全部)。可细分值:Credit(信用卡/銀聯/Apple Pay)、ATM(FIRST/CHINATRUST/UBOT/KGI)、CVS(CVS/FAMILY/IBON/HILIFE)、BarcodeATM(CHINATRUST)、AFTEE。 ⚠️ Apple Pay 不是独立 ChoosePayment,归在 Credit 下(付款页内选);回覆 PaymentType 同为 Credit_CreditCard仅凭 PaymentType 无法区分信用卡与 Apple Pay(本期不区分)。

C2. 回覆 PaymentType(回调 PaymentType,落 pos_order_omg_payment.pay_type

PaymentType 名称 即时/延期
Credit_CreditCard 信用卡(含銀聯/Apple Pay) 即时
BarcodeATM_CHINATRUST 超商快付代碼繳費 即时
ATM_FIRST / ATM_CHINATRUST / ATM_UBOT / ATM_KGI 各银行 ATM 延期(取虚帐→期限内付款)
CVS_CVS / CVS_FAMILY / CVS_IBON / CVS_HILIFE 超商代碼繳費 延期
AFTEE_AFTEE AFTEE 先享後付 延期

延期方式(ATM/CVS/AFTEE)走 PaymentInfoURL 取号 → US3。

C3. RtnCode(回调 / 退款响应)

1 = 成功;其余均为失败。完整代码表文档为图片且持续新增,须到「歐買尬廠商後台 → 系統開發管理 → 交易狀態代碼查詢」查全。 实现策略RtnCode==1 视成功(核销 / 退款成功);非 1 一律失败,记录 rtn_code+rtn_msg 供诊断,不硬编码错误码分支

C4. URLEncode(CheckMacValue 计算,须完全照此 · reference 05)

.NET 风格 URLEncode。Java 实现URLEncoder.encode(s, UTF_8)(空格已→+)后,照 PHP 范例做替换以对齐 .NET,再转小写、SHA256、hex 大写:

  • 不编码(字面):- _ . ! * ( )~%7e(两侧同)。
  • 空格→+(.NET/Java 表单编码一致;标准 URLEncode 是 %20,勿混用)。
  • 其余特殊符 @ # $ % ^ & = + ; ? / \ > < [ ] { } : ' " , | 均为 %XX;中文按 UTF-8 %XX
  • 替换集(防御性,照 PHP 范例):%2d→-%5f→_%2e→.%21→!%2a→*%28→(%29→)(Java URLEncoder 本就不编 -_.!*() 需替换回)。

签名约定(所有请求/回调通用)

CheckMacValue(EncryptType=1, SHA256): 去 CheckMacValue → 参数按 key 字母序 → k=v&... → 包夹 HashKey={k}&..&HashIV={iv} → .NET 风格 URL 编码(-_.!*() 不编码) → 转小写 → SHA256 → hex 大写。校验同理重算比对。实现:OmgCheckMacValue(独立,不复用 NewebPayEncryptUtil)。