|
@@ -32,188 +32,303 @@ class Wechat
|
|
|
private $project;
|
|
|
|
|
|
/**
|
|
|
- * 构造函数 初始化
|
|
|
- *
|
|
|
- * @return mixed
|
|
|
- */
|
|
|
- public function __construct($type = 'component', $project = false)
|
|
|
+ * 构造函数 初始化
|
|
|
+ *
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
+ public function __construct($type = 1, $project = false)
|
|
|
{
|
|
|
- $this->config = Dever::config('sign')->cAll;
|
|
|
-
|
|
|
+ $this->config = Dever::config('wechat')->cAll;
|
|
|
+
|
|
|
if (!$project) {
|
|
|
- $project = Dever::input('project', 1);
|
|
|
+ $appid = Dever::input('appid');
|
|
|
+ if ($appid) {
|
|
|
+ $project = Dever::db('main/project')->one(array('option_type' => $type, 'option_appid' => $appid));
|
|
|
+ }
|
|
|
+ if (!$project) {
|
|
|
+ $project = Dever::input('project', 1);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if (!$project) {
|
|
|
Dever::alert('project is not exits!');
|
|
|
}
|
|
|
|
|
|
+ if (is_numeric($project)) {
|
|
|
+ $project = Dever::db('main/project')->one($project);
|
|
|
+ }
|
|
|
+
|
|
|
$this->project = $project;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 获取当前站点的配置
|
|
|
- *
|
|
|
- * @return mixed
|
|
|
- */
|
|
|
+ * 获取当前站点的配置
|
|
|
+ *
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
public function project()
|
|
|
{
|
|
|
return $this->project;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 获取当前站点的配置
|
|
|
- *
|
|
|
- * @return mixed
|
|
|
- */
|
|
|
+ * 获取当前基本的配置
|
|
|
+ *
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
public function config()
|
|
|
{
|
|
|
- return $this->config['accessToken'][$this->project];
|
|
|
+ return $this->config;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
- * 获取签名信息
|
|
|
- *
|
|
|
- * @return mixed
|
|
|
- */
|
|
|
- public function get($url)
|
|
|
+ * 更新数据库
|
|
|
+ *
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
+ private function save($type = 'ticket', $value, $expires = false, $interval = 2000)
|
|
|
{
|
|
|
- $ticket = $this->ticket($this->token());
|
|
|
-
|
|
|
- if (!$ticket) {
|
|
|
- $return['status'] = 0;
|
|
|
- $return['msg'] = 'error';
|
|
|
+ if (strpos($type, '.')) {
|
|
|
+ $temp = explode('.', $type);
|
|
|
+ $table = 'main/' . $temp[1];
|
|
|
} else {
|
|
|
- $timestamp = time();
|
|
|
- $nonce = $this->nonce();
|
|
|
- $signature = $this->signature($ticket, $url, $timestamp, $nonce);
|
|
|
- $return = array
|
|
|
- (
|
|
|
- 'appId' => $this->config['accessToken'][$this->project]['appid'],
|
|
|
- 'timestamp' => $timestamp,
|
|
|
- 'nonceStr' => $nonce,
|
|
|
- 'signature' => $signature,
|
|
|
- 'status' => 1,
|
|
|
- 'msg' => '成功',
|
|
|
- );
|
|
|
+ $table = 'main/' . $type;
|
|
|
+ }
|
|
|
+ $db = Dever::db($table);
|
|
|
+ $where['option_project_id'] = $this->project['id'];
|
|
|
+ $info = $db->one($where);
|
|
|
+
|
|
|
+ $update = false;
|
|
|
+
|
|
|
+ if ($info && time() - $info['mdate'] >= $info['expires']) {
|
|
|
+ $update = true;
|
|
|
+ } elseif($info) {
|
|
|
+ return $info['value'];
|
|
|
+ }
|
|
|
+ if (!$info) {
|
|
|
+ $update = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!$value) {
|
|
|
+ $value = $this->param($type);
|
|
|
+ }
|
|
|
+
|
|
|
+ $data = array();
|
|
|
+ if (is_array($value) || (is_string($value) && strstr($value, 'http://'))) {
|
|
|
+ $result = $this->curl(false, $value);
|
|
|
+
|
|
|
+ $key = $type;
|
|
|
+ if ($type == 'token') {
|
|
|
+ $key = 'access_token';
|
|
|
+ }
|
|
|
+ if ($result && isset($result[$key])) {
|
|
|
+ $data = $result;
|
|
|
+ $data['value'] = $result[$key];
|
|
|
+ $data['expires'] = $result['expires_in'];
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ $data['value'] = $value;
|
|
|
+ $data['expires'] = $expires;
|
|
|
}
|
|
|
|
|
|
- Dever::out($return);
|
|
|
+ if ($data && isset($data['value']) && $data['value']) {
|
|
|
+ $data['project_id'] = $this->project['id'];
|
|
|
+ $expires = $data['expires'] - $interval;
|
|
|
+ if ($expires <= 0) {
|
|
|
+ $data['expires'] = $data['expires'] - 300;
|
|
|
+ } else {
|
|
|
+ $data['expires'] = $expires;
|
|
|
+ }
|
|
|
+ if ($update == true) {
|
|
|
+ $data['where_id'] = $info['id'];
|
|
|
+ $db->update($data);
|
|
|
+ } else {
|
|
|
+ $db->insert($data);
|
|
|
+ }
|
|
|
+ } elseif($info['value']) {
|
|
|
+ $data['value'] = $info['value'];
|
|
|
+ }
|
|
|
+
|
|
|
+ return $data['value'];
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
/**
|
|
|
- * 获取nonce
|
|
|
- *
|
|
|
- * @return mixed
|
|
|
- */
|
|
|
- private function nonce()
|
|
|
+ * 获取最新的token
|
|
|
+ *
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
+ public function token($value = false, $expires = false, $interval = 2000)
|
|
|
{
|
|
|
- return substr(md5(microtime()), rand(10, 15));
|
|
|
+ return $this->save('token', $value, $expires, $interval);
|
|
|
}
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取accessToken
|
|
|
- *
|
|
|
- * @return mixed
|
|
|
- */
|
|
|
- public function token($state = 1)
|
|
|
- {
|
|
|
- $url = $this->config['accessToken']['url'] . '&' . http_build_query($this->config['accessToken'][$this->project]);
|
|
|
-
|
|
|
- $where['where_project'] = $this->project;
|
|
|
- $info = Dever::load('main/token-info', $where);
|
|
|
|
|
|
- $request = $update = false;
|
|
|
-
|
|
|
- if ($info && ((time() - $info['mdate'] >= $info['expires_in']) || $state == 2)) {
|
|
|
- $request = $update = true;
|
|
|
- } elseif ($info) {
|
|
|
- return $info['token'];
|
|
|
+ /**
|
|
|
+ * 获取最新的ticket
|
|
|
+ *
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
+ public function ticket($value = false, $expires = false, $interval = 200)
|
|
|
+ {
|
|
|
+ return $this->save('ticket', $value, $expires, $interval);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取最新的oauth token
|
|
|
+ *
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
+ public function oauth($value = false, $expires = false, $interval = 200)
|
|
|
+ {
|
|
|
+ return $this->save('oauth.oauth', $value, $expires, $interval);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取最新的code
|
|
|
+ *
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
+ public function code($value = false, $expires = false, $interval = 200)
|
|
|
+ {
|
|
|
+ return $this->save('oauth.code', $value, $expires, $interval);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取最新的oauth login地址
|
|
|
+ *
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
+ public function login($callback = false, $code = false, $location = true)
|
|
|
+ {
|
|
|
+ if (!$code) {
|
|
|
+ $code = $this->code();
|
|
|
}
|
|
|
- if (!$info) {
|
|
|
- $request = true;
|
|
|
- $update = false;
|
|
|
+ $callback = urlencode(Dever::url($callback));
|
|
|
+ $config = $this->param('oauth.login', array('code' => $code, 'redirect' => $callback));
|
|
|
+ $url = $config['url'] . http_build_query($config['param']);
|
|
|
+ if ($location == true) {
|
|
|
+ Dever::location($url);
|
|
|
}
|
|
|
-
|
|
|
- if ($request == true) {
|
|
|
- $data = json_decode(Dever::curl($url), true);
|
|
|
-
|
|
|
- if ($data && isset($data['access_token'])) {
|
|
|
- $data['expires_in'] = $data['expires_in'] - 2000;
|
|
|
- if ($update == true) {
|
|
|
- $set['set_project'] = $this->project;
|
|
|
- $set['set_token'] = $data['access_token'];
|
|
|
- $set['set_expires_in'] = $data['expires_in'];
|
|
|
- $set['where_id'] = $info['id'];
|
|
|
- Dever::load('main/token-update', $set);
|
|
|
- } else {
|
|
|
- $insert['add_project'] = $this->project;
|
|
|
- $insert['add_token'] = $data['access_token'];
|
|
|
- $insert['add_expires_in'] = $data['expires_in'];
|
|
|
- Dever::load('main/token-insert', $insert);
|
|
|
- }
|
|
|
-
|
|
|
- return $data['access_token'];
|
|
|
+ return $url;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从wechat获取数据
|
|
|
+ *
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
+ public function curl($method, $param = array())
|
|
|
+ {
|
|
|
+ if (is_string($param)) {
|
|
|
+ $result = json_decode(Dever::curl($param), true);
|
|
|
+ } else {
|
|
|
+ if ($method) {
|
|
|
+ $param = $this->param($method, $param);
|
|
|
}
|
|
|
+
|
|
|
+ $result = json_decode(Dever::curl($param['url'], $param['param'], $param['method'], $param['json']), true);
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取ticket
|
|
|
- *
|
|
|
- * @return mixed
|
|
|
- */
|
|
|
- private function ticket($token)
|
|
|
- {
|
|
|
- $url = $this->config['ticket'] . $token;
|
|
|
-
|
|
|
- $where['where_project'] = $this->project;
|
|
|
- $info = Dever::load('main/ticket-info', $where);
|
|
|
-
|
|
|
- $request = $update = false;
|
|
|
-
|
|
|
- if ($info && time() - $info['mdate'] >= $info['expires_in']) {
|
|
|
- $request = $update = true;
|
|
|
- } elseif($info) {
|
|
|
- return $info['ticket'];
|
|
|
+ if (isset($result['errcode']) && $result['errcode'] != 0) {
|
|
|
+ $result = $param + $result;
|
|
|
+ Dever::log($result);
|
|
|
+ Dever::alert(json_encode($result));
|
|
|
}
|
|
|
- if (!$info) {
|
|
|
- $request = true;
|
|
|
- $update = false;
|
|
|
+
|
|
|
+ if (isset($param['response'])) {
|
|
|
+ foreach ($param['response'] as $k => $v) {
|
|
|
+ if (strpos($k, '.')) {
|
|
|
+ $temp = explode('.', $k);
|
|
|
+ if (isset($result[$temp[0]][$temp[1]])) {
|
|
|
+ $result[$v] = $result[$temp[0]][$temp[1]];
|
|
|
+ }
|
|
|
+ } elseif (isset($result[$k])) {
|
|
|
+ $result[$v] = $result[$k];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return $result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 拼装wechat需要的参数
|
|
|
+ *
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
+ public function param($method, $param = array())
|
|
|
+ {
|
|
|
+ if (strpos($method, '.')) {
|
|
|
+ $temp = explode('.', $method);
|
|
|
+ $config = $this->config[$temp[0]][$temp[1]];
|
|
|
+ } else {
|
|
|
+ if (!isset($this->config[$method])) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ $config = $this->config[$method];
|
|
|
}
|
|
|
|
|
|
- if ($request == true) {
|
|
|
- $data = json_decode(Dever::curl($url), true);
|
|
|
-
|
|
|
- if ($data && isset($data['ticket'])) {
|
|
|
- $data['expires_in'] = $data['expires_in'] - 2000;
|
|
|
- if ($update == true) {
|
|
|
- $set['set_project'] = $this->project;
|
|
|
- $set['set_ticket'] = $data['ticket'];
|
|
|
- $set['set_expires_in'] = $data['expires_in'];
|
|
|
- $set['where_name'] = $this->project;
|
|
|
- Dever::load('main/ticket-update', $set);
|
|
|
- } else {
|
|
|
- $insert['add_project'] = $this->project;
|
|
|
- $insert['add_ticket'] = $data['ticket'];
|
|
|
- $insert['add_expires_in'] = $data['expires_in'];
|
|
|
- Dever::load('main/ticket-insert', $insert);
|
|
|
- }
|
|
|
-
|
|
|
- return $data['ticket'];
|
|
|
+ $param = $this->project + $param;
|
|
|
+
|
|
|
+ foreach ($config['param'] as $k => $v) {
|
|
|
+ if ($v == 'token') {
|
|
|
+ $config['url'] .= $k . '=' . $this->token();
|
|
|
+ unset($config['param'][$k]);
|
|
|
+ } elseif ($v == 'ticket') {
|
|
|
+ $config['param'][$k] = $this->ticket();
|
|
|
+ } elseif ($v == 'code') {
|
|
|
+ $config['param'][$k] = $this->code();
|
|
|
+ }elseif ($v == 'oauth') {
|
|
|
+ $config['param'][$k] = $this->oauth();
|
|
|
+ } elseif (isset($param[$v]) && $param[$v]) {
|
|
|
+ $config['param'][$k] = $param[$v];
|
|
|
+ } elseif($v) {
|
|
|
+ $config['param'][$k] = $v;
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取signature
|
|
|
- *
|
|
|
- * @return mixed
|
|
|
- */
|
|
|
- private function signature($ticket, $url, $timestamp, $noncestr)
|
|
|
- {
|
|
|
+
|
|
|
+ $config['json'] = isset($config['json']) && $config['json'] ? true : false;
|
|
|
+
|
|
|
+ return $config;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 消息解密
|
|
|
+ *
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
+ public function decode($sign, $timestamp, $nonce, $encrypt)
|
|
|
+ {
|
|
|
+ include(DEVER_PROJECT_PATH . 'example/wxBizMsgCrypt.php');
|
|
|
+ $crypt = new \WXBizMsgCrypt($this->project['token'], $this->project['key'], $this->project['appid']);
|
|
|
+
|
|
|
+ $format = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%s]]></Encrypt></xml>";
|
|
|
+ $xml = sprintf($format, $encrypt);
|
|
|
+
|
|
|
+ $result = '';
|
|
|
+ $code = $crypt->decryptMsg($sign, $timestamp, $nonce, $xml, $result);
|
|
|
+ if ($code == 0) {
|
|
|
+ libxml_disable_entity_loader(true);
|
|
|
+ $result = (array) simplexml_load_string($result, 'SimpleXMLElement', LIBXML_NOCDATA);
|
|
|
+ }
|
|
|
+
|
|
|
+ return $result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取nonce
|
|
|
+ *
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
+ public function nonce()
|
|
|
+ {
|
|
|
+ return substr(md5(microtime()), rand(10, 15));
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取signature
|
|
|
+ *
|
|
|
+ * @return mixed
|
|
|
+ */
|
|
|
+ public function signature($ticket, $url, $timestamp, $noncestr)
|
|
|
+ {
|
|
|
$info = array();
|
|
|
$info['jsapi_ticket'] = $ticket;
|
|
|
$info['url'] = $url;
|
|
@@ -222,15 +337,6 @@ class Wechat
|
|
|
ksort($info);
|
|
|
|
|
|
$signature_string = substr(http_build_query($info), 0, -1);
|
|
|
-
|
|
|
- /*
|
|
|
- foreach($info as $k => $v)
|
|
|
- {
|
|
|
- $signature_string .= $k . '=' . $v . '&';
|
|
|
- }
|
|
|
-
|
|
|
- $signature_string = substr($signature_string, 0, -1);
|
|
|
- */
|
|
|
return sha1($signature_string);
|
|
|
}
|
|
|
}
|