149 lines
5.3 KiB
PHP
149 lines
5.3 KiB
PHP
<?php
|
||
namespace lib\wechat;
|
||
|
||
use Exception;
|
||
|
||
class WechatAPI
|
||
{
|
||
private $wid;
|
||
private $accessToken;
|
||
private $jsapiTicket;
|
||
|
||
public function __construct($id)
|
||
{
|
||
$this->wid = $id;
|
||
}
|
||
|
||
public function getAccessToken($force = false)
|
||
{
|
||
global $DB;
|
||
if(!empty($this->accessToken)) return $this->accessToken;
|
||
$DB->beginTransaction();
|
||
try{
|
||
$row = $DB->getRow("SELECT * FROM pre_weixin WHERE id='{$this->wid}' LIMIT 1 FOR UPDATE");
|
||
if(!$row) throw new Exception('记录不存在');
|
||
if($row['access_token'] && strtotime($row['expiretime']) - 200 >= time() && !$force){
|
||
$DB->rollback();
|
||
$this->accessToken = $row['access_token'];
|
||
return $this->accessToken;
|
||
}
|
||
$appid = $row['appid'];
|
||
$secret = $row['appsecret'];
|
||
$url = "https://api.weixin.qq.com/cgi-bin/stable_token";
|
||
$post = json_encode(['grant_type'=>'client_credential', 'appid'=>$appid, 'secret'=>$secret]);
|
||
$output = get_curl($url, $post);
|
||
$res = json_decode($output, true);
|
||
if (isset($res['access_token'])) {
|
||
$this->accessToken = $res['access_token'];
|
||
$expire_time = time() + $res['expires_in'];
|
||
$DB->exec("UPDATE pre_weixin SET access_token=:access_token,updatetime=NOW(),expiretime=:expiretime WHERE id=:id", [':access_token'=>$this->accessToken, ':expiretime'=>date("Y-m-d H:i:s", $expire_time), ':id'=>$this->wid]);
|
||
}elseif(isset($res['errmsg'])){
|
||
throw new Exception('AccessToken获取失败:'.$res['errmsg']);
|
||
}else{
|
||
throw new Exception('AccessToken获取失败');
|
||
}
|
||
$DB->commit();
|
||
return $this->accessToken;
|
||
}catch(Exception $e){
|
||
$DB->rollback();
|
||
throw $e;
|
||
}
|
||
}
|
||
|
||
public function generate_scheme($path, $query, $expire = 600)
|
||
{
|
||
$access_token = $this->getAccessToken();
|
||
$url = "https://api.weixin.qq.com/wxa/generatescheme?access_token=".$access_token;
|
||
$data = ['jump_wxa'=>['path'=>$path, 'query'=>$query]];
|
||
if($expire>0){
|
||
$data['is_expire'] = true;
|
||
$data['expire_time'] = time()+$expire;
|
||
}
|
||
$output = get_curl($url, json_encode($data));
|
||
$res = json_decode($output, true);
|
||
if ($res && $res['errcode'] == 0) {
|
||
return $res['openlink'];
|
||
}else{
|
||
throw new Exception('urlscheme生成失败:'.$res['errmsg']);
|
||
}
|
||
}
|
||
|
||
//发送微信公众号模板消息
|
||
public function sendTemplateMessage($openid, $template_id, $jumpurl, $data){
|
||
$access_token = $this->getAccessToken();
|
||
$url = 'https://api.weixin.qq.com/cgi-bin/message/template/send?access_token='.$access_token;
|
||
$post = [
|
||
'touser' => $openid,
|
||
'template_id' => $template_id,
|
||
'url' => $jumpurl,
|
||
'data' => $data
|
||
];
|
||
$response = get_curl($url, json_encode($post));
|
||
$res = json_decode($response, true);
|
||
if ($res && $res['errcode'] == 0) {
|
||
return true;
|
||
}else{
|
||
throw new Exception('模板消息发送失败:'.$res['errmsg']);
|
||
}
|
||
}
|
||
|
||
public function getJsapiTicket($force = false)
|
||
{
|
||
global $CACHE;
|
||
if(!empty($this->jsapiTicket)) return $this->jsapiTicket;
|
||
|
||
$cachekey = 'wx_jsapi_ticket_'.$this->wid;
|
||
$row = $CACHE->read($cachekey);
|
||
if($row){
|
||
$row = unserialize($row);
|
||
if($row['ticket'] && strtotime($row['expiretime']) - 200 >= time() && !$force){
|
||
$this->jsapiTicket = $row['ticket'];
|
||
return $this->jsapiTicket;
|
||
}
|
||
}
|
||
|
||
$access_token = $this->getAccessToken();
|
||
$url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token='.$access_token.'&type=jsapi';
|
||
$output = get_curl($url);
|
||
$res = json_decode($output, true);
|
||
if (isset($res['ticket'])) {
|
||
$this->jsapiTicket = $res['ticket'];
|
||
$expire_time = time() + $res['expires_in'];
|
||
$CACHE->save($cachekey, ['ticket'=>$this->jsapiTicket, 'expiretime'=>date("Y-m-d H:i:s", $expire_time)], $res['expires_in']);
|
||
}elseif(isset($res['errmsg'])){
|
||
throw new Exception('JsapiTicket获取失败:'.$res['errmsg']);
|
||
}else{
|
||
throw new Exception('JsapiTicket获取失败');
|
||
}
|
||
}
|
||
|
||
public function getJsapiConfig($appid, $url, $jsApiList, $debug = false)
|
||
{
|
||
$ticket = $this->getJsapiTicket();
|
||
$data = [
|
||
'jsapi_ticket' => $ticket,
|
||
'timestamp' => time(),
|
||
'noncestr' => random(16),
|
||
'url' => $url
|
||
];
|
||
$config = [
|
||
'debug' => $debug,
|
||
'appId' => $appid,
|
||
'timestamp' => $data['timestamp'],
|
||
'nonceStr' => $data['noncestr'],
|
||
'signature' => $this->getSignature($data),
|
||
'jsApiList' => $jsApiList
|
||
];
|
||
return $config;
|
||
}
|
||
|
||
public function getSignature($data)
|
||
{
|
||
ksort($data);
|
||
$params = array();
|
||
foreach ($data as $key => $value) {
|
||
$params[] = "{$key}={$value}";
|
||
}
|
||
return sha1(join('&', $params));
|
||
}
|
||
} |