wo-base-messenger/messenger.js
2022-03-25 21:01:28 +08:00

128 lines
6.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const util = require('util')
const http = require('http')
const NodeMailer = require('nodemailer')
const my = {}
module.exports = {
init (envi) {
my.envi = envi
my.smtpTransporter = NodeMailer.createTransport(envi.SMTP)
my.smsClient = new (require('@alicloud/sms-sdk'))(envi.SMS.aliyun) // https://www.npmjs.com/package/@alicloud/sms-sdk
},
// 或者如果smtp参数已经确定就可以直接定义 sendMail: Bluebird.promisify(Smtp.sendMail).bind(Smtp)
async sendMail (messageObject) { // messageObject: { from, to, cc, bcc, subject, text, html, sender, replyTo, inReplyTo }
my.smtpTransporter = my.smtpTransporter || NodeMailer.createTransport(wo.envi.SMTP)
return await util.promisify(my.smtpTransporter.sendMail).call(my.smtpTransporter, messageObject)
},
async sendSms ({ phone, vendor,
msg, // for vendor==='DXTON'
msgParam, msgTemplate, // for ['ALIYUN','UNICLOUD'].includes(vendor)
signName, // for vendor==='ALIYUN',
appid, // for vendor==='UNICLOUD',
} = {}) {
// 通过option对象对外提供统一的调用参数格式
if (/^\+\d+-\d+$/.test(phone)) {
if (vendor === 'DXTON' && msg) {
return await this.sendSmsDxton(phone, msg)
} else if (vendor === 'ALIYUN' && msgParam && msgTemplate) {
return await this.sendSmsAliyun(phone, msgParam, msgTemplate, signName)
} else if (vendor === 'UNICLOUD' && msgParam && msgTemplate) {
return await this.sendSmsUnicloud({phone, msgParam, msgTemplate, appid})
}
}
return null // 手机号格式错误,或者 vendor 错误。
},
/* 使用 dxton.com 的短信接口 http://www.dxton.com/help_detail/38.html
- 测试接口:
- 国内: http://sms.106jiekou.com/utf8/sms.aspx?account=9999&password=接口密码&mobile=13900008888&content=您的订单编码888888。如需帮助请联系客服。
- 国外: http://sms.106jiekou.com/utf8/worldapi.aspx?account=9999&password=接口密码&mobile=手机号码&content=尊敬的用户您已经注册成功,用户名:{0} 密码:{1} 感谢您的注册!
- response 的 content-type 为 text/html
*/
async sendSmsDxton (phone, msg) {
var matches = phone.match(/\d+/g)
var smsNumber, smsUrl
if (matches[0] === '86') {
smsUrl = wo.envi.SMS.DXTON.urlChina
smsNumber = matches[1]
} else {
smsUrl = wo.envi.SMS.DXTON.urlWorld // 国际短信不需要签名、模板,可发送任意内容。
smsNumber = matches[0] + matches[1]
}
// let returnCode = await RequestPromise.get(smsUrl + '&mobile=' + smsNumber + '&content=' + encodeURIComponent(msg))
// let returnCode = await axios.get(smsUrl + '&mobile=' + smsNumber + '&content=' + encodeURIComponent(msg))
return await new Promise((resolve, reject)=>{
http.get(smsUrl + '&mobile=' + smsNumber + '&content=' + encodeURIComponent(msg), (resp)=>{
let returnCode = ''
resp.on('returnCode', (chunk) => { returnCode += chunk })
resp.on('end', () => {
if (parseInt(returnCode)===100){
resolve({ _state: 'SMS_SENT_SUCCESS' }) // 100: 发送成功 (表示已和我们接口连通)
}else{
resolve({ _state: 'SMS_SEND_FAIL', error: { returnCode }}) // 短信接口错误代码http://www.dxton.com/help_detail/2.html
}
})
}).on("error",(error)=>{
reject({ _state: 'SMS_SEND_ERROR', error })
})
})
},
async sendSmsAliyun (phone, msgParam, msgTemplate, signName) {
my.smsClient = my.smsClient || new (require('@alicloud/sms-sdk'))(wo.envi.SMS.aliyun)
const [countryCode, callNumber] = phone.match(/\d+/g)
const smsNumber = countryCode === '86' ? callNumber : `00${countryCode}${callNumber}`
const envi = my.envi || wo.envi
return await my.smsClient
.sendSMS({
PhoneNumbers: smsNumber, //必填:待发送手机号。支持以逗号分隔的形式进行批量调用批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式;发送国际/港澳台消息时接收号码格式为00+国际区号+号码如“0085200000000”
SignName: signName || envi.SMS.ALIYUN.signName, //必填:短信签名-可在短信控制台中找到
TemplateCode: msgTemplate, //必填:短信模板-可在短信控制台中找到,发送国际/港澳台消息时,请使用国际/港澳台短信模版
TemplateParam: JSON.stringify(msgParam), //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时。
})
.then(
function (result) {
let { Code } = result
if (Code === 'OK') {
return { _state: 'SMS_SENT_SUCCESS' }
} else {
return { _state: 'SMS_SEND_FAIL', error: result }
}
},
function (error) {
return { _state: 'SMS_SEND_ERROR', error }
}
)
},
async sendSmsUnicloud({ phone, msgTemplate, msgParam, appid, smsKey, smsSecret }) {
try {
const envi = my.envi || wo.envi // 不能在下面调用 my.envi.*** 因为 my.envi 可能并未初始化,而 unicloud 又不支持 ?. 操作符.
const result = await uniCloud.sendSms({
appid: appid || envi.SMS.UNICLOUD.appid,
smsKey: smsKey || envi.SMS.UNICLOUD.smsKey,
smsSecret: smsSecret || envi.SMS.UNICLOUD.smsSecret,
phone: phone.match(/\d+/g)[1],
templateId: msgTemplate || 'uni_sms_test',
data: msgParam // 模版中的变量的值,例如 { passcode: '234345', purpose: '注册' }
})
// 调用成功,请注意这时不代表发送成功
return { _state:'SMS_SENT_SUCCESS' } // { code:0, errCode:0, success:true }
} catch (error) {
// 调用失败
// {"code":undefined,"msg":"短信发送失败:账户余额不足"}
return {
_state: 'SMS_SEND_FAIL',
error // { errCode, errMsg }
}
}
}
}