微信公众平台开发教程②微信端分享功能图文详解


Posted in PHP onApril 10, 2019

本文实例讲述了微信公众平台微信端分享功能。分享给大家供大家参考,具体如下:

背景

    初次尝试微信公众号的开发,对于学习方法的探索都是来源于网上的博客、问答,对于参差不齐的信息,自己也是有苦说不出,抽出一点时间写点文章,既是对自己的学习总结,也希望给予同是菜鸟的小白一点帮助。

    今天想添加微信分享的功能,如果不进行自定义设计,那么当我们点击分享朋友圈、好友或者QQ好友、空间时,默认的标题就是<title>标签中的信息,而显示的描述信息就是链接,图片多是默认为页面中显示的第一张图片,显然这样的处理是不合理的,所以需要查询开发文档进行编码设计。

操作步骤:

一.参考微信公众号开发文档

【1】.登录微信公众号

      打开 “开发者工具->开发者文档->微信网页开发->微信JS-SDK说明文档”,找到对应的位置,首先要了解官方的需求说明才能进行下一步的开发。
        微信公众平台开发教程②微信端分享功能图文详解

【2】.建议详细参考文档后再考虑代码的编写

      提示:下拉上图中的网页最下端,下载官方提供的参考demo。本文的最后我会提供一份稍作修改的仅针对于php的实现代码,可作参考。
        微信公众平台开发教程②微信端分享功能图文详解

二.代码实现(PHP)及部分问题引导

【1】.我提供的代码就是下图中的几个简单文件

      主要来源于微信公众号的开发文档,上面提到过一次。其中,我们操作的分享页面代码只需参考 sharePage.php就好,对于官方的实现可以去阅读其他文件,毕竟我们实现功能只需导入文件,调用所提供类及方法就好。
        微信公众平台开发教程②微信端分享功能图文详解

【2】.在此提供 sharePage.php 简单代码,以便参考讲解。

      其中提出几点需要注意的是: 

(1).需要提供 $appid, $secret 

(2).代码中需要引用微信端提供的js文件<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script> ,当然也可以下载其源代码,放于本地链接获取就可以。 

(3).保证 wx.config 的信息配置的正确,debug如果为true可以提示操作的过程,测试没有问题后可以改为false,这样才是合理的操作,另外jsApiList中要补全自己需要的功能 

(4).之前我把分享功能的代码写在 wx.config 平级中无法实现,之后测试发现应该写在wx.reday(function())中,具体的代码模式都应该参考开发文档。

<?php
require_once "jssdk.php";

//获取到网页授权的access_token
$appid = "wx36xxxxxxxxxx199";// 输入公众号、服务号、或者测试号的appid 
$secret = "9caxxxxxxxxxxxxxxxxxx8a2";// 输入公众号、服务号、或者测试号的 secret


$jssdk = new JSSDK($appid, $secret);
$signPackage = $jssdk->GetSignPackage();

//此处用于输出得到的数据 用来测试签名证书是否正确 
/*
echo ' appId:'. $signPackage["appId"].'<br/>';
echo ' jsapi_ticket:'. $signPackage["jsapiTicket"].'<br/>';
echo ' url:'. $signPackage["url"].'<br/>';
echo ' timestamp:'. $signPackage["timestamp"].'<br/>';
echo ' nonceStr:'. $signPackage["nonceStr"].'<br/>';
echo ' signature:'. $signPackage["signature"];
echo '<br/>';
echo '<br/>';
echo '<br/>';
exit;
*/

?>
<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title></title>
</head>
<body>
 Hello Hello Hello
</body>
<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
<script>
 /*
 * 注意:
 * 1. 所有的JS接口只能在公众号绑定的域名下调用,公众号开发者需要先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”。
 * 2. 如果发现在 Android 不能分享自定义内容,请到官网下载最新的包覆盖安装,Android 自定义分享接口需升级至 6.0.2.58 版本及以上。
 * 3. 常见问题及完整 JS-SDK 文档地址:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
 *
 * 开发中遇到问题详见文档“附录5-常见错误及解决办法”解决,如仍未能解决可通过以下渠道反馈:
 * 邮箱地址:weixin-open@qq.com
 * 邮件主题:【微信JS-SDK反馈】具体问题
 * 邮件内容说明:用简明的语言描述问题所在,并交代清楚遇到该问题的场景,可附上截屏图片,微信团队会尽快处理你的反馈。
 */
 wx.config({
 debug: true,
 appId: '<?php echo $signPackage["appId"];?>',
 timestamp: <?php echo $signPackage["timestamp"];?>,
 nonceStr: '<?php echo $signPackage["nonceStr"];?>',
 signature: '<?php echo $signPackage["signature"];?>',
 jsApiList: [
  // 所有要调用的 API 都要加到这个列表中
  'checkJsApi',
  'onMenuShareTimeline',
  'onMenuShareAppMessage',
  'onMenuShareQQ',
  'onMenuShareWeibo',
  'onMenuShareQZone',
 ]
 });

 wx.ready(function () {
 // 在这里调用 API
 //获取“分享到朋友圈”按钮点击状态及自定义分享内容接口
 wx.onMenuShareTimeline({
  title: '快来!分享朋友圈', // 分享标题
  link: 'http://www.baidu.com', // 分享链接
  imgUrl: 'http://img1.3lian.com/img013/v2/4/d/101.jpg', // 分享图标
  success: function () {
  // 用户确认分享后执行的回调函数
  },
  cancel: function () {
  // 用户取消分享后执行的回调函数
  }
 });
 //获取“分享给朋友”按钮点击状态及自定义分享内容接口
 wx.onMenuShareAppMessage({
  title: ' 微信分享给朋友', // 分享标题
  desc: '描述一下,可是知道该咋描述你呢?', // 分享描述
  link: 'http://www.baidu.com', // 分享链接
  imgUrl: 'http://img1.3lian.com/img013/v2/4/d/101.jpg', // 分享图标
  type: 'link', // 分享类型,music、video或link,不填默认为link
  dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
 });
 wx.onMenuShareQQ({
  title: 'QQ我要跳转到百度页面了啊!', // 分享标题
  desc: '描述一下,可是知道该咋描述你呢?', // 分享描述
  link: 'http://www.baidu.com', // 分享链接
  imgUrl: 'http://img1.3lian.com/img013/v2/4/d/101.jpg', // 分享图标
 });
 wx.onMenuShareQZone({
  title: 'QZone我要跳转到百度页面了啊!', // 分享标题
  desc: '描述一下,可是知道该咋描述你呢?', // 分享描述
  link: 'http://www.baidu.com', // 分享链接
  imgUrl: 'http://img1.3lian.com/img013/v2/4/d/101.jpg', // 分享图标
 });
 });
</script>
</html>
【3】.正常操作中,可能会有 “errMsg config:invalid signature" 签名错误

      可以参考博文  《微信js sdk invalid signature签名错误》,网上多数的建议是检查签名证书是否正确,用作者的话就是“确认签名算法正确,可用 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 页面工具进行校验”。
       微信公众平台开发教程②微信端分享功能图文详解       对于需要填入的信息,可以从上文中打印出需要的信息,我做注释的那一部分信息,请参考。不过,普遍情况,这样的签名是没有问题的,可作为参考。

【4】.新发现一种情况

     原先一切正常的分享功能,突然变得无法显示分享时的链接、图片等,我将 wx.config 中的debug 设定为true继续报错“errMsg config:invalid signature",并非签名证书的问题,我猜测应该是文档中一直提及的token或ticket缓存问题,个人打开之前导入的两个文件发现已经重新写入了值,但是我将其重新改为当初下载下来的文件放入服务器中覆盖,意外的发现可以重新获得正确的分享能力,不知哪一天又会出现问题,也希望好心的大牛告知一下。

【2016-7-14 补充】

      经测试发现,上文提及分享功能的失败,与token ,ticket 存储文件没有多大关系,因为如今无法重现 Bug,无语的是,发现当初开发者中心使用的测试号是被赋予了分享权限的,然而自己申请的订阅号,通过查看“接口权限”发现“未获得”分享权限。

        微信公众平台开发教程②微信端分享功能图文详解

      一般的服务号都是拥有分享权限的,获取需要开通什么来着,具体的可百度,我的问题是没有进入“公众号平台->公众号设置->功能设置”中填写“JS接口安全域名”,其中要求是备案过的域名,个人实验证明填写去掉“http://www”后的形如“beidou.com”的域名即可,便于限制诱导关注的情况出现。

      设置完成后可以查看上图中的“分享接口”,保证里面显现的是获得权限,然后再进行菜单栏的分享测试即可发现,正常进行。

【5】.我遇到过提示此处代码报错的问题

      参考网上资源介绍的多是与签名安全相关的信息,可自行百度,鉴于能力有限,暂时发现注释此处的代码可避免该问题的影响,等有时间再做深入解决。
     微信公众平台开发教程②微信端分享功能图文详解

【6】.最后的报错信息显示该处对于文件操作的权限不足的问题

      类似 “Warning: fopen(access_token.json) [function.fopen]: failed to open stream: Permission denied in jssdk.php "问题,可以参考此文的部分介绍。
     微信公众平台开发教程②微信端分享功能图文详解       值得一提的是该问题大多牵扯操作系统的权限分配,之前我用的是新浪SAE进行测试,后面得知SAE是无法由我们用户进行权限设定的,最后我选择了公司服务器,使用类似 “chmod -R 777 /home/mypackage ” 的命令进行对应文件的操作权限分配。

三.补充

1.出现问题,多参考别人的解决方法,可见有一个可以带你的前辈是多么重要 

2.自己探索问题的解决方法,然后做好笔记作为自己的经历回顾,虽然解决时间拉长,但成就感绝对比从别人口中听来分量重的多。 

3.在此我粘贴稍作修改后的代码,其实就是其中的大概几行的改动,为了配合上面签名的测试,所以需要参考,其中另外的两个文件没做改动,无需上传,公众号开发文档的最后就有 demo 文件,具体的请参照开发文档。      

<?php
class JSSDK {
 private $appId;
 private $appSecret;

 public function __construct($appId, $appSecret) {
 $this->appId = $appId;
 $this->appSecret = $appSecret;
 }

 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,
 "jsapiTicket" => $jsapiTicket,
 "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, true);
 //curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);
 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($filename), 15));
 }
 private function set_php_file($filename, $content) {
 $fp = fopen($filename, "w");
 fwrite($fp, "<?php exit();?>" . $content);
 fclose($fp);
 }
}

四、附录

    1.在此推荐参考一篇比较详细的 微信分享博文,向前辈致敬。   
    2.源代码之前存于360云盘共享
如今已经过期找不到了。其实参考文中的代码同时下载官方demo就能完全重现源代码。
    3.此处 推荐参考新篇: 微信公众平台开发教程微信开发集成类的使用 (包含微信分享功能)

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
桌面中心(一)创建数据库
Oct 09 PHP
小偷PHP+Html+缓存
Nov 25 PHP
PHP备份/还原MySQL数据库的代码
Jan 06 PHP
php入门学习知识点八 PHP中for循环基本应用之九九乘法口绝表
Jul 14 PHP
让ThinkPHP支持大小写url地址访问的方法
Oct 31 PHP
ThinkPHP控制器间实现相互调用的方法
Oct 31 PHP
一个完整的php文件上传类实例讲解
Oct 27 PHP
PHP GD库相关图像生成和处理函数小结
Sep 30 PHP
php 中的closure用法详解
Jun 12 PHP
php readfile()修改文件上传大小设置
Aug 11 PHP
PHP实现无限极分类的两种方式示例【递归和引用方式】
Mar 25 PHP
TP5(thinkPHP5框架)基于bootstrap实现的单图上传插件用法示例
May 29 PHP
ThinkPHP框架整合微信支付之刷卡模式图文详解
Apr 10 #PHP
laravel配置Redis多个库的实现方法
Apr 10 #PHP
在Ubuntu 18.04上安装PHP 7.3 7.2和7.0的方法
Apr 09 #PHP
微信公众号实现扫码获取微信用户信息(网页授权)
Apr 09 #PHP
ThinkPHP框架整合微信支付之Native 扫码支付模式二图文详解
Apr 09 #PHP
ThinkPHP框架整合微信支付之Native 扫码支付模式一图文详解
Apr 09 #PHP
ThinkPHP框架整合微信支付之JSAPI模式图文详解
Apr 09 #PHP
You might like
PHP简介
2006/10/09 PHP
php删除页面记录 同时刷新页面 删除条件用GET方式获得
2012/01/10 PHP
PHP浮点数的一个常见问题
2016/03/10 PHP
PHP函数积累总结
2019/03/19 PHP
jquery右下角弹出提示框示例代码
2013/10/08 Javascript
解决ueditor jquery javascript 取值问题
2014/12/30 Javascript
JQuery中节点遍历方法实例
2015/05/18 Javascript
关于 jQuery Easyui异步加载tree的问题解析
2016/12/06 Javascript
jQuery zTree树插件动态加载实例代码
2017/05/11 jQuery
基于vue中css预加载使用sass的配置方式详解
2018/03/13 Javascript
JavaScript实现的文本框placeholder提示文字功能示例
2018/07/25 Javascript
js实现的订阅发布者模式简单示例
2020/03/14 Javascript
vue+vant使用图片预览功能ImagePreview的问题解决
2020/04/10 Javascript
Python linecache.getline()读取文件中特定一行的脚本
2008/09/06 Python
Python中使用第三方库xlrd来读取Excel示例
2015/04/05 Python
利用Python获取赶集网招聘信息前篇
2016/04/18 Python
Python中set与frozenset方法和区别详解
2016/05/23 Python
Python操作MySQL数据库的三种方法总结
2018/01/30 Python
python解析含有重复key的json方法
2019/01/22 Python
python画图的函数用法以及技巧
2019/06/28 Python
python的json中方法及jsonpath模块用法分析
2019/12/06 Python
opencv+python实现均值滤波
2020/02/19 Python
浅谈keras中的batch_dot,dot方法和TensorFlow的matmul
2020/06/18 Python
使用Python实现微信拍一拍功能的思路代码
2020/07/09 Python
详解CSS3的opacity属性设置透明效果的用法
2016/05/09 HTML / CSS
在HTML5中使用MathML数学公式的简单讲解
2016/02/19 HTML / CSS
英国汽车座椅和婴儿车购物网站:Uber Kids
2017/04/19 全球购物
Android面试题附答案
2014/12/08 面试题
后勤自我鉴定
2013/10/13 职场文书
关于是否需要写商业计划书
2014/02/07 职场文书
合作投资意向书
2014/04/01 职场文书
部门年终奖分配方案
2014/05/07 职场文书
社区服务标语
2014/07/01 职场文书
纪念9.18事变演讲稿
2014/09/14 职场文书
学校党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
2014年纪检工作总结
2014/11/12 职场文书