H5微信分享JS/后端PHP完整版代码

有差不多一年没有接H5的开发了,最近又接了一个,发现以前写过的微信分享部分不管用了,踩坑,又踩坑了!

首先是服务号的设置问题,我已经在这篇老的博客里更新:https://blog.brain1981.com/1784.html
此处重复一遍更新的内容,IP地址白名单从前可以不填,现在必须填写了,要不然死活调试不出分享,开发者工具会显示无权限获取access_token!
服务号后台必须填写IP白名单

第二个坑是微信已经更改了分享机制,如果你是点击URL进入H5页面,那么这时候即使分享请求正确,分享出去的都只能是一个文本的URL,而不是卡片式的分享格式。相关讨论和通知见这个链接:https://developers.weixin.qq.com/community/develop/doc/0000ea53f1cf60dcfc1da027a55c00
一度我还以为是微信又出了什么隐藏bug,明明debug模式和开发者工具都显示分享请求成功,死活分享不出卡片… 这也是微信的老毛病了,你说它没通知开发者么,倒也不尽然,但这种政策更改的通知就是不给你用白话讲清楚,要你自己去体会效果!

最后一个坑,是暂时没有爆的,但相信很快会爆,之前的两个分享接口 wx.onMenuShareTimeline 和 wx.onMenuShareAppMessage 即将被废弃了。需要换成 wx.updateAppMessageShareData 和 wx.updateTimelineShareData, 调用方式和参数大致没变。注意是大致没变,如果只是照搬替换,很可能又要踩坑,为造福广大苦逼码农,本文直接附上可以直接拿来用的分享代码。

先是前端部分,需jQuery

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
var shareMsg = {
	appid:'wx******************',
	title: "分享标题",
	desc:"分享描述",
	image:'https://****/share.png', //分享方块小图,建议150×150正方形
	link: 'https://****'  //分享链接,必须和当前页面是同一个域名/子域名下的URL
}
 
//getSign.php为后端文件,代码在后面
var jsSignService = 'getSign.php';
function weixin(appid,callback){
	var _self = this;
	this.appid = appid;
	this.callback = callback;
	$.each(wx,function(k,v){
		weixin.prototype[k] = v;
	})
	for(var k in wx) {
		weixin[k] = wx[k];
	}
	if(this.callback){
		this.ready(this.callback);
	}
 
	$.getJSON(jsSignService,{'appid':this.appid,'url':location.href.split('#')[0]},function(response){
		_self.config({
			debug: false, // 开启调试模式
			appId: response.appId,
			timestamp: response.timestamp,
			nonceStr: response.nonceStr,
			signature: response.signature,
			jsApiList: [
				'checkJsApi',
				'onMenuShareTimeline',
				'onMenuShareAppMessage',
				'onMenuShareQQ',
				'onMenuShareWeibo',
				'updateAppMessageShareData',
				'updateTimelineShareData',]
		});
	});
}
$(function(){
	var wx = new weixin(shareMsg.appid,function(){
		wx.error(function(res){
			//用于查看回调失败的情形,辅助debug
			//alert(res);
		});
 
		wx.ready(function() {
			//如果页面有背景音乐,可以在这里直接开始播放,无需点击(超越手机浏览器协议)
			//document.getElementById("bg-music").play();
		});
		changeShareVal();
	});
})
 
function changeShareVal(){
	//微信好友/QQ好友/群聊
	wx.updateAppMessageShareData({
		title: shareMsg.title, // 分享标题
		desc: shareMsg.desc,  // 分享描述
		link: shareMsg.link, // 分享链接
		imgUrl: shareMsg.image, // 分享图标
		success: function () { // 分享成功后回调
		},
		cancel: function () { // 分享失败后回调
		}
	});
	//朋友圈/QQ空间
	wx.updateTimelineShareData({
		title: shareMsg.title, // 分享标题
		desc: shareMsg.desc,  // 分享描述
		link: shareMsg.link, // 分享链接
		imgUrl: shareMsg.image, // 分享图标
		success: function () { // 分享成功后回调
		},
		cancel: function () { // 分享失败后回调
		}
	});
}

后端请求文件getSign.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
error_reporting(E_ALL^E_NOTICE^E_WARNING);
class JSSDK {
	private $appId;
	private $appSecret;
 
	public function __construct($appId, $appSecret) {
		$this->appId = $appId;
		$this->appSecret = $appSecret;
	}
 
	public function getSignPackage() {
		$jsapiTicket = $this->getJsApiTicket();
		$url = $_GET['url'];
		$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; 
	}
 
	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 应该全局存储与更新,如无本地 jsapi_ticket 文件,此处会生成一个
		$data = json_decode(file_get_contents("jsapi_ticket.json"));
		if ($data->expire_time < time()) {
			$accessToken = $this->getAccessToken();
			$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;
				$fp = fopen("jsapi_ticket.json", "w");
				fwrite($fp, json_encode($data));
				fclose($fp);
			}
		} else {
			$ticket = $data->jsapi_ticket;
		}
		return $ticket;
	}
 
	private function getAccessToken() {
		//access_token 应该全局存储与更新,如无本地access_token 文件,此处会生成一个
		$data = json_decode(file_get_contents("access_token.json"));
		if ($data->expire_time < time()) {
			$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;
				$fp = fopen("access_token.json", "w");
				fwrite($fp, json_encode($data));
				fclose($fp);
			}
		} 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);
		curl_setopt($curl, CURLOPT_URL, $url);
		$res = curl_exec($curl);
		curl_close($curl);
		return $res;
	}
}
 
$jssdk = new JSSDK("×××××", "×××××××");//此处填写服务号的APPID和APPSecret
$signPackage = $jssdk->GetSignPackage();
echo json_encode($signPackage);

本站所有文章均为原创,欢迎转载,请注明文章出处:https://blog.brain1981.com/2685.html。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。

关注我们的微信公众号-JennyStudio 本站记录了近几年的工作中遇到的一些技术问题和解决过程,“作品集”还收录了本人的大部分作品展示。除了本博客外,我们的工作室网站 – JennyStudio,内有更多作品回顾和展示。
您也可以扫描左边的二维码,关注我们的微信公众号,在微信上查看我们的案例。

发表评论

您的电子邮箱地址不会被公开。