> ## Documentation Index
> Fetch the complete documentation index at: https://sdk.qfapi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Alipay Web Payments

> Integration guide for Alipay Web payments (Hong Kong + Overseas).

This guide describes how to integrate **Alipay Web Payments** for both Hong Kong and overseas merchants.

<Note>
  **AlipayHK does not support the native Alipay checkout page.**\
  For AlipayHK, merchants typically request a QR code / payment URL and embed it in the merchant page (e.g. as a QR code image or via an `iframe`).
</Note>

***

## Overview

Alipay Web Payments allow customers to complete a purchase by scanning a QR code (or opening a hosted payment URL). After payment confirmation, funds are deducted from the customer’s wallet and the result is returned to the merchant system.

* Mainland China users pay in **CNY**; QFPay settles to merchants in the configured settlement currency.
* Hong Kong users pay in **HKD**.

If `return_url` is provided, the customer is redirected back to the merchant website after payment.

***

## HTTP Request

**Endpoint**

`POST /trade/v1/payment`

***

## Supported Pay Types

| PayType | Description                    |
| ------: | ------------------------------ |
|  801101 | Alipay Web Payment (Overseas)  |
|  801514 | Alipay Web Payment (Hong Kong) |

***

## Request Parameters

| Field          | Type        | Required | Description                                                                            |
| -------------- | ----------- | -------- | -------------------------------------------------------------------------------------- |
| `txamt`        | Int(11)     | Yes      | Amount in cents. Suggested > 200 to reduce risk control triggers.                      |
| `txcurrcd`     | String(3)   | Yes      | Currency (e.g. `HKD`, `CNY`). See [Currencies](/integration/api-reference/currencies). |
| `pay_type`     | String(6)   | Yes      | PayType (see table above).                                                             |
| `out_trade_no` | String(128) | Yes      | Unique merchant order ID.                                                              |
| `txdtm`        | String(20)  | Yes      | Timestamp `YYYY-MM-DD HH:mm:ss`.                                                       |
| `expired_time` | String(3)   | No       | QR expiry (minutes). 5–120. (MPM only)                                                 |
| `goods_name`   | String(64)  | No       | Product name (≤20 chars). Use UTF-8 if Chinese.                                        |
| `mchid`        | String(16)  | No       | Required if provided by QFPay for your store setup.                                    |
| `udid`         | String(40)  | No       | Device ID for reporting.                                                               |
| `return_url`   | String(512) | No       | Redirect URL after successful payment.                                                 |

***

## Response Parameters

| Field          | Type        | Description                                                                 |
| -------------- | ----------- | --------------------------------------------------------------------------- |
| `respcd`       | String(4)   | Return code. `0000` = success; `1143/1145` = retry needed; others = failed. |
| `resperr`      | String(128) | Error details (if any).                                                     |
| `respmsg`      | String(128) | General response message.                                                   |
| `syssn`        | String(40)  | QFPay transaction ID.                                                       |
| `out_trade_no` | String(128) | Merchant order ID.                                                          |
| `txamt`        | Int(11)     | Amount (cents).                                                             |
| `txdtm`        | String(20)  | Request timestamp.                                                          |
| `sysdtm`       | String(20)  | Server timestamp (used for settlement cutoff).                              |
| `pay_type`     | String(6)   | PayType used.                                                               |
| `pay_url`      | String(512) | Payment URL (render as QR code or embed in `iframe`).                       |

***

## Code Examples

<Note>
  Use the language tabs below. Replace the placeholders with your own credentials and values.
</Note>

<CodeGroup>
  ```python Python theme={null}
  # coding=utf-8
  import hashlib
  import requests
  import datetime

  environment = "https://test-openapi-hk.qfapi.com"
  app_code = "YOUR_APP_CODE"
  client_key = "YOUR_CLIENT_KEY"

  def make_req_sign(data, key):
      keys = sorted(list(data.keys()))
      parts = []
      for k in keys:
          parts.append(f"{k}={data[k]}")
      sign_str = ("&".join(parts) + key).encode("utf-8")
      return hashlib.md5(sign_str).hexdigest().upper()

  current_time = datetime.datetime.now().replace(microsecond=0).strftime("%Y-%m-%d %H:%M:%S")

  data = {
      "txamt": "10",
      "txcurrcd": "HKD",
      "pay_type": "801101",
      "out_trade_no": "01234567890123",
      "txdtm": current_time,
      # "mchid": "ZaMVg*****"  # include only if provided by QFPay
  }

  headers = {
      "X-QF-APPCODE": app_code,
      "X-QF-SIGN": make_req_sign(data, client_key),
  }

  r = requests.post(environment + "/trade/v1/payment", data=data, headers=headers)
  print(r.json())
  ```

  ```java Java theme={null}
  import java.text.SimpleDateFormat;
  import java.util.Date;
  import java.util.HashMap;
  import java.util.Map;

  public class TestMain {
    public static void main(String[] args) {
      String appcode = "YOUR_APP_CODE";
      String key = "YOUR_CLIENT_KEY";

      String pay_type = "801101";
      String out_trade_no = "01234567890123";
      String txdtm = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());

      Map<String, String> params = new HashMap<>();
      params.put("pay_type", pay_type);
      params.put("out_trade_no", out_trade_no);
      params.put("txdtm", txdtm);
      params.put("txamt", "10");
      params.put("txcurrcd", "HKD");
      // params.put("mchid", "ZaMVg*****"); // include only if provided by QFPay

      String data = QFPayUtils.getDataString(params);
      String md5 = QFPayUtils.getMd5Value(data + key);

      String url = "https://test-openapi-hk.qfapi.com";
      String resp = Requests.sendPostRequest(url + "/trade/v1/payment", data, appcode, md5);
      System.out.println(resp);
    }
  }
  ```

  ```javascript JavaScript theme={null}
  const crypto = require("crypto");
  const request = require("request");

  const environment = "https://test-openapi-hk.qfapi.com";
  const app_code = "YOUR_APP_CODE";
  const client_key = "YOUR_CLIENT_KEY";

  const txdtm = new Date().toISOString().replace("T", " ").replace(/\..+/, "");
  const out_trade_no = String(Math.round(Math.random() * 1000000000));

  const payload = {
    txamt: "10",
    txcurrcd: "HKD",
    pay_type: "801101",
    out_trade_no,
    txdtm
    // mchid: "ZaMVg*****" // include only if provided by QFPay
  };

  const ordered = Object.keys(payload).sort().map(k => `${k}=${payload[k]}`).join("&");
  const signString = ordered + client_key;
  const sign = crypto.createHash("md5").update(signString).digest("hex").toUpperCase();

  request({
    uri: environment + "/trade/v1/payment",
    headers: {
      "X-QF-APPCODE": app_code,
      "X-QF-SIGN": sign
    },
    method: "POST",
    form: payload
  }, function (error, response, body) {
    console.log(body);
  });
  ```

  ```php PHP theme={null}
  <?php
  function randStr($length) {
    $str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    $out = '';
    for ($i = 0; $i < $length; $i++) {
      $out .= $str[rand(0, strlen($str) - 1)];
    }
    return $out;
  }

  $url = 'https://test-openapi-hk.qfapi.com';
  $api = '/trade/v1/payment';

  $app_code = 'YOUR_APP_CODE';
  $app_key = 'YOUR_CLIENT_KEY';

  $fields = array(
    'pay_type' => '801101',
    'out_trade_no' => randStr(20),
    'txcurrcd' => 'HKD',
    'txamt' => '2200',
    'txdtm' => date("Y-m-d H:i:s")
    // 'mchid' => 'ZaMVg*****' // include only if provided by QFPay
  );

  ksort($fields);
  $pairs = array();
  foreach($fields as $k => $v) { $pairs[] = $k . '=' . $v; }
  $fields_string = implode('&', $pairs);

  $sign = strtoupper(md5($fields_string . $app_key));

  $header = array(
    'X-QF-APPCODE: ' . $app_code,
    'X-QF-SIGN: ' . $sign
  );

  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url . $api);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt($ch, CURLOPT_POST, 1);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);

  $output = curl_exec($ch);
  curl_close($ch);

  echo $output;
  ?>
  ```
</CodeGroup>

***

## Sample Response

```json theme={null}
{
  "sysdtm": "2020-04-13 10:30:34",
  "paydtm": "2020-04-13 10:30:34",
  "txcurrcd": "HKD",
  "respmsg": "",
  "pay_type": "801101",
  "udid": "qiantai2",
  "txdtm": "2020-04-13 10:30:34",
  "txamt": "300",
  "resperr": "success",
  "out_trade_no": "4K35N374II7UJJ8RGIAE45O2CVHGHFF0",
  "syssn": "20200413000300020087033882",
  "respcd": "0000",
  "pay_url": "https://globalmapi.alipay.com/gateway.do?...",
  "chnlsn": ""
}
```

***

## Notes

<Tip>
  Render the QR code or `iframe` using `pay_url`.
</Tip>

<Warning>
  Do not reuse `out_trade_no` across payments or refunds.
</Warning>

<Info>
  If `respcd` is `1143` or `1145`, retry or query the transaction result using `/trade/v1/query`.
</Info>
