Browse Source

aliyun sms send done

master
filesite 7 months ago
parent
commit
54cb1beb39
  1. 33
      README.md
  2. 26
      common.js
  3. 4
      conf/config.js
  4. 5
      package.json
  5. 70
      router_aliyun.js
  6. 52
      server.js
  7. 31
      test/aliyun.test.js

33
README.md

@ -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 );
```

26
common.js

@ -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;

4
conf/config.js

@ -13,7 +13,6 @@ exports.getCustomConfigs = async function(configFile) { @@ -13,7 +13,6 @@ exports.getCustomConfigs = async function(configFile) {
let data = null;
let customConfigFile = resolve(configFile);
console.log(customConfigFile);
if (fs.existsSync(customConfigFile)) {
try {
const contents = await readFile(customConfigFile, { encoding: 'utf8' });
@ -29,6 +28,9 @@ exports.getCustomConfigs = async function(configFile) { @@ -29,6 +28,9 @@ exports.getCustomConfigs = async function(configFile) {
};
exports.default = {
"secret": "Api调用的密钥",
//阿里云API调用配置
"ALIBABA_CLOUD_ACCESS_KEY_ID": myAccessKey,
"ALIBABA_CLOUD_ACCESS_KEY_SECRET": myAccessSecret,
};

5
package.json

@ -12,6 +12,9 @@ @@ -12,6 +12,9 @@
"node": ">=8.x"
},
"dependencies": {
"@alicloud/dysmsapi20170525": "^2.0.24"
"@alicloud/dysmsapi20170525": "^2.0.24",
"express": "^4.18.2",
"md5": "^2.3.0",
"axios": "^1.3.3"
}
}

70
router_aliyun.js

@ -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;

52
server.js

@ -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);
});

31
test/aliyun.test.js

@ -2,10 +2,17 @@ @@ -2,10 +2,17 @@
const test = require('node:test');
const assert = require('node:assert');
const axios = require('axios');
const {default: common} = require('../common.js');
const {default: aliyunSmsClient} = require('../aliyunSmsClient');
const {default: defaultConfig, getCustomConfigs: getCustomConfigs} = require('../conf/config');
const axiosConfig = {
timeout: 5000,
proxy: false
};
test('Custom config load test', async (t) => {
console.log('Config data', defaultConfig);
assert.equal(defaultConfig.ALIBABA_CLOUD_ACCESS_KEY_ID, '你的AccessKey ID');
@ -21,6 +28,7 @@ test('AliyunSmsClient test', async (t) => { @@ -21,6 +28,7 @@ test('AliyunSmsClient test', async (t) => {
assert.ok(client);
/*
let signName = 'Ta荐',
templateCode = 'SMS_465915662',
templateParam = '{"code":"2345"}',
@ -29,4 +37,27 @@ test('AliyunSmsClient test', async (t) => { @@ -29,4 +37,27 @@ test('AliyunSmsClient test', async (t) => {
let sended = await aliyunSmsClient.send(myConfig, signName, templateCode, templateParam, phoneNumber);
assert.equal(sended, true);
*/
});
test('Aliyun api test', async (t) => {
let myConfig = await getCustomConfigs('./conf/custom_config.json');
let api = 'http://127.0.0.1:8081/aliyun/sendverifycode';
let params = {
phoneNumber: '13168946847',
codeNumber: '8866',
action: 'register'
};
let sign = common.sign(params, myConfig.secret);
assert.ok(myConfig);
assert.ok(sign);
params.sign = sign;
const response = await axios.post(api, params, axiosConfig);
console.log(response.data);
assert.equal(response.status, 200);
assert.equal(response.data.code, 1);
});
Loading…
Cancel
Save