unicloud云函数开发微信客服消息自动回复图片消息完整步骤

最近搞得小程序开通流量主之后,想着给公众号引流一下,就要从小程序能够去关注公众号咯。但是小程序的机制大家懂的,不能直接跳转到公众号哦,那就只能找客服回复一个二维码图片咯!!!

配置一下

unicloud配置
  1. 先在项目uniCloud下面的云函数文件夹中右键添加云函数

  1. 在弹出层中新建一个名称为 contact 的云函数(名称随便取都行)

  1. 创建好之后,在contact云函数文件夹上右键上传云函数

  1. 云函数代码如下:

  1. 暂时不写云函数代码,先去unicloud后台配置小程序需要的URL数据

  1. 在右侧目录找到云函数 - 函数列表之后,找到contact云函数,点击详情按钮

  1. 找到云函数URL化模块,点击编辑

  1. 在输入框中输入 /contact 注意:此处必须用/开头,名称可以随便取

  1. 点击确定之后,在点击PATH后面的复制路径按钮

此时,uniCloud配置完成,下面开始配置小程序

小程序配置
  1. 微信公众平台登录自己的小程序账号
  2. 在左侧菜单栏找到开发 - 开发管理

  1. 进入开发管理之后切换tab到开发设置

  1. 找到消息推送,点击启用

  1. 跳转到消息推送配置页面之后,按照图片方式进行配置

此时点击提交,会提示你Token校验失败,请检查确认,不要慌,只是云函数里面没有写而已。这个时候就可以去写云函数的代码了~~

开始写云函数

如果对消息来源要求不高,或者不考虑安全性,可以直接在云函数中返回 event.queryStringParameters.echostr

云函数代码如下:

'use strict';
exports.main = async (event, context) => {
  //event为客户端上传的参数
  console.log('event : ', event)
  
  //返回数据给客户端
  return event.queryStringParameters.echostr;
};

校验安全性也很简单的

1. 将token、timestamp、nonce三个参数进行字典序排序

2. 将三个参数字符串拼接成一个字符串进行sha1加密

3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

云函数代码如下:

'use strict';
//npm install sha1
const sha1 = require("sha1");
const token = "123qweASD";

function verifyMSGSender(params){
  const mysignature = sha1([token,params.timestamp,params.nonce].sort().join(""));
  
  console.log(mysignature===params.signature?"校验通过":"校验失败");
  
  if(mysignature===params.signature)return true;
  else return false;
}

exports.main = async (event, context) => {
  //event为客户端上传的参数
  if(!verifyMSGSender(event.queryStringParameters))return "来源校验失败";
  //校验通过后,下面这行返回echostr的代码注释掉
  else return event.queryStringParameters.echostr;
  
  //返回数据给客户端
  return;
};

注意:token需要和消息配置页面的token保持一致哦~

此时就可以去消息配置里面点击保存按钮啦!!!

配置完成后是这样的

校验通过之后,代码里面的 echostr 代码就可以注释掉了

//校验通过后,下面这行返回echostr的代码注释掉
else return event.queryStringParameters.echostr;

此时给客服发消息之后,在云函数日志里面可以看到返回结果了

但是这个结果是一个字符串的,我们需要把字符串转为json格式

// 解析json格式字符串
const receiveMsg = JSON.parse(event.body);

数据包返回格式

根据用户发送的消息,会有以下格式

{// 文本消息返回数据包

  "ToUserName": "toUser",

  "FromUserName": "fromUser",//客服消息发起者的openid

  "CreateTime": 1482048670,

  "MsgType": "text",//该条消息类型

  "Content": "this is a test",

  "MsgId": 1234567890123456

}
{// 图片消息返回数据包

  "ToUserName": "toUser",

  "FromUserName": "fromUser",//客服消息发起者的openid

  "CreateTime": 1482048670,

  "MsgType": "image",//该条消息类型

  "PicUrl": "this is a url",

  "MediaId": "media_id",//微信媒体资源id

  "MsgId": 1234567890123456

}
// 小程序卡片消息button按钮配置
<button 
  size="mini" 
  type="primary" 
  :plain="true" 
  open-type="contact" 
  :session-from="" 
  :show-message-card="true" 
  :send-message-title="title">
  查看
 </button>
 
 {// 小程序卡片消息返回数据包

  "ToUserName": "toUser",

  "FromUserName": "fromUser",//客服消息发起者的openid

  "CreateTime": 1482048670,

  "MsgType": "miniprogrampage",//该条消息类型

  "MsgId": 1234567890123456,

  "Title":"title",//小程序卡片标题

  "AppId":"appid",//小程序appid

  "PagePath":"path",//小程序卡片跳转页面

  "ThumbUrl":"",//小程序卡片缩略图

  "ThumbMediaId":""

}
{// 客服消息进入会话事件

  "ToUserName": "toUser",

  "FromUserName": "fromUser",//客服消息发起者的openid

  "CreateTime": 1482048670,

  "MsgType": "event",//该条消息类型

  "Event": "user_enter_tempsession",

  "SessionFrom": "sessionFrom"//开发者在客服会话按钮设置的 session-from 属性

}

回复客服消息

微信客服消息文档

先获取access_token

微信获取access_token文档

注意:APPID和APPSECRET配置在微信公众平台开发管理里面获取

const tokenUrl = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' + APPID + '&secret=' + APPSECRET;
// uniCloud.httpclient 发起请求
const res1 = await uniCloud.httpclient.request(tokenUrl,
{
	method: 'GET',
	dataType:"json"
});
//返回数据给客户端
const access_token = res1.data.access_token;
开始回复消息
const access_token = res1.data.access_token
const res2 = await uniCloud.httpclient.request("https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token="+access_token,{
    method:"POST",
    headers:{
      "Content-Type":"application/json"
    },
    dataType:"json",
    data:{
      touser:touser,//接收此消息用户的openid
      msgtype:"text",//此消息的类型
      text:{
        content:"回复的文本内容",
      }
    }
});

回复消息的种类有很多,text文本消息,img图片消息,link链接消息,miniprogrampage小程序卡片消息。下面只说回复图片消息(这个在大部分教程里面都没写过,其他的可以自行在掘金上搜索)

在做图片消息自动回复之前,根据微信文档描述,需要现将图片上传到临时文件服务器,而且图片保存时间有效期只有三天

上传图片信息

微信客服上传临时图片文档

在请求参数中可以看到,我们需要传一个media的参数,而且是FormData类型的,但是我们不会在小程序上添加一个input框来用作上传图片,所以需要借助nodeJS的form-data模块

注意:在微信小程序中,不能直接在代码中写 new FormData() ,需要自行安装模块

  1. 首先将需要的图片上传到unicloud云存储中,获取到对应的URL

const img_url = 'https://云存储路径.jpg'

  1. 将图片链接转为Buffer
const url = await uniCloud.httpclient.request(img_url)
let buff = new Buffer(url.data);
  1. 将buff传入formData
// 此处的FormData需要安装到当前云函数文件夹中
// npm install form-data
let form = new FormData()
// 将 media 参数、buff信息、formdata中需要包含的filename、图片信息打包
form.append('media', buff, {
	filename: `${Date.now()}.jpg`,
	contentType: 'image/jpeg'
})
  1. 请求上传客服临时文件接口,将formdata信息上传,获取到media_id
// 请求微信服务器API,将formdata信息上传,获取到media_id
const imgRes = await uniCloud.httpclient.request("https://api.weixin.qq.com/cgi-bin/media/upload?access_token=" + access_token + '&type=image', {
	method: "POST",
	headers: form.getHeaders(),
	dataType: 'json',
	content: form.getBuffer()
});
return imgRes.data.media_id
  1. 判断用户发送的消息,然后回复图片

注意:我这里判断的是用户发送 2 之后,回复消息

// 判断用户发送的消息内容
if(receiveMsg.Content === '2'){
	// 调用获取media_id的方法
	// 因为方法是一个promise,所以调用的时候需要加上 await 前缀
	let media_id = await uploadTempImg(url, access_token)
	if(media_id){
		// 发送消息
		const res2 = await uniCloud.httpclient.request("https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + access_token, {
			method: "POST",
			headers: {
				"Content-Type": "application/json"
			},
			dataType: "json",
			data: {
				touser: receiveMsg.FromUserName, //接收此消息用户的openid
				msgtype: "image", //此消息的类型
				image: {
					media_id: media_id
				}
			}
                });
	}
}
自动回复的小机器人就出现了

完整代码

'use strict';
// 需要先执行初始化 npm init -y 生成packages.json文件后
// 再执行安装 npm install sha1
// 安装在当前目录哦。。不是全局安装的
const sha1 = require("sha1");
const FormData = require("form-data");
const token = "123qweASD";
const db = uniCloud.database();

function verifyMSGSender(params) {
	const mysignature = sha1([token, params.timestamp, params.nonce].sort().join(""));

	console.log(mysignature === params.signature ? "校验通过" : "校验失败");

	if (mysignature === params.signature) return true;
	else return false;
}

async function uploadTempImg(img_url, access_token){
	// 现将图片链接转为buffer
	const url = await uniCloud.httpclient.request(img_url)
	let buff = new Buffer(url.data);
	// 此处的FormData需要安装到当前云函数文件夹中
	// npm install form-data
	let form = new FormData()
	// 将 media 参数、buff信息、formdata中需要包含的filename、图片信息打包
	form.append('media', buff, {
		filename: `${Date.now()}.jpg`,
		contentType: 'image/jpeg'
	})
	// 请求微信服务器API,将formdata信息上传,获取到media_id
	const imgRes = await uniCloud.httpclient.request(
		"https://api.weixin.qq.com/cgi-bin/media/upload?access_token=" + access_token + '&type=image', {
			method: "POST",
			headers: form.getHeaders(),
			dataType: 'json',
			content: form.getBuffer()
		});
		return imgRes.data.media_id
}

exports.main = async (event, context) => {
	// 获取config中配置的appid和appSecret
	let appId = await db.collection('wx_config').where({
		'key': 'wxId'
	}).get()
	let appSecret = await db.collection('wx_config').where({
		'key': 'wxSecret'
	}).get()
	const APPID = appId.data[0].val
	const APPSECRET = appSecret.data[0].val
	const tokenUrl = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' + APPID + '&secret=' + APPSECRET;
	// uniCloud.httpclient 发起请求
	const res1 = await uniCloud.httpclient.request(tokenUrl,
	{
		method: 'GET',
		dataType:"json"
	});
	//返回数据给客户端
	const access_token = res1.data.access_token;

	//event为客户端上传的参数
	if (!verifyMSGSender(event.queryStringParameters)) return "来源校验失败";
	//校验通过后,下面这行返回echostr的代码注释掉
	// else return event.queryStringParameters.echostr;

	// 解析json格式字符串
	const receiveMsg = JSON.parse(event.body);
	const url = 'https://vkceyugu.cdn.bspapp.com/VKCEYUGU-a8a16cef-f2b9-4644-b216-3b95bcb12602/eed2e97a-be28-4e6d-beb3-ca338d195858.jpg'
	// 判断用户发送的消息内容
	if(receiveMsg.Content === '2'){
		// 调用获取media_id的方法
		// 因为方法是一个promise,所以调用的时候需要加上 await 前缀
		let media_id = await uploadTempImg(url, access_token)
		if(media_id){
			// 发送消息
			const res2 = await uniCloud.httpclient.request(
				"https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + access_token, {
					method: "POST",
					headers: {
						"Content-Type": "application/json"
					},
					dataType: "json",
					data: {
						touser: receiveMsg.FromUserName, //接收此消息用户的openid
						msgtype: "image", //此消息的类型
						image: {
							media_id: media_id
						}
					}
				});
		}
	}

	//返回数据给客户端
	return;
};

原文地址:https://cloud.tencent.com/developer/article/2110955

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340