Hi,为确保您的账号安全,请大家修改登陆密码为包含大小写字母、标点、数字的复合密码,不要使用过于简单的登陆密码。
您当前的位置:首页 :: PHP

larave之微信授权篇

时间:2018-01-16 16:28:33  来源:  作者:

在实际项目中需要用到微信支付与微信授权登录与微信相关的业务,这里只说H5的微信授权

当然了现在在github上面有基于laravel的微信授权与第三方授权的功能,自己搜索就可以找得到,然后配置一下加载的自己的项目里就可以正常的使用,那么如果你自己搞过可以绕道了,本文只讲微信授权,望大神不要喷我, 小弟在此谢过!

laravel的微信授权功能有使用的service模块来实现,有的直接使用一个控制器,或自己写的一个类都是可以实现的,具体方法大家可以发挥只要能实现功能就是好方法,而本文使用的方法是
traits方法,那么有些同学会问了什么是traits? 这个我只能说不懂百度啊! 大哥, 下面我们简单说一下什么是traits,.

什么是traits呢? 自PHP5.4.0起,PHP实现了一个代码复用的一个方法称为traits,它为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用方法集,和类组合的语义是定义了一种方式来减少复杂性,避免传统多继承和混入类(Mixin)相关的典型问题。Traits和一个类相似,但仅仅旨在用细粒度和一致的方式来组合功能。Traits不能通过它自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用类的成员不需要继承。

讲一下Trait的优先级也就是顺序问题:从基类继承的成员被 traits插入的成员所覆盖。优先顺序是来自当前类的成员覆盖了traits的方法,而traits则覆盖了被继承的方法。下面是个例子:

<?php
class Base {
	public function sayHello() {
		echo 'Hello ';
	}
}
trait SayWorld {
	public function sayHello() {
		parent::sayHello();
		echo 'World!';
	}
}
class MyHelloWorld extends Base {
	use SayWorld;
}
$o = new MyHelloWorld();
$o->sayHello();
//输出Hello World!
?>

从上的面例子里可以看到MyHelloWorld是继承base的,而且MyHelloWorld并没有sayHello方法,如果不加trait则是调用基类里base里方法,加了trait则就是调用trait里的方法.然后还有trait冲突问题等,大家可以百度自行学习一下,这里不多过讲解

代码如下:

<?php

namespace App\Traits;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Config;
use Carbon\Carbon;
/**
 * trait WxChat
 * @package App\Traits
 */
trait WxChat
{
    // 0 GET请求  1 post 请求
    public function curl($url, $type = 0, $postData = [])
    {
        if (!$url) {
            return false;
        }

        if ($type == 0) {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_HEADER, false);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        } elseif ($type == 1) {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        }

        $result = curl_exec($ch);
        curl_close($ch);

        return $result;
    }

    public function getAccessTokenInfo($appId, $appSecret, $code)
    {
        if (!$code || !$appSecret) {
            return false;
        }

        $accessToken = md5($code . DOMAIN_WWW . 'f_wx_access_token');
        $refreshToken = md5($code . DOMAIN_WWW . 'f_wx_refresh_token');
        $appId = $appId ? $appId : $this->config['app_id'];

        if (Cache::has($refreshToken)) {
            if (Cache::has($accessToken)) {
                $tokenInfo = Cache::get($accessToken);
            } else {
                $refreshToken = Cache::get($refreshToken);
                $url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=$appId&grant_type=refresh_token&refresh_token=$refreshToken";
                $tokenInfo = $this->wxTokenCache($url, $accessToken, $refreshToken);
            }
        } else {
            $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=$appId&secret=$appSecret&code=$code&grant_type=authorization_code";
            $tokenInfo = $this->wxTokenCache($url, $accessToken, $refreshToken);
        }

        return $tokenInfo;
    }

    public function getUserInfo($accessToken, $openid)
    {
        if (!$accessToken || !$openid) {
            return false;
        }

        $url = "https://api.weixin.qq.com/sns/userinfo?access_token=$accessToken&openid=$openid";

        return json_decode($this->curl($url), true);
    }

    public function wxTokenCache($url, $accessTokenKey, $refreshTokenKey)
    {
        if (!$url || !$accessTokenKey || !$refreshTokenKey) {
            return false;
        }

        $expiresAtAccessToken = Carbon::now()->addMinutes(110);
        $expiresAtRefreshToken = Carbon::now()->addMinutes(60 * 24 * 30 - 60);
        $tokenInfo = json_decode($this->curl($url), true);

        Cache::put($accessTokenKey, $tokenInfo, $expiresAtAccessToken);
        Cache::put($refreshTokenKey, $tokenInfo['refresh_token'], $expiresAtRefreshToken);

        return $tokenInfo;
    }

    //web授权
    public function wxUserAuth(Request $request){
        $redirect = UrlEncode(DOMAIN_WWW . 'user/dowxuserauth'); //这里是回调处理地址别写错了,要写你自己的路径
        $state = md5(trim($request->input('redirect', ''))); //特码证我们md5并放到了redis里,你可以试着改改
        Cache::put($state, trim($request->input('redirect', '')), 10);
        $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . $this->config['app_id'] . "&redirect_uri=$redirect&response_type=code&scope=snsapi_base&state=$state#wechat_redirect";
        header("Location: $url");
        exit;
    }
    public function dowxUserAuth(Request $request){
        $code = $request->input('code', '');
        if(empty($code)) return false;

        $redirect = trim($request->input('state', ''));
        $redirect = Cache::get($redirect);//用上面的特码证去拿授权地址并把授权完成的信息传过去
        $accessTokenInfo = $this->getAccessTokenInfo($this->config['app_id'], $this->config['app_secret'], $code);
        $userInfo = $this->getUserInfo($accessTokenInfo['access_token'], $accessTokenInfo['openid']);
        $redirect .= (!strpos($redirect, '?') ? '?' : '&').'wxuserinfo='.base64_encode(json_encode($userInfo));
        header("Location: $redirect");
        exit;
    }
}

上面代码入口就是wxUserAuth方法带微信配置信息去微信服务器拿code并返到dowxUserAuth方法里,这里需要注意的就是scope=snsapi_base,这时授权的时候不弹绿页让用户同意授权,只要用户最基本的信息,当拿到code以后就去拿是个临时的assessToken然后去拿该授权的用户信息, 上面accessTokenInfo里已经含有用户的基本信,比如openid等,$userInfo那步可有要无,主要看业务逻辑,哪到用户的授权信息之后,改干什么那是你自己的事情,我们这里把用户授权信息返回给了需要授权的地方

下面再放出处理授权过来的方法,在使用的记得use WxChat 把trait加载进来

protected function wxAuth()
{
	//先判断seesion里有没有授权的信息如果没有则去权授
    $wxuserinfo = session('wxuserinfo');
    if (!empty($wxuserinfo['openid'])) {
        return true;
    }
    //这里处量授权回来的回调处理,并把授权完成的用户信息放到session里
    if (isset($_GET['wxuserinfo'])) {
        $wxuserinfo = json_decode(base64_decode($_GET['wxuserinfo']), 1);
        if (!empty($wxuserinfo) && !empty($wxuserinfo['openid'])) {
            session(['wxuserinfo' => $wxuserinfo]);
            return true;
        }
    }
    //gogo去权授吧 
    $redirectUrl = "https://{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
    $url = DOMAIN_WWW . "wxauth/wxuserauth?redirect=$redirectUrl";
    header("Location:{$url}");
    return true;
}

好了,授权基本就完成了,比如授权登录等就可以直接这些的基本上进行修改与扩展,怎么发挥就看个人水平了.

举报
收藏0次 / 评论0
评论(0)
还可以输入 2000 个字符
还可以输入 2000 个字符
取消回复
举报×

还可以输入 264 字符

收藏(0)×