004:快速整合微信公众号开发
1 微信公众号开发项目演示
今日课程任务
- 微信公众号架构设计原理
- 微信公众号如何本地开发测试
- 快速构建微信公众号服务项目
- 构建微信关键字回复内容
- 实现微信公众号实时查询城市温度
2 微信公众号开发设计原理
微信公众号开发的原理
当我们在微信客户端中,关注某个微信公众号之后,发出任何行为操作都会上传到微信公众号服务器端,再转发给开发者服务器。
3 基于natapp将本地项目发布到外网
外网映射工具的使用
目前有很多外网映射工具,比如NatApp、花生壳、ngrok等。
NatApp的使用
https://natapp.cn/ 购买域名、隧道,下载客户端
进入客户端下载解压目录,输入:natapp -authtoken=752cca064ce33a9b
测试效果:
4 对接微信公众号测试平台
微信公众号测试平台
https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login&token=579271486&lang=zh_CN
微信开发接口框架
微信开发的框架:weixin-java-mp
微信开发接口的验证
http://maplefire.natapp1.cc/wx/portal/wx84fa688175f78964
相关技术文档:
https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html
打开项目weixin-java-mp-demo-springboot-master,配置参数信息
5 第三方微信框架快速实现微信开发
6 微信公众号数据库关键词表设计
微服务整合微信开发框架
Maven依赖
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
数据库表结构
CREATE TABLE `wechat_keywords` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`keyword_name` varchar(255) DEFAULT NULL,
`keyword_value` varchar(255) DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
`version` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of wechat_keywords
-- ----------------------------
INSERT INTO `wechat_keywords` VALUES ('1', '蚂蚁课堂', '蚂蚁课堂专注于java微服务开发网站www.mayikt.com', '2020-03-10 17:32:15', '2020-03-11 17:32:18', '1');
INSERT INTO `wechat_keywords` VALUES ('2', '余胜军', '蚂蚁课堂创始人', '2020-03-10 17:32:45', '2020-03-10 17:32:49', '2');
INSERT INTO `wechat_keywords` VALUES ('3', '枫火', '蚂蚁课堂小菜鸟', '2020-04-09 17:32:45', '2020-03-10 17:32:49', '3');
核心代码
@Data
public class WechatKeyword {
private Long id;
private String keywordName;
private String keywordValue;
private Date createTime;
private Date updateTime;
private Long version;
}
@Mapper
public interface KeywordMapper {
@Select("SELECT id as id ,keyword_name as keywordname,\n" +
"keyword_value as keywordvalue,create_time as createtime,\n" +
"update_time as updatetime ,version as version\n" +
" FROM wechat_keywords where keyword_name=#{keyword};")
WechatKeyword findByKeyword(String keyword);
}
@Component
@RefreshScope
public class MsgHandler extends AbstractHandler {
@Value("${mayikt.wx.defaultMsg}")
private String defaultMsg;
@Value("${mayikt.wx.rpcWeatherUrl}")
private String rpcWeatherUrl;
@Resource
private KeywordMapper keywordMapper;
@Override
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
Map<String, Object> context, WxMpService weixinService,
WxSessionManager sessionManager) {
if (!wxMessage.getMsgType().equals(XmlMsgType.EVENT)) {
//TODO 可以选择将消息保存到本地
}
String content = wxMessage.getContent();
//1.先匹配数据库
WechatKeyword wechatKeyword = keywordMapper.findByKeyword(content);
if (wechatKeyword != null) {
String keywordValue = wechatKeyword.getKeywordValue();
return new TextBuilder().build(StringUtils.isEmpty(keywordValue) ? defaultMsg
: keywordValue, wxMessage, weixinService);
}
//2.调用第三方天气预报接口查询
String replaceRpcWeatherUrl = rpcWeatherUrl.replace("####", content);
JSONObject resultJsonObject = HttpClientUtils.httpGet(replaceRpcWeatherUrl);
if (resultJsonObject != null) {
JSONArray results = resultJsonObject.getJSONArray("results");
JSONObject resultsZeroJSONObject = results.getJSONObject(0);
JSONObject locationJSONObject = resultsZeroJSONObject.getJSONObject("location");
// 地址
String path = locationJSONObject.getString("path");
JSONObject nowJSONObject = resultsZeroJSONObject.getJSONObject("now");
String text = nowJSONObject.getString("text");
String temperature = nowJSONObject.getString("temperature");
String lastUpdate = resultsZeroJSONObject.getString("last_update");
String resultMsg = "您当前查询的城市" + content + ",天气为" + text + "天、实时温度为:" + temperature + "℃," +
"最后更新的时间为:" + lastUpdate;
return new TextBuilder().build(resultMsg, wxMessage, weixinService);
}
//3.回复默认消息
return new TextBuilder().build(defaultMsg, wxMessage, weixinService);
}
}
新增配置文件
logging:
level:
org.springframework.web: INFO
com.github.binarywang.demo.wx.mp: DEBUG
me.chanjar.weixin: DEBUG
wx:
mp:
configs:
- appId: wx84fa688175f78964
secret: 3cb04d764a6da943c61f79fde98a0a09
token: mayikt
mayikt:
wx:
defaultMsg: 您的消息已经收到,后期会给您回复!
rpcWeatherUrl: http://api.seniverse.com/v3/weather/now.json?key=S2f6L62SpD0ivVO6j&location=####&language=zh-Hans&unit=c
测试效果:
7 调用天气预报接口查询当前城市实时天气
整合第三方天气预报接口
https://www.seniverse.com/ 心知天气接口
新建项目mt-shop-common
----mt-shop-common-core
/**
* HttpClientUtils工具类
*/
public class HttpClientUtils {
private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class); // 日志记录
public static RequestConfig getRequestConfig(){
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(5000)
.setSocketTimeout(5000)
.setConnectionRequestTimeout(5000)
.build();
return requestConfig;
}
/**
* post请求传输json参数
*
* @param url url地址
* @return
*/
public static JSONObject httpPost(String url, JSONObject jsonParam) {
// post请求返回结果
CloseableHttpClient httpClient = HttpClients.createDefault();
JSONObject jsonResult = null;
HttpPost httpPost = new HttpPost(url);
// 设置请求和传输超时时间
httpPost.setConfig(getRequestConfig());
try {
if (null != jsonParam) {
// 解决中文乱码问题
StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");
entity.setContentEncoding("UTF-8");
entity.setContentType("application/json");
httpPost.setEntity(entity);
}
CloseableHttpResponse result = httpClient.execute(httpPost);
// 请求发送成功,并得到响应
if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
String str = "";
try {
// 读取服务器返回过来的json字符串数据
str = EntityUtils.toString(result.getEntity(), "utf-8");
// 把json字符串转换成json对象
jsonResult = JSONObject.parseObject(str);
} catch (Exception e) {
logger.error("post请求提交失败:" + url, e);
}
}
} catch (IOException e) {
logger.error("post请求提交失败:" + url, e);
} finally {
httpPost.releaseConnection();
}
return jsonResult;
}
/**
* post请求传输String参数 例如:name=Jack&sex=1&type=2
* Content-type:application/x-www-form-urlencoded
*
* @param url url地址
* @param strParam 参数
* @return
*/
public static JSONObject httpPost(String url, String strParam) {
// post请求返回结果
CloseableHttpClient httpClient = HttpClients.createDefault();
JSONObject jsonResult = null;
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(getRequestConfig());
try {
if (null != strParam) {
// 解决中文乱码问题
StringEntity entity = new StringEntity(strParam, "utf-8");
entity.setContentEncoding("UTF-8");
entity.setContentType("application/x-www-form-urlencoded");
httpPost.setEntity(entity);
}
CloseableHttpResponse result = httpClient.execute(httpPost);
// 请求发送成功,并得到响应
if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
String str = "";
try {
// 读取服务器返回过来的json字符串数据
str = EntityUtils.toString(result.getEntity(), "utf-8");
// 把json字符串转换成json对象
jsonResult = JSONObject.parseObject(str);
} catch (Exception e) {
logger.error("post请求提交失败:" + url, e);
}
}
} catch (IOException e) {
logger.error("post请求提交失败:" + url, e);
} finally {
httpPost.releaseConnection();
}
return jsonResult;
}
/**
* 发送get请求
*
* @param url 路径
* @return
*/
public static JSONObject httpGet(String url) {
// get请求返回结果
JSONObject jsonResult = null;
CloseableHttpClient client = HttpClients.createDefault();
// 发送get请求
HttpGet request = new HttpGet(url);
request.setConfig(getRequestConfig());
try {
CloseableHttpResponse response = client.execute(request);
// 请求发送成功,并得到响应
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
// 读取服务器返回过来的json字符串数据
HttpEntity entity = response.getEntity();
String strResult = EntityUtils.toString(entity, "utf-8");
// 把json字符串转换成json对象
jsonResult = JSONObject.parseObject(strResult);
} else {
logger.error("get请求提交失败:" + url);
}
} catch (IOException e) {
logger.error("get请求提交失败:" + url, e);
} finally {
request.releaseConnection();
}
return jsonResult;
}
}
微信服务引入mt-shop-common-core依赖
测试效果: