天翼云短信

This commit is contained in:
wkj 2024-01-05 16:24:20 +08:00
parent 98cdc5f39e
commit 54ae64afc1
53 changed files with 1077 additions and 206 deletions

6
es/SmsSdk.d.ts vendored
View File

@ -1,11 +1,13 @@
import { TencentSmsInstance } from './service/tencent/Sms';
import { AliSmsInstance } from './service/ali/Sms';
import { CTYunSmsInstance } from './service/ctyun/Sms';
declare class SmsSDK {
tencentMap: Record<string, TencentSmsInstance>;
aliMap: Record<string, AliSmsInstance>;
ctyunMap: Record<string, CTYunSmsInstance>;
constructor();
getInstance(origin: 'ali' | 'tencent', accessKey: string, accessSecret: string, endpoint: string, region?: string, apiVersion?: string): TencentSmsInstance | AliSmsInstance;
getInstance(origin: 'ali' | 'tencent' | 'ctyun', accessKey: string, accessSecret: string, endpoint: string, region?: string, apiVersion?: string): TencentSmsInstance | AliSmsInstance | CTYunSmsInstance;
}
declare const SDK: SmsSDK;
export default SDK;
export { TencentSmsInstance, AliSmsInstance };
export { TencentSmsInstance, AliSmsInstance, CTYunSmsInstance };

View File

@ -1,12 +1,15 @@
import { TencentSmsInstance } from './service/tencent/Sms';
import { AliSmsInstance } from './service/ali/Sms';
import { CTYunSmsInstance } from './service/ctyun/Sms';
import { assert } from 'oak-domain/lib/utils/assert';
class SmsSDK {
tencentMap;
aliMap;
ctyunMap;
constructor() {
this.tencentMap = {};
this.aliMap = {};
this.ctyunMap = {};
}
getInstance(origin, accessKey, accessSecret, endpoint, region, apiVersion //阿里云独有
) {
@ -33,6 +36,16 @@ class SmsSDK {
});
return instance;
}
else if (origin === 'ctyun') {
if (this.ctyunMap[accessKey]) {
return this.ctyunMap[accessKey];
}
const instance = new CTYunSmsInstance(accessKey, accessSecret, endpoint);
Object.assign(this.ctyunMap, {
[accessKey]: instance,
});
return instance;
}
else {
assert(false, `${origin} not implemented`);
}
@ -40,4 +53,4 @@ class SmsSDK {
}
const SDK = new SmsSDK();
export default SDK;
export { TencentSmsInstance, AliSmsInstance };
export { TencentSmsInstance, AliSmsInstance, CTYunSmsInstance };

4
es/index.d.ts vendored
View File

@ -1,8 +1,8 @@
import WechatSDK, { WechatMpInstance, WechatPublicInstance, WechatWebInstance } from './WechatSDK';
import AmapSDK from './AmapSDK';
import QiniuSDK, { QiniuCloudInstance } from './QiniuSDK';
import SmsSdk, { TencentSmsInstance, AliSmsInstance } from './SmsSdk';
import SmsSdk, { TencentSmsInstance, AliSmsInstance, CTYunSmsInstance } from './SmsSdk';
import CTYunSDk, { CTYunInstance } from './CTYunSDK';
export * from './service/amap/Amap';
export { AmapSDK, QiniuSDK, WechatSDK, CTYunSDk, CTYunInstance, WechatMpInstance, WechatPublicInstance, WechatWebInstance, QiniuCloudInstance, SmsSdk, TencentSmsInstance, AliSmsInstance, };
export { AmapSDK, QiniuSDK, WechatSDK, CTYunSDk, CTYunInstance, WechatMpInstance, WechatPublicInstance, WechatWebInstance, QiniuCloudInstance, SmsSdk, TencentSmsInstance, AliSmsInstance, CTYunSmsInstance, };
export * from './types';

View File

@ -1,8 +1,8 @@
import WechatSDK, { WechatMpInstance, WechatPublicInstance, WechatWebInstance } from './WechatSDK';
import AmapSDK from './AmapSDK';
import QiniuSDK, { QiniuCloudInstance } from './QiniuSDK';
import SmsSdk, { TencentSmsInstance, AliSmsInstance } from './SmsSdk';
import SmsSdk, { TencentSmsInstance, AliSmsInstance, CTYunSmsInstance, } from './SmsSdk';
import CTYunSDk, { CTYunInstance } from './CTYunSDK';
export * from './service/amap/Amap';
export { AmapSDK, QiniuSDK, WechatSDK, CTYunSDk, CTYunInstance, WechatMpInstance, WechatPublicInstance, WechatWebInstance, QiniuCloudInstance, SmsSdk, TencentSmsInstance, AliSmsInstance, };
export { AmapSDK, QiniuSDK, WechatSDK, CTYunSDk, CTYunInstance, WechatMpInstance, WechatPublicInstance, WechatWebInstance, QiniuCloudInstance, SmsSdk, TencentSmsInstance, AliSmsInstance, CTYunSmsInstance, };
export * from './types';

View File

@ -14,5 +14,6 @@ export declare class AliSmsInstance {
client: Dysmsapi20170525;
constructor(accessKeyId: string, accessKeySecret: string, endpoint?: string);
sendSms(params: SendSmsRequest): Promise<$Dysmsapi20170525.SendSmsResponseBody>;
syncTemplate(params: $Dysmsapi20170525.QuerySmsTemplateListRequest): Promise<$Dysmsapi20170525.QuerySmsTemplateListResponseBody>;
}
export {};

View File

@ -22,7 +22,9 @@ export class AliSmsInstance {
async sendSms(params) {
const { phoneNumbers, templateParam = {}, templateCode, signName, } = params;
let sendSmsRequest = new $Dysmsapi20170525.SendSmsRequest({
phoneNumbers: (phoneNumbers instanceof Array) ? phoneNumbers.join(',') : phoneNumbers,
phoneNumbers: phoneNumbers instanceof Array
? phoneNumbers.join(',')
: phoneNumbers,
templateParam: JSON.stringify(templateParam),
templateCode: templateCode,
signName: signName,
@ -31,7 +33,7 @@ export class AliSmsInstance {
const data = await this.client.sendSmsWithOptions(sendSmsRequest, new $Util.RuntimeOptions({}));
const { statusCode, body } = data;
if (statusCode != 200) {
throw new Error(`ali.sendSms接口返回状态码错误${statusCode}`);
throw new Error(`sendSms接口返回状态码错误${statusCode}`);
}
return body;
}
@ -39,4 +41,22 @@ export class AliSmsInstance {
throw error;
}
}
async syncTemplate(params) {
const { PageIndex, PageSize } = params;
try {
let querySmsTemplateListRequest = new $Dysmsapi20170525.QuerySmsTemplateListRequest({
PageIndex,
PageSize,
});
const result = await this.client.querySmsTemplateListWithOptions(querySmsTemplateListRequest, new $Util.RuntimeOptions({}));
const { statusCode, body } = result;
if (statusCode != 200) {
throw new Error(`syncTemplate接口返回状态码错误${statusCode}`);
}
return body;
}
catch (err) {
throw err;
}
}
}

View File

@ -13,12 +13,12 @@ type SendSmsResponse = {
RequestId: string;
};
export declare class AliSmsInstance {
secretId: string;
secretKey: string;
accessKeyId: string;
accessKeySecret: string;
region: string;
endpoint: string;
client: any;
constructor(secretId: string, secretKey: string, region: string, endpoint: string);
constructor(accessKeyId: string, accessKeySecret: string, region: string, endpoint: string);
sendSms(params: SendSmsRequest): Promise<SendSmsResponse>;
}
export {};

View File

@ -1,26 +1,14 @@
export class AliSmsInstance {
secretId;
secretKey;
accessKeyId;
accessKeySecret;
region;
endpoint;
client;
constructor(secretId, secretKey, region, endpoint) {
this.secretId = secretId;
this.secretKey = secretKey;
constructor(accessKeyId, accessKeySecret, region, endpoint) {
this.accessKeyId = accessKeyId;
this.accessKeySecret = accessKeySecret;
this.region = region;
this.endpoint = endpoint;
const clientConfig = {
credential: {
secretId: this.secretId,
secretKey: this.secretKey,
},
region: this.region,
profile: {
httpProfile: {
endpoint: this.endpoint || 'dysmsapi.aliyuncs.com',
},
},
};
}
async sendSms(params) {
console.log('mp走不到这里');

View File

@ -13,12 +13,12 @@ type SendSmsResponse = {
RequestId: string;
};
export declare class AliSmsInstance {
secretId: string;
secretKey: string;
accessKeyId: string;
accessKeySecret: string;
region: string;
endpoint: string;
client: any;
constructor(secretId: string, secretKey: string, region: string, endpoint: string);
constructor(accessKeyId: string, accessKeySecret: string, region: string, endpoint: string);
sendSms(params: SendSmsRequest): Promise<SendSmsResponse>;
}
export {};

View File

@ -1,26 +1,14 @@
export class AliSmsInstance {
secretId;
secretKey;
accessKeyId;
accessKeySecret;
region;
endpoint;
client;
constructor(secretId, secretKey, region, endpoint) {
this.secretId = secretId;
this.secretKey = secretKey;
constructor(accessKeyId, accessKeySecret, region, endpoint) {
this.accessKeyId = accessKeyId;
this.accessKeySecret = accessKeySecret;
this.region = region;
this.endpoint = endpoint;
const clientConfig = {
credential: {
secretId: this.secretId,
secretKey: this.secretKey,
},
region: this.region,
profile: {
httpProfile: {
endpoint: this.endpoint || 'dysmsapi.aliyuncs.com',
},
},
};
}
async sendSms(params) {
console.log('react-native走不到这里[ali/sms.native');

View File

@ -13,12 +13,12 @@ type SendSmsResponse = {
RequestId: string;
};
export declare class AliSmsInstance {
secretId: string;
secretKey: string;
accessKeyId: string;
accessKeySecret: string;
region: string;
endpoint: string;
client: any;
constructor(secretId: string, secretKey: string, region: string, endpoint: string);
constructor(accessKeyId: string, accessKeySecret: string, region: string, endpoint: string);
sendSms(params: SendSmsRequest): Promise<SendSmsResponse>;
}
export {};

View File

@ -1,26 +1,14 @@
export class AliSmsInstance {
secretId;
secretKey;
accessKeyId;
accessKeySecret;
region;
endpoint;
client;
constructor(secretId, secretKey, region, endpoint) {
this.secretId = secretId;
this.secretKey = secretKey;
constructor(accessKeyId, accessKeySecret, region, endpoint) {
this.accessKeyId = accessKeyId;
this.accessKeySecret = accessKeySecret;
this.region = region;
this.endpoint = endpoint;
const clientConfig = {
credential: {
secretId: this.secretId,
secretKey: this.secretKey,
},
region: this.region,
profile: {
httpProfile: {
endpoint: this.endpoint || 'dysmsapi.aliyuncs.com',
},
},
};
}
async sendSms(params) {
console.log('web走不到这里');

48
es/service/ctyun/Sms.d.ts vendored Normal file
View File

@ -0,0 +1,48 @@
type SendSmsRequest = {
phoneNumber: string;
templateCode: string;
signName: string;
templateParam?: Record<string, string>;
extendCode?: string;
sessionId?: string;
};
type SendSmsResponse = {
code: 'OK' | string;
message: string;
requestId: string;
};
type DescribeSmsTemplateListRequest = {
pageIndex: number;
pageSize: number;
};
type DescribeSmsTemplateListResponse = {
code: 'OK' | string;
message: string;
requestId: string;
total: number;
data: {
reason: string;
createTime: Date;
updateTime: Date;
example: string;
remark: string;
status: 0 | 1 | 2;
templateCode: string;
templateType: 1 | 2;
templateName: string;
templateContent: string;
templateStatus: 0 | 1 | 2;
}[];
};
export declare class CTYunSmsInstance {
accessKey: string;
securityKey: string;
endpoint: string;
constructor(accessKey: string, securityKey: string, endpoint: string);
sendSms(params: SendSmsRequest): Promise<SendSmsResponse>;
syncTemplate(params: DescribeSmsTemplateListRequest): Promise<DescribeSmsTemplateListResponse>;
private access;
private hmacsha256;
private sha256;
}
export {};

117
es/service/ctyun/Sms.js Normal file
View File

@ -0,0 +1,117 @@
import crypto from 'crypto';
import { Buffer } from 'buffer';
import { OakNetworkException, } from 'oak-domain/lib/types/Exception';
function format(date, layout) {
function pad(num, digit) {
const d = digit || 2;
let result = num.toString();
while (result.length < d) {
result = '0' + result;
}
return result;
}
const d = new Date(date);
const year = d.getFullYear();
const month = d.getMonth() + 1;
const day = d.getDate();
const hour = d.getHours();
const minute = d.getMinutes();
const second = d.getSeconds();
const millisecond = d.getMilliseconds();
let result = layout || 'YYYYMMDDTHHmmss';
result = result
.replace(/YYYY/g, year.toString())
.replace(/MM/g, pad(month))
.replace(/DD/g, pad(day))
.replace(/HH/g, pad(hour))
.replace(/mm/g, pad(minute))
.replace(/ss/g, pad(second))
.replace(/SSS/g, pad(millisecond, 3));
return result;
}
export class CTYunSmsInstance {
accessKey;
securityKey;
endpoint;
constructor(accessKey, securityKey, endpoint) {
this.accessKey = accessKey;
this.securityKey = securityKey;
this.endpoint = endpoint || 'sms-global.ctapi.ctyun.cn';
}
async sendSms(params) {
const { phoneNumber, templateParam = {}, templateCode, signName, } = params;
const sendSmsRequest = {
action: 'SendSms',
phoneNumber,
templateParam: JSON.stringify(templateParam),
templateCode: templateCode,
signName: signName,
};
try {
const data = await this.access(`https://${this.endpoint}/sms/api/v1`, sendSmsRequest);
return data;
}
catch (error) {
throw error;
}
}
async syncTemplate(params) {
const { pageIndex, pageSize } = params;
const request = {
action: 'QuerySmsTemplateList',
pageIndex,
pageSize,
};
try {
const data = await this.access(`https://${this.endpoint}/sms/api/v1`, request);
return data;
}
catch (err) {
throw err;
}
}
async access(url, body, method) {
// SETUP2:构造时间戳
const timestamp = format(new Date(), 'YYYYMMDDTHHmmss') + 'Z';
// SETUP3:构造请求流水号
const requestId = crypto.randomUUID();
// SETUP4:构造待签名字符串
const headerStr = `ctyun-eop-request-id:${requestId}\neop-date:${timestamp}\n\n`;
const calculateContentHash = this.sha256(JSON.stringify(body));
const rawString = `${headerStr}\n${calculateContentHash}`;
// SETUP5:构造签名
const signTime = this.hmacsha256(timestamp, this.securityKey);
const signAK = this.hmacsha256(this.accessKey, Buffer.from(signTime, 'hex'));
const signDate = this.hmacsha256(timestamp.slice(0, 8), Buffer.from(signAK, 'hex'));
const sign = this.hmacsha256(rawString, Buffer.from(signDate, 'hex'));
const signature = Buffer.from(sign, 'hex').toString('base64');
// SETUP:6 构造请求头
const signatureHeader = `${this.accessKey} Headers=ctyun-eop-request-id;eop-date Signature=${signature}`;
const headers = {
'Content-Type': 'application/json',
'eop-date': timestamp,
'Eop-Authorization': signatureHeader,
'ctyun-eop-request-id': requestId,
};
let response;
try {
response = await fetch(url, {
method: method || 'POST',
headers,
body: JSON.stringify(body),
});
}
catch (err) {
// fetch返回异常一定是网络异常
throw new OakNetworkException();
}
return response.json();
}
hmacsha256(data, key) {
const hmac = crypto.createHmac('sha1', key).update(data).digest('hex');
return hmac;
}
sha256(data) {
return crypto.createHash('SHA256').update(data).digest('hex');
}
}

22
es/service/ctyun/Sms.mp.d.ts vendored Normal file
View File

@ -0,0 +1,22 @@
type SendSmsRequest = {
action: 'SendSms' | string;
phoneNumber: string;
templateCode: string;
signName: string;
templateParam?: Record<string, string>;
extendCode?: string;
sessionId?: string;
};
type SendSmsResponse = {
code: 'OK' | string;
message: string;
requestId: string;
};
export declare class CTYunSmsInstance {
accessKey: string;
securityKey: string;
endpoint: string;
constructor(accessKey: string, securityKey: string, endpoint: string);
sendSms(params: SendSmsRequest): Promise<SendSmsResponse>;
}
export {};

View File

@ -0,0 +1,14 @@
export class CTYunSmsInstance {
accessKey;
securityKey;
endpoint;
constructor(accessKey, securityKey, endpoint) {
this.accessKey = accessKey;
this.securityKey = securityKey;
this.endpoint = endpoint;
}
async sendSms(params) {
console.log('mp走不到这里');
return {};
}
}

22
es/service/ctyun/Sms.native.d.ts vendored Normal file
View File

@ -0,0 +1,22 @@
type SendSmsRequest = {
action: 'SendSms' | string;
phoneNumber: string;
templateCode: string;
signName: string;
templateParam?: Record<string, string>;
extendCode?: string;
sessionId?: string;
};
type SendSmsResponse = {
code: 'OK' | string;
message: string;
requestId: string;
};
export declare class CTYunSmsInstance {
accessKey: string;
securityKey: string;
endpoint: string;
constructor(accessKey: string, securityKey: string, endpoint: string);
sendSms(params: SendSmsRequest): Promise<SendSmsResponse>;
}
export {};

View File

@ -0,0 +1,14 @@
export class CTYunSmsInstance {
accessKey;
securityKey;
endpoint;
constructor(accessKey, securityKey, endpoint) {
this.accessKey = accessKey;
this.securityKey = securityKey;
this.endpoint = endpoint;
}
async sendSms(params) {
console.log('react-native走不到这里[ali/sms.native');
return {};
}
}

22
es/service/ctyun/Sms.web.d.ts vendored Normal file
View File

@ -0,0 +1,22 @@
type SendSmsRequest = {
action: 'SendSms' | string;
phoneNumber: string;
templateCode: string;
signName: string;
templateParam?: Record<string, string>;
extendCode?: string;
sessionId?: string;
};
type SendSmsResponse = {
code: 'OK' | string;
message: string;
requestId: string;
};
export declare class CTYunSmsInstance {
accessKey: string;
securityKey: string;
endpoint: string;
constructor(accessKey: string, securityKey: string, endpoint: string);
sendSms(params: SendSmsRequest): Promise<SendSmsResponse>;
}
export {};

View File

@ -0,0 +1,14 @@
export class CTYunSmsInstance {
accessKey;
securityKey;
endpoint;
constructor(accessKey, securityKey, endpoint) {
this.accessKey = accessKey;
this.securityKey = securityKey;
this.endpoint = endpoint;
}
async sendSms(params) {
console.log('web走不到这里');
return {};
}
}

View File

@ -42,7 +42,6 @@ export class TencentSmsInstance {
return result;
}
catch (err) {
console.error(err);
throw err;
}
}

6
lib/SmsSdk.d.ts vendored
View File

@ -1,11 +1,13 @@
import { TencentSmsInstance } from './service/tencent/Sms';
import { AliSmsInstance } from './service/ali/Sms';
import { CTYunSmsInstance } from './service/ctyun/Sms';
declare class SmsSDK {
tencentMap: Record<string, TencentSmsInstance>;
aliMap: Record<string, AliSmsInstance>;
ctyunMap: Record<string, CTYunSmsInstance>;
constructor();
getInstance(origin: 'ali' | 'tencent', accessKey: string, accessSecret: string, endpoint: string, region?: string, apiVersion?: string): TencentSmsInstance | AliSmsInstance;
getInstance(origin: 'ali' | 'tencent' | 'ctyun', accessKey: string, accessSecret: string, endpoint: string, region?: string, apiVersion?: string): TencentSmsInstance | AliSmsInstance | CTYunSmsInstance;
}
declare const SDK: SmsSDK;
export default SDK;
export { TencentSmsInstance, AliSmsInstance };
export { TencentSmsInstance, AliSmsInstance, CTYunSmsInstance };

View File

@ -1,17 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AliSmsInstance = exports.TencentSmsInstance = void 0;
exports.CTYunSmsInstance = exports.AliSmsInstance = exports.TencentSmsInstance = void 0;
const Sms_1 = require("./service/tencent/Sms");
Object.defineProperty(exports, "TencentSmsInstance", { enumerable: true, get: function () { return Sms_1.TencentSmsInstance; } });
const Sms_2 = require("./service/ali/Sms");
Object.defineProperty(exports, "AliSmsInstance", { enumerable: true, get: function () { return Sms_2.AliSmsInstance; } });
const Sms_3 = require("./service/ctyun/Sms");
Object.defineProperty(exports, "CTYunSmsInstance", { enumerable: true, get: function () { return Sms_3.CTYunSmsInstance; } });
const assert_1 = require("oak-domain/lib/utils/assert");
class SmsSDK {
tencentMap;
aliMap;
ctyunMap;
constructor() {
this.tencentMap = {};
this.aliMap = {};
this.ctyunMap = {};
}
getInstance(origin, accessKey, accessSecret, endpoint, region, apiVersion //阿里云独有
) {
@ -38,6 +42,16 @@ class SmsSDK {
});
return instance;
}
else if (origin === 'ctyun') {
if (this.ctyunMap[accessKey]) {
return this.ctyunMap[accessKey];
}
const instance = new Sms_3.CTYunSmsInstance(accessKey, accessSecret, endpoint);
Object.assign(this.ctyunMap, {
[accessKey]: instance,
});
return instance;
}
else {
(0, assert_1.assert)(false, `${origin} not implemented`);
}

4
lib/index.d.ts vendored
View File

@ -1,8 +1,8 @@
import WechatSDK, { WechatMpInstance, WechatPublicInstance, WechatWebInstance } from './WechatSDK';
import AmapSDK from './AmapSDK';
import QiniuSDK, { QiniuCloudInstance } from './QiniuSDK';
import SmsSdk, { TencentSmsInstance, AliSmsInstance } from './SmsSdk';
import SmsSdk, { TencentSmsInstance, AliSmsInstance, CTYunSmsInstance } from './SmsSdk';
import CTYunSDk, { CTYunInstance } from './CTYunSDK';
export * from './service/amap/Amap';
export { AmapSDK, QiniuSDK, WechatSDK, CTYunSDk, CTYunInstance, WechatMpInstance, WechatPublicInstance, WechatWebInstance, QiniuCloudInstance, SmsSdk, TencentSmsInstance, AliSmsInstance, };
export { AmapSDK, QiniuSDK, WechatSDK, CTYunSDk, CTYunInstance, WechatMpInstance, WechatPublicInstance, WechatWebInstance, QiniuCloudInstance, SmsSdk, TencentSmsInstance, AliSmsInstance, CTYunSmsInstance, };
export * from './types';

View File

@ -1,6 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AliSmsInstance = exports.TencentSmsInstance = exports.SmsSdk = exports.QiniuCloudInstance = exports.WechatWebInstance = exports.WechatPublicInstance = exports.WechatMpInstance = exports.CTYunInstance = exports.CTYunSDk = exports.WechatSDK = exports.QiniuSDK = exports.AmapSDK = void 0;
exports.CTYunSmsInstance = exports.AliSmsInstance = exports.TencentSmsInstance = exports.SmsSdk = exports.QiniuCloudInstance = exports.WechatWebInstance = exports.WechatPublicInstance = exports.WechatMpInstance = exports.CTYunInstance = exports.CTYunSDk = exports.WechatSDK = exports.QiniuSDK = exports.AmapSDK = void 0;
const tslib_1 = require("tslib");
const WechatSDK_1 = tslib_1.__importStar(require("./WechatSDK"));
exports.WechatSDK = WechatSDK_1.default;
@ -16,6 +16,7 @@ const SmsSdk_1 = tslib_1.__importStar(require("./SmsSdk"));
exports.SmsSdk = SmsSdk_1.default;
Object.defineProperty(exports, "TencentSmsInstance", { enumerable: true, get: function () { return SmsSdk_1.TencentSmsInstance; } });
Object.defineProperty(exports, "AliSmsInstance", { enumerable: true, get: function () { return SmsSdk_1.AliSmsInstance; } });
Object.defineProperty(exports, "CTYunSmsInstance", { enumerable: true, get: function () { return SmsSdk_1.CTYunSmsInstance; } });
const CTYunSDK_1 = tslib_1.__importStar(require("./CTYunSDK"));
exports.CTYunSDk = CTYunSDK_1.default;
Object.defineProperty(exports, "CTYunInstance", { enumerable: true, get: function () { return CTYunSDK_1.CTYunInstance; } });

View File

@ -14,5 +14,6 @@ export declare class AliSmsInstance {
client: Dysmsapi20170525;
constructor(accessKeyId: string, accessKeySecret: string, endpoint?: string);
sendSms(params: SendSmsRequest): Promise<$Dysmsapi20170525.SendSmsResponseBody>;
syncTemplate(params: $Dysmsapi20170525.QuerySmsTemplateListRequest): Promise<$Dysmsapi20170525.QuerySmsTemplateListResponseBody>;
}
export {};

View File

@ -26,7 +26,9 @@ class AliSmsInstance {
async sendSms(params) {
const { phoneNumbers, templateParam = {}, templateCode, signName, } = params;
let sendSmsRequest = new $Dysmsapi20170525.SendSmsRequest({
phoneNumbers: (phoneNumbers instanceof Array) ? phoneNumbers.join(',') : phoneNumbers,
phoneNumbers: phoneNumbers instanceof Array
? phoneNumbers.join(',')
: phoneNumbers,
templateParam: JSON.stringify(templateParam),
templateCode: templateCode,
signName: signName,
@ -35,7 +37,7 @@ class AliSmsInstance {
const data = await this.client.sendSmsWithOptions(sendSmsRequest, new $Util.RuntimeOptions({}));
const { statusCode, body } = data;
if (statusCode != 200) {
throw new Error(`ali.sendSms接口返回状态码错误${statusCode}`);
throw new Error(`sendSms接口返回状态码错误${statusCode}`);
}
return body;
}
@ -43,5 +45,23 @@ class AliSmsInstance {
throw error;
}
}
async syncTemplate(params) {
const { PageIndex, PageSize } = params;
try {
let querySmsTemplateListRequest = new $Dysmsapi20170525.QuerySmsTemplateListRequest({
PageIndex,
PageSize,
});
const result = await this.client.querySmsTemplateListWithOptions(querySmsTemplateListRequest, new $Util.RuntimeOptions({}));
const { statusCode, body } = result;
if (statusCode != 200) {
throw new Error(`syncTemplate接口返回状态码错误${statusCode}`);
}
return body;
}
catch (err) {
throw err;
}
}
}
exports.AliSmsInstance = AliSmsInstance;

View File

@ -13,12 +13,12 @@ type SendSmsResponse = {
RequestId: string;
};
export declare class AliSmsInstance {
secretId: string;
secretKey: string;
accessKeyId: string;
accessKeySecret: string;
region: string;
endpoint: string;
client: any;
constructor(secretId: string, secretKey: string, region: string, endpoint: string);
constructor(accessKeyId: string, accessKeySecret: string, region: string, endpoint: string);
sendSms(params: SendSmsRequest): Promise<SendSmsResponse>;
}
export {};

View File

@ -2,28 +2,16 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.AliSmsInstance = void 0;
class AliSmsInstance {
secretId;
secretKey;
accessKeyId;
accessKeySecret;
region;
endpoint;
client;
constructor(secretId, secretKey, region, endpoint) {
this.secretId = secretId;
this.secretKey = secretKey;
constructor(accessKeyId, accessKeySecret, region, endpoint) {
this.accessKeyId = accessKeyId;
this.accessKeySecret = accessKeySecret;
this.region = region;
this.endpoint = endpoint;
const clientConfig = {
credential: {
secretId: this.secretId,
secretKey: this.secretKey,
},
region: this.region,
profile: {
httpProfile: {
endpoint: this.endpoint || 'dysmsapi.aliyuncs.com',
},
},
};
}
async sendSms(params) {
console.log('mp走不到这里');

View File

@ -13,12 +13,12 @@ type SendSmsResponse = {
RequestId: string;
};
export declare class AliSmsInstance {
secretId: string;
secretKey: string;
accessKeyId: string;
accessKeySecret: string;
region: string;
endpoint: string;
client: any;
constructor(secretId: string, secretKey: string, region: string, endpoint: string);
constructor(accessKeyId: string, accessKeySecret: string, region: string, endpoint: string);
sendSms(params: SendSmsRequest): Promise<SendSmsResponse>;
}
export {};

View File

@ -2,28 +2,16 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.AliSmsInstance = void 0;
class AliSmsInstance {
secretId;
secretKey;
accessKeyId;
accessKeySecret;
region;
endpoint;
client;
constructor(secretId, secretKey, region, endpoint) {
this.secretId = secretId;
this.secretKey = secretKey;
constructor(accessKeyId, accessKeySecret, region, endpoint) {
this.accessKeyId = accessKeyId;
this.accessKeySecret = accessKeySecret;
this.region = region;
this.endpoint = endpoint;
const clientConfig = {
credential: {
secretId: this.secretId,
secretKey: this.secretKey,
},
region: this.region,
profile: {
httpProfile: {
endpoint: this.endpoint || 'dysmsapi.aliyuncs.com',
},
},
};
}
async sendSms(params) {
console.log('react-native走不到这里[ali/sms.native');

View File

@ -13,12 +13,12 @@ type SendSmsResponse = {
RequestId: string;
};
export declare class AliSmsInstance {
secretId: string;
secretKey: string;
accessKeyId: string;
accessKeySecret: string;
region: string;
endpoint: string;
client: any;
constructor(secretId: string, secretKey: string, region: string, endpoint: string);
constructor(accessKeyId: string, accessKeySecret: string, region: string, endpoint: string);
sendSms(params: SendSmsRequest): Promise<SendSmsResponse>;
}
export {};

View File

@ -2,28 +2,16 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.AliSmsInstance = void 0;
class AliSmsInstance {
secretId;
secretKey;
accessKeyId;
accessKeySecret;
region;
endpoint;
client;
constructor(secretId, secretKey, region, endpoint) {
this.secretId = secretId;
this.secretKey = secretKey;
constructor(accessKeyId, accessKeySecret, region, endpoint) {
this.accessKeyId = accessKeyId;
this.accessKeySecret = accessKeySecret;
this.region = region;
this.endpoint = endpoint;
const clientConfig = {
credential: {
secretId: this.secretId,
secretKey: this.secretKey,
},
region: this.region,
profile: {
httpProfile: {
endpoint: this.endpoint || 'dysmsapi.aliyuncs.com',
},
},
};
}
async sendSms(params) {
console.log('web走不到这里');

48
lib/service/ctyun/Sms.d.ts vendored Normal file
View File

@ -0,0 +1,48 @@
type SendSmsRequest = {
phoneNumber: string;
templateCode: string;
signName: string;
templateParam?: Record<string, string>;
extendCode?: string;
sessionId?: string;
};
type SendSmsResponse = {
code: 'OK' | string;
message: string;
requestId: string;
};
type DescribeSmsTemplateListRequest = {
pageIndex: number;
pageSize: number;
};
type DescribeSmsTemplateListResponse = {
code: 'OK' | string;
message: string;
requestId: string;
total: number;
data: {
reason: string;
createTime: Date;
updateTime: Date;
example: string;
remark: string;
status: 0 | 1 | 2;
templateCode: string;
templateType: 1 | 2;
templateName: string;
templateContent: string;
templateStatus: 0 | 1 | 2;
}[];
};
export declare class CTYunSmsInstance {
accessKey: string;
securityKey: string;
endpoint: string;
constructor(accessKey: string, securityKey: string, endpoint: string);
sendSms(params: SendSmsRequest): Promise<SendSmsResponse>;
syncTemplate(params: DescribeSmsTemplateListRequest): Promise<DescribeSmsTemplateListResponse>;
private access;
private hmacsha256;
private sha256;
}
export {};

122
lib/service/ctyun/Sms.js Normal file
View File

@ -0,0 +1,122 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CTYunSmsInstance = void 0;
const tslib_1 = require("tslib");
const crypto_1 = tslib_1.__importDefault(require("crypto"));
const buffer_1 = require("buffer");
const Exception_1 = require("oak-domain/lib/types/Exception");
function format(date, layout) {
function pad(num, digit) {
const d = digit || 2;
let result = num.toString();
while (result.length < d) {
result = '0' + result;
}
return result;
}
const d = new Date(date);
const year = d.getFullYear();
const month = d.getMonth() + 1;
const day = d.getDate();
const hour = d.getHours();
const minute = d.getMinutes();
const second = d.getSeconds();
const millisecond = d.getMilliseconds();
let result = layout || 'YYYYMMDDTHHmmss';
result = result
.replace(/YYYY/g, year.toString())
.replace(/MM/g, pad(month))
.replace(/DD/g, pad(day))
.replace(/HH/g, pad(hour))
.replace(/mm/g, pad(minute))
.replace(/ss/g, pad(second))
.replace(/SSS/g, pad(millisecond, 3));
return result;
}
class CTYunSmsInstance {
accessKey;
securityKey;
endpoint;
constructor(accessKey, securityKey, endpoint) {
this.accessKey = accessKey;
this.securityKey = securityKey;
this.endpoint = endpoint || 'sms-global.ctapi.ctyun.cn';
}
async sendSms(params) {
const { phoneNumber, templateParam = {}, templateCode, signName, } = params;
const sendSmsRequest = {
action: 'SendSms',
phoneNumber,
templateParam: JSON.stringify(templateParam),
templateCode: templateCode,
signName: signName,
};
try {
const data = await this.access(`https://${this.endpoint}/sms/api/v1`, sendSmsRequest);
return data;
}
catch (error) {
throw error;
}
}
async syncTemplate(params) {
const { pageIndex, pageSize } = params;
const request = {
action: 'QuerySmsTemplateList',
pageIndex,
pageSize,
};
try {
const data = await this.access(`https://${this.endpoint}/sms/api/v1`, request);
return data;
}
catch (err) {
throw err;
}
}
async access(url, body, method) {
// SETUP2:构造时间戳
const timestamp = format(new Date(), 'YYYYMMDDTHHmmss') + 'Z';
// SETUP3:构造请求流水号
const requestId = crypto_1.default.randomUUID();
// SETUP4:构造待签名字符串
const headerStr = `ctyun-eop-request-id:${requestId}\neop-date:${timestamp}\n\n`;
const calculateContentHash = this.sha256(JSON.stringify(body));
const rawString = `${headerStr}\n${calculateContentHash}`;
// SETUP5:构造签名
const signTime = this.hmacsha256(timestamp, this.securityKey);
const signAK = this.hmacsha256(this.accessKey, buffer_1.Buffer.from(signTime, 'hex'));
const signDate = this.hmacsha256(timestamp.slice(0, 8), buffer_1.Buffer.from(signAK, 'hex'));
const sign = this.hmacsha256(rawString, buffer_1.Buffer.from(signDate, 'hex'));
const signature = buffer_1.Buffer.from(sign, 'hex').toString('base64');
// SETUP:6 构造请求头
const signatureHeader = `${this.accessKey} Headers=ctyun-eop-request-id;eop-date Signature=${signature}`;
const headers = {
'Content-Type': 'application/json',
'eop-date': timestamp,
'Eop-Authorization': signatureHeader,
'ctyun-eop-request-id': requestId,
};
let response;
try {
response = await fetch(url, {
method: method || 'POST',
headers,
body: JSON.stringify(body),
});
}
catch (err) {
// fetch返回异常一定是网络异常
throw new Exception_1.OakNetworkException();
}
return response.json();
}
hmacsha256(data, key) {
const hmac = crypto_1.default.createHmac('sha1', key).update(data).digest('hex');
return hmac;
}
sha256(data) {
return crypto_1.default.createHash('SHA256').update(data).digest('hex');
}
}
exports.CTYunSmsInstance = CTYunSmsInstance;

22
lib/service/ctyun/Sms.mp.d.ts vendored Normal file
View File

@ -0,0 +1,22 @@
type SendSmsRequest = {
action: 'SendSms' | string;
phoneNumber: string;
templateCode: string;
signName: string;
templateParam?: Record<string, string>;
extendCode?: string;
sessionId?: string;
};
type SendSmsResponse = {
code: 'OK' | string;
message: string;
requestId: string;
};
export declare class CTYunSmsInstance {
accessKey: string;
securityKey: string;
endpoint: string;
constructor(accessKey: string, securityKey: string, endpoint: string);
sendSms(params: SendSmsRequest): Promise<SendSmsResponse>;
}
export {};

View File

@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CTYunSmsInstance = void 0;
class CTYunSmsInstance {
accessKey;
securityKey;
endpoint;
constructor(accessKey, securityKey, endpoint) {
this.accessKey = accessKey;
this.securityKey = securityKey;
this.endpoint = endpoint;
}
async sendSms(params) {
console.log('mp走不到这里');
return {};
}
}
exports.CTYunSmsInstance = CTYunSmsInstance;

22
lib/service/ctyun/Sms.native.d.ts vendored Normal file
View File

@ -0,0 +1,22 @@
type SendSmsRequest = {
action: 'SendSms' | string;
phoneNumber: string;
templateCode: string;
signName: string;
templateParam?: Record<string, string>;
extendCode?: string;
sessionId?: string;
};
type SendSmsResponse = {
code: 'OK' | string;
message: string;
requestId: string;
};
export declare class CTYunSmsInstance {
accessKey: string;
securityKey: string;
endpoint: string;
constructor(accessKey: string, securityKey: string, endpoint: string);
sendSms(params: SendSmsRequest): Promise<SendSmsResponse>;
}
export {};

View File

@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CTYunSmsInstance = void 0;
class CTYunSmsInstance {
accessKey;
securityKey;
endpoint;
constructor(accessKey, securityKey, endpoint) {
this.accessKey = accessKey;
this.securityKey = securityKey;
this.endpoint = endpoint;
}
async sendSms(params) {
console.log('react-native走不到这里[ali/sms.native');
return {};
}
}
exports.CTYunSmsInstance = CTYunSmsInstance;

22
lib/service/ctyun/Sms.web.d.ts vendored Normal file
View File

@ -0,0 +1,22 @@
type SendSmsRequest = {
action: 'SendSms' | string;
phoneNumber: string;
templateCode: string;
signName: string;
templateParam?: Record<string, string>;
extendCode?: string;
sessionId?: string;
};
type SendSmsResponse = {
code: 'OK' | string;
message: string;
requestId: string;
};
export declare class CTYunSmsInstance {
accessKey: string;
securityKey: string;
endpoint: string;
constructor(accessKey: string, securityKey: string, endpoint: string);
sendSms(params: SendSmsRequest): Promise<SendSmsResponse>;
}
export {};

View File

@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CTYunSmsInstance = void 0;
class CTYunSmsInstance {
accessKey;
securityKey;
endpoint;
constructor(accessKey, securityKey, endpoint) {
this.accessKey = accessKey;
this.securityKey = securityKey;
this.endpoint = endpoint;
}
async sendSms(params) {
console.log('web走不到这里');
return {};
}
}
exports.CTYunSmsInstance = CTYunSmsInstance;

View File

@ -45,7 +45,6 @@ class TencentSmsInstance {
return result;
}
catch (err) {
console.error(err);
throw err;
}
}

View File

@ -1,18 +1,22 @@
import { TencentSmsInstance } from './service/tencent/Sms';
import { AliSmsInstance } from './service/ali/Sms';
import { CTYunSmsInstance } from './service/ctyun/Sms';
import { assert } from 'oak-domain/lib/utils/assert';
class SmsSDK {
tencentMap: Record<string, TencentSmsInstance>;
aliMap: Record<string, AliSmsInstance>;
ctyunMap: Record<string, CTYunSmsInstance>;
constructor() {
this.tencentMap = {};
this.aliMap = {};
this.ctyunMap = {};
}
getInstance(
origin: 'ali' | 'tencent',
origin: 'ali' | 'tencent' | 'ctyun',
accessKey: string,
accessSecret: string,
endpoint: string,
@ -27,7 +31,7 @@ class SmsSDK {
accessKey,
accessSecret,
region!,
endpoint!,
endpoint!
);
Object.assign(this.tencentMap, {
[accessKey]: instance,
@ -43,12 +47,25 @@ class SmsSDK {
const instance = new AliSmsInstance(
accessKey,
accessSecret,
endpoint,
endpoint
);
Object.assign(this.aliMap, {
[accessKey]: instance,
});
return instance;
} else if (origin === 'ctyun') {
if (this.ctyunMap[accessKey]) {
return this.ctyunMap[accessKey];
}
const instance = new CTYunSmsInstance(
accessKey,
accessSecret,
endpoint
);
Object.assign(this.ctyunMap, {
[accessKey]: instance,
});
return instance;
} else {
assert(false, `${origin} not implemented`);
}
@ -58,4 +75,4 @@ class SmsSDK {
const SDK = new SmsSDK();
export default SDK;
export { TencentSmsInstance, AliSmsInstance };
export { TencentSmsInstance, AliSmsInstance, CTYunSmsInstance };

View File

@ -1,7 +1,11 @@
import WechatSDK, { WechatMpInstance, WechatPublicInstance, WechatWebInstance } from './WechatSDK';
import AmapSDK from './AmapSDK';
import QiniuSDK, { QiniuCloudInstance } from './QiniuSDK';
import SmsSdk, { TencentSmsInstance, AliSmsInstance } from './SmsSdk';
import SmsSdk, {
TencentSmsInstance,
AliSmsInstance,
CTYunSmsInstance,
} from './SmsSdk';
import CTYunSDk, { CTYunInstance } from './CTYunSDK';
export * from './service/amap/Amap';
@ -18,6 +22,7 @@ export {
SmsSdk,
TencentSmsInstance,
AliSmsInstance,
CTYunSmsInstance,
};
export * from './types';

View File

@ -15,35 +15,22 @@ type SendSmsResponse = {
};
export class AliSmsInstance {
secretId: string;
secretKey: string;
accessKeyId: string;
accessKeySecret: string;
region: string;
endpoint: string;
client: any;
constructor(
secretId: string,
secretKey: string,
accessKeyId: string,
accessKeySecret: string,
region: string,
endpoint: string
) {
this.secretId = secretId;
this.secretKey = secretKey;
this.accessKeyId = accessKeyId;
this.accessKeySecret = accessKeySecret;
this.region = region;
this.endpoint = endpoint;
const clientConfig = {
credential: {
secretId: this.secretId,
secretKey: this.secretKey,
},
region: this.region,
profile: {
httpProfile: {
endpoint: this.endpoint || 'dysmsapi.aliyuncs.com',
},
},
};
}
async sendSms(params: SendSmsRequest) {

View File

@ -15,35 +15,22 @@ type SendSmsResponse = {
};
export class AliSmsInstance {
secretId: string;
secretKey: string;
accessKeyId: string;
accessKeySecret: string;
region: string;
endpoint: string;
client: any;
constructor(
secretId: string,
secretKey: string,
accessKeyId: string,
accessKeySecret: string,
region: string,
endpoint: string
) {
this.secretId = secretId;
this.secretKey = secretKey;
this.accessKeyId = accessKeyId;
this.accessKeySecret = accessKeySecret;
this.region = region;
this.endpoint = endpoint;
const clientConfig = {
credential: {
secretId: this.secretId,
secretKey: this.secretKey,
},
region: this.region,
profile: {
httpProfile: {
endpoint: this.endpoint || 'dysmsapi.aliyuncs.com',
},
},
};
}
async sendSms(params: SendSmsRequest) {

View File

@ -19,6 +19,7 @@ type SendSmsResponse = {
RequestId: string;
};
export class AliSmsInstance {
accessKeyId: string;
accessKeySecret: string;
@ -28,7 +29,7 @@ export class AliSmsInstance {
constructor(
accessKeyId: string,
accessKeySecret: string,
endpoint?: string,
endpoint?: string
) {
this.accessKeyId = accessKeyId;
this.accessKeySecret = accessKeySecret;
@ -51,20 +52,52 @@ export class AliSmsInstance {
signName,
} = params;
let sendSmsRequest = new $Dysmsapi20170525.SendSmsRequest({
phoneNumbers: (phoneNumbers instanceof Array) ? phoneNumbers.join(',') : phoneNumbers,
phoneNumbers:
phoneNumbers instanceof Array
? phoneNumbers.join(',')
: phoneNumbers,
templateParam: JSON.stringify(templateParam),
templateCode: templateCode,
signName: signName,
});
try {
const data = await this.client.sendSmsWithOptions(sendSmsRequest, new $Util.RuntimeOptions({}));
const data = await this.client.sendSmsWithOptions(
sendSmsRequest,
new $Util.RuntimeOptions({})
);
const { statusCode, body } = data;
if (statusCode != 200) {
throw new Error(`ali.sendSms接口返回状态码错误${statusCode}`);
throw new Error(
`sendSms接口返回状态码错误${statusCode}`
);
}
return body;
} catch (error) {
throw error;
}
}
async syncTemplate(params: $Dysmsapi20170525.QuerySmsTemplateListRequest) {
const { PageIndex, PageSize } = params;
try {
let querySmsTemplateListRequest =
new $Dysmsapi20170525.QuerySmsTemplateListRequest({
PageIndex,
PageSize,
});
const result = await this.client.querySmsTemplateListWithOptions(
querySmsTemplateListRequest,
new $Util.RuntimeOptions({})
);
const { statusCode, body } = result;
if (statusCode != 200) {
throw new Error(
`syncTemplate接口返回状态码错误${statusCode}`
);
}
return body;
} catch (err) {
throw err;
}
}
}

View File

@ -15,35 +15,22 @@ type SendSmsResponse = {
};
export class AliSmsInstance {
secretId: string;
secretKey: string;
accessKeyId: string;
accessKeySecret: string;
region: string;
endpoint: string;
client: any;
constructor(
secretId: string,
secretKey: string,
accessKeyId: string,
accessKeySecret: string,
region: string,
endpoint: string
) {
this.secretId = secretId;
this.secretKey = secretKey;
this.accessKeyId = accessKeyId;
this.accessKeySecret = accessKeySecret;
this.region = region;
this.endpoint = endpoint;
const clientConfig = {
credential: {
secretId: this.secretId,
secretKey: this.secretKey,
},
region: this.region,
profile: {
httpProfile: {
endpoint: this.endpoint || 'dysmsapi.aliyuncs.com',
},
},
};
}
async sendSms(params: SendSmsRequest) {

View File

@ -0,0 +1,32 @@
type SendSmsRequest = {
action: 'SendSms' | string; // 系统规定参数。取值SendSms。
phoneNumber: string; // 接收短信的手机号码。格式国内短信无任何前缀的11位手机号码例如1381111****。多个手机号码使用英文","隔开最多支持一次提交200个手机号码。
templateCode: string;
signName: string;
templateParam?: Record<string, string>;
extendCode?: string;
sessionId?: string;
};
type SendSmsResponse = {
code: 'OK' | string;
message: string;
requestId: string;
};
export class CTYunSmsInstance {
accessKey: string;
securityKey: string;
endpoint: string;
constructor(accessKey: string, securityKey: string, endpoint: string) {
this.accessKey = accessKey;
this.securityKey = securityKey;
this.endpoint = endpoint;
}
async sendSms(params: SendSmsRequest) {
console.log('mp走不到这里');
return {} as SendSmsResponse;
}
}

View File

@ -0,0 +1,32 @@
type SendSmsRequest = {
action: 'SendSms' | string; // 系统规定参数。取值SendSms。
phoneNumber: string; // 接收短信的手机号码。格式国内短信无任何前缀的11位手机号码例如1381111****。多个手机号码使用英文","隔开最多支持一次提交200个手机号码。
templateCode: string;
signName: string;
templateParam?: Record<string, string>;
extendCode?: string;
sessionId?: string;
};
type SendSmsResponse = {
code: 'OK' | string;
message: string;
requestId: string;
};
export class CTYunSmsInstance {
accessKey: string;
securityKey: string;
endpoint: string;
constructor(accessKey: string, securityKey: string, endpoint: string) {
this.accessKey = accessKey;
this.securityKey = securityKey;
this.endpoint = endpoint;
}
async sendSms(params: SendSmsRequest) {
console.log('react-native走不到这里[ali/sms.native');
return {} as SendSmsResponse;
}
}

197
src/service/ctyun/Sms.ts Normal file
View File

@ -0,0 +1,197 @@
import crypto from 'crypto';
import { Buffer } from 'buffer';
import * as querystring from 'querystring';
import {
OakExternalException,
OakNetworkException,
} from 'oak-domain/lib/types/Exception';
type SendSmsRequest = {
phoneNumber: string; // 接收短信的手机号码。格式国内短信无任何前缀的11位手机号码例如1381111****。多个手机号码使用英文","隔开最多支持一次提交200个手机号码。
templateCode: string;
signName: string;
templateParam?: Record<string, string>;
extendCode?: string;
sessionId?: string;
};
type SendSmsResponse = {
code: 'OK' | string;
message: string;
requestId: string;
};
type DescribeSmsTemplateListRequest = {
pageIndex: number;
pageSize: number;
};
type DescribeSmsTemplateListResponse = {
code: 'OK' | string;
message: string;
requestId: string;
total: number;
data: {
reason: string;
createTime: Date;
updateTime: Date;
example: string;
remark: string;
status: 0 | 1 | 2; // 0: 未审核1审核通过2审核未通过
templateCode: string;
templateType: 1 | 2; // 短信类型。1验证码2短信通知
templateName: string;
templateContent: string;
templateStatus: 0 | 1 | 2; // 0: 未审核1审核通过2审核未通过
}[];
};
function format(date: Date, layout: string) {
function pad(num: number, digit?: number) {
const d = digit || 2;
let result = num.toString();
while (result.length < d) {
result = '0' + result;
}
return result;
}
const d = new Date(date);
const year = d.getFullYear();
const month = d.getMonth() + 1;
const day = d.getDate();
const hour = d.getHours();
const minute = d.getMinutes();
const second = d.getSeconds();
const millisecond = d.getMilliseconds();
let result = layout || 'YYYYMMDDTHHmmss';
result = result
.replace(/YYYY/g, year.toString())
.replace(/MM/g, pad(month))
.replace(/DD/g, pad(day))
.replace(/HH/g, pad(hour))
.replace(/mm/g, pad(minute))
.replace(/ss/g, pad(second))
.replace(/SSS/g, pad(millisecond, 3));
return result;
}
export class CTYunSmsInstance {
accessKey: string;
securityKey: string;
endpoint: string;
constructor(accessKey: string, securityKey: string, endpoint: string) {
this.accessKey = accessKey;
this.securityKey = securityKey;
this.endpoint = endpoint || 'sms-global.ctapi.ctyun.cn';
}
async sendSms(params: SendSmsRequest) {
const {
phoneNumber,
templateParam = {},
templateCode,
signName,
} = params;
const sendSmsRequest = {
action: 'SendSms',
phoneNumber,
templateParam: JSON.stringify(templateParam),
templateCode: templateCode,
signName: signName,
};
try {
const data = await this.access(
`https://${this.endpoint}/sms/api/v1`,
sendSmsRequest
);
return data as SendSmsResponse;
} catch (error) {
throw error;
}
}
async syncTemplate(params: DescribeSmsTemplateListRequest) {
const { pageIndex, pageSize } = params;
const request = {
action: 'QuerySmsTemplateList',
pageIndex,
pageSize,
};
try {
const data = await this.access(
`https://${this.endpoint}/sms/api/v1`,
request
);
return data as DescribeSmsTemplateListResponse;
} catch (err) {
throw err;
}
}
private async access(
url: string,
body: Record<string, any>,
method?: RequestInit['method']
) {
// SETUP2:构造时间戳
const timestamp = format(new Date(), 'YYYYMMDDTHHmmss') + 'Z';
// SETUP3:构造请求流水号
const requestId = crypto.randomUUID();
// SETUP4:构造待签名字符串
const headerStr = `ctyun-eop-request-id:${requestId}\neop-date:${timestamp}\n\n`;
const calculateContentHash = this.sha256(JSON.stringify(body));
const rawString = `${headerStr}\n${calculateContentHash}`;
// SETUP5:构造签名
const signTime = this.hmacsha256(timestamp, this.securityKey);
const signAK = this.hmacsha256(
this.accessKey,
Buffer.from(signTime, 'hex')
);
const signDate = this.hmacsha256(
timestamp.slice(0, 8),
Buffer.from(signAK, 'hex')
);
const sign = this.hmacsha256(rawString, Buffer.from(signDate, 'hex'));
const signature = Buffer.from(sign, 'hex').toString('base64');
// SETUP:6 构造请求头
const signatureHeader = `${this.accessKey} Headers=ctyun-eop-request-id;eop-date Signature=${signature}`;
const headers = {
'Content-Type': 'application/json',
'eop-date': timestamp,
'Eop-Authorization': signatureHeader,
'ctyun-eop-request-id': requestId,
};
let response: Response;
try {
response = await fetch(url, {
method: method || 'POST',
headers,
body: JSON.stringify(body),
});
} catch (err) {
// fetch返回异常一定是网络异常
throw new OakNetworkException();
}
return response.json();
}
private hmacsha256(data: any, key: Buffer | string) {
const hmac = crypto.createHmac('sha1', key).update(data).digest('hex');
return hmac;
}
private sha256(data: string) {
return crypto.createHash('SHA256').update(data).digest('hex');
}
}

View File

@ -0,0 +1,32 @@
type SendSmsRequest = {
action: 'SendSms' | string; // 系统规定参数。取值SendSms。
phoneNumber: string; // 接收短信的手机号码。格式国内短信无任何前缀的11位手机号码例如1381111****。多个手机号码使用英文","隔开最多支持一次提交200个手机号码。
templateCode: string;
signName: string;
templateParam?: Record<string, string>;
extendCode?: string;
sessionId?: string;
};
type SendSmsResponse = {
code: 'OK' | string;
message: string;
requestId: string;
};
export class CTYunSmsInstance {
accessKey: string;
securityKey: string;
endpoint: string;
constructor(accessKey: string, securityKey: string, endpoint: string) {
this.accessKey = accessKey;
this.securityKey = securityKey;
this.endpoint = endpoint;
}
async sendSms(params: SendSmsRequest) {
console.log('web走不到这里');
return {} as SendSmsResponse;
}
}

View File

@ -52,7 +52,6 @@ export class TencentSmsInstance {
const result: DescribeSmsTemplateListResponse = await this.client.DescribeSmsTemplateList(params);
return result
} catch (err) {
console.error(err);
throw err;
}
}