filesite
7 months ago
7 changed files with 220 additions and 3 deletions
@ -1,3 +1,36 @@
@@ -1,3 +1,36 @@
|
||||
# service-3rd |
||||
|
||||
Service implement api or sdk of 3rd party. |
||||
|
||||
实现第三方平台接口的公用服务,通过API调用。 |
||||
|
||||
## 已对接功能 |
||||
|
||||
* 阿里云的短信发送接口 |
||||
|
||||
|
||||
## 接口参数签名方法 |
||||
|
||||
将所有参数按字母排序之后转换成JSON字符串(注意需保持斜杠/和unicode字符串不转义),最后再拼接上token计算MD5值。 |
||||
|
||||
示例如下: |
||||
``` |
||||
var token = 'hello world'; //config.js里配置的密钥 |
||||
var params = { //参数示例 |
||||
"b": 2, |
||||
"a": 1, |
||||
"t": 234343 |
||||
}; |
||||
|
||||
var sortObj = function(obj) { //参数排序方法 |
||||
return Object.keys(obj).sort().reduce(function(result, key) { |
||||
result[key] = obj[key]; |
||||
return result; |
||||
}, {}); |
||||
}; |
||||
|
||||
//1. 排序参数 |
||||
var sortedParams = sortObj(params); |
||||
//2. 计算MD5值 |
||||
var sign = md5( JSON.stringify(sortedParams) + token ); |
||||
``` |
||||
|
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
'use strict'; |
||||
|
||||
const md5 = require('md5'); |
||||
|
||||
class Common { |
||||
static sortDict(obj) { //dict按key排序
|
||||
return Object.keys(obj).sort().reduce(function(result, key) { |
||||
result[key] = obj[key]; |
||||
return result; |
||||
}, {}); |
||||
} |
||||
|
||||
static sign(params, token) { //对参数做MD5签名
|
||||
return md5( JSON.stringify(Common.sortDict(params)) + token ); |
||||
} |
||||
|
||||
static isPhoneNumber(number) { |
||||
return /^1[3-9][0-9]{9}$/i.test(number); |
||||
} |
||||
|
||||
static isVerifyCode(code) { |
||||
return /^[0-9]{4}$/i.test(code); |
||||
} |
||||
} |
||||
|
||||
exports.default = Common; |
@ -0,0 +1,70 @@
@@ -0,0 +1,70 @@
|
||||
'use strict'; |
||||
|
||||
/** |
||||
* Express router of aliyun/ |
||||
*/ |
||||
|
||||
const express = require('express'); |
||||
const {default: common} = require('./common.js'); |
||||
|
||||
const {default: aliyunSmsClient} = require('./aliyunSmsClient'); |
||||
const {default: defaultConfig, getCustomConfigs: getCustomConfigs} = require('./conf/config'); |
||||
|
||||
|
||||
|
||||
const router = express.Router(); |
||||
|
||||
//发送注册验证码短信接口
|
||||
/** |
||||
* @phoneNumber: 手机号码 |
||||
* @codeNumber: 4位数字的验证码 |
||||
* @action: ['register', 'login'] |
||||
* @sign: 签名 |
||||
*/ |
||||
router.post('/sendverifycode', async (req, res) => { |
||||
let phoneNumber = req.body.phoneNumber; |
||||
let codeNumber = req.body.codeNumber; |
||||
let action = req.body.action ? req.body.action : 'register'; |
||||
let sign = req.body.sign; |
||||
|
||||
let data = {code: 0, message: ''}; |
||||
let myConfig = await getCustomConfigs('./conf/custom_config.json'); |
||||
|
||||
if (!phoneNumber || !codeNumber || !sign) { |
||||
data.message = '参数不能为空'; |
||||
}else if (common.isPhoneNumber(phoneNumber) == false) { |
||||
data.message = '手机号码格式错误'; |
||||
}else if (common.isVerifyCode(codeNumber) == false) { |
||||
data.message = '验证码格式错误,必须是4位数的数字'; |
||||
}else { |
||||
let paramsCheck = {}; |
||||
for (const key in req.body) { |
||||
if (key != 'sign') { |
||||
paramsCheck[key] = req.body[key]; |
||||
} |
||||
} |
||||
|
||||
let mySign = common.sign(paramsCheck, myConfig.secret); |
||||
if (mySign.toLowerCase() != sign.toLowerCase()) { |
||||
data.message = `签名 ${sign} 不匹配,请确保密钥正确及签名方法跟文档一致`; |
||||
} |
||||
} |
||||
|
||||
if (!data.message) { |
||||
let signName = 'Ta荐', |
||||
templateCode = action == 'register' ? 'SMS_465895580' : 'SMS_465915662', |
||||
templateParam = `{"code":"${codeNumber}"}`; |
||||
|
||||
let sended = await aliyunSmsClient.send(myConfig, signName, templateCode, templateParam, phoneNumber); |
||||
if (sended) { |
||||
data.code = 1; |
||||
data.message = '验证码发送成功'; |
||||
}else { |
||||
data.message = '验证码发送失败,请稍后重试'; |
||||
} |
||||
} |
||||
|
||||
return res.status(200).json(data); |
||||
}); |
||||
|
||||
exports.default = router; |
@ -0,0 +1,52 @@
@@ -0,0 +1,52 @@
|
||||
'use strict'; |
||||
|
||||
/** |
||||
* Main program of service of 3rd party |
||||
**/ |
||||
|
||||
const express = require('express'); |
||||
const bodyParser = require('body-parser'); |
||||
const {default: aliyunRouter} = require('./router_aliyun.js'); |
||||
|
||||
const app = express(); |
||||
|
||||
//Express behind proxies
|
||||
app.set('trust proxy', true); |
||||
app.disable('x-powered-by'); |
||||
|
||||
//Serving static files
|
||||
app.use(express.static('public')); |
||||
|
||||
// parse application/x-www-form-urlencoded
|
||||
app.use(bodyParser.urlencoded({ limit: '2mb', extended: false })) |
||||
// parse application/json
|
||||
app.use(bodyParser.json({ limit: '2mb' })) |
||||
|
||||
app.get('/', (req, res) => { |
||||
return res.send('Welcome to @filesite/service-3rd'); |
||||
}); |
||||
|
||||
//阿里云相关接口调用
|
||||
app.use('/aliyun', aliyunRouter); |
||||
|
||||
//error handler
|
||||
app.use((err, req, res, next) => { |
||||
if (res.headersSent) { |
||||
return next(err); |
||||
} |
||||
|
||||
console.error('Request error in @filesite/service-3rd: %s', err.stack); |
||||
|
||||
var statusCode = 500; |
||||
if (typeof(err.statusCode) != 'undefined' && err.statusCode) { |
||||
statusCode = err.statusCode; |
||||
} |
||||
return res.status(statusCode).send(err.message); |
||||
}) |
||||
|
||||
// Listen to the App Engine-specified port, or 8080 otherwise
|
||||
const PORT = process.env.PORT || 8081; |
||||
const HOST = '127.0.0.1'; |
||||
app.listen(PORT, HOST, async () => { |
||||
console.log('Server listening on port %s...', PORT); |
||||
}); |
Loading…
Reference in new issue