Skip to content

Commit

Permalink
feat(connector): add YunPian SMS connector (#6906)
Browse files Browse the repository at this point in the history
* feat(connector): add YunPian SMS connector

* chore: update README and pnpm lock

* chore: update SVG and error messages

---------

Co-authored-by: Charles Zhao <[email protected]>
  • Loading branch information
u0x01 and charIeszhao authored Dec 31, 2024
1 parent 3fa2b79 commit 3004ae9
Show file tree
Hide file tree
Showing 12 changed files with 603 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/brown-donkeys-share.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@logto/connector-yunpian-sms": minor
---

add YunPian SMS connector
1 change: 0 additions & 1 deletion packages/connectors/connector-xiaomi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
"build": "tsup",
"dev": "tsup --watch",
"lint": "eslint --ext .ts src",
"lint:fix": "eslint --ext .ts src --fix",
"lint:report": "pnpm lint --format json --output-file report.json",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
Expand Down
60 changes: 60 additions & 0 deletions packages/connectors/connector-yunpian-sms/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Yunpian SMS connector

The official Logto connector for Yunpian SMS service. [中文文档](https://github.com/logto-io/logto/tree/master/packages/connectors/connector-yunpian-sms/README.zh-CN.md)

**Table of contents**

- [Yunpian SMS connector](#yunpian-sms-connector)
- [Get started](#get-started)
- [Set up SMS service in Yunpian Console](#set-up-sms-service-in-yunpian-console)
- [Create a Yunpian account](#create-a-yunpian-account)
- [Get API KEY](#get-api-key)
- [Configure SMS templates](#configure-sms-templates)
- [Configure in Logto](#configure-in-logto)
- [Notes](#notes)
- [References](#references)

## Get started

Yunpian is a communication service provider offering various services including SMS. The Yunpian SMS Connector is a plugin provided by the Logto team to integrate with Yunpian's SMS service, enabling Logto end-users to register and sign in via SMS verification codes.

## Set up SMS service in Yunpian Console

### Create a Yunpian account

Visit [Yunpian's website](https://www.yunpian.com/) to register an account and complete real-name verification.

### Get API KEY

1. Log in to Yunpian Console
2. Go to "Account Settings" -> "Sub-account Management"
3. Find and copy the API KEY

### Configure SMS templates

1. In Yunpian Console, go to "Domestic SMS" -> "Signature Filing"
2. Create and submit a signature, wait for carrier approval
3. Go to "Domestic SMS" -> "Template Filing" and select "Verification Code"
4. Create a verification code template, ensure it includes the `#code#` variable (you can also use "Common Templates" to speed up the approval process)
5. Wait for template approval
6. If you need to send international SMS, repeat the above steps but select "International SMS" -> "Template Filing"

## Configure in Logto

1. In Logto Console, go to "Connectors"
2. Find and click "Yunpian SMS Service"
3. Fill in the configuration form:
- API KEY: The API KEY obtained from Yunpian
- SMS templates: Configure templates according to usage, ensure they match exactly with approved templates in Yunpian

## Notes

1. SMS template content must match exactly with the approved template in Yunpian
2. The verification code variable placeholder in Yunpian templates is `#code#`, while in the connector configuration it's `{{code}}`
3. Yunpian automatically adds the default signature based on API KEY, no need to include signature in the template content
4. It's recommended to test the configuration before formal use

## References

- [Yunpian Development Documentation](https://www.yunpian.com/official/document/sms/zh_CN/introduction_brief)
- [Logto SMS Connector Guide](https://docs.logto.io/docs/recipes/configure-connectors/sms-connector/)
60 changes: 60 additions & 0 deletions packages/connectors/connector-yunpian-sms/README.zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# 云片网短信连接器

云片网短信服务 Logto 官方连接器

**目录**

- [云片网短信连接器](#云片网短信连接器)
- [开始使用](#开始使用)
- [在云片网中配置](#在云片网中配置)
- [创建云片网账号](#创建云片网账号)
- [获取 API KEY](#获取-api-key)
- [配置短信模板](#配置短信模板)
- [在 Logto 中配置](#在-logto-中配置)
- [注意事项](#注意事项)
- [参考](#参考)

## 开始使用

云片网是一家通信服务提供商,提供包括短信在内的多种通信服务。云片网 SMS 连接器是由 Logto 团队提供的插件,用于调用云片网的短信服务,帮助 Logto 终端用户通过短信验证码进行注册和登录。

## 在云片网中配置

### 创建云片网账号

访问[云片网官网](https://www.yunpian.com/),注册账号并完成实名认证。

### 获取 API KEY

1. 登录云片网控制台
2. 进入"账户设置" -> "子账户管理"
3. 找到并复制 API KEY

### 配置短信模板

1. 在云片网控制台中进入"国内短信" -> "签名报备"
2. 创建签名并提交,等待运营商审核通过
3. 在云片网控制台中进入"国内短信" -> "模板报备",选择"验证码类"
4. 创建验证码类短信模板,确保模板中包含 `#code#` 变量(也可以直接使用`常用模板`申请,加快审核速度)
5. 等待模板审核通过
6. 如果您需要发送国际短信,请重复上述步骤,选择"国际短信" -> "模板报备"并提交

## 在 Logto 中配置

1. 在 Logto 管理控制台中转到"连接器"
2. 找到并点击"云片短信服务"
3. 在配置表单中填入:
- API KEY: 从云片网获取的 API KEY
- 短信模板: 按照用途配置相应的模板内容,确保与云片网审核通过的模板内容一致

## 注意事项

1. 短信模板内容必须与云片网审核通过的模板完全一致
2. 短信审核模板中的验证码变量占位符为 `#code#`,模板配置中验证码变量占位符为 `{{code}}`
3. 云片网会自动根据 API KEY 添加默认签名,无需在发送模板内容中包含签名
4. 建议在正式使用前进行测试,确保配置正确

## 参考

- [云片网开发文档](https://www.yunpian.com/official/document/sms/zh_CN/introduction_brief)
- [Logto SMS 连接器指南](https://docs.logto.io/zh-CN/connectors/sms-connectors)
13 changes: 13 additions & 0 deletions packages/connectors/connector-yunpian-sms/logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
68 changes: 68 additions & 0 deletions packages/connectors/connector-yunpian-sms/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{
"name": "@logto/connector-yunpian-sms",
"version": "1.0.0",
"description": "云片网 SMS connector implementation.",
"author": "Silverhand Inc. <[email protected]>",
"dependencies": {
"@logto/connector-kit": "workspace:^4.0.0",
"@silverhand/essentials": "^2.9.1",
"got": "^14.0.0",
"zod": "^3.23.8"
},
"main": "./lib/index.js",
"module": "./lib/index.js",
"exports": "./lib/index.js",
"license": "MPL-2.0",
"type": "module",
"files": [
"lib",
"docs",
"logo.svg",
"logo-dark.svg"
],
"scripts": {
"precommit": "lint-staged",
"check": "tsc --noEmit",
"build": "tsup",
"dev": "tsup --watch",
"lint": "eslint --ext .ts src",
"lint:report": "pnpm lint --format json --output-file report.json",
"test": "vitest src",
"test:ci": "pnpm run test --silent --coverage",
"prepublishOnly": "pnpm build"
},
"engines": {
"node": "^20.9.0"
},
"eslintConfig": {
"extends": "@silverhand",
"settings": {
"import/core-modules": [
"@silverhand/essentials",
"got",
"nock",
"snakecase-keys",
"zod"
]
}
},
"prettier": "@silverhand/eslint-config/.prettierrc",
"publishConfig": {
"access": "public"
},
"devDependencies": {
"@silverhand/eslint-config": "6.0.1",
"@silverhand/ts-config": "6.0.0",
"@types/node": "^20.11.20",
"@types/supertest": "^6.0.2",
"@vitest/coverage-v8": "^2.1.8",
"eslint": "^8.56.0",
"lint-staged": "^15.0.2",
"nock": "^13.3.1",
"prettier": "^3.0.0",
"supertest": "^7.0.0",
"tsup": "^8.3.0",
"typescript": "^5.5.3",
"vitest": "^2.1.8"
}
}
72 changes: 72 additions & 0 deletions packages/connectors/connector-yunpian-sms/src/constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import type { ConnectorMetadata } from '@logto/connector-kit';
import { ConnectorConfigFormItemType } from '@logto/connector-kit';

export const endpoint = 'https://sms.yunpian.com/v2/sms/single_send.json';

export const defaultMetadata: ConnectorMetadata = {
id: 'yunpian-sms',
target: 'yunpian-sms',
platform: null,
name: {
en: 'YunPian SMS Service',
zh: '云片短信服务',
},
logo: './logo.svg',
logoDark: null,
description: {
en: 'YunPian is a SMS service provider.',
zh: '云片网是一家短信服务提供商。',
},
readme: './README.md',
formItems: [
{
key: 'apikey',
label: 'API Key',
type: ConnectorConfigFormItemType.Text,
required: true,
placeholder: '<api-key>',
},
{
key: 'templates',
label: 'SMS Template',
type: ConnectorConfigFormItemType.Json,
required: true,
defaultValue: [
{
usageType: 'SignIn',
content: '您的验证码是 {{code}}。如非本人操作,请忽略本短信',
},
{
usageType: 'Register',
content: '您的验证码是 {{code}}。如非本人操作,请忽略本短信',
},
{
usageType: 'ForgotPassword',
content: '您的验证码是 {{code}}。如非本人操作,请忽略本短信',
},
{
usageType: 'Generic',
content: '您的验证码是 {{code}}。如非本人操作,请忽略本短信',
},
],
},
{
key: 'enableInternational',
label: 'Enable International SMS',
description:
'* To enable it, you need to apply for international templates at the same time.',
type: ConnectorConfigFormItemType.Switch,
required: false,
defaultValue: false,
},
{
key: 'unsupportedCountriesMsg',
label: 'Unsupported Countries Error Message',
description:
'The message to be displayed when the phone number is not supported. If left empty, no error will be returned.',
type: ConnectorConfigFormItemType.Text,
required: false,
defaultValue: 'The administrator has not enabled international SMS services.',
},
],
};
54 changes: 54 additions & 0 deletions packages/connectors/connector-yunpian-sms/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import nock from 'nock';

import { TemplateType } from '@logto/connector-kit';

import { endpoint } from './constant.js';
import createConnector from './index.js';
import { mockedConfig } from './mock.js';

const getConfig = vi.fn().mockResolvedValue(mockedConfig);

describe('yunpian SMS connector', () => {
it('init without throwing errors', async () => {
await expect(createConnector({ getConfig })).resolves.not.toThrow();
});

describe('sendMessage()', async () => {
const connector = await createConnector({ getConfig });
const { sendMessage } = connector;

beforeAll(() => {
nock.disableNetConnect();
});

afterAll(() => {
nock.enableNetConnect();
});

afterEach(() => {
nock.cleanAll();
});

it('should send message successfully', async () => {
const mockResponse = {
code: 0,
msg: '发送成功',
count: 1,
fee: 0.05,
unit: 'RMB',
mobile: '13800138000',
sid: 3_310_228_982,
};

nock(endpoint).post('').reply(200, mockResponse);

await expect(
sendMessage({
to: '13800138000',
type: TemplateType.Generic,
payload: { code: '1234' },
})
).resolves.not.toThrow();
});
});
});
Loading

0 comments on commit 3004ae9

Please sign in to comment.