# Connect

Connect a verified WeChat Service Account with its AppID and AppSecret, then point its server configuration at Zernio.

import { Tab, Tabs } from 'fumadocs-ui/components/tabs';

A WeChat connection takes three steps: whitelist Zernio's IPs, send the account's credentials, then paste the server values Zernio returns. All three happen in the [Weixin Official Accounts Platform](https://mp.weixin.qq.com/) under Settings and Development > Basic Configuration.

## Before you start

- The account is a **Service Account** and is **verified**.
- You can open Settings and Development > Basic Configuration, which shows the **AppID** and lets you reset the **AppSecret**.

## Whitelist Zernio's IPs

WeChat refuses API calls from IPs that are not on the account's API IP whitelist. Get Zernio's with `GET /v1/connect/wechat/ip-whitelist` and add every one of them.

<Tabs items={['Node.js', 'Python', 'curl']}>
<Tab value="Node.js">
```typescript
import Zernio from '@zernio/node';

const zernio = new Zernio();

const { data } = await zernio.connect.getWechatIpWhitelist();

console.log(data.ips);
```
</Tab>
<Tab value="Python">
```python
from zernio import Zernio

client = Zernio()

result = client.connect.get_wechat_ip_whitelist()

print(result["ips"])
```
</Tab>
<Tab value="curl">
```bash
curl "https://zernio.com/api/v1/connect/wechat/ip-whitelist" \
  -H "Authorization: Bearer $ZERNIO_API_KEY"
```
</Tab>
</Tabs>

Response (`200`):

```json
{
  "ips": ["203.0.113.10"]
}
```

## Send the credentials

Call `POST /v1/connect/wechat/credentials` with the AppID, the AppSecret and a `state` of `{userId}-{profileId}`. `displayName` is optional.

<Tabs items={['Node.js', 'Python', 'curl']}>
<Tab value="Node.js">
```typescript
const { data: wechat } = await zernio.connect.connectWechatCredentials({
  body: {
    appId: 'wx1234567890abcdef',
    appSecret: '0123456789abcdef0123456789abcdef',
    state: '6507a1b2c3d4e5f6a7b8c9d0-6507a1b2c3d4e5f6a7b8c9d1',
    displayName: 'Acme China',
  },
});

console.log(wechat.server);
```
</Tab>
<Tab value="Python">
```python
wechat = client.connect.connect_wechat_credentials(
    app_id="wx1234567890abcdef",
    app_secret="0123456789abcdef0123456789abcdef",
    state="6507a1b2c3d4e5f6a7b8c9d0-6507a1b2c3d4e5f6a7b8c9d1",
    display_name="Acme China",
)

print(wechat["server"])
```
</Tab>
<Tab value="curl">
```bash
curl -X POST "https://zernio.com/api/v1/connect/wechat/credentials" \
  -H "Authorization: Bearer $ZERNIO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "appId": "wx1234567890abcdef",
    "appSecret": "0123456789abcdef0123456789abcdef",
    "state": "6507a1b2c3d4e5f6a7b8c9d0-6507a1b2c3d4e5f6a7b8c9d1",
    "displayName": "Acme China"
  }'
```
</Tab>
</Tabs>

Response (`200`):

```json
{
  "message": "WeChat Official Account connected. Finish the server configuration in the WeChat dashboard to start receiving messages.",
  "account": {
    "accountId": "6507a1b2c3d4e5f6a7b8c9e1",
    "platform": "wechat",
    "username": "wx1234567890abcdef",
    "displayName": "Acme China",
    "isActive": true
  },
  "server": {
    "url": "https://zernio.com/api/webhook/wechat/6507a1b2c3d4e5f6a7b8c9e1",
    "token": "Zq8x2LmP4vR7tY1wK9sD3fH6jN0bC5eA",
    "encodingAESKey": "hT3kP9xQ2mV7wL4rZ8nB1cF6yJ0dG5sA3uE9iO2tR7q",
    "encryptionMode": "safe"
  },
  "ipWhitelist": ["203.0.113.10"]
}
```

## Paste the server configuration

In Basic Configuration > Server Configuration:

1. Paste `server.url` as the Server URL, `server.token` as the Token and `server.encodingAESKey` as the EncodingAESKey.
2. Choose **Safe mode** as the message encryption mode.
3. Submit, then enable the configuration. WeChat calls the URL once to check it.

Until the configuration is enabled, WeChat delivers no messages to Zernio.

Enabling it turns off the auto-replies and custom menus set in the WeChat dashboard. Recreate the ones you need as Zernio automations.

## How it behaves

- Reconnecting the same AppID on the same profile updates the existing account and keeps the Token and EncodingAESKey, so nothing has to be pasted again.
- Zernio requests access tokens in a way that does not invalidate the tokens other tools on the same account hold.
- Zernio stores the AppSecret, Token and EncodingAESKey encrypted.

## If it fails

| Error | Cause | Fix |
|-------|-------|-----|
| `400` `wechat_ip_not_whitelisted` | Zernio's IPs are not on the API IP whitelist | Add every IP from `GET /v1/connect/wechat/ip-whitelist`, then connect again. |
| `400` `invalid_field_value` (`param` is `appId` or `appSecret`) | A wrong AppID, or an AppSecret that was reset since | Copy the AppID again; reset the AppSecret and use the new one. |
| WeChat says the URL check failed | The Token or EncodingAESKey was mistyped, or the mode is not Safe mode | Paste the values from the response again and pick Safe mode. |

## Related

- [Connect WeChat](/connect/connect-wechat-credentials) - Request and response fields
- [Get the IP whitelist](/connect/get-wechat-ip-whitelist) - The IPs to whitelist
- [Connecting accounts](/guides/connecting-accounts) - Where `state` comes from