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

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 微信分享:后端参数获取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>



相关文章
|
2月前
|
小程序 安全 关系型数据库
专业打造一款圈子源码软件系统 / 后端 PHP 搭建部署一样实现利益化
本教程详解基于PHP后端与Uni-app的小程序开发全流程,涵盖技术选型、环境搭建、源码导入、接口对接及功能实现。采用Laravel/Symfony框架,结合MySQL/PostgreSQL数据库,使用WebSocket实现实时通信,并集成IM SDK实现音视频聊天。前端使用Uni-app开发,支持跨平台运行。教程包含完整部署流程与安全优化方案,助力快速搭建高性能、安全稳定的小程序系统。
144 5
|
4月前
|
存储 消息中间件 前端开发
PHP后端与uni-app前端协同的校园圈子系统:校园社交场景的跨端开发实践
校园圈子系统校园论坛小程序采用uni-app前端框架,支持多端运行,结合PHP后端(如ThinkPHP/Laravel),实现用户认证、社交关系管理、动态发布与实时聊天功能。前端通过组件化开发和uni.request与后端交互,后端提供RESTful API处理业务逻辑并存储数据于MySQL。同时引入Redis缓存热点数据,RabbitMQ处理异步任务,优化系统性能。核心功能包括JWT身份验证、好友系统、WebSocket实时聊天及活动管理,确保高效稳定的用户体验。
240 4
PHP后端与uni-app前端协同的校园圈子系统:校园社交场景的跨端开发实践
|
6月前
|
JSON 自然语言处理 前端开发
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
274 72
【01】对APP进行语言包功能开发-APP自动识别地区ip后分配对应的语言功能复杂吗?-成熟app项目语言包功能定制开发-前端以uniapp-基于vue.js后端以laravel基于php为例项目实战-优雅草卓伊凡
|
6月前
|
前端开发 算法 NoSQL
前端uin后端php社交软件源码,快速构建属于你的交友平台
这是一款功能全面的社交软件解决方案,覆盖多种场景需求。支持即时通讯(一对一聊天、群聊、文件传输、语音/视频通话)、内容动态(发布、点赞、评论)以及红包模块(接入支付宝、微信等第三方支付)。系统采用前后端分离架构,前端基于 UniApp,后端使用 PHP 框架(如 Laravel/Symfony),配合 MySQL/Redis 和自建 Socket 服务实现高效实时通信。提供用户认证(JWT 集成)、智能匹配算法等功能,助力快速上线,显著节约开发成本。
133 1
前端uin后端php社交软件源码,快速构建属于你的交友平台
|
6月前
|
数据库连接 PHP 数据库
【YashanDB知识库】PHP使用ODBC使用数据库绑定参数功能异常
【YashanDB知识库】PHP使用ODBC使用数据库绑定参数功能异常
|
6月前
|
PHP 数据库
【YashanDB知识库】PHP使用OCI接口使用数据库绑定参数功能异常
【YashanDB知识库】PHP使用OCI接口使用数据库绑定参数功能异常
|
7月前
|
存储 小程序 前端开发
微信小程序与Java后端实现微信授权登录功能
微信小程序极大地简化了登录注册流程。对于用户而言,仅仅需要点击授权按钮,便能够完成登录操作,无需经历繁琐的注册步骤以及输入账号密码等一系列复杂操作,这种便捷的登录方式极大地提升了用户的使用体验
2263 12
|
8月前
|
存储 缓存 安全
网安入门之PHP后端基础
PHP 是一种服务器端脚本语言,广泛用于动态网站和Web应用程序开发。其文件扩展名为`.php`,支持嵌入HTML、CSS和JavaScript。PHP代码由Web服务器解析后返回给浏览器。PHP是弱类型语言,变量以`$`开头,支持字符串、整数、浮点数、布尔值、数组、对象等类型。PHP具有跨平台、开源、丰富的扩展库等特点。常用超全局变量如`$_GET`、`$_POST`、`$_SESSION`等处理用户输入和会话数据。HTTP请求方法GET和POST在数据传输方式、长度限制、安全性等方面有显著差异。
网安入门之PHP后端基础
|
10月前
|
监控 PHP Apache
优化 PHP-FPM 参数配置:实现服务器性能提升
优化PHP-FPM的参数配置可以显著提高服务器的性能和稳定性。通过合理设置 `pm.max_children`、`pm.start_servers`、`pm.min_spare_servers`、`pm.max_spare_servers`和 `pm.max_requests`等参数,并结合监控和调优措施,可以有效应对高并发和负载波动,确保Web应用程序的高效运行。希望本文提供的优化建议和配置示例能够帮助您实现服务器性能的提升。
513 3
|
10月前
|
小程序 前端开发 算法