搭建测试环境
首先使用微信测试号进行测试: 测试号地址
使用调试工具进行接口调试: 微信公众平台接口调试工具
参考资料: 获取access_token,接收事件推送, 客服接口-发消息
第一步,接入服务器
url就是服务器接口地址,token是自定义的,等验证的时候后台要用到,后续微信发的消息都是通过这个接口来接收的。
服务器校验:
@RequestMapping("receiveWeixin")
public void receiveWeixin(String signature, String timestamp, String nonce, String echostr,
HttpServletRequest request, HttpServletResponse response) {
try {
//服务器校验
String token = "yxg2i1";
List<String> list = new ArrayList<>();
list.add(token);
list.add(timestamp);
list.add(nonce);
list = CollectionUtil.sort(list, (o1, o2) -> o1.compareTo(o2));
String str = CollectionUtil.join(list, "");
if (!signature.equals(SecureUtil.sha1(str))) {
return;
}
if (StringUtils.isNotEmpty(echostr)) {
//校验服务器
response.getOutputStream().write(echostr.getBytes());
response.getOutputStream().flush();
return;
}
}
第二步,接收消息,发送消息
配置完服务器,就能接收消息了,比如当用户订阅你的公众号,就能收到一条事件推送,消息的格式是xml的
这里面有openId,可以通过openid给用户回复客服消息,当然回复客服消息是有限制的,比如只有当用户发送消息,或者关注公众号时才能回复。
@RequestMapping("receiveWeixin")
public void receiveWeixin(String signature, String timestamp, String nonce, String echostr,
HttpServletRequest request, HttpServletResponse response) {
try {
//服务器校验
String token = "yxg2i1";
List<String> list = new ArrayList<>();
list.add(token);
list.add(timestamp);
list.add(nonce);
list = CollectionUtil.sort(list, (o1, o2) -> o1.compareTo(o2));
String str = CollectionUtil.join(list, "");
if (!signature.equals(SecureUtil.sha1(str))) {
return;
}
if (StringUtils.isNotEmpty(echostr)) {
//校验服务器
response.getOutputStream().write(echostr.getBytes());
response.getOutputStream().flush();
return;
}
//接收消息
Document document = XmlUtil.readXML(request.getInputStream());
Map map = XmlUtil.xmlToMap(document);
JSONObject json = JSONObject.parseObject(JsonUtil.getJson(map)).getJSONObject("xml");
String msgType = json.getString("MsgType");
if (msgType.equals("event")) {
WeixinPushVO weixinPushVO = JSONObject.parseObject(json.toJSONString(), WeixinPushVO.class);
if (weixinPushVO.getEvent().equals("subscribe")) {
// 下发欢迎消息
ThreadUtil.execAsync(() -> weixinConfigService.sendWelcomeMsg(weixinPushVO.getFromUserName()));
}
} else if (msgType.equals("text")) {
WeixinReceiveText weixinReceiveText = JSONObject.parseObject(json.toJSONString(), WeixinReceiveText.class);
ThreadUtil.execAsync(() -> weixinConfigService.replyMessage(weixinReceiveText.getFromUserName(), weixinReceiveText.getContent()));
}
} catch (Exception e) {
e.printStackTrace();
}
}
获取access_token,发送消息代码:
@Component
public class WeiXinUtil {
protected static Logger logger = LoggerFactory.getLogger(WeiXinUtil.class);
private final String TOKEN_KEY = "WEIXIN_TOKEN:";
@Autowired
private RedisTemplate redisTemplate;
public synchronized String getToken(String appId, String appsecret) {
String redisKey = TOKEN_KEY + appId;
String token = (String) redisTemplate.opsForValue().get(redisKey);
if (StrUtil.isNotEmpty(token)) return token;
JSONObject params = new JSONObject();
params.put("grant_type", "client_credential");
params.put("appid", appId);
params.put("secret", appsecret);
String str = HttpUtil.post(WeixinConstants.ACCESS_TOKEN_URL, params.toJSONString());
JSONObject result = handleResult(str, appId);
token = result.getString("access_token");
redisTemplate.opsForValue().set(redisKey, token
, result.getIntValue("expires_in") - 10 * 60, TimeUnit.SECONDS);
return token;
}
private JSONObject handleResult(String str, String appId) {
JSONObject result = JSONObject.parseObject(str);
if (StrUtil.isNotBlank(result.getString("errcode"))) {
if (result.getString("errcode").equals("0")) {
return result;
}
if (result.getString("errcode").equals("40014")) {
clearToken(appId);
}
throw new ServiceException(StrUtil.format("微信接口出错, errcode: {}, msg: {}"
, result.getString("errcode"), result.getString("errmsg")));
}
return result;
}
public void clearToken(String appId) {
String redisKey = TOKEN_KEY + appId;
redisTemplate.delete(redisKey);
}
public JSONObject getMenuInfo(String appId, String appsecret) {
String token = getToken(appId, appsecret);
String str = HttpUtil.get(StrUtil.format(WeixinConstants.GET_MENU_INFO_URL, token));
JSONObject result = handleResult(str, appId);
JSONObject menuInfo = result.getJSONObject("selfmenu_info");
if (menuInfo == null) {
menuInfo = new JSONObject();
}
return menuInfo;
}
public void createMenu(String appId, String appsecret, String menu) {
String token = getToken(appId, appsecret);
String str = HttpUtil.post(StrUtil.format(WeixinConstants.CREATE_MENU_URL, token), menu);
handleResult(str, appId);
}
public void customSend(String appId, String appsecret, String openId, String message) {
String token = getToken(appId, appsecret);
JSONObject body = new JSONObject();
body.put("touser", openId);
body.put("msgtype", "text");
JSONObject content = new JSONObject();
body.put("text", content);
content.put("content", message);
String str = HttpUtil.post(StrUtil.format(WeixinConstants.CUSTOM_SEND_URL, token), body.toJSONString());
handleResult(str, appId);
}
}
public class WeixinConstants {
/**
* 获取token
*/
public static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/stable_token";
/**
* 获取菜单
*/
public static final String GET_MENU_INFO_URL = "https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token={}";
/**
* 创建菜单
*/
public static final String CREATE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token={}";
/**
* 客服接口-发消息
*/
public static final String CUSTOM_SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token={}";
}
public class WeixinBaseVO {
private String ToUserName;
private String FromUserName;
private String CreateTime;
private String MsgType;
}
public class WeixinPushVO extends WeixinBaseVO {
private String Event;
}
public class WeixinReceiveText extends WeixinBaseVO {
private String Content;
private String MsgId;
private String MsgDataId;
private String Idx;
}
public class WeixinConfigServiceImpl implements WeixinConfigService {
@Autowired
private WeiXinUtil weiXinUtil;
@Override
public void sendWelcomeMsg(String openId) {
weiXinUtil.customSend("自己的appid", "自己的appsecret", openId, "欢迎");
}
@Override
public void replyMessage(String openId, String content) {
weiXinUtil.customSend("自己的appid", "自己的appsecret", openId, "你好啊");
}
}