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


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 相关文章推荐
PHP Undefined index报错的修复方法
Jul 17 PHP
PHP实现读取一个1G的文件大小
Aug 24 PHP
php模仿asp Application对象在线人数统计实现方法
Jan 04 PHP
使用新浪微博API的OAuth认证发布微博实例
Mar 27 PHP
Yii使用migrate命令执行sql语句的方法
Mar 15 PHP
PHP中Restful api 错误提示返回值实现思路
Apr 12 PHP
Yii2 输出xml格式数据的方法
May 03 PHP
thinkPHP线上自动加载异常与修复方法实例分析
Dec 01 PHP
PHP给源代码加密的几种方法汇总(推荐)
Feb 06 PHP
PHP分页显示的方法分析【附PHP通用分页类】
May 10 PHP
thinkPHP框架实现多表查询的方法
Jun 14 PHP
解决PHP Opcache 缓存刷新、代码重载出现无法更新代码的问题
Aug 24 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,不用COM,生成excel文件
2006/10/09 PHP
PHP中根据IP地址判断城市实现城市切换或跳转代码
2012/09/04 PHP
修改php.ini不生效问题解决方法(上传大于8M的文件)
2013/06/14 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(一)
2014/06/23 PHP
php生成图片验证码的方法
2016/04/15 PHP
accesskey 提交
2006/06/26 Javascript
javascript 字符串连接的性能问题(多浏览器)
2008/11/18 Javascript
JavaScript null和undefined区别分析
2009/10/14 Javascript
十分钟打造AutoComplete自动完成效果代码
2009/12/26 Javascript
JQuery 构建客户/服务分离的链接模型中Table中的排序分析
2010/01/22 Javascript
谷歌浏览器不支持showModalDialog模态对话框的解决方法
2014/09/22 Javascript
jQuery中DOM树操作之使用反向插入方法实例分析
2015/01/23 Javascript
JavaScript在Android的WebView中parseInt函数转换不正确问题解决方法
2015/04/25 Javascript
原生JS版和jquery版实现checkbox的全选/全不选/点选/行内点选(Mr.Think)
2016/10/29 Javascript
JS获取年月日时分秒的方法分析
2016/11/28 Javascript
AngularJS定时器的使用与移除操作方法【interval与timeout】
2016/12/14 Javascript
javascript编写简易计算器
2017/05/06 Javascript
基于JS对象创建常用方式及原理分析
2017/06/28 Javascript
vue+springboot前后端分离实现单点登录跨域问题解决方法
2018/01/30 Javascript
layui点击导航栏刷新tab页的示例代码
2018/08/14 Javascript
jQuery超简单遮罩层实现方法示例
2018/09/06 jQuery
小程序实现锚点滑动效果
2019/09/23 Javascript
jQuery实现验证用户登录
2019/12/10 jQuery
Vue结合路由配置递归实现菜单栏功能
2020/06/16 Javascript
在vue中使用image-webpack-loader实例
2020/11/12 Javascript
Python和JavaScript间代码转换的4个工具
2016/02/22 Python
Python3 适合初学者学习的银行账户登录系统实例
2017/08/08 Python
Python文件和流(实例讲解)
2017/09/12 Python
Python实现的读取电脑硬件信息功能示例
2018/05/30 Python
Python模拟简单电梯调度算法示例
2018/08/20 Python
Linux系统下升级pip的完整步骤
2021/01/31 Python
Java servlet面试题
2012/03/04 面试题
入党申请自荐书范文
2014/02/11 职场文书
教师读书活动总结
2014/05/07 职场文书
超市督导岗位职责
2015/04/10 职场文书
如何利用python和DOS获取wifi密码
2021/03/31 Python