# 嵌入式注册

本文档介绍了如何实现嵌入式注册并捕获其生成的数据，以便让新客户通过您的软件创建WABA。

## 步骤1：添加允许的域名 <a href="#step-1--add-allowed-domains" id="step-1--add-allowed-domains"></a>

登录Meta开发者平台 [App Dashboard](https://developers.facebook.com/apps) ， 前往 **Facebook Login for Business** > **Settings** > **Client OAuth settings**:

<figure><img src="https://scontent-hkg4-1.xx.fbcdn.net/v/t39.2365-6/465708937_913631386932225_3931496644600528212_n.png?_nc_cat=110&#x26;ccb=1-7&#x26;_nc_sid=e280be&#x26;_nc_ohc=sIEt9lKGcS0Q7kNvwGwfiiM&#x26;_nc_oc=AdknZNhyb-RbAgoCzMPuc_C2ZXTSMvHYtonp9xEn54zqENctPMonou-BcZlEnKDGm7M&#x26;_nc_zt=14&#x26;_nc_ht=scontent-hkg4-1.xx&#x26;_nc_gid=KewqQkxMs2vkbZVoxnONzg&#x26;oh=00_AfYpn1aFaHjzCdMl8LYvcPZrCj7ONwA7RrwrNNE-Xp_UKw&#x26;oe=68E331CC" alt=""><figcaption></figcaption></figure>

将以下开关设置为 **Yes**：

* **Client OAuth login**
* **Web OAuth login**
* **Enforce HTTPS**
* **Embedded Browser OAuth Login**
* **use Strict Mode for redirect URIs**
* **Login with the JavaScript SDK**

{% hint style="info" %}
**注意**：\
\- 嵌入式注册 (Embedded Signup) 依赖于 JavaScript SDK。\
\- 当企业客户完成嵌入式注册流程时，客户的 **WABA ID**、**企业电话号码 ID**  会返回到触发该流程的窗口，但前提是：该窗口所在页面的域名必须已添加到 **Allowed domains** 和 **Valid OAuth redirect URIs** 字段中。请将你计划部署嵌入式注册的所有域名（包括开发环境下测试流程用的域名）添加到上述字段中。

\- 仅支持启用了 **HTTPS** 的域名
{% endhint %}

## 步骤2: 创建 **Facebook Login for Business** ConfigurationID <a href="#step-2--create-a-facebook-login-for-business-configuration" id="step-2--create-a-facebook-login-for-business-configuration"></a>

Facebook Login for Business 配置定义了在企业客户使用 **嵌入式注册 (Embedded Signup)** 时，需要请求哪些权限以及收集哪些额外信息。

在控制台中导航到 **Facebook Login for Business > Configurations**

<figure><img src="https://scontent-hkg1-2.xx.fbcdn.net/v/t39.2365-6/518383927_1808192009811748_4848992549354412342_n.png?_nc_cat=107&#x26;ccb=1-7&#x26;_nc_sid=e280be&#x26;_nc_ohc=uQCNTsbeOb4Q7kNvwE-6FPf&#x26;_nc_oc=Adn70OzqwRCOY7TveR1wkTMw5EBU6VF_0s8QX2HGwOMiFcXXJow8TaIt5FtcC4AfTvw&#x26;_nc_zt=14&#x26;_nc_ht=scontent-hkg1-2.xx&#x26;_nc_gid=KewqQkxMs2vkbZVoxnONzg&#x26;oh=00_AfaHaf4UsUyZkYEmR2xEKW_XG3Rszd64CgbjgZsjBvVCTQ&#x26;oe=68E33255" alt=""><figcaption></figcaption></figure>

点击 **Create from template** 按钮，选择 **WhatsApp Embedded Signup Configuration With 60 Expiration Token** 模板来创建配置。

该模板会生成一个包含最常用权限和访问级别的配置。

![](https://scontent-hkg4-1.xx.fbcdn.net/v/t39.2365-6/517194886_4216258301935474_6660886375301368534_n.png?_nc_cat=100\&ccb=1-7&_nc_sid=e280be&_nc_ohc=fWICyCQVs6sQ7kNvwFaHNrx&_nc_oc=AdltqNr7IT27q1iAMpRxuSGNExwaaqr4B3XVfv7wmy809b5RPNvqDBXaZhXNJK5SnzU&_nc_zt=14&_nc_ht=scontent-hkg4-1.xx&_nc_gid=KewqQkxMs2vkbZVoxnONzg\&oh=00_AfZZ60ZXSbdSvbi3SW16habeixjyyUGU3vTOuOJsx45MsA\&oe=68E32FD5)

配置完成后，请记录下 **Configuration ID**，因为在下一步中会用到它。

## 步骤3：将嵌入式注册（Embedded Signup）集成到你的网站

把下面的 **HTML** 和 **JavaScript** 代码加入你的网站。这些就是实现 Embedded Signup 所需的完整代码。

我们建议根据您提供的解决方案或企业客户的需求，构建不同的嵌入式注册。它们分别用于：

* [创建WhatsApp API Account ](https://www.ycloud.com/whatsapp-business-api)
* [WhatsApp Business App 共存](https://www.ycloud.com/whatsapp-business-app-coexistence)

### 嵌入式注册 - 用于创建WhatsApp API Account&#x20;

#### 1.创建嵌入式注册按钮

```
<html>
  <head>
    <meta charset="utf-8" />
    <script>
      window.fbAsyncInit = function () {
        // JavaScript SDK configuration and setup
        FB.init({
          appId: '{YOUR-FACEBOOK-APP-ID}', // Facebook App ID
          cookie: true, // enable cookies
          xfbml: true, // parse social plugins on this page
          version: 'v22.0', //Graph API version
        })
      }

      // Load the JavaScript SDK asynchronously
      ;(function (d, s, id) {
        var js,
          fjs = d.getElementsByTagName(s)[0]
        if (d.getElementById(id)) {
          return
        }
        js = d.createElement(s)
        js.id = id
        js.setAttribute('defer', true)
        js.src = 'https://connect.facebook.net/en_US/sdk.js'
        fjs.parentNode.insertBefore(js, fjs)
      })(document, 'script', 'facebook-jssdk')

      // Facebook Login with JavaScript SDK
      function launchWhatsAppSignup() {
        // Launch Facebook login
        FB.login(
          function (response) {
            if (response.status === 'connected' && response.authResponse) {
              const code = response.authResponse.code
              console.log('User authResponse code:', code)
              // The returned code must be transmitted to your backend,
              // which will perform a server-to-server call from there to our servers for an access token
            } else {
              console.log('User cancelled login or did not fully authorize.')
            }
          },
          {
            config_id: '{YOUR-CONFIGURATION-ID}',
            response_type: 'code', // must be set to 'code' for System User access token
            override_default_response_type: true, // when true, any response types passed in the "response_type" will take precedence over the default types
            extras: {
              features: [
                {
                  name: 'marketing_messages_lite',
                },
              ],
              setup: {
                solutionID: '{YOUR-SOLUTION-ID}' // add solution ID here, ensure it is in quotes
              },
              sessionInfoVersion: '3',
            },
          },
        )
      }

      const sessionInfoListener = (event) => {
        if (event.origin == null) {
          return
        }

        // Make sure the data is coming from facebook.com
        if (!event.origin.endsWith('facebook.com')) {
          return
        }

        try {
          const data = JSON.parse(event.data)
          if (data.type === 'WA_EMBEDDED_SIGNUP') {
            // if user finishes the Embedded Signup flow
            if (data.event === 'FINISH') {
              const { phone_number_id, waba_id, businessId } = data.data
              console.log(
                'Business ID ',
                businessId,
                'Phone number ID ',
                phone_number_id,
                ' WhatsApp business account ID ',
                waba_id,
              )
            }
            // if user reports an error during the Embedded Signup flow
            else if (data.event === 'ERROR') {
              const { error_message } = data.data
              console.error('error ', error_message)
            }
            // if user cancels the Embedded Signup flow
            else {
              const { current_step } = data.data
              console.warn('Cancel at ', current_step)
            }
          }
        } catch {
          // Don’t parse info that’s not a JSON
          console.log('Non JSON Response', event.data)
        }
      }

      window.addEventListener('message', sessionInfoListener)
    </script>
  </head>

  <body>
    <button
      onclick="launchWhatsAppSignup()"
      style="
        background-color: #1877f2;
        border: 0;
        border-radius: 4px;
        color: #fff;
        cursor: pointer;
        font-family: Helvetica, Arial, sans-serif;
        font-size: 16px;
        font-weight: bold;
        height: 40px;
        padding: 0 24px;
      "
    >
      Launch Embedded Signup
    </button>
  </body>
</html>
```

{% hint style="info" %}
**注意**

* 请将上面示例代码中的 appId、config\_id、solutionID 替换为实际值
* 前端获取到 waba\_id 和 phone\_number\_id 要传给后端，用于获取 WABA 和注册号码， 详见后文。
  {% endhint %}

更多细节参考：<https://developers.facebook.com/docs/whatsapp/embedded-signup/implementation>

#### 2.绑定WABA 和注册号码

客户完成嵌入式注册后，您的前端会拿到 `waba_id` 和 `phone_number_id` ，将其传给后端用于后续接口调用。

#### 绑定 WABA <a href="#ycloud-ji-shu-ti-gong-shang-he-zuo-huo-ban-ji-cheng-zhi-nan-huo-qu-waba" id="ycloud-ji-shu-ti-gong-shang-he-zuo-huo-ban-ji-cheng-zhi-nan-huo-qu-waba"></a>

调用 YCloud WABA绑定API，然后将其与您系统的客户的账号关联在一起。

请求示例：

```
curl -X POST -H 'X-API-Key: {{YOUR_API_KEY}}' \
    'https://api.ycloud.com/v2/whatsapp/businessAccounts/{wabaId}/tp/bind'
```

成功响应示例：

```
{
    "id": "{{waba_id}}",
    "name": "WABA name",
    "accountReviewStatus": "APPROVED",
    "paymentMethodAttached": true,
    "currency": "AUD",
    "timezoneId": "1"
}
```

**注意**：响应字段 `paymentMethodAttached` 为 `true` 表明 YCloud 已成功关联支付方式给此 WABA，否则，**请联系 YCloud Team解决该问题**。

#### 注册号码 <a href="#ycloud-ji-shu-ti-gong-shang-he-zuo-huo-ban-ji-cheng-zhi-nan-zhu-ce-hao-ma" id="ycloud-ji-shu-ti-gong-shang-he-zuo-huo-ban-ji-cheng-zhi-nan-zhu-ce-hao-ma"></a>

调用 YCloud [Register a phone number](https://docs.ycloud.com/reference/whatsapp_phone_number-register) 接口注册号码，接口响应 HTTP status 200 即成功。

一般地，号码注册成功后状态会由 PENDING 转为 CONNECTED，即可使用该号码发送消息。

请求示例：

```
curl -XPOST 'https://api.ycloud.com/v2/whatsapp/phoneNumbers/{{waba_id}}/{{phone_number_id}}/register' \
-H 'X-API-Key: {{YOUR-API-KEY}}'
```

成功响应示例：

```
{
  "phoneNumber": "{{phonenumber}}",
  "wabaId": "{{waba_id}}",
  "verifiedName": "Phone number name",
  "qualityRating": "GREEN",
  "messagingLimit": "TIER_250",
  "status": "CONNECTED"
}
```

<br>

### 嵌入式注册 - WhatsApp Business App 共存 <a href="#bu-zhou-7-jiang-whatsapp-api-neng-li-ji-cheng-dao-zi-you-ying-yong-zhong" id="bu-zhou-7-jiang-whatsapp-api-neng-li-ji-cheng-dao-zi-you-ying-yong-zhong"></a>

#### 1.创建嵌入式注册按钮 <a href="#bu-zhou-7-jiang-whatsapp-api-neng-li-ji-cheng-dao-zi-you-ying-yong-zhong" id="bu-zhou-7-jiang-whatsapp-api-neng-li-ji-cheng-dao-zi-you-ying-yong-zhong"></a>

```
<html>
  <head>
    <meta charset="utf-8" />
    <script>
      window.fbAsyncInit = function () {
        FB.init({
          appId: '{YOUR-FACEBOOK-APP-ID}',
          cookie: true,
          xfbml: true,
          version: 'v22.0',
        });
      };
      (function (d, s, id) {
        var js,
          fjs = d.getElementsByTagName(s)[0];
        if (d.getElementById(id)) return;
        js = d.createElement(s);
        js.id = id;
        js.setAttribute('defer', true);
        js.src = 'https://connect.facebook.net/en_US/sdk.js';
        fjs.parentNode.insertBefore(js, fjs);
      })(document, 'script', 'facebook-jssdk');

      function launchWhatsAppSignup() {
        FB.login(
          function (response) {
            if (response.status === 'connected' && response.authResponse) {
              const code = response.authResponse.code;
              console.log('User authResponse code:', code);
            } else {
              console.log('User cancelled login or did not fully authorize.');
            }
          },
          {
            config_id: '{YOUR-CONFIGURATION-ID}',
            response_type: 'code',
            override_default_response_type: true,
            extras: {
              setup: { solutionID: '{YOUR-SOLUTION-ID}' },
              sessionInfoVersion: 3,
              featureType: 'whatsapp_business_app_onboarding',
            },
          },
        );
      }

      const sessionInfoListener = (event) => {
        if (!event.origin?.endsWith('facebook.com')) return;
        try {
          const data = JSON.parse(event.data);
          if (data.type === 'WA_EMBEDDED_SIGNUP') {
            if (data.event === 'FINISH_WHATSAPP_BUSINESS_APP_ONBOARDING' || (data.event === 'FINISH' && data.data.is_wa_login_user)) {
              const { business_id, waba_id, phone_number_id } = data.data;
              console.log('Business ID ', business_id, 'WABA ID ', waba_id, 'Phone number ID ', phone_number_id);
            } else if (data.event === 'ERROR') {
              console.error('error ', data.data.error_message);
            } else {
              console.warn('Cancel at ', data.data.current_step);
            }
          }
        } catch {
          console.log('Non JSON Response', event.data);
        }
      };

      window.addEventListener('message', sessionInfoListener);
    </script>
  </head>
  <body>
    <button
      onclick="launchWhatsAppSignup()"
      style="background-color: #1877f2; border: 0; border-radius: 4px; color: #fff; cursor: pointer; font-family: Helvetica, Arial, sans-serif; font-size: 16px; font-weight: bold; height: 40px; padding: 0 24px"
    >
      Launch Embedded Signup
    </button>
  </body>
</html>
```

#### 2.获取WABA并绑定到YCloud

客户完成嵌入式注册后，您的前端会拿到 `waba_id`  ，将其传给后端用于后续接口调用。

调用 YCloud SMB绑定API，调用成功后将其与您系统的客户的账号关联在一起。

请求示例：

```
curl 'POST /v2/whatsapp/businessAccounts/{wabaId}/smb/bind' \
-H 'X-API-Key: {{YOUR-API-KEY}}'
```

成功响应示例：

```
{
  "id": "{{phonenumber_id}}",
  "phoneNumber": "{{phonenumber}}",
  "wabaId": "{{waba_id}}",
  "qualityRating": "GREEN",
  "messagingLimit": "TIER_1K",
  "verifiedName": "John's Cake Shop",
  "codeVerificationStatus": "VERIFIED",
  "isOfficialBusinessAccount": true,
  "status": "PENDING",
  "nameStatus": "APPROVED",
  "newNameStatus": "APPROVED",
  "decision": "APPROVED",
  "requestedVerifiedName": "string",
  "rejectionReason": "string",
  "qualityUpdateEvent": "ONBOARDING"
}

```

## 常见问题

<details>

<summary>如何判断嵌入式注册配置是否正确？</summary>

您配置了 solutionID，客户在 Facebook 授权时将看到 Solution Partner 对应的真实名称，若没有，说明配置未生效。请确保完成 [App Review](#bu-zhou-8-app-review)。

![](/files/EIWiAJiQehRh9TtwVssL)

</details>

<details>

<summary>什么情况 YCloud 无法给 WABA 关联支付方式？</summary>

用户可能选择了一个原有的 WABA 而非新建的 WABA，而原有的 WABA 可能有支付方式未解除。

</details>

<details>

<summary>嵌入式注册报错 App not active</summary>

打开嵌入式注册页面提示：

*App not active*

*This app is not currently accessible and the app developer is aware of the issue. You will be able to log in when the app is reactivated.*

App 模式为 Development 时，只有测试用户拥有权限时（到 App Dashboard > App roles > Roles / Test Users 查看）才可打开。

解决方案：将 App 模式切换为 **Live**，到 [Meta Apps](https://developers.facebook.com/apps) 点击对应的 App 进入 Dashboard 进行操作；或者为当前用户授权，详见 [Assign business assets to people in your business portfolio](https://www.facebook.com/business/help/325571851329683?id=2190812977867143)。

</details>

<details>

<summary>嵌入式注册报错 Feature unavailable</summary>

打开嵌入式注册页面提示：

*Feature unavailable*

*Facebook Login is currently unavailable for this app as we are updating additional details for this app. Please try again later.*

请到 App Dashboard > App Review > Permissions and Features 申请 **public\_profile** 高级访问权限。<br>

</details>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://helpdocs.ycloud.com/partner-center/technology-development-partnern/qian-ru-shi-zhu-ce.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
