Full Flow

Payment Flow

Complete payment flow for SuperQi miniapps

This guide walks you through the complete payment flow for SuperQi miniapps. Before implementing payment functionality, ensure you have completed the authentication flow to obtain the user's access token.

Overview

The payment process consists of two main steps:

  1. Backend: Create a payment request and obtain a payment URL
  2. Frontend: Use the payment URL to initiate the payment process
Prerequisites: You must have a valid accessToken from the authentication flow before proceeding with payments.

Step 1: Backend - Create Payment Request

API Endpoint

URL: POST /v1/payments/pay

Request Body

{
  "productCode": "51051000101000000011",
  "paymentRequestId": "your_unique_order_id",
  "paymentAmount": {
    "currency": "IQD",
    "value": "150000"
  },
  "order": {
    "orderDescription": "Product purchase description",
    "buyer": {
      "referenceBuyerId": "user_access_token"
    }
  },
  "paymentExpiryTime": "2024-01-18T16:10:36+03:00",
  "paymentRedirectUrl": "https://your-domain.com/payment-success",
  "paymentNotifyUrl": "https://your-domain.com/api/payment-notification",
  "voidNotifyUrl": "https://your-domain.com/api/void-notification",
  "extendInfo": "Additional payment information"
}

Request Parameters

productCode (String, Required)

  • Defines the payment type. Choose from:
    • Online Purchase: "51051000101000000011"
    • Online Purchase (Auth Capture): "51051000101000000012"
    • Agreement Payment: "51051000101000100031"

paymentRequestId (String, Required)

  • Your unique order ID from your database
  • Used for idempotence control
  • Max length: 64 characters

paymentAuthCode (String, Optional)

  • Payment authorization code
  • Max length: 128 characters

paymentAmount (Object, Required)

  • currency: Always "IQD"
  • value: Amount in fils (multiply IQD by 1000)
    • Example: 1000 IQD = "1000000" fils

order (Object, Required)

  • orderDescription: Description of the purchase
  • buyer.referenceBuyerId: The user's access token from authentication

paymentExpiryTime (String, Optional)

  • Payment expiration time in ISO 8601 format
  • If empty, wallet will set default expiry

paymentRedirectUrl (String, Optional)

  • URL to redirect user after payment completion
  • Max length: 1024 characters

paymentNotifyUrl (String, Optional)

  • Your backend endpoint to receive payment success notifications
  • Max length: 1024 characters

voidNotifyUrl (String, Optional)

  • Your backend endpoint to receive payment void notifications
  • Max length: 1024 characters

extendInfo (String, Optional)

  • Additional information in JSON format
  • Max length: 2048 characters

Expected Response

{
  "result": {
    "resultCode": "ACCEPT",
    "resultStatus": "A",
    "resultMessage": "accept"
  },
  "paymentId": "2023120611121280010016600090000xxxx",
  "redirectActionForm": {
    "redirectionUrl": "https://www.wallet.com/cashier?orderId=xxxxxxx"
  }
}
For detailed request/response specifications, see the payment API documentation.

Step 2: Frontend - Initiate Payment

Implementation

After receiving the payment URL from your backend, use the my.tradePay method to initiate the payment:

my.tradePay({
  paymentUrl: String(redirectionUrl), // URL from backend response
  success: (res) => {
    // Handle successful payment
    console.log("Payment successful:", res);
    // TODO: Implement success actions (redirect, show success message, etc.)
  },
  fail: (res) => {
    // Handle payment failure
    console.error("Payment failed:", res);
    // TODO: Implement error handling (show error message, retry option, etc.)
  },
});

Payment Flow Example

1. User Initiates Payment

// Frontend: User clicks "Pay Now" button
function initiatePayment(amount, orderDescription) {
  // Send payment request to your backend
  // TODO: Implement your backend API call
  console.log(`Initiating payment for ${amount} IQD`);
}

2. Backend Creates Payment Request

// Backend: Create payment request
const paymentRequest = {
  productCode: "51051000101000000011", // Online Purchase
  paymentRequestId: generateUniqueOrderId(),
  paymentAmount: {
    currency: "IQD",
    value: String(amount * 1000), // Convert IQD to fils
  },
  order: {
    orderDescription: orderDescription,
    buyer: {
      referenceBuyerId: userAccessToken, // From authentication flow
    },
  },
  paymentNotifyUrl: "https://your-domain.com/api/payment-notification",
};

// TODO: Send request to SuperQi API with proper headers and signature

3. Frontend Processes Payment

// Frontend: Use the payment URL from backend response
my.tradePay({
  paymentUrl: paymentResponse.redirectActionForm.redirectionUrl,
  success: (res) => {
    // Payment completed successfully
    window.location.href = "/payment-success";
  },
  fail: (res) => {
    // Payment failed
    alert("Payment failed. Please try again.");
  },
});

Important Notes

Payment Amount Calculation
  • Always multiply IQD amount by 1000 to convert to fils
  • Example: 150 IQD = 150,000 fils = "150000" ::
Payment Notifications
  • Set up paymentNotifyUrl to receive payment success notifications
  • Set up voidNotifyUrl to handle payment cancellations
  • These endpoints should be secured and validate the incoming requests ::
Order ID Management
  • Use paymentRequestId for idempotence control
  • Ensure each payment request has a unique order ID
  • Store the mapping between your order ID and SuperQi's paymentId ::

Additional Resources