Create and present a payment session
For an end-to-end walkthrough, choose a payment method. This page covers the shared session contract and recovery operations.
A payment session connects your business order to the instructions a customer uses to pay. Create it on your backend, save the platform order ID, and pass the invocation to your client.
Create the session
Send POST /payment-sessions to the Payment API with payments:write and an Idempotency-Key header.
| Field | Meaning |
|---|---|
app_id | The platform application ID authorized by the key. |
payment_entry | An enabled WeChat or Alipay entry. |
amount_minor | Positive integer amount in CNY fen. |
currency | CNY. |
external_order_id | Your stable business order ID, unique within the application. |
description | A concise description of what the customer is buying. |
scene | Additional context required by the entry. |
For wechat_h5, provide scene.client_ip and scene.return_url_id. The return URL ID refers to an approved configuration; it is not an arbitrary destination URL.
{
"app_id": "app_demo",
"payment_entry": "wechat_h5",
"amount_minor": 10000,
"currency": "CNY",
"external_order_id": "shop_order_1043",
"description": "One-time app purchase",
"scene": {
"client_ip": "203.0.113.10",
"return_url_id": "return_checkout"
}
}
Use the customer's actual payment IP for a real request. Determine your trusted proxy handling on the server before populating it.
Present payment instructions
Read data.invocation.kind and the field named for that kind. All non-null invocations have an expires_at value.
kind | Field | Client action |
|---|---|---|
sdk_string | sdk_string | Pass the complete value to the relevant payment SDK. |
sdk_fields | sdk_fields | Map the named fields into the provider's native payment request. |
redirect_url | redirect_url | Navigate to the returned HTTPS payment URL. |
qr_url | qr_url | Encode the value as a QR code for the customer to scan. |
html_form | html_form | Present the provider payment form through your controlled checkout integration. |
alipay_qr returns redirect_url: encode that cashier link as a QR code using the Alipay QR tutorial. wechat_native returns qr_url: encode the provider URI using the WeChat QR tutorial.
Use the returned discriminator even when you expect a particular provider response. Reject unknown kinds in your client handler and retain the order so your backend can recover it.
For html_form, establish a dedicated rendering path for authenticated payment responses. Apply your provider destination policy and keep this path separate from customer-supplied HTML.
WeChat native fields
The sdk_fields object contains provider, app_id, merchant_id, prepay_id, package, nonce, timestamp, signature, and signature_algorithm.
Here, sdk_fields.app_id is the WeChat AppID. It is different from the platform app_id used to create the order. Preserve the supplied values when constructing the SDK request; your client does not generate a new payment signature.
Retrieve the original session
curl --fail-with-body \
"https://pay.appconnect.cn/payment/v1/orders/$ORDER_ID/payment-session" \
--header "Authorization: Bearer $PAYMENT_API_KEY"
Use this endpoint when the original response was lost or the invocation is not ready. Retrieval refers to the existing order; it does not authorize creating a second business order. An expired invocation is not proof that an order is unpaid. Query the order before deciding what to show next.
Close an unpaid order
Retrieve the latest order, then send POST /orders/{order_id}/close with an idempotency key and its version as expected_version:
{"expected_version": 3}
Save the body as close.json. Persist a close-command idempotency key and the exact body before sending:
curl --fail-with-body --request POST \
'https://pay.appconnect.cn/payment/v1/orders/ord_demo_001/close' \
--header "Authorization: Bearer $PAYMENT_API_KEY" \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: close-shop-order-1042-v1' \
--data-binary @close.json
Use payments:write. Save the returned data.id as the operation ID. Query its status with operations:read:
curl --fail-with-body \
'https://pay.appconnect.cn/payment/v1/operations/op_demo_001' \
--header "Authorization: Bearer $PAYMENT_API_KEY"
The operation can be pending, running, succeeded, failed, or manual_review. Continue tracking unresolved work. After it resolves, retrieve the order again; a completed HTTP request alone does not establish that the order is closed.
If payment completed while the close was in flight, reconcile the paid order and use the refund workflow if needed. After a confirmed failed or closed attempt, a customer may explicitly start a new attempt with a new unique external reference linked to the same business purchase. Never reuse the old signed invocation or create a replacement while its payment outcome remains unresolved.