本文目录导读:

在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}×tamp={$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×tamp=$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>
注意事项
- 签名URL必须与当前页面URL完全一致(包括后面的部分)
- access_token和jsapi_ticket需要缓存,不能每次都请求
- JS接口安全域名需要在微信公众平台配置
- 签名算法使用SHA1,参数顺序不能改变
- jsapi_ticket有效期为7200秒,需要提前刷新
错误排查
- invalid signature:检查签名URL是否与当前页面URL一致
- invalid appid:检查appid是否正确
- timeout:检查服务器时间是否偏差太大(不允许超过5分钟)
- 权限不足:检查是否开通了对应的JS接口权限
如果需要使用更稳定的请求方式,可以使用cURL代替file_get_contents,并加入错误处理和重试机制。