## 6. API Documentation (Hosted Checkout Mode) Hosted Checkout mode is Infini's most recommended integration method. Merchants only need to create orders, redirect to checkout_url, and handle Webhooks to complete payment integration. This chapter only contains API documentation and corresponding field descriptions for Hosted Checkout mode. All API prefix: `/v1/acquiring` ### 6.1 Create Order **POST** /v1/acquiring/order Used to create an order and return the hosted checkout access URL (checkout_url). #### Headers ```json Content-Type: application/json Date: {GMT Time} Authorization: Signature ... ``` #### Request Body | Field | Type | Required | Description | | --- | --- | --- | --- | | amount | string/number | Yes | Order fiat amount (up to 6 decimal places) | | currency | string | Yes | Fiat currency, e.g. "USD" | | request_id | string | Yes | Merchant-generated idempotency key, UUID "a759b99a-9d22-433d-bced-ab1d2e1bea1d" | | client_reference | string | No | Merchant custom order number, recommended to be unique | | description | string | No | Order description | | expires_in | number | No | Order expiration relative time (Unix seconds); use backend default if not provided | | merchant_alias | string | No | Merchant display name (overrides backend configuration) | | success_url | string | No | Redirect address after successful order payment | | failure_url | string | No | Redirect address after failed order payment | #### Response Example ```json { "order_id": "10290d05-xxxx", "amount": "100", "currency": "USD", "checkout_url": "https://checkout.infini.money/pay/xxxx", "expires_in": 3600 } ``` ### 6.2 Query Order **GET** /v1/acquiring/order?order_id ={order_id} Returns real-time order status information. #### Order Status Field Description ##### `status` - Payment Progress Status Real-time calculated field reflecting the order's current payment progress (based on `amount_confirmed` vs `order_amount`). | Value | Description | | --- | --- | | `pending` | Awaiting payment, no funds received | | `partial_paid` | Partial payment, received partial funds but insufficient | | `paid` | Paid, received sufficient funds | | `overpaid` | Overpaid, received funds exceed order amount | | `expired` | Expired | | `closed` | Expired with only partial funds received | ##### `pay_status` - Order Processing Status Database stored field recording the order's processing status. | Value | Description | | --- | --- | | `pending` | Awaiting payment | | `processing` | Processing (partial funds received) | | `paid` | Paid | | `partial_paid` | Partial payment expired | | `expired` | Expired without payment | ##### Webhook Events The `status` field in Webhook is consistent with `pay_status` in the query interface. #### Response Example ```json { "order_id": "ord-123", "status": "processing", "pay_status": "processing", "amount": "100", "currency": "USD", "amount_confirming": "0", "amount_confirmed": "0.5", "expires_at": 1763512195, "created_at": 1763512000, "exception_tags": ["wrong_currency"], "client_reference": "ORDER-001" } ``` ### 6.3 Reissue Checkout Token **POST** /v1/acquiring/token/reissue Used to regenerate the hosted checkout URL, suitable for scenarios such as payment page closure or Token expiration. #### Request Body | Field | Type | Required | Description | | --- | --- | --- | --- | | order_id | string | Yes | Unique order ID | #### Response ```json { "order_id": "ord-123", "checkout_url": "https://checkout.infini.money/pay/xxxx" } ``` ### 6.4 Webhook (Order Status Callback) Merchants can configure Webhook receiving address in the backend. When order status changes, Infini will actively push the following events: - order.created - order.processing - order.completed - order.expired - order.late_payment #### Webhook Headers | Header | Description | | --- | --- | | X-Webhook-Timestamp | Unix timestamp | | X-Webhook-Event-Id | Unique event ID | | X-Webhook-Signature | Webhook HMAC signature | #### Webhook Payload Example ```json { "event": "order.completed", "order_id": "ord-123", "client_reference": "ORDER-001", "amount": "100", "currency": "USD", "status": "paid", "amount_confirmed": "100", "amount_confirming": "0", "created_at": 1763512195, "updated_at": 1763512573, "exception_tags": [] } ``` For Webhook signature verification methods, please refer to **Chapter 4: Authorization and Security Mechanisms**. ### 6.5 Error Codes All error response format: ```json { "code": 40001, "message": "Invalid request", "detail": "expires_at must be greater than current timestamp" } ``` #### Common Error Codes | HTTP | Code | Description | | --- | --- | --- | | 400 | 40003 | amount must be positive | | 400 | 40006 | amount must be greater than 0.01 | | 401 | 401 | Invalid HMAC signature | | 404 | 40401 | Order does not exist | | 409 | 40902 | client_reference duplicate | | 409 | 40906 | Order expired | ### 6.6 Python Example (Hosted Checkout Mode) The following example demonstrates the complete flow: Create Order → Redirect to Checkout → Webhook → Reissue Token. #### 6.6.1 Create Order ```python import hmac, hashlib, base64, time from datetime import datetime, timezone import requests key_id = "merchant-001-prod" secret_key = b"your-secret-key" def create_order(amount): method = "POST" path = "/v1/acquiring/order" gmt_time = datetime.now(timezone.utc).strftime('%a, %d %b %Y %H:%M:%S GMT') signing_string = f"{key_id}\n{method} {path}\ndate: {gmt_time}\n" signature = base64.b64encode( hmac.new(secret_key, signing_string.encode(), hashlib.sha256).digest() ).decode() response = requests.post( f"https://openapi.infini.money{path}", json={ "amount": amount, "currency": "USD", "client_reference": "ORDER-2024-001", "description": "Product purchase", "expires_at": int(time.time()) + 3600 }, headers={ "Date": gmt_time, "Authorization": f'Signature keyId="{key_id}",algorithm="hmac-sha256",headers="@request-target date",signature="{signature}"', "Content-Type": "application/json" } ) response.raise_for_status() return response.json() ``` #### 6.6.2 Frontend Redirect to Checkout ```python @app.route('/create-payment', methods=['POST']) def create_payment(): order = create_order(amount=request.json['amount']) return {"checkout_url": order["checkout_url"]} ``` #### 6.6.3 Webhook Callback Handling ```python @app.route('/webhook', methods=['POST']) def handle_webhook(): event = request.json if event['event'] == 'order.completed': process_fulfillment(event['order_id'], event['amount_confirmed']) elif event['event'] == 'order.processing': update_order_progress(event['order_id'], event['status']) elif event['event'] == 'order.expired': mark_order_expired(event['order_id']) return {"status": "ok"} ``` #### 6.6.4 Reissue Checkout Token ```python def reissue_checkout_token(order_id): method = "POST" path = "/v1/acquiring/token/reissue" gmt_time = datetime.now(timezone.utc).strftime('%a, %d %b %Y %H:%M:%S GMT') signing_string = f"{key_id}\n{method} {path}\ndate: {gmt_time}\n" signature = base64.b64encode( hmac.new(secret_key, signing_string.encode(), hashlib.sha256).digest() ).decode() response = requests.post( f"https://api.infini.money{path}", json={"order_id": order_id}, headers={ "Date": gmt_time, "Authorization": f'Signature keyId="{key_id}",algorithm="hmac-sha256",headers="@request-target date",signature="{signature}"', "Content-Type": "application/json" } ) response.raise_for_status() return response.json() ```