Blogger Information
Blog 71
fans 1
comment 1
visits 86858
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
531-微信公众平台开发:本地环境搭建和签名校验与获取access_token
小威的博客
Original
2386 people have browsed it
  •  搭建本地开发环境

由于微信公众平台开发,涉及到与平台对接,所以需要公网域名,而内网映射到公网的方法:国内有花生壳,但是蛋疼的是80端口要花钱买,而微信只对80端口开放对接。没办法只能用国外免费的NGROK,国外的网真难撸

  • 1. 先注册ngrok帐号 注册地址:https://dashboard.ngrok.com/user/signup 注意在注册时会出现验证码项,但天朝有些不明原因被屏蔽了,弄了一天也没注册成功,后来用谷歌浏览器+谷歌访问助手,成功注册到了。。。

0.png

  • 2. 注册成功 登录帐号  下载ngrok程序,解压到项目根目录,例如:D:\myphp_www\PHPTutorial\WWW\tp51

  • 3. 用命令行 安装程序  并运行程序

1.png

  • 4. 安装成功,如下图界面:并且获取到外网域名了

2.png

  • 注意:norok程序运行窗口,在开发过程中最好不要关闭,一关闭就会断线,再开启公网域名就会更新了

  • 5. 配置本地域名管理器-PHP工具箱。

3.png

  • 到此,本地开发环境就配置成功了,,但是后续开发服务号需要备案域名,所以云服务器+备案域名是最佳运行环境。


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

一、填写服务器配置

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

4.png

URL  根据开发环境域名配置    Token 协议密钥  开发者自定义   EncodingAESKey 开发者自定义或随机生成43个字符

二、验证服务器地址的有效性

开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,GET请求携带参数如下表所示:

signature    微信加密签名  timestamp    时间戳     nonce    随机数     echostr    随机字符串    

我们这里用get的方法拿:signature timestamp nonce   echostr 这四项参数

 $signature = input('get.signature');
 $timestamp = input('get.timestamp');
 $nonce = input('get.nonce');
 $echostr = input('get.echostr');
 
 $token = config('app.token');

token 是我们自定义的,所以让我们提供:$token = ‘abcd12345’

而在企业级开发中,一般密钥口令之类的,我们不能写在项目中,而是写到配置中  再在项目中调用的

//微信配置
'token'            => 'aMCikdpelcnEk1omMjK4'

开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。加密/校验流程如下:

先将获取到的参数,保存到本地记事本,看看能否获得到相关参数

file_put_contents('D://data.txt','signature='.$signature.' timestamp='.$timestamp.' nonce='.$nonce.' echostr='.$echostr);

1)将token、timestamp、nonce三个参数进行字典序排序 

$tmpArr = array($timestamp,$nonce,$token);  //将几个参数放到一个数组中
sort($tmpArr, SORT_STRING); //sort(,SORT_STRING)   对数组进行排序

2)将三个参数字符串拼接成一个字符串进行sha1加密 

$str = implode($tmpArr);//implode 拼接字符串
$sign = sha1($str);//sha1加密字符串
echo $sign;//输出一下看看效果
exit;

QQ截图20180603000140.png

3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信

if ($sign !=$signature) {//如果检验不匹配
            exit('signature error');//返回一个签名错误
        }
        exit($echostr);//如果匹配通过,原样返回

以上所有校验代码都可以进行优化,将校验过程封装到模型中做为校验方法:tp51/application/model/Weixin.php

<?php
namespace app\index\model;
use think\Model;
use think\facade\Cache;

class Weixin extends Model{

    // 签名校验
    public function valid(){
        $signature = input('get.signature');
        $timestamp = input('get.timestamp');
        $nonce = input('get.nonce');
        $echostr = input('get.echostr');
        $token = config('app.token');

        $tmpArr = array($timestamp,$nonce,$token);
        sort($tmpArr, SORT_STRING);
        $str = implode($tmpArr);
        if(sha1($str) != $signature){
            return false;
        }
        return true;
    }

而在控制器中直接用valid()方法调用:

<?php
namespace app\index\controller;
use think\Controller;
use think\facade\Cache;//导入门面模式缓存方法

class Weixin extends Controller{
    public function __construct(){
        parent::__construct();
        $this->model = model('Weixin');//用构造器方法  方便后期整体参数修改
    }
    public function valid(){
        $valid = $this->model->valid();
        if(!$valid){
            exit('signature error');
        }
        exit(input('get.echostr'));
    }

三、依据接口文档实现业务逻辑

验证URL有效性成功后即接入生效,成为开发者。你可以在公众平台网站中申请微信认证,认证成功后,将获得更多接口权限,满足更多业务需求。

成为开发者后,用户每次向公众号发送消息、或者产生自定义菜单、或产生微信支付订单等情况时,开发者填写的服务器配置URL将得到微信服务器推送过来的消息和事件,开发者可以依据自身业务逻辑进行响应,如回复消息。

  • 获取access_token

access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。

1. 公众号可以使用AppID和AppSecret调用本接口来获取access_token。

2. AppID和AppSecret可在“微信公众平台-开发-基本配置”页中获得(需要已经成为开发者,且帐号没有异常状态)。

3. 调用接口时,请提前将服务器IP地址添加到IP白名单中,点击查看设置方法,否则将无法调用成功。

5.png

接口https请求方式: GET:

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

此请求URL中有两个重要参数: APPID  APPSECRET  这两个参数一般不直接写在项目中,而是写到项目配置中APP

//微信配置
    'token'            => 'aMCikdpelc00k1omMjK4',

    'appid'                  => 'wxdb8a19000a62f575',

    'appsecret'              => '8084703db2897e05000024975dc1708',

URL请求方式:GET,微信官方有给我们提供实例程序如下:把它写到公共文件下面:tp51/application/common.php

<?
// 应用公共文件
function http_Get($url){
	$curl = curl_init();
	curl_setopt($curl,CURLOPT_URL,trim($url));
	curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
	curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
	curl_setopt($curl,CURLOPT_HEADER,0);
	curl_setopt($curl,CURLOPT_CUSTOMREQUEST,'GET');//需要要传送的内容
	curl_setopt($curl,CURLOPT_RETURNTRANSFER,1);
	$return_str = curl_exec($curl);
	curl_close($curl);
	return $return_str;
}

这个实例程序怎么写的,为什么这样写,我们都不用管它,尽管按官方的方法写就行

curl:就是在应用程序里面模拟浏览器去访问一些URL资源

//获取access_token
    public function get_access_token(){
        $appid = config('app.appid');
        $appsecret = config('app.appsecret');
        $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$appid.'&secret='.$appsecret;
        $res = http_Get($url);
        dump($res); exit;
        }

此处$appid   $appsecret 都是调用配置文件的值   URL用字符串拼接的方式       用http_Get请求的方法

6.png

测试得到错误信息是:IP不在白名单内,只需添加公网IP到白名单即可获取到access_token

7.png

由于微信公众平台的access_token有调用次数限制,服务号是10000次,个人号更少,每天调用完就没得用了,还会造成通讯浪费,对于固定密钥我们可以一个策略方法:将获取到的access_token缓存到本地目录中,当需要时直接从本地目录调用即可。

8.png

然而access_token只有2个小时的有效期,到期就更新,所以我们又要想到缓存周期为2小时内,当快过2小时时,再次从平台获取缓存

$res = json_decode($res,true);//json_decode对JSON数据进行解码,转换为PHP变量
Cache::set('access_token',$res['access_token'],$res['expires_in']-300);
//cache::set() 方法  有三个参数:1. 键 2. 值 3. 时间

前提要先导入方法:use think\facade\Cache;//导入门面模式缓存方法

9.png

同样我们也要把这个获取access_token的方法,封装到模型中:tp51/application/model/Weixin.php

//获取access_token
	public function access_token($iscache = true){
	$key = 'access_token'; //简化常量
        if(!$iscache){
            Cache::rm($key);
        }
		$data = Cache::get($key);
		if($data && $iscache){
			return $data;
		}
		$appid = config('app.appid');
    	$appsecret = config('app.appsecret');
    	$url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$appid.'&secret='.$appsecret;
    	$res = http_get($url);
    	$res = json_decode($res,true);
    	if(!isset($res['access_token'])){
    		return false;
    	}
    	Cache::set($key,$res['access_token'],($res['expires_in']-100));
    	return $res['access_token'];
	}

1. access_token($iscache = true)  默认要缓存 access_token

2. 判断是否要删除缓存

if(!$iscache){
           Cache::rm($key);
       }

3. 判断是否有缓存数据:如果有就直接从缓存拿数据  如果没有就从平台获取数据

$data = Cache::get($key);
		if($data && $iscache){
			return $data;
		}

而在控制器中直接用get_access_token()方法调用:

//获取access_token
    public function get_access_token(){
        $key = 'access_token';
        $access_token = Cache::get($key);
        if($access_token){
            return $access_token;
        }

        $appid = config('app.appid');
        $appsecret = config('app.appsecret');
        $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$appid.'&secret='.$appsecret;
        $res = http_Get($url);
        $res = json_decode($res,true);
        Cache::set($cache_key,$res['access_token'],$res['expires_in']-600);
        return $res['access_token'];
    }

总结:其实整个过程就是:

1. 开发者网站发出接入请求,微信公众平台发出GET请求,signature timestamp nonce   echostr 等参数(这些参数由微信公众平台和开发者共同约定设置好的,只有两者知道),开发者网站与其对比匹配,其中将token、timestamp、nonce三个参数进行字典序排序,拼接,加密。。如果对比通过,就允许接入。对比不通过,就是非法请求,拒绝!

2. 微信公众平台为了通讯的安全性,设定了个口令,并且2小时更新一次,开发者网站后续功能操作,需要实时检验口令,口令通过才能继续通讯操作相关功能。。由于官方口令的限制性,我们又对口令采取了缓存本地并且每2小时内重新从微信平台获取口令一次的策略

以上两部完成了对接和验证功能,就可以继续后面的工作开发。。。

其实第三方平台对接都是这个策略,先互相校验设定好的口令(类似于江湖上的对暗号),暗号对上了,就可以开始互相交换相关数据,并开发相关功能操作。。。

Correction status:Uncorrected

Teacher's comments:
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post