Step 1: Create a Payment Intent
There are two approaches depending on when the payment method is available:- Direct payment
- Delayed confirmation
Include API reference: Create Payment Intent
payment_method in the creation request. The payment processes immediately.Step 2: Handle the response
Check theintent_status field in the response to determine what to do next:
Successful response example
Step 3: Handle customer actions
Whenintent_status is REQUIRES_CUSTOMER_ACTION, the next_action field tells you what the customer needs to do.
3DS redirect
If the card requires 3D Secure authentication,next_action contains a redirect URL:
return_url. For detailed 3DS integration guidance, see:
QR code display
For e-wallet payments (AlipayCN, WeChatPay, etc.),next_action may contain a QR code:
Step 4: Get payment results
Use one or both of these methods to confirm the final payment status:Webhooks (recommended)
Configure your server to receive asynchronous notifications from UQPAY. This is the most reliable method. Key webhook events:acquiring.payment_intent.succeeded— payment completedacquiring.payment_attempt.failed— payment attempt failed. Note:acquiring.payment_intent.failedis only triggered when the PI times out and auto-closes (30-minute expiry), not on individual attempt failures.acquiring.payment_attempt.capture_requested— capture submitted. Receiving this event also indicates the payment has succeeded.
Retrieve API (polling)
Query the payment status directly:E-wallet payments
The same API supports e-wallet payment methods. Replace thepayment_method object with the appropriate wallet type:
AlipayCN QR code example
AlipayCN QR code example
next_action.display_qr_code for the customer to scan.AlipayCN payment code example (in-person)
AlipayCN payment code example (in-person)
Pre-authorization and manual capture
Before using pre-authorization, confirm that your account and payment channel support it. Use the direct API withcard or card_present; Hosted Payment Page and Payment Links do not support pre-authorization.
- Set
authorization_typetopre_authorizationwhen you create or confirm the PaymentIntent. Setpayment_method.card.auto_captureorpayment_method.card_present.auto_capturetofalse. If you also provide the authorization type inside the payment method, both values must match. A pre-authorized PaymentIntent cannot be changed to ordinary authorization at confirmation. - After authorization, inspect
intent_status,authorization_expires_at, andavailable_to_capture. Capture while the PaymentIntent isREQUIRES_CAPTUREand before the returned expiry. Do not assume a fixed authorization period. - Capture the PaymentIntent once. Omit
final_captureor set it totrue;falseis rejected. Omitamount_to_captureto capture the available amount, or supply a positive amount up to that balance. Partial final capture requires channel support. Zero, empty, and null amounts are rejected. The system handles any remaining authorization release; do not send a second capture or a zero-amount capture to release it. - Keep the returned
capture_idandmerchant_capture_order_id. Retrieve the PaymentIntent to inspectcapture_records. Capture acceptance and the PaymentIntent aggregate amount do not establish channel completion. Each record has achannel_capture_status:0pending,1processing,2completed, or3failed.
Capture references and retries
Use an account-uniquemerchant_capture_order_id of at most 64 characters. If omitted, it defaults to the PaymentIntent’s merchant_order_id. Keep the same X-Idempotency-Key when retrying an identical request after a transport failure. A recorded capture reference submitted again outside the cached response is rejected, not executed as another capture. Query the existing PaymentIntent to determine the result before taking further action. A failed capture does not permit another capture against the same authorization.
Cancellation and refunds
Before any capture, you can cancel an unexpired pre-authorization when the channel supports cancellation. After capture, use the refund flow for captured funds. A positiveavailable_to_void value alone does not establish cancellation eligibility.
PaymentIntent captured_amount is the aggregate capture amount; PaymentAttempt has no capture-amount field. Use capture_records[].capture_amount and the associated processing status for individual captures.
