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


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 中的批处理的实现
Jun 14 PHP
PHPMailer邮件类利用smtp.163.com发送邮件方法
Sep 11 PHP
IIS6+PHP5+MySQL5+Zend Optimizer+phpMyAdmin安装配置图文教程 2009年
Jun 08 PHP
PHP中json_encode、json_decode与serialize、unserialize的性能测试分析
Jun 09 PHP
使用openssl实现rsa非对称加密算法示例
Jan 24 PHP
PHP遍历并打印指定目录下所有文件实例
Feb 10 PHP
php上传图片存入数据库示例分享
Mar 11 PHP
php查询mysql大量数据造成内存不足的解决方法
Mar 04 PHP
浅谈PHP中的错误处理和异常处理
Feb 04 PHP
php+mysql+jquery实现日历签到功能
Feb 27 PHP
YII2框架中使用RBAC对模块,控制器,方法的权限控制及规则的使用示例
Mar 18 PHP
discuz论坛更换域名,详细文件修改步骤
Dec 09 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基于表单密码验证与HTTP验证用法实例
2015/01/06 PHP
php中smarty实现多模版网站的方法
2015/06/11 PHP
php生成图片验证码的实例讲解
2015/08/03 PHP
对比分析php中Cookie与Session的异同
2016/02/19 PHP
PHP自定义函数实现格式化秒的方法
2016/09/14 PHP
php操作路径的经典方法(必看篇)
2016/10/04 PHP
YII框架学习笔记之命名空间、操作响应与视图操作示例
2019/04/30 PHP
基于jQuery的Tab选项框效果代码(插件)
2011/03/01 Javascript
页面元素绑定jquery toggle后元素隐藏的解决方法
2014/03/27 Javascript
jQuery蓝色风格滑动导航栏代码分享
2015/08/19 Javascript
使用nodejs中httpProxy代理时候出现404异常的解决方法
2016/08/15 NodeJs
node.js路径处理方法以及绝对路径详解
2021/03/04 Javascript
Bootstrap 3 进度条的实现
2017/02/22 Javascript
jQuery实现三级联动效果
2017/03/02 Javascript
深入浅出webpack教程系列_安装与基本打包用法和命令参数详解
2017/09/10 Javascript
js Element Traversal规范中的元素遍历方法
2018/04/19 Javascript
微信小程序中的canvas 文字断行和省略号显示功能的处理方法
2018/11/14 Javascript
详解element-ui表格中勾选checkbox,高亮当前行
2019/09/02 Javascript
python算法学习之基数排序实例
2013/12/18 Python
python3使用pyqt5制作一个超简单浏览器的实例
2017/10/19 Python
python如何读写csv数据
2018/03/21 Python
python爬取微信公众号文章
2018/08/31 Python
Python Web程序搭建简单的Web服务器
2019/07/31 Python
python爬虫请求头设置代码
2020/07/28 Python
利用Python实现自动扫雷小脚本
2020/12/17 Python
html5调用摄像头功能的实现代码
2018/05/07 HTML / CSS
详解如何通过H5(浏览器/WebView/其他)唤起本地app
2017/12/11 HTML / CSS
优质的学校老师推荐信
2013/10/28 职场文书
12岁生日感言
2014/01/21 职场文书
软件毕业生个人鉴定
2014/03/03 职场文书
学校庆元旦歌咏比赛主持词
2014/03/18 职场文书
2014年妇委会工作总结
2014/12/10 职场文书
污水处理保证书
2015/05/09 职场文书
五年级作文之学校的四季
2019/12/05 职场文书
Python 实现Mac 屏幕截图详解
2021/10/05 Python