微信公众号开发(二)—— 微信公众平台接入

  在上一篇《微信公众号开发(一)——环境搭建》中我们已经准备好了微信公众号开发环境,那么接下来我们要真正的开始进行公众号的实际开发之旅。

在真正的开发公众号之前我们必须要接入微信公众平台,那为什么要接入、如何接入本文就这些问题一一解答;

首先我们来了解一下接入平台的原理,然后再贴出代码上手实践测试。

一、微信公众平台的基本原理

微信服务器就相当于一个转发服务器,终端(手机、Pad等)发起请求至微信服务器,微信服务器然后将请求转发给我们的应用服务器。应用服务器处理完毕后,将响应数据回发给微信服务器,微信服务器再将具体响应信息回复到微信App终端。

  通信协议为:HTTP

  数据传输格式为:XML

  具体的流程如下图所示:

  

  来一张更加直观的图吧:

  

  我们需要做的事情,就是对微信服务器转发的HTTP请求做出响应。具体的请求内容,我们按照特定的XML格式去解析,处理完毕后,也要按照特定的XML格式返回。

二、微信公众平台接入步骤

微信公众平台开发者文档上,关于公众号接入这一节内容在接入指南上写的比较详细的,文档中说接入公众号需要3个步骤,分别是:

  1、填写服务器配置
  2、验证服务器地址的有效性
  3、依据接口文档实现业务逻辑

  其实,第3步已经不能算做公众号接入的步骤,而是接入之后,开发人员可以根据微信公众号提供的接口所能做的一些开发。

  第1步中服务器配置包含服务器地址(URL)、Token和EncodingAESKey。

  服务器地址即公众号后台提供业务逻辑的入口地址,目前只支持80端口,之后包括接入验证以及任何其它的操作的请求(例如消息的发送、菜单管理、素材管理等)都要从这个地址进入。接入验证和其它请求的区别就是,接入验证时是get请求,其它时候是post请求;

  Token可由开发者可以任意填写,用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性);

  EncodingAESKey由开发者手动填写或随机生成,将用作消息体加解密密钥。本例中全部以未加密的明文消息方式,不涉及此配置项。

以测试账号为例:

  第1步 配置我们的服务器参数

我们点击修改按钮输入url和token点击提交; 

  第2步,验证服务器地址的有效性,当点击“提交”按钮后,微信服务器将发送一个http的get请求到刚刚填写的服务器地址,并且携带四个参数:

  

  接到请求后,我们需要做如下三步,若确认此次GET请求来自微信服务器,原样返回echostr参数内容,则接入生效,否则接入失败。

  1. 将token、timestamp、nonce三个参数进行字典序排序
  2. 将三个参数字符串拼接成一个字符串进行sha1加密
  3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

   第3步  依据接口文档实现业务逻辑  

  验证URL有效性成功后即接入生效,成为开发者。你可以在公众平台网站中申请微信认证,认证成功后,将获得更多接口权限,满足更多业务需求。
  成为开发者后,用户每次向公众号发送消息、或者产生自定义菜单、或产生微信支付订单等情况时,开发者填写的服务器配置URL将得到微信服务器推送过来的消息和事件,开

  发者可以依据自身业务逻辑进行响应,如回复消息。

  公众号调用各接口时,一般会获得正确的结果,具体结果可见对应接口的说明。返回错误时,可根据返回码来查询错误原因。全局返回码说明
  用户向公众号发送消息时,公众号方收到的消息发送者是一个OpenID,是使用用户微信号加密后的结果,每个用户对每个公众号有一个唯一的OpenID

 三、代码示例

  1、首先我们要创建一个java web 工程

  2、创建一个controller 来进行服务器的验证

package com.quanlian.controller;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import util.NetWorkHelper;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.quanlian.entity.AccessToken;
import com.quanlian.entity.AccessTokenInfo;
import com.quanlian.runner.MyApplicationRunner;


@RestController
public class WxController {
    
    private final String TOKEN = "super";
    @RequestMapping(value="/hello")
    public String hello(){
        return "hello";
    }
    
    @RequestMapping(value = "wx")
    public String wxcheck(HttpServletRequest request,HttpServletResponse response) throws UnsupportedEncodingException {
        String method = request.getMethod();
        System.out.println(method);
        if(method.equals("POST")){
            return wxMessage(request,response);
        }else{
            String signature = request.getParameter("signature");  
            String timestamp = request.getParameter("timestamp");  
            String nonce = request.getParameter("nonce");  
            String echostr = request.getParameter("echostr");  
            System.out.println(echostr);
            //排序
            String sortString = sort(TOKEN, timestamp, nonce);
            //加密
            String mySignature = sha1(sortString);
            if(signature!=null&&signature!=""&&signature.equals(mySignature)){
                System.out.println("签名校验通过。");
                return echostr;
            }else{
                System.out.println("签名校验失败.");
                return "xxxx";
            }
        }

    }
    
    @RequestMapping(value="wxMessage",method=RequestMethod.POST)
    public String wxMessage(HttpServletRequest request,HttpServletResponse response) throws UnsupportedEncodingException{
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        System.out.println("请求进入");
        String result = "";
        try {
            Map<String,String> map = MessageHandlerUtil.parseXml(request);
            System.out.println("开始构造消息");
            result = MessageHandlerUtil.buildXml(map);
            System.out.println(result);
            if(result.equals("")){
                result = "未正确响应";
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("发生异常:"+ e.getMessage());
        }
        return result;
    }
    
    /**
     * 排序
     */
    public String sort(String token, String timestamp, String nonce){
        String[] strArray = {token,timestamp,nonce};
        Arrays.sort(strArray);
        StringBuilder sb = new StringBuilder();
        for(String str : strArray){
            sb.append(str);
        }
        return sb.toString();
    }
    /**
     * 进行sha1加密
     */
    public String sha1(String str){
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-1");
            digest.update(str.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 "";
        
    }
    
}

  3、启动我们的服务,这里直接运行SpringbootApplication.java就可以了 我使用的是springboot 有关springboot 的知识请自行百度

  4、运行我们的natapp.exe 将我们的服务映射到外网

    

  

  5、将映射的http地址配置到测试账号中

  

  这里的 URL一定要保证和natapp中映射的外网地址相匹配;

  6、我们的服务后台是打印出如下信息表示我们的本地服务器配置成功

  

  Ok到这里本文关于接入服务器的演示完毕!

 

posted @ 2018-06-18 16:42  喂,我养你啊  阅读(853)  评论(0编辑  收藏  举报