微信公众号号开发(Java)

 

使用java开发微信公众号

 注意:

我们都知道学习使用只能申请【订阅号】,但是,我们申请的是个人(没有认证)。这就造成了一下问题:由于用户体验和安全性方面的考虑,微信公众号的注册有一定门槛,某些高级接口的权限需要微信认证后才可以获取.所以,为了帮助开发者快速了解和上手微信公众号开发,熟悉各个接口的调用,我们推出了微信公众帐号测试号,通过手机微信扫描二维码即可获得测试号。

1、测试号的申请

登录到微信公众平台:https://mp.weixin.qq.com/,打开【订阅号】中的开发文档。

   

选择 《开始开发》-->《接口测试号申请》-----点击------ > 《进入微信公众测试号申请系统》

 

2、填写服务器配置

申请成功后的页面,此页面需要两个参数,url和token

 

URL:填写的URL(本地项目地址,需要自己创建,见后文3、项目创建)需要正确响应微信发送的Token验证

Token: 暂时可以随便设置

注意:我们要想微信消息响应到本地,就必须使用内网穿透。简单概述:通过内网穿透别人就可以访问我们本地的项目(见后文4内网穿透工具使用)。

3、项目创建

用Eclipse新建一个项目,这里我建的是web项目

新建一个servlet,重写doGet方法接收微信发来的GET请求

package com.bgm.bgmserver.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

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

import com.bgm.bgmserver.service.BGMService;

public class BGMServlet extends  HttpServlet{
	
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		System.out.println("微信发送的get请求");
		//微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
		String signature=request.getParameter("signature");
		//时间戳
		String timestamp=request.getParameter("timestamp");
		//随机数
		String nonce=request.getParameter("nonce");
		//随机字符串
		String echostr=request.getParameter("echostr");
		
		System.out.println("signature:"+signature);
		System.out.println("timestamp:"+timestamp);
		System.out.println("nonce:"+nonce);
		System.out.println("echostr:"+echostr);
		//校验请求
		if(BGMService.check(signature,timestamp,nonce)){
			System.out.println("接入成功");
			//若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效
			PrintWriter out = response.getWriter();
			out.print(echostr);
			out.flush();
			out.close();
		}else{
			System.out.println("接入失败");
		}


	}
 
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		System.out.println("微信发送的post请求");
		//输出xml数据包
		/*ServletInputStream is = request.getInputStream();
		byte[] b=new byte[1024];
		int len;
		StringBuilder sb=new StringBuilder();
		while((len=is.read(b))!=-1){
			sb.append(new String(b,0,len));
		}
		System.out.println(sb.toString());*/
		Map<String,String> requestMap= BGMService.parseRequest(request.getInputStream());
		System.out.println(requestMap);
	}

	
}

BGMService 代码:

package com.bgm.bgmserver.service;

import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class BGMService {

	/**
     * Token可由开发者可以任意填写,用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性)
     * 比如这里我将Token设置为bgm_tocken
     */
	private static String TOKEN="bgm_tocken";
	 
	/**
	 * @param timestamp 时间戳
	 * @param nonce 随机数
	 * @param signature 微信加密签名
	 * @return
	 */
	public static boolean check(String signature, String timestamp, String nonce) {
		// 1)将token、timestamp、nonce三个参数进行字典序排序
		String[] strArray = {TOKEN, timestamp, nonce};
        Arrays.sort(strArray);
        //2)将三个参数字符串拼接成一个字符串进行sha1加密
        StringBuilder sb = new StringBuilder();
        for (String str : strArray) {
            sb.append(str);
        }
		//sha1加密
		String sha1Str=sha1(sb.toString());
		System.out.println("sha1加密:"+sha1Str);
		System.out.println("signature:"+signature);
		//3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信//校验签名
		return sha1Str.equalsIgnoreCase(signature);
	}
	
	/**
	 * 进行sha1加密
	 * @param str
	 * @return
	 */
	private static String sha1(String str) {
		try {
			//获取一个加密对象
			MessageDigest md=MessageDigest.getInstance("sha1");
			//加密
			byte [] digest=md.digest(str.getBytes());
			char [] chars= {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
			StringBuilder sb=new StringBuilder();
			//处理加密结果
			for(byte b:digest){
				sb.append(chars[(b>>4)&15]);
				sb.append(chars[b&15]);
			}
			return sb.toString();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return null;
	}
	
    /**
     * 将字符串进行sha1加密
     *
     * @param str 需要加密的字符串
     * @return 加密后的内容
     */
   /* 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 "";
    }*/

	/*public static String getSha1(String str){
        if(str==null||str.length()==0){
            return null;
        }
        char hexDigits[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
        try {
            MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
            mdTemp.update(str.getBytes("UTF-8"));
            byte[] md = mdTemp.digest();
            int j = md.length;
            char buf[] = new char[j*2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
                buf[k++] = hexDigits[byte0 & 0xf];      
            }
            return new String(buf);
        } catch (Exception e) {
            return null;
        }
	}*/
	/**
	 * 解析xml数据包
	 * @param is
	 * @return
	 */
	public static Map<String, String> parseRequest(InputStream is) {
		Map<String, String> map=new HashMap<String, String>();
		SAXReader reader = new SAXReader();  
		 try {
			//读取数据流,获取文档对象
			Document document=reader.read(is);
			//根据文档对象获取根节点
			Element root = document.getRootElement();
			//获取根节点的所有的子节点
			List<Element> elements = root.elements();
			for (Element e : elements) {
				map.put(e.getName(), e.getStringValue());
			}
			
		} catch (DocumentException e) {
			e.printStackTrace();
		}
		return map;
	}

}

其中SAXReader 需要引入dom4j-1.6.1.jar  jaxen-1.1.1.jar

代码写完后,启动项目,需要一个工具将我们的内网链接映射为公网,这样微信才能访问到我们的后台,这里我采用的是一款免费的映射工具ngrok

4、内网穿透工具使用

内网穿透工具(外网映射工具)ngrok:将我们的内网链接映射为公网。下载链接: https://ngrok.com/download

下载完后解压到指定位置

双击运行(ngrok.exe),弹出命令行黑窗口

输入ngrok http 8080 回车,显示结果中,Forwarding对应内容即为公网链接,可直接访问本机127.0.0.1:8080下的链接内容,分别是http协议和https协议对应的地址:

5、测试

执行步骤2,填入地址,与自定义的tocken,此处为bgm_tocken,点击提交

java后台显示:

此时接口接入成功:

 

https://developers.weixin.qq.com/doc/offiaccount/Getting_Started/Getting_Started_Guide.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值