diff --git a/es/SmsSdk.d.ts b/es/SmsSdk.d.ts index 2599fd9..313ccf7 100644 --- a/es/SmsSdk.d.ts +++ b/es/SmsSdk.d.ts @@ -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; aliMap: Record; + ctyunMap: Record; 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 }; diff --git a/es/SmsSdk.js b/es/SmsSdk.js index f97b075..dba1592 100644 --- a/es/SmsSdk.js +++ b/es/SmsSdk.js @@ -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 }; diff --git a/es/index.d.ts b/es/index.d.ts index beb8eee..9db43d6 100644 --- a/es/index.d.ts +++ b/es/index.d.ts @@ -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'; diff --git a/es/index.js b/es/index.js index beb8eee..c9cbae3 100644 --- a/es/index.js +++ b/es/index.js @@ -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'; diff --git a/es/service/ali/Sms.d.ts b/es/service/ali/Sms.d.ts index 49030b8..57b1bd5 100644 --- a/es/service/ali/Sms.d.ts +++ b/es/service/ali/Sms.d.ts @@ -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 {}; diff --git a/es/service/ali/Sms.js b/es/service/ali/Sms.js index ca50a24..4dd48ff 100644 --- a/es/service/ali/Sms.js +++ b/es/service/ali/Sms.js @@ -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; + } + } } diff --git a/es/service/ali/Sms.mp.d.ts b/es/service/ali/Sms.mp.d.ts index c287612..0001890 100644 --- a/es/service/ali/Sms.mp.d.ts +++ b/es/service/ali/Sms.mp.d.ts @@ -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; } export {}; diff --git a/es/service/ali/Sms.mp.js b/es/service/ali/Sms.mp.js index 8b63d72..0492fbd 100644 --- a/es/service/ali/Sms.mp.js +++ b/es/service/ali/Sms.mp.js @@ -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走不到这里'); diff --git a/es/service/ali/Sms.native.d.ts b/es/service/ali/Sms.native.d.ts index c287612..0001890 100644 --- a/es/service/ali/Sms.native.d.ts +++ b/es/service/ali/Sms.native.d.ts @@ -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; } export {}; diff --git a/es/service/ali/Sms.native.js b/es/service/ali/Sms.native.js index 446fbfe..48361f2 100644 --- a/es/service/ali/Sms.native.js +++ b/es/service/ali/Sms.native.js @@ -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'); diff --git a/es/service/ali/Sms.web.d.ts b/es/service/ali/Sms.web.d.ts index c287612..0001890 100644 --- a/es/service/ali/Sms.web.d.ts +++ b/es/service/ali/Sms.web.d.ts @@ -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; } export {}; diff --git a/es/service/ali/Sms.web.js b/es/service/ali/Sms.web.js index ad940d7..900b10e 100644 --- a/es/service/ali/Sms.web.js +++ b/es/service/ali/Sms.web.js @@ -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走不到这里'); diff --git a/es/service/ctyun/Sms.d.ts b/es/service/ctyun/Sms.d.ts new file mode 100644 index 0000000..407dea6 --- /dev/null +++ b/es/service/ctyun/Sms.d.ts @@ -0,0 +1,48 @@ +type SendSmsRequest = { + phoneNumber: string; + templateCode: string; + signName: string; + templateParam?: Record; + 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; + syncTemplate(params: DescribeSmsTemplateListRequest): Promise; + private access; + private hmacsha256; + private sha256; +} +export {}; diff --git a/es/service/ctyun/Sms.js b/es/service/ctyun/Sms.js new file mode 100644 index 0000000..2a84cba --- /dev/null +++ b/es/service/ctyun/Sms.js @@ -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'); + } +} diff --git a/es/service/ctyun/Sms.mp.d.ts b/es/service/ctyun/Sms.mp.d.ts new file mode 100644 index 0000000..a046cfa --- /dev/null +++ b/es/service/ctyun/Sms.mp.d.ts @@ -0,0 +1,22 @@ +type SendSmsRequest = { + action: 'SendSms' | string; + phoneNumber: string; + templateCode: string; + signName: string; + templateParam?: Record; + 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; +} +export {}; diff --git a/es/service/ctyun/Sms.mp.js b/es/service/ctyun/Sms.mp.js new file mode 100644 index 0000000..64755b6 --- /dev/null +++ b/es/service/ctyun/Sms.mp.js @@ -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 {}; + } +} diff --git a/es/service/ctyun/Sms.native.d.ts b/es/service/ctyun/Sms.native.d.ts new file mode 100644 index 0000000..a046cfa --- /dev/null +++ b/es/service/ctyun/Sms.native.d.ts @@ -0,0 +1,22 @@ +type SendSmsRequest = { + action: 'SendSms' | string; + phoneNumber: string; + templateCode: string; + signName: string; + templateParam?: Record; + 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; +} +export {}; diff --git a/es/service/ctyun/Sms.native.js b/es/service/ctyun/Sms.native.js new file mode 100644 index 0000000..0801052 --- /dev/null +++ b/es/service/ctyun/Sms.native.js @@ -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 {}; + } +} diff --git a/es/service/ctyun/Sms.web.d.ts b/es/service/ctyun/Sms.web.d.ts new file mode 100644 index 0000000..a046cfa --- /dev/null +++ b/es/service/ctyun/Sms.web.d.ts @@ -0,0 +1,22 @@ +type SendSmsRequest = { + action: 'SendSms' | string; + phoneNumber: string; + templateCode: string; + signName: string; + templateParam?: Record; + 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; +} +export {}; diff --git a/es/service/ctyun/Sms.web.js b/es/service/ctyun/Sms.web.js new file mode 100644 index 0000000..bc9c655 --- /dev/null +++ b/es/service/ctyun/Sms.web.js @@ -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 {}; + } +} diff --git a/es/service/tencent/Sms.js b/es/service/tencent/Sms.js index e91d0fd..903cf4f 100644 --- a/es/service/tencent/Sms.js +++ b/es/service/tencent/Sms.js @@ -42,7 +42,6 @@ export class TencentSmsInstance { return result; } catch (err) { - console.error(err); throw err; } } diff --git a/lib/SmsSdk.d.ts b/lib/SmsSdk.d.ts index 2599fd9..313ccf7 100644 --- a/lib/SmsSdk.d.ts +++ b/lib/SmsSdk.d.ts @@ -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; aliMap: Record; + ctyunMap: Record; 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 }; diff --git a/lib/SmsSdk.js b/lib/SmsSdk.js index 51263e0..22e8199 100644 --- a/lib/SmsSdk.js +++ b/lib/SmsSdk.js @@ -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`); } diff --git a/lib/index.d.ts b/lib/index.d.ts index beb8eee..9db43d6 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -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'; diff --git a/lib/index.js b/lib/index.js index 0d95207..39e356f 100644 --- a/lib/index.js +++ b/lib/index.js @@ -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; } }); diff --git a/lib/service/ali/Sms.d.ts b/lib/service/ali/Sms.d.ts index 49030b8..57b1bd5 100644 --- a/lib/service/ali/Sms.d.ts +++ b/lib/service/ali/Sms.d.ts @@ -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 {}; diff --git a/lib/service/ali/Sms.js b/lib/service/ali/Sms.js index 24050d0..6c05fc9 100644 --- a/lib/service/ali/Sms.js +++ b/lib/service/ali/Sms.js @@ -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; diff --git a/lib/service/ali/Sms.mp.d.ts b/lib/service/ali/Sms.mp.d.ts index c287612..0001890 100644 --- a/lib/service/ali/Sms.mp.d.ts +++ b/lib/service/ali/Sms.mp.d.ts @@ -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; } export {}; diff --git a/lib/service/ali/Sms.mp.js b/lib/service/ali/Sms.mp.js index c66aadf..6cc9919 100644 --- a/lib/service/ali/Sms.mp.js +++ b/lib/service/ali/Sms.mp.js @@ -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走不到这里'); diff --git a/lib/service/ali/Sms.native.d.ts b/lib/service/ali/Sms.native.d.ts index c287612..0001890 100644 --- a/lib/service/ali/Sms.native.d.ts +++ b/lib/service/ali/Sms.native.d.ts @@ -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; } export {}; diff --git a/lib/service/ali/Sms.native.js b/lib/service/ali/Sms.native.js index 35032e9..d9583cb 100644 --- a/lib/service/ali/Sms.native.js +++ b/lib/service/ali/Sms.native.js @@ -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'); diff --git a/lib/service/ali/Sms.web.d.ts b/lib/service/ali/Sms.web.d.ts index c287612..0001890 100644 --- a/lib/service/ali/Sms.web.d.ts +++ b/lib/service/ali/Sms.web.d.ts @@ -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; } export {}; diff --git a/lib/service/ali/Sms.web.js b/lib/service/ali/Sms.web.js index 24fbd59..e5fd2ff 100644 --- a/lib/service/ali/Sms.web.js +++ b/lib/service/ali/Sms.web.js @@ -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走不到这里'); diff --git a/lib/service/ctyun/Sms.d.ts b/lib/service/ctyun/Sms.d.ts new file mode 100644 index 0000000..407dea6 --- /dev/null +++ b/lib/service/ctyun/Sms.d.ts @@ -0,0 +1,48 @@ +type SendSmsRequest = { + phoneNumber: string; + templateCode: string; + signName: string; + templateParam?: Record; + 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; + syncTemplate(params: DescribeSmsTemplateListRequest): Promise; + private access; + private hmacsha256; + private sha256; +} +export {}; diff --git a/lib/service/ctyun/Sms.js b/lib/service/ctyun/Sms.js new file mode 100644 index 0000000..1c14ad2 --- /dev/null +++ b/lib/service/ctyun/Sms.js @@ -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; diff --git a/lib/service/ctyun/Sms.mp.d.ts b/lib/service/ctyun/Sms.mp.d.ts new file mode 100644 index 0000000..a046cfa --- /dev/null +++ b/lib/service/ctyun/Sms.mp.d.ts @@ -0,0 +1,22 @@ +type SendSmsRequest = { + action: 'SendSms' | string; + phoneNumber: string; + templateCode: string; + signName: string; + templateParam?: Record; + 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; +} +export {}; diff --git a/lib/service/ctyun/Sms.mp.js b/lib/service/ctyun/Sms.mp.js new file mode 100644 index 0000000..ffef2f8 --- /dev/null +++ b/lib/service/ctyun/Sms.mp.js @@ -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; diff --git a/lib/service/ctyun/Sms.native.d.ts b/lib/service/ctyun/Sms.native.d.ts new file mode 100644 index 0000000..a046cfa --- /dev/null +++ b/lib/service/ctyun/Sms.native.d.ts @@ -0,0 +1,22 @@ +type SendSmsRequest = { + action: 'SendSms' | string; + phoneNumber: string; + templateCode: string; + signName: string; + templateParam?: Record; + 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; +} +export {}; diff --git a/lib/service/ctyun/Sms.native.js b/lib/service/ctyun/Sms.native.js new file mode 100644 index 0000000..dbd1d0d --- /dev/null +++ b/lib/service/ctyun/Sms.native.js @@ -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; diff --git a/lib/service/ctyun/Sms.web.d.ts b/lib/service/ctyun/Sms.web.d.ts new file mode 100644 index 0000000..a046cfa --- /dev/null +++ b/lib/service/ctyun/Sms.web.d.ts @@ -0,0 +1,22 @@ +type SendSmsRequest = { + action: 'SendSms' | string; + phoneNumber: string; + templateCode: string; + signName: string; + templateParam?: Record; + 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; +} +export {}; diff --git a/lib/service/ctyun/Sms.web.js b/lib/service/ctyun/Sms.web.js new file mode 100644 index 0000000..a014516 --- /dev/null +++ b/lib/service/ctyun/Sms.web.js @@ -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; diff --git a/lib/service/tencent/Sms.js b/lib/service/tencent/Sms.js index a111384..9760f2b 100644 --- a/lib/service/tencent/Sms.js +++ b/lib/service/tencent/Sms.js @@ -45,7 +45,6 @@ class TencentSmsInstance { return result; } catch (err) { - console.error(err); throw err; } } diff --git a/src/SmsSdk.ts b/src/SmsSdk.ts index 08ccd52..e45d7b6 100644 --- a/src/SmsSdk.ts +++ b/src/SmsSdk.ts @@ -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; aliMap: Record; + ctyunMap: Record; 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 }; diff --git a/src/index.ts b/src/index.ts index fc8ba81..b3c67ba 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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'; \ No newline at end of file diff --git a/src/service/ali/Sms.mp.ts b/src/service/ali/Sms.mp.ts index 53d2248..3e45f79 100644 --- a/src/service/ali/Sms.mp.ts +++ b/src/service/ali/Sms.mp.ts @@ -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) { diff --git a/src/service/ali/Sms.native.ts b/src/service/ali/Sms.native.ts index 9515fc0..3eea21a 100644 --- a/src/service/ali/Sms.native.ts +++ b/src/service/ali/Sms.native.ts @@ -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) { diff --git a/src/service/ali/Sms.ts b/src/service/ali/Sms.ts index e47bae6..a6cea1f 100644 --- a/src/service/ali/Sms.ts +++ b/src/service/ali/Sms.ts @@ -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; + } + } } diff --git a/src/service/ali/Sms.web.ts b/src/service/ali/Sms.web.ts index 555b0c2..9ab2855 100644 --- a/src/service/ali/Sms.web.ts +++ b/src/service/ali/Sms.web.ts @@ -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) { diff --git a/src/service/ctyun/Sms.mp.ts b/src/service/ctyun/Sms.mp.ts new file mode 100644 index 0000000..146f41f --- /dev/null +++ b/src/service/ctyun/Sms.mp.ts @@ -0,0 +1,32 @@ +type SendSmsRequest = { + action: 'SendSms' | string; // 系统规定参数。取值:SendSms。 + phoneNumber: string; // 接收短信的手机号码。格式:国内短信:无任何前缀的11位手机号码,例如1381111****。多个手机号码使用英文","隔开,最多支持一次提交200个手机号码。 + templateCode: string; + signName: string; + templateParam?: Record; + 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; + } +} diff --git a/src/service/ctyun/Sms.native.ts b/src/service/ctyun/Sms.native.ts new file mode 100644 index 0000000..b134313 --- /dev/null +++ b/src/service/ctyun/Sms.native.ts @@ -0,0 +1,32 @@ +type SendSmsRequest = { + action: 'SendSms' | string; // 系统规定参数。取值:SendSms。 + phoneNumber: string; // 接收短信的手机号码。格式:国内短信:无任何前缀的11位手机号码,例如1381111****。多个手机号码使用英文","隔开,最多支持一次提交200个手机号码。 + templateCode: string; + signName: string; + templateParam?: Record; + 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; + } +} diff --git a/src/service/ctyun/Sms.ts b/src/service/ctyun/Sms.ts new file mode 100644 index 0000000..f916a3f --- /dev/null +++ b/src/service/ctyun/Sms.ts @@ -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; + 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, + 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'); + } +} diff --git a/src/service/ctyun/Sms.web.ts b/src/service/ctyun/Sms.web.ts new file mode 100644 index 0000000..bbde2ee --- /dev/null +++ b/src/service/ctyun/Sms.web.ts @@ -0,0 +1,32 @@ +type SendSmsRequest = { + action: 'SendSms' | string; // 系统规定参数。取值:SendSms。 + phoneNumber: string; // 接收短信的手机号码。格式:国内短信:无任何前缀的11位手机号码,例如1381111****。多个手机号码使用英文","隔开,最多支持一次提交200个手机号码。 + templateCode: string; + signName: string; + templateParam?: Record; + 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; + } +} diff --git a/src/service/tencent/Sms.ts b/src/service/tencent/Sms.ts index fb46562..5bdca25 100644 --- a/src/service/tencent/Sms.ts +++ b/src/service/tencent/Sms.ts @@ -52,7 +52,6 @@ export class TencentSmsInstance { const result: DescribeSmsTemplateListResponse = await this.client.DescribeSmsTemplateList(params); return result } catch (err) { - console.error(err); throw err; } }