Common

namespace Proxy\Action;

use Think\Action;

use Vendor\Func\Red;

class CommonAction extends Action

{

public $red;

public function _initialize(){

$this->red = Red::create();

header('Content-type: text/html; charset=utf-8');

}

/**

* 错误的json

* @param $code

* @param string $message

* @param array $data

*/

public function jsonError($code, $message = 'error', $data = [])

{

$returnData = [

'code' => $code,

'message' => $message,

'data' => $data

];

header('Content-type:application/json;charset=utf-8');

echo json_encode($returnData);

exit;

}

/**

* 正确的json

* @param int $code

* @param string $message

* @param array $data

*/

public function jsonSuccess($code = 1, $message = 'success', $data = [])

{

$returnData = [

'code' => $code,

'message' => $message,

'data' => $data

];

header('Content-type:application/json;charset=utf-8');

echo json_encode($returnData);

exit;

}

/**

* 设置Redis

* @param $k

* @param $v

* @param int $expires

* @return mixed

*/

public function setCache($k, $v, $expires = -1)

{

if ($expires === -1) {

return $this->red->set($k, $v);

} else {

return $this->red->setex($k, $expires, $v);

}

}

/**

* 获取Redis

* @param $k

* @return mixed

*/

public function getCache($k)

{

return $this->red->get($k);

}

/**

* 删除Redis

* @param $k

* @return mixed

*/

public function delCache($k)

{

return $this->red->delete($k);

}

/**

* 获取过期时间

* @param $k

* @return bool

*/

public function getCacheTtl($k)

{

$ttl = $this->red->ttl($k);

if ($ttl != '-2') {

return $ttl;

} else {

return false;

}

}

/**

* 检查是否存在

* @param $k

* @return mixed

*/

public function cacheExists($k)

{

return $this->red->exists($k);

}

}

AccessToken

namespace Proxy\Action;

use Vendor\Func\Http;

/***

* 基础支持的access_token,每日两千次

* @package Proxy\Action

*/

class AccessTokenAction extends CommonAction

{

const API_TOKEN = 'https://api.weixin.qq.com/cgi-bin/token';

const API_TICKET = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket';

const TOKEN_EXPIRES = 1500;

const TICKET_EXPIRES = 1500;

protected $access_token_key = ''; // access_token Redis 键值名

protected $js_ticket_key = ''; // 凭证 Redis 键值名

public function __construct()

{

parent::__construct();

$this->access_token_key = C('WX_APP_ID').':access_token';

$this->js_ticket_key = C('WX_APP_ID').':js_ticket';

}

/**

* 获取全局access_token

*/

public function get()

{

// step1 判是存在

$exists = $this->cacheExists($this->access_token_key);

// step2 是否强制刷新或者已过期

if ((isset($_GET['flush']) & $_GET['flush']) || !$exists) {

$data = $this->reload();

} else {

$data = [

'access_token' => $this->getCache($this->access_token_key),

'expires_in' => $this->getCacheTtl($this->access_token_key)

];

}

if (!$data['access_token']) {

$this->ajaxReturn($this->jsonError(10002, '接口请求失败'));

}

$this->ajaxReturn($this->jsonSuccess(1, '成功', $data));

}

/**

* 公众号用于调用微信JS接口的临时票据

* @return bool

*/

public function jsTicket()

{

// step1 判是存在

$exists = $this->cacheExists($this->js_ticket_key);

if (!$exists) {

// 获取token

$token = $this->getCache($this->access_token_key);

setlog($token,[],'token');

// 如果token不存在,重新生成

if (!$token) {

// 重新加载一次Token

$this->reload();

$token = $this->getCache($this->access_token_key);

}

$params = [

'access_token' => $token,

'type' => 'jsapi',

];

$data = Http::newDoGet(self::API_TICKET, $params);

$data = json_decode($data, true);

if ((int)$data['errcode'] !== 0) {

$this->delCache($this->access_token_key);

return false;

}

// 减少1500秒过期时间,提前过期

$this->setCache($this->js_ticket_key, $data['ticket'], $data['expires_in'] - self::TICKET_EXPIRES);

} else {

$data['ticket'] = $this->getCache($this->js_ticket_key);

}

return $data['ticket'];

}

/**

* 获取JS-SDK配置信息

*/

public function getConfig()

{

if (!isset($_GET['uri'])) {

$this->ajaxReturn($this->jsonError(0, '参数错误'));

}

$url = $_GET['uri'];

$ticket = $this->jsTicket();

setlog($ticket,[],'ticket');

while (!$ticket) {

$this->reload();

$ticket = $this->jsTicket();

}

$data = [

'jsapi_ticket' => $ticket,

'nonceStr' => (string)mt_rand(),

'timestamp' => time(),

'url' => $url

];

$sign = $this->getSign($data);

$data['signature'] = $sign;

$data['appId'] = C('WX_APP_ID');

$this->ajaxReturn($this->jsonSuccess(1, '成功', $data));

}

/**

* 重新载入 access_token

*/

protected function reload()

{

if ($this->cacheExists($this->access_token_key)) {

$data = [

'access_token' => $this->getCache($this->access_token_key),

'expires_in' => $this->getCacheTtl($this->access_token_key)

];

return $data;

}

$params = [

'grant_type' => 'client_credential',

'appid' => C('WX_APP_ID'),

'secret' => C('WX_APP_SECRET')

];

$data = Http::newDoGet(self::API_TOKEN, $params);

if (!$data) {

$this->ajaxReturn($this->jsonError(10002, '接口请求失败'));

}

$data = json_decode($data, true);

if (isset($data['errcode'])) {

$this->ajaxReturn($this->jsonError($data['errcode']), $data['errmsg']);

}

$this->setCache($this->access_token_key, $data['access_token'], $data['expires_in'] - self::TOKEN_EXPIRES);

return $data;

}

/**

* 签名算法

* @param $data

* @return string

*/

protected function getSign($data)

{

$str = '';

foreach ($data as $k => $v) {

$str .= strtolower($k) .'='.$v;

$str .= '&';

}

$str = trim($str, '&');

$str = sha1($str);

return $str;

}

}

查看原文