学php、微信开发、laravel之类的,我都是野路子,没什么系统,所以很多时候去改别人开发好的模块,非常为难,还不如自己去折腾,因此,折腾出一个批代码,做个记录,当然,其实下面这几个函数也和laravel没啥关系,纯粹的php代码
首先写一个用于调用的公共类 WechatClass.php
<?php namespace App\Myclass; use App\Models\Access_token; use App\Models\Wechat; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; class WechatClass { public static function curlGet($url) { $ch = curl_init(); $headers[] = 'Accept-Charset:utf-8'; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET'); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $result = curl_exec($ch); curl_close($ch); return $result; } public static function curlPost($url, $data) { $ch = curl_init(); $headers[] = 'Accept-Charset: utf-8'; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)'); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_AUTOREFERER, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $result = curl_exec($ch); curl_close($ch); $result = json_decode($result, true); if (isset($result['errcode'])) { return array('errcode' => $result['errcode']); } else { $result['errcode'] = 0; return $result; } } public static function checkSignature($signature, $timestamp, $nonce) { $token = TOKEN; $tmpArr = array($token, $timestamp, $nonce); sort($tmpArr, SORT_STRING); $tmpStr = implode($tmpArr); $tmpStr = sha1($tmpStr); if ($tmpStr == $signature) { return true; } else { return false; } } public static function getUserinfo($openid, $access_token) { if ($access_token && $openid) { // $url = "https://api.weixin.qq.com/sns/userinfo?access_token=" . $access_token . "&openid=" . $openid . "&lang=zh_CN"; $url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=$access_token&openid=$openid&lang=zh_CN"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($ch); curl_close($ch); return json_decode($output, true); } } public static function getAccessToken() { $access_token=Access_token::orderBy('id','desc')->first(); if($access_token){ if(time() - $access_token->time < 7100){ //dd($access_token->access_token); return $access_token->access_token; } } $appid = env('WECHAT_OFFICIAL_ACCOUNT_APPID'); $secret = env('WECHAT_OFFICIAL_ACCOUNT_SECRET'); $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $appid . "&secret=" . $secret; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($ch); curl_close($ch); $result = json_decode($output, true); DB::insert('insert into access_token (access_token,time) VALUES (?,?)',[$result['access_token'],time()]); return $result['access_token']; } public static function get_qrcode($scene_id,$logkey){ $access_token = self::getAccessToken(); $qrcode_url = 'https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=' . $access_token; $paras = array("scene_id"=>$scene_id,"logkey"=>$logkey); $post_data = array(); $post_data['expire_seconds'] = 3600 * 24; //有效时间 $post_data['action_name'] = 'QR_STR_SCENE';//字符串 QR_SCENE 数字 $post_data['action_info']['scene']['scene_str'] = json_encode($paras); //传参二维码主键id,微信端可获取 $json = self::curlPost($qrcode_url, json_encode($post_data)); if (!$json['errcode']) { $ticket = $json['ticket']; $ticket_img = 'https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=' . urlencode($ticket); $png = fopen($ticket_img,'r'); file_put_contents(dirname(dirname(dirname(__FILE__))).'/public/uploads/qrcode/'.$logkey.'.png',$png); return $ticket_img; } else { return false; } } }
然后再在controller里面调用这个类
<?php namespace App\Http\Controllers; use App\Models\User; use App\Models\Wechat; use Illuminate\Http\Request; use Illuminate\Support\Facades\Cookie; use Illuminate\Support\Facades\DB; use Auth; use Illuminate\Support\Str; use App\Myclass\WechatClass; define('TOKEN', 'weixin'); class WechatController extends Controller { ///生成带参数的登录二维码 public function index(){ $logkey = Str::random(30); DB::insert('insert into wechat (time,logkey,log_type) VALUES (?,?,?)',[time(),$logkey,'login']); $scene_id=1; $ticket_img=WechatClass::get_qrcode($scene_id,$logkey); if ($ticket_img) { $title='微信扫码测试'; return view('user.wechat',compact('title','ticket_img','logkey')); } else { return 'error'; } } ///用于微信回调url public function callback(Request $request){ $signature = $request->input('signature'); $timestamp = $request->input('timestamp'); $nonce = $request->input('nonce'); $echoStr = $request->input('echostr'); //if (WechatClass::checkSignature($signature, $timestamp, $nonce)) { $data = $request->all(); if(isset($data['openid'])){ $openid = $data['openid']; $access_token = WechatClass::getAccessToken(); //return $access_token; $u = WechatClass::getUserinfo($openid, $access_token); $postStr = file_get_contents('php://input'); $data = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA); if($data->Event) { $FromUserName = $data->FromUserName; //openid $EventKey = $data->EventKey; //带前缀的Key $EventKey = ltrim($EventKey, 'qrscene_'); //去掉前缀就是我们传递给微信的Key $EventKey=json_decode($EventKey,true); $logkey=$EventKey['logkey']; $user = Wechat::where('logkey',$logkey)->first(); $user->subscribe=$u['subscribe']; $user->openid=$u['openid']; $user->nickname=$u['nickname']; $user->sex=$u['sex']; $user->city=$u['city']; $user->province=$u['province']; $user->country=$u['country']; $user->headimgurl=$u['headimgurl']; $user->update(); unlink(dirname(dirname(dirname(dirname(__FILE__)))).'/public/uploads/qrcode/'.$logkey.'.png'); } } ob_end_clean(); //必须清空缓冲区 return $echoStr; //} else { // return 'Token verification failed.'; // } } ///检查登录状态 public function check_auth(Request $request){ $logkey=$request->input('key'); $wechat = Wechat::where('logkey',$logkey)->first(); //dd($wechat->openid); if($wechat->openid){ $user = User::where('openid',$wechat->openid)->first(); if(!$user){ $array=[ 'name'=>$wechat->nickname, 'openid'=>$wechat->openid, 'created_at'=>date('Y-m-d H:i:s'), 'updated_at'=>date('Y-m-d H:i:s'), 'password'=>bcrypt('power123456'), 'log_type'=>$wechat->log_type, 'img'=>$wechat->headimgurl ]; $result = User::create($array); }else{ $user->lasttime=date('Y-m-d H:i:s'); $user->log_type=$wechat->log_type; $user->img=$wechat->headimgurl; $user->update(); $result = $user; } //Cookie::queue('img',urldecode($wechat->headimgurl),60*24); Auth::login($result, true); //$wechat->delete(); return 1; } else{ return 0; } } }
记得将类文件加入composer中
autoload: { "classmap": [ "database", "app/Myclass/WechatClass.php" ], "psr-4": { "App\\": "app/" } },
然后运行以下命令
composer dumpautoload
注意:
1、callback的路由要用any,另外在Middleware/VerifyCsrfToken.php中将改一下post验证例外
protected $except = [ 'wechat', 'callback', ];
2、blade文件中这样写
@extends('user.header') @section('content') <script src="{{asset('layouts/common/jquery.js')}}"></script> <img src="{{$ticket_img}}" alt="" width="200px"> <script language="javascript" type="text/javascript"> $(document).ready(function(e) { getRemote(); }); function getRemote () { $.getJSON("{{url('check_auth/?key='.$logkey)}}", function (data) { console.log(data); // console.log(result); if(data===1){ location.href ="{{url('user/profile')}}"; } }) setTimeout(getRemote,2000); } </script> @endsection