2018-02-03 09:43:54 yji534123343 阅读数 913
  • thinkphp5微信开发实践教程

    本课程是基于ThinkPHP5.0.1的微信开发教程,在整个课程中全部采用原理讲解和实践开发配套的方式。在该教程中还包含了源码供大家下载。代码下载地址:https://code.csdn.net/hayixia606/wechat/tree/master

    2918 人正在学习 去看看 魏永强
一、微信开发的整体介绍
开放平台:https://open.weixin.qq.com/
公众平台:https://mp.weixin.qq.com/
1、微信开发的种类
①移动应用开发
支持微信的分享、收藏、支付三大功能,原生开发的人员去使用的开发类别
②网站应用开发
网站支持使用微信账号进行注册和登录,从而来实现:提高用户的留存率,方便不同账号的统一(结合unionId)
③公众账号开发


④公众账号第三方平台
优势在于免繁琐设置,方便小白用户去使用。


2、公众账号开发
①服务号
主要偏向于给用户提供查询服务(招商银行、麦当劳。。)
显示在好友列表,每个月只能群发4条消息


②订阅号
主要偏向于给用户提供资讯(朝闻天下、Web前端。。)
显示在订阅号文件夹内,每天都可以群发1条消息


③小程序
2017年1月9号 (2007年1月9号 推出iphone)
基于微信的平台,ui提供了很多组件,js提供了很多接口


(微信官方的小程序:小程序示例,包含了微信官方封装好的组件、以及封装好的接口)


目标:万物互联 (IOT),  二维码
开放范围:(不包含个人)
http://www.wxapp-union.com/forum.php?mod=viewthread&tid=495


https://mp.weixin.qq.com/debug/wxadoc/dev/index.html


数据存储和服务器:
两种解决方案 ①腾讯云(不到100) ②godaddy


④企业号
主要是建立起 企业与人的关系,提供信息、和企业相关的定制功能


温馨提示:
1)如果想简单的发送消息,达到宣传效果,建议可选择订阅号;
2)如果想进行商品销售,进行商品售卖,建议可申请服务号;
3)如果想用来管理内部企业员工、团队,对内使用,可申请企业号。
4)订阅号可通过微信认证资质审核通过后有一次升级为服务号的入口,升级成功后类型不可再变。
5)服务号不可变更成订阅号。


3、九大类高级接口


语音识别接口
客服接口
OAuth2.0 网页授权接口
生成带参数的二维码接口
获取用户地理位置接口
获取用户基本信息接口
获取关注者列表接口
用户分组接口
上传下载多媒体文件接口


+ 微信支付
(十大类接口的使用,必须是认证过的服务号和订阅号才能使用)




4、正式环境的搭建
(公众账号-》订阅号)


购买自己的域名(万网、dnsPod、godaddy)
购买申请主机空间(新浪云、阿里云、腾讯云、大米云、godaddy、aws)
注册订阅号
登录到订阅号管理接口、服务器的配置、调用10大类接口


5、测试环境的搭建
(公众账号-》订阅号)


主机空间(新浪云)
注册订阅号
登录到订阅号管理接口、服务器的配置、调用10大类接口


6、注册订阅号
①填写邮箱、密码
②到邮箱中激活账号
③选择类型
④登记信息(个人、组织、媒体、企业。。)
⑤填写公众号的信息(名称、介绍、头像)






二、个人订阅号(jssdk)


1、实现功能:统计页面被访问的次数


分析:
①存储需要持久保存的数据
数据库、文件系统、内存中:fileSystem
②读写过程
读:file_get_contents($fileUrl);
写:file_put_contents($fileUrl,$content);


需要apache启动


2、新浪云storage


通过bucket管理我们的文件,如何访问?
saestor:// testbucket/count.txt




3、jsSDK的使用步骤
①绑定域名
②引入js文件
③注入接口(将使用接口的名称,写在config方法中jsAPIList这个数组中)
④在ready中调用接口
⑤在error中处理失败的异常情况






sample.zip有4个文件,
前两个文件都是用来存储数据的,jssdk.php进行网络请求以及数据的读写操作,sample.php文件主要完成接口的注入和调用


jssdk.php封装了2个方法get_php_file、set_php_file,如果部署在服务端,写文件会出现权限拒绝的问题。
①将存储文件 放到新浪云的bucket中
②修改读写文件的路径为 saestor://bucketName/**.php




require subscribe 需要订阅测试账号。




三、版本控制工具(git)


1、版本控制
记录一个或者多个文件内容变化,以便于未来查询指定的版本信息。


svn 集中式/git  分布式
①防止代码的丢失
②团队协作
③版本还原
④更好的管理代码


2、git介绍
用于代码的版本控制,使用方式:命令行/图形化


git(分布式版本控制工具)与github(托管开源项目的网站,托管项目的方式采用的是git)


3、自己使用git将项目上传到github


①申请github的账号 
https://github.com/
注册账号,在选择计划的时候选择continue,在编辑经验时选择skip跳过。
②去邮件激活账号
③start project 只需要指定repository的名称,点击create去创建。


④安装git
一路next,最后点击install安装 取消所有的勾选就可以了。
⑤启动git
到所有程序中,找到git,找到gitbash,点击启动


⑥基础命令
ls (list) 查看当前目录下的文件
clear 清除当前的屏幕信息
pwd (print the work directory)显示当前目录
mkdir web1609 在当前的路径中创建一个叫做web1609的目录
cd web1609 (change directory)
touch a.txt 创建一个叫做a.txt的一个文件


通过电脑中的文件系统找到文件,写上了hello git.


git的用法


git init 初始化仓库
git status 查看仓库的状态
git add a.txt 将a.txt添加到代码仓库
git commit -m '第一次提交'     添加到缓存区


配置上传到github上的用户信息:
git config --global user.name "web1609best"
git config --global user.email "web1609@vip.163.com"


设置完账号之后,重新提交到缓存区:
git commit -m '第一次提交'     添加到缓存区


将本地的代码设置它推送到github上的地址:
git remote add origin https://github.com/web1609best/web1609.git


将当前目录的git仓库推送到github对应的origin地址的master分支
git push origin master

















2018-09-29 14:18:31 qq_29914837 阅读数 776
  • thinkphp5微信开发实践教程

    本课程是基于ThinkPHP5.0.1的微信开发教程,在整个课程中全部采用原理讲解和实践开发配套的方式。在该教程中还包含了源码供大家下载。代码下载地址:https://code.csdn.net/hayixia606/wechat/tree/master

    2918 人正在学习 去看看 魏永强

上一节内容:
微信开发学习总结(二)——微信开发环境准备(1)
https://blog.csdn.net/qq_29914837/article/details/82891095


三、access_token管理

3.1、介绍access_token
我们的公众号和微信服务器对接成功之后,接下来要做的就是根据我们的业务需求调用微信公众号提供的接口来实现相应的逻辑了。在使用微信公众号接口中都需要一个access_token。
access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token,开发者需要妥善保存access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。并且每天调用获取access_token接口的上限是2000次。
  总结以上说明,access_token需要做到以下两点:
  ①因为access_token有2个小时的时效性,要有一个机制保证最长2个小时重新获取一次。
  ②因为接口调用上限每天2000次,所以不能调用太频繁。
  
3.2、通过微信公众平台提供的接口获取access_token

接口调用请求说明

https请求方式: GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
参数 是否必须 说明
grant_type 获取access_token填写client_credential
appid 第三方用户唯一凭证
secret 第三方用户唯一凭证密钥,即appsecret

返回说明
正常情况下,微信会返回下述JSON数据包给公众号:

{"access_token":"ACCESS_TOKEN","expires_in":7200}
参数 说明
access_token 获取到的凭证
expires_in 凭证有效时间,单位:秒

错误时微信会返回错误码等信息,JSON数据包示例如下(该示例为AppID无效错误):

{"errcode":40013,"errmsg":"invalid appid"}

返回码说明

返回码 说明
-1 系统繁忙,此时请开发者稍候再试
0 请求成功
40001 AppSecret错误或者AppSecret不属于这个公众号,请开发者确认AppSecret的正确性
40002 请确保grant_type字段值为client_credential
40164 调用接口的IP地址不在白名单中,请在接口IP白名单中进行设置。(小程序及小游戏调用不要求IP地址在白名单内。)

在这里插入图片描述
这是我申请公众号测试帐号时分配到的AppID和AppSecret。

3.3、获取access_token方案以及具体实现

这里采用的方案是这样的,定义一个默认启动的servlet,在init方法中启动一个Thread,这个进程中定义一个无限循环的方法,用来获取access_token,当获取成功后,此进程休眠7000秒(7000秒=1.944444444444444小时),否则休眠3秒钟继续获取。流程图如下:
在这里插入图片描述

完整的项目结构
在这里插入图片描述

①定义一个AccessToken实体类

package weixin.entity.accesstoken;

/**
 * @所属类别:实体类
 * @用途:微信公众号开发中AccessToken实体类
 * @author yilei
 * @version:1.0
 */
public class AccessToken {

    //获取到的凭证
    private String accessToken;
    //凭证有效时间,单位:秒
    private int expiresin;

    public String getAccessToken() {
        return accessToken;
    }

    public void setAccessToken(String accessToken) {
        this.accessToken = accessToken;
    }

    public int getExpiresin() {
        return expiresin;
    }

    public void setExpiresin(int expiresin) {
        this.expiresin = expiresin;
    }
}

②定义一个WeiXin类,静态变量,代码如下:

package weixin.util;

/**
 * @所属类别:工具类
 * @用途:存放微信公众号开发中全部静态变量(微信开发服务器配置-token-access_token等)
 * @author yilei
 * @version:1.0
 */
public class WeiXin {
	/**
	 * Token可由开发者可以任意填写,用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性)
	 * 这里和你服务器配置-令牌(token)一致
	 */
	public static final String TOKEN  ="yilei";
	
	
	/**
	 * 第三方用户唯一凭证
	 */
	public static String APPID="wxc931e30eb7da614b";
	
	/**
	 * 第三方用户唯一凭证密钥,即appsecret
	 */
	public static String APPSECRET="ae68f7583fda08460e116fc02780aab8";
	
	/**
	 * 获取access_token的调用接口
	 */
	public static String ACCESS_TOKEN_URL="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";

}

③WeiXinCheck 工具类,存在共用方法

package weixin.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import net.sf.json.JSONObject;
import weixin.entity.accesstoken.AccessToken;

/**
 * @所属类别:工具类
 * @用途:微信开发校验方法、sha1加密算法等
 * @author yilei
 * @version:1.0
 */
public class WeiXinCheck {

	/**
	 * @method 将token、timestamp、nonce三个参数进行字典序排序
	 * @param token
	 * @param timestamp
	 * @param nonce
	 * @return 排序后的字符串
	 */
	public static 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();
	}

	/**
	 * @method 将三个参数字符串拼接成一个字符串进行sha1加密
	 * @param str,需要加密的字符串(排序后的字符串)
	 * @return 加密后的内容
	 */
	public static 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 "";
	}

	/**
	 * @method 开发者获得加密后的字符串可与signature对比
	 * @param str ,需要加密的字符串(排序后的字符串)
	 * @return 加密后的内容
	 */
	public static boolean equalSignature(String str, String signature) {
		boolean falg = false;
		if (str != null && str != "") {
			if (str.equals(signature)) {
				falg = true;
			}
		}
		return falg;

	}

	/**
	 * 发起Http请求, 通过GET方式访问网络用到的方法
	 * @param url,请求的URL地址
	 * @return 响应后的字符串
	 */
	public static JSONObject doGetStr(String url){
		DefaultHttpClient httpClient = new DefaultHttpClient();
		HttpGet httpGet = new HttpGet(url);
		JSONObject jsonObject = null;
		try {
			HttpResponse response =  httpClient.execute(httpGet);
			HttpEntity entity = response.getEntity();
			if(entity!=null){
				String result=EntityUtils.toString(entity);
				jsonObject = JSONObject.fromObject(result);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return jsonObject;
	}
	
	/**
	 * 发起Http请求, 通过POST方式访问网络用到的方法
	 * @param url,请求的URL地址
	 * @return 响应后的字符串
	 */
	public static JSONObject doPostStr(String url,String outstr){
		DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);
        JSONObject jsonObject = null;
		try {
			httpPost.setEntity(new StringEntity(outstr, "UTF-8"));
			HttpResponse response = httpClient.execute(httpPost);
			HttpEntity entity = response.getEntity();
			String result=EntityUtils.toString(entity,"UTF-8");
			jsonObject = JSONObject.fromObject(result);
		
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		return jsonObject;
		
	}

	/**
	 * 获取access_token
	 * @return AccessToken对象
	 */
	public static AccessToken getAccessToken() {
		AccessToken accessToken = new AccessToken();
		String url = WeiXin.ACCESS_TOKEN_URL.replace("APPID", WeiXin.APPID).replace("APPSECRET", WeiXin.APPSECRET);
		JSONObject jsonObject = WeiXinCheck.doGetStr(url);
		if (jsonObject != null) {
			accessToken.setAccessToken(jsonObject.getString("access_token"));
			accessToken.setExpiresin(jsonObject.getInt("expires_in"));
		}
		return accessToken;
	}
}

④AccessTokenServlet类(当服务器启动时会自动获取获取AccessToken,设置每隔7000s重新获取一次AccessToken)

package weixin.controller.accesstoken;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import weixin.entity.accesstoken.AccessToken;
import weixin.util.WeiXinCheck;
/**
 * @所属类别:servlet类
 * @用途:当服务器启动时会自动获取获取AccessToken,设置每隔7000s重新获取一次AccessToken
 * @author yilei
 * @version:1.0
 */
public class AccessTokenServlet extends HttpServlet {

	  @Override
	    public void init() throws ServletException {
	        System.out.println("默认启动AccessTokenServlet");
	        super.init();

	        //开启一个新的线程
	        new Thread(new Runnable() {
	            @Override
	            public void run() {
	                while (true) {
	                    try {
	                        //获取accessToken
	                    	AccessToken accessToken = WeiXinCheck.getAccessToken();
	                        //获取成功
	                        if (accessToken != null) {
	                        	System.out.println("access_token获取成功");
	                            //获取到access_token 休眠7000秒,大约2个小时左右
	                            Thread.sleep(7000 * 1000);
	                            //Thread.sleep(10 * 1000);//10秒钟获取一次
	                        } else {
	                            //获取失败
	                            Thread.sleep(1000 * 3); //获取的access_token为空 休眠3秒
	                        }
	                    } catch (Exception e) {
	                        System.out.println("发生异常:" + e.getMessage());
	                        e.printStackTrace();
	                        try {
	                            Thread.sleep(1000 * 10); //发生异常休眠1秒
	                        } catch (Exception e1) {

	                        }
	                    }
	                }

	            }
	        }).start();
	    }
}

⑤MainApplication微信开发接口入口

package weixin;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import weixin.util.WeiXin;
import weixin.util.WeiXinCheck;
/**
 * @所属类别:servlet类
 * @用途:微信开发接口入口
 * @author yilei
 * @version:1.0
 */
public class MainApplication extends HttpServlet{

	/**
	 * 开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上
	 * @param request
	 * @param response
	 * @throws IOException 
	 */
	@Override
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		 // TODO Auto-generated method stub
		 System.out.println("开始校验签名");
		 //接收微信服务器发送请求时传递过来的4个参数
		 String signature = request.getParameter("signature");//微信加密签名signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
		 String timestamp = request.getParameter("timestamp");//时间戳
		 String nonce = request.getParameter("nonce");//随机数
		 String echostr = request.getParameter("echostr");//随机字符串
		 //排序
		 String sortString = WeiXinCheck.sort(WeiXin.TOKEN, timestamp, nonce);
		 //sha1加密
		 String mySignature = WeiXinCheck.sha1(sortString);
		 //校验签名
		 if (WeiXinCheck.equalSignature(mySignature, signature)) {
	            System.out.println("签名校验通过。");
	            //如果检验成功输出echostr,微信服务器接收到此输出,才会确认检验完成。
	            //response.getWriter().println(echostr);
	            response.getWriter().println(echostr);
	        } else {
	            System.out.println("签名校验失败.");
	        }
	}
    @Override
	public void doPost(HttpServletRequest request, HttpServletResponse response){
	
    }
	
}

⑥web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <display-name></display-name>
  <servlet>
    <servlet-name>MainApplication</servlet-name>
    <servlet-class>weixin.MainApplication</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>MainApplication</servlet-name>
    <url-pattern>/main.do</url-pattern>
  </servlet-mapping>
  
    <servlet>
    <servlet-name>AccessTokenServlet</servlet-name>
    <servlet-class>weixin.controller.accesstoken.AccessTokenServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>AccessTokenServlet</servlet-name>
    <url-pattern>/AccessTokenServlet.do</url-pattern>
  </servlet-mapping>	
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

启动服务器,控制台输入:
在这里插入图片描述


微信开发学习总结(二)——微信开发环境准备(2)项目源码
下载地址:

https://download.csdn.net/download/qq_29914837/10696721


下一节内容:
微信开发学习总结(三)——消息管理—接收普通消息—(1)文本消息
https://blog.csdn.net/qq_29914837/article/details/82903594

2018-09-28 22:37:39 qq_29914837 阅读数 800
  • thinkphp5微信开发实践教程

    本课程是基于ThinkPHP5.0.1的微信开发教程,在整个课程中全部采用原理讲解和实践开发配套的方式。在该教程中还包含了源码供大家下载。代码下载地址:https://code.csdn.net/hayixia606/wechat/tree/master

    2918 人正在学习 去看看 魏永强

上一节内容:
微信开发学习总结(一)——微信公众号开发入门指引
https://blog.csdn.net/qq_29914837/article/details/82874832


本节要求:
①理解微信公众平台的基本原理
②测试公众号的注册
③准备微信公众号开发的环境

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

在我们开始使用微信进行开发前,需要明白微信公众平台的基本原理,这样才能事半功倍。

1.1、理解微信服务器概念

微信服务器就相当于一个转发服务器,我们在使用终端(手机、Pad等)发起请求至微信服务器,微信服务器做的工作就是将发起的请求转发到开发者的应用服务器。应用服务器处理完毕后,将响应数据又返回给微信服务器,微信服务器再将具体响应信息回复到微信App等终端。
1.2、通信协议
微信服务器和应用服务器之间通信协议:HTTP协议
1.3、数据传输格式
微信服务器和转发给应用服务器的数据,还是应用服务器通过微信服务器返回给终端的数据格式都是:XML

微信公众号开发对的整个流程如下图所示:
在这里插入图片描述

在这里插入图片描述
1.4、微信开发核心工作
微信开发中核心工作就是对微信服务器转发的HTTP请求做出响应。
应用服务器接受到请求后,按照特定的XML格式去解析得到具体的请求内容,处理完毕后,也要按照特定的XML格式返回。


二、微信公众号接入

微信公众号的接入在微信公众平台-微信公众平台技术文档中有着详细的介绍。在进行微信开发前,建议先完整的浏览下这个文档,可以帮助你有一个对微信开发的整体意识。

接入微信公众平台开发,开发者需要按照如下步骤完成:

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

下面详细介绍这3个步骤。

第一步:填写服务器配置
①登录微信公众平台官网后,在公众平台官网的开发-基本设置页面,勾选协议成为开发者。
②点击“修改配置”按钮,填写服务器地址(URL)、Token和EncodingAESKey,其中URL是开发者用来接收微信消息和事件的接口URL。Token可由开发者可以任意填写,用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性)。EncodingAESKey由开发者手动填写或随机生成,将用作消息体加解密密钥。
在这里插入图片描述

同时,开发者可选择消息加解密方式:明文模式、兼容模式和安全模式。模式的选择与服务器配置在提交后都会立即生效,请开发者谨慎填写及选择。加解密方式的默认状态为明文模式,选择兼容模式和安全模式需要提前配置好相关加解密代码,详情请参考消息体签名及加解密部分的文档 。

第二步:验证消息的确来自微信服务器

(1)实现原理过程
开发者当点击“提交”按钮后,微信服务器将发送一个http的get请求到刚刚填写的服务器地址,并且携带四个参数:
在这里插入图片描述

接到请求后,我们需要做如下三步,若确认此次GET请求来自微信服务器,原样返回echostr参数内容,则接入生效,否则接入失败。
①将token、timestamp、nonce三个参数进行字典序排序
② 将三个参数字符串拼接成一个字符串进行sha1加密
③开发者获得加密后的字符串可与signature对比,标识该请求来源于微信


(2)用Java代码来验证消息的确来自微信服务器

新建一个javaWeb项目
开发工具和环境和项目前期准备工作可以部分参考
https://blog.csdn.net/qq_29914837/article/details/82686202

在这里插入图片描述
在这里插入图片描述

WeiXin.java (存放微信公众号开发中全部静态变量(微信开发服务器配置-token等))

package weixin.util;

/**
 * @所属类别:工具类
 * @用途:存放微信公众号开发中全部静态变量(微信开发服务器配置-token等)
 * @author yilei
 * @version:1.0
 */
public class WeiXin {
	/**
	 * Token可由开发者可以任意填写,用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性)
	 * 这里和你服务器配置-令牌(token)一致
	 */
	public static final String TOKEN  ="yilei";

}

WeiXinCheck.java (微信开发校验方法、sha1加密算法等)

package weixin.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
/**
 * @所属类别:工具类 
 * @用途:微信开发校验方法、sha1加密算法等
 * @author yilei 
 * @version:1.0
 */
public class WeiXinCheck {

	/**
	 * @method 将token、timestamp、nonce三个参数进行字典序排序
	 * @param token
	 * @param timestamp
	 * @param nonce
	 * @return 排序后的字符串
	 */
	public static 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();
	}
	

    /**
     * @method 将三个参数字符串拼接成一个字符串进行sha1加密
     * @param str 需要加密的字符串(排序后的字符串)
     * @return 加密后的内容
     */
    public static 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 "";
    }
    
    
    /**
     * @method 开发者获得加密后的字符串可与signature对比
     * @param str 需要加密的字符串(排序后的字符串)
     * @return 加密后的内容
     */
    public static boolean equalSignature(String str,String signature) {
    	boolean falg=false;
    	 if (str != null && str != "") {
    		 if(str.equals(signature)){
    			 falg = true;
    		 }
    	 }
		return falg;
    	
    }
}

MainApplication.java (微信开发接口入口)

package weixin;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import weixin.util.WeiXin;
import weixin.util.WeiXinCheck;
/**
 * @所属类别:servlet类
 * @用途:微信开发接口入口
 * @author yilei
 * @version:1.0
 */
public class MainApplication extends HttpServlet{

	/**
	 * 开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上
	 * @param request
	 * @param response
	 * @throws IOException 
	 */
	@Override
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		 // TODO Auto-generated method stub
		 System.out.println("开始校验签名");
		 //接收微信服务器发送请求时传递过来的4个参数
		 String signature = request.getParameter("signature");//微信加密签名signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
		 String timestamp = request.getParameter("timestamp");//时间戳
		 String nonce = request.getParameter("nonce");//随机数
		 String echostr = request.getParameter("echostr");//随机字符串
		 //排序
		 String sortString = WeiXinCheck.sort(WeiXin.TOKEN, timestamp, nonce);
		 //sha1加密
		 String mySignature = WeiXinCheck.sha1(sortString);
		 //校验签名
		 if (WeiXinCheck.equalSignature(mySignature, signature)) {
	            System.out.println("签名校验通过。");
	            //如果检验成功输出echostr,微信服务器接收到此输出,才会确认检验完成。
	            //response.getWriter().println(echostr);
	            response.getWriter().println(echostr);
	        } else {
	            System.out.println("签名校验失败.");
	        }
	}
    @Override
	public void doPost(HttpServletRequest request, HttpServletResponse response){
	
    }
	
}

web.xml (配置servlet)

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
  <display-name></display-name>
  <servlet>
    <servlet-name>MainApplication</servlet-name>
    <servlet-class>weixin.MainApplication</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>MainApplication</servlet-name>
    <url-pattern>/main.do</url-pattern>
  </servlet-mapping>	
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>

重点:微信服务器配置中要求url必须以http://或https://开头,分别支持80端口和443端口。
在这里插入图片描述

因此建议先改tomcat的端口号,将8080改为80,双击Tomcat v8.0,修改HTTP/1.1为80
在这里插入图片描述

启动ngrok.exe,输入 ngrok http 80,回车
在这里插入图片描述

复制http://f1d06bc1.ngrok.io
在这里插入图片描述
打开微信公众平台 - 开发–基本配置
在这里插入图片描述

填写url,URL中的/weixin/main.do为上(2)中新建项目的servlet访问地址
token 要求和项目中WeiXin.java中 TOKEN变量一致。

在这里插入图片描述

记住要先将tomcat端口号改为80,再启动项目。
项目启动完毕后,运行ngrok.exe 获得外网访问地址,填写到微信公众平台服务器配置中,注意,token要一致,最后再点击保存。

提交成功,控制台输出
在这里插入图片描述

表示验证消息的确来自微信服务器成功

同理,可以在微信公众平台-开发者工具-公众平台测试账号中进行一样的配置(后面我将直接通过微信提供的测试号来进行开发。)
在这里插入图片描述
在这里插入图片描述


第三步:依据接口文档实现业务逻辑
 第3步本质上不是微信公众号接入的步骤,而是接入之后,开发人员可以根据微信公众号提供的接口所能做的一些开发。


三、access_token管理

下一节内容:
微信开发学习总结(二)——微信开发环境准备(2)
https://blog.csdn.net/qq_29914837/article/details/82896861


2017-09-12 14:35:08 dlz_Mr 阅读数 289
  • thinkphp5微信开发实践教程

    本课程是基于ThinkPHP5.0.1的微信开发教程,在整个课程中全部采用原理讲解和实践开发配套的方式。在该教程中还包含了源码供大家下载。代码下载地址:https://code.csdn.net/hayixia606/wechat/tree/master

    2918 人正在学习 去看看 魏永强

微信开发笔记(1)——配置微信服务器、验证信息

配置微信服务器消息验证接口

微信开发需要你有自己的服务器才可以;如果没有公网服务器,有内网映射工具也是可以,我用的花生壳,网上比较多,大家可以搜索一下

登录微信mp平台

https://mp.weixin.qq.com
如果已经注册直接登录即可,未注册的话点击注册先行注册

配置服务器信息
在mp平台上:开发菜单-基本配置中配置服务器
这里写图片描述

*此处的url配制成你自己服务器的接口,此接口为get方式
*此处的Token和之后会涉及到的access_token不同,这里的token是自己定义的,用来验证消息是不是微信服务器发送过来的
*消息加密密钥随机生成就可以,如果之后选择安全模式则需要此处的密钥

都配置完毕后点击提交验证一下服务器可用性;如果提示配置成功则证明你的服务器可用且代码逻辑正确;如果配置失败根据具体提示检验服务器可用性和代码逻辑问题。

java代码逻辑:验证消息是否为微信服务器发来

微信服务器会请求你配置的服务器url,并携带以下参数:
signature :微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
timestamp 时间戳
nonce 随机数
echostr 随机字符串
验证逻辑:
1)将token、timestamp、nonce三个参数进行字典序排序
2)将三个参数字符串拼接成一个字符串进行sha1加密
3)将自己加密后获得的字符串可与signature对比,如果与微信服务器返回的加密字符串signature一样,那就将微信返回来的echostr 随机字符串原封不懂的返回微信服务器,不对的话返回空串或者什么都不返回
java代码示例:

public void pushMessage(HttpServletRequest request, HttpServletResponse response) throws IOException {
        log.info("WeChatController-->pushMessage():start");
        // 微信加密签名
        String signature = request.getParameter("signature");
        // 时间戳
        String timestamp = request.getParameter("timestamp");
        // 随机数
        String nonce = request.getParameter("nonce");
        // 随机字符串
        String echostr = request.getParameter("echostr");

        PrintWriter out = response.getWriter();
        // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
        if (SignUtil.checkSignature(signature, timestamp, nonce)) {
            out.print(echostr);
        }
        out.close();
        out = null;
   }  
    /** 
     * 验证签名 
     *  
     * @param signature 
     * @param timestamp 
     * @param nonce 
     * @return 
     */
    public static boolean checkSignature(String signature, String timestamp,String nonce) {
        String []arr = new String []{token,timestamp,nonce};
        Arrays.sort(arr);
        StringBuffer content = new StringBuffer();
        for (int i = 0; i < arr.length; i++) {
            content.append(arr[i]);
        }
        MessageDigest md = null;
        String tmpStr = null;
        try {
            md = MessageDigest.getInstance("SHA-1");
            byte[] digest = md.digest(content.toString().getBytes());
            tmpStr = byteToStr(digest);
        } catch (NoSuchAlgorithmException e) {
            // TODO: handle exception
        }
        content = null;
        return tmpStr!=null?tmpStr.equals(signature.toUpperCase()):false;
    }

/** 
     * 将字节数组转换为十六进制字符串 
     *  
     * @param byteArray 
     * @return 
    public static String byteToStr(byte[] byteArray) {
        String strDigest ="";
        for (int i = 0; i < byteArray.length; i++) {
            strDigest +=byteToHexStr(byteArray[i]);
        }
        return strDigest;
    }

编写验证url的post接口
当与微信服务器验证url无误后,微信服务器后将将用户请求的信息以post方式发送到验证url的post接口上,此时就需要你在这个接口中处理剩下的逻辑
微信服务器会将信息以xml的方式放到request中,所以我们需要将流中的xml信息解析出来,获取xml中的数据。
xml信息类似如下:
这里写图片描述

解析流中的xml代码示例:

public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {
        // 将解析结果存储在HashMap中
        Map<String, String> map = new HashMap<String, String>();
        // 从request中取得输入流
        InputStream inputStream = request.getInputStream();
        // 读取输入流
        SAXReader reader = new SAXReader();
        Document document = reader.read(inputStream);
        // 得到xml根元素
        Element root = document.getRootElement();
        // 得到根元素的所有子节点
        List<Element> elementList = root.elements();

        // 遍历所有子节点
        for (Element e : elementList){
            System.out.println("-->e.getName()-->"+e.getName() +"-->e.getText()-->"+e.getText());
            map.put(e.getName(), e.getText());
        }
        // 释放资源
        inputStream.close();
        inputStream = null;

        return map;
    }
2018-06-11 11:46:53 qq_16398399 阅读数 758
  • thinkphp5微信开发实践教程

    本课程是基于ThinkPHP5.0.1的微信开发教程,在整个课程中全部采用原理讲解和实践开发配套的方式。在该教程中还包含了源码供大家下载。代码下载地址:https://code.csdn.net/hayixia606/wechat/tree/master

    2918 人正在学习 去看看 魏永强

在微信项目开发中,我们有时候需要用到微信的一些功能,这就需要引入微信jssdk,这个js引入的协议应该与项目使用的协议之,例如:

http时:http://res.wx.qq.com/open/js/jweixin-1.0.0.js

https时:https://res.wx.qq.com/open/js/jweixin-1.0.0.js

如果项目使用的是https协议,引入js用的是http,android和ios低版本不会有影响,高版本的ios会使用不了

没有更多推荐了,返回首页