一:申请公众号

无聊的去申请一个个人公众号,试了下微信实现自定义菜单与自定义对话的一些基本功能,如果多花点时间,金钱(= =!)还是有不少功能可以使用,还是蛮有意思的。

废话不多说,先看一下申请的流程。首先进入微信公众平台申请一个个人的订阅号,其实它自带的功能里就有自动回复的设置,不过还是试试开发接口去实现,更有意思。

二:接口实现

在开发-基本配置里,服务器配置就是当前公众号和我们自己服务器建立连接的配置。

controller:该方法的路径就是基本配置里的服务器地址(URL)

/**

* 微信接入

* @param

* @return

* @throws IOException

*/

@RequestMapping(value="/wechat/connect",method = {RequestMethod.GET, RequestMethod.POST})

@ResponseBody

public void connectWeixin(HttpServletRequest request, HttpServletResponse response) throws IOException {

// 将请求、响应的编码均设置为UTF-8(防止中文乱码)

request.setCharacterEncoding("UTF-8"); //微信服务器POST消息时用的是UTF-8编码,在接收时也要用同样的编码,否则中文会乱码;

response.setCharacterEncoding("UTF-8"); //在响应消息(回复消息给用户)时,也将编码方式设置为UTF-8,原理同上;boolean isGet = request.getMethod().toLowerCase().equals("get");

PrintWriter out = response.getWriter();

try {

if (RequestMethod.GET.name().equals(request.getMethod())) {

String signature = request.getParameter("signature");// 微信加密签名

String timestamp = request.getParameter("timestamp");// 时间戳

String nonce = request.getParameter("nonce");// 随机数

String echostr = request.getParameter("echostr");//随机字符串

// 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败

if (SignUtil.checkSignature(DNBX_TOKEN, signature, timestamp, nonce)) {

LOGGER.info("Connect the weixin server is successful.");

response.getWriter().write(echostr);

} else {

LOGGER.error("Failed to verify the signature!");

}

}else{

String respMessage = "";

try {

respMessage = wechatService.weixinPost(request);

out.write(respMessage);

LOGGER.info("The request completed successfully");

LOGGER.info("to weixin server "+respMessage);

} catch (Exception e) {

LOGGER.error("Failed to convert the message from weixin!", e);

}

}

} catch (Exception e) {

LOGGER.error("Connect the weixin server is error.", e);

}finally{

out.close();

}

}

校验的代码如下:

public class SignUtil {

/**

* 验证签名

*

* @param token 微信服务器token,在env.properties文件中配置的和在开发者中心配置的必须一致

* @param signature 微信服务器传过来sha1加密的证书签名

* @param timestamp 时间戳

* @param nonce 随机数

* @return

*/

public static boolean checkSignature(String token,String signature, String timestamp, String nonce) {

String[] arr = new String[] { token, timestamp, nonce };

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

Arrays.sort(arr);

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

String tmpStr = SHA1.encode(arr[0] + arr[1] + arr[2]);

// 将sha1加密后的字符串可与signature对比,标识该请求来源于微信

return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;

}

}

import java.security.MessageDigest;

/**

* 微信公众平台(JAVA) SDK

*

* SHA1算法

*

* @author helijun 2016/06/15 19:49

*/

public final class SHA1 {

private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5',

'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

/**

* Takes the raw bytes from the digest and formats them correct.

*

* @param bytes the raw bytes from the digest.

* @return the formatted bytes.

*/

private static String getFormattedText(byte[] bytes) {

int len = bytes.length;

StringBuilder buf = new StringBuilder(len * 2);

// 把密文转换成十六进制的字符串形式

for (int j = 0; j < len; j++) {

buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);

buf.append(HEX_DIGITS[bytes[j] & 0x0f]);

}

return buf.toString();

}

public static String encode(String str) {

if (str == null) {

return null;

}

try {

MessageDigest messageDigest = MessageDigest.getInstance("SHA1");

messageDigest.update(str.getBytes());

return getFormattedText(messageDigest.digest());

} catch (Exception e) {

throw new RuntimeException(e);

}

}

}

其中加密字段分别为:signature:微信加密签名   timestamp:时间戳  nonce:随机数  echostr:随机字符串,

而代码中的DNBX_TOKEN 就是公众号里配置的 令牌(Token)。如果校验成功就把echostr返回给微信端即可。

再来看看如何处理具体的post请求:

import com.alibaba.fastjson.JSON;

import com.alibaba.fastjson.JSONObject;

import com.yxy.nova.bean.wechat.TextMessage;

import com.yxy.nova.util.MessageUtil;

import com.yxy.nova.util.SimpleHttpClient;

import com.yxy.nova.util.wechat.weather.TianQiCityID;

import com.yxy.nova.util.wechat.weather.TianQiWeatherHelper;

import com.yxy.nova.web.util.WebUtil;

import org.apache.commons.lang3.StringUtils;

import org.apache.http.NameValuePair;

import org.apache.http.message.BasicNameValuePair;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;

import java.io.IOException;

import java.util.Map;

/**

* @date 2021/1/22 上午11:38

* @Description

*/

@Service

public class WechatServiceImpl implements WechatService {

private final Logger LOGGER = LoggerFactory.getLogger(getClass());

private static JSONObject accessToken = new JSONObject();

@Value("${wechat-AppId}")

private String appleId;

@Value("${wechat-AppSecret}")

private String appSecret;

@Autowired

private SimpleHttpClient simpleHttpClient;

/**

* 处理微信发来的请求

*

* @param request

* @return

*/

@Override

public String weixinPost(HttpServletRequest request) {

String respMessage = null;

try {

// xml请求解析

Map requestMap = MessageUtil.xmlToMap(request);

// 发送方帐号(open_id)

String fromUserName = requestMap.get("FromUserName");

// 公众帐号

String toUserName = requestMap.get("ToUserName");

// 消息类型

String msgType = requestMap.get("MsgType");

// 消息内容

String content = requestMap.get("Content");

LOGGER.info("FromUserName is:" + fromUserName + ", ToUserName is:" + toUserName + ", MsgType is:" + msgType);

// 文本消息

if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {

//这里根据关键字执行相应的逻辑,只有你想不到的,没有做不到的

TianQiCityID ci = new TianQiCityID();

if(ci.getCityIDMap().get(content) !=null){

TextMessage text = new TextMessage();

TianQiWeatherHelper tianQiWeatherHelper = new TianQiWeatherHelper();

tianQiWeatherHelper.setSimpleHttpClient(simpleHttpClient);

text.setContent(tianQiWeatherHelper.getWeatherReportByCityName(content));

text.setToUserName(fromUserName);

text.setFromUserName(toUserName);

text.setCreateTime(System.currentTimeMillis() + "");

text.setMsgType(msgType);

respMessage = MessageUtil.textMessageToXml(text);

}

if ("天气".equals(content)) {

TextMessage text = new TextMessage();

TianQiWeatherHelper tianQiWeatherHelper = new TianQiWeatherHelper();

tianQiWeatherHelper.setSimpleHttpClient(simpleHttpClient);

text.setContent(tianQiWeatherHelper.getWeatherReportByIP(WebUtil.getRemoteAddr(request)));

text.setToUserName(fromUserName);

text.setFromUserName(toUserName);

text.setCreateTime(System.currentTimeMillis() + "");

text.setMsgType(msgType);

respMessage = MessageUtil.textMessageToXml(text);

}

//自动回复

// TextMessage text = new TextMessage();

// text.setContent("the text is" + content);

// text.setToUserName(fromUserName);

// text.setFromUserName(toUserName);

// text.setCreateTime(System.currentTimeMillis() + "");

// text.setMsgType(msgType);

// respMessage = MessageUtil.textMessageToXml(text);

}

// else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {// 事件推送

// String eventType = requestMap.get("Event");// 事件类型

//

// if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {// 订阅

// respContent = "欢迎关注xxx公众号!";

// return MessageResponse.getTextMessage(fromUserName , toUserName , respContent);

// } else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {// 自定义菜单点击事件

// String eventKey = requestMap.get("EventKey");// 事件KEY值,与创建自定义菜单时指定的KEY值对应

// logger.info("eventKey is:" +eventKey);

// return xxx;

// }

// }

//开启微信声音识别测试 2015-3-30

// else if(msgType.equals("voice"))

// {

// String recvMessage = requestMap.get("Recognition");

// //respContent = "收到的语音解析结果:"+recvMessage;

// if(recvMessage!=null){

// respContent = TulingApiProcess.getTulingResult(recvMessage);

// }else{

// respContent = "您说的太模糊了,能不能重新说下呢?";

// }

// return MessageResponse.getTextMessage(fromUserName , toUserName , respContent);

// }

//拍照功能

// else if(msgType.equals("pic_sysphoto"))

// {

//

// }

// else

// {

// return MessageResponse.getTextMessage(fromUserName , toUserName , "返回为空");

// }

// 事件推送

else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {

String eventType = requestMap.get("Event");// 事件类型

// 订阅

if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {

TextMessage text = new TextMessage();

text.setContent("欢迎关注,xxx");

text.setToUserName(fromUserName);

text.setFromUserName(toUserName);

text.setCreateTime(System.currentTimeMillis() + "");

text.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);

respMessage = MessageUtil.textMessageToXml(text);

}

// TODO 取消订阅后用户再收不到公众号发送的消息,因此不需要回复消息

else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {// 取消订阅

}

// 自定义菜单点击事件

else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {

String eventKey = requestMap.get("EventKey");// 事件KEY值,与创建自定义菜单时指定的KEY值对应

if (eventKey.equals("weather")) {

TextMessage text = new TextMessage();

text.setContent("请输入城市名称");

text.setToUserName(fromUserName);

text.setFromUserName(toUserName);

text.setCreateTime(System.currentTimeMillis() + "");

text.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);

respMessage = MessageUtil.textMessageToXml(text);

}

}

}

}

catch (Exception e) {

LOGGER.error("error......");

}

return respMessage;

}

}

如上面的代码,我在文本消息中,简单的实现了根据城市名称查询天气情况。接口的实现就不贴出来了,就是一个简单的接口对接。

三:第三方接口

网上有关于 www.weather.com.cn网站获取天气情况的接口,但是本人测试使用发现返回字段比较少,而且刷新的不是很及时,

现在推荐一个免费的第三方接口:https://www.tianqiapi.com/,在api接口中有三个免费的接口,可以实现一些简单的功能了。

我在demo中使用的就是:免费实况天气接口:https://www.tianqiapi.com/index/doc?version=v6,用完感受还是不错的。

至此,已经实现了公众号的部分功能,其实微信的接口文档还有很多,还有很多更好玩的功能,比如微信对话开放平台,有兴趣的可以申请开发权限,去探索一下吧。

java微信个人订阅号发信息_微信个人公众号开发-java相关推荐

  1. 公众号 多服务器配置_多账号公众号分享的素材如何采集以及一键分发?

    企业有多个微信公众号很常见,一个人同时运营多个公众号也并不少见.一个人两个公众号,每天保持2篇文章的固定输出都不是那么容易,那如何同时运营多个公众号呢?我谈下我之前操作的一些方法,供大家参考. 我们每 ...

  2. js如何获取jwt信息_谈房地产公众号如何涨粉?一篇文章让你轻松获取信息

    原标题:谈房地产公众号如何涨粉?一篇文章让你轻松获取信息 对于房地产企业来说,如何学会运营自己企业的房地产微信公众号是涨粉引流的关键一步,老话说:一步走好,步步稳.值得夸奖的是近几年中高端房地产企业在 ...

  3. 微信订阅号签到功能_微信公众号积分签到功能怎么添加,怎么制作微信签到赚积分...

    导读:在公众号里做每日签到的好处是可以提高粉丝的活跃度和粘性,签到送积分,可以换礼物,这样比较能留住粉丝,该怎么设置呢,因为这个是会员卡里的一个插件,首先我们需要先添加好会员卡功能,下面分享具体教程. ...

  4. 公众号 多服务器配置_微信公众号的服务器配置

    现在很多开发,都依托在微信,有微信公众号,或者是小程序,而近段时间一直在跟进微信的会员开发功能,但是一直对于服务配置这方面都是过一遍就忘,记录一下 一般,都会有公司的公众号,在没有公司的公众号的时候, ...

  5. 公众号向特定用户主动推送消息_小程序商城,商家神器!微信导购助手内测,能主动联系公众号粉丝...

    小程序·做出来·会使用 做小程序的钱才不白花 我们可以多聊聊,如何运营你的小程序? - 正 文 - 微信导购助手内测 "我公众号有几万粉丝,除了推文,我可以主动给他们发消息吗?" ...

  6. 批量关闭公众号推送_微信喊你「批量屏蔽公众号」啦!还有其他新功能!!

    原标题:微信喊你「批量屏蔽公众号」啦!还有其他新功能!! 小派有可能会迟到 但尽量不缺席 昨天 公众号被爆出大大大的功能 「可批量取消长期不阅读公众号的推送」 虽然这个功能目前还是内测 部分长时间不阅 ...

  7. 一键回到页面顶部_微信上线新功能!长期不看的公众号,帮你一键拒收

    用过 TIM 的朋友都称赞过一个功能,那就是它能把你长时间未联系的 QQ 好友一键分组,让你能够「尴尬又不失礼貌」地把不常联系的好友单独区分开来. 而在微信上,许多人也面临着同样的问题--只不过这次「 ...

  8. 批量关闭公众号推送_微信发大招,长期不读的公众号可“批量关闭”!

    有意思的是,这个功能如果放在头条.百家号等内容平台,可能都不会引起如此广泛的关注.因为各家的分发机制不同,内容制作者和用户的连接方式也各不相同. 众所周知,头条的内容分发逻辑核心是算法,即机器分发.机 ...

  9. 微信公众号发送小程序卡片_如何在公众号文章中添加小程序卡片

    在公众号中添加小程序卡片可以给阅读者更好的文章阅读体验,腾讯地图+小程序可以在文章内容中提供位置卡片和路线规划卡片,适用于各类含有地点信息的文章推文. 绑定腾讯地图+小程序的方法如下: 第一步:公众号 ...

最新文章

  1. 2020-1024=996
  2. 中国联通华东云数据中心—电气培训
  3. 数据库ORA-03113排查
  4. GDCM:gdcm::CodeString的测试程序
  5. 小程序 textarea ios兼容解决
  6. LeetCode 1037. 有效的回旋镖
  7. jmstemplate 获取队列id_学习Linux(38)消息队列
  8. 用Python来搞副业?这届大学生到底有多野……
  9. linux系统反应优化,细说Linux系统优化-实践篇【转载】
  10. 用最简单直白的人类语言解释下jsonP到底是什么鬼
  11. python语言基础实验一_实验1 Python语言基础
  12. plc和pc串口通讯接线_电脑和PLC连接不上我用的是USB转串口的连接线
  13. 计算机如何恢复记事本,如何使用电脑桌面便签恢复误删除了的记事本数据内容?...
  14. 从招聘信息看-数据分析师(数据分析报告)
  15. 软件开发成本估算方法
  16. 美国小学计算机编程课程,美国小学STEM课程案例研究
  17. 测绘——利用ExifTool提取照片exif信息【windows环境下】(信息非常全)
  18. 考研数学笔记(更新中)
  19. python嗅探器_Python中的包嗅探器
  20. 【nowcoder 110246】Dima and Salad

热门文章

  1. windows store 应用商店消失 ,找不到
  2. FaceBoxes论文阅读
  3. 高二计算机课程难点,巧用信息技术手段 突破高中数学课堂教学的重难点
  4. 【数据竞赛】风控实操案例 | 基于Xgboost与Catboost实现非法集资企业识别
  5. flink设置checkpoint部署后一直重启,出现检查点无法写入的问题
  6. uni-app 和H5页面视频播放flv格式视频监控
  7. 若依项目中添加导入excel功能
  8. 基于3D Frangi滤波的血管强化方法(附代码python)
  9. 2013年MBA、MPA、MPAcc入学考试综合能力辅导教材
  10. 福利:学生免费注册使用JB全家桶