> ## 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.

# WeChat JSAPI Payment (Official Account)

> Integrate WeChat JSAPI payments within the WeChat in-app browser using OAuth authorization and JSAPI payment invocation.

<Frame>
  <img src="https://mintcdn.com/qfpay-8e347952/Z1AddYlWO-nm9608/images/online-shop/wechat_jsapi_process.jpg?fit=max&auto=format&n=Z1AddYlWO-nm9608&q=85&s=aec8f141cd27a945576e3151f740e7cb" alt="Wechat Jsapi Process" width="1414" height="780" data-path="images/online-shop/wechat_jsapi_process.jpg" />
</Frame>

<Warning>
  This payment method must be initiated **inside the WeChat in-app browser**.\
  It will NOT work in external browsers such as Chrome or Safari.
</Warning>

***

## Overview

WeChat JSAPI enables payments inside an Official Account web page viewed within WeChat.

This method is ideal for:

* Official Account H5 stores
* In-app service flows
* QR campaigns opening inside WeChat

> For merchants in Canada, refer to\
> [Alipay Web Payments](/integration/online-shop/integration-by-payment-type/alipay/alipay-web-payments)\
> where `pay_type = 800207`.

***

## Integration Methods

### Method 1 — Merchant’s Own Official Account

Merchants use their verified WeChat Official Account.

**Requirements**

1. Official Account verified & linked to QFPay
2. Obtain user `openid`
3. Domain added to JSAPI whitelist

Resources:

* [https://developers.weixin.qq.com/doc/offiaccount/en/Getting\_Started/Overview.html](https://developers.weixin.qq.com/doc/offiaccount/en/Getting_Started/Overview.html)
* [https://pay.weixin.qq.com/wiki/doc/api/jsapi.php](https://pay.weixin.qq.com/wiki/doc/api/jsapi.php)

***

### Method 2 — QFPay Official Account (Indirect Settlement)

For merchants without a verified account, QFPay provides an Official Account.

***

## Payment Flow Overview

1. User opens payment page inside WeChat
2. Retrieve OAuth code
3. Exchange code → obtain `openid`
4. Submit payment request
5. Redirect to WeChat JSAPI payment module
6. Verify payment result via backend

***

## Step 1 — Obtain WeChat OAuth Code

**Request**

GET `/tool/v1/get_weixin_oauth_code`

<Note>
  This endpoint must be opened inside WeChat.\
  `app_code` and `sign` must be sent as **query parameters**, not headers.
</Note>

### Parameters

| Name         | Param          | Required | Description                     |
| ------------ | -------------- | -------- | ------------------------------- |
| App Code     | `app_code`     | Yes      | Provided by QFPay               |
| Redirect URL | `redirect_uri` | Yes      | URL after authorization         |
| Merchant ID  | `mchid`        | No       | Provided if applicable          |
| Signature    | `sign`         | Yes      | MD5 signature using client\_key |

```python theme={null}
def make_req_sign(data, key):
    keys = sorted(data.keys())
    raw = "&".join(f"{k}={data[k]}" for k in keys) + key
    return hashlib.md5(raw.encode()).hexdigest().upper()
```

**Response**

```json theme={null}
{
  "redirect": "https://yourdomain.com/callback?code=011xxxxx"
}
```

Redirect the user to the returned URL.

***

## Step 2 — Exchange Code for `openid`

**Request**

GET `/tool/v1/get_weixin_openid`

### Parameters

| Parameter | Required | Description                 |
| --------- | -------- | --------------------------- |
| `code`    | Yes      | OAuth code from Step 1      |
| `mchid`   | No       | Required for some merchants |

Headers required:

* `X-QF-APPCODE`
* `X-QF-SIGN`

```python theme={null}
def get_open_id(code):
    params = {"code": code}
    headers = {
        "X-QF-APPCODE": app_code,
        "X-QF-SIGN": make_req_sign(params, client_key)
    }
    r = requests.get(environment + "/tool/v1/get_weixin_openid",
                     params=params, headers=headers)
    return r.json().get("openid")
```

**Response**

```json theme={null}
{
  "respcd": "0000",
  "openid": "oo3Lss8d0hLOuyTuSJMVwLTk68JE"
}
```

<Note>
  A new OAuth code and openid must be obtained for **each payment attempt**.\
  Do not cache or reuse.
</Note>

***

## Step 3 — Submit Payment Request

**Endpoint**

POST `/trade/v1/payment`

**PayType:** `800207` (WeChat JSAPI)

### Required Fields

| Field             | Required | Description                                  |
| ----------------- | -------- | -------------------------------------------- |
| `sub_openid`      | Yes      | openid from Step 2                           |
| Common Parameters | Yes      | amount, currency, timestamp, order no        |
| `limit_pay`       | No       | restrict payment methods                     |
| `extend_info`     | No       | real-name verification (Mainland China only) |

Refer to:

* [Common Parameters](/integration/api-reference/request-format)
* [PayType Reference](/integration/api-reference/paytypes)

```python theme={null}
def create_payment(openid):
    data = {
        "txamt": "100",
        "txcurrcd": "HKD",
        "pay_type": "800207",
        "out_trade_no": "ORDER12345",
        "txdtm": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        "sub_openid": openid
    }
    headers = {
        "X-QF-APPCODE": app_code,
        "X-QF-SIGN": make_req_sign(data, client_key)
    }
    r = requests.post(environment + "/trade/v1/payment",
                      params=data, headers=headers)
    return r.json()["pay_params"]
```

***

### pay\_params Response

| Field       | Description            |
| ----------- | ---------------------- |
| `appId`     | Official Account AppID |
| `timeStamp` | timestamp              |
| `nonceStr`  | random string          |
| `package`   | prepay package         |
| `signType`  | signature method       |
| `paySign`   | payment signature      |

***

## Step 4 — Redirect to WeChat Payment Module

Redirect the user’s browser to:

`GET https://o2-hk.qfapi.com/q/direct`

### Required Parameters

| Parameter      | Description           |
| -------------- | --------------------- |
| `mchntnm`      | Merchant display name |
| `txamt`        | Amount                |
| `currency`     | Currency              |
| `redirect_url` | URL after payment     |
| `package`      | from pay\_params      |
| `timeStamp`    | from pay\_params      |
| `signType`     | from pay\_params      |
| `paySign`      | from pay\_params      |
| `appId`        | from pay\_params      |
| `nonceStr`     | from pay\_params      |

<Note>
  This request is sent directly from the user’s browser.\
  No authentication headers are required.
</Note>

***

## Additional Notes

* JSAPI flow must be executed sequentially
* Do not reuse OAuth codes or openid
* If payment result is delayed, verify via\
  [Transaction Enquiry API](/integration/common-api/transaction-enquiry)
* Real-name verification is optional and depends on merchant configuration
