TP5 實現微信網頁自定義分享
荊軻刺秦王
文章部分借鑑於:https://www.cnblogs.com/sunshineliulu/p/8034286.html
在實際操作中還有一些需要注意的問題:
1.登入微信公眾平臺,設定—公眾號設定—功能設定裡,填寫『JS介面安全域名』。填寫的域名須通過ICP備案的驗證,並將平臺給的txt檔案放到域名指向的web伺服器之下。
注意:在 TP5 框架下,web伺服器根目錄表示的是 TP5 框架的 Public 目錄!
2.整個流程為:
2.1 公眾號的認證
2.2 JS安全域名設定
2.3 將微信公眾平臺給的txt檔案放到網站根目錄下
2.4 獲取到 AppID 和 AppSecret
3. 下載官方示例程式碼:http://demo.open.weixin.qq.com/jssdk/sample.zip
這個連結是直接下載,瀏覽器會提示安全資訊 不用理會 直接下載即可 解壓出來是這樣的:
本文主要講解 PHP 的部分 而且是放在 TP5框架上的
4. 將解壓的access_token.php、jsapi_ticket.php和jssdk.php放入到 TP5 框架的 extend 目錄下,如下圖:
5. 完成以上步驟後 咱們需要將 Jssdk.php 做一點修改!
5.1 將jssdk.php檔案重新命名為Jssdk.php檔案,設定名稱空間,因為tp路由的關係,需要加上私有屬性path,並在建構函式中設定 $this->path = __DIR__ . DS; 如下圖:
5.2 同時將函式 get_php_file 函式返回值中的 $filename 改為 $this->path . $filename ,否則會報錯。如圖:
5.3 在 config.php 檔案中,將先前獲得的AppID和AppSecret配置好。如下圖:
5.4 到這一步 就是基本完成了,現在我們做一個小測試
在application/index/controller下新建Wechat.php檔案,內容如下:
<?php /** * Created by PhpStorm. * User: liuyaowei * Date: 2018/12/8 * Time: 15:57 */ namespace app\index\controller; use think\Config; use think\Controller; use org\wechat\JSSDK; class Wechat extends Controller{ //jssdk分享封裝功能 public function share(){ $jssdk = new JSSDK(Config::get('WEIXINAPPID'),Config::get('WEIXINAPPSECRET')); $res = $jssdk->getSignPackage(); $appId = $res['appId']; $timestamp = $res['timestamp']; $nonceStr = $res['nonceStr']; $signature = $res['signature']; $this->assign( array( 'appId'=>$appId, 'timestamp'=>$timestamp, 'nonceStr'=>$nonceStr, 'signature'=>$signature, ) ); return $this->fetch('index'); } }
以上就是自定義分享需要設定的後臺部分
前端內容如下:
JS 部分
1. 需要引入微信的js檔案:
<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函式中。
});
實際專案中的程式碼如下:
<script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
<script type="text/javascript">
var title = 'this is the share title';
var imgUrl = 'this is the share imgUrl make it can use browser for open';
var link = 'http://www.domain.com';
var desc = 'this is a share description';
wx.config({
debug: false,//開啟除錯模式,呼叫的所有api的返回值會在客戶端alert出來,若要檢視傳入的引數,可以在pc端開啟,引數資訊會通過log打出,僅在pc端時才會列印。
appId: '{$appId}', // 必填,公眾號的唯一標識
timestamp: '{$timestamp}', // 必填,生成簽名的時間戳
nonceStr: '{$nonceStr}', //必填, 生成簽名的隨機串
signature: '{$signature}', //必填,簽名
jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareQZone'] //必填, JS介面列表,這裡只填寫了分享需要的介面
})
wx.ready(function () {
wx.onMenuShareTimeline({
title: title,
link: link,
desc:desc,
imgUrl: imgUrl,
success: function() {
// 使用者確認分享後執行的回撥函式
},
cancel: function() {
// 使用者取消分享後執行的回撥函式
}
});
wx.onMenuShareAppMessage({
title: title, // 分享標題
desc: desc, // 分享描述
link: link, // 分享連結
imgUrl: imgUrl, // 分享圖示
type: 'link', // 分享型別,music、video或link,不填預設為link
dataUrl: '', // 如果type是music或video,則要提供資料鏈接,預設為空
success: function() {
// 使用者確認分享後執行的回撥函式
},
cancel: function() {
// 使用者取消分享後執行的回撥函式
}
});
})
</script>
控制器中的程式碼:
private function wxShare(){
$jssdk = new JSSDK(Config::get('WEIXINAPPID'),Config::get('WEIXINAPPSECRET'));
$res = $jssdk->getSignPackage();
$appId = $res['appId'];
$timestamp = $res['timestamp'];
$nonceStr = $res['nonceStr'];
$signature = $res['signature'];
return $this->assign(
array(
'appId'=>$appId,
'timestamp'=>$timestamp,
'nonceStr'=>$nonceStr,
'signature'=>$signature,
)
);
}
將分享設為一個單獨方法 然後在其他 function 裡呼叫就可以了:
$this->wxShare();
還有一點,如果你出現這種情況:
這個時候 將
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);
這兩行的第三個引數改為 false 就可以了
具體程式碼:
private function httpGet($url) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 500);
// 為保證第三方伺服器與微信伺服器之間資料傳輸的安全性,所有微信介面採用https方式呼叫,必須使用下面2行程式碼開啟ssl安全校驗。
// 如果在部署過程中程式碼在此處驗證失敗,請到 http://curl.haxx.se/ca/cacert.pem 下載新的證書判別檔案。
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_URL, $url);
$res = curl_exec($curl);
curl_close($curl);
return $res;
}
最後附上 整個 Jssdk 的程式碼:
<?php
namespace org\wechat;
class Jssdk {
private $appId;
private $appSecret;
private $path;
public function __construct($appId, $appSecret) {
$this->appId = $appId;
$this->appSecret = $appSecret;
$this->path = __DIR__ . DS;
}
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×tamp=$timestamp&url=$url";
$signature = sha1($string);
$signPackage = array(
"appId" => $this->appId,
"nonceStr" => $nonceStr,
"timestamp" => $timestamp,
"url" => $url,
"signature" => $signature,
"rawString" => $string
);
return $signPackage;
}
private function createNonceStr($length = 16) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$str = "";
for ($i = 0; $i < $length; $i++) {
$str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
}
return $str;
}
private function getJsApiTicket() {
// jsapi_ticket 應該全域性儲存與更新,以下程式碼以寫入到檔案中做示例
$data = json_decode($this->get_php_file("jsapi_ticket.php"));
if ($data->expire_time < time()) {
$accessToken = $this->getAccessToken();
// 如果是企業號用以下 URL 獲取 ticket
// $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
$url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
$res = json_decode($this->httpGet($url));
$ticket = $res->ticket;
if ($ticket) {
$data->expire_time = time() + 7000;
$data->jsapi_ticket = $ticket;
$this->set_php_file("jsapi_ticket.php", json_encode($data));
}
} else {
$ticket = $data->jsapi_ticket;
}
return $ticket;
}
private function getAccessToken() {
// access_token 應該全域性儲存與更新,以下程式碼以寫入到檔案中做示例
$data = json_decode($this->get_php_file("access_token.php"));
if ($data->expire_time < time()) {
// 如果是企業號用以下URL獲取access_token
// $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=$this->appId&corpsecret=$this->appSecret";
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$this->appId&secret=$this->appSecret";
$res = json_decode($this->httpGet($url));
$access_token = $res->access_token;
if ($access_token) {
$data->expire_time = time() + 7000;
$data->access_token = $access_token;
$this->set_php_file("access_token.php", json_encode($data));
}
} else {
$access_token = $data->access_token;
}
return $access_token;
}
private function httpGet($url) {
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_TIMEOUT, 500);
// 為保證第三方伺服器與微信伺服器之間資料傳輸的安全性,所有微信介面採用https方式呼叫,必須使用下面2行程式碼開啟ssl安全校驗。
// 如果在部署過程中程式碼在此處驗證失敗,請到 http://curl.haxx.se/ca/cacert.pem 下載新的證書判別檔案。
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_URL, $url);
$res = curl_exec($curl);
curl_close($curl);
return $res;
}
private function get_php_file($filename) {
return trim(substr(file_get_contents($this->path . $filename), 15));
}
private function set_php_file($filename, $content) {
$fp = fopen($filename, "w");
fwrite($fp, "<?php exit();?>" . $content);
fclose($fp);
}
}
以上就是整個 TP5 自定義微信網頁分享的程式碼了,因為我的專案每個頁面的分享內容都是一樣,而且我的分享內容是在 html 裡面設定的,大家在寫的時候可以改為自定義的設定的。