Feature: specs/016-omg-payment/spec.md Date: 2026-07-29
约束:OMG 全部独立实现,零
newebpay依赖(见 research.md §0)。签名统一用CheckMacValue(SHA256, EncryptType=1),无 AES、无解密。
Cashier/AioCheckOut/V5(US1)https://payment-stage.funpoint.com.tw/Cashier/AioCheckOut/V5;正式 https://payment.funpoint.com.tw/Cashier/AioCheckOut/V5POST,application/x-www-form-urlencodedMerchantID、MerchantTradeNo(=OMG+ddId)、MerchantTradeDate(yyyy/MM/dd HH:mm:ss)、PaymentType=aio、TotalAmount(整数元)、ReturnURL、ChoosePayment=ALL、CheckMacValue、EncryptType=1TradeDesc、ItemName(# 分隔)、OrderResultURL、PaymentInfoURL、ClientRedirectURL、NeedExtraPaidInfo(建议 Y,供退款查 gwsr)、CustomField1–4、LanguageInvoiceMark=N(发票走 ezPay);ReturnURL ≠ OrderResultURL;MerchantTradeNo 全平台唯一/pay/omg/notify(CT text/html)MerchantID、MerchantTradeNo、StoreID、RtnCode(1=成功,其余勿发货)、RtnMsg、TradeNo(OMG 交易号,须存并与 MerchantTradeNo 关联)、TradeAmt、PaymentDate、PaymentType、TradeDate、SimulatePaid(1=模拟,勿发货)、CustomField1–4、CheckMacValue1|OK(首字符 1=成功);未收到 5–15 分重试,当天最多 4 次RtnCode==1 → SimulatePaid!=1 → TradeAmt==订单 amount → trade_no 幂等/pay/omg/paymentInfo,返回虚帐/缴费码(BankCode/vAccount/ExpireDate 或 PaymentNo/ExpireDate 等,详见文档 02 页),带 CheckMacValue 需验签1|OKCashier/QueryTradeInfo/V5(凭证验证 / 补单)https://payment-stage.funpoint.com.tw/Cashier/QueryTradeInfo/V5;正式 https://payment.funpoint.com.tw/Cashier/QueryTradeInfo/V5MerchantID、MerchantTradeNo、TimeStamp(3 分钟内)、PlatformID?、CheckMacValueTradeStatus(0 未付/1 已付/10200095 失败)、TradeNo、TradeAmt、PaymentDate、PaymentType、TradeDate、CheckMacValue…CreditDetail/DoAction(US4)https://payment.funpoint.com.tw/CreditDetail/DoAction(stage 不可用)MerchantID、MerchantTradeNo、TradeNo、Action(C 關帳/R 退刷/E 取消/N 放棄)、TotalAmount、CheckMacValue、PlatformID?RtnCode(1=成功)、RtnMsg已關帳→R、已授權→N、要關帳→E 再 N 或 R;分期必须全额;ATM/CVS/BarcodeATM 不适用(走人工);自动关帳开启时避开 20:15–20:30POST /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{ gatewayUrl, MerchantID, MerchantTradeNo, MerchantTradeDate, PaymentType=aio, TotalAmount, ReturnURL, ChoosePayment=ALL, EncryptType=1, ItemName, CheckMacValue, ... },前端构建隐藏 form 自动 submit 到 gatewayUrlPOST /pay/omg/notify(US2,@Anonymous)1|OKGET|POST /pay/omg/return(US2,@Anonymous)POST /pay/omg/paymentInfo(US3,@Anonymous)1|OKPOST /pay/omg/query(US2 补单,可选)orderid → 调 A4 → 据 TradeStatus 补单/查状态PosOrderShOprate 商家取消 / UserOrderController 用户取消)内,对 OMG 已支付订单调 A5 DoAction;或 POST /pay/omg/refund?orderid=(落点 tasks 定)pos_order_omg_refund;成功置 pos_order_omg_payment.pay_status=3、pos_order.pay_status=2/system/storeOmg/*(US5,@PreAuthorize)GET /list(分页筛选)、GET /{storeId}、PUT /apply/{storeId}、PUT /saveCredentials(录入+QueryTradeInfo 探测验证)、PUT /toggleEnable/{storeId}、PUT /reset/{storeId}、PUT /enabledPayments/{storeId}PosStoreNewebpayController 模式,但独立 Controller/Service/实体/表本期固定 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(本期不区分)。
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。
1 = 成功;其余均为失败。完整代码表文档为图片且持续新增,须到「歐買尬廠商後台 → 系統開發管理 → 交易狀態代碼查詢」查全。
实现策略:RtnCode==1 视成功(核销 / 退款成功);非 1 一律失败,记录 rtn_code+rtn_msg 供诊断,不硬编码错误码分支。
.NET 风格 URLEncode。Java 实现:URLEncoder.encode(s, UTF_8)(空格已→+)后,照 PHP 范例做替换以对齐 .NET,再转小写、SHA256、hex 大写:
- _ . ! * ( );~→%7e(两侧同)。+(.NET/Java 表单编码一致;标准 URLEncode 是 %20,勿混用)。@ # $ % ^ & = + ; ? / \ > < [ ] { } : ' " , | 均为 %XX;中文按 UTF-8 %XX。%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)。