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;