저는 최근 WeChat 인터페이스를 개발하고 있으므로 WeChat 로그인을 승인하고 사용자 정보를 얻기 위한 이 인터페이스의 개발 프로세스를 요약하겠습니다.
1. 먼저, WeChat 공개 계정은 해당 AppID와 AppSecret을 받아야 합니다. WeChat 로그인을 신청하고 검토를 통과한 후에만 액세스 프로세스를 시작할 수 있습니다.
2. 승인 프로세스
1. 프로세스 설명
(1) 제3자가 WeChat 승인 로그인 요청을 시작한 후 WeChat 사용자가 승인을 허용합니다. 타사 애플리케이션 중 WeChat은 애플리케이션을 실행하거나 타사 웹사이트로 리디렉션하고 인증 임시 티켓 코드 매개변수를 가져옵니다.
(2). , 등을 통해 API를 통해 access_token;
(3)을 통해 사용자의 기본 데이터 리소스를 얻거나 사용자가 기본을 구현하도록 돕습니다. 운영.
2. access_token 시퀀스 다이어그램을 얻습니다:
3. 개발(저는 CI 프레임워크를 사용합니다. 사실 모든 프레임워크는 동일합니다. MVC 모드가 됩니다)
1. 코드 요청
weixin.php
<?php class weixinController extends CI_Controller { public $userInfo; public $wxId; public function __construct(){ parent::__construct(); //只要用户一访问此模块,就登录授权,获取用户信息 $this->userInfo = $this->getWxUserInfo(); } /** * 确保当前用户是在微信中打开,并且获取用户信息 * * @param string $url 获取到微信授权临时票据(code)回调页面的URL */ private function getWxUserInfo($url = '') { //微信标记(自己创建的) $wxSign = $this->input->cookie('wxSign'); //先看看本地cookie里是否存在微信唯一标记, //假如存在,可以通过$wxSign到redis里取出微信个人信息(因为在第一次取到微信个人信息,我会将其保存一份到redis服务器里缓存着) if (!empty($wxSign)) { //如果存在,则从Redis里取出缓存了的数据 $userInfo = $this->model->redisCache->getData("weixin:sign_{$wxSign}"); if (!empty($userInfo)) { //获取用户的openid $this->wxId = $userInfo['openid']; //将其存在cookie里 $this->input->set_cookie('wxId', $this->wxId, 60*60*24*7); return $userInfo; } } //获取授权临时票据(code) $code = $_GET['code']; if (empty($code)) { if (empty($url)) { $url = rtirm($_SERVER['QUERY_STRING'], '/'); //到WxModel.php里获取到微信授权请求URL,然后redirect请求url redirect($this->model->wx->getOAuthUrl(baseUrl($url))); } } } } ?>
컨트롤러 코드 가져오기
Wxmodel.php
<?php class WxModel extends ModelBase{ public $appId; public $appSecret; public $token; public function __construct() { parent::__construct(); //审核通过的移动应用所给的AppID和AppSecret $this->appId = 'wx0000000000000000'; $this->appSecret = '00000000000000000000000000000'; $this->token = '00000000'; } /** * 获取微信授权url * @param string 授权后跳转的URL * @param bool 是否只获取openid,true时,不会弹出授权页面,但只能获取用户的openid,而false时,弹出授权页面,可以通过openid获取用户信息 * */ public function getOAuthUrl($redirectUrl, $openIdOnly, $state = '') { $redirectUrl = urlencode($redirectUrl); $scope = $openIdOnly ? 'snsapi_base' : 'snsapi_userinfo'; $oAuthUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appId}&redirect_uri={$redirectUrl}&response_type=code&scope=$scope&state=$state"; return $oAuthUrl; } 获取code的Model代码
코드의 모델 코드 가져오기
여기 첨부된 내용은 요청 매개변수 설명과 반환 값 설명입니다
요청 매개변수 설명:
응답 반환값 설명:
요청이 성공하면 요청 매개변수의 Redirect_uri 값으로 리디렉션됩니다. 실제로 weixin.php의 $this->userInfo = $this->getWxUserInfo(); 라인으로 반환됩니다. 그런 다음 getWxUserInfo()를 다시 입력합니다. 이 때
//获取授权临时票据(code) $code = $_GET['code'];
줄에서도 코드 값을 가져올 수 있습니다. 그런 다음 두 번째 단계로 진행합니다.
2. 코드를 통해 access_token 가져오기
weixin.php
userInfo = $this->getWxUserInfo(); } /** * 确保当前用户是在微信中打开,并且获取用户信息 * * @param string $url 获取到微信授权临时票据(code)回调页面的URL */ private function getWxUserInfo($url = '') { //微信标记(自己创建的) $wxSign = $this->input->cookie('wxSign'); //先看看本地cookie里是否存在微信唯一标记, //假如存在,可以通过$wxSign到redis里取出微信个人信息(因为在第一次取到微信个人信息,我会将其保存一份到redis服务器里缓存着) if (!empty($wxSign)) { //如果存在,则从Redis里取出缓存了的数据 $userInfo = $this->model->redisCache->getData("weixin:sign_{$wxSign}"); if (!empty($userInfo)) { //获取用户的openid $this->wxId = $userInfo['openid']; //将其存在cookie里 $this->input->set_cookie('wxId', $this->wxId, 60*60*24*7); return $userInfo; } } //获取授权临时票据(code) $code = $_GET['code']; if (empty($code)) { if (empty($url)) { $url = rtirm($_SERVER['QUERY_STRING'], '/'); //到WxModel.php里获取到微信授权请求URL,然后redirect请求url redirect($this->model->wx->getOAuthUrl(baseUrl($url))); } } /***************这里开始第二步:通过code获取access_token****************/ $result = $this->model->wx->getOauthAccessToken($code); //如果发生错误 if (isset($result['errcode'])) { return array('msg'=>'授权失败,请联系客服','result'=>$result); } //到这一步就说明已经取到了access_token $this->wxId = $result['openid']; $accessToken = $result['access_token']; $openId = $result['openid']; //将openid和accesstoken存入cookie中 $this->input->set_cookie('wx_id', $this->wxId, 60*60*24*7); $this->input->set_cookie('access_token', $accessToken); 获取access_token的控制器代码
access_token 컨트롤러 코드 가져오기
WxModel.php
<?php class WxModel extends ModelBase{ public $appId; public $appSecret; public $token; public function __construct() { parent::__construct(); //审核通过的移动应用所给的AppID和AppSecret $this->appId = 'wx0000000000000000'; $this->appSecret = '00000000000000000000000000000'; $this->token = '00000000'; } /** * 获取微信授权url * @param string 授权后跳转的URL * @param bool 是否只获取openid,true时,不会弹出授权页面,但只能获取用户的openid,而false时,弹出授权页面,可以通过openid获取用户信息 * */ public function getOAuthUrl($redirectUrl, $openIdOnly, $state = '') { $redirectUrl = urlencode($redirectUrl); $scope = $openIdOnly ? 'snsapi_base' : 'snsapi_userinfo'; $oAuthUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appId}&redirect_uri={$redirectUrl}&response_type=code&scope=$scope&state=$state#wechat_redirect"; return $oAuthUrl; } /** * 获取access_token */ public function getoAuthAccessToken($code) { return json_decode(file_get_contents("https://api.weixin.qq.com/sns/oauth2/access_token?appid={$this->AppId}&secret={$this->AppSecret}&code={$authCode}&grant_type=authorization_code",true); } 获取access_token的Model代码
access_token의 모델 코드 가져오기
여기에 매개변수 설명이 첨부되어 있습니다
매개변수 설명 요청:
응답 반환 값 설명:
오류가 반환되면 다음과 같습니다.
3. access_token을 통해 인터페이스 호출(사용자 정보 획득)
access_token을 얻은 후 다음 전제 조건으로 인터페이스 호출을 수행합니다.
(1) access_tokec이 유효하고 시간 초과되지 않았습니다.
(2) WeChat 사용자가 타사 애플리케이션 계정의 해당 인터페이스 범위(범위)를 승인했습니다.
다음은 사용자 정보를 얻는 코드
weixin.php
userInfo = $this->getWxUserInfo(); } /** * 确保当前用户是在微信中打开,并且获取用户信息 * * @param string $url 获取到微信授权临时票据(code)回调页面的URL */ private function getWxUserInfo($url = '') { //微信标记(自己创建的) $wxSign = $this->input->cookie('wxSign'); //先看看本地cookie里是否存在微信唯一标记, //假如存在,可以通过$wxSign到redis里取出微信个人信息(因为在第一次取到微信个人信息,我会将其保存一份到redis服务器里缓存着) if (!empty($wxSign)) { //如果存在,则从Redis里取出缓存了的数据 $userInfo = $this->model->redisCache->getData("weixin:sign_{$wxSign}"); if (!empty($userInfo)) { //获取用户的openid $this->wxId = $userInfo['openid']; //将其存在cookie里 $this->input->set_cookie('wxId', $this->wxId, 60*60*24*7); return $userInfo; } } //获取授权临时票据(code) $code = $_GET['code']; if (empty($code)) { if (empty($url)) { $url = rtirm($_SERVER['QUERY_STRING'], '/'); //到WxModel.php里获取到微信授权请求URL,然后redirect请求url redirect($this->model->wx->getOAuthUrl(baseUrl($url))); } } /***************这里开始第二步:通过code获取access_token****************/ $result = $this->model->wx->getOauthAccessToken($code); //如果发生错误 if (isset($result['errcode'])) { return array('msg'=>'授权失败,请联系客服','result'=>$result); } //到这一步就说明已经取到了access_token $this->wxId = $result['openid']; $accessToken = $result['access_token']; $openId = $result['openid']; //将openid和accesstoken存入cookie中 $this->input->set_cookie('wx_id', $this->wxId, 60*60*24*7); $this->input->set_cookie('access_token', $accessToken); /*******************这里开始第三步:通过access_token调用接口,取出用户信息***********************/ $this->userInfo = $this->model->wx->getUserInfo($openId, $accessToken); //自定义微信唯一标识符 $wxSign =substr(md5($this->wxId.'k2a5dd'), 8, 16); //将其存到cookie里 $this->input->set_cookie('wxSign', $wxSign, 60*60*24*7); //将个人信息缓存到redis里 $this->library->redisCache->set("weixin:sign_{$wxSign}", $userInfo, 60*60*24*7); return $userInfo; } } ?> 获取用户信息的Controller
사용자 정보를 얻는 컨트롤러
WxModel.php
<?php class WxModel extends ModelBase{ public $appId; public $appSecret; public $token; public function __construct() { parent::__construct(); //审核通过的移动应用所给的AppID和AppSecret $this->appId = 'wx0000000000000000'; $this->appSecret = '00000000000000000000000000000'; $this->token = '00000000'; } /** * 获取微信授权url * @param string 授权后跳转的URL * @param bool 是否只获取openid,true时,不会弹出授权页面,但只能获取用户的openid,而false时,弹出授权页面,可以通过openid获取用户信息 * */ public function getOAuthUrl($redirectUrl, $openIdOnly, $state = '') { $redirectUrl = urlencode($redirectUrl); $scope = $openIdOnly ? 'snsapi_base' : 'snsapi_userinfo'; $oAuthUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appId}&redirect_uri={$redirectUrl}&response_type=code&scope=$scope&state=$state#wechat_redirect"; return $oAuthUrl; } /** * 获取access_token */ public function getoAuthAccessToken($code) { return json_decode(file_get_contents("https://api.weixin.qq.com/sns/oauth2/access_token?appid={$this->AppId}&secret={$this->AppSecret}&code={$authCode}&grant_type=authorization_code",true); } /** * 获取用户信息 */ public function getUserInfo($openId, $accessToken) { $url = 'https://api.weixin.qq.com/sns/userinfo'; //获取用户微信账号信息 $userInfo = $this->callApi("$url?access_token=$accessToken&openid=$openId&lang=zh-CN"); if ($userInfo['errcode']) { return array('msg'=>'获取用户信息失败,请联系客服', $userInfo); } $userInfo['wx_id'] = $openId; return $userInfo; } /** * 发起Api请求,并获取返回结果 * @param string 请求URL * @param mixed 请求参数 (array|string) * @param string 请求类型 (GET|POST) * @return array */ public function callApi($apiUrl, $param = array(), $method = 'GET') { $result = curl_request_json($error, $apiUrl, $params, $method); //假如返回的数组有错误码,或者变量$error也有值 if (!empty($result['errcode'])) { $errorCode = $result['errcode']; $errorMsg = $result['errmsg']; } else if ($error != false) { $errorCode = $error['errorCode']; $errorMsg = $error['errorMessage']; } if (isset($errorCode)) { //将其插入日志文件 file_put_contents("/data/error.log", "callApi:url=$apiUrl,error=[$errorCode]$errorMsg"); if ($errorCode === 40001) { //尝试更正access_token后重试 try { $pos = strpos(strtolower($url), 'access_token='); if ($pos !==false ) { $pos += strlen('access_token='); $pos2 = strpos($apiUrl, '&' ,$pos); $accessTokened = substr($apiUrl, $pos, $pos2 === false ? null : ($pos2 - $pos)); return $this->callApi(str_replace($accessTokened, $this->_getApiToken(true), $apiUrl), $param, $method); } }catch (WeixinException $e) { } } //这里抛出异常,具有的就不详说了 throw new WeixinException($errorMessage, $errorCode); } return $result; } /** * 获取微信 api 的 access_token 。 不同于 OAuth 中的 access_token ,参见 http://mp.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96access_token * * @param bool 是否强制刷新 accessToken */ private function _getApiToken($forceRefresh = false) { //先查看一下redis里是否已经缓存过access_token $accessToken = $this->library->redisCache->get('Weixin:AccessToken'); if($forceRefresh || empty($accessToken)) { $result = $this->callApi("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->appId}&secret={$this->appSecret}"); $accessToken = $result['access_token']; $expire = max(1, intval($result['expires_in']) - 60); //将access_token缓存到redis里去 $this->library->redisCache->set('Weixin:AccessToken', $accessToken, $expire); } return $accessToken; } ?>
사용자 정보를 가져오는 모델
Common.php
<?php /** * 发起一个HTTP(S)请求,并返回json格式的响应数据 * @param array 错误信息 array($errorCode, $errorMessage) * @param string 请求Url * @param array 请求参数 * @param string 请求类型(GET|POST) * @param int 超时时间 * @param array 额外配置 * * @return array */ public function curl_request_json(&$error, $url, $param = array(), $method = 'GET', $timeout = 10, $exOptions = null) { $error = false; $responseText = curl_request_text($error, $url, $param, $method, $timeout, $exOptions); $response = null; if ($error == false && $responseText > 0) { $response = json_decode($responseText, true); if ($response == null) { $error = array('errorCode'=>-1, 'errorMessage'=>'json decode fail', 'responseText'=>$responseText); //将错误信息记录日志文件里 $logText = "json decode fail : $url"; if (!empty($param)) { $logText .= ", param=".json_encode($param); } $logText .= ", responseText=$responseText"; file_put_contents("/data/error.log", $logText); } } return $response; } /** * 发起一个HTTP(S)请求,并返回响应文本 * @param array 错误信息 array($errorCode, $errorMessage) * @param string 请求Url * @param array 请求参数 * @param string 请求类型(GET|POST) * @param int 超时时间 * @param array 额外配置 * * @return string */ public function curl_request_text(&$error, $url, $param = array(), $method = 'GET', $timeout = 15, $exOptions = NULL) { //判断是否开启了curl扩展 if (!function_exists('curl_init')) exit('please open this curl extension'); //将请求方法变大写 $method = strtoupper($method); $ch = curl_init(); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_HEADER, false); if (isset($_SERVER['HTTP_USER_AGENT'])) curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); if (isset($_SERVER['HTTP_REFERER'])) curl_setopt($ch, CURLOPT_REFERER, $_SERVER['HTTP_REFERER']); curl_setopt($ch, CURLOPT_AUTOREFERER, 1); switch ($method) { case 'POST': curl_setopt($ch, CURLOPT_POST, true); if (!empty($param)) { curl_setopt($ch, CURLOPT_POSTFIELDS, (is_array($param)) ? http_build_query($param) : $param); } break; case 'GET': case 'DELETE': if ($method == 'DELETE') { curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE'); } if (!empty($param)) { $url = $url.(strpos($url, '?') ? '&' : '?').(is_array($param) ? http_build_query($param) : $param); } break; } curl_setopt($ch, CURLINFO_HEADER_OUT, true); curl_setopt($ch, CURLOPT_URL, $url); //设置额外配置 if (!empty($exOptions)) { foreach ($exOptions as $k => $v) { curl_setopt($ch, $k, $v); } } $response = curl_exec($ch); $error = false; //看是否有报错 $errorCode = curl_errno($ch); if ($errorCode) { $errorMessage = curl_error($ch); $error = array('errorCode'=>$errorCode, 'errorMessage'=>$errorMessage); //将报错写入日志文件里 $logText = "$method $url: [$errorCode]$errorMessage"; if (!empty($param)) $logText .= ",$param".json_encode($param); file_put_contents('/data/error.log', $logText); } curl_close($ch); return $response; } ?>
사용자 정보를 가져오는 사용자 정의 기능
위의 세 단계에 걸쳐 인터페이스를 호출하면 사용자의 위챗 계정 정보를 얻을 수 있습니다.
코드를 자세히 보시면 이해하기 쉽도록 여러 곳에 주석을 달았습니다. 배우고 싶은 친구들이 자세히 살펴 볼 수 있기를 바랍니다.
WeChat 인증 로그인 및 사용자 정보 인터페이스 접근과 관련된 더 많은 기사를 보려면 PHP 중국어 웹사이트를 주목하세요!