微信分享-无后端的单页面实现
程序员文章站
2022-05-30 08:38:05
...
不需要后端,微信获取token,签名什么的都在这一个页面里完成了,在服务器只需要部署这一个页面就能用。
其中微信类的appId和appSecret需要替换为自己公众号的,分享图标也需要替换。
保存为.php文件,放在服务端的php环境中 ,然后在同级目录下新建个缓存文件夹cache
启动服务,然后就可以在微信访问分享了。
<?php
//缓存类
class Cache
{
private $cache_path;//缓存路径
private $cache_expire;//缓存过期的秒数
//缓存构造函数,可选的过期时间和缓存路径
public function Cache($exp_time = 7200, $path = "cache/")
{
$this->cache_expire = $exp_time;
$this->cache_path = $path;
}
//返回缓存的文件名
private function fileName($key)
{
return $this->cache_path . md5($key);
}
//用给定的数据创建新的缓存文件,$key==缓存的名称,数据信息/值存储
public function put($key, $data)
{
$values = serialize($data);
$filename = $this->fileName($key);
$file = fopen($filename, 'w');
if ($file) {//能够创建文件
fwrite($file, $values);
fclose($file);
} else return false;
}
//返回给定键的缓存
public function get($key)
{
$filename = $this->fileName($key);
if (!file_exists($filename) || !is_readable($filename)) {//无法读取缓存
return false;
}
if (time() < (filemtime($filename) + $this->cache_expire)) {//**未过期的缓存
$file = fopen($filename, "r");// 读取数据文件
if ($file) {//能够打开文件
$data = fread($file, filesize($filename));
fclose($file);
return unserialize($data);//返回的值
} else return false;
} else return false;//过期了
}
}
//微信类
class Wechat{
protected $appId;
protected $appSecret;
protected $cache;
public function Wechat(){
$this->appId = 'xxxxxxxxx';
$this->appSecret = 'xxxxxxxxxxx';
$this->cache=new Cache();
}
//发送请求
protected function _http_request($url,$data = null){
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
if (!empty($data)){
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($curl);
curl_close($curl);
return $output;
}
/**
* 产生随机字符串,不长于32位
*/
function getNonceStr($length = 32){
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
$str ="";
for ( $i = 0; $i < $length; $i++ ) {
$str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
}
return $str;
}
//获取assessToken 实效性2小时
function getAccessToken(){
//获取缓存中的token的过期时间
$access_token_past_time=$this->cache->get('access_token_past_time');
//获取缓存中token
$access_token=$this->cache->get('access_token');
//没有为false 或者 当前时间大于 token的过期时间
if(!$access_token||time()>$access_token_past_time){
//重新获取
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$this->appId."&secret=".$this->appSecret;
$result = $this->_http_request($url);
$result_array = json_decode($result,true);
if(isset($result_array['access_token'])){
//获取到accessToken
$access_token = $result_array['access_token'];
$access_token_past_time = $result_array['expires_in']+time();
//保存到缓存
$this->cache->put('access_token',$access_token);
$this->cache->put('access_token_past_time',$access_token_past_time);
}else{
var_dump($result_array);
}
}else{
return $access_token;
}
}
//获取接口临时票据 实效性2小时
function getJsApiTicket(){
//获取缓存中的token的过期时间
$jsapi_ticket_past_time=$this->cache->get('jsapi_ticket_past_time');
//获取缓存中token
$jsapi_ticket=$this->cache->get('jsapi_ticket');
//没有为false 或者 当前时间大于 token的过期时间
if(!$jsapi_ticket||time()>$jsapi_ticket_past_time){
//重新获取
$access_token = $this->getAccessToken();
$url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=".$access_token;
$result = $this->_http_request($url);
$result_array = json_decode($result,true);
if(isset($result_array['ticket'])){
$jsapi_ticket = $result_array['ticket'];
$jsapi_ticket_past_time = $result_array['expires_in']+time();
//保存到缓存
$this->cache->put('jsapi_ticket',$jsapi_ticket);
$this->cache->put('jsapi_ticket_past_time',$jsapi_ticket_past_time);
}else{
var_dump($result_array);
}
}else{
return $jsapi_ticket;
}
}
/**
* 获取jsapi配置信息
*
**/
public function getSignPackage($url){
$jsapi_ticket=$this->getJsApiTicket();
//时间戳
$timestamp = time();
//随机字符串
$nonceStr = $this->getNonceStr();
//签名(这里参数的顺序要按照 key 值 ASCII 码升序排序)
$string = "jsapi_ticket=$jsapi_ticket&noncestr=$nonceStr×tamp=$timestamp&url=$url";
$signature = sha1($string);
// 注意 URL 一定要动态获取,不能 hardcode.
$signPackage = array(
"appId" => $this->appId,
"nonceStr" => $nonceStr,
"timestamp" => $timestamp,
"url" => $url,
"signature" => $signature,
"rawString" => $string
);
return $signPackage;
}
}
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
<title>元旦快乐</title>
<meta name="description" content=""/>
<meta name="keywords" content=""/>
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0">
<meta name="format-detection" content="telephone=no">
<style type="text/css">
</style>
</head>
<body>
<div>
<img src="yuandan.png" width="100%"/>
</div>
<script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
<script src="http://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
<script>
<?php $wechat=new Wechat();
$url='http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$signPackage=$wechat->getSignPackage($url);
?>
var signPackage='<?php echo json_encode($signPackage) ?>';
var configData=JSON.parse(signPackage)
wx.config({
// debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: configData.appId, // 必填,公众号的唯一标识
timestamp: configData.timestamp, // 必填,生成签名的时间戳
nonceStr: configData.nonceStr, // 必填,生成签名的随机串
signature: configData.signature,// 必填,签名
jsApiList: [
"updateAppMessageShareData",
"updateTimelineShareData"
] // 必填,需要使用的JS接口列表
});
wx.ready(function () { //需在用户可能点击分享按钮前就先调用
//自定义“分享给朋友”及“分享到QQ”
wx.updateAppMessageShareData({
title: '祝您元旦快乐!', // 分享标题
desc: '元旦乐 万事兴 新年行大运 祝福您身体健康,万事如意 幸福快乐', // 分享描述
link: window.location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: 'http://xxxxx/yuandan.png', // 分享图标
success: function () {
console.log("设置成功");
}
});
//自定义“分享到朋友圈”及“分享到QQ空间”
wx.updateTimelineShareData({
title: '祝您元旦快乐!', // 分享标题
link: window.location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: 'http://xxxxx/yuandan.png', // 分享图标
success: function () {
console.log("设置成功");
}
})
});
</script>
</body>
</html>