实施与上线

为了成功地将 Smile 融入您的流程,我们建议通过以下3个步骤来实现:

  • 收集需求 - 探索您的使用用例,以及您想通过 Smile 数据实现什么目标
  • 设计 - 设计您的用户流程以及与 Smile 的集成
  • 实施与上线(本指南)--设置和启动集成的详细步骤

第1步:实施 Smile Wink

如果想让用户在您的网站或应用程序上连接他们的就业账户,您需要集成 Smile Wink Widget。请看下面的配置示例:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="icon" href="smileicon32.webp" sizes="32x32">
    <link rel="icon" href="smileicon192.webp" sizes="192x192">
    <title>Smile Wink</title>
</head>

<body>
    <script src="https://web.smileapi.io/v2/smile.v2.js"></script>
    <script type="text/javascript">
        const smileLinkModal = new SmileLinkModal({
          // .....
      
            /**
             * User Token: 从你的后端服务里面获取,你的后端服务需要调用 SmileAPI /tokens 或者 /users 接口来获取。
             */
            userToken: '<usertoken>',

            /**
             * 使用模板来控制集成在你APP或者网站上的WinkWidget的页面样式与数据
             * 你可以在 Smile 的开发者控制台创建并获取 TemplateID
             * https://developer-portal.smileapi.io/link/template
             */
            templateId: "<ID of wink template >",

            /**
             * 账号创建时的回调.
             */
            onAccountCreated: ({ accountId, userId, providerId }) => {
                console.log('Account created: ', accountId, ' User ID:', userId, ' Provider ID:', providerId)
            },

            /**
             * 账号登录成功时的回调.
             */
            onAccountConnected: ({ accountId, userId, providerId }) => {
                console.log('Account connected: ', accountId, ' User ID:', userId, ' Provider ID:', providerId)
            },

            /**
             * 账号撤销链接的回调.
             */
            onAccountRemoved: ({ accountId, userId, providerId }) => {
                console.log('Account removed: ', accountId, ' User ID:', userId, ' Provider ID:', providerId)
            },

            /**
             * Token 失效时的回调
             */
            onTokenExpired: () => {
                console.log('Token expired');
            },

            /**
             * Smile 的 WinkWidget 关闭时回调。如果你想知道用户通过哪种方式关闭的 WinkWidget,你可以像下面的实例一样传递参数:
             * onClose:({reason})=>{}
             * 如果 reason == "close", 说明用户点击了右上角的关闭图标
             * 如果 reason == "close", 说明用户在尝试通过 Wink Widget 连接时发生错误后点击了 "EXIT" 按钮
             * 如果 reason == "exit", 说明用户点击了链接成功页面的 "DONE" 按钮
             */
            onClose: ({ reason }) => {
                console.log('Link closed, reason:', reason)
            },

            /**
             * 账号链接出错时的回调
             */
            onAccountError: ({ accountId, userId, providerId, errorCode }) => {
                console.log('Account error: ', accountId, ' User ID:', userId, ' Provider ID:', providerId, 'Error Code:', errorCode)
            },

            /**
             * 数据上传时的回调
             */
            onUploadsCreated: ({ uploads, userId }) => {
                console.log('Uploads: ', uploads, ' User ID:', userId);
            },

            /**
             * 撤销已上传的数据时的回调
             */
            onUploadsRemoved: ({ uploads, userId }) => {
                console.log('Uploads: ', uploads, ' User ID:', userId);
            },

            /**
             * 当页面UI发生改变时推送的事件
             * @param eventName 事件名称
             * @param eventTime 发生时间
             * @param mode 沙箱|生产环境
             * @param userId 用户ID
             * @param account Account对象
             * @param archive Archive对象
             * Uploads revoke callback.
             */
            onUIEvent: ({ eventName, eventTime, mode, userId, account, archive }) => {
                console.log('eventName:', eventName,
                    "eventTime:", eventTime,
                    "mode:", mode,
                    "userId:", userId,
                    "account:", account,
                    "archive:", archive);
            }
        });
        smileLinkModal.open()
    </script>
</body>

</html>

User tokens (Link tokens)

User tokens 是临时的(5小时后失效)访问密钥,通过它开始您与 Smile 链接的过程。

新用户的链接初始化:

  1. 通过调用 /users 端点创建一个带有源数据的新的 Smile 用户,类似于您的产品/系统中的用户标识。您将收到一个 Smile userId。我们建议您在系统中保存这个 Smile userId,以便将来参考与使用。
  2. 通过调用 /tokens endpoint ,使用 userId 来创建一个新的 user token。您将收到相应的 userToken
  3. 我们在您的 Smile Wink 初始化中提供userToken。请确保 user token 在服务器端被请求,您的 client_idclient_secret 将永远不会暴露在前端。

老用户的链接初始化或刷新 Link token

  1. 通过调用 /tokens endpoint 获得一个新的 user token,其 userId是您之前保存的。
  2. 我们在您的 Smile Wink 初始化中提供 userToken。请确保 user token 在服务器端被请求,您的 client_idclient_secret 永远不会暴露在前端。
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="icon" href="smileicon32.webp" sizes="32x32">
    <link rel="icon" href="smileicon192.webp" sizes="192x192">
    <title>Smile Wink</title>
</head>

<body>
    <script src="https://web.smileapi.io/v2/smile.v2.js"></script>
    <script type="text/javascript">
        const smileLinkModal = new SmileLinkModal({
          // .....
          
            /**
             * 来自 Smile API 的user token 是从您的后端服务进行传递的。
             */
            userToken: '<usertoken>', // Put your user token here.

            // .....
        });
        smileLinkModal.open()
    </script>
</body>

</html>

第2步: 连接测试账户并检索 identities, employment 以及 contributions 数据

如果想要使用 Sandbox,您可以使用以下示例凭证:

User NameFull NameEmailMobile PhonePasswordVerification Code
GeorgeGeorge Palomero Jr.[email protected](+63) 95599912341234561234
RyanRyan Ng[email protected](+62) 81199943216543211234
ChristinaChristina Tan[email protected](+65) 99996789YGUS11234
AnishaAnisha Bhatia[email protected](+91) 95111987651234561234

在进行下一步之前,请确保您测试过您的实施。点击提供商列表中的一个提供商,并使用其中一个 sandbox 凭证来连接所选的提供商。

我们建议在 sandbox 模式下订阅 Smile API 的 webhook payload,以检索测试帐户的个人信息、就业信息和社保缴费信息。通过 Smile API 的 Webhook payload,您可以同时从一个特定数据点或多个数据点获取不同字段。

您可以通过 Developer Portal 沙盒模式中的 Webhook 部分启用 Webhook payload,通过订阅下面列出的以下 Webhook 事件并在“Include Payload”设置中选择“True”,您可以相应地检索三个数据点的数据。

事件类型详情
TASK_FINISHED返回所选数据点的 payload。
ACCOUNT_SYNC_TASK_FINISHED返回新同步数据点的 payload。
IDENTITY_ADDED检索个人信息数据字段。
EMPLOYMENT_ADDED检索就业信息数据字段。
CONTRIBUTIONS_ADDED检索社保缴费信息数据字段。

为了验证个人信息,从 IDENTITY_ADDED 事件获取以下字段:

  • First name
  • Last name
  • Primary address

下面是一个示例响应:

{
  "id": "i-123abc456def789abc123def456abc78",
  "fullName": "George Cimafranca Palomero, Jr",
  "firstName": "George",
  "middleName": "Cimafranca",
  "lastName": "Palomero",
  "suffix": "Jr",
  "gender": "Male",
  "dob": "1970-08-24",
  "maritalStatus": "Married",
  "countryResidence": "PH",
  "citizenship": "Citizen",
  "photoUrl": "https://cdn.smileapi.io/image/avatar/v20211115191600/george.jpg",
  "referenceId": null,
  "profileUrl": null,
  "emails": [
    {
      "address": "[email protected]",
      "type": "Primary"
    }
  ],
  "phones": [
    {
      "number": "+639559991234",
      "type": "Mobile"
    }
  ],
  "socialProfiles": [
    {
      "socialUrl": "https://www.facebook.com/gpalomero1234",
      "type": "Facebook"
    }
  ],
  "addresses": [
    {
      "fullAddress": "12 Maybunga St, Barangay Paraiso, Pasig City, NCR, 1600, PH",
      "line1": "12 Maybunga St",
      "line2": "Barangay Paraiso",
      "city": "Pasig City",
      "region": "NCR",
      "zip": "1600",
      "country": "PH",
      "latitude": "14.573454",
      "longitude": "121.085042",
      "type": "Primary"
    }
  ],
  "metadata": {
    "createdAt": "2022-08-19T07:29:08Z",
    "sourceId": "a-123abc456def789abc123def456abc78",
    "sourceType": "ACCOUNT",
    "userId": "tenantId-123abc456def789abc123def456abc78",
    "providerId": "abccorp"
  }
}

为了验证就业信息,从 EMPLOYMENT_ADDED 事件获取以下字段:

  • Employer name
  • Job title
  • Start date
  • End date

下面是一个示例响应:

[{
    "id": "e-123abc456def789abc123def456abc78",
    "startDate": "2022-07-01",
    "name": "Security",
    "description": null,
    "jobTitle": "Security Guard",
    "department": null,
    "employeeNumber": "EMP-123456",
    "employer": "ABC Corporation",
    "status": "Permanent",
    "endDate": "2022-07-31",
    "metadata": {
        "createdAt": "2022-09-01T01:44:18Z",
        "sourceId": "a-123abc456def789abc123def456abc78",
        "sourceType": "ACCOUNT",
        "userId": "tenantId-123abc456def789abc123def456abc78",
        "providerId": "abccorp",
        "accountId": "a-123abc456def789abc123def456abc78"
    }
}, {
    "id": "e-123abc456def789abc123def456abc78",
    "startDate": "2022-06-01",
    "name": "Security",
    "description": null,
    "jobTitle": "Security Guard",
    "department": null,
    "employeeNumber": "CDE-98765",
    "employer": "CDE Corporation",
    "status": "Permanent",
    "endDate": "2022-06-30",
    "metadata": {
        "createdAt": "2022-09-01T01:44:18Z",
        "sourceId": "a-123abc456def789abc123def456abc78",
        "sourceType": "ACCOUNT",
        "userId": "tenantId-123abc456def789abc123def456abc78",
        "providerId": "cdecorp",
        "accountId": "a-123abc456def789abc123def456abc78"
    }
}]

为了验证社保缴费信息,从 CONTRIBUTIONS_ADDED 事件获取以下字段:

  • Employer name
  • Job title
  • Start date
  • End date

下面是一个示例响应:

[{
    "id": "con-123abc456def789abc123def456abc78",
    "date": "2022-06-30",
    "currency": "PHP",
    "amount": 2250,
    "referenceId": null,
    "metadata": {
        "createdAt": "2022-08-24T05:14:37Z",
        "sourceId": "a-123abc456def789abc123def456abc78",
        "sourceType": "ACCOUNT",
        "userId": "tenantId-123abc456def789abc123def456abc78",
        "providerId": "sss_ph",
        "accountId": "a-123abc456def789abc123def456abc78"
    }
}, {
    "id": "con-123abc456def789abc123def456abc78",
    "date": "2022-05-31",
    "currency": "PHP",
    "amount": 2250,
    "referenceId": null,
    "metadata": {
        "createdAt": "2022-08-24T05:14:37Z",
        "sourceId": "a-123abc456def789abc123def456abc78",
        "sourceType": "ACCOUNT",
        "userId": "tenantId-123abc456def789abc123def456abc78",
        "providerId": "sss_ph",
        "accountId": "a-123abc456def789abc123def456abc78"
    }
}, {
    "id": "con-123abc456def789abc123def456abc78",
    "date": "2022-04-30",
    "currency": "PHP",
    "amount": 2250,
    "referenceId": null,
    "metadata": {
        "createdAt": "2022-08-24T05:14:37Z",
        "sourceId": "a-123abc456def789abc123def456abc78",
        "sourceType": "ACCOUNT",
        "userId": "tenantId-123abc456def789abc123def456abc78",
        "providerId": "sss_ph",
        "accountId": "a-123abc456def789abc123def456abc78"
    }
}]

关于其他数据字段,请参考 Smile API reference 并通过选择各自的 Webhook 事件来订阅其他 payload。

第3步:设置 webhooks

如果想要定期收到用户的账户,identity,contribution 以及 employment 数据的更新,请订阅 webhooks

Webhooks 在每次发生事件时向您的系统发送通知,例如,当一个账户被连接、移除或更新时。

为了监控新的以及现有的账户,Smile 建议您订阅以下 webhooks:

事件事件类型详情
帐户连接成功ACCOUNT_CONNECTED当用户成功连接其工作账户时发送
帐户断线成功ACCOUNT_DISCONNECTED当用户断开或撤销其工作账户的连接时发送
帐户连接失败ACCOUNT_FAILED当账户连接失败时发送

为了监控 identity, contribution 以及 employment 数据的变化,Smile 建议通过开发者门户中的 Webhook 部分订阅以下 Webhooks 事件,然后通过在“Include Payloads”设置中选择“True”来检索相应的数据。

但请注意,Webhook Payload 仅适用于“TASK_FINISHED”和“Account_SYNC_TASK_FINISHED”的 Webhook 事件。

事件事件类型详情
任务开始TASK_STARTED当用户账户的数据同步开始时发送
任务结束TASK_FINISHED当用户账户的数据同步结束时发送,包含已被同步的数据端点

或者您可以订阅特定数据端点的相关事件

事件事件类型详情
添加了社保缴费数据CONTRIBUTIONS_ADDED当用户提供的社保缴费数据被添加时发送
添加了预估收入数据EINCOMES_ADDED当用户提供的预估收入数据被添加时发送
添加了交易数据TRANSACTIONS_ADDED当用户提供的交易数据被添加时发送
.........

第4步:上线运行并扩大规模

在 Sandbox 模式下成功实施并测试成功后,您可以切换到 Production 模式进行发布。`

更改 API Keys

API Key 可以在 Developer Portal 的 API Key 部分找到。在切换到 Production 模式时请使用 Production密钥。

循序渐进

对于您的第一个 Production 账户,您可以使用自己的账户进行测试,或者在一个自由职业者的工作平台(如 Upwork)上创建一个账户并连接。

上线运行并扩大规模

在您的个人账户测试成功后,您可以对真实用户进行测试。我们建议从一个小的用户子集开始,以确保一切正常。然后,将这个子集逐渐推进到您的全部用户群。