微信公众号开发01---环境申请及开发准备

1.开通开发者帐号

注意:开通微信公众号必须是“个体户”或“企业性质”。

  1. 通过个人微信号扫码登录并开通微信服务号
  2. 开通成功后,此时的公众号是【未认证状态】
    在这里插入图片描述
  3. 未认证与认证的公众号的主要区别
    在【开发—接口权限】菜单中,可查看到使用各接口的权限。
    在这里插入图片描述我们要进行二次开发,不申请开通“开发者帐号”,你的公众号就只是个摆设。
  4. 认证服务号并开通开发者帐号
服务号的认证:无论是“个体户”还是“企业”,最好是首先将公司的对公帐户开通好。
因为如果你的系统还要申请微信支付功能的话,开通了对公帐户,后面的操作会简单很多。
  1. 服务号认证成功后,我们会看到接口权限基本上全部都可使用了
    在这里插入图片描述

2.程序与公众号联合调试

2.1 准备联调的服务器

注意:微信公众号与服务器交互时,只能访问你服务器的 80端口
云服务器
云服务器联调,则在调试中,可能要多打些log日志来调试

发送请求
转发
公众号
公众平台服务器
云服务器工程

2.2 配置公众平台

2.2.1 菜单: 开发-- 基本配置

在这里插入图片描述```
IP白名单:公众号允许指定外网访问的IP地址(官方要求必须配置)
注意:如果你用的是云服务器,直接将服务器的公网IP配置此处即可。

2.2.2 服务器配置(重点)

在这里插入图片描述

URL: 公众号默认将访问的服务器的地址。
注意:这里是公众号与后台连接的总入口
Token:类似票据,可自行设置并系统自行保留
EncodingAESKey:随机生成即可,这个值应该是给公众号来用的,系统联调时,不会用到该值。

在配置上面的URL时,必须先确保你的服务器已成功启动
如果你服务器连接的URL配置错误,【提交】按钮就无法成功点击,公众平台会报错。

2.2.3 服务器后台核心代码

注:这里以springboot工程为例
因为公众号访问我们服务器,都走的统一的一个接口,就是我们上面配置的URL,所以在项目中,我们可以创建一个Servlet来专门接收和处理公众号的请求。
具体代码步骤如下

  1. 在启动类上添加注解
@SpringBootApplication
@ServletComponentScan
public class WXApplication {
	public static void main(String[] args) {
		SpringApplication.run(WXApplication.class, args);
	}
}
  1. 创建一个servlet并编写连接所需的核心代码:WechatCallbackApi.java
@WebServlet("/wechat")
public class WechatCallbackApi extends HttpServlet {
    @Autowired
    private WeixinGZHService weixinGZHService;
    
    @Override//不添加此方法,直接注入service会报空指针
    public void init(ServletConfig config) {
        try {
            SpringBeanAutowiringSupport.processInjectionBasedOnServletContext(this, config.getServletContext());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
        doGet(req, resp);
    }


    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
        try {
            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            //进行签名校验
            weixinGZHService.validateWeixinServer(request, response);

            //处理菜单响应操作
        /*
       <xml>
            <ToUserName><![CDATA[gh_409cf2d2d396]]></ToUserName>
            <FromUserName><![CDATA[o64up1E1tBRXaLhRne9Dm9rrcp5g]]></FromUserName>
            <CreateTime>1558324778</CreateTime>
            <MsgType><![CDATA[event]]></MsgType>
            <Event><![CDATA[CLICK]]></Event>
            <EventKey><![CDATA[V1001_GET_ORDER]]></EventKey>
        </xml>
         */
            String message = IOUtils.toString(request.getInputStream(), "utf-8");
            //先转成map对象
            Map<String, String> xmlToMap = WeChatXMLUtils.xmlToMap(message);
            //在调用模板消息时,有个非常坑的地方,就是微信公众号服务器每向微信用户发送消息后,必须要有回应,无回应微信那边则会报异常
            if (xmlToMap == null || StringUtils.isBlank(xmlToMap.get("EventKey"))) {
                return;
            }
            WeixinResult weixinResult = WeChatXMLUtils.xmlToBean(message, WeixinResult.class);

            //发送模板消息时,也会向公众号返回一条消息,但此消息的数据类型与 click事件的返回类型不同。需要判断eventKey的值
            if (weixinResult != null && StringUtils.isNotBlank(weixinResult.getEventKey())) {
                switch (weixinResult.getEventKey()) {

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  1. 实体类WeixinResult .java
/*
<xml>
     <ToUserName><![CDATA[gh_409cf2d2d396]]></ToUserName>
     <FromUserName><![CDATA[o64up1E1tBRXaLhRne9Dm9rrcp5g]]></FromUserName>
     <CreateTime>1558324778</CreateTime>
     <MsgType><![CDATA[event]]></MsgType>
     <Event><![CDATA[CLICK]]></Event>
     <EventKey><![CDATA[V1001_GET_ORDER]]></EventKey>
 </xml>
 */
//设置根据字段还是方法生成
//设置生成的xml的根节点的名称
@XmlRootElement(name = "xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class WeixinResult implements Serializable {
    private String ToUserName;
    private String FromUserName;
    private String MsgType;
    private long CreateTime;
    private String Event;
    private String EventKey;
    private String Content;
    // view类型时,需要这个字段
    private String MenuId;
}

注意: 上面实体类的属性名,其实就是根据调用公众号接口返回的统一XML命名。实体类属性名,最好是与XML数据中返回的字段名保持一致,这样后面在接收数据并进行转换时就非常方便

  1. 签名校验方法weixinGZHService.validateWeixinServer
    weixinGZHService.java类中核心代码
    下面方法上会用到一个参数 TOKEN,这个值就是我们在公众号中配置的token值
/**
     * 验证当前微信服务器是否正常
     *
     * @param request
     * @param response
     * @throws IOException
     */
    public void validateWeixinServer(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String signature = request.getParameter("signature");
        String timestamp = request.getParameter("timestamp");
        String nonce = request.getParameter("nonce");
        String echostr = request.getParameter("echostr");

        ArrayList<String> array = new ArrayList<String>();
        array.add(signature);
        array.add(timestamp);
        array.add(nonce);

        //排序
        String sortString = sort(TOKEN, timestamp, nonce);
        //加密
        String mytoken = SHA1.SHA1(sortString);
        //校验签名
        if (mytoken != null && mytoken != "" && mytoken.equals(signature)) {
            response.getWriter().println(echostr); //如果检验成功输出echostr,微信服务器接收到此输出,才会确认检验完成。
        }
    }
    /**
     * 排序方法
     *
     * @param token
     * @param timestamp
     * @param nonce
     * @return
     */
    private String sort(String token, String timestamp, String nonce) {
        String[] strArray = {token, timestamp, nonce};
        Arrays.sort(strArray);

        StringBuilder sbuilder = new StringBuilder();
        for (String str : strArray) {
            sbuilder.append(str);
        }

        return sbuilder.toString();
    }
  1. 实体类SHA1.java
public class SHA1 {
    public static String SHA1(String decript) {
        try {
            MessageDigest digest = MessageDigest
                    .getInstance("SHA-1");
            digest.update(decript.getBytes());
            byte messageDigest[] = digest.digest();
            // Create Hex String
            StringBuffer hexString = new StringBuffer();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return "";
    }
}

2.2.4 联调检测

在上面的后台代码都配置好后,此时,再回到公众平台【开发–基本配置—服务器配置】
当修改配置成功后,点修改配置,弹出【提交成功提示】则表示配置成功。
在这里插入图片描述到此,公众平台与我们服务器的整体联调测试就全部完成。
后面,会再教如何进行自定义菜单开发。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章