diff --git a/docs/tutorial/build/publish-mp-weixin-cli.md b/docs/tutorial/build/publish-mp-weixin-cli.md index 8a5c637e96b821df23ab0421427d827d2a01a696..ccd748addcf79425e9858249f0d490e2e108362f 100644 --- a/docs/tutorial/build/publish-mp-weixin-cli.md +++ b/docs/tutorial/build/publish-mp-weixin-cli.md @@ -2,7 +2,7 @@ > HBuilderX 3.3.7+, uni-app 发行到微信小程序,支持自动上传代码到微信平台,无需再打开微信开发者工具上传发行 -![](https://hx.dcloud.net.cn/static/snapshots/cli/wechat-upload.png) + 通过微信小程序CI,使用上传密钥上传代码,无需打开微信开发者工具,一键完成微信小程序代码的上传、预览等操作。 @@ -10,4 +10,5 @@ - 自动上传到微信平台,依赖CI插件,如弹窗提示要求安装CI插件,请点击确认安装; - 自动上传到微信平台,需要配置`上传密钥`,并正确填写`微信小程序appid`和`privatekey`; -- 自动上传到微信平台,如果开启了`IP白名单`,请确保微信平台已正确配置 `IP白名单`。 \ No newline at end of file +- 自动上传到微信平台,如果开启了`IP白名单`,请确保微信平台已正确配置 `IP白名单`。 +- 关于微信ci机器人编号,仅支持HBuilderX 3.6.16+ \ No newline at end of file diff --git a/docs/uniCloud/aliyun-migrate-business.md b/docs/uniCloud/aliyun-migrate-business.md index 3bef200a3582f7268fd1144270fd6bb3e1051d62..1e69ac28ecf76c6f8d32e1ee0adddaf2fcd4f80a 100644 --- a/docs/uniCloud/aliyun-migrate-business.md +++ b/docs/uniCloud/aliyun-migrate-business.md @@ -156,3 +156,44 @@ url化访问时不管是默认域名还是自定义域名均和上述转发逻 ![](https://f184e7c3-1912-41b2-b81f-435d1b37c7b4.cdn.bspapp.com/VKCEYUGU-f184e7c3-1912-41b2-b81f-435d1b37c7b4/5fa6249a-2900-40aa-b4b8-16f37d2307a1.png) 需要开发者在[uniCloud控制台](https://unicloud.dcloud.net.cn)将自定义域名删除后重新绑定,通过该操作获取到新的CNAME后,将域名解析更换到新的CNAME以完成域名迁移。 这个期间前端网页托管自定义域名访问会中断,建议在访问量较低的时候处理。 + + +## 迁移后uniCloud相关业务消耗资源费用变更情况 + +### 短信及一键登录资源消耗评估@sms-unilogin-fee + +`短信`和`一键登录`业务涉及费用的部分主要是云函数/云对象的使用量、调用次数、和出网流量(如:使用`uni-id-co`或自定义的云函数/云对象来发送短信)。 +接下来,我们对不同资源,分别进行费用评估。 + +我们按照[uniCloud官网](https://uniapp.dcloud.net.cn/uniCloud/price.html#aliyun-postpay)列出的按量计费规则,计算一下云函数的资源消耗。 + +![](https://mp-8ca8132b-2139-4831-aff2-582d4c8385da.cdn.bspapp.com/cloudstorage/8492ba8e-f4c6-45de-abf2-f9d6825ceefb.png) + +我们可以简单得出如下公式: + +`云函数/云对象费用 = 资源使用量 * 0.000110592 + 调用次数 * 0.0133 / 10000 + 出网流量 * 0.8` + +其中: +- 资源使用量 = 云函数内存(单位为G) * 云函数平均单次执行时长(单位为秒) * 调用次数 +- 调用次数 = 发送短信条数(一般情况下发送条数 = 调用次数,特殊情况除外)+ 一键登录调用次数(如果只使用其中某一项业务,则可设另一项业务调用次数为0) + + +我们假设如下数据模型: + +- 云函数内存:512M,即0.5G (云函数内存默认为512M,用户可以自定义设置,最低可设置为128M) +- 云函数平均单次执行时长:200毫秒,即0.2秒 +- 短信和一键登录业务平均每日调用次数:10000次 +- 出网流量:单次请求 2 KB + +按照如上公式,其`短信`业务云函数每天的费用为: + +``` +云函数费用(天) = 资源使用量 * 0.000110592 + 调用次数 * 0.0133 / 10000 + 出网流量 * 0.8 + = 云函数内存(单位为G) * 云函数平均单次执行时长(单位为秒) * 调用次数 + 调用次数 * 0.0133 / 10000 + 出网流量 * 0.8 + = 0.5G * 0.2S * 10000 * 0.000110592 + 10000 * 0.0133/10000 + 10000 * 2 * 0.8 / 1024 * 1024 + = 0.110592 + 0.0133 + 0.0152587890625 + = 0.1391507890625(元) + ≈ 0.139(元) +``` + +即:如果你的`短信`和`一键登录`业务平均每天发送条数为10000条,使用阿里云正式版云服务空间后,对应云函数每天大概消耗0.139元,对比之前的短信和一键登录费用,平均每次调用多花0.0000139元,几乎可忽略不计。 \ No newline at end of file diff --git a/docs/uniCloud/cf-database-aggregate-operator.md b/docs/uniCloud/cf-database-aggregate-operator.md index 49d75e42f35442dfda4f1fea01bb20f4c0657ee2..35bc5d9b820c3323d37bddeda69f01abe8453087 100644 --- a/docs/uniCloud/cf-database-aggregate-operator.md +++ b/docs/uniCloud/cf-database-aggregate-operator.md @@ -315,32 +315,41 @@ let res = await db.collection('sales').aggregate() #### API 说明 - 语法如下: - +语法如下: + ```js db.command.aggregate.ln() ``` `` 可以是任意解析为非负数字的表达式。 - `ln` 等价于 `log([, Math.E])`,其中 `Math.E` 是 `JavaScript` 获取 `e` 的值的方法。 +`ln` 等价于 `log([, Math.E])`,其中 `Math.E` 是 `JavaScript` 获取 `e` 的值的方法。 #### 示例代码 - -#### db.command.aggregate.ln - -计算给定数字在自然对数值。 - -语法如下: - +假设集合 curve 有如下记录: ```js -db.command.aggregate.ln() +{ _id: 1, x: 1 } +{ _id: 2, x: 2 } +{ _id: 3, x: 3 } +``` +计算 ln(x) 的值: +```js +const $ = db.command.aggregate +let res = await db.collection('curve').aggregate() + .project({ + log: $.ln('$x') + }) + .end() +``` +返回结果如下: +```js +{ _id: 1, ln: 0 } +{ _id: 2, ln: 0.6931471805599453 } +{ _id: 3, ln: 1.0986122886681098 } ``` -`` 可以是任意解析为非负数字的表达式。 - `ln` 等价于 `log([, Math.E])`,其中 `Math.E` 是 `JavaScript` 获取 `e` 的值的方法。 ### log diff --git a/docs/uniCloud/cf-database-dbcmd.md b/docs/uniCloud/cf-database-dbcmd.md index cccad2deec831ae94e44867cda8c0e051af886cc..1e33aed950c4b7ed307fefbca83fca755b5f5176 100644 --- a/docs/uniCloud/cf-database-dbcmd.md +++ b/docs/uniCloud/cf-database-dbcmd.md @@ -98,8 +98,8 @@ function and(...expressions: Expression[]): Command ```js -let res = await const dbCmd = db.command -db.collection('todo').where({ +const dbCmd = db.command +let res = await db.collection('todo').where({ progress: dbCmd.gt(80).or(dbCmd.lt(20)) }).get() ``` diff --git a/docs/uniCloud/price.md b/docs/uniCloud/price.md index a7f457be2627a6723fb9c7a3fde695814c8f57b8..975e41a4020de36dead7b5f48a0b8bfc3b2abde7 100644 --- a/docs/uniCloud/price.md +++ b/docs/uniCloud/price.md @@ -40,7 +40,7 @@ uniCloud提供包月、按量计费两种计费方式,具体说明如下: **免费额度注意事项:** - 单个账号只能创建一个阿里云免费服务空间 -- 阿里云免费服务空间有效期默认一个月,到期时需主动续费(续费时依旧免费),否则将会被停服释放 +- 阿里云免费服务空间有效期默认一个月,到期时需主动续费(到期前15天可续费,续费时依旧免费),否则将会被停服释放 - 免费版如需升配,只能针对剩余有效期进行操作,无法自定义升配时间 - 免费版可以转换为按量计费 - 免费版升配或转为按量计费后,免费额度会释放,此时仍可再创建一个免费版 diff --git a/docs/uniCloud/redis.md b/docs/uniCloud/redis.md index 558758657d2eb7f333fda42244b2dba85258c792..3c5b85cdd680b431bccccb25239854a319614f58 100644 --- a/docs/uniCloud/redis.md +++ b/docs/uniCloud/redis.md @@ -2166,7 +2166,7 @@ member 移除成功返回 1,member 不是 source 集合成员,并且没有 **示例** ```js -await redis.sadd('key', 'a', 'b', 'c') +await redis.sadd('source', 'a', 'b', 'c') await redis.smove('source', 'destination', 'a') // 返回 1 ``` diff --git a/docs/uniCloud/send-sms.md b/docs/uniCloud/send-sms.md index 4b26bbaee8d9f0a74b6c6455a0b576dc1f72b9df..4bc527f04d8e1e36c0ab5e0b3280a95346cc884d 100644 --- a/docs/uniCloud/send-sms.md +++ b/docs/uniCloud/send-sms.md @@ -1,231 +1,242 @@ -## 发送短信 - - - -> 自`HBuilderX 3.3.0`起,本接口支持传入phoneList参数批量发送短信,其他参数均于发送单条短信相同 - -> 自`HBuilderX 3.4.0`起云函数需启用uni-cloud-sms之后才可以调用sendSms接口,详细说明见:[云函数使用短信扩展库](#extension) - -自HBuilderX 2.8.1起,uniCloud内置了短信发送API。给开发者提供更方便、更便宜的短信发送能力。 - -该服务类似小程序的模板消息,在一个固定模板格式的文字里自定义某些字段,而不是所有文字都可以随便写。 - -使用本功能需要在[DCloud开发者中心](https://dev.dcloud.net.cn/pages/sms/base)开通并充值,教程参考[短信服务开通指南](https://ask.dcloud.net.cn/article/37534) - -因涉及费用,为保障安全,本能力应该在云函数中调用,而不是在前端调用。 - -云函数API名称:`uniCloud.sendSms` - -**参数说明** - -参数结构体为json格式。 - -|参数名 |类型 |必填 |说明 | -|:-: |:-: |:-: |:-: | -|appid |String |是 |DCloud appid,可以在项目manifest.json内看到 | -|smsKey |String |是 |调用短信接口的密钥key,从 dev.dcloud.net.cn/uniSms 后台获取 | -|smsSecret |String |是 |调用短信接口的密钥secret,从 dev.dcloud.net.cn/uniSms 后台获取 | -|phone |String |和phoneList二选一|发送目标手机号,暂仅支持中国大陆手机号 | -|phoneList |Array |和phone二选一 |发送目标手机号,暂仅支持中国大陆手机号,最多50个手机号码,`HBuilderX 3.3.0`起支持 | -|templateId |String |是 |模版Id,短信内容为固定模板,详见下方说明(应用开发阶段,可以使用 DCloud 提供的测试模板) | -|data |Object |是 |模版里的各个变量字段,json格式 | - - -**注意** - -- 如果使用uni-id发送短信,无需自行开发,请参考[uni-id-pages](uni-id-pages.md) - -#### 云函数使用短信扩展库@extension - -自HBuilderX 3.4.0起,短信相关功能移至扩展库`uni-cloud-sms`内。在一段时间内无论开发者是否使用扩展库云函数都可以正常使用`uniCloud.sendSms`。HBuilderX 3.4.0及之后的版本上传云函数时如果没有指定使用`uni-cloud-sms`扩展库的云函数将无法调用uniCloud.sendSms接口。 - -关于扩展库的说明见:[云函数扩展库](cf-functions.md#extension) - -在云函数的package.json内添加`uni-cloud-sms`的引用即可为云函数启用此扩展,无需做其他调整,完整的package.json示例如下: - -```js -{ - "name": "uni-sms", - "extensions": { - "uni-cloud-sms": {} // 启用短信扩展,值为空对象即可 - } -} -``` - -#### 参数templateId说明@smstemplate - -按照国家法律和运营商要求,每个要发送短信的应用,需要备案其短信模板,并且经过运营商的审核。通过审核的模板,会得到一个templateId。 - -短信内容规范: -1. 不能包含涉政、黄赌毒、暴力、房产、移民、贷款、代开发票等违法内容 -2. 不能包含运营商禁止发送的内容 -3. 不能包含侵犯第三方权益的内容(如侵犯他人商标或冒名行为) -4. 营销类短信不能违反广告法 -5. 不能利用短信骚扰或诈骗用户 - -报备模板的方式: - -1. 如果尚未添加签名,请在在开发者中心-[签名配置](https://dev.dcloud.net.cn/pages/sms/sign)内添加签名 -2. 在开发者中心-[模板配置](https://dev.dcloud.net.cn/pages/sms/template)内申请自定义模板 - -- 短信签名: -即短信内容开头的【xxx】,可选内容为App或小程序名称、网站名称、企业名称(可使用简称,但需具备辨识度)、商标名称。如`【DCloud】`,即是DCloud官方发送短信的签名。签名的作用是明确告知用户该短信由什么样的主体发送。签名内容只允许包含中文、英文、数字,签名的长度限制为2-8位。 - -- 模板内容: -短信模板必然以短信签名作为开头,其内容中允许有一定的变量,以满足灵活性需求。变量用${}包裹。 - -例如:【hello uni-app】验证码:${code},${expMinute}分钟内有效,请勿泄露并尽快验证。 - -在实际发送短信时,在短信API中传入该模板ID,然后传入合适的变量,最终发送的短信将变为: -`【hello uni-app】验证码:123465,用于注册,15分钟内有效,请勿泄露并尽快验证。` - -- 短信类别: -分为3类,即验证码类短信、通知类短信、营销类短信。验证码类短信,其模板审核简单快速,只能单次发送。 - -**短信测试模板说明** - -运营商目前审核比较严格,处于开发阶段的应用可能无法通过运营商的审核。为方便开发者测试短信功能,DCloud 提供了一个测试模板,该模板的templateId为:uni_sms_test,内容为:`【统一应用软件】尊敬的用户,您的验证码是:${code}。5分钟内有效,请尽快验证。请勿泄漏您的验证码。` - -使用该模板的限制: - -1. 每日最多给10个手机号发送不超过100条短信; -2. 使用该模板也会正常收取费用,请保证账户有充足余额。 - - -**返回值** - -接口调用失败时会直接抛出错误,调用成功时才会有返回值。 - -注意接口调用成功不代表短信发送成功,比如目标手机关机会导致短信发送失败。真实的短信发送成功与否请在[https://dev.dcloud.net.cn/pages/sms/base](https://dev.dcloud.net.cn/pages/sms/base)后台查看报表。 - -|参数名 |类型 |说明 | -|:-: |:-: |:-: | -|errCode|Number|成功返回0,调用失败错误码见下表 | -|errMsg|String|错误描述,调用失败时返回 | - -**错误码说明** - -|错误码 |错误 | -|:-: |:-: | -|1001 |参数校验未通过,errMsg内会给出详细信息| -|4000 |参数错误 | -|4001 |apiKey 不存在 或 templateId 不正确 | -|4002 |请检查smsKey、smsSecret是否有误 | -|4003 |服务空间或IP地址不在白名单中 | -|5000 |服务错误,请联系DCloud进行排查 | -|5001 |服务器异常,请重试! | - -**调用示例** - -```js -// 发送单条短信示例 -'use strict'; -exports.main = async (event, context) => { - try { - const res = await uniCloud.sendSms({ - appid: '__UNI__xxxxxxx', - smsKey: '****************', - smsSecret: '****************', - phone: '188********', - templateId: '100**', // 请替换为自己申请的模板id - data: { - name: 'DCloud', - code: '123456', - expMinute: '3', - } - }) - // 调用成功,请注意这时不代表发送成功 - return res - } catch(err) { - // 调用失败 - console.log(err.errCode) - console.log(err.errMsg) - return { - code: err.errCode, - msg: err.errMsg - } - } -}; - -// 批量发送短信示例 -'use strict'; -exports.main = async (event, context) => { - try { - const res = await uniCloud.sendSms({ - appid: '__UNI__xxxxxxx', - smsKey: '****************', - smsSecret: '****************', - phoneList: ['188********', '138********'], - templateId: '100**', // 请替换为自己申请的模板id - data: { - name: 'DCloud', - code: '123456', - expMinute: '3', - } - }) - // 调用成功,请注意这时不代表发送成功 - return res - } catch(err) { - // 调用失败 - console.log(err.errCode) - console.log(err.errMsg) - return { - code: err.errCode, - msg: err.errMsg - } - } -}; -``` - -本示例使用的模板为: -``` -【uniID】“${name}”验证码:${code},${expMinute}分钟内有效,请勿泄露并尽快验证。 -``` - -本示例发送的短信,在手机上将显示为: -``` -【uniID】“DCloud”验证码:123456,3分钟内有效,请勿泄露并尽快验证。 -``` - -### 发送失败注意@fail - -- data内如果有`测试`、`test`等字样,系统可能会被判定为测试用途,不会真正把短信下发到对应手机(此行为由运营商控制,可能真实发送,也可能不发送) -- 短信内容不可包含★、 ※、 →、 ●等特殊符号,可能会导致短信乱码 -- 如果本地运行提示`不支持的模板ID`,请更新到`2.9.9+`版本的HBuilderX -- 使用同一短信模板给同一个手机号发送短信时,频率不能太高。如果1分钟内超过1次,会被运营商判定为骚扰或短信重发而被拦截,导致短信发送失败 -- 尽量使用企业实名认证,个人实名认证的审核更严格,更容易发送失败 - - -**其他注意事项** - -- 在[DCloud开发者中心](https://dev.dcloud.net.cn/pages/sms/base)绑定`uniCloud`服务空间后,将会只允许绑定的服务空间调用此接口,绑定列表为空时表示不限制服务空间 -- 如果是用于用户注册的短信验证码,那么强烈推荐使用uni-id,这是一套云端一体的、完善的用户管理方案,已经内置封装好的短信验证码功能,详见:[uni-id-pages](uni-id-pages.md)。 -- 发送短信前,如果需要图形验证码来防止机刷,可以使用[uni-captcha图形验证码](https://ext.dcloud.net.cn/plugin?id=4048)。在[uni-id-pages](uni-id-pages.md)模板中已经集成了uni-id、uni-captcha -- Android手机在App端获取短信验证码,参考:[https://ask.dcloud.net.cn/article/676](https://ask.dcloud.net.cn/article/676) -- 短信内容超过70个字符时为长短信,需分条发送,每67个字按一条短信计算 - -更多问题:欢迎加入DCloud短信技术交流群 -咨询 - - +## 发送短信 + + + +> 自`HBuilderX 3.3.0`起,本接口支持传入phoneList参数批量发送短信,其他参数均于发送单条短信相同 + +> 自`HBuilderX 3.4.0`起云函数需启用uni-cloud-sms之后才可以调用sendSms接口,详细说明见:[云函数使用短信扩展库](#extension) + +自HBuilderX 2.8.1起,uniCloud内置了短信发送API。给开发者提供更方便、更便宜的短信发送能力。 + +该服务类似小程序的模板消息,在一个固定模板格式的文字里自定义某些字段,而不是所有文字都可以随便写。 + +使用本功能需要在[DCloud开发者中心](https://dev.dcloud.net.cn/pages/sms/base)开通并充值,教程参考[短信服务开通指南](https://ask.dcloud.net.cn/article/37534) + +因涉及费用,为保障安全,本能力应该在云函数中调用,而不是在前端调用。 + +云函数API名称:`uniCloud.sendSms` + +**参数说明** + +参数结构体为json格式。 + +|参数名 |类型 |必填 |说明 | +|:-: |:-: |:-: |:-: | +|appid |String |是 |DCloud appid,可以在项目manifest.json内看到 | +|smsKey |String |是 |调用短信接口的密钥key,从 dev.dcloud.net.cn/uniSms 后台获取 | +|smsSecret |String |是 |调用短信接口的密钥secret,从 dev.dcloud.net.cn/uniSms 后台获取 | +|phone |String |和phoneList二选一|发送目标手机号,暂仅支持中国大陆手机号 | +|phoneList |Array |和phone二选一 |发送目标手机号,暂仅支持中国大陆手机号,最多50个手机号码,`HBuilderX 3.3.0`起支持 | +|templateId |String |是 |模版Id,短信内容为固定模板,详见下方说明(应用开发阶段,可以使用 DCloud 提供的测试模板) | +|data |Object |是 |模版里的各个变量字段,json格式 | + + +**注意** + +- 如果使用uni-id发送短信,无需自行开发,请参考[uni-id-pages](uni-id-pages.md) + +#### 云函数使用短信扩展库@extension + +自HBuilderX 3.4.0起,短信相关功能移至扩展库`uni-cloud-sms`内。在一段时间内无论开发者是否使用扩展库云函数都可以正常使用`uniCloud.sendSms`。HBuilderX 3.4.0及之后的版本上传云函数时如果没有指定使用`uni-cloud-sms`扩展库的云函数将无法调用uniCloud.sendSms接口。 + +关于扩展库的说明见:[云函数扩展库](cf-functions.md#extension) + +在云函数的package.json内添加`uni-cloud-sms`的引用即可为云函数启用此扩展,无需做其他调整,完整的package.json示例如下: + +```js +{ + "name": "uni-sms", + "extensions": { + "uni-cloud-sms": {} // 启用短信扩展,值为空对象即可 + } +} +``` + +#### 参数templateId说明@smstemplate + +按照国家法律和运营商要求,每个要发送短信的应用,需要备案其短信模板,并且经过运营商的审核。通过审核的模板,会得到一个templateId。 + +短信内容规范: +1. 不能包含涉政、黄赌毒、暴力、房产、移民、贷款、代开发票等违法内容 +2. 不能包含运营商禁止发送的内容 +3. 不能包含侵犯第三方权益的内容(如侵犯他人商标或冒名行为) +4. 营销类短信不能违反广告法 +5. 不能利用短信骚扰或诈骗用户 + +报备模板的方式: + +1. 如果尚未添加签名,请在在开发者中心-[签名配置](https://dev.dcloud.net.cn/pages/sms/sign)内添加签名 +2. 在开发者中心-[模板配置](https://dev.dcloud.net.cn/pages/sms/template)内申请自定义模板 + +- 短信签名: +即短信内容开头的【xxx】,可选内容为App或小程序名称、网站名称、企业名称(可使用简称,但需具备辨识度)、商标名称。如`【DCloud】`,即是DCloud官方发送短信的签名。签名的作用是明确告知用户该短信由什么样的主体发送。签名内容只允许包含中文、英文、数字,签名的长度限制为2-8位。 + +- 模板内容: +短信模板必然以短信签名作为开头,其内容中允许有一定的变量,以满足灵活性需求。变量用${}包裹。 + +例如:【hello uni-app】验证码:${code},${expMinute}分钟内有效,请勿泄露并尽快验证。 + +在实际发送短信时,在短信API中传入该模板ID,然后传入合适的变量,最终发送的短信将变为: +`【hello uni-app】验证码:123465,用于注册,15分钟内有效,请勿泄露并尽快验证。` + +- 短信类别: +分为3类,即验证码类短信、通知类短信、营销类短信。验证码类短信,其模板审核简单快速,只能单次发送。 + +**短信测试模板说明** + +运营商目前审核比较严格,处于开发阶段的应用可能无法通过运营商的审核。为方便开发者测试短信功能,DCloud 提供了一个测试模板,该模板的templateId为:uni_sms_test,内容为:`【统一应用软件】尊敬的用户,您的验证码是:${code}。5分钟内有效,请尽快验证。请勿泄漏您的验证码。` + +使用该模板的限制: + +1. 每日最多给10个手机号发送不超过100条短信; +2. 使用该模板也会正常收取费用,请保证账户有充足余额。 + + +**返回值** + +接口调用失败时会直接抛出错误,调用成功时才会有返回值。 + +注意接口调用成功不代表短信发送成功,比如目标手机关机会导致短信发送失败。真实的短信发送成功与否请在[https://dev.dcloud.net.cn/pages/sms/base](https://dev.dcloud.net.cn/pages/sms/base)后台查看报表。 + +|参数名 |类型 |说明 | +|:-: |:-: |:-: | +|errCode|Number|成功返回0,调用失败错误码见下表 | +|errMsg|String|错误描述,调用失败时返回 | + +**错误码说明** + +|错误码 |错误 | +|:-: |:-: | +|1001 |参数校验未通过,errMsg内会给出详细信息| +|4000 |参数错误 | +|4001 |apiKey 不存在 或 templateId 不正确 | +|4002 |请检查smsKey、smsSecret是否有误 | +|4003 |服务空间或IP地址不在白名单中 | +|5000 |服务错误,请联系DCloud进行排查 | +|5001 |服务器异常,请重试! | + +**调用示例** + +```js +// 发送单条短信示例 +'use strict'; +exports.main = async (event, context) => { + try { + const res = await uniCloud.sendSms({ + appid: '__UNI__xxxxxxx', + smsKey: '****************', + smsSecret: '****************', + phone: '188********', + templateId: '100**', // 请替换为自己申请的模板id + data: { + name: 'DCloud', + code: '123456', + expMinute: '3', + } + }) + // 调用成功,请注意这时不代表发送成功 + return res + } catch(err) { + // 调用失败 + console.log(err.errCode) + console.log(err.errMsg) + return { + code: err.errCode, + msg: err.errMsg + } + } +}; + +// 批量发送短信示例 +'use strict'; +exports.main = async (event, context) => { + try { + const res = await uniCloud.sendSms({ + appid: '__UNI__xxxxxxx', + smsKey: '****************', + smsSecret: '****************', + phoneList: ['188********', '138********'], + templateId: '100**', // 请替换为自己申请的模板id + data: { + name: 'DCloud', + code: '123456', + expMinute: '3', + } + }) + // 调用成功,请注意这时不代表发送成功 + return res + } catch(err) { + // 调用失败 + console.log(err.errCode) + console.log(err.errMsg) + return { + code: err.errCode, + msg: err.errMsg + } + } +}; +``` + +本示例使用的模板为: +``` +【uniID】“${name}”验证码:${code},${expMinute}分钟内有效,请勿泄露并尽快验证。 +``` + +本示例发送的短信,在手机上将显示为: +``` +【uniID】“DCloud”验证码:123456,3分钟内有效,请勿泄露并尽快验证。 +``` + + +### 发送失败注意@fail + +- data内如果有`测试`、`test`等字样,系统可能会被判定为测试用途,不会真正把短信下发到对应手机(此行为由运营商控制,可能真实发送,也可能不发送) +- 短信内容不可包含★、 ※、 →、 ●等特殊符号,可能会导致短信乱码 +- 如果本地运行提示`不支持的模板ID`,请更新到`2.9.9+`版本的HBuilderX +- 使用同一短信模板给同一个手机号发送短信时,频率不能太高。如果1分钟内超过1次,会被运营商判定为骚扰或短信重发而被拦截,导致短信发送失败 +- 尽量使用企业实名认证,个人实名认证的审核更严格,更容易发送失败 + + +**其他注意事项** + +- 在[DCloud开发者中心](https://dev.dcloud.net.cn/pages/sms/base)绑定`uniCloud`服务空间后,将会只允许绑定的服务空间调用此接口,绑定列表为空时表示不限制服务空间 +- 如果是用于用户注册的短信验证码,那么强烈推荐使用uni-id,这是一套云端一体的、完善的用户管理方案,已经内置封装好的短信验证码功能,详见:[uni-id-pages](uni-id-pages.md)。 +- 发送短信前,如果需要图形验证码来防止机刷,可以使用[uni-captcha图形验证码](https://ext.dcloud.net.cn/plugin?id=4048)。在[uni-id-pages](uni-id-pages.md)模板中已经集成了uni-id、uni-captcha +- Android手机在App端获取短信验证码,参考:[https://ask.dcloud.net.cn/article/676](https://ask.dcloud.net.cn/article/676) +- 短信内容超过70个字符时为长短信,需分条发送,每67个字按一条短信计算 + +更多问题:欢迎加入DCloud短信技术交流群 +咨询 + + +### 短信费用说明@sms-fee + +- 短信费用为:0.036元/条,但在实际使用中需要依赖`uniCloud`云服务,在使用阿里云正式版后,每条大约需要多花0.0000139元,几乎可以忽略不计,费用计算详见[短信及一键登录资源消耗评估](uniCloud/aliyun-migrate-business.md#sms-unilogin-fee)。 +- 计费条数计算方法:短信内容少于70个字符(每个汉字、标点、空格、字母均算一个字符)算作1条短信,短信内容多于70个字符时,每67个字符算作一条短信,并向上取整(不足67个字符的部分也算做1条)。 例: 短信内容有 100个字符时计费短信条数应为 100 / 67 ≈ 1.49 向上取整后算作2条。 +- 最终按照成功回执状态为"成功"的短信条数计费,成功回执状态可在"发送记录"页面查看。 + +特别注意:短信成功回执最长延迟为72小时。 + + + diff --git a/docs/uniCloud/univerify.md b/docs/uniCloud/univerify.md index 1aae8869a6e7766c68f79f26ad1ee124e1ee7559..e7359d17f87e2d4f43390b9d36052dd34db6644d 100644 --- a/docs/uniCloud/univerify.md +++ b/docs/uniCloud/univerify.md @@ -1,237 +1,242 @@ -## 一键登录@univerify - - - -`univerify` 是DCloud 推出的一键登录产品,通过与运营商深度合作,实现APP用户无需输入帐号密码,即可使用本机手机号码自动登录的能力。 - -`univerify`是替代短信验证登录的下一代登录验证方式,能消除现有短信验证模式等待时间长、操作繁琐和容易泄露的痛点。 - -> 注意:一键登录必须是手机使用流量的前提下才能获取到手机号码,用Wi-Fi联网时无法获取到手机号码,同时如果是双卡手机,获取到的手机号码是默认移动数据的那个手机卡的号码。 - -## 重要调整 - -### 云函数使用一键登录扩展库@extension - -自`HBuilderX 3.4.0`起,一键登录相关功能移至扩展库`uni-cloud-verify`内。在一段时间内无论开发者是否使用扩展库云函数都可以正常使用`uniCloud.getPhoneNumber`。HBuilderX 3.4.0及之后的版本上传云函数时如果没有指定使用`uni-cloud-verify`扩展库的云函数将无法调用uniCloud.getPhoneNumber接口。 - -关于扩展库的说明见:[云函数扩展库](uniCloud/cf-functions.md?id=extension) - -在云函数的package.json内添加`uni-cloud-verify`的引用即可为云函数启用此扩展,无需做其他调整,完整的package.json示例如下: - -```js -{ - "name": "univerify", - "extensions": { - "uni-cloud-verify": {} // 启用一键登录扩展,值为空对象即可 - } -} -``` - -## 客户端@client - -客户端如何使用一键登录请参考此文档:[univerify 使用指南](/univerify) - -## 云函数@cloud - -> 自`HBuilderX 3.4.0`起云函数需启用uni-cloud-verify之后才可以调用getPhoneNumber接口,详细说明见:[云函数使用一键登录扩展库](#extension) - -客户端调用一键登录接口会获取如下结果 - -```js -{ - "target": { - "id": "univerify", - "description": "一键登录", - "authResult": { - "openid": "xxx", - "access_token": "xxx" - } - } -} -``` - -使用上面结果中的`openid`和`access_token`即可在`云函数`内调用接口获取手机号 - -云函数内接口调用形式如下 - -```js -exports.main = async function(event, context){ - const res = await uniCloud.getPhoneNumber({ - provider: 'univerify', - appid: context.APPID, // 客户端callFunction时携带的AppId信息 - apiKey: 'xxx', // 在开发者中心开通服务并获取apiKey - apiSecret: 'xxx', // 在开发者中心开通服务并获取apiSecret - access_token: event.access_token, - openid: event.openid - }) - // res形式如下 - // { - // code: 0, - // message: '', - // phoneNumber: '138xxxxxxxx' - // } -} -``` - -**相关文档** -- [uniCloud快速上手](https://uniapp.dcloud.net.cn/uniCloud/quickstart) -- [云函数URL化](https://uniapp.dcloud.net.cn/uniCloud/http) - -### uni-app项目 - -如果开发uni-app项目可以使用callFunction的方式调用云函数 - -```js -// 客户端 -uniCloud.callFunction({ - name: 'xxx', // 你的云函数名称 - data: { - access_token: 'xxx', // 客户端一键登录接口返回的access_token - openid: 'xxx' // 客户端一键登录接口返回的openid - } -}).then(res => { - // res.result = { - // code: '', - // message: '' - // } -}).catch(err=>{ - // 处理错误 -}) - -// 云函数 -exports.main = async function (event, context){ - const res = await uniCloud.getPhoneNumber({ - appid: context.APPID, // 客户端callFunction时携带的AppId信息 - provider: 'univerify', - apiKey: 'xxx', // 在开发者中心开通服务并获取apiKey - apiSecret: 'xxx', // 在开发者中心开通服务并获取apiSecret - access_token: event.access_token, - openid: event.openid - }) - // 执行入库等操作,正常情况下不要把完整手机号返回给前端 - return { - code: 0, - message: '获取手机号成功' - } -} -``` - -**注意** - -- 开发期间如果重新获取过appid需要重新编译uni-app项目 - -### 5+项目 - -5+项目不可使用callFunction请求云函数,这时候可以使用云函数URL化让5+项目通过http请求的方式访问云函数 - -```js -// 客户端 -const xhr = new plus.net.XMLHttpRequest(); -xhr.onload = function(e) { - const { - code, - message - } = JSON.parse(xhr.responseText) -} -xhr.open( "POST", "https://xxx" ); // url应为云函数Url化之后的地址,可以在uniCloud web控制台云函数详情页面看到 -xhr.setRequestHeader('Content-Type','application/json'); -xhr.send(JSON.stringify({ - access_token: 'xxx', // 客户端一键登录接口返回的access_token - openid: 'xxx' // 客户端一键登录接口返回的openid -})); - -// 云函数,下面仅展示客户端使用post方式发送content-type为application/json请求的场景 -exports.main = async function(event){ - let body = event.body - if(event.isBase64Encoded) { - body = Buffer.from(body,'base64') - } - const { - access_token, - openid - } = JSON.parse(body) - const res = await uniCloud.getPhoneNumber({ - provider: 'univerify', - appid: 'xxx', // DCloud appid - apiKey: 'xxx', // 在开发者中心开通服务并获取apiKey - apiSecret: 'xxx', // 在开发者中心开通服务并获取apiSecret - access_token: access_token, - openid: openid - }) - // 执行入库等操作,正常情况下不要把完整手机号返回给前端 - return { - code: 0, - message: '获取手机号成功' - } -} -``` - -### 自有服务器调用 - -写法类似上面5+项目的云函数url化的方式,但是不同的是需要云函数返回手机号给自己服务器,这样就需要确保数据安全。 - -下面以一个简单的例子演示如何使用签名验证请求是否合法 - -```js -// 以nodejs为例 -const crypto = require('crypto') - -const secret = 'your-secret-string' // 自己的密钥不要直接使用示例值,且注意不要泄露 -const hmac = crypto.createHmac('sha256', secret); - -// 自有服务器生成签名,并以GET方式发送请求 -const params = { - access_token: 'xxx', // 客户端传到自己服务器的参数 - openid: 'xxx' -} -// 字母顺序排序后拼接签名串 -const signStr = Object.keys(params).sort().map(key => { - return `${key}=${params[key]}` -}).join('&') -hmac.update(signStr); -const sign = hmac.digest('hex') -// 最终请求如下链接,其中https://xxxx/xxx为云函数Url化地址 -// https://xxxx/xxx?access_token=xxx&openid=xxx&sign=${sign} 其中${sign}为上一步得到的sign值 -``` - - -```js -// 云函数验证签名,此示例中以接受GET请求为例作演示 -const crypto = require('crypto') -exports.main = async function (event){ - - const secret = 'your-secret-string' // 自己的密钥不要直接使用示例值,且注意不要泄露 - const hmac = crypto.createHmac('sha256', secret); - - let params = event.queryStringParameters - const sign = params.sign - delete params.sign - const signStr = Object.keys(params).sort().map(key => { - return `${key}=${params[key]}` - }).join('&') - - hmac.update(signStr); - - if(sign!==hmac.digest('hex')){ - throw new Error('非法访问') - } - - const { - access_token, - openid - } = params - const res = await uniCloud.getPhoneNumber({ - provider: 'univerify', - appid: 'xxx', // DCloud appid - apiKey: 'xxx', // 在开发者中心开通服务并获取apiKey - apiSecret: 'xxx', // 在开发者中心开通服务并获取apiSecret - access_token: access_token, - openid: openid - }) - // 返回手机号给自己服务器 - return res -} -``` +## 一键登录@univerify + + + +`univerify` 是DCloud 推出的一键登录产品,通过与运营商深度合作,实现APP用户无需输入帐号密码,即可使用本机手机号码自动登录的能力。 + +`univerify`是替代短信验证登录的下一代登录验证方式,能消除现有短信验证模式等待时间长、操作繁琐和容易泄露的痛点。 + +> 注意:一键登录必须是手机使用流量的前提下才能获取到手机号码,用Wi-Fi联网时无法获取到手机号码,同时如果是双卡手机,获取到的手机号码是默认移动数据的那个手机卡的号码。 + +## 重要调整 + +### 云函数使用一键登录扩展库@extension + +自`HBuilderX 3.4.0`起,一键登录相关功能移至扩展库`uni-cloud-verify`内。在一段时间内无论开发者是否使用扩展库云函数都可以正常使用`uniCloud.getPhoneNumber`。HBuilderX 3.4.0及之后的版本上传云函数时如果没有指定使用`uni-cloud-verify`扩展库的云函数将无法调用uniCloud.getPhoneNumber接口。 + +关于扩展库的说明见:[云函数扩展库](uniCloud/cf-functions.md?id=extension) + +在云函数的package.json内添加`uni-cloud-verify`的引用即可为云函数启用此扩展,无需做其他调整,完整的package.json示例如下: + +```js +{ + "name": "univerify", + "extensions": { + "uni-cloud-verify": {} // 启用一键登录扩展,值为空对象即可 + } +} +``` + +## 客户端@client + +客户端如何使用一键登录请参考此文档:[univerify 使用指南](/univerify) + +## 云函数@cloud + +> 自`HBuilderX 3.4.0`起云函数需启用uni-cloud-verify之后才可以调用getPhoneNumber接口,详细说明见:[云函数使用一键登录扩展库](#extension) + +客户端调用一键登录接口会获取如下结果 + +```js +{ + "target": { + "id": "univerify", + "description": "一键登录", + "authResult": { + "openid": "xxx", + "access_token": "xxx" + } + } +} +``` + +使用上面结果中的`openid`和`access_token`即可在`云函数`内调用接口获取手机号 + +云函数内接口调用形式如下 + +```js +exports.main = async function(event, context){ + const res = await uniCloud.getPhoneNumber({ + provider: 'univerify', + appid: context.APPID, // 客户端callFunction时携带的AppId信息 + apiKey: 'xxx', // 在开发者中心开通服务并获取apiKey + apiSecret: 'xxx', // 在开发者中心开通服务并获取apiSecret + access_token: event.access_token, + openid: event.openid + }) + // res形式如下 + // { + // code: 0, + // message: '', + // phoneNumber: '138xxxxxxxx' + // } +} +``` + +**相关文档** +- [uniCloud快速上手](https://uniapp.dcloud.net.cn/uniCloud/quickstart) +- [云函数URL化](https://uniapp.dcloud.net.cn/uniCloud/http) + +### uni-app项目 + +如果开发uni-app项目可以使用callFunction的方式调用云函数 + +```js +// 客户端 +uniCloud.callFunction({ + name: 'xxx', // 你的云函数名称 + data: { + access_token: 'xxx', // 客户端一键登录接口返回的access_token + openid: 'xxx' // 客户端一键登录接口返回的openid + } +}).then(res => { + // res.result = { + // code: '', + // message: '' + // } +}).catch(err=>{ + // 处理错误 +}) + +// 云函数 +exports.main = async function (event, context){ + const res = await uniCloud.getPhoneNumber({ + appid: context.APPID, // 客户端callFunction时携带的AppId信息 + provider: 'univerify', + apiKey: 'xxx', // 在开发者中心开通服务并获取apiKey + apiSecret: 'xxx', // 在开发者中心开通服务并获取apiSecret + access_token: event.access_token, + openid: event.openid + }) + // 执行入库等操作,正常情况下不要把完整手机号返回给前端 + return { + code: 0, + message: '获取手机号成功' + } +} +``` + +**注意** + +- 开发期间如果重新获取过appid需要重新编译uni-app项目 + +### 5+项目 + +5+项目不可使用callFunction请求云函数,这时候可以使用云函数URL化让5+项目通过http请求的方式访问云函数 + +```js +// 客户端 +const xhr = new plus.net.XMLHttpRequest(); +xhr.onload = function(e) { + const { + code, + message + } = JSON.parse(xhr.responseText) +} +xhr.open( "POST", "https://xxx" ); // url应为云函数Url化之后的地址,可以在uniCloud web控制台云函数详情页面看到 +xhr.setRequestHeader('Content-Type','application/json'); +xhr.send(JSON.stringify({ + access_token: 'xxx', // 客户端一键登录接口返回的access_token + openid: 'xxx' // 客户端一键登录接口返回的openid +})); + +// 云函数,下面仅展示客户端使用post方式发送content-type为application/json请求的场景 +exports.main = async function(event){ + let body = event.body + if(event.isBase64Encoded) { + body = Buffer.from(body,'base64') + } + const { + access_token, + openid + } = JSON.parse(body) + const res = await uniCloud.getPhoneNumber({ + provider: 'univerify', + appid: 'xxx', // DCloud appid + apiKey: 'xxx', // 在开发者中心开通服务并获取apiKey + apiSecret: 'xxx', // 在开发者中心开通服务并获取apiSecret + access_token: access_token, + openid: openid + }) + // 执行入库等操作,正常情况下不要把完整手机号返回给前端 + return { + code: 0, + message: '获取手机号成功' + } +} +``` + +### 自有服务器调用 + +写法类似上面5+项目的云函数url化的方式,但是不同的是需要云函数返回手机号给自己服务器,这样就需要确保数据安全。 + +下面以一个简单的例子演示如何使用签名验证请求是否合法 + +```js +// 以nodejs为例 +const crypto = require('crypto') + +const secret = 'your-secret-string' // 自己的密钥不要直接使用示例值,且注意不要泄露 +const hmac = crypto.createHmac('sha256', secret); + +// 自有服务器生成签名,并以GET方式发送请求 +const params = { + access_token: 'xxx', // 客户端传到自己服务器的参数 + openid: 'xxx' +} +// 字母顺序排序后拼接签名串 +const signStr = Object.keys(params).sort().map(key => { + return `${key}=${params[key]}` +}).join('&') +hmac.update(signStr); +const sign = hmac.digest('hex') +// 最终请求如下链接,其中https://xxxx/xxx为云函数Url化地址 +// https://xxxx/xxx?access_token=xxx&openid=xxx&sign=${sign} 其中${sign}为上一步得到的sign值 +``` + + +```js +// 云函数验证签名,此示例中以接受GET请求为例作演示 +const crypto = require('crypto') +exports.main = async function (event){ + + const secret = 'your-secret-string' // 自己的密钥不要直接使用示例值,且注意不要泄露 + const hmac = crypto.createHmac('sha256', secret); + + let params = event.queryStringParameters + const sign = params.sign + delete params.sign + const signStr = Object.keys(params).sort().map(key => { + return `${key}=${params[key]}` + }).join('&') + + hmac.update(signStr); + + if(sign!==hmac.digest('hex')){ + throw new Error('非法访问') + } + + const { + access_token, + openid + } = params + const res = await uniCloud.getPhoneNumber({ + provider: 'univerify', + appid: 'xxx', // DCloud appid + apiKey: 'xxx', // 在开发者中心开通服务并获取apiKey + apiSecret: 'xxx', // 在开发者中心开通服务并获取apiSecret + access_token: access_token, + openid: openid + }) + // 返回手机号给自己服务器 + return res +} +``` + + +### 一键登录费用说明@unilogin-fee + +- 0.02元/次,失败不计费,但在实际使用中需要依赖`uniCloud`云服务,在使用阿里云正式版后,每条大约需要多花0.0000139元,几乎可以忽略不计,费用计算详见[短信及一键登录资源消耗评估](uniCloud/aliyun-migrate-business.md#sms-unilogin-fee)。