1.小程序客服发送消息(2023-06-09)
接口说明
当前需求是当我点击某个按钮的时候,跳转到小程序客服页面,然后触发客服发送消息事件,然后客服会想你发送一个你想要的内容。
首先在发送这个客服消息的时候,他是一个事件,你需要去做一些操作进行触发。通过配置让微信每次进入客服消息界面的时候都会发送数据包,根据数据包中的Event时间来判断是否是要发送客服消息,是的话发送客服消息。这个前提是你在客服界面和页面进行交互, 当前交互是用户主动和客服发送一个任意消息包括文字,图片,小程序等,完成交互之后,48小时之内客服可以给用户发送5次消息。当然这个配置,让每次进入客服页面都会触发这个事件。
接口英文名
sendCustomMessage
功能描述
该接口用于发送客服消息给用户。详细规则见 发送客服消息
注意事项
- 发送文本消息时,支持添加可跳转小程序的文字连接.
- data-miniprogram-appid 项,填写小程序appid,则表示该链接跳转小程序
- data-miniprogram-path项,填写小程序路径,路径与app.json中保持一致,可带参数;
- 对于不支持 data-miniprogram-appid 项的客户端版本(6.5.16 以下),如果有 herf 项,则仍然保持跳 href 中的链接;
- 小程序发带小程序文字链的文本消息,data-miniprogram-appid必须是该小程序的appid
调用方式
HTTPS 调用
POST https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN
第三方调用
- 调用方式以及出入参和HTTPS相同,仅是调用的token不同
- 该接口所属的权限集id为:1、6、19、59、100、101
- 服务商获得其中之一权限集授权后,可通过使用authorizer_access_token代商家进行调用
请求参数
属性 | 类型 | 必填 | 说明 | |
access_token | string | 是 | 接口调用凭证,该参数为 URL 参数,非 Body 参数。使用getAccessToken 或者 authorizer_access_token | |
touser | string | 是 | 用户的 OpenID | |
msgtype | string | 是 | 消息类型。text表示文本消息;image表示图片消息;link表示图文链接;miniprogrampage表示小程序卡片。 | |
text | object | 否 | 文本消息,msgtype=“text” 时必填 | |
属性类型必填说明contentstring否文本消息内容。msgtype=“text” 时必填 | ||||
image | object | 否 | 图片消息,msgtype=“image” 时必填 | |
属性类型必填说明media_idstring否发送的图片的媒体ID,通过 uploadTempMedia上传图片文件获得。 | ||||
link | object | 否 | 图文链接,msgtype=“link” 时必填 | |
属性类型必填说明titlestring否消息标题descriptionstring否图文链接消息urlstring否图文链接消息被点击后跳转的链接thumb_urlstring否图文链接消息的图片链接,支持 JPG、PNG 格式,较好的效果为大图 640 X 320,小图 80 X 80 | ||||
miniprogrampage | object | 否 | 小程序卡片,msgtype=“miniprogrampage” 时必填 | |
属性类型必填说明titlestring否消息标题pagepathstring否小程序的页面路径,跟app.json对齐,支持参数,比如pages/index/index?foo=barthumb_media_idstring否小程序消息卡片的封面, image 类型的 media_id,通过 uploadTempMedia接口上传图片文件获得,建议大小为 520*416 |
返回参数
属性 | 类型 | 说明 |
errcode | number | 错误码 |
errmsg | string | 错误信息 |
调用示例
示例说明: 发送文本消息
请求数据示例
{
"touser":"OPENID",
"msgtype":"text",
"text":
{
"content":"Hello World"
}
}
返回数据示例
{
"errcode":0,
"errmsg":"ok"
}
示例说明: 发送图片消息
请求数据示例
{
"touser":"OPENID",
"msgtype":"image",
"image": {
"media_id":"MEDIA_ID"
}
}
返回数据示例
{
"errcode":0,
"errmsg":"ok"
}
示例说明: 发送图文链接
请求数据示例
{
"touser": "OPENID",
"msgtype": "link",
"link": {
"title": "Happy Day",
"description": "Is Really A Happy Day",
"url": "URL",
"thumb_url": "THUMB_URL"
}
}
返回数据示例
{
"errcode":0,
"errmsg":"ok"
}
示例说明: 发送小程序卡片
请求数据示例
{
"touser":"OPENID",
"msgtype":"miniprogrampage",
"miniprogrampage": {
"title":"title",
"pagepath":"pagepath",
"thumb_media_id":"thumb_media_id"
}
}
返回数据示例
{
"errcode":0,
"errmsg":"ok"
}
错误码
错误码 | 错误码取值 | 解决方案 |
-1 | system error | 系统繁忙,此时请开发者稍候再试 |
40001 | invalid credential access_token isinvalid or not latest | 获取 access_token 时 AppSecret 错误,或者 access_token 无效。请开发者认真比对 AppSecret 的正确性,或查看是否正在为恰当的公众号调用接口 |
40013 | invalid appid | 不合法的 AppID ,请开发者检查 AppID 的正确性,避免异常字符,注意大小写 |
代码示例
@PostMapping("/sendCsMessage")
public ActionData<Object> sendCsMessage(HttpServletRequest request) throws Exception {
String event = request.getParameter("Event");
if(event.equals("user_enter_tempsession")){
Long userId = HmtTenantContextHolder.getTnuserLocal();
//根据用户Id获取该用户的openId
String openId = request.getParameter("FromUserName");
//获取微信accessToken
String accessToken = sendSubscribeMessage.getAccessToken();
//构造参数,向微信发送客服消息
com.alibaba.fastjson.JSONObject jsonObject = new com.alibaba.fastjson.JSONObject();
jsonObject.put("touser",openId);
jsonObject.put("msgtype","link");
//构造link信息的Json数据
com.alibaba.fastjson.JSONObject jsonObject1 = new com.alibaba.fastjson.JSONObject();
jsonObject1.put("title","标题");
jsonObject1.put("description","描述");
jsonObject1.put("url","所要发送的Url链接地址");
jsonObject1.put("thumb_url","链接的图片(便于美观)");
jsonObject.put("link",jsonObject1);
String params = jsonObject.toString();
String response = WxHttpUtils.sendPost("https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" + accessToken, params);
return ActionDataResult.genResult(response,"ok");
}
return ActionDataResult.genResult(null,"fail");
}
这里是微信验证你是否具备解密能力的接口
验证签名工具类
package hmyd.xq.ut;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
/**
* 描述:请求校验工具类.
* @author zrxJuly
* @createDate 2017-12-9
* @since 1.0
*
*/
public class SignUtil {
// 与开发模式接口配置信息中的Token保持一致.
private static String token = "haimaio2023";
/**
* 校验签名
* @param signature 微信加密签名.
* @param timestamp 时间戳.
* @param nonce 随机数.
* @return
*/
public static boolean checkSignature(String signature, String timestamp, String nonce) {
// 对token、timestamp、和nonce按字典排序.
String[] paramArr = new String[] {token, timestamp, nonce};
Arrays.sort(paramArr);
// 将排序后的结果拼接成一个字符串.
String content = paramArr[0].concat(paramArr[1]).concat(paramArr[2]);
String ciphertext = null;
try {
MessageDigest md = MessageDigest.getInstance("SHA-1");
// 对拼接后的字符串进行sha1加密.
byte[] digest = md.digest(content.toString().getBytes());
ciphertext = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
// 将sha1加密后的字符串与signature进行对比.
return ciphertext != null ? ciphertext.equals(signature.toUpperCase()) : false;
}
/**
* 将字节数组转换为十六进制字符串.
* @param byteArray
* @return
*/
private static String byteToStr(byte[] byteArray) {
String strDigest = "";
for (int i = 0; i < byteArray.length; i++) {
strDigest += byteToHexStr(byteArray[i]);
}
return strDigest;
}
/**
* 将字节转换为十六进制字符串.
* @param mByte
* @return
*/
private static String byteToHexStr(byte mByte) {
char[] Digit = { '0', '1' , '2', '3', '4' , '5', '6', '7' , '8', '9', 'A' , 'B', 'C', 'D' , 'E', 'F'};
char[] tempArr = new char[2];
tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
tempArr[1] = Digit[mByte & 0X0F];
String s = new String(tempArr);
return s;
}
}
System.out.println("=======开始请求校验======");
// 微信加密签名.
String signature = request.getParameter("signature");
System.out.println("signature====" + signature);
// 时间戳.
String timestamp = request.getParameter("timestamp");
System.out.println("timestamp====" + timestamp);
// 随机数.
String nonce = request.getParameter("nonce");
System.out.println("nonce====" + nonce);
// 随机字符串.
String echostr = request.getParameter("echostr");
System.out.println("echostr====" + echostr);
PrintWriter out = response.getWriter();
// 请求校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败.
if (SignUtil.checkSignature(signature, timestamp, nonce)) {
System.out.println("=======请求校验成功======" + echostr);
out.print(echostr);
}
out.close();
out = null;