短信支持亚马逊云

This commit is contained in:
cool 2023-12-05 19:54:37 +08:00
parent 12e6b9c50f
commit d15ae19f33
12 changed files with 395 additions and 270 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "@cool-midway/core", "name": "@cool-midway/core",
"version": "7.0.2", "version": "7.0.3",
"description": "", "description": "",
"main": "dist/index.js", "main": "dist/index.js",
"typings": "index.d.ts", "typings": "index.d.ts",

View File

@ -344,11 +344,34 @@ export interface CoolSmsConfig {
/** /**
* *
*/ */
tx: CoolTxConfig; tx: CoolSmsTxConfig;
/** /**
* *
*/ */
yp: CoolYpConfig; yp: CoolSmsYpConfig;
/**
* aws短信配置
*/
aws: CoolSmsAwsConfig;
}
export interface CoolSmsAwsConfig {
/**
*
*/
region: string;
/**
* accessKeyId
*/
accessKeyId: string;
/**
* secretAccessKey
*/
secretAccessKey: string;
/**
*
*/
extend?: any;
} }
/** /**
@ -376,7 +399,7 @@ export interface CoolSmsAliConfig {
/** /**
* *
*/ */
export interface CoolTxConfig { export interface CoolSmsTxConfig {
/** /**
* ID * ID
*/ */
@ -402,7 +425,7 @@ export interface CoolTxConfig {
/** /**
* *
*/ */
export interface CoolYpConfig { export interface CoolSmsYpConfig {
/** /**
* apikey * apikey
*/ */

View File

@ -1,6 +1,6 @@
{ {
"name": "@cool-midway/core", "name": "@cool-midway/core",
"version": "7.0.2", "version": "7.0.3",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"typings": "index.d.ts", "typings": "index.d.ts",

View File

@ -1,6 +1,6 @@
{ {
"name": "@cool-midway/sms", "name": "@cool-midway/sms",
"version": "7.0.0", "version": "7.0.1",
"description": "cool-js.com 短信", "description": "cool-js.com 短信",
"main": "dist/index.js", "main": "dist/index.js",
"typings": "index.d.ts", "typings": "index.d.ts",
@ -35,15 +35,16 @@
"@midwayjs/mock": "^3.9.0", "@midwayjs/mock": "^3.9.0",
"@types/jest": "^29.2.5", "@types/jest": "^29.2.5",
"@types/node": "^18.11.18", "@types/node": "^18.11.18",
"axios": "^1.5.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"jest": "^29.3.1", "jest": "^29.3.1",
"mwts": "^1.3.0", "mwts": "^1.3.0",
"ts-jest": "^29.0.3", "ts-jest": "^29.0.3",
"axios": "^1.5.0",
"typescript": "^4.9.4" "typescript": "^4.9.4"
}, },
"dependencies": { "dependencies": {
"@alicloud/pop-core": "^1.7.13", "@alicloud/pop-core": "^1.7.13",
"@aws-sdk/client-sns": "^3.465.0",
"tencentcloud-sdk-nodejs": "^4.0.607" "tencentcloud-sdk-nodejs": "^4.0.607"
} }
} }

View File

@ -1,5 +1,5 @@
import * as Core from '@alicloud/pop-core'; import * as Core from '@alicloud/pop-core';
import { Config, Provide } from "@midwayjs/core"; import { Config, Provide } from '@midwayjs/core';
import { CoolSmsAliConfig } from './interface'; import { CoolSmsAliConfig } from './interface';
import { CoolCommException } from '@cool-midway/core'; import { CoolCommException } from '@cool-midway/core';
@ -8,57 +8,61 @@ import { CoolCommException } from '@cool-midway/core';
*/ */
@Provide() @Provide()
export class SmsAli { export class SmsAli {
@Config('cool.sms.ali') @Config('cool.sms.ali')
config: CoolSmsAliConfig; config: CoolSmsAliConfig;
/** /**
* *
* @param config * @param config
*/ */
setConfig(config: CoolSmsAliConfig) { setConfig(config: CoolSmsAliConfig) {
this.config = config; this.config = config;
} }
/** /**
* *
* @param phone * @param phone
* @param params * @param params
* @param config signName template * @param config signName template
* @returns * @returns
*/ */
async send(phone, params: { async send(
[key: string]: string; phone,
}, config?: { params: {
signName: string; [key: string]: string;
template: string; },
}) { config?: {
const { accessKeyId, accessKeySecret } = this.config; signName: string;
if (!accessKeyId || !accessKeyId) { template: string;
throw new CoolCommException('请配置阿里云短信');
}
if (!config) {
config = {
signName: this.config.signName,
template: this.config.template,
};
}
const client = new Core({
accessKeyId,
accessKeySecret,
endpoint: 'https://dysmsapi.aliyuncs.com',
// endpoint: 'https://cs.cn-hangzhou.aliyuncs.com',
apiVersion: '2017-05-25',
// apiVersion: '2018-04-18',
});
const data = {
RegionId: 'cn-shanghai',
PhoneNumbers: phone,
signName: config.signName,
templateCode: config.template,
TemplateParam: JSON.stringify(params),
};
return await client.request('SendSms', data, {
method: 'POST',
});
} }
} ) {
const { accessKeyId, accessKeySecret } = this.config;
if (!accessKeyId || !accessKeyId) {
throw new CoolCommException('请配置阿里云短信');
}
if (!config) {
config = {
signName: this.config.signName,
template: this.config.template,
};
}
const client = new Core({
accessKeyId,
accessKeySecret,
endpoint: 'https://dysmsapi.aliyuncs.com',
// endpoint: 'https://cs.cn-hangzhou.aliyuncs.com',
apiVersion: '2017-05-25',
// apiVersion: '2018-04-18',
});
const data = {
RegionId: 'cn-shanghai',
PhoneNumbers: phone,
signName: config.signName,
templateCode: config.template,
TemplateParam: JSON.stringify(params),
};
return await client.request('SendSms', data, {
method: 'POST',
});
}
}

50
sms/src/aws.ts Normal file
View File

@ -0,0 +1,50 @@
import { Config, Provide } from '@midwayjs/core';
import { CoolSmsAwsConfig } from './interface';
import { CoolCommException } from '@cool-midway/core';
import { SNSClient, PublishCommand } from '@aws-sdk/client-sns';
/**
*
*/
@Provide()
export class SmsAws {
@Config('cool.sms.aws')
config: CoolSmsAwsConfig;
/**
*
* @param config
*/
setConfig(config: CoolSmsAwsConfig) {
this.config = config;
}
/**
*
* @param phone
* @param params
* @returns
*/
async send(phone: string, content: string) {
const { region, accessKeyId, secretAccessKey, extend = {} } = this.config;
if (!region || !accessKeyId || !secretAccessKey) {
throw new CoolCommException('请配置AWS短信');
}
// 配置 AWS
const client = new SNSClient({
region, // 例如 'us-east-1'
credentials: {
accessKeyId,
secretAccessKey,
},
...extend,
});
const data = {
Message: content,
PhoneNumber: phone,
};
const result = await client.send(new PublishCommand(data));
return result;
}
}

View File

@ -5,5 +5,6 @@ export * from './interface';
export * from './ali'; export * from './ali';
export * from './yp'; export * from './yp';
export * from './tx'; export * from './tx';
export * from './aws';
export * from './sms'; export * from './sms';

View File

@ -6,11 +6,34 @@ export interface CoolSmsConfig {
/** /**
* *
*/ */
tx: CoolTxConfig; tx: CoolSmsTxConfig;
/** /**
* *
*/ */
yp: CoolYpConfig; yp: CoolSmsYpConfig;
/**
* aws短信配置
*/
aws: CoolSmsAwsConfig;
}
export interface CoolSmsAwsConfig {
/**
*
*/
region: string;
/**
* accessKeyId
*/
accessKeyId: string;
/**
* secretAccessKey
*/
secretAccessKey: string;
/**
*
*/
extend?: any;
} }
/** /**
@ -38,7 +61,7 @@ export interface CoolSmsAliConfig {
/** /**
* *
*/ */
export interface CoolTxConfig { export interface CoolSmsTxConfig {
/** /**
* ID * ID
*/ */
@ -64,7 +87,7 @@ export interface CoolTxConfig {
/** /**
* *
*/ */
export interface CoolYpConfig { export interface CoolSmsYpConfig {
/** /**
* apikey * apikey
*/ */

View File

@ -1,6 +1,6 @@
{ {
"name": "@cool-midway/sms", "name": "@cool-midway/sms",
"version": "7.0.0", "version": "7.0.1",
"description": "cool-js.com 短信", "description": "cool-js.com 短信",
"main": "index.js", "main": "index.js",
"typings": "index.d.ts", "typings": "index.d.ts",
@ -44,6 +44,7 @@
}, },
"dependencies": { "dependencies": {
"@alicloud/pop-core": "^1.7.13", "@alicloud/pop-core": "^1.7.13",
"@aws-sdk/client-sns": "^3.465.0",
"tencentcloud-sdk-nodejs": "^4.0.607" "tencentcloud-sdk-nodejs": "^4.0.607"
} }
} }

View File

@ -1,83 +1,97 @@
import { Config, Inject, Provide } from "@midwayjs/core"; import { Config, Inject, Provide } from '@midwayjs/core';
import { SmsYp } from "./yp"; import { SmsYp } from './yp';
import { SmsAli } from "./ali"; import { SmsAli } from './ali';
import { SmsTx } from "./tx"; import { SmsTx } from './tx';
import { CoolSmsConfig } from "./interface"; import { CoolSmsConfig } from './interface';
import { SmsAws } from './aws';
@Provide() @Provide()
export class CoolSms { export class CoolSms {
@Inject() @Inject()
smsYp: SmsYp smsYp: SmsYp;
@Inject() @Inject()
smsAli: SmsAli smsAli: SmsAli;
@Inject() @Inject()
smsTx: SmsTx smsTx: SmsTx;
@Config('cool.sms') @Inject()
config: CoolSmsConfig; smsAws: SmsAws;
/** @Config('cool.sms')
* config: CoolSmsConfig;
* @param config
*/ /**
setConfig(config: CoolSmsConfig) { *
this.smsYp.setConfig(config.yp); * @param config
this.smsAli.setConfig(config.ali); */
this.smsTx.setConfig(config.tx); setConfig(config: CoolSmsConfig) {
this.config = config; this.smsYp.setConfig(config.yp);
this.smsAli.setConfig(config.ali);
this.smsTx.setConfig(config.tx);
this.config = config;
}
/**
* code
* @param phone
* @param config
*/
async sendCode(
phone,
config?: {
signName: string;
template: string;
} }
) {
const code = this.generateNumber();
let params = {
code,
};
await this.send(phone, this.config.tx ? [code] : params, config);
return code;
}
/** /**
* code *
* @param phone * @param phone
* @param config * @param params
*/ * @param config
async sendCode(phone, config?: { * @returns
signName: string; */
template: string; async send(
}) { phone: string,
const code = this.generateNumber(); params: any,
let params = { config?: {
code signName: string;
} template: string;
await this.send(phone, this.config.tx ? [code] : params, config)
return code;
} }
) {
if (this.config.ali) {
return await this.smsAli.send(phone, params, config);
}
if (this.config.tx) {
return await this.smsTx.send(phone, params, config);
}
if (this.config.yp) {
return await this.smsYp.send(phone, params, config);
}
if (this.config.aws) {
return await this.smsAws.send(phone, params);
}
return true;
}
/** /**
* *
* @param phone */
* @param params generateNumber(digits = 4) {
* @param config if (digits <= 0) {
* @returns return 0;
*/
async send(phone: string, params: any, config?: {
signName: string;
template: string;
}) {
if (this.config.ali) {
return await this.smsAli.send(phone, params, config);
}
if (this.config.tx) {
return await this.smsTx.send(phone, params, config);
}
if (this.config.yp) {
return await this.smsYp.send(phone, params, config);
}
return true;
} }
const min = Math.pow(10, digits - 1);
/** const max = Math.pow(10, digits) - 1;
* return Math.floor(Math.random() * (max - min + 1)) + min;
*/ }
generateNumber(digits = 4) { }
if (digits <= 0) {
return 0;
}
const min = Math.pow(10, digits - 1);
const max = Math.pow(10, digits) - 1;
return Math.floor(Math.random() * (max - min + 1)) + min;
}
}

View File

@ -1,70 +1,74 @@
import { Config, Provide } from "@midwayjs/core"; import { Config, Provide } from '@midwayjs/core';
import { CoolTxConfig } from './interface'; import { CoolSmsTxConfig } from './interface';
import * as tencentcloud from "tencentcloud-sdk-nodejs"; import * as tencentcloud from 'tencentcloud-sdk-nodejs';
import { CoolCommException } from "@cool-midway/core"; import { CoolCommException } from '@cool-midway/core';
/** /**
* *
*/ */
@Provide() @Provide()
export class SmsTx { export class SmsTx {
@Config('cool.sms.tx') @Config('cool.sms.tx')
config: CoolTxConfig; config: CoolSmsTxConfig;
/** /**
* *
* @param config * @param config
*/ */
setConfig(config: CoolTxConfig) { setConfig(config: CoolSmsTxConfig) {
this.config = config; this.config = config;
}
/**
*
* @param phone
* @param params
* @param config signName template
* @returns
*/
async send(
phone: string,
params: string[],
config?: {
signName: string;
template: string;
} }
) {
/** const { appId, secretId, secretKey } = this.config;
* if (!config) {
* @param phone config = {
* @param params signName: this.config.signName,
* @param config signName template template: this.config.template,
* @returns };
*/
async send(phone: string, params: string[], config?: {
signName: string;
template: string;
}) {
const { appId, secretId, secretKey } = this.config;
if(!config) {
config = {
signName: this.config.signName,
template: this.config.template,
};
}
if(!appId || !secretId || !secretKey) {
throw new CoolCommException('请配置腾讯云短信');
}
const smsClient = tencentcloud.sms.v20210111.Client;
const client = new smsClient({
credential: {
secretId,
secretKey,
},
region: 'ap-guangzhou',
profile: {
signMethod: 'HmacSHA256',
httpProfile: {
reqMethod: 'POST',
reqTimeout: 30,
endpoint: 'sms.tencentcloudapi.com',
},
},
});
const data = {
SmsSdkAppId: appId,
SignName: config.signName,
TemplateId: config.template,
TemplateParamSet: params,
PhoneNumberSet: [`+86${phone}`],
};
return client.SendSms(data);
} }
} if (!appId || !secretId || !secretKey) {
throw new CoolCommException('请配置腾讯云短信');
}
const smsClient = tencentcloud.sms.v20210111.Client;
const client = new smsClient({
credential: {
secretId,
secretKey,
},
region: 'ap-guangzhou',
profile: {
signMethod: 'HmacSHA256',
httpProfile: {
reqMethod: 'POST',
reqTimeout: 30,
endpoint: 'sms.tencentcloudapi.com',
},
},
});
const data = {
SmsSdkAppId: appId,
SignName: config.signName,
TemplateId: config.template,
TemplateParamSet: params,
PhoneNumberSet: [`+86${phone}`],
};
return client.SendSms(data);
}
}

View File

@ -1,6 +1,6 @@
import { Config, Provide } from "@midwayjs/core"; import { Config, Provide } from '@midwayjs/core';
import { CoolYpConfig } from "./interface"; import { CoolSmsYpConfig } from './interface';
import { CoolCommException } from "@cool-midway/core"; import { CoolCommException } from '@cool-midway/core';
import axios from 'axios'; import axios from 'axios';
/** /**
@ -8,79 +8,83 @@ import axios from 'axios';
*/ */
@Provide() @Provide()
export class SmsYp { export class SmsYp {
@Config('cool.sms.yp') @Config('cool.sms.yp')
config: CoolYpConfig; config: CoolSmsYpConfig;
/** /**
* *
* @param config * @param config
*/ */
setConfig(config: CoolYpConfig) { setConfig(config: CoolSmsYpConfig) {
this.config = config; this.config = config;
}
/**
*
* @param phones ["+8612345678901"]
* @param params
* @param config signName template
* @returns
*/
async send(
phones: string,
params: {
[key: string]: string;
},
config?: {
signName: string;
template: string;
}
) {
const { apikey } = this.config;
if (!config) {
config = {
signName: this.config.signName,
template: this.config.template,
};
}
if (!apikey) {
throw new CoolCommException('请配置云片短信');
} }
/** const headers = {
* Accept: 'application/json;charset=utf-8',
* @param phones ["+8612345678901"] 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
* @param params };
* @param config signName template const data = {
* @returns apikey: apikey,
*/ mobile: phones,
async send(phones: string, params: { tpl_id: config.template,
[key: string]: string; tpl_value: this.smsTplValue(params),
}, config?: { };
signName: string; const result = await axios.post(
template: string; 'https://sms.yunpian.com/v2/sms/tpl_single_send.json',
}) { data,
const { apikey } = this.config; { headers }
if (!config) { );
config = { if (result.data.code === 0) {
signName: this.config.signName, return true;
template: this.config.template, }
}; return false;
} }
if (!apikey) {
throw new CoolCommException('请配置云片短信');
}
const headers = { /**
Accept: 'application/json;charset=utf-8', *
'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8', * @param obj
}; * @returns
const data = { */
apikey: apikey, protected smsTplValue(obj) {
mobile: phones, const urlParams = [];
tpl_id: config.template,
tpl_value: this.smsTplValue(params), for (let key in obj) {
}; // eslint-disable-next-line no-prototype-builtins
const result = await axios.post( if (obj.hasOwnProperty(key)) {
'https://sms.yunpian.com/v2/sms/tpl_single_send.json', const encodedKey = encodeURIComponent(`#${key}#`);
data, const encodedValue = encodeURIComponent(obj[key]);
{ headers } urlParams.push(`${encodedKey}=${encodedValue}`);
); }
if (result.data.code === 0) {
return true;
}
return false;
} }
/** return urlParams.join('&');
* }
* @param obj }
* @returns
*/
protected smsTplValue(obj) {
const urlParams = [];
for (let key in obj) {
// eslint-disable-next-line no-prototype-builtins
if (obj.hasOwnProperty(key)) {
const encodedKey = encodeURIComponent(`#${key}#`);
const encodedValue = encodeURIComponent(obj[key]);
urlParams.push(`${encodedKey}=${encodedValue}`);
}
}
return urlParams.join('&');
}
}