ThinkPHP5集成JS-SDK實現微信自定義分享功能


最近開發一個項目,需要將鏈接分享給好友時能夠自定義標題、簡介和logo,現將ThinkPHP5集成JS-SDK實現微信自定義分享功能的過程整理成文。

一、准備工作

1、認證的公眾號
不管是訂閱號還是服務號,都需要是經過認證的,否者不支持微信分享功能。
2、綁定域名
登錄微信公眾平台,設置—公眾號設置—功能設置里,填寫『JS接口安全域名』。
填寫的域名須通過ICP備案的驗證,並將平台給的txt文件放到域名指向的web服務器之下。
3、獲取開發者ID和開發者密碼
登錄微信公眾平台,開發—基本配置,即可看到AppID和AppSecret(若沒有需要開啟)。
4、下載官方示例代碼
可在http://demo.open.weixin.qq.com/jssdk/sample.zip下載包含php、java、nodejs以及python的示例代碼,其中php文件夾包含如下文件:
二、正式開發
1、PHP部分
1)將下載的php示例代碼中的access_token.php、jsapi_ticket.php和jssdk.php放入到tp5框架的第三方接口擴展目錄下,路徑為extend/org/wechat/文件。
2)將jssdk.php文件重命名為Jssdk.php文件,設置命名空間,因為tp路由的關系,需要加上私有屬性path,並在構造函數中設置 $this->path = __DIR__ . DS; 
同時將get_php_file函數返回值中的$filename改為 $this->path . $filename ,否則會報錯。
3)在config.php文件中,將先前獲得的AppID和AppSecret配置好。
4)在application/index/controller下新建Wechat.php文件,內容如下:
2、JS部分
1)引入JS文件
在需要調用JS接口的頁面引入JS文件(支持https):
<script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>

2)調用JS接口

官方技術文檔給了如下說明:

// 通過config接口注入權限驗證配置
wx.config({ debug: true, // 開啟調試模式,調用的所有api的返回值會在客戶端alert出來,若要查看傳入的參數,可以在pc端打開,參數信息會通過log打出,僅在pc端時才會打印。
    appId: '',   // 必填,公眾號的唯一標識
    timestamp: , // 必填,生成簽名的時間戳
    nonceStr: '', // 必填,生成簽名的隨機串
    signature: '',// 必填,簽名
    jsApiList: [] // 必填,需要使用的JS接口列表
}); // 通過ready接口處理成功驗證
wx.ready(function(){ // config信息驗證后會執行ready方法,所有接口調用都必須在config接口獲得結果之后,config是一個客戶端的異步操作,所以如果需要在頁面加載時就調用相關接口,則須把相關接口放在ready函數中調用來確保正確執行。
    // 對於用戶觸發時才調用的接口,則可以直接調用,不需要放在ready函數中。
});

代碼如下:

至此就完成微信分享功能的開發了。

三、問題及解決方法
在開發過程中先后遇到了兩次invalid signature簽名錯誤,一次是分享首頁成功,但是分享二級頁面失敗;一次是分享過的頁面再次分享時會失敗。
官方技術文檔給了如下說明:
確保你獲取用來簽名的url是動態獲取的。
如果是html的靜態頁面在前端通過ajax將url傳到后台簽名,前端需要用js獲取當前頁面除去'#'hash部分的鏈接(可用location.href.split('#')[0]獲取,而且需要encodeURIComponent),
因為頁面一旦分享,微信客戶端會在你的鏈接末尾加入其它參數,如果不是動態獲取當前鏈接,將導致分享后的頁面簽名失敗。

第一個問題是因為首頁由控制器輸出模板,對模板進行賦值。控制器生成的簽名和首頁一致,與二級頁面卻不一致,所以我采取ajax方法,將靜態頁面的url傳給后台(PHP),這樣生成的簽名就一致了。

1)首先是改寫Jssdk.php中的簽名算法,因為生成簽名的方法為:
public function getSignPackage() { $jsapiTicket = $this->getJsApiTicket(); // 注意 URL 一定要動態獲取,不能 hardcode.
    $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://"; : "http://";; $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; $timestamp = time(); $nonceStr = $this->createNonceStr(); // 這里參數的順序要按照 key 值 ASCII 碼升序排序
    $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url"; $signature = sha1($string); $signPackage = array( "appId"     => $this->appId,
        "nonceStr"  => $nonceStr,
        "timestamp" => $timestamp,
        "url"       => $url,
        "signature" => $signature,
        "rawString" => $string ); return $signPackage; }

其中, $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url”; 這里的url要改成靜態頁面的url。

所以在Jssdk.php文件中增加私有屬性url,並在構造函數中設置 $this->url = $url; 

2)控制器中不再采用給模板賦值的方式,而是使用json_encode()函數中將簽名返回給靜態頁面。
3)靜態頁面中用ajax獲取wx.config配置所需的幾個參數的值,可以這樣做:
<script type="text/javascript"> url = location.href.split('#')[0]; // 傳給后台PHP
 $.ajax({ type: "GET", url: "https://xxx.com/wechat/share?url="+url, dataType : "json", success: function(data) { // 先前分享部分的代碼挪到這里來
 } }); </script>

在需要分享的靜態頁面中引入這段JS代碼,即可成功分享所有頁面。第一個問題就解決了~

第二個問題更簡單,官方技術文檔已經說得很清楚了,js獲取當前頁面的鏈接可用location.href.split('#')[0]獲取,而且需要encodeURIComponent,因為頁面一旦分享,微信客戶端會在你的鏈接末尾加入其它參數。
果然,因為我沒encodeURIComponent,所以再次分享時鏈接為https://xxx.com/index.html?from=singlemessage&isappinstalled=0
url中紅色部分內容是微信自動為分享鏈接添加的參數,目的是為了記錄分享來源。
from=singlemessage&isappinstalled=0表示來自好友分享
from=timeline&isappinstalled=0表示來自朋友圈分享
from=groupmessage&isappinstalled=0表示來自微信群分享

只要在上述JS代碼中加上encodeURIComponent這句代碼即可。如下所示:

url = location.href.split('#')[0];
url = encodeURIComponent(url);

That’s all~


免責聲明!

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



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