05:接口文档

一、准备商品数据接口路由

  • 在项目中创建新文件夹,准备存放接口文件:myapp—->api文件夹
    1. 创建商品接口的路由文件:api---->goods.js
    2. 在app.js中注册接口:
1
2
var apiGoods = require("./api/goods.js");
app.use("/api/goods",apiGoods);
3.  测试接口:`localhost:3000/api/goods` 

二、实现获取商品数据接口

  1. 引入数据库相关模块
  2. 接收到路由请求后,读取数据库数据,处理之后返回
  3. 数据格式规范:
    • 没有数据
      • { "code": 400, "title": "请求失败", "msg": "NOT DATA" }
    • 有数据
      • { "code": 200, "title": "请求成功", "msg": 数据 }

三、编写接口文档

  • 使用自动生成在线接口文档的工具:apidoc
  1. 下载:npm i apidoc -D
  2. 创建文档目录:在public文件夹内,创建apidoc文件夹
  3. 配置package文件,增加:"apidoc": {"title":"接口文档", "url":"http://localhost:3000"}
  4. 编写文档:在api---->goods.js内,使用/***/的形式,添加注释,以注释的形式编写文档
  5. 文档格式要求:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* @apiGroup 商品信息
* @api {get} /api/goods 获取商品数据
* @apiVersion 0.0.0
* @apiDescription 分页请求商品数据
* @apiParam {Number} limit=10 数据条数
* @apiParam {Number} index=0 分页数据页码
* @apiSuccess {number} code 请求状态
* @apiSuccess {string} title 请求说明
* @apiSuccess {array} msg 请求数据
* @apiSuccessExample {json} Success-Response:
* {
* "code":200,
* "title":"请求成功",
* "msg":[{},{},...]
* }
* @apiError {number} code 请求状态
* @apiError {string} title 请求说明
* @apiError {array} msg 请求数据
* @apiErrorExample {json} Error-Response:
* {
* "code":400,
* "title":"请求失败",
* "msg":"NOT DATA"
* }
* @apiSampleRequest http://localhost:3000/api/goods
*/
  1. 命令行运行:apidoc -i api/ -o public/apidoc
  2. 启动项目后,浏览器查看:localhost:3000/apidoc/index.html

四、其他商品数据接口

  1. 创建排序数据接口,生成接口文档
  2. 创建类目数据接口,生成接口文档
  3. 创建商品详情数据接口,生成接口文档

五、注册接口

1. 短信验证码服务

  1. 登录阿里云
  2. 选择:产品分类 -> 云通信 -> 短信服务 -> 管理控制台 -> 新手引导
  3. 申请国内短信签名
  4. 申请国内短信模板
  5. 选择AccessKey,创建AccessKey
  6. 选择OpenAPI Explorer,填写SendSms中的必要信息,测试短信发送功能
  7. 切换到Node.js示例代码,复制代码已备后用

2. 封装短信发送验证码

  1. 安装randomnumber模块
    • npm install randomnumber
  2. 引入并使用
    • const randomnum = require("randomnumber")
    • randomnum.generate(4)
  3. 创建tools文件,将阿里短信验证码发送实例代码,封装到发送短信功能,及随机数生成。处理参数,处理异步

3. 注册的业务逻辑

  • 用户名 + 手机号 + 密码,完成注册
  • 发送手机验证码后将验证码存数据库,由后端校验前端验证码是否输入一致
  1. 点击获取手机验证码 - 验证手机是否注册
    • 根据手机号查询用户集合,没有查询到记录
      • 表示手机号没有被注册
      • 根据手机号发送验证码,并在发送成功后将手机号和验证码一起插入用户集合
    • 如果查询到记录
      • 验证账户名和密码是否为空,如果不为空,表示该手机号已经被注册
      • 如果为空,表示只是发送过短信验证码,重新发送一条验证码,并更新该手机号对应的验证码即可
  2. 提交表单信息 - 注册功能
    • 获取表单信息,验证用户名是否被注册过
      • 如果注册过,提示该用户名已被占用
      • 如果没有被注册,继续下一步
    • 验证手机号是否存在
      • 如果手机号不存在,直接提醒用户先获取短信验证码
      • 如果手机号存在,继续下一步
    • 根据当前手机号,验证用户名是否为空
      • 用户名不为空,提示一个手机号只能注册一个用户
      • 用户名为空,继续下一步
    • 校验验证码是否正确
      • 如果验证码不正确,提醒用户验证码错误
      • 如果验证码正确,给密码加密,以 手机号 或 用户名 为条件,更新数据库的数据

4. 设计用户信息数据库集合

  1. 准备数据库,在myapp项目中创建用户信息数据库集合:user.js(创建集合)
  2. 并设计集合结构(user.js):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
userId:{type:String}, // 用户id
userName:{type:String}, // 用户名
nickName:{type:String}, // 昵称
passWord:{type:String}, // 密码
tel:{type:String}, // 手机号
email:{type:String}, // 邮箱
avatar:{type:String}, // 头像
birthday:{type:String}, // 生日 - 时间戳
sex:{type:Number}, // 1男,0女
hobby:{type:Array}, // 兴趣爱好
regTime:{type:String}, // 注册时间
lastTime:{type:String}, // 上一次登录时间/最后一次登录时间
loginState:{type:Number}, // 1已登录,0未登录
code:{type:String} // 短信验证码
}
- 将集合模块暴露,准备实现数据的操作

5. 创建注册路由

  1. 完善发送短信验证码路由逻辑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// 获取手机验证码
router.post('/sendMsg', function(req, res, next) {
const tel = req.body.tel;
const code = tools.random(4);
// 验证手机是否注册:根据手机号查询用户集合
sql.find(user,{ tel },{_id:0,__v:0}).then((data)=>{
if(data.length > 0){
// 如果查询到记录
// 验证账户名和密码是否为空
if(data[0].userName === ""){
// 如果为空,表示只是发送过短信验证码,重新发送一条验证码,并更新该手机号对应的验证码即可
tools.sendMsg(tel, code).then(()=>{
sql.update(user, { tel }, { $set: { code } }).then(()=>{
res.send({
state:202,
msg:"短信验证码发送成功",
code // 此为测试用,真实项目要删掉
})
})
});
}else{
// 如果不为空,表示该手机号已经被注册
res.send({
state:204,
msg:"该手机号已被注册"
})
}
}else{
// 没有查询到记录,表示手机号没有被注册
// 根据手机号发送验证码,并在发送成功后将手机号和验证码一起插入用户集合
tools.sendMsg(tel, code).then(()=>{
res.send({
state:201,
msg:"短信验证码发送成功",
code // 此为测试用,真实项目要删掉
})

sql.insert(user, {
userId:"user"+uuid.v1(), // 用户id
userName:"", // 用户名
nickName:"临时用户", // 昵称
passWord:"", // 密码
tel, // 手机号
email:"", // 邮箱
avatar:"", // 头像
birthday:"", // 生日 - 时间戳
sex:1, // 1男,0女
hobby:[], // 兴趣爱好
regTime:Date.now(), // 注册时间
lastTime:Date.now(), // 上一次登录时间/最后一次登录时间
loginState:0, // 1已登录,0未登录
code
})
});
}
})
});

六、登录

1. 登录的业务逻辑

  • 用户名或手机号登录
    • 首先验证用户名或手机号是否存在
      • 不存在,则提示用户用户名未注册
      • 存在,继续下一步
    • 验证密码是否和用户名或手机号匹配
      • 不匹配,提示用户密码不符
      • 匹配,提示登录成功

2. 创建登录路由

  • 完善发送短信验证码路由逻辑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
router.post('/login', function(req, res, next) {
let {userName,tel,passWord} = req.body;
// 首先验证用户名或手机号是否存在
sql.find(user, {$or:[{userName},{tel}]}, {}).then(data=>{
if(data.length>0){
// 存在,继续下一步
// 验证密码是否和用户名或手机号匹配
if(data[0].passWord == md5(passWord)){
// 匹配,更新当前账户的登录时间 和 登录状态
sql.update(user,{userId:data[0].userId},{
lastTime:Date.now(),
loginState:1
}).then(()=>{
// 更新之后,提示登录成功
res.send({
state:200,
title:"登录成功",
msg:req.body,
userMsg:data
})
})
}else{
// 不匹配,提示用户密码不符
res.send({
state:202,
title:"用户名密码不匹配",
msg:req.body
})
}

}else{
// 不存在,则提示用户用户名未注册
res.send({
state:201,
title:"用户名未注册",
msg:req.body
})
}
})
})

七、前端登录验证

1. token验证思路

  • 第一次请求时,用户发送账号与密码
  • 后台校验通过,生成一个有时效性的token,再将此token发送给用户
  • 用户获得token后,将此token存储在本地,一般存储在localstorage或cookie
  • 之后每次请求都会将此token添加在请求头,所有需要校验身份的接口都会被校验token,若token解析后的数据包含用户身份信息,则身份验证通过。
  • ajax登陆,成功后接受后端返回一个token字段str,
  • 使用localStorage.setItem(‘token’, str)或document.cookie = “token=” + str,
  • 以后再调用接口时先从本地取出token字段的值,然后随着请求的数据一起发送到服务器,服务器验证token的有效性,如果ok则返回数据,如果不ok,返回某一个字段,表示未登录,前端负责页面跳转到登录页面

2. 生成token

  1. 安装第三方模块 - jsonwebtoken
    • npm i jsonwebtoken -S
  2. 生成token
1
2
3
4
5
6
7
8
9
10
11
const jwt = require("jsonwebtoken");
// 参数1:要存储的数据
// 参数2:加密因子
// 参数3:有效期时间
const token = jwt.sign({
userId: data.id
}, "潜水的旱鸭子", {
expiresIn: 7 * 24 * 60 * 60
});

// 将token返回给前端请求
  1. 验证token
1
2
3
4
jwt.verify(token, "潜水的旱鸭子", (err, data)=>{
if(err){ reject('token 验证失败')}
console.log(data)
})

八、封装获取个人信息接口