微信分享:后端参数获取PHP实现

简介: 微信分享:后端参数获取PHP实现

微信分享


文档:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html

1、微信后台配置

设置与开发/
    公众号设置 / 功能设置 / JS接口安全域名 (配置网页所用的域名, 【需通过备案】)
    基本配置 / IP白名单 (将服务器公网ip配置到此处)

2、后端代码

PHP版 参照官网给出的示例,稍作改造

PHP版本 7.1

目录结构:

./
    JSSDK.php       微信分享必要参数获取基本接口
    JSSDKCache.php  通过继承,实现对access_token、jsapi_ticket数据的缓存
    RedisService.php   Redis缓存服务
    WeixinService.php  配置具体的微信参数,调用JSSDKCache.php
    WeixinController.php   对外提供数据接口

用到的第三方库

# 网络请求
composer require rmccue/requests
# Redis客户端
composer require  predis/predis

JSSDK.php

<?php
namespace app\utils\weixin;
use Requests;
/**
 * 微信分享必要参数获取基本接口
 *
 * Class JSSDK
 * @package app\utils\weixin
 */
class JSSDK
{
    // 开发者ID
    protected $appId;
    // 开发者密码(AppSecret)
    protected $appSecret;
    public function __construct($appId, $appSecret)
    {
        $this->appId     = $appId;
        $this->appSecret = $appSecret;
    }
    public function getSignPackage($jsapi_ticket, $url)
    {
        $timestamp = time();
        $nonceStr  = $this->createNonceStr();
        // 这里参数的顺序要按照 key 值 ASCII 码升序排序
        $string = "jsapi_ticket=$jsapi_ticket&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;
    }
    /**
     * 获取 Access token
     * https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
     */
    public function getAccessToken()
    {
        $params = [
            'grant_type' => 'client_credential',
            'appid'      => $this->appId,
            'secret'     => $this->appSecret
        ];
        $url = "https://api.weixin.qq.com/cgi-bin/token?" . http_build_query($params);
        $data = self::httpGet($url);
        if ($data) {
            return empty($data['access_token']) ? null : $data['access_token'];
        } else {
            return null;
        }
    }
    /**
     * 获取 jsapi_ticket
     * https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html#62
     */
    public function getJsapiTicket($access_token)
    {
        $params = [
            'access_token' => $access_token,
            'type'         => 'jsapi',
        ];
        $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?" . http_build_query($params);
        $data = self::httpGet($url);
        if ($data) {
            return empty($data['ticket']) ? null : $data['ticket'];
        } else {
            return null;
        }
    }
    private function httpGet($url)
    {
        $response = Requests::get($url);
        if ($response->success) {
            return json_decode($response->body, true);
        } else {
            return null;
        }
    }
}

JSSDKCache.php

<?php
namespace app\utils\weixin;
use app\service\RedisService;
/**
 * 自定义实现缓存: access_token、jsapi_ticket
 *
 * Class JSSDKCache
 * @package app\utils\weixin
 */
class JSSDKCache extends JSSDK
{
    public function getSignData($url)
    {
        $jsapi_ticket = $this->getJsapiTicketFromCache();
        $data = $this->getSignPackage($jsapi_ticket, $url);
        return $data;
    }
    public function getAccessTokenFromCache()
    {
        $cache_key = 'access_token.' . $this->appId;
        $access_token = RedisService::get($cache_key);
        if (!$access_token) {
            // 获取access_token
            $access_token = $this->getAccessToken();
            // 7200
            RedisService::set($cache_key, $access_token, 7100);
        }
        return $access_token;
    }
    public function getJsapiTicketFromCache()
    {
        $cache_key = 'jsapi_ticket.' . $this->appId;
        $jsapi_ticket = RedisService::get($cache_key);
        if (!$jsapi_ticket) {
            // 获取access_token
            $access_token = $this->getAccessTokenFromCache();
            $jsapi_ticket = parent::getJsapiTicket($access_token);
            // 7200
            RedisService::set($cache_key, $jsapi_ticket, 7100);
        }
        return $jsapi_ticket;
    }
}
<?php
namespace app\service;
use Predis\Client;
/**
 * 使用Redis 缓存
 *
 * Class RedisService
 * @package app\service
 */
class RedisService
{
    // 可能有多个网站,每个网站给一个前缀
    private static $prefix = 'www';
    public static function getClient()
    {
        $client = new Client();
        return $client;
    }
    public static function getKey($key)
    {
        return self::$prefix . '.' . $key;
    }
    public static function get($key)
    {
        $client = self::getClient();
        $key    = self::getKey($key);
        return $client->get($key);
    }
    public static function set($key, $value, $expire = null)
    {
        //https://learnku.com/laravel/t/3563/using-predis-to-operate-the-redis-database-how-to-set-the-key-life-cycle-expires
        $client = self::getClient();
        $key    = self::getKey($key);
        if ($expire) {
            // SET key value [EX seconds] [PX milliseconds] [NX|XX]
            $client->set($key, $value, 'EX', $expire);
        } else {
            $client->set($key, $value);
        }
    }
}

WeixinService.php

<?php
namespace app\service;
use app\utils\weixin\JSSDKCache;
class WeixinService
{
    // 公众号 开发者ID
    private static $APP_ID = '';
    // 开发者密码(AppSecret)
    private static $APP_SECRET = '';
    public static function getWeixinConfig($url)
    {
        $jssdk = new JSSDKCache(self::$APP_ID, self::$APP_SECRET);
        return $jssdk->getSignData($url);
    }
}

WeixinController.php

<?php
namespace app\api\controller;
use app\BaseController;
use app\service\WeixinService;
class WeixinController extends BaseController
{
    public function getWeixinConfig()
    {
        $url = input('url');
        return WeixinService::getWeixinConfig($url);
    }
}

3、前端代码weixin-share.html

方式一:后端渲染

<!--微信分享-->
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
<script>
    wx.config({
        debug: false, // 开启调试模式
        appId: '{$appId}', // 必填,公众号的唯一标识
        timestamp: '{$timestamp}', // 必填,生成签名的时间戳
        nonceStr: '{$nonceStr}', // 必填,生成签名的随机串
        signature: '{$signature}',// 必填,签名
        // 必填,需要使用的JS接口列表
        jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData'], 
        // 可选,获取开放标签权限
        openTagList: ['wx-open-launch-app'] 
    });
    // 自定义“分享给朋友”及“分享到QQ”按钮的分享内容
    wx.ready(function () {   //需在用户可能点击分享按钮前就先调用
        wx.updateAppMessageShareData({
            title: '{$title}', // 分享标题
            desc: '{$summary}', // 分享描述
            link: '{$url}', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
            imgUrl: "{$cover_icon}", // 分享图标
            success: function () {
                // 设置成功
            }
        });
        // 分享到朋友圈
        wx.updateTimelineShareData({
            title: '{$title}', // 分享标题
            link: '{$url}', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
            imgUrl: "{$cover_icon}", // 分享图标
            success: function () {
                // 设置成功
            }
        })
    });
    wx.error(function(res){
        // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
        console.log("config验证失败")
    });
</script>

方式二:前端通过接口获取

<!-- Axios -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<!--微信分享-->
<script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
<script>
    url = window.location.href.split('#')[0];
    axios.post('/api/getWeixinConfig', {url: url}).then(res=>{
        let data = res.data.data;
        wx.config({
            debug: false, // 开启调试模式
            appId: data.appId, // 必填,公众号的唯一标识
            timestamp: data.timestamp, // 必填,生成签名的时间戳
            nonceStr: data.nonceStr, // 必填,生成签名的随机串
            signature: data.signature,// 必填,签名
            // 必填,需要使用的JS接口列表
            jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData'],
            // 可选,获取开放标签权限
            // openTagList: ['wx-open-launch-app']
        });
        // 自定义“分享给朋友”及“分享到QQ”按钮的分享内容
        wx.ready(function () {   //需在用户可能点击分享按钮前就先调用
            wx.updateAppMessageShareData({
                title: '{{ detail.title }}', // 分享标题
                desc: '{{ detail.summary }}', // 分享描述
                link: data.url, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
                imgUrl: '{{ detail.head_image }}', // 分享图标
                success: function () {
                    // 设置成功
                }
            });
            // 分享到朋友圈
            wx.updateTimelineShareData({
                title: '{{ detail.title }}', // 分享标题
                link: data.url, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
                imgUrl: '{{ detail.head_image }}', // 分享图标
                success: function () {
                    // 设置成功
                }
            })
        });
        wx.error(function(res){
            // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
            console.log("config验证失败")
        });
    })
</script>



相关文章
|
小程序 前端开发 PHP
PHP实现生成小程序二维码带参数进入指定页面、小程序URL scheme实现携带数据跳转小程序
PHP实现生成小程序二维码带参数进入指定页面、小程序URL scheme实现携带数据跳转小程序
432 0
|
JavaScript 前端开发 安全
php学习笔记-普通表单参数提交获取及页面的重定向和一个登录小demo-day05
本文介绍了PHP中普通表单参数的提交获取、页面重定向的方法,并通过一个登录示例演示了表单参数的封装和页面跳转处理。
|
9月前
|
数据库连接 PHP 数据库
【YashanDB知识库】PHP使用ODBC使用数据库绑定参数功能异常
【YashanDB知识库】PHP使用ODBC使用数据库绑定参数功能异常
|
9月前
|
PHP 数据库
【YashanDB知识库】PHP使用OCI接口使用数据库绑定参数功能异常
【YashanDB知识库】PHP使用OCI接口使用数据库绑定参数功能异常
|
监控 PHP Apache
优化 PHP-FPM 参数配置:实现服务器性能提升
优化PHP-FPM的参数配置可以显著提高服务器的性能和稳定性。通过合理设置 `pm.max_children`、`pm.start_servers`、`pm.min_spare_servers`、`pm.max_spare_servers`和 `pm.max_requests`等参数,并结合监控和调优措施,可以有效应对高并发和负载波动,确保Web应用程序的高效运行。希望本文提供的优化建议和配置示例能够帮助您实现服务器性能的提升。
723 3
|
SQL 关系型数据库 数据库连接
php连接数据库之PDO,PDO的简单使用和预定义占位符的使用以及PDOStatement对象的使用,占位符的不同形式,bindValue和bindParam绑定预定义占位符参数的区别
本文介绍了PHP中PDO(PHP Data Objects)扩展的基本概念和使用方法。内容包括PDO类和PDOStatement类的介绍,PDO的简单使用,预定义占位符的使用方法,以及PDOStatement对象的使用。文章还讨论了绑定预定义占位符参数的不同形式,即bindValue和bindParam的区别。通过具体示例,展示了如何使用PDO进行数据库连接、数据查询、数据插入等操作。
php连接数据库之PDO,PDO的简单使用和预定义占位符的使用以及PDOStatement对象的使用,占位符的不同形式,bindValue和bindParam绑定预定义占位符参数的区别
|
PHP
PHP - Laravel 路由参数
PHP - Laravel 路由参数
197 0
|
数据采集 存储 JavaScript
PHP爬虫技术:利用simple_html_dom库分析汽车之家电动车参数
本文旨在介绍如何利用PHP中的simple_html_dom库结合爬虫代理IP技术来高效采集和分析汽车之家网站的电动车参数。通过实际示例和详细说明,读者将了解如何实现数据分析和爬虫技术的结合应用,从而更好地理解和应用相关技术。
230 0
PHP爬虫技术:利用simple_html_dom库分析汽车之家电动车参数