api.md 7.1 KB

API Contract: 创建 OMG AIO 支付订单

POST /pay/omg/create

Authentication

  • Header: token: <user-login-token>
  • Spring annotations: @Anonymous + project @Auth
  • Controller method must declare @RequestHeader String token.

Request

POST /pay/omg/create
Content-Type: application/json
token: <login-token>

{
  "orderId": "991786433092835"
}

Rules:

  • DTO has exactly one field: orderId.
  • Controller uses explicit @RequestBody(required = false).
  • orderId is trimmed, non-empty and at most 64 characters.
  • Client cannot provide amount, MerchantID, gateway URL, ReturnURL, text, channel or signature fields.

Success

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.

Business failure

{
  "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.

POST /pay/omg/notify

Request

POST /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:

  • No login token is required.
  • Controller receives one explicit OmgNotifyRequest DTO; it does not accept Map or HttpServletRequest.
  • The request boundary preserves the exact raw body plus every decoded parameter, including unknown fields and empty values.
  • Duplicate parameter names, malformed percent encoding, unsupported content type or an oversized body are invalid.
  • Signature input contains every actual parameter except CheckMacValue; no field whitelist is used.
  • Credential lookup begins from the locked MerchantTradeNo attempt and uses its credential snapshot.
  • MerchantID and TradeAmt must equal the creation snapshot.

Acknowledged

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.

Retryable rejection

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.

IPN logging

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.

POST /pay/omg/query

Header 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.

  • POST MerchantID, MerchantTradeNo, current Unix TimeStamp and CheckMacValue to the OMG stage QueryTradeInfo/V5 endpoint.
  • Use the attempt credential snapshot, parse and sign every actual response field (including additional and empty fields), excluding only CheckMacValue.
  • Verify 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.
  • User-triggered query is not an incoming IPN and is not inserted into 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.

POST /pay/omg/refund

Current 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.