dever 6 years ago
commit
4de72a5da5
9 changed files with 1281 additions and 0 deletions
  1. 99 0
      database/code.php
  2. 103 0
      database/log.php
  3. 135 0
      database/oauth.php
  4. 156 0
      database/project.php
  5. 99 0
      database/ticket.php
  6. 99 0
      database/token.php
  7. 8 0
      index.php
  8. 82 0
      lib/Core.php
  9. 500 0
      lib/Wechat.php

+ 99 - 0
database/code.php

@@ -0,0 +1,99 @@
+<?php
+/**
+ * code 一般用于保存oauth code
+ */
+
+return array
+(
+	# 表名
+	'name' => 'code',
+	# 显示给用户看的名称
+	'lang' => 'code数据表',
+	'menu' => false,
+	# 数据结构
+	'struct' => array
+	(
+		'id' 		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> 'ID',
+			'default' 	=> '',
+			'desc' 		=> '',
+			'match' 	=> 'is_numeric',
+			'search'	=> 'order',
+			'list'		=> true,
+		),
+
+		'project_id'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '项目',
+			'default' 	=> '',
+			'desc' 		=> '请输入项目',
+			'match' 	=> 'is_numeric',
+			//'search'	=> 'order,fulltext',
+			'update'	=> 'text',
+			'list'		=> '{project_id} > 0 ? Dever::load("main/project-one#name", {project_id}) : "未知"',
+		),
+		
+		'value'		=> array
+		(
+			'type' 		=> 'varchar-255',
+			'name' 		=> 'code标识',
+			'default' 	=> '',
+			'desc' 		=> 'code标识',
+			'match' 	=> 'is_string',
+			'update'	=> 'text',
+			'list'		=> true,
+			'modal'		=> '查看',
+		),
+		
+		'expires'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '过期时间',
+			'default' 	=> '',
+			'desc' 		=> '过期时间',
+			'match' 	=> 'is_numeric',
+			'update'	=> 'text',
+			'list'		=> true,
+		),
+		
+		'mdate'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '更新时间',
+			'match' 	=> array('is_numeric', time()),
+			'desc' 		=> '',
+			'list'		=> 'date("Y-m-d H:i:s", {mdate})',
+		),
+		
+		'state'		=> array
+		(
+			'type' 		=> 'tinyint-1',
+			'name' 		=> '状态',
+			'default' 	=> '1',
+			'desc' 		=> '请选择状态',
+			'match' 	=> 'is_numeric',
+		),
+		
+		'cdate'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '录入时间',
+			'match' 	=> array('is_numeric', time()),
+			'desc' 		=> '',
+			# 只有insert时才生效
+			'insert'	=> true,
+		),
+	),
+
+	//'top' => 'main/project_id',
+
+	'manage' => array
+	(
+		'delete' => false,
+		'insert' => false,
+		'edit' => false,
+	),
+);

+ 103 - 0
database/log.php

@@ -0,0 +1,103 @@
+<?php
+/**
+ * tester
+ */
+
+
+return array
+(
+	# 表名
+	'name' => 'log',
+	# 显示给用户看的名称
+	'lang' => '请求日志',
+	'order' => 1,
+	# 数据结构
+	'struct' => array
+	(
+		'id' 		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> 'ID',
+			'default' 	=> '',
+			'desc' 		=> '',
+			'match' 	=> 'is_numeric',
+			'search'	=> 'order',
+			'list'		=> true,
+		),
+
+		'name'		=> array
+		(
+			'type' 		=> 'varchar-100',
+			'name' 		=> '请求名称',
+			'default' 	=> '',
+			'desc' 		=> '请求名称',
+			'match' 	=> 'option',
+			'update'	=> 'textarea',
+			'list'		=> true,
+		),
+
+		'url'		=> array
+		(
+			'type' 		=> 'varchar-255',
+			'name' 		=> '请求地址',
+			'default' 	=> '',
+			'desc' 		=> '请求地址',
+			'match' 	=> 'option',
+			'update'	=> 'textarea',
+			'list'		=> true,
+			'modal'		=> '查看详情',
+
+		),
+
+		'param'		=> array
+		(
+			'type' 		=> 'text-255',
+			'name' 		=> '请求信息',
+			'default' 	=> '',
+			'desc' 		=> '请求信息',
+			'match' 	=> 'option',
+			'update'	=> 'textarea',
+			'list'		=> true,
+			'modal'		=> '查看详情',
+		),
+
+		'result'		=> array
+		(
+			'type' 		=> 'longtext',
+			'name' 		=> '微信返回信息',
+			'default' 	=> '',
+			'desc' 		=> '微信返回信息',
+			'match' 	=> 'option',
+			'update'	=> 'textarea',
+			'list'		=> true,
+			'modal'		=> '查看详情',
+		),
+		
+		'state'		=> array
+		(
+			'type' 		=> 'tinyint-1',
+			'name' 		=> '状态',
+			'default' 	=> '1',
+			'desc' 		=> '请选择状态',
+			'match' 	=> 'is_numeric',
+		),
+
+		'cdate'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '录入时间',
+			'match' 	=> array('is_numeric', time()),
+			'desc' 		=> '',
+			# 只有insert时才生效
+			'insert'	=> true,
+			'list'		=> 'date("Y-m-d H:i:s", {cdate})',
+		),
+	),
+
+	'manage' => array
+	(
+		'delete' => false,
+		'insert' => false,
+		'edit' => false,
+	),
+);

+ 135 - 0
database/oauth.php

@@ -0,0 +1,135 @@
+<?php
+/**
+ * token
+ */
+
+return array
+(
+	# 表名
+	'name' => 'oauth',
+	# 显示给用户看的名称
+	'lang' => 'oauth数据表',
+	'menu' => false,
+	# 数据结构
+	'struct' => array
+	(
+		'id' 		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> 'ID',
+			'default' 	=> '',
+			'desc' 		=> '',
+			'match' 	=> 'is_numeric',
+			'search'	=> 'order',
+			'list'		=> true,
+		),
+
+		'project_id'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '项目',
+			'default' 	=> '',
+			'desc' 		=> '请输入项目',
+			'match' 	=> 'is_numeric',
+			//'search'	=> 'order,fulltext',
+			'update'	=> 'text',
+			'list'		=> '{project_id} > 0 ? Dever::load("main/project-one#name", {project_id}) : "未知"',
+		),
+
+		'openid'		=> array
+		(
+			'type' 		=> 'varchar-60',
+			'name' 		=> '用户id-如果是第三方平台,则为appid',
+			'default' 	=> '',
+			'desc' 		=> '用户id',
+			'match' 	=> 'is_string',
+			//'search'	=> 'order,fulltext',
+			'update'	=> 'text',
+			'list'		=> true,
+		),
+
+		'unionid'		=> array
+		(
+			'type' 		=> 'varchar-60',
+			'name' 		=> '用户唯一id-如果是第三方平台,则为appid',
+			'default' 	=> '',
+			'desc' 		=> '用户唯一id',
+			'match' 	=> 'is_string',
+			//'search'	=> 'order,fulltext',
+			'update'	=> 'text',
+			'list'		=> true,
+		),
+		
+		'value'		=> array
+		(
+			'type' 		=> 'varchar-255',
+			'name' 		=> 'token标识',
+			'default' 	=> '',
+			'desc' 		=> 'token标识',
+			'match' 	=> 'is_string',
+			'update'	=> 'text',
+			'list'		=> true,
+			'modal'		=> '查看',
+		),
+
+		'refresh'		=> array
+		(
+			'type' 		=> 'varchar-255',
+			'name' 		=> 'refresh token标识',
+			'default' 	=> '',
+			'desc' 		=> 'refresh token标识',
+			'match' 	=> 'is_string',
+			'update'	=> 'text',
+			'list'		=> true,
+			'modal'		=> '查看',
+		),
+		
+		'expires'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '过期时间',
+			'default' 	=> '',
+			'desc' 		=> '过期时间',
+			'match' 	=> 'is_numeric',
+			'update'	=> 'text',
+			'list'		=> true,
+		),
+		
+		'mdate'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '更新时间',
+			'match' 	=> array('is_numeric', time()),
+			'desc' 		=> '',
+			'list'		=> 'date("Y-m-d H:i:s", {mdate})',
+		),
+		
+		'state'		=> array
+		(
+			'type' 		=> 'tinyint-1',
+			'name' 		=> '状态',
+			'default' 	=> '1',
+			'desc' 		=> '请选择状态',
+			'match' 	=> 'is_numeric',
+		),
+		
+		'cdate'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '录入时间',
+			'match' 	=> array('is_numeric', time()),
+			'desc' 		=> '',
+			# 只有insert时才生效
+			'insert'	=> true,
+		),
+	),
+
+	//'top' => 'main/project_id',
+
+	'manage' => array
+	(
+		'delete' => false,
+		'insert' => false,
+		'edit' => false,
+	),
+);

+ 156 - 0
database/project.php

@@ -0,0 +1,156 @@
+<?php
+
+$type = array
+(
+	//1 => '保留',
+	2 => '公众号',
+	3 => '小程序',
+	4 => '小游戏',
+	5 => '第三方平台',
+	6 => '开发者',
+	7 => '有赞',
+);
+
+return array
+(
+	# 表名
+	'name' => 'project',
+	# 显示给用户看的名称
+	'lang' => '项目管理',
+	'order' => -10,
+	# 数据结构
+	'struct' => array
+	(
+		'id' 		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> 'ID',
+			'default' 	=> '',
+			'desc' 		=> '',
+			'match' 	=> 'is_numeric',
+			//'search'	=> 'order',
+			'order'		=> 'desc',
+			'list'		=> true,
+		),
+		
+		'name'		=> array
+		(
+			'type' 		=> 'varchar-60',
+			'name' 		=> '项目名称',
+			'default' 	=> '',
+			'desc' 		=> '请输入项目名称',
+			'match' 	=> 'is_string',
+			'update'	=> 'text',
+			'search'	=> 'fulltext',
+			'list'		=> true,
+		),
+
+		'type'		=> array
+		(
+			'type' 		=> 'tinyint-11',
+			'name' 		=> '项目类型',
+			'default' 	=> '1',
+			'desc' 		=> '项目类型',
+			'match' 	=> 'is_numeric',
+			'update'	=> 'select',
+			'option'	=> $type,
+			'list'		=> true,
+		),
+
+		'appid'		=> array
+		(
+			'type' 		=> 'varchar-150',
+			'name' 		=> '微信appid',
+			'default' 	=> '',
+			'desc' 		=> '请输入微信appid',
+			'match' 	=> 'is_string',
+			'search'	=> 'order,fulltext',
+			'update'	=> 'text',
+			'list'		=> 'table',
+			'modal' 	=> '详细信息',
+		),
+
+		'secret'		=> array
+		(
+			'type' 		=> 'varchar-150',
+			'name' 		=> '微信secret',
+			'default' 	=> '',
+			'desc' 		=> '请输入微信secret',
+			'match' 	=> 'is_string',
+			'search'	=> 'order,fulltext',
+			'update'	=> 'text',
+			//'list'		=> 'table',
+			//'modal' 	=> '详细信息',
+		),
+
+		'token'		=> array
+		(
+			'type' 		=> 'varchar-150',
+			'name' 		=> '通信token(注意不是access_token)',
+			'default' 	=> '',
+			'desc' 		=> '请输入通信token',
+			'match' 	=> 'option',
+			'update'	=> 'text',
+		),
+
+		'key'		=> array
+		(
+			'type' 		=> 'varchar-150',
+			'name' 		=> '消息加解密密钥',
+			'default' 	=> '',
+			'desc' 		=> '请输入消息加解密密钥',
+			'match' 	=> 'option',
+			'update'	=> 'text',
+		),
+
+		'state'		=> array
+		(
+			'type' 		=> 'tinyint-1',
+			'name' 		=> '状态',
+			'default' 	=> '1',
+			'desc' 		=> '请选择状态',
+			'match' 	=> 'is_numeric',
+		),
+		
+		'cdate'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '录入时间',
+			'match' 	=> array('is_numeric', time()),
+			'desc' 		=> '',
+			# 只有insert时才生效
+			'insert'	=> true,
+			'list'		=> 'date("Y-m-d H:i:s", {cdate})',
+		),
+	),
+	
+	'manage' => array
+	(
+		'button' => array
+		(
+			'同步小程序' => 'main/data.applet',
+		),
+	),
+
+	'top' => array
+	(
+		# 数据来源
+		'data' => 'state',
+		# 菜单名
+		'name' => '项目选择',
+		# 默认值
+		'value' => 1,
+		# 对应的字段值,设置这个之后,所有设置等于这个值的字段,都要遵循这个权限的控制
+		'key' => 'main/project_id',
+		# 本表中代表名称的字段
+		'col' => 'name',
+		# type类型字段
+		'type' => 'type',
+	),
+	
+	# request 请求接口定义
+	'request' => array
+	(
+		
+	),
+);

+ 99 - 0
database/ticket.php

@@ -0,0 +1,99 @@
+<?php
+/**
+ * ticket
+ */
+
+return array
+(
+	# 表名
+	'name' => 'ticket',
+	# 显示给用户看的名称
+	'lang' => 'ticket数据表',
+	'menu' => false,
+	# 数据结构
+	'struct' => array
+	(
+		'id' 		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> 'ID',
+			'default' 	=> '',
+			'desc' 		=> '',
+			'match' 	=> 'is_numeric',
+			'search'	=> 'order',
+			'list'		=> true,
+		),
+
+		'project_id'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '项目',
+			'default' 	=> '',
+			'desc' 		=> '请输入项目',
+			'match' 	=> 'is_numeric',
+			//'search'	=> 'order,fulltext',
+			'update'	=> 'text',
+			'list'		=> '{project_id} > 0 ? Dever::load("main/project-one#name", {project_id}) : "未知"',
+		),
+		
+		'value'		=> array
+		(
+			'type' 		=> 'varchar-255',
+			'name' 		=> 'ticket标识',
+			'default' 	=> '',
+			'desc' 		=> 'ticket标识',
+			'match' 	=> 'is_string',
+			'update'	=> 'text',
+			'list'		=> true,
+			'modal'		=> '查看',
+		),
+		
+		'expires'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '过期时间',
+			'default' 	=> '',
+			'desc' 		=> '过期时间',
+			'match' 	=> 'is_numeric',
+			'update'	=> 'text',
+			'list'		=> true,
+		),
+		
+		'mdate'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '更新时间',
+			'match' 	=> array('is_numeric', time()),
+			'desc' 		=> '',
+			'list'		=> 'date("Y-m-d H:i:s", {mdate})',
+		),
+		
+		'state'		=> array
+		(
+			'type' 		=> 'tinyint-1',
+			'name' 		=> '状态',
+			'default' 	=> '1',
+			'desc' 		=> '请选择状态',
+			'match' 	=> 'is_numeric',
+		),
+		
+		'cdate'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '录入时间',
+			'match' 	=> array('is_numeric', time()),
+			'desc' 		=> '',
+			# 只有insert时才生效
+			'insert'	=> true,
+		),
+	),
+
+	//'top' => 'main/project_id',
+
+	'manage' => array
+	(
+		'delete' => false,
+		'insert' => false,
+		'edit' => false,
+	),
+);

+ 99 - 0
database/token.php

@@ -0,0 +1,99 @@
+<?php
+/**
+ * token
+ */
+
+return array
+(
+	# 表名
+	'name' => 'token',
+	# 显示给用户看的名称
+	'lang' => 'token数据表',
+	'menu' => false,
+	# 数据结构
+	'struct' => array
+	(
+		'id' 		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> 'ID',
+			'default' 	=> '',
+			'desc' 		=> '',
+			'match' 	=> 'is_numeric',
+			'search'	=> 'order',
+			'list'		=> true,
+		),
+
+		'project_id'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '项目',
+			'default' 	=> '',
+			'desc' 		=> '请输入项目',
+			'match' 	=> 'is_numeric',
+			//'search'	=> 'order,fulltext',
+			'update'	=> 'text',
+			'list'		=> '{project_id} > 0 ? Dever::load("main/project-one#name", {project_id}) : "未知"',
+		),
+		
+		'value'		=> array
+		(
+			'type' 		=> 'varchar-255',
+			'name' 		=> 'token标识',
+			'default' 	=> '',
+			'desc' 		=> 'token标识',
+			'match' 	=> 'is_string',
+			'update'	=> 'text',
+			'list'		=> true,
+			'modal'		=> '查看',
+		),
+		
+		'expires'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '过期时间',
+			'default' 	=> '',
+			'desc' 		=> '过期时间',
+			'match' 	=> 'is_numeric',
+			'update'	=> 'text',
+			'list'		=> true,
+		),
+		
+		'mdate'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '更新时间',
+			'match' 	=> array('is_numeric', time()),
+			'desc' 		=> '',
+			'list'		=> 'date("Y-m-d H:i:s", {mdate})',
+		),
+		
+		'state'		=> array
+		(
+			'type' 		=> 'tinyint-1',
+			'name' 		=> '状态',
+			'default' 	=> '1',
+			'desc' 		=> '请选择状态',
+			'match' 	=> 'is_numeric',
+		),
+		
+		'cdate'		=> array
+		(
+			'type' 		=> 'int-11',
+			'name' 		=> '录入时间',
+			'match' 	=> array('is_numeric', time()),
+			'desc' 		=> '',
+			# 只有insert时才生效
+			'insert'	=> true,
+		),
+	),
+
+	//'top' => 'main/project_id',
+
+	'manage' => array
+	(
+		'delete' => false,
+		'insert' => false,
+		'edit' => false,
+	),
+);

+ 8 - 0
index.php

@@ -0,0 +1,8 @@
+<?php
+
+define('DEVER_APP_NAME', 'token');
+define('DEVER_APP_LANG', '微信开发管理');
+define('DEVER_APP_PATH', dirname(__FILE__) . DIRECTORY_SEPARATOR);
+define('DEVER_MANAGE_ORDER', -1);
+define('DEVER_MANAGE_ICON', 'glyphicon glyphicon-road');
+include(DEVER_APP_PATH . '../boot.php');

+ 82 - 0
lib/Core.php

@@ -0,0 +1,82 @@
+<?php
+namespace Token\Lib;
+
+use Dever;
+
+
+function callAction($send)
+{
+	if (isset($send['i']) && $send['i'] > 0) {
+		$wechat = new Wechat($send['i'], $send['a']);
+		$param = array();
+		if (!isset($send['p'])) {
+			$send['p'] = false;
+		}
+		if ($send['s']) {
+			$param = Dever::load($send['a'] . '/' . $send['s'], $send['p']);
+		}
+
+		if (isset($param['run_num']) && $param['run_num'] > 1) {
+			for ($i = 1; $i <= $param['run_num']; $i++) {
+				$result = $wechat->curl($send['t'], $param, false);
+				if ($send['e']) {
+					Dever::load($send['a'] . '/' . $send['e'], $send['i'], $result, $send['p']);
+				}
+			}
+			if ($send['e']) {
+				Dever::load($send['a'] . '/' . $send['e'], $send['i'], $result, $send['p'], true);
+			}
+		} else {
+			$result = $wechat->curl($send['t'], $param, false);
+			if ($send['e']) {
+				Dever::load($send['a'] . '/' . $send['e'], $send['i'], $result, $send['p']);
+				if (isset($param['run_num'])) {
+					Dever::load($send['a'] . '/' . $send['e'], $send['i'], $result, $send['p'], true);
+				}
+			}
+		}
+
+		return $result;
+	}
+	return array();
+}
+
+class Core
+{
+	static public function run($id, $method, $start, $end, $app, $param = false, $state = false)
+	{
+		$send = array();
+		$send['i'] = $id;
+		$send['t'] = $method;
+		$send['s'] = $start;
+		$send['e'] = $end;
+		$send['a'] = $app;
+		$send['p'] = $param;
+		if ($state == false) {
+			$result = Dever::daemon(self::url($send), 'main');
+		} else {
+			$result = callAction($send);
+		}
+
+		return $result;
+	}
+
+	static public function url($send)
+	{
+		$send = base64_encode(json_encode($send));
+		$url = 'lib/core.call?param=' . $send;
+		return $url;
+	}
+
+	public function call_api()
+	{
+		$send = json_decode(base64_decode(Dever::input('param')), true);
+		$result = callAction($send);
+		if (isset($result)) {
+			print_r($result);
+			die;
+		}
+		
+		return;
+	}
+}

+ 500 - 0
lib/Wechat.php

@@ -0,0 +1,500 @@
+<?php
+/*
+|--------------------------------------------------------------------------
+| core.php 微信平台核心类
+|--------------------------------------------------------------------------
+*/
+namespace Token\Lib;
+
+use Dever;
+
+class Wechat
+{
+	/**
+	 * config
+	 *
+	 * @var array
+	 */
+	private $config;
+	
+	/**
+	 * project
+	 *
+	 * @var string
+	 */
+	private $project;
+
+	/**
+	 * alert
+	 *
+	 * @var int
+	 */
+	private $alert;
+	
+	/**
+	 * 构造函数 初始化
+	 * 
+	 * @return mixed
+	 */
+	public function __construct($project = false, $type = '')
+	{
+		$this->config = Dever::config('wechat', $type)->cAll;
+		$type = $this->config['type'];
+
+		if (!$project) {
+			$appid = Dever::input('appid');
+			if ($appid) {
+				$project = Dever::db('token/project')->one(array('option_type' => $type, 'option_appid' => $appid));
+			}
+
+			/*
+			if (!$project) {
+				$project = Dever::db('token/project')->one(array('option_type' => $type));
+			}
+			*/
+
+			if (!$project) {
+				$project = Dever::input('project', 1);
+			}
+		}
+
+		if (is_numeric($project)) {
+			$project = Dever::db('token/project')->one(array('option_type' => $type, 'option_id' => $project));
+		}
+
+		if (!$project) {
+			Dever::alert('project is not exits!');
+		}
+
+		$this->project = $project;
+	}
+	
+	/**
+	 * 获取当前站点的配置
+	 * 
+	 * @return mixed
+	 */
+	public function project()
+	{
+		return $this->project;
+	}
+
+	/**
+	 * 获取当前基本的配置
+	 * 
+	 * @return mixed
+	 */
+	public function config()
+	{
+		return $this->config;
+	}
+
+	/**
+	 * 更新数据库
+	 * state true为强制更新数据库中的token数据
+	 * 
+	 * @return mixed
+	 */
+	private function save($type = 'ticket', $value, $expires = false, $interval = 2000, $data = false, $state = false)
+	{
+		$refresh = false;
+		if (strpos($type, '.')) {
+			$temp = explode('.', $type);
+			if ($temp[1] == 'refresh') {
+				$refresh = true;
+				$temp[1] = 'oauth';
+			}
+			$table = 'token/' . $temp[1];
+		} else {
+			$table = 'token/' . $type;
+		}
+		$db = Dever::db($table);
+
+		if ($data) {
+			if (isset($data['id'])) {
+				$where['option_id'] = $data['id'];
+				unset($data['id']);
+			}
+			if (isset($data['openid'])) {
+				$where['option_openid'] = $data['openid'];
+			}
+			if (isset($data['unionid'])) {
+				$where['option_unionid'] = $data['unionid'];
+			}
+		}
+		
+		$where['option_project_id'] = $this->project['id'];
+		$info = $db->one($where);
+
+		$update = false;
+			
+		if ($state == true) {
+			$update = true;
+		} elseif ($info && time() - $info['mdate'] >= $info['expires']) {
+			$update = true;
+		} elseif($info) {
+			return $info;
+		}
+		if (!$info) {
+			$update = false;
+		}
+		if (!$value) {
+			$value = $this->param($type, $info);
+		}
+
+		if (is_array($value) || (is_string($value) && strstr($value, 'http://'))) {
+			if ($refresh) {
+				$result = $this->curl(false, $value, false, $type);
+			} else {
+				$result = $this->curl(false, $value, true, $type);
+			}
+			
+
+			$key = $type;
+			if ($result && isset($result[$key])) {
+				$data = $result;
+				$data['value'] = $result[$key];
+				$data['expires'] = $result['expires_in'];
+			}
+		} else {
+			$data['value'] = $value;
+			$data['expires'] = $expires;
+		}
+		
+		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'];
+				$id = $info['id'];
+				$db->update($data);
+			} else {
+				$id = $db->insert($data);
+			}
+			$data['id'] = $id;
+			if ($id > 0 && isset($result['callback'])) {
+				foreach ($result['callback'] as $v) {
+					Dever::load($v[0], $id, $v[1], $this->project['id']);
+				}
+			}
+		} elseif($info && $info['value']) {
+			$data = $info;
+			$data['value'] = $info['value'];
+		}
+
+		return $data;
+	}
+
+	/**
+	 * 获取最新的token
+	 * 
+	 * @return mixed
+	 */
+	public function token($value = false, $expires = false, $interval = 2000, $state = false)
+	{
+		$result = $this->save('token', $value, $expires, $interval, false, $state);
+		return $result['value'];
+	}
+
+	/**
+	 * 获取最新的ticket
+	 * 
+	 * @return mixed
+	 */
+	public function ticket($value = false, $expires = false, $interval = 200, $state = false)
+	{
+		$result = $this->save('ticket', $value, $expires, $interval, false, $state);
+		return $result['value'];
+	}
+
+	/**
+	 * 获取最新的oauth token
+	 * 
+	 * @return mixed
+	 */
+	public function oauth($param, $interval = 2000, $state = false)
+	{
+		if (is_array($param) && isset($param['auth_code'])) {
+			$result = $this->curl('oauth.oauth', $param);
+			if (isset($result['oauth.oauth'])) {
+				return $this->save('oauth.oauth', $result['oauth.oauth'], $result['expires_in'], $interval, $result);
+			} else {
+				Dever::alert('oauth error');
+			}
+		} else {
+			if (is_numeric($param)) {
+				$id = $param;
+				$param = array();
+				$param['id'] = $id;
+			}
+			return $this->save('oauth.refresh', false, false, $interval, $param, $state);
+		}
+	}
+
+	/**
+	 * 获取最新的code
+	 * 
+	 * @return mixed
+	 */
+	public function code($value = false, $expires = false, $interval = 200)
+	{
+		$result = $this->save('oauth.code', $value, $expires, $interval, false, true);
+		return $result['value'];
+	}
+
+	/**
+	 * 获取最新的openid
+	 * 
+	 * @return mixed
+	 */
+	public function openid($id, $key = 'openid')
+	{
+		$info = Dever::db('token/oauth')->one($id);
+		return $info[$key];
+	}
+
+	/**
+	 * 获取最新的oauth login地址
+	 * 
+	 * @return mixed
+	 */
+	public function login($callback = false, $code = false, $location = true)
+	{
+		if (!$code) {
+			$code = $this->code();
+		}
+		$callback = 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);
+		}
+		return $url;
+	}
+
+	/**
+	 * 从wechat获取数据
+	 * 
+	 * @return mixed
+	 */
+	public function curl($method, $param = array(), $alert = true, $type = false)
+	{
+		if (!$this->alert) {
+			if (!$alert) {
+				$this->alert = 1;
+			} else {
+				$this->alert = 2;
+			}
+		}
+		
+		//return 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);
+			$this->log($result, $param['name'], $param['url'], $param['param']);
+		}
+		if (isset($result['errcode']) && $result['errcode'] != 0) {
+			/*
+			if ($result['errcode'] == 40001) {
+				$token = $this->token(false, false, 2000, true);
+				return $this->curl($type, array(), $alert);
+			}
+			*/
+			$result = $param + $result;
+			Dever::log($result);
+			if ($alert && $this->alert == 2) {
+				Dever::alert(json_encode($result, JSON_UNESCAPED_UNICODE));
+			}
+		}
+
+		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];
+				}
+
+				if (strpos($v, 'callback.') !== false) {
+					$temp = explode('callback.', $v);
+					$result['callback'][] = array($temp[1], $result[$v]);
+				}
+			}
+		}
+		return $result;
+	}
+
+	public function log($result, $name, $url, $param)
+	{
+		$insert['name'] = $name;
+		$insert['url'] = $url;
+		$insert['result'] = json_encode($result, JSON_UNESCAPED_UNICODE);
+		$insert['param'] = json_encode($param, JSON_UNESCAPED_UNICODE);
+		Dever::db('token/log')->insert($insert);
+	}
+
+	/**
+	 * 拼装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 (!$param) {
+			$param = array();
+		}
+		
+		$param = $this->project + $param;
+
+		//print_r($param);die;
+		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') {
+				if (!isset($param['oauth'])) {
+					Dever::alert('oauth erorr');
+				} elseif (is_numeric($param['oauth'])) {
+					$oauth = $this->oauth($param['oauth']);
+					$param['oauth'] = $oauth['value'];
+				}
+				$config['url'] .= $k . '=' . $param['oauth'];
+				unset($config['param'][$k]);
+			} elseif (!is_array($v) && isset($param[$v])) {
+				$config['param'][$k] = $param[$v];
+			} elseif($v) {
+				$config['param'][$k] = $this->replace($v, $param);
+			}
+		}
+
+		$config['json'] = isset($config['json']) && $config['json'] ? true : false;
+
+		return $config;
+	}
+
+	/**
+	 * 替换{}
+	 * 
+	 * @return mixed
+	 */
+	public function replace($value, $param)
+	{
+		if (isset($param['domain']) && strpos($value, '{domain}') !== false) {
+			foreach ($param['domain'] as $k => $v) {
+				$param['domain'][$k] = str_replace('{domain}', $v, $value);
+			}
+			return $param['domain'];
+		}
+
+		return $value;
+	}
+
+	/**
+	 * 消息解密
+	 * 
+	 * @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;
+		$info['timestamp'] = $timestamp;
+		$info['noncestr'] = $noncestr;
+		ksort($info);
+		*/
+
+		$signature_string = "jsapi_ticket=$ticket&noncestr=$noncestr&timestamp=$timestamp&url=$url";
+
+		//$signature_string = substr(http_build_query($info), 0, -1);
+		return sha1($signature_string);
+	}
+
+	/**
+	 * 获取sign签名数据包
+	 * 
+	 * @return mixed
+	 */
+	public function sign($url)
+	{
+		$ticket = $this->ticket();
+		if (!$url) {
+			$url = Dever::url();
+		} else {
+			$url = htmlspecialchars_decode($url);
+		}
+		$timestamp = time();
+		$noncestr = $this->nonce();
+		$signature = $this->signature($ticket, $url, $timestamp, $noncestr);
+
+		$sign = array();
+		$sign['appId'] = $this->project['appid'];
+		$sign['nonceStr'] = $noncestr;
+		$sign['timestamp'] = $timestamp;
+		$sign['url'] = $url;
+		$sign['signature'] = $signature;
+		return $sign;
+		
+	}
+}