基于Nodejs+Koa搭建极光推送的用户服务端程序,RESTful接口、文件上传。

服务框架


使用 Koa脚手架 快速开发服务端程序,clone下来此项目,删除controller下的UserController.js、comomon/UploadController.js,新建PushController.js,编写处理请求的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
'use strict'

var pushNotice = async (ctx, next) => {
let param = ctx.request.body
console.log(param)
ctx.body = format({}, ERROR_CODE.OK)

await next()
}

module.exports = {
'POST /push/notice': pushNotice
}

先测试一下接口,用postman提交请求

接收到的参数如下

1
2
{ alias: [ '17816118870', '18796221162' ],
content: { uuid: '1232' } }

集成JPush SDK


参考极光推送官方文档,安装sdk依赖,

1
npm install jpush-async --save

在PushController.js中引入依赖

1
2
3
4
5
const JPush = require('jpush-async').JPushAsync
const jPushClient = JPush.buildClient(
'0a2*****************2ba',
'5e2*****************8dc'
)

buildClient()中 两个参数分别为为 极光推送的AppKey以及Master Secret,填写这两个参需要注意,不要复制错误或留有空格,这都会导致服务调用异常。
使用Alias方式发送自定义消息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

/**
* jpush send message
* @param {*} alias
* @param {*} notice
*/
var jPushSend = function(alias, notice) {
jPushClient
.push()
.setPlatform('ios', 'android')
// 设置别名
.setAudience(JPush.alias(alias))
// .setNotification('NotificationContent')
// 设置推送内容
.setMessage(notice)
.setOptions(null, 60)
.send()
.then(function(result) {
console.log(result)
})
.catch(function(err) {
console.log(err)
})
}

alias格式为 ‘17816227765,18746578867’,所以需要将接收到的参数格式化,直接数组转字符串即可

1
2
3
4
5
6
7
8
9
var pushNotice = async (ctx, next) => {
let param = ctx.request.body
console.log(param)
let alias = param.alias.toString()
param.content.type = 'NOTICE'
jPushSend(alias, JSON.stringify(param.content))
ctx.body = format({}, ERROR_CODE.OK)
await next()
}

进行接口测试,移动端可正常接收推送消息。

推送媒体文件


实现思路为 接收客户端推送图片、视频、语音等媒体文件,保存成功后根据推送参数向指定客户端推送消息,附带上文件的url(多个文件则放入数组)以及其他的推送内容。

保存推送的媒体文件

使用文件上传接口的部分代码,将文件保存在服务端或第三方文件服务器,并获得文件的url,

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
/**
* handle media push
* @param {} ctx
* @param {*} next
*/
var pushMedia = async (ctx, next) => {
// ctx.req.files contains files uploaded
// ctx.req.body contains fields property
console.log(ctx.req.files)
console.log(ctx.req.body)
if (!ctx.req.files || ctx.req.files.length == 0) {
ctx.body = format({}, ERROR_CODE.FILE_NULL)
await next()
return
}
// push param
let param = ctx.req.body
param.content = {}
param.content.type = 'MEDIA'
let alias = param.alias.toString()

let datas
// single file
if (ctx.req.files.length == 1) {
let file = ctx.req.files[0]
datas = await saveFile(file)
if (datas) {
ctx.body = format(datas, ERROR_CODE.OK)
} else {
ctx.body = format({}, ERROR_CODE.FILE_WRITE_ERROR)
}
} else {
// multi files
datas = []
for (let i = 0; i < ctx.req.files.length; i++) {
let file = ctx.req.files[i]
let res = await saveFile(file)
if (res) {
datas.push(res)
}
}
ctx.body = format({ datas }, ERROR_CODE.OK)
}

// push
param.content.media = datas
jPushSend(alias, JSON.stringify(param.content))

await next()
}

推送消息

param.content是完整的推送内容,param.content.media是媒体文件的url,jPushSend(alias, JSON.stringify(param.content))
调用SDK完成推送。

返回信息为文件上传结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"code": 0,
"msg": "OK",
"data": {
"datas": [
{
"url": "/uploads/2018-10-21/9e0e8bde-2e22-4f8d-9ada-bbe74c6a6d8d.png",
"name": "study.png"
},
{
"url": "/uploads/2018-10-21/92b10c98-fc1e-4be0-ba48-9111069fc485.jpeg",
"name": "1_S7BwOWdiQNcL0HHG2fDL0w.jpeg"
}
]
}
}

至此,基于Nodejs+JPush搭建的推送服务基本完成。

多推送通道