微信公众平台--客服接口(发送消息)

前言:
小伙伴们如果有什么问题,欢迎评论区留言。

步骤:
讲解部分
(1) 我今天要做的是调用微信公众平台-客服接口发送消息(文本消息,菜单消息,图片消息),其他的读者可以在此基础上自行发挥。:官方文档地址

(2)一些参数。

AppId 和AppSecret用来获取AccessToken 地址
需要一个OpenId (在微信公众平台中每个用户的唯一标识)。之所以用到这个是因为我们要告诉微信公众平台我们需 要 将该消息发送给哪个用户
代码部分
(1) 控制层
@ApiOperation(value = "1.7 客服接口-发送消息")
@GetMapping(value = "/sendCustomerProviderNews")
public void sendCustomerProviderNews() {
//1.客服接口-发送文本消息
// customerProviderService.sendCustomerProviderNews("1");
//2.发送图片消息
customerProviderService.sendCustomerProviderNews("2");
//7.发送菜单消息
// customerProviderService.sendCustomerProviderNews("7");


}
(2) 业务逻辑层
package com.bos.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.bos.common.ResultData;
import com.bos.data.model.weixin.ServiceProvider.*;
import com.bos.service.CustomerProviderService;
import com.bos.util.QiYeWeiUtil;
import com.bos.util.SendRequest;
import com.bos.util.WeiXinParamesUtil;
import com.google.gson.JsonObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
* @Author tanghh
* @Date 2020/2/14 10:32
*/
@Service
public class CustomerProviderServiceImpl implements CustomerProviderService {
private Logger logger = LoggerFactory.getLogger(CustomerProviderServiceImpl.class);

/**
* 客户接口-发送消息
* https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Service_Center_messages.html#7
* @param type
* @return
*/
@Override
public void sendCustomerProviderNews(String type) {
try{
String toUser ="用户OpenID";
String accessToken = WeiXinParamesUtil.getAccessToken2("weixin");
String url = WeiXinParamesUtil.sendCustomerMsgUrl;
url = url.replace("ACCESS_TOKEN",accessToken);
//普通的文本消息
if(type.equals("1")){
ServiceTextMessage serviceTextMessage = new ServiceTextMessage();
serviceTextMessage.setTouser(toUser);

ServiceText text = new ServiceText();
text.setContent("中国加油");
serviceTextMessage.setText(text);

String jsonStr = JSONObject.toJSONString(serviceTextMessage);
JSONObject jsonObject = SendRequest.sendPost(url,jsonStr);
}else if(type.equals("2")){
//发送图片消息

//获取图片的media_id
//上传到微信公众平台服务器上
//1.创建本地文件
File file = new File("C://uploadFile/QiWeiFiles/bf9d099ace3cbfe8ce37d7c02687c986_7740.png");
//2.拼接请求url
String uploadMaterialToWeiUrl = WeiXinParamesUtil.uploadMaterialToWeiUrl.replace("ACCESS_TOKEN", accessToken)
.replace("TYPE", "image");
//3.调用接口,发送请求,上传文件到微信服务器
String result = QiYeWeiUtil.httpRequest(uploadMaterialToWeiUrl, file);
//4.json字符串转对象:解析返回值,json反序列化
result = result.replaceAll("[\\\\]", "");
JSONObject resultJSON = JSONObject.parseObject(result);

String media_id = (String) resultJSON.get("media_id");

ServiceImageMessage serviceImageMessage = new ServiceImageMessage();
serviceImageMessage.setTouser(toUser);

ServiceImage serviceImage = new ServiceImage();
serviceImage.setMedia_id(media_id);

serviceImageMessage.setImage(serviceImage);

String jsonStr = JSONObject.toJSONString(serviceImageMessage);
JSONObject jsonObject = SendRequest.sendPost(url,jsonStr);
}else if(type.equals("3")){
//发送语言消息

}else if(type.equals("4")){
//发送视频消息

}else if(type.equals("5")){
//发送音乐消息
}else if(type.equals("6")){
//发送图文消息

}else if(type.equals("7")){
//发送菜单消息
ServiceMenuMessage serviceMenuMessage = new ServiceMenuMessage();
serviceMenuMessage.setTouser(toUser);

ServiceMenu serviceMenu = new ServiceMenu();
serviceMenu.setHead_content("您对本次服务是否满意呢?");

List<ServiceMenuContent> list = new ArrayList<>();
ServiceMenuContent content1 = new ServiceMenuContent();
content1.setId(101);
content1.setContent("满意");
ServiceMenuContent content2 = new ServiceMenuContent();
content2.setId(101);
content2.setContent("不满意");
list.add(content1);
list.add(content2);
serviceMenu.setList(list);
serviceMenu.setTail_content("欢迎再次光临");

serviceMenuMessage.setMsgmenu(serviceMenu);

String jsonStr = JSONObject.toJSONString(serviceMenuMessage);
JSONObject jsonObject = SendRequest.sendPost(url,jsonStr);
}else if(type.equals("8")){

}
}catch (Exception e){
logger.error("客户接口发送消息失败",e);
}
}
}
(3) 发送文本消息
ServiceTextMessage

package com.bos.data.model.weixin.ServiceProvider;

import lombok.Data;

/**
* @Author tanghh
* @Date 2020/2/14 10:39
*/
@Data
public class ServiceTextMessage {
/**
* 发送方用户名
*/
private String touser;
/**
* 发送消息类型
*/
private String msgtype="text";
/**
* 文本
*/
private ServiceText text;

}
ServiceText

 

package com.bos.data.model.weixin.ServiceProvider;

import lombok.Data;

/**
* @Author tanghh
* @Date 2020/2/14 10:41
*/
@Data
public class ServiceText {
/**
* 发送消息内容
*/
private String content;
}

(4) 图片消息
ServiceImageMessage

package com.bos.data.model.weixin.ServiceProvider;

import lombok.Data;

/**
* @Author tanghh
* @Date 2020/2/14 16:03
*/
@Data
public class ServiceImageMessage {
private String touser;
private String msgtype="image";
private ServiceImage image;
}
ServiceImage

package com.bos.data.model.weixin.ServiceProvider;

import lombok.Data;

/**
* @Author tanghh
* @Date 2020/2/14 16:04
*/
@Data
public class ServiceImage {
private String media_id;
}

(5) 菜单消息
ServiceMenuMessage

package com.bos.data.model.weixin.ServiceProvider;

import lombok.Data;

/**
* @Author tanghh
* @Date 2020/2/14 11:45
*/
@Data
public class ServiceMenuMessage {
private String touser;
private String msgtype="msgmenu";
private ServiceMenu msgmenu;
}

ServiceMenu

package com.bos.data.model.weixin.ServiceProvider;

import lombok.Data;

import java.util.List;

/**
* @Author tanghh
* @Date 2020/2/14 11:46
*/
@Data
public class ServiceMenu {
private String head_content;
private List<ServiceMenuContent> list;
private String tail_content;
}
ServiceMenuContent

package com.bos.data.model.weixin.ServiceProvider;

import lombok.Data;

/**
* @Author tanghh
* @Date 2020/2/14 11:47
*/
@Data
public class ServiceMenuContent {
private Integer id;
private String content;
}
(6)上传文件素材的代码
package com.bos.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bos.data.model.weixin.send.SendBaseMessage;
import com.bos.qiWechat.AesException;
import com.bos.qiWechat.WXBizMsgCrypt;
import com.bos.wechat.MyX509TrustManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

/**
* @author tanghh
* @Date: 2019/4/17
*/
public class QiYeWeiUtil {
private static Logger logger= LoggerFactory.getLogger(QiYeWeiUtil.class);
// 微信加密签名
private String msg_signature;
// 时间戳
private String timestamp;
// 随机数
private String nonce;
/**
* 1.企业微信上传素材的请求方法
* @param
* @return
*/
public static String httpRequest(String requestUrl, File file) {
StringBuffer buffer = new StringBuffer();

try{
//1.建立连接
URL url = new URL(requestUrl);
//打开链接
HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();

//1.1输入输出设置
httpUrlConn.setDoInput(true);
httpUrlConn.setDoOutput(true);
// post方式不能使用缓存
httpUrlConn.setUseCaches(false);
//1.2设置请求头信息
httpUrlConn.setRequestProperty("Connection", "Keep-Alive");
httpUrlConn.setRequestProperty("Charset", "UTF-8");
//1.3设置边界
String BOUNDARY = "----------" + System.currentTimeMillis();
httpUrlConn.setRequestProperty("Content-Type","multipart/form-data; boundary="+ BOUNDARY);

// 请求正文信息
// 第一部分:
//2.将文件头输出到微信服务器
StringBuilder sb = new StringBuilder();
// 必须多两道线
sb.append("--");
sb.append(BOUNDARY);
sb.append("\r\n");
sb.append("Content-Disposition: form-data;name=\"media\";filelength=\"" + file.length()
+ "\";filename=\""+ file.getName() + "\"\r\n");
sb.append("Content-Type:application/octet-stream\r\n\r\n");
byte[] head = sb.toString().getBytes("utf-8");
// 获得输出流
OutputStream outputStream = new DataOutputStream(httpUrlConn.getOutputStream());
// 将表头写入输出流中:输出表头
outputStream.write(head);

//3.将文件正文部分输出到微信服务器
// 把文件以流文件的方式 写入到微信服务器中
DataInputStream in = new DataInputStream(new FileInputStream(file));
int bytes = 0;
byte[] bufferOut = new byte[1024];
while ((bytes = in.read(bufferOut)) != -1) {
outputStream.write(bufferOut, 0, bytes);
}
in.close();
//4.将结尾部分输出到微信服务器
// 定义最后数据分隔线
byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("utf-8");
outputStream.write(foot);
outputStream.flush();
outputStream.close();


//5.将微信服务器返回的输入流转换成字符串
InputStream inputStream = httpUrlConn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

String str = null;
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}

bufferedReader.close();
inputStreamReader.close();
// 释放资源
inputStream.close();
inputStream = null;
httpUrlConn.disconnect();


} catch (IOException e) {
System.out.println("发送POST请求出现异常!" + e);
e.printStackTrace();
}
return buffer.toString();
}

/**
* 2.发送https请求之获取临时素材
* @param requestUrl
* @param savePath 文件的保存路径,此时还缺一个扩展名
* @return
* @throws Exception
*/
public static File getFile(String requestUrl,String savePath) throws Exception {
//String path=System.getProperty("user.dir")+"/img//1.png";
// 创建SSLContext对象,并使用我们指定的信任管理器初始化
TrustManager[] tm = { new MyX509TrustManager() };
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 从上述SSLContext对象中得到SSLSocketFactory对象
SSLSocketFactory ssf = sslContext.getSocketFactory();

URL url = new URL(requestUrl);
HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();
httpUrlConn.setSSLSocketFactory(ssf);

httpUrlConn.setDoOutput(true);
httpUrlConn.setDoInput(true);
httpUrlConn.setUseCaches(false);
// 设置请求方式(GET/POST)
httpUrlConn.setRequestMethod("GET");

httpUrlConn.connect();

//获取文件扩展名
String ext=getExt(httpUrlConn.getContentType());
savePath=savePath+ext;
System.out.println("savePath"+savePath);
//下载文件到f文件
File file = new File(savePath);


// 获取微信返回的输入流
InputStream in = httpUrlConn.getInputStream();

//输出流,将微信返回的输入流内容写到文件中
FileOutputStream out = new FileOutputStream(file);

int length=100*1024;
//存储文件内容
byte[] byteBuffer = new byte[length];

int byteread =0;
int bytesum=0;
//字节数 文件大小
while (( byteread=in.read(byteBuffer)) != -1) {
bytesum += byteread;
out.write(byteBuffer,0,byteread);

}
System.out.println("bytesum: "+bytesum);

in.close();
// 释放资源
out.close();
in = null;
out=null;

httpUrlConn.disconnect();


return file;
}

private static String getExt(String contentType){
if("image/jpeg".equals(contentType)){
return ".jpg";
}else if("image/png".equals(contentType)){
return ".png";
}else if("image/gif".equals(contentType)){
return ".gif";
}

return null;
}

/**
* @param accessToken
* @param message void
* @desc :0.公共方法:发送消息给企业微信
*/
public static void sendMessage(String accessToken, SendBaseMessage message) {
//1.获取请求的url
String sendMessage_url = QiWeiXinParamesUtil.sendMessage_url.replace("ACCESS_TOKEN", accessToken);
String json = JSON.toJSONString(message);
//2.发送消息:调用业务类,发送消息
JSONObject jsonObject = SendRequest.sendPost(sendMessage_url, json);
//4.错误消息处理
if (null != jsonObject) {
if (0 != jsonObject.getIntValue("errcode")) {
logger.error("发送消息失败 errcode:{} errmsg:{}", jsonObject.getIntValue("errcode"), jsonObject.getString("errmsg"));
}
}
}


/**
* @param request
* @return String 消息明文
* @desc :2.从request中获取消息明文
*/
public String getDecryptMsg(HttpServletRequest request) throws IOException {
// 密文,对应POST请求的数据
String postData = "";
// 明文,解密之后的结果
String result = "";
// 微信加密签名
this.msg_signature = request.getParameter("msg_signature");
// 时间戳
this.timestamp = request.getParameter("timestamp");
// 随机数
this.nonce = request.getParameter("nonce");

try {
//1.获取加密的请求消息:使用输入流获得加密请求消息postData
ServletInputStream in = request.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
//作为输出字符串的临时串,用于判断是否读取完毕
String tempStr = "";
while (null != (tempStr = reader.readLine())) {
postData += tempStr;
}

//2.获取消息明文:对加密的请求消息进行解密获得明文
WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(QiWeiXinParamesUtil.token, QiWeiXinParamesUtil.encodingAESKey, QiWeiXinParamesUtil.corpId);
result = wxcpt.DecryptMsg(msg_signature, timestamp, nonce, postData);

} catch (IOException e) {
e.printStackTrace();
} catch (AesException e) {
e.printStackTrace();
}

return result;
}

}
(7) 微信公众平台参数类
package com.bos.util;

import com.alibaba.fastjson.JSONObject;
import com.bos.common.CommenUtil;
import com.bos.data.model.WeiUserInfoModel;

/**
* 微信公众平台的参数
* @param
* @return
*/
public class WeiXinParamesUtil {
/**
* 获取微信公众平台accessToken
* @param
* @return
*/
public static String getWeiAccessToken ="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";

public static String getUserInfoList = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
public static String getUserList = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID";
public static String updateUserRemark = "https://api.weixin.qq.com/cgi-bin/user/info/updateremark?access_token=ACCESS_TOKEN";
public static String open_access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={appid}&secret={secret}&code={code}&grant_type=authorization_code";
/**
* 客户接口发送消息
* @param
* @return
*/
public static String sendCustomerMsgUrl="https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN";
/**
* 上传临时文件素材到微信服务器上
* @param
* @return
*/
public static String uploadMaterialToWeiUrl="https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE";

/**
* 从微信服务器上下载临时文件素材
* @param
* @return
*/
public static String downloadMaterialFromWeiUrl="https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID";

/**
* 获取access_token的接口地址(GET) 限200(次/天)
* @param
* @return
*/
public static String access_token_url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpId}&corpsecret={corpsecret}";



public static String open_id = "gh_b920df4d06d0";
/**
* 微信扫码之后获取用户基本信息的地址
* @param
* @return
*/
public static String getuserinfo_url = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
/**
* 发送消息给微信公众平台的url
* @param
* @return
*/
public static String sendMessageToWei_url="https://api.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN";

/**
* 消息管理模块的成员类型
* @param
* @return
*/
public static String QI_OUT_LINKMAN="企业微信外部联系人";
public static String QI_INE_MEMBER="企业微信成员";
public static String WEI_MEMBER="微信公众号";


//------------微信公众平台的参数
/**
* appId
* @param
* @return
*/
public static String APPID;
/**
* secret
* @param
* @return
*/
public static String SECRET;

//----------------微信开放平台的参数
/**
* openAppid
* @param
* @return
*/
public static String OPENAPPID;
/**
* appSecret
* @param
* @return
*/
public static String OPENSECRET;


/**
* 回调地址 redirect_uri
* @param
* @return
*/
public static String REDIRECT_URI;
/**
* scope
* @param
* @return
*/
public static String SCOPE;
/**
* 模板id
* @param
* @return
*/
public static String TEMPLATEID;





static {

//正式的服务号参数

APPID = "你的APPID";
SECRET = "你的APPSecret";
SCOPE = "snsapi_userinfo";
REDIRECT_URI = "snsapi_userinfo";

}

/**
* 获取微信公众平台的access_token
* @param type
* @return
*/
public static String getAccessToken(String type) {
String url = "";
if ("users".equals(type)) {
url = getWeiAccessToken.replace("APPID", WeiXinParamesUtil.APPID).replace("APPSECRET", WeiXinParamesUtil.SECRET);
// url = getWeiAccessToken.replace("APPID", "wxd842e30025df0f97").replace("APPSECRET", "349459f58dbf19a71f7f58c67f2eea3d");
}else if("customerService".equals(type)){
url = getWeiAccessToken.replace("APPID", WeiXinParamesUtil.APPID).replace("APPSECRET", WeiXinParamesUtil.SECRET);
}
JSONObject departmentJson = SendRequest.sendGet2(url);
return departmentJson.getString("access_token");
}

/**
* 获取微信公众平台的access_token
* @param type
* @return
*/
public static String getAccessToken2(String type) {
String url = "";
if ("weixin".equals(type)) {
url = getWeiAccessToken.replace("APPID", WeiXinParamesUtil.APPID).replace("APPSECRET", WeiXinParamesUtil.SECRET);
}
JSONObject departmentJson = SendRequest.sendGet2(url);
return departmentJson.getString("access_token");
}

}
(8)发送POST请求的代码
// 发送post请求(返回json)
public static JSONObject sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
JSONObject jsonObject = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// conn.addRequestProperty("Cookie", "stay_login=1 smid=DumpWzWQSaLmKlFY1PgAtURdV_u3W3beoei96zsXkdSABwjVCRrnnNBsnH1wGWI0-VIflgvMaZAfli9H2NGtJg id=EtEWf1XZRLIwk1770NZN047804");//设置获取的cookie
// 获取URLConnection对象对应的输出流(设置请求编码为UTF-8)
out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(), "UTF-8"));
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 获取请求返回数据(设置返回数据编码为UTF-8)
in = new BufferedReader(
new InputStreamReader(conn.getInputStream(), "UTF-8"));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
jsonObject = JSONObject.parseObject(result);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}

return jsonObject;
}

(8)效果图

————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/tangthh123/article/details/104314417

posted @ 2024-06-24 17:30  枫树湾河桥  阅读(114)  评论(0编辑  收藏  举报
Live2D