/pay/omg/createtoken: <user-login-token>@Anonymous + project @Auth@RequestHeader String token.POST /pay/omg/create
Content-Type: application/json
token: <login-token>
{
"orderId": "991786433092835"
}
Rules:
orderId.@RequestBody(required = false).orderId is trimmed, non-empty and at most 64 characters.Outer response keeps the project AjaxResult format. data is:
{
"status": "CREATED",
"gatewayUrl": "https://payment-stage.funpoint.com.tw/Cashier/AioCheckOut/V5",
"formFields": {
"MerchantID": "1000031",
"MerchantTradeNo": "OMGR8K3P7W2M9C4X6A1B",
"MerchantTradeDate": "2026/08/13 15:30:23",
"PaymentType": "aio",
"TotalAmount": "100",
"TradeDesc": "Foodie order 991786433092835",
"ItemName": "Order 991786433092835",
"ReturnURL": "https://foodieapi.waimai-paotui.com/pay/omg/notify",
"ChoosePayment": "ALL",
"EncryptType": "1",
"InvoiceMark": "N",
"NeedExtraPaidInfo": "Y",
"ExpireDate": "1",
"StoreExpireDate": "30",
"BarcodeATMExpireDate": "1",
"CheckMacValue": "<64 uppercase hexadecimal characters>"
}
}
The client must submit every formFields entry in the current page as an application/x-www-form-urlencoded POST to gatewayUrl. It must not use iframe, a new window or a GET link.
{
"code": 500,
"msg": "<localized message>",
"data": {
"status": "PAYMENT_ATTEMPT_EXISTS"
}
}
Stable statuses:
| Status | Meaning |
|---|---|
AUTH_REQUIRED |
No usable user identity reached the new Controller |
ORDER_REQUIRED |
Request or orderId is missing/invalid |
ORDER_NOT_AVAILABLE |
Order does not exist or is not owned by this user |
MULTI_STORE_ORDER_NOT_SUPPORTED |
Matched row is a multi-store child order |
ORDER_STATE_NOT_PAYABLE |
State is not 0, 1 or 2 |
ORDER_ALREADY_PAID |
pay_status is not 0 |
ORDER_AMOUNT_INVALID |
Amount is null or not positive |
PAYMENT_TYPE_INVALID |
pay_type is not "2" |
STORE_CREDENTIAL_UNAVAILABLE |
No enabled credential exists for the order store |
PAYMENT_ATTEMPT_EXISTS |
The order already has an active CREATED attempt |
PAYMENT_CONFIGURATION_INVALID |
Stage/ReturnURL safety validation failed |
PAYMENT_CREATION_FAILED |
Controlled generation/insert attempts could not complete |
No error response includes token, HashKey, HashIV, CheckMacValue, form fields, SQL or stack trace.
/pay/omg/notifyPOST /pay/omg/notify
Content-Type: application/x-www-form-urlencoded
MerchantID=1000031&MerchantTradeNo=OMGR8K3P7W2M9C4X6A1B&RtnCode=1&RtnMsg=Succeeded&TradeNo=26081300000000000001&TradeAmt=100&PaymentDate=2026%2F08%2F13+16%3A20%3A00&PaymentType=Credit_CreditCard&PaymentTypeChargeFee=3&TradeDate=2026%2F08%2F13+16%3A18%3A00&SimulatePaid=1&CustomField1=&CustomField2=&CustomField3=&CustomField4=&card4no=4242&CheckMacValue=<CHECK_MAC_VALUE>
Rules:
OmgNotifyRequest DTO; it does not accept Map or HttpServletRequest.CheckMacValue; no field whitelist is used.MerchantTradeNo attempt and uses its credential snapshot.MerchantID and TradeAmt must equal the creation snapshot.HTTP/1.1 200 OK
Content-Type: text/plain;charset=UTF-8
1|OK
This response is used for a verified success, verified final failure, or an idempotently repeated fact. RtnCode=1 marks the attempt and order paid even when SimulatePaid=1. RtnCode!=1 marks a non-paid attempt failed and leaves the order unpaid.
HTTP/1.1 200 OK
Content-Type: text/plain;charset=UTF-8
0|ERROR
This response is used when the request cannot be trusted or atomically processed: unknown trade number, invalid/missing fields, duplicate fields, credential snapshot unavailable, signature mismatch, MerchantID/amount mismatch, conflicting gateway TradeNo, or database transaction failure. No order/payment state is changed.
Every HTTP request is inserted before business handling into existing ipn_log with type=omg, request IP, receive time and the full raw form body. This insert uses an independent transaction. Failure to write ipn_log is logged but does not block payment processing.
/pay/omg/queryHeader token is required. The JSON body contains only the business order ID:
{"orderId":"991786433092835"}
The server verifies ownership and chooses the only current payment attempt. An unpaid order queries its unique CREATED attempt; an already-paid order queries its first PAID attempt. The client cannot provide MerchantTradeNo, amount, credentials or gateway URL.
MerchantID, MerchantTradeNo, current Unix TimeStamp and CheckMacValue to the OMG stage QueryTradeInfo/V5 endpoint.CheckMacValue.MerchantID, MerchantTradeNo and TradeAmt against the attempt snapshot.TradeStatus=1 reuses the callback's locked idempotent settlement transaction and compensates a lost callback by marking the attempt/order paid.TradeStatus=0 changes no local state; 10200095 synchronizes an unpaid attempt to failed; paid facts are irreversible.ipn_log.The response whitelist includes normalized status (PAID, UNPAID, FAILED, UNKNOWN), raw tradeStatus, trade numbers, amount, gateway dates, payment type and fees. Invalid/tampered responses return PAYMENT_QUERY_FAILED; no eligible attempt returns PAYMENT_QUERY_NOT_AVAILABLE.
/pay/omg/refundCurrent scope is a test-environment safety boundary. Header token is required and the JSON body contains only:
{"orderId":"991786433092835"}
The client cannot provide refund amount, MerchantTradeNo, TradeNo, Action, credentials or gateway URL. After authentication and basic order-ID validation, the endpoint always returns:
{
"code":500,
"msg":"OMG 测试环境不支持退款,请在正式环境启用后操作",
"data":{"status":"PAYMENT_REFUND_UNAVAILABLE_IN_TEST_ENVIRONMENT"}
}
The endpoint does not call the production-only OMG CreditDetail/DoAction API, does not read or update order/payment/refund state, does not insert ipn_log, and does not create a refund record. Formal refund orchestration remains out of scope until the production environment is explicitly enabled.