PHP如何输出微信JS-SDK

wen PHP项目 1

本文目录导读:

PHP如何输出微信JS-SDK

  1. 获取access_token
  2. 获取jsapi_ticket
  3. 生成签名
  4. 完整示例代码
  5. 在页面中使用
  6. 注意事项
  7. 错误排查

在PHP中输出微信JS-SDK,主要涉及以下步骤:

获取access_token

function getAccessToken($appid, $secret) {
    $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$secret}";
    $result = file_get_contents($url);
    $data = json_decode($result, true);
    return $data['access_token'];
}

获取jsapi_ticket

function getJsApiTicket($access_token) {
    $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={$access_token}&type=jsapi";
    $result = file_get_contents($url);
    $data = json_decode($result, true);
    return $data['ticket'];
}

生成签名

function getSignature($jsapi_ticket, $noncestr, $timestamp, $url) {
    $string = "jsapi_ticket={$jsapi_ticket}&noncestr={$noncestr}&timestamp={$timestamp}&url={$url}";
    return sha1($string);
}

完整示例代码

class WechatJsSdk {
    private $appid;
    private $secret;
    public function __construct($appid, $secret) {
        $this->appid = $appid;
        $this->secret = $secret;
    }
    // 获取签名包
    public function getSignPackage() {
        $jsapiTicket = $this->getJsApiTicket();
        $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&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;
    }
    // 获取jsapi_ticket
    private function getJsApiTicket() {
        // 缓存到文件中,7200秒有效
        $ticketFile = 'jsapi_ticket.json';
        if (file_exists($ticketFile)) {
            $data = json_decode(file_get_contents($ticketFile), true);
            if ($data['expire_time'] > time()) {
                return $data['ticket'];
            }
        }
        $accessToken = $this->getAccessToken();
        $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={$accessToken}&type=jsapi";
        $result = file_get_contents($url);
        $data = json_decode($result, true);
        if ($data['errcode'] == 0) {
            // 保存到文件
            $cache = array(
                'ticket' => $data['ticket'],
                'expire_time' => time() + 7000 // 提前200秒过期
            );
            file_put_contents($ticketFile, json_encode($cache));
            return $data['ticket'];
        }
        return false;
    }
    // 获取access_token
    private function getAccessToken() {
        // 缓存到文件中,7200秒有效
        $tokenFile = 'access_token.json';
        if (file_exists($tokenFile)) {
            $data = json_decode(file_get_contents($tokenFile), true);
            if ($data['expire_time'] > time()) {
                return $data['access_token'];
            }
        }
        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->appid}&secret={$this->secret}";
        $result = file_get_contents($url);
        $data = json_decode($result, true);
        if (isset($data['access_token'])) {
            // 保存到文件
            $cache = array(
                'access_token' => $data['access_token'],
                'expire_time' => time() + 7000 // 提前200秒过期
            );
            file_put_contents($tokenFile, json_encode($cache));
            return $data['access_token'];
        }
        return false;
    }
}

在页面中使用

// 初始化
$jssdk = new WechatJsSdk('your_appid', 'your_secret');
$signPackage = $jssdk->getSignPackage();
// 输出到页面
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">微信JS-SDK Demo</title>
    <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
</head>
<body>
    <script>
        wx.config({
            debug: false, // 调试时可设为true
            appId: '<?php echo $signPackage["appId"];?>',
            timestamp: <?php echo $signPackage["timestamp"];?>,
            nonceStr: '<?php echo $signPackage["nonceStr"];?>',
            signature: '<?php echo $signPackage["signature"];?>',
            jsApiList: [
                'checkJsApi',
                'onMenuShareTimeline',
                'onMenuShareAppMessage',
                'chooseImage',
                'previewImage',
                'uploadImage',
                'getLocation'
                // 按需添加需要的接口
            ]
        });
        wx.ready(function () {
            // 配置成功后执行
            console.log('JS-SDK配置成功');
            // 获取地理位置
            wx.getLocation({
                type: 'wgs84',
                success: function (res) {
                    var latitude = res.latitude;
                    var longitude = res.longitude;
                    console.log(latitude, longitude);
                }
            });
        });
        wx.error(function (res) {
            // 配置失败
            console.log('JS-SDK配置失败', res.errMsg);
        });
    </script>
</body>
</html>

注意事项

  1. 签名URL必须与当前页面URL完全一致(包括后面的部分)
  2. access_token和jsapi_ticket需要缓存,不能每次都请求
  3. JS接口安全域名需要在微信公众平台配置
  4. 签名算法使用SHA1,参数顺序不能改变
  5. jsapi_ticket有效期为7200秒,需要提前刷新

错误排查

  • invalid signature:检查签名URL是否与当前页面URL一致
  • invalid appid:检查appid是否正确
  • timeout:检查服务器时间是否偏差太大(不允许超过5分钟)
  • 权限不足:检查是否开通了对应的JS接口权限

如果需要使用更稳定的请求方式,可以使用cURL代替file_get_contents,并加入错误处理和重试机制。

抱歉,评论功能暂时关闭!