Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
取酒独倾
unidocs-zh
提交
693e430e
U
unidocs-zh
项目概览
取酒独倾
/
unidocs-zh
与 Fork 源项目一致
Fork自
DCloud / unidocs-zh
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
unidocs-zh
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
693e430e
编写于
1月 03, 2023
作者:
WangMoYang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
docs: 短信及一键登录测评
上级
6eecd39c
变更
3
展开全部
隐藏空白更改
内联
并排
Showing
3 changed file
with
542 addition
and
468 deletion
+542
-468
docs/uniCloud/send-sms.md
docs/uniCloud/send-sms.md
+242
-231
docs/uniCloud/sms-and-unilogin-evaluation.md
docs/uniCloud/sms-and-unilogin-evaluation.md
+58
-0
docs/uniCloud/univerify.md
docs/uniCloud/univerify.md
+242
-237
未找到文件。
docs/uniCloud/send-sms.md
浏览文件 @
693e430e
此差异已折叠。
点击以展开。
docs/uniCloud/sms-and-unilogin-evaluation.md
0 → 100644
浏览文件 @
693e430e
近期,uniCloud阿里云版开始正式商用,部分开发者对基于uniCloud的
`短信`
和
`一键登录`
业务开始纠结,不清楚
`短信`
和
`一键登录`
业务比之前会多花费多少钱,对比其它厂家是否还具有价格优势。
本文尝试算细账、算总账,以阿里云
[
按量计费
](
https://uniapp.dcloud.net.cn/uniCloud/price.html#aliyun-postpay
)
为例,详细预测
`短信`
和
`一键登录`
业务在不同用户规模下的资源消耗及对应费用,帮助大家明智选择,无忧开发。
本文主要分为两个部分:
-
短信和一键登录业务的消耗资源费用测算
-
综合考虑,你该如何选择
## 短信和一键登录业务的消耗资源费用测算
`短信`
和
`一键登录`
业务涉及费用的部分主要是云函数/云对象的使用量、调用次数、和出网流量(如:使用
`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元。
## 综合考虑,你该如何选择
再次说回
`短信`
和
`一键登录`
业务,通过上面的费用测算可得知,
`短信`
和
`一键登录`
业务单次调用费用只增加了0.0000139元,几乎可以忽略不计,相比其它厂商仍然保持着价格优势。
以日均调用1000次来说,每月才多了0.417元,每年才多了5块钱,一年多花5块钱,可以省掉工程师重新选择厂商对接的成本,让工程师将更多精力投入核心业务中。这5块钱的买卖,不划算吗?它不香吗?
不重复制造轮子,聚焦业务,快速验证模式,实现商业增长,才应该是聪明工程师的追求。
本篇评测仅供大家参考。
docs/uniCloud/univerify.md
浏览文件 @
693e430e
## 一键登录@univerify
<!--
/// meta
keyword: 手机号
-->
`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
<!--
/// meta
keyword: 手机号
-->
`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/sms-and-unilogin-evaluation.md
)
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录