小程序在线客服自动回复作用(node版)
序言
我们知道H5网页页面常常要将客户导流到APP,根据下载安装包或是跳转至小米应用商店销售市场/Appstore等方法开展导流。可是因为小程序嵌入webview时必须校检网站域名,因而跳转到第三方应用销售市场和Appstroe没法完成导流。那怎么办呢? 只有说道高一尺魔高一丈,看看微博小程序是怎么导流的:
攘外必先安内的方法,运用小程序的线上作用可以打开H5的方法,去开展免费下载正确引导。 因此,就引入了此次文本文档的主题风格,小程序在线客服自动回复作用。
阅读文章本文本文档以前,最好是早已掌握过小程序客服信息官方网的相关的文本文档:
1.在线客服信息操作指南
2.小程序在线客服信息服务器端插口
3.在线客服信息开发文本
此次开发设计做在线客服作用也踩了许多坑,在网上也查看许多材料,但绝大多数的后台管理全是根据php或是python,java开发,node.js开发设计的偏少,因而将此次开发设计的步骤记录一下,供大伙儿参照,防止大伙儿踩坑。也许会出现一些不正确地区热烈欢迎纠正沟通交流。 此外,大家用的node架构是根据koa自主封装形式的,在一些关键点完成上和别的架构会出现差别,无须担心。
需求描述
小程序中心点按键跳转在线客服页面,依据关键字自动回复 客服回复判断条件,适用cms配置key,及 respond respond 适用配置下列种类,及回应具体内容:
type具体内容texttext=文字回应具体内容linktitle=文章标题 description=叙述 url=跳转连接 thumb_url=图片地址imageimageurl=图片地址
- 配置后客户必须精准匹配回应标准才可接到自动回复
- 可适用配置好几个key,及相匹配respond
- 除开配置的key之外的回应,可配置默认设置的自动回复
开发流程
写个跳转在线客服的按键吧
index.wxml
<button open-type=\"contact\">转在线客服</button>
复制代码
后台管理配置
登陆小程序后台管理后,在「开发设计」-「开发设计设定」-「消息提醒」中,管理人员扫二维码开启信息服务项目,填好服务器ip(URL)、动态口令(Token) 和 信息数据加密密匙(EncodingAESKey)等信息内容。
- URL服务器ip
URL: 开发人员用于接受微信消息和事件的插口 URL。开发人员所填好的URL 务必以 http:// 或 https:// 开始,各自适用 80 端口号和 443 端口号。
务必要记牢,服务器ip必须是网上详细地址,由于必须微信服务器去浏览。localhost,IP,内网地址都不行的。
要不然会提醒 ‘解析失败,请检查信息内容是不是填好恰当’。
问题来了,不一样的企业都是有一套发布步骤,总不能为了能调节URL是否可用要上到线上来检测,成本费很大,也不方便。
这就需要引出来内网穿透了,简单来说便是配置一个网上网站域名,可是这一网站域名能够透过到你配置的当地开发设计详细地址上,这样可以便捷你来调节看日志。 推荐一个能够完成内网穿透的专用工具。(非广告宣传 )
NATAPP 实际不详解,省得广告宣传行为。
简单说,NATAPP有不要钱和收费二种方式,完全免费的是网站域名不定时拆换,针对手机微信的推送消息配置一个月仅有3次变更机遇而言,有点儿奢华。不确定何时配置的网站域名就无法浏览,得再次配置。而付钱的乃是固定不动网站域名,投射的内网地址还可以随时随地变更。小编从完全免费切出付费模式,一个月的VIP应用大约十几块钱钱。
2.Token
Token自身随便写就可以了,可是要记住它,由于你在插口时要用的。
3.EncodingAESKey
随机生成就可以。
4.加密算法和数据类型
依据自己喜欢挑选,小编选用的安全中心和JSON文件格式。 不一样的玩法和数据类型,在开发设计上会出现不一样,自身考量。 即然这种配置都清晰,那逐渐码编码。
验证消息确实来源于微信服务器
配置递交前,必须把验证消息来源于微信服务器的插口写好。
server.js
/*
* https://developers.weixin.qq.com/miniprogram/dev/framework/server-ability/message-push.html
* 验证消息确实来源于微信服务器
* 开发人员根据检测 signature 对申请开展校检(下边有校检方法)。
* 若确定本次 GET 要求来源于微信服务器,请原状回到 echostr 主要参数具体内容,
* 则连接起效,变成开发人员取得成功,不然连接不成功。数据加密/校检步骤如下所示:
* 将token、timestamp、nonce三个主要参数开展词典序排列
* 将三个主要参数字符串拼接成一个字符串数组开展sha1数据加密
* 开发人员得到数据加密后的字符串数组可与signature比照,标志该要求来自手机微信
*/
const crypto = require(\'crypto\');
async wxCallbackAction(){
const ctx = this.ctx;
const method = ctx.method;
//微信服务器签字认证,确定要求来源于手机微信
if(method === \'GET\') {
// 1.获得微信服务器Get要求的主要参数 signature、timestamp、nonce、echostr
const {
signature,
timestamp,
nonce,
echostr
} = ctx.query;
// 2.将token、timestamp、nonce三个主要参数开展词典序排列
let array = [\'yourToken\', timestamp, nonce];
array.sort();
// 3.将三个主要参数字符串拼接成一个字符串数组开展sha1数据加密
const tempStr = array.join(\'\');
const hashCode = crypto.createHash(\'sha1\'); //建立数据加密种类
const resultCode = hashCode.update(tempStr, \'utf8\').digest(\'hex\');
// 4.开发人员得到数据加密后的字符串数组可与signature比照,标志该要求来自手机微信
if (resultCode === signature) {
console.log(\'验证通过,信息是以微信服务器分享来\');
return this.json(echostr);
}else {
console.log(\'验证失败!!!\');
return this.json({
status: -1,
message: \"验证失败\"
});
}
}
}
复制代码
认证接口开发结束,后台管理配置可以去点提交了。配置取得成功会显示如下所示:
接受信息和推送消息
当消费者在客户服务对话发送消息、或由一些特殊的客户实际操作引起事情消息推送时,微信服务器会将信息或事情的数据发送至开发人员填好的 URL。开发人员接到要求后需要用 推送在线客服信息 插口开展多线程回应。
文中以接受文字信息为例子开发设计:
server.js
const WXDecryptContact = require(\'./WXDecryptContact\');
async wxCallbackAction(){
const ctx = this.ctx;
const method = ctx.method;
//接收信息时为POST要求;(详细编码自主与上边认证时的合拼就可以)
if(method === \'POST\'){
const { Encrypt } = ctx.request.body;
//配置时选的安全中心 因而必须破译
if(!Encrypt){
return this.json(\'success\');
}
const decryptData = WXDecryptContact(Encrypt);
await this._handleWxMsg(decryptData);
return this.json(\'success\');
}
}
//解决微信回调最新消息的总入口处 (只处理了文本类型,其他类型自行添加)
async _handleWxMsg(msgJson){
if(!msgJson){
return ;
}
const { MsgType } = msgJson;
if(MsgType === \'text\'){
await this._sendTextMessage(msgJson);
}
}
//微信文本信息关键词全自动回复
async _sendTextMessage(msgJson){
//获取CMS客服关键词回复配置
const result = await this.callService(\'cms.getDataByName\', \'wxApplet.contact\');
let keyWordObj = result.data || {};
//默认设置回复default
let options = keyWordObj.default;
for(let key in keyWordObj){
//查询是不是击中配置的关键词
if(msgJson.Content === key){
//CMS配置项
options = keyWordObj[key];
}
}
}
//获取access_token
const accessToken = await this._getAccessToken();
/*
* 先分辨配置回复的信息种类是否image类型
* 如果是 则必须先根据 新增加素材内容插口 上传照片文档得到 media_id
*/
let media_id = \'\';
if(options.type === \'image\'){
//获取图片地址(绝对路径)
let url = options.url;
const file = fs.createReadStream(url);
//启用手机微信 uploadTempMedia接口 实际完成见 service.js
const mediaResult = await this.callService(\'wxApplet.uploadTempMedia\',
{
access_token: accessToken,
type: \'image\'
},
{
media: file
}
);
if(mediaResult.status === 0){
media_id = mediaResult.data.media_id;
}else {
//假如照片id获取不成功 则按默认设置解决
options = keyWordObj.default;
}
}
//回复信息给客户
const sendMsgResult = await this.callService(\'wxApplet.sendMessageToCustomer\',
{
access_token: accessToken,
touser: msgJson.FromUserName,
msgtype: options.type || \'text\',
text: {
content: options.description || \'\',
},
link: options.type === \"link\" ?
{
title: options.title,
description: options.description,
url: options.url,
thumb_url: options.thumb_url
}
:
{},
image: {
media_id
}
}
);
}
复制代码
service.js
const request = require(\'request\');
/*
* 获取CMS客服关键词回复配置
* 这一插口仅仅为了能回家CMS配置的字段名回复关键词配置 返回的data数据构造如下所示
*/
async contact(){
return {
data: {
\"1\": {
\"type\": \"link\",
\"title\": \"立即下载[****]APP\",
\"description\": \"申请注册领到领***元注册红包礼\",
\"url\": \"https://m.renrendai.com/mo/***.html\",
\"thumb_url\": \"https://m.we.com/***/test.png\"
},
\"2\": {
\"url\": \"http://m.renrendai.com/cms/****/test.jpg\",
\"type\": \"image\"
},
\"3\": {
\"url\": \"/cms/***/test02.png\",
\"type\": \"image\"
},
\"default\": {
\"type\": \"text\",
\"description\": \"再会\"
}
}
}
}
/*
* 把新闻媒体上传文件到微信服务器。现阶段仅适用照片。用以推送客服信息或处于被动回复客户信息。
* https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/customer-message/customerServiceMessage.uploadTempMedia.html
*/
async uploadTempMedia(data,formData){
const url = `https://api.weixin.qq.com/cgi-bin/media/upload?access_token=${data.access_token}&type=${data.type}`;
return new Promise((resolve, reject) => {
request.post({url, formData: formData}, (err, response, body) => {
try{
const out = JSON.parse(body);
let result = {
data: out,
status: 0,
message: \"ok\"
}
return resolve(result);
}catch(err){
return reject({
status: -1,
message: err.message
});
}
});
}
}
/*
* 推送客服信息给使用者
* https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/customer-message/customerServiceMessage.send.html
*/
async sendMessageToCustomer(data){
const url = `https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=${data.access_token}`;
return new Promise((resolve, reject) => {
request.post({url, data}, (err, response, body) => {
...
});
}
}
复制代码
WXDecryptContact.js
信息加密解密文本文档
const crypto = require(\'crypto\'); // 数据加密控制模块
const decodePKCS7 = function (buff) {
let pad = buff[buff.length - 1];
if (pad < 1 || pad > 32) {
pad = 0;
}
return buff.slice(0, buff.length - pad);
};
// 朋友圈转发客服信息破译
const decryptContact = (key, iv, crypted) => {
const aesCipher = crypto.createDecipheriv(\'aes-256-cbc\', key, iv);
aesCipher.setAutoPadding(false);
let decipheredBuff = Buffer.concat([aesCipher.update(crypted, \'base64\'), aesCipher.final()]);
decipheredBuff = decodePKCS7(decipheredBuff);
const lenNetOrderCorpid = decipheredBuff.slice(16);
const msgLen = lenNetOrderCorpid.slice(0, 4).readUInt32BE(0);
const result = lenNetOrderCorpid.slice(4, msgLen 4).toString();
return result;
};
// 破译微信返回给配置的信息服务器的信息
const decryptWXContact = (wechatData) => {
if(!wechatData){
wechatData = \'\';
}
//EncodingAESKey 为后台管理配备时随机生成的
const key = Buffer.from(EncodingAESKey \'=\', \'base64\');
const iv = key.slice(0, 16);
const result = decryptContact(key, iv, wechatData);
const decryptedResult = JSON.parse(result);
console.log(decryptedResult);
return decryptedResult;
};
module.exports = decryptWXContact;
复制代码
汇总
开发设计并非一帆风顺的,也遇到了一些需要留心的坑,注重一下:
- 后台管理配备URL详细地址一定外网地址可浏览(能通过内网穿透处理)
- 上传文件插口uploadTempMedia media主要参数得用 FormData数据文件格式 (用node的request库非常容易完成。urllib这一库有坑有坑 都是泪T_T)
- 谨记接收消息无论成功与失败都需要返回success,要不然即便取得成功接收返回消息,日志并没有出错的情况下,或是发生IOS提醒该微信小程序给予的服务项目出现异常 请稍后重试。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。