相信从事微信开发的小伙伴们遇到过这样的情况,就是甲方的微信公众帐号的网页授权指定域名指向了其它的域名(以后叫A),并在该域名下实现了一部分功能。现在,需要开发另一个功能,且该功能所在的域名(以后叫B)不再网页授权指定域名下。 怎么办呢?造成网页授权域名的冲突了。
解决方案:
需要获取用户信息的时候我们完全可以让用户跳转到A方完成授权,授权完成后带着关键参数回传给B。然后B获取关键参数,请求微信生成用户相关信息。
思路有了,怎么实现呢?
1、首先,我们需要A给我们提供一个接口,该接口的调用必须要2个参数
@param String token 签名机制,目的防止用户授权泄漏,被其它人调用了这个接口。
@param String retUrl 回调地址,完成授权后让用户post回跳到这个地址(retUrl 最好做一个urlencode转义),当然post中也包含着一些关键的数据(code)
2、用户回传的code 数据后,我们可以根据这个code 获得用户的数据了(详情见微信网页授权,也就是通过code 获取临时授权签名 access_token 在通过access_token 获得 用户信息)
是不是很简单,现在我演示一下demo。
为方便时间我用php代码做演示。
A、B都需要依赖的类auth.php
<?php
class Wxuserapi {
/*以下内容请填写*/
private $app_id = '';
private $app_secret = '';
/*配置信息*/
public function __construct($appid,$appsecret){
$this->app_id = $appid;
$this->app_secret = $appsecret;
}
/**
* 获取微信授权链接
*
* @param string $redirect_uri 跳转地址
* @param mixed $state 参数
*/
public function get_authorize_url($redirect_uri = '', $state = '')
{
$redirect_uri = urlencode($redirect_uri);
$url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->app_id}&redirect_uri={$redirect_uri}&response_type=code&scope=snsapi_userinfo&state={$state}#wechat_redirect";
echo "<script language='javascript' type='text/javascript'>";
echo "window.location.href='$url'";
echo "</script>";
}
/**
* 获取授权token
*
* @param string $code 通过get_authorize_url获取到的code
*/
public function get_access_token($code = '')
{
$token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$this->app_id}&secret={$this->app_secret}&code={$code}&grant_type=authorization_code";
$token_data = $this->http($token_url);
if(!empty($token_data[0]))
{
return json_decode($token_data[0], TRUE);
}
return FALSE;
}
/**
* 获取授权后的微信用户信息
*
* @param string $access_token
* @param string $open_id
*/
public function get_user_info($access_token = '', $open_id = '')
{
if($access_token && $open_id)
{
$access_url = "https://api.weixin.qq.com/sns/auth?access_token={$access_token}&openid={$open_id}";
$access_data = $this->http($access_url);
$access_info = json_decode($access_data[0], TRUE);
if($access_info['errmsg']!='ok'){
exit('页面过期');
}
$info_url = "https://api.weixin.qq.com/sns/userinfo?access_token={$access_token}&openid={$open_id}&lang=zh_CN";
$info_data = $this->http($info_url);
if(!empty($info_data[0]))
{
return json_decode($info_data[0], TRUE);
}
}
return FALSE;
}
/**
* Http方法
*
*/
public function http($url)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_HEADER, false);
$output = curl_exec($ch);//输出内容
curl_close($ch);
return array($output);
}
}
?>
A、B 需要依赖的函数库 common.php
/**
* 获取当前完整url
* @return
* String 当前地址
*/
function getMyUrl()
{
if($_SERVER['QUERY_STRING'])
{
return 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'];
}else{
return 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];
}
}
/***token 签名机制 我不写,每个人都有自己的算法,我就不献丑了***/
/**
* token 签名生成
* @return
* String token
*/
function getToken()
{
}
/**
* token 验证
* @param
* String token 需要验证的token
* @return
* boolean
*/
function checkToken($token)
{
}
域名A 要做的工作
<?php
session_start();
require("./auth.php");
require("./common.php");
if(isset($_GET['urlcode']))
{
$_SESSION['urlcode'] = $_GET['urlcode'];
//token 验证机制
if(isset($_GET['token']))
{
if(!checkToken(trim($_GET['token'])))
{
//签名错误处理
header("content-type:text/html;charset=utf-8");
echo "token error";
exit;
}
}
}
//必填项,参数可以在微信后台中找到
$config = array(
'appid' => '', //公众号appid
'appsecret' => '' //公众号appsecret
);
$auth = new \Wxuserapi($config['appid'],$config['appsecret']);
if(isset($_GET['code'])){
$code = $_GET['code'];
}else{
$url = getMyUrl();
$auth->get_authorize_url($url,"snsapi_userinfo");
exit;
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<form action="<?php echo urldecode($_SESSION['urlcode']); ?>" name="form1" method="post">
<input type="hidden" name="code" value="<?php echo $code; ?>" />
</form>
</body>
<script>
window.onload = function(){
document.form1.submit();
}
</script>
</html>
域名B 要做的工作
<?php
session_start();
require("./auth.php");
require("./common.php");
$code = isset($_POST['code']) ? $_POST['code'] : false;
//不存在code 时回调到域名A 指定接口地址
if(!$code)
{
$retUrl = urlencode(getMyUrl());
$token = getToken();
//假设我们域名A 提供的接口地址是 http://www.xxx.com/auth.php
$url = "http://www.xxx.com/auth.php?urlcode={$retUrl}&token={$token}";
header("location:{$url}");
exit;
}
//必填项,参数可以在微信后台中找到
$config = array(
'appid' => '', //公众号appid
'appsecret' => '' //公众号appsecret
);
$auth = new \Wxuserapi($config['appid'],$config['appsecret']);
$access = $auth->get_access_token($code);
$userinfo = $auth->get_user_info($access['access_token'],$access['openid']);
var_dump($userinfo);