【原创】配置微信服务器与内网穿透--转载请注明出处

微信公众号开发

在进行学习微信公众号开发时,首先我们需要做好一些必须的准备。

1.具有一个自己的公众号平台,方便进行学习。

2.在网上找一款内网穿透器,进行内网穿透,接入微信开发。

3.有一个已经搭建好的Web项目。

1.申请微信公众号

进行微信公众号申请时,在下方地址进行申请即可,我们申请时可以根据自己的不同需求进行申请,选择订阅号或者服务号。企业号的开发模式和微信公众号类似,但是必须由企业才能进行申请。

https://mp.weixin.qq.com/cgi-bin/registermidpage?action=index&lang=zh_CN

这里不对申请做过多描述,按照表单填写即可,很简单。

2.使用内网穿透器进行内网穿透

免费的内网穿透器有很多,博主使用过的有花生壳和Ngrok,这里推荐使用Ngrok,花生壳速度很慢,而且自身网站也有很多BUG。Ngrok的网站地址如下:

https://www.ngrok.cc/#down-client

申请注册完成后,选择登录按钮进行登录,在左侧选择开通隧道,进入如下界面,选择免费的版本。

 

选择后进行隧道开通,可以将表单设置为如下信息:

 

前置域名可以写一个自己喜欢的域名,端口号要与本地服务器的端口号一致。隧道名称可以随便起,方便自己识别。

然后我们要去下载区进行下载windows版本的客户端。下载完成后进行解压,可以获得到两个文件夹,这里我们只保留下面一个文件夹即可。

 

运行该文件夹下的脚本文件 Sunny-Ngrok启动工具.bat之后,可以看到如下界面

 

在这里我们可以输入隧道Id,隧道Id可以在穿透器的管理界面获得,即下方的隧道Id

随后将隧道Id填写脚本中,如果需要启动多个隧道,则以逗号进行分割,启动内网穿透器,不要关闭。

3.测试项目内网穿透

在项目的隧道编辑页面可以找到如下前置域名

 

该域名为与我们平时项目运行时的域名localhost:8080相同,后跟项目路径即可。

我的项目访问名直接配置的/,可以获得如下界面:

 

测试接口访问成功后,我们的准备工作就已经完成了。

4.连接微信公众号

我们可以进入开发者工具---开发者文档 进行查看如何进行URL的接入

https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432

在开始开发--接入指南 中可以看到,在进行接入时,微信公众号会向定义好的接口URL发送get请求,参数为

signature

微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。

timestamp

时间戳

nonce

随机数

echostr

随机字符串

根据微信开发文档所指出,我们可以通过对所获得的参数进行加密处理进行校验,如果成功则返回echostr参数,表示接入成功。这里我们将直接返回该参数,不进行验证。

然后进入项目,进行代码编写,创建一个SpringMVC的Servlet接口:

@RequestMapping("check.do")
@ResponseBody
public String checkInterface(String signature, String timestamp, String nonce,
                           String echostr, HttpServletResponse response) throws IOException {
    // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
    
System.out.println(echostr);
    return echostr;
}

接口编写完成以后,我们可以在微信管理界面中,进行接入接口的配置。

我们登录进入自己所申请的微信公众号,在最下方的开发中,有一个 基本配置 按钮,进入页面,进行配置我们公众号的一系列信息。

 

这里为了便于学习,采用了明文模式,即不对来往的消息进行加密处理。URL需要填写我们进行接入微信公众号的URL,token可以随意填写,识别验证进行使用。EncodingAESKey使用随机生成即可。

5.Access_token的获取

Access_token是在微信开发中,常用的一个token参数,这个参数每天最多获取2000次,且参数的有效期默认为7200秒。我们可以通过以下接口进行获取:

https://api.weixin.qq.com/cgi-bin/token

grant_type

获取access_token填写client_credential

appid

第三方用户唯一凭证

secret

第三方用户唯一凭证密钥,即appsecret

该接口中,具有以上三个参数,其中grant_type直接填写client_credential即可,后两个参数可以在开发者配置中找到,如下图所示

 

开发者密码需要进行重置以后才能看到。看完开发者密码以后,要注意保存,否则无法再次查看。我们在进行对微信公众平台的访问时,需要通过httpClient进行。在添加httpClient的jar包到项目中以后,添加一个工具类:

 

package com.mender.mdoa.weixin.util;

import org.apache.http.HttpEntity;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class HttpUtil {

    /**
     * 发送get请求到指定的URl
     * @param url Url地址
     * @param params 参数列表
     * @return 返回的信息
     */
    public String sendGet(String url, Map<String, String> params){
        StringBuffer sbUrl = new StringBuffer(url);
        //1.使用默认的配置的httpclient
        CloseableHttpClient client = HttpClients.createDefault();
        //2.使用get方法
        if(params != null && params.size() != 0){
            Set<String> keys = params.keySet();
            sbUrl.append("?");
            for(String key : keys){
                sbUrl.append(key).append("=").append(params.get(key)).append("&");
            }
            sbUrl.substring(0,sbUrl.length() - 1);
        }
        System.out.println(sbUrl.toString());
        HttpGet httpGet = new HttpGet(sbUrl.toString());
        InputStream inputStream = null;
        CloseableHttpResponse response = null;
        return this.excute(httpGet);
    }

    /**
     * 发送post请求到指定的URl
     * @param url Url地址
     * @param params 参数列表
     * @return 返回的信息
     */
    public String sendPost(String url, Map<String, String> params) throws UnsupportedEncodingException {
        StringBuffer sbUrl = new StringBuffer(url);
        //1.使用默认的配置的httpclient
        CloseableHttpClient client = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(sbUrl.toString());
        if(params != null && params.size() > 0){
            List<BasicNameValuePair> paramList = new LinkedList<BasicNameValuePair>();
            Set<Map.Entry<String, String>> entrySet = params.entrySet();
            for(Map.Entry<String, String> entry : entrySet){
                paramList.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
            }
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList,"UTF-8");
            httpPost.setEntity(entity);
        }
        return this.excute(httpPost);
    }

    /**
     * 发送信息
     * @param request
     * @return
     */
    private String excute(HttpUriRequest request){
        InputStream inputStream = null;
        CloseableHttpResponse response = null;
        CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            response = httpClient.execute(request);
            HttpEntity entity = response.getEntity();
            return EntityUtils.toString(entity, "utf-8");
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            if (response != null) {
                try {
                    response.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }
}

 

 

 

 

 

然后使用该工具类发送请求到微信的access_token获取接口即可。

如下方代码所示:

 

public static String getToken(){
    String url="https://api.weixin.qq.com/cgi-bin/token";
    Map<String, String> params = new HashMap<String, String>();
    params.put("grant_type","client_credential");
    params.put("appid","wx128a89fa44624819");
    params.put("secret","a6ac12b17e8ce4b611f50c0e99571855");
    HttpUtil httpUtil = new HttpUtil();
    String response = httpUtil.sendGet(url, params);
    System.out.println(response);
    return response;
}

 

该方法所返回的response字符串,就是一个包含了access_token的json串,从字符串中提取即可。

在这里可能会出现一下异常提示

{"errcode":40164,"errmsg":"invalid ip XXX.10.XXX.XXX, not in whitelist hint: [.L7cCA0682nfo1]"}

这里是因为我们没有将自己的ip地址设置到公众号的ip地址白名单中,我们只需要将报错信息中的ip复制,然后添加到 微信管理中心---开发配置---白名单 中即可。

6.Access_token过期?

Access_token过期以后会跑出一个异常编码,编码的信息可以在微信开发文档中进行查看。因为Access_token具有有效期,因此我们需要每隔一段时间进行一次获取,Access_token在获取到下一个以后,前一个仍然是有效的,可以使用的,因此在这里建议使用Spring的定时任务进行获取,时间周期设定在小于两小时即可。

我们也可以通过如下代码进行有效性的测试:

 

public static void main(String args[]) throws UnsupportedEncodingException {
    String token1 = getToken();
    String token2 = getToken();
    Gson gson = new Gson();
    Map<String, String> map = gson.fromJson(token1, HashMap.class);
    token1 = map.get("access_token");
    map = gson.fromJson(token2, HashMap.class);
    token2 = map.get("access_token");
    String address1 = getServerAddress(token1);
    String address2 = getServerAddress(token2);
    System.out.println(address1);
    System.out.println(address2);
}

public static String getToken(){
    String url="https://api.weixin.qq.com/cgi-bin/token";
    Map<String, String> params = new HashMap<String, String>();
    params.put("grant_type","client_credential");
    params.put("appid","wx128a89fa44624819");
    params.put("secret","a6ac12b17e8ce4b611f50c0e99571855");
    HttpUtil httpUtil = new HttpUtil();
    String response = httpUtil.sendGet(url, params);
    System.out.println(response);
    return response;
}

public static String getServerAddress(String token){
    String url="https://api.weixin.qq.com/cgi-bin/getcallbackip";
    Map<String, String> params = new HashMap<String, String>();
    params.put("access_token",token);
    HttpUtil httpUtil = new HttpUtil();
    String response = httpUtil.sendGet(url, params);
    System.out.println(response);
    return response;
}

 

 

 

 

 

先获取了两个access_token然后使用这两个access_token来获取微信的服务地址,最后我们就可以得到这个结果。这样可以证明access_token是可以多次获取,且在后一次获取后,前一次依然有效的。

 

 

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