300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 微信公众号开发 - 配置表设计以及接入公众号接口开发

微信公众号开发 - 配置表设计以及接入公众号接口开发

时间:2023-08-06 15:19:47

相关推荐

微信公众号开发 - 配置表设计以及接入公众号接口开发

微信公众号开发文章目录

1.微信公众号开发 - 环境搭建

2.微信公众号开发 - 配置表设计以及接入公众号接口开发

3.微信公众号开发 - token获取(保证同一时间段内只请求一次)

4.微信公众号开发 - 菜单按钮bean封装

5.微信公众号开发 - 创建菜单

6.微信公众号开发 - 事件处理和回复消息

7.微信公众号开发 - 发送Emoji表情

项目完整代码请访问github:/liaozq0426/wx.git

微信公众号配置表设计

在公众号的开发过程中,很多接口都需要读取配置,如appId、appSecret、菜单配置等,因此在开发之前,配置表的设计尤为重要。创建表名为wx_cfg的配置表,建表语句如下

CREATE TABLE `wx_cfg` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',`type` varchar(20) NOT NULL COMMENT '配置项类型',`name` varchar(20) NOT NULL COMMENT '配置项名称',`value` varchar(255) DEFAULT NULL COMMENT '配置项值',`parent_id` int(11) DEFAULT NULL COMMENT '父ID',`sort` tinyint(4) DEFAULT NULL COMMENT '排序',`platform` varchar(36) NOT NULL COMMENT '公众号标识',`wx_type` varchar(15) DEFAULT NULL COMMENT '公众号类型,service:服务号 , subscribe : 订阅号',`enabled` tinyint(1) DEFAULT '1' COMMENT '是否可用,1:可用,0:不可用',`desc` varchar(255) DEFAULT NULL COMMENT '描述信息',PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

建表语句中每个字段含义都有注释说明,其中以下两个字段详细说明一下

1)parent_id,这个字段用于配置公众号菜单时,如果有多级菜单,那么子菜单就需要用parent_id字段标识父菜单是谁

2)platform,当同一配置表用于多公众号开发时,这个字段就可以用于区分不同公众号的配置

配置表创建好后,插入appId、appSecret、Token

INSERT INTO `wx_cfg` (`id`, `type`, `name`, `value`, `parent_id`, `platform`, `enabled`, `desc`) VALUES ('1', 'wx_token', 'wxToken', 'YmRjYjAyN2M1ZjMaYUzI1Mzg1ZmU1MGYaIzBY=', NULL, 'gavin', '1', NULL);INSERT INTO `wx_cfg` (`id`, `type`, `name`, `value`, `parent_id`, `platform`, `enabled`, `desc`) VALUES ('2', 'wx_key', 'appId', 'd3hiODU5ODYwMDY0NmM1MKL1', NULL, 'gavin', '1', NULL);INSERT INTO `wx_cfg` (`id`, `type`, `name`, `value`, `parent_id`, `platform`, `enabled`, `desc`) VALUES ('3', 'wx_key', 'appSecret', 'NjYzNzhkYTVlN2QxMDdhZmUyZTg3MTMwYjRlUGAZI=', NULL, 'gavin', '1', NULL);

注意

1)在开发的时候需要使用自己申请的微信公众号配置信息。

2)appId、appSecret、Token都使用了Base64加密。

插入完成后可以看一下此时wx_cfg表中已经有了三条记录

接入校验接口开发

接下来编写mapper来操作配置表,mapper接口中需要一个查询方法

package com.gavin.mapper;import java.util.List;import com.gavin.pojo.WxCfg;public interface WxCfgMapper {public List<WxCfg> select(WxCfg wxCfg);}

WxCfgMapper.xml实现如下

<mapper namespace="com.gavin.mapper.WxCfgMapper"><resultMap type="com.gavin.pojo.WxCfg" id="WxCfgMap"><id column="id" property="id" /><result column="type" property="type" /><result column="name" property="name" /><result column="value" property="value" /><result column="parent_id" property="parentId" /><result column="platform" property="platform" /><result column="wx_type" property="wxType" /><result column="enabled" property="enabled" jdbcType="TINYINT" javaType="Boolean" /><result column="desc" property="desc" /></resultMap><select id="select" parameterType="com.gavin.pojo.WxCfg" resultMap="WxCfgMap">select id,type,name,IF(type='menu' or type = 'url',concat((SELECT value FROM wx_cfg WHERE type = 'app_url' AND enabled = 1 AND platform = #{platform}) , value) , value) AS value ,parent_id,platform,wx_type,enabled,a.descfrom wx_cfg a<trim prefix="where" suffixOverrides="and|AND|or|OR"><if test="id != null and id &gt; 0 ">id = #{id} and</if><if test="type != null and type !='' ">type = #{type} and</if><if test="name != null and name !='' ">name = #{name} and</if><if test="parentId == null">parent_id is null and</if><if test="parentId != null and parentId > 0">parent_id = #{parentId} and</if><if test="platform != null and platform !='' ">platform = #{platform} and</if><if test="enabled != null">enabled = #{enabled} and</if></trim><if test="orderBy != null and orderBy != '' ">order by ${orderBy}</if></select></mapper>

接下来编写service接口,service接口中有三个方法,分别用来查询列表和单条记录,以及微信公众号的key信息

package com.gavin.service;import java.util.List;import com.gavin.pojo.Wechat;import com.gavin.pojo.WxCfg;public interface WxCfgService {List<WxCfg> select(WxCfg cfg) throws Exception;WxCfg selectOne(WxCfg cfg) throws Exception;Wechat selectWechat(String platform) throws Exception;}

实现代码如下

package com.gavin.service.impl;import java.util.List;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.gavin.cfg.WxCfgEnum;import com.gavin.mapper.WxCfgMapper;import com.gavin.pojo.Wechat;import com.gavin.pojo.WxCfg;import com.gavin.service.WxCfgService;@Servicepublic class WxCfgServiceImpl implements WxCfgService{@Autowiredprivate WxCfgMapper wxCfgMapper;/*** @title 查询WxCfg集合* @author gavin* @date 11月25日*/@Overridepublic List<WxCfg> select(WxCfg cfg) throws Exception {return wxCfgMapper.select(cfg);}/*** @title 查询WxCfg单条记录* @author gavin* @date 11月25日*/@Overridepublic WxCfg selectOne(WxCfg cfg) throws Exception {List<WxCfg> cfgList = select(cfg);if(cfgList.size() == 1)return cfgList.get(0);return null;}/*** @title 查询微信公众号appId和appSecret* @author gavin* @date 5月24日* @param platform* @return* @throws Exception*/@Overridepublic Wechat selectWechat(String platform) throws Exception {WxCfg cfgParam = new WxCfg();cfgParam.setPlatform(platform);cfgParam.setType(WxCfgEnum.WX_KEY_APPID.getType());List<WxCfg> cfgList = wxCfgMapper.select(cfgParam);Wechat wechat = new Wechat();for(WxCfg cfg : cfgList) {String name = cfg.getName();if(WxCfgEnum.WX_KEY_APPID.getName().equals(name)) {// 获取appIdString appId = cfg.getValue();wechat.setAppId(appId);}else if(WxCfgEnum.WX_KEY_APPSECRET.getName().equals(name)) {// 获取appSecretString appSecret = cfg.getValue();wechat.setAppSecret(appSecret);}}return wechat;}}

上述代码中使用到了一个枚举WxCfgEnum,代码如下

package com.gavin.cfg;public enum WxCfgEnum {APP_URL("app_url" , "appUrl"),WX_TOKEN("wx_token" , "wxToken"),WX_KEY_APPID("wx_key" , "appId"),WX_KEY_APPSECRET("wx_key" , "appSecret"),MENU("menu");private String type;// 对应wx_cfg表中的type字段private String name;// 对应wx_cfg表中的name字段private WxCfgEnum(String type , String name) {this.type = type;this.name = name;}private WxCfgEnum(String type) {this.type = type;}public String getType() {return type;}public void setType(String type) {this.type = type;}public String getName() {return name;}public void setName(String name) {this.name = name;}}

接下来编写controller,实现接入接口

package com.gavin.controller;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import com.gavin.cfg.WxAccessVo;import com.gavin.service.WxCfgService;@RestControllerpublic class WxController {@Autowiredprivate WxCfgService wxCfgService;@GetMapping("wxIn")public String wxIn(WxAccessVo accessVo) {try {return wxCfgService.wxInVerify(accessVo); } catch (Exception e) {e.printStackTrace();return null;} }}

代码中用到的WxAccessVo定义如下,用于接收微信传过来的参数

package com.gavin.pojo;/*** @title 公众号接口校验bean* @author gavin* @date 11月25日*/public class WxAccessVo {private String signature;private String timestamp;private String nonce;private String echostr;private String platform;public String getPlatform() {return platform;}public void setPlatform(String platform) {this.platform = platform;}public String getSignature() {return signature;}public void setSignature(String signature) {this.signature = signature;}public String getTimestamp() {return timestamp;}public void setTimestamp(String timestamp) {this.timestamp = timestamp;}public String getNonce() {return nonce;}public void setNonce(String nonce) {this.nonce = nonce;}public String getEchostr() {return echostr;}public void setEchostr(String echostr) {this.echostr = echostr;}}

在WxCfgService新增wxInVerify接口

String wxInVerify(WxAccessVo accessVo) throws Exception;

实现代码如下

/*** @title 微信公众号接入认证* @author gavin* @date 11月25日*/@Overridepublic String wxInVerify(WxAccessVo accessVo) throws Exception{boolean result = false;if(accessVo == null)return null;String platform = accessVo.getPlatform();if (!StringUtils.isBlank(platform)) {// 从数据库中查询TokenWxCfg wxCfg = new WxCfg();wxCfg.setEnabled(true);wxCfg.setType(WxCfgEnum.WX_TOKEN.getType());wxCfg.setPlatform(platform);WxCfg wxCfgA = this.selectOne(wxCfg);String token = wxCfgA.getValue();token = EncryptionUtil.base64Decode(token);// 校验签名result = WxUtil.verifySignature(accessVo.getSignature(), token, accessVo.getNonce(), accessVo.getTimestamp());}System.out.println(accessVo.getPlatform() + "配置微信公众号" + (result ? "成功" : "失败"));// 如果校验成功则返回echostr,否则返回空return result ? accessVo.getEchostr() : null;}

其中签名校验封装成了WxUtil类的一个方法,verifySignature代码如下

/*** @title 微信公众号服务器配置校验* @param signatureWx* @param token* @param nonce* @param timestamp* @return*/public static boolean verifySignature(String signatureWx , String token , String nonce , String timestamp) throws Exception{if(StringUtils.isBlank(signatureWx))return false;String[] arr = {token , nonce , timestamp};StringBuffer sb = new StringBuffer();// 排序Arrays.sort(arr);// 拼接字符串sb.append(arr[0]).append(arr[1]).append(arr[2]);// sha1算法加密String signature = DigestUtils.sha1Hex(sb.toString());return signatureWx.equals(signature);}

到这里,接入认证接口就开发完成了。接下来开启natapp内网穿透,登录到微信公众号后台,在基本配置中修改配置,在URL中输入刚刚开发好的wxIn接口,并带上platform参数,如下图

输入完成后,点击下方提交按钮,如果校验成功页面会弹出如下提示

如果校验失败页面会弹出如下提示

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。