微信分享:后端参数获取PHP实现-阿里云开发者社区

开发者社区> 开发者小助手-bz> 正文

微信分享:后端参数获取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>



版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
9998 0
js之获取url查询参数
js之获取url查询参数
4832 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
13793 0
Javascript获取地址栏参数值
采用正则表达式获取地址栏参数: function GetQueryString(name) { var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)"); var r = window.
494 0
C#分析URL参数获取参数和值得对应列表(一)
C#操作Url参数 http://www.cnblogs.com/RobotH/archive/2008/11/17/1335322.html 用 C# 分析 URL 中的参数信息 http://www.
703 0
1569
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载