Third-party payments

A three-part toolkit — create order, query order and refund order. Supports Alipay, WeChat Pay, QQ Wallet and more on both desktop and mobile: just render a QR code or open the cashier URL according to the returned pay_type.

/api/pay/

Service Description

The payment service condenses the whole "create order → user pays → funds credited / goods delivered" chain into three endpoints: /api/pay/create returns the payment parameters, /api/pay/query looks the order up and syncs its status, and /api/pay/refund issues a refund. Callers never have to deal with the individual payment platforms' protocols or signatures.

Payment results are taken only from the asynchronous callback and an active query — a page redirect does not count: once the user has paid, the platform notifies this site asynchronously, and after verifying the signature and the amount the site advances the order (topping up the calling project's points balance). Notifications are occasionally lost, so callers can poll query after payment as a fallback; either path can trigger it, and delivery happens only once.

Desktop and mobile share one path: the platform decides the payment form from method / device, and pay_info can simply be rendered on the page (qrcode renders a QR code, jump opens the cashier URL). For mobile H5 / embedded WebViews use method=jump + device=mobile; to invoke the payment app from a native app use method=app; inside WeChat use device=wechat.

Response Format

Every endpoint returns the same JSON envelope; the payload is always inside data:

{
  "code": 10000,
  "msg": "成功",
  "data": { ... }
}
  • code: business status code. 10000 means success; anything else is an error — see the Error Codes page for the full list.
  • msg: a human-readable message you can show to end users, but never use it for program logic.
  • data: the payload; usually null on error. Each endpoint's Response section lists its data fields.

Judge success by code, not by the HTTP status code. View all error codes

EZFP

ezfp.cn (aggregated payment gateway, RSA signatures) Signature Required

聚合支付网关,网关地址与商户凭据(商户 ID + 商户私钥 + 平台公钥)由本站后台「支付设置」维护,调用方无需也不应持有。下单的 notify_url 由本站固定为/pay/notify/ezfp/,调用方不需要传。实际可用的支付方式取决于商户用户组开通了哪些,未开通的方式下单时平台会直接报错。

POST /api/pay/create Total calls: 0 Free Service price

Create order

Create a payment order and return the payment parameters (QR code content or cashier redirect URL) together with the merchant order number.

Required. Must match a method enabled for the merchant user group, otherwise the platform returns an error

Required. A number greater than 0 with two decimals; must not be below the per-order minimum set in the console

Optional. If omitted, the first enabled channel is used (currently only ezfp)

Optional. The product name shown to the user on the cashier page; when omitted a default subject is used

Optional. Only decides where the browser returns after payment; it takes no part in judging whether the order is paid

Optional. Returned verbatim, which makes it easy to link the order to your own business record during reconciliation

Optional. Use jump for mobile H5 / WebView and app inside a native app

Optional. Use mobile on phones and wechat inside WeChat

  • After you get the response, render according to pay_type: for qrcode turn pay_info into a QR code; for jump open pay_info in a browser / WebView (the cashier page carries its own QR code and payment entry). In practice the same WeChat payment comes back as qrcode under method=web and as an https cashier URL under method=jump, so do not hard-code either form.
  • Payment is recognised only from the asynchronous callback and an active query: the return_url redirect merely means the user saw a result page and must not be used as proof of delivery; rely on paid from the query endpoint or on the balance change that follows this site's asynchronous notification.
  • Charged only once: when the same order triggers repeated callbacks, or a callback and a query land at the same time, this site uses a row lock plus a status check to guarantee that delivery happens exactly once.
  • No QR code library needed on mobile: with method=jump the response is an ordinary web URL that opens directly in a desktop browser, a mobile browser or a WebView.
  • Creating an order costs no project points (this service is priced at 0 points per call), so a project with zero balance can still call this endpoint to top itself up.
Response Common envelope
Field Type Description
out_trade_no string Merchant order number (generated by this site; used by both query and refund)
trade_no string Platform order number (empty for some channels at creation time and filled in after payment)
provider string Channel identifier, currently ezfp
pay_type string Payment form: qrcode=QR code content / jump=cashier URL
amount string Amount (yuan, two decimals)
subject string Product name
status string Order status: pending (awaiting payment) / paid / partial_refunded / refunded / failed (order creation failed) / closed
pay_info string Payment parameter: the QR code content when pay_type=qrcode, the cashier URL when jump
param string Business extension parameter, returned verbatim
Example response
{
  "out_trade_no": "XY20261002120000123456",
  "trade_no": "2026100222001412345678",
  "provider": "ezfp",
  "pay_type": "qrcode",
  "amount": "1.00",
  "subject": "账户充值",
  "status": "pending",
  "pay_info": "weixin://wxpay/bizpayurl?pr=AbCdEfG",
  "param": ""
}
POST /api/pay/query Total calls: 0 Free Service price

Query order

Look an order up by merchant order number and sync the platform's latest status back to this site (a paid order is delivered at that point).

Required. The out_trade_no returned by the create-order endpoint

  • You can only look up orders created by your own caller: orders are isolated by APPID owner, and someone else's order always comes back as "order not found".
  • When the platform shows the order as paid while this site has not yet advanced it, this endpoint delivers on the spot (crediting the calling project's points at the rate configured in the console), so polling the query endpoint covers the case where the callback never arrived.
  • After creating an order, poll once every 3–5 seconds until paid=true or you time out; there is no need to poll faster, since the platform-side order status does not change several times in an instant.
Response Common envelope
Field Type Description
out_trade_no string Merchant order number (generated by this site; used by both query and refund)
trade_no string Platform order number (empty for some channels at creation time and filled in after payment)
provider string Channel identifier, currently ezfp
pay_type string Payment form: qrcode=QR code content / jump=cashier URL
amount string Amount (yuan, two decimals)
subject string Product name
status string Order status: pending (awaiting payment) / paid / partial_refunded / refunded / failed (order creation failed) / closed
pay_info string Payment parameter: the QR code content when pay_type=qrcode, the cashier URL when jump
param string Business extension parameter, returned verbatim
paid bool Whether the order is paid (when true, the order has been advanced and delivered)
Example response
{
  "out_trade_no": "XY20261002120000123456",
  "trade_no": "2026100222001412345678",
  "provider": "ezfp",
  "pay_type": "qrcode",
  "amount": "1.00",
  "subject": "账户充值",
  "status": "paid",
  "pay_info": "weixin://wxpay/bizpayurl?pr=AbCdEfG",
  "param": "",
  "paid": true
}
POST /api/pay/refund Total calls: 0 Free Service price

Refund order

Refund a paid order; leaving `amount` empty refunds the remaining refundable amount.

Required. The order number to refund

Optional. Must not exceed the refundable amount (order amount − already refunded)

  • You can only refund your own orders. Whether partial refunds are allowed and how long the money takes to arrive are decided by the payment platform and the channel; this endpoint only submits the request and writes the result back to the order.
  • After a successful refund the order status becomes refunded (or partial_refunded for a partial refund), and the cumulative refunded amount is recorded in refund_amount.
  • ⚠️ Refunding an order whose amount has already been credited to the calling project's points does not claw those points back automatically — contact this site's administrator if you need it reconciled manually.
Response Common envelope
Field Type Description
out_trade_no string Merchant order number (generated by this site; used by both query and refund)
trade_no string Platform order number (empty for some channels at creation time and filled in after payment)
provider string Channel identifier, currently ezfp
pay_type string Payment form: qrcode=QR code content / jump=cashier URL
amount string Amount (yuan, two decimals)
subject string Product name
status string Order status: pending (awaiting payment) / paid / partial_refunded / refunded / failed (order creation failed) / closed
pay_info string Payment parameter: the QR code content when pay_type=qrcode, the cashier URL when jump
param string Business extension parameter, returned verbatim
refund_amount string Cumulative refunded amount (yuan)
Example response
{
  "out_trade_no": "XY20261002120000123456",
  "trade_no": "2026100222001412345678",
  "provider": "ezfp",
  "pay_type": "qrcode",
  "amount": "1.00",
  "subject": "账户充值",
  "status": "refunded",
  "pay_info": "weixin://wxpay/bizpayurl?pr=AbCdEfG",
  "param": "",
  "refund_amount": "1.00"
}
XiaoYingAPI · Unified API Aggregation Service