快速参考
所有的 API 访问都是通过 HTTPS 进行的.API 访问需要在 https://www.scanify.com 域名下。
注册
URL | HTTP | 功能 |
---|---|---|
/api/user | POST | 用户注册 |
/api/user/sendSmsCode | POST | 请求重新发送手机号码注册OTP验证短信 |
/api/user/verifySmsCode/<code> | POST | 请求验证注册手机OTP短信验证码。 |
/api/<code> | POST | 请求使用 "验证码" |
/api/user/<id> | GET | 获取用户信息 |
/api/user/<id>/updatePassword | PUT | 更新密码,要求输入旧密码。 |
登陆
URL | HTTP | 功能 |
---|---|---|
/api/login | GET | 用户登录 |
/api/login/sendSmsCode | POST | 请求发送手机号码登录OTP短信。 |
/api/login/verifySmsCode/<code> | POST | 请求验证登陆手机OTP短信验证码。 |
用户操作
URL | HTTP | 功能 |
---|---|---|
/api/user/<id> | GET | 获取用户信息 |
/api/user/<id>/updatePassword | PUT | 更新密码,要求输入旧密码。 |
app保护
URL | HTTP | 功能 |
---|---|---|
/api/user/protect/ | PUT | app请求保护完成。 |
/api/user/protect/<code> | POST | app请求保护验证。 |
客户端保护
URL | HTTP | 功能 |
---|---|---|
/api/protect/ | POST | 请求保护某个用户,返回二维码URL。 |
/api/protect/<id> | GET | 请求保护结果。 |
签名方式
暂定使用SHA1数字签名标准。
请求格式
对于 POST 和 PUT 请求, 请求的主体必须是 JSON 格式, 而且 HTTP header 的 Content-Type 需要设置为 application/json。
客户端验证是通过 HTTP header 来进行的, X-Scanify-Application-Id 头标明正在运行的是哪个客户端程序。
安全的验证方式
用户除了需要传递 X-Scanify-Application-Id 的 http 头表示 App id外,还需要传递 X-Scanify-Application-Sign 头,它的值要求是一个形如 sign,timestamp 的字符串,其中:
- sign(必须)- 将 timestamp 加上 app key 组成的字符串做 sha1 签名。
- timestamp(必须)- 客户端产生本次请求的 unix 时间戳,精确到毫秒。
响应格式
对于所有的请求的响应格式都是一个 JSON 对象.
一个请求是否成功是由状态码标明的. 一个 2XX 的状态码表示成功, 而一个 4XX 表示请求失败. 当一个请求失败时响应的主体仍然是一个 JSON 对象, 但是总是会包含 code 和 msg 这两个字段, 可以用它们来进行调试。具体的响应码解释待定。 举个例子, 如果尝试用不允许的 app key 来请求会得到如下信息:
{
"code": 105,
"msg": "未知的的客户端请求"
}
数据类型
对象格式
通过 REST API 保存数据需要将对象的数据通过 JSON 来编码. 您只需要设置 key-value 对就可以, 后端会解析它. 举个例子, 假设您注册一个用户信息. 一个简单的对象可能包含:
{
"phone":"138xxxxxxxx",
"password":"xxxxxx",
"smsCode":"6位短信验证码"
}
Key 必须是字母和数字组成的 String,使用驼峰命名法(如手机号为phone)。Value 可以是任何可以 JSON 编码的东西.
详细请参考具体对象信息
日期
类似createdAt(创建时间)、updatedAt(更新时间)等所有日期格式 都是采用 UTC 时间戳, 以 ISO 8601 标准和毫秒级精度储存:YYYY-MM-DDTHH:MM:SS.MMMMZ, 如:
"createdAt": "2015-08-20T02:06:57.931Z",
"updatedAt": "2015-08-20T02:06:57.931Z"
数组
通用数组格式为:
"arrayColor":["red","green"]
用户
不仅在移动app 上, 在所有客户端中的用户都尽量统一注册登录流程. 通过 REST API 访问用户的账户.
注册
注册第一步
注册一个新用户时 phone 和 password 字段都是必要的.Password 字段会以和其他的字段不一样的方式处理, 它在储存时会被加密而且永远不会被返回给任何来自客户端的请求.
app提交注册
为了注册一个新的用户, 需要向 user 路径发送一个 POST 请求, 例子:
POST https://www.scanify.com/api/user
Headers
{
"X-Scanify-Application-Id": "n35a5fdhawz56y24pjn3u9d5zp9r1nhpebrxyyu359cq0ddo",
"X-Scanify-Application-Sign": "28ad0513f8788d58bb0f7caa0af23400,1389085779854",
"Content-Type": "application/json;charset=utf-8"
}
Data
{"phone":"138xxxxxxxx","password":"p_n7!-e8"}
Scanify服务器返回
app提交手机号和密码后,Scanify会验证手机号码唯一性,如果没有注册过,则会创建新用户并发送OTP短信到这个手机号,同时返回给app, sessionToken 可以被用来认证这名用户随后的请求
{
"createdAt": "2015-11-07T20:58:34.448Z",
"id": "143214",
"sessionToken": "pnktnjyb996sj4p156gjtp4im"
"code": 200,
"msg": "Created"
}
注册第二步
app端要求验证OTP短信
app跳转到第二步要求输入收到的短信验证码,注意:注册或登录以后的操作都必须加入一个 X-Scanify-Session-Token 头部来请求其它操作
如果没有收到验证码,可重新发送(要包含sessionToken):
POST https://www.scanify.com/api/user/sendSmsCode
Headers
{
"X-Scanify-Application-Id": "n35a5fdhawz56y24pjn3u9d5zp9r1nhpebrxyyu359cq0ddo",
"X-Scanify-Application-Sign": "28ad0513f8788d58bb0f7caa0af23400,1389085779854",
"X-Scanify-Session-Token: pnktnjyb996sj4p156gjtp4im",
"Content-Type": "application/json;charset=utf-8"
}
服务器收到请求重新发送短信并返回:
{
"code": 200,
"msg": "Created"
}
app输入短信验证码并发送:
POST https://www.scanify.com/api/user/verifySmsCode/234fss
Headers
{
"X-Scanify-Application-Id": "n35a5fdhawz56y24pjn3u9d5zp9r1nhpebrxyyu359cq0ddo",
"X-Scanify-Application-Sign": "28ad0513f8788d58bb0f7caa0af23400,1389085779854",
"X-Scanify-Session-Token: pnktnjyb996sj4p156gjtp4im",
"Content-Type": "application/json;charset=utf-8"
}
Scanify服务器返回
服务器验证最新的OTP,验证成功时该用户才视为激活状态
{
"code": 200,
"msg": "success"
}
登陆
用户登陆和注册流程类似,只是调用接口不同而已。同时登陆后同样会返回sessionToken。
用户操作
获取用户信息
app发送请求(要包含sessionToken):
GET https://www.scanify.com/api/user/143214
Headers
{
"X-Scanify-Application-Id": "n35a5fdhawz56y24pjn3u9d5zp9r1nhpebrxyyu359cq0ddo",
"X-Scanify-Application-Sign": "28ad0513f8788d58bb0f7caa0af23400,1389085779854",
"X-Scanify-Session-Token: pnktnjyb996sj4p156gjtp4im",
"Content-Type": "application/json;charset=utf-8"
}
服务器收到请求返回JSON对象, 除了密码以外. 也包括了 createdAt,updatedAt 和 id 字段:
{
"phone": "138xxxxxxxx",
"createdAt": "2014-11-07T20:58:34.448Z",
"updatedAt": "2014-11-07T20:58:34.448Z",
"id": "2342525",
"code": 200,
"msg": "sucess"
}
更新密码
app发送请求(要包含sessionToken):
PUT https://www.scanify.com/api/user/143214/updatePassword
Headers
{
"X-Scanify-Application-Id": "n35a5fdhawz56y24pjn3u9d5zp9r1nhpebrxyyu359cq0ddo",
"X-Scanify-Application-Sign": "28ad0513f8788d58bb0f7caa0af23400,1389085779854",
"X-Scanify-Session-Token: pnktnjyb996sj4p156gjtp4im",
"Content-Type": "application/json;charset=utf-8"
}
Data
{"old_password":"the_old_pass", "new_password":"the_new_pass"}
服务器收到请求返回:
{
"code": 200,
"msg": "sucess"
}
保护
通过二维码的方式保护账户安全,以下分别为服务器与app之间和服务器与客户端直接的交互方法
app端
请求保护验证
扫描二维码后解析出保护URL并请求这个URL,URL中已包含保护随机码,除此之外还需要传递用户id,请求方法:
PUT https://www.scanify.com/api/user/protect/sfdsafsafdsaf
Headers
{
"X-Scanify-Application-Id": "n35a5fdhawz56y24pjn3u9d5zp9r1nhpebrxyyu359cq0ddo",
"X-Scanify-Application-Sign": "28ad0513f8788d58bb0f7caa0af23400,1389085779854",
"X-Scanify-Session-Token: pnktnjyb996sj4p156gjtp4im",
"Content-Type": "application/json;charset=utf-8"
}
Data
{"id":"143214"}
服务器收到请求并验证随机码后,通过用户id创建一条保护记录,返回是否允许保护, 同时会返回一个保护id:
{
"protectId": "fdsajfdsjakfksdajfjkafjfsf",
"code": 200,
"msg": "sucess"
}
保护确认
app收到验证成功后用手势、语音等方式确认用户,然后给服务器回复保护成功确认, 相当于请求修改保护状态state:
PUT https://www.scanify.com/api/user/protect/
Headers
{
"X-Scanify-Application-Id": "n35a5fdhawz56y24pjn3u9d5zp9r1nhpebrxyyu359cq0ddo",
"X-Scanify-Application-Sign": "28ad0513f8788d58bb0f7caa0af23400,1389085779854",
"X-Scanify-Session-Token: pnktnjyb996sj4p156gjtp4im",
"Content-Type": "application/json;charset=utf-8"
}
Data
{"protectId":"fdsajfdsjakfksdajfjkafjfsf",'state':'1'}
服务器收到请求返回成功并保护结束:
{
"code": 200,
"msg": "sucess"
}
支付客户端
请求保护某个用户
客户端和Scanify交互要保护更多用户信息在里面,包含:
- clientUserID(必须)- 就是客户端的用户id,比如商户或个人用户的id。
- componentId(必须)- 代表客户端的细化组件id。
- code(必须)- 代表客户端的某个保护操作代码。
- remarks(可选)- 保护操作说明。
钱包请求app需要的保护验证URL,用于生成二维码, 此时:
PUT https://www.scanify.com/api/protect/
Headers
{
"X-Scanify-Application-Id": "n35a5fdhawz56y24pjn3u9d5zp9r1nhpebrxyyu359cq0ddo",
"X-Scanify-Application-Sign": "28ad0513f8788d58bb0f7caa0af23400,1389085779854",
"Content-Type": "application/json;charset=utf-8"
}
Data
{"clientUserID":"23432432432",'componentId':'24241441441',"code":"10","remarks":"支付保护"}
服务器收到请求后,首先通过clientUserID查询Scanify用户表中是否存在记录,包含以下几种情况:
- 不存在clientUserID: 如果没有将创建一条用户记录(需要注册)。
- 存在clientUserID记录但没有注册完成:(需要重新注册)。
- 存在并已注册完成 - app扫描后可以直接验证保护。
服务器收到请求后将返回上面APP验证请求的URL(即/api/user/protect/<code>,code是服务器生成的保护随机码 - 随机码怎么存储还没有考虑好),客户端通过这个URL生成二维码:
{
"url": "https://www.scanify.com/api/user/protect/sfdsafsafdsaf";
"code": 200,
"msg": "sucess"
}
请求保护结果
得到二维码显示到网页后需要获取用户保护结果, 在客户端有这么几种方法:
- Scanify服务器直接给客户端服务发验证结果, 同时通过网页轮询技术直接请求Scanify服务器,有可能遇到跨域的问题,但是这个方法最直接高效。
- Scanify服务器直接给客户端服务发验证结果,然后通过网页轮询技术请求客户端服务器,这种方法
- Scanify服务器直接给客户端服务发验证结果,然后客户端服务器通过服务器推技术给网页发结果,这种方法最安全,但是代价稍高,需要服务器支持。
综上所述,客户端必须提供验证结果的接口,类似支付验证的retrunUrl, Scanify服务器会Post验证结果信息给客户端,同时提供客户端请求Scanify的接口:
GET https://www.scanify.com/api/protect/234234234
Headers
{
"X-Scanify-Application-Id": "n35a5fdhawz56y24pjn3u9d5zp9r1nhpebrxyyu359cq0ddo",
"X-Scanify-Application-Sign": "28ad0513f8788d58bb0f7caa0af23400,1389085779854",
"Content-Type": "application/json;charset=utf-8"
}
服务器收到请求返回保护详情,保护结束
{
"url": "https://www.scanify.com/api/user/protect/sfdsafsafdsaf";
"code": 200,
"msg": "sucess"
}