微信網頁授權demo2


1、在微信公眾號請求用戶網頁授權之前,開發者需要先到公眾平台官網中的“開發 - 接口權限 - 網頁服務 - 網頁帳號 - 網頁授權獲取用戶基本信息”的配置選項中,修改授權回調域名。請注意,這里填寫的是域名(是一個字符串),而不是URL,因此請勿加 http:// 等協議頭; 比如需要網頁授權的域名為:www.qq.com,配置以后此域名下面的頁面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以進行OAuth2.0鑒權。但http://pay.qq.com 、 http://music.qq.com 、 http://qq.com無法進行OAuth2.0鑒權 (就是不能用)

2、關於網頁授權access_token和普通access_token的區別:我理解的就是 網頁授權的access_token沒什么特別的限制(雖然貌似也是2小時有效期)。大家隨便無限制用;但是除此之外用到的access_token是有限制的。真的是有效期2小時,而且每天有獲取access_token的限制次數。

因為有限制次數,所以我在做的時候是把獲取到的access_token保存在某個文件里,設置7000(小於一點點官方的2小時)秒過期,下次我再去獲取access_token的時候看這個設置的過期時間有沒有到。如果沒到。就直接獲取access_token值直接用。如果過期了,那么再次去獲取下。再次保存到這個文件里去;

另外普通過的access_token 是一個全局的共用的值,什么意思呢,比如你倆個模塊都用到了access_token 但是你 倆個模塊都單獨存了一份access_token的文件。那么恭喜你,你中招了。因為 每次用戶獲取一次access_token的時候微信的服務器是緩存記錄了最新access_token的最新值。比如你A模塊獲取更新了一次access_token,緊接着B模塊也獲取更新了一次access_token。那么,此時微信服務器緩存記錄的是B模塊獲取的access_token值,再接着A模塊去獲取一次access_token。因為是緊接着嘛,那么倆小時肯定沒到啊,也就是沒過期啊,那么自動從access_token保存文件里獲取值,可是實際此時微信服務器里緩存的access_token值 是B模塊最新更新的值啊,那你繼續進行你當前模塊下涉及到access_token的運算,肯定是要提示access_token錯誤的(跟服務器的不一致啊);

所以普通的access_token 一定要放在一個公共的,所有模塊都調用的同一個地方。這樣就避免了上面的錯誤;

 

好了,下面進入正題。先介紹下微信網頁授權的基本流程;

1.你進入到某個頁面,這個頁面先判斷地址url里有沒有code參數;如果有code參數直接調用請求以下鏈接獲取access_token:  https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code 可以獲取到

直接就可以獲取到openid的值。 也就是完成了網頁授權的基本流程,剩下你自己程序的操作了。

2.如果這個頁面沒有code參數,那么先組裝url到那個讓用戶點擊授權的頁面,

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect ;跳轉到這個url去,得到下圖

用戶點擊確認登錄之后。頁面自動貨跳轉到  redirect_uri/?code=CODE&state=STATE。這個頁面(redirect_uri是上面你自己設置url頁面,默認就是用戶剛開始進入第一個頁面的url)。

此時,等於又一次進入到當前頁面了。默認會執行第一步判斷操作(此時url獲取的code的值),完成授權基本流程。

getOpenId.php 代碼如下

<?php
require_once "./lib/WxPay.JsApiPay.php";

$tools = new JsApiPay();
$openId = $tools->GetOpenid();
echo $openId;
?>

WxPay.Config.php代碼如下

<?php
/**
* 	配置賬號信息
*/

class WxPayConfig
{
	//=======【基本信息設置】=====================================
	//
	/**
	 * TODO: 修改這里配置為您自己申請的商戶信息
	 * 微信公眾號信息配置
	 * 
	 * APPID:綁定支付的APPID(必須配置,開戶郵件中可查看)
	 * 
	 * MCHID:商戶號(必須配置,開戶郵件中可查看)
	 * 
	 * KEY:商戶支付密鑰,參考開戶郵件設置(必須配置,登錄商戶平台自行設置)
	 * 設置地址:https://pay.weixin.qq.com/index.php/account/api_cert
	 * 
	 * APPSECRET:公眾帳號secert(僅JSAPI支付的時候需要配置, 登錄公眾平台,進入開發者中心可設置),
	 * 獲取地址:https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=2005451881&lang=zh_CN
	 * @var string
	 */
	const APPID = '123123213213';
	const MCHID = '123123123123123123';
	const KEY = '13123123123213';
	const APPSECRET = '123123213213213123213123';
	//=======【證書路徑設置】=====================================
	/**
	 * TODO:設置商戶證書路徑
	 * 證書路徑,注意應該填寫絕對路徑(僅退款、撤銷訂單時需要,可登錄商戶平台下載,
	 * API證書下載地址:https://pay.weixin.qq.com/index.php/account/api_cert,下載之前需要安裝商戶操作證書)
	 * @var path
	 */
	const SSLCERT_PATH = '../xxxx/apiclient_cert.pem';
	const SSLKEY_PATH = '../xxxx/apiclient_key.pem';
	
	//=======【curl代理設置】===================================
	/**
	 * TODO:這里設置代理機器,只有需要代理的時候才設置,不需要代理,請設置為0.0.0.0和0
	 * 本例程通過curl使用HTTP POST方法,此處可修改代理服務器,
	 * 默認CURL_PROXY_HOST=0.0.0.0和CURL_PROXY_PORT=0,此時不開啟代理(如有需要才設置)
	 * @var unknown_type
	 */
	const CURL_PROXY_HOST = "0.0.0.0";//"10.152.18.220";
	const CURL_PROXY_PORT = 0;//8080;
	
	//=======【上報信息配置】===================================
	/**
	 * TODO:接口調用上報等級,默認緊錯誤上報(注意:上報超時間為【1s】,上報無論成敗【永不拋出異常】,
	 * 不會影響接口調用流程),開啟上報之后,方便微信監控請求調用的質量,建議至少
	 * 開啟錯誤上報。
	 * 上報等級,0.關閉上報; 1.僅錯誤出錯上報; 2.全量上報
	 * @var int
	 */
	const REPORT_LEVENL = 1;
}

WxPay.JsApiPay.php代碼如下

<?php
require_once "WxPay.Config.php";
/**
 * 
 * JSAPI支付實現類
 * 該類實現了從微信公眾平台獲取code、通過code獲取openid和access_token、
 * 生成jsapi支付js接口所需的參數、生成獲取共享收貨地址所需的參數
 * 
 * 該類是微信支付提供的樣例程序,商戶可根據自己的需求修改,或者使用lib中的api自行開發
 * 
 * @author widy
 *
 */
class JsApiPay
{
	/**
	 * 
	 * 網頁授權接口微信服務器返回的數據,返回樣例如下
	 * {
	 *  "access_token":"ACCESS_TOKEN",
	 *  "expires_in":7200,
	 *  "refresh_token":"REFRESH_TOKEN",
	 *  "openid":"OPENID",
	 *  "scope":"SCOPE",
	 *  "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
	 * }
	 * 其中access_token可用於獲取共享收貨地址
	 * openid是微信支付jsapi支付接口必須的參數
	 * @var array
	 */
	public $data = null;
	
	/**
	 * 
	 * 通過跳轉獲取用戶的openid,跳轉流程如下:
	 * 1、設置自己需要調回的url及其其他參數,跳轉到微信服務器https://open.weixin.qq.com/connect/oauth2/authorize
	 * 2、微信服務處理完成之后會跳轉回用戶redirect_uri地址,此時會帶上一些參數,如:code
	 * 
	 * @return 用戶的openid
	 */
	public function GetOpenid()
	{
		//通過code獲得openid
		if (!isset($_GET['code'])){
			//觸發微信返回code碼
			$url = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].$_SERVER['QUERY_STRING'];
			$baseUrl = rtrim($url, '/');
			$baseUrl = urlencode($baseUrl);
			$url = $this->__CreateOauthUrlForCode($baseUrl);
			Header("Location: $url");
			exit();
		} else {
			//獲取code碼,以獲取openid
		    $code = $_GET['code'];
			$openid = $this->getOpenidFromMp($code);
			return $openid;
		}
	}
	
	/**
	 * 
	 * 獲取jsapi支付的參數
	 * @param array $UnifiedOrderResult 統一支付接口返回的數據
	 * @throws WxPayException
	 * 
	 * @return json數據,可直接填入js函數作為參數
	 */
	public function GetJsApiParameters($UnifiedOrderResult)
	{
		if(!array_key_exists("appid", $UnifiedOrderResult)
		|| !array_key_exists("prepay_id", $UnifiedOrderResult)
		|| $UnifiedOrderResult['prepay_id'] == "")
		{
			throw new WxPayException("參數錯誤");
		}
		$jsapi = new WxPayJsApiPay();
		$jsapi->SetAppid($UnifiedOrderResult["appid"]);
		$timeStamp = time();
		$jsapi->SetTimeStamp("$timeStamp");
		$jsapi->SetNonceStr(WxPayApi::getNonceStr());
		$jsapi->SetPackage("prepay_id=" . $UnifiedOrderResult['prepay_id']);
		$jsapi->SetSignType("MD5");
		$jsapi->SetPaySign($jsapi->MakeSign());
		$parameters = json_encode($jsapi->GetValues());
		return $parameters;
	}
	
	/**
	 * 
	 * 通過code從工作平台獲取openid機器access_token
	 * @param string $code 微信跳轉回來帶上的code
	 * 
	 * @return openid
	 */
	public function GetOpenidFromMp($code)
	{
		$url = $this->__CreateOauthUrlForOpenid($code);
		//初始化curl
		$ch = curl_init();
		//設置超時
		// curl_setopt($ch, CURLOPT_TIMEOUT, $this->curl_timeout);
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,FALSE);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST,FALSE);
		curl_setopt($ch, CURLOPT_HEADER, FALSE);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
		if(WxPayConfig::CURL_PROXY_HOST != "0.0.0.0" 
			&& WxPayConfig::CURL_PROXY_PORT != 0){
			curl_setopt($ch,CURLOPT_PROXY, WxPayConfig::CURL_PROXY_HOST);
			curl_setopt($ch,CURLOPT_PROXYPORT, WxPayConfig::CURL_PROXY_PORT);
		}
		//運行curl,結果以jason形式返回
		$res = curl_exec($ch);
		curl_close($ch);
		//取出openid
		$data = json_decode($res,true);
		$this->data = $data;
		$openid = $data['openid'];
		return $openid;
	}
	
	/**
	 * 
	 * 拼接簽名字符串
	 * @param array $urlObj
	 * 
	 * @return 返回已經拼接好的字符串
	 */
	private function ToUrlParams($urlObj)
	{
		$buff = "";
		foreach ($urlObj as $k => $v)
		{
			if($k != "sign"){
				$buff .= $k . "=" . $v . "&";
			}
		}
		
		$buff = trim($buff, "&");
		return $buff;
	}
	
	/**
	 * 
	 * 獲取地址js參數
	 * 
	 * @return 獲取共享收貨地址js函數需要的參數,json格式可以直接做參數使用
	 */
	public function GetEditAddressParameters()
	{	
		$getData = $this->data;
		$data = array();
		$data["appid"] = WxPayConfig::APPID;
		$data["url"] = "http://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
		$time = time();
		$data["timestamp"] = "$time";
		$data["noncestr"] = "1234568";
		$data["accesstoken"] = $getData["access_token"];
		ksort($data);
		$params = $this->ToUrlParams($data);
		$addrSign = sha1($params);
		
		$afterData = array(
			"addrSign" => $addrSign,
			"signType" => "sha1",
			"scope" => "jsapi_address",
			"appId" => WxPayConfig::APPID,
			"timeStamp" => $data["timestamp"],
			"nonceStr" => $data["noncestr"]
		);
		$parameters = json_encode($afterData);
		return $parameters;
	}
	
	/**
	 * 
	 * 構造獲取code的url連接
	 * @param string $redirectUrl 微信服務器回跳的url,需要url編碼
	 * 
	 * @return 返回構造好的url
	 */
	private function __CreateOauthUrlForCode($redirectUrl)
	{
		$urlObj["appid"] = WxPayConfig::APPID;
		$urlObj["redirect_uri"] = "$redirectUrl";
		$urlObj["response_type"] = "code";
		$urlObj["scope"] = "snsapi_base";
		$urlObj["state"] = "STATE"."#wechat_redirect";
		$bizString = $this->ToUrlParams($urlObj);
		return "https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString;
	}
	
	/**
	 * 
	 * 構造獲取open和access_toke的url地址
	 * @param string $code,微信跳轉帶回的code
	 * 
	 * @return 請求的url
	 */
	private function __CreateOauthUrlForOpenid($code)
	{
		$urlObj["appid"] = WxPayConfig::APPID;
		$urlObj["secret"] = WxPayConfig::APPSECRET;
		$urlObj["code"] = $code;
		$urlObj["grant_type"] = "authorization_code";
		$bizString = $this->ToUrlParams($urlObj);
		return "https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString;
	}
}

  

注意code只能用一次的。如果你第一次頁面獲取到openid了,你刷新這個頁面。就會報錯。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM