Browse Source

Merge pull request #168 from binsee/master

更新公众号类,增加JSAPI授权相关方法
dodge 10 years ago
parent
commit
7b9059379e
6 changed files with 290 additions and 139 deletions
  1. 13 8
      README.md
  2. 78 4
      Thinkphp/Wechat.class.php
  3. 123 122
      errCode.php
  4. 70 4
      wechat.class.php
  5. 1 1
      wiki/Home.md
  6. 5 0
      wiki/官方API类库.md

+ 13 - 8
README.md

@@ -9,7 +9,7 @@ weixin developer SDK.
 ## 使用详解
 使用前需先打开微信帐号的开发模式,详细步骤请查看微信公众平台接口使用说明:  
 微信公众平台: http://mp.weixin.qq.com/wiki/
-微信企业平台: http://qy.weixin.qq.com/wiki/
+微信企业平台: http://qydev.weixin.qq.com/wiki/
 
 微信支付接入文档:
 https://mp.weixin.qq.com/cgi-bin/readtemplate?t=business/course2_tmpl&lang=zh_CN
@@ -18,13 +18,13 @@ https://mp.weixin.qq.com/cgi-bin/readtemplate?t=business/course2_tmpl&lang=zh_CN
 
 
 ## 目录 
-> **[wechat.class.php 官方API类库](#1-wechatclassphp-官方api类库)**  
-> **[wechatext.class.php 非官方扩展API](#2-wechatextclassphp-非官方扩展api)**  
-> **[wechatauth.class.php 授权登陆](#3-wechatauthclassphp-授权登陆)**  
-> **[wechat.js 内嵌JS](#4-wechatjs-内嵌js)**  
-> **[errCode.php 全局返回码类](#5-errcodephp-全局返回码类)**  
-> **[qywechat.class.php 企业号API类库](#6-qywechatclassphp-企业号api类库)**  
-> **[调用示例](#调用示例)**  
+> **[wechat.class.php 官方API类库](#user-content-1-wechatclassphp-官方api类库)**  
+> **[wechatext.class.php 非官方扩展API](#user-content-2-wechatextclassphp-非官方扩展api)**  
+> **[wechatauth.class.php 授权登陆](#user-content-3-wechatauthclassphp-授权登陆)**  
+> **[wechat.js 内嵌JS](#user-content-4-wechatjs-内嵌js)**  
+> **[errCode.php 全局返回码类](#user-content-5-errcodephp-全局返回码类)**  
+> **[qywechat.class.php 企业号API类库](#user-content-6-qywechatclassphp-企业号api类库)**  
+> **[调用示例](#user-content-调用示例)**  
 
 ----------
 
@@ -53,6 +53,7 @@ https://mp.weixin.qq.com/cgi-bin/readtemplate?t=business/course2_tmpl&lang=zh_CN
 - 卡券管理(创建、修改、删除、发放、门店管理等) **(认证权限)**
 - 语义理解 **(服务号、认证权限)**
 - 获取微信服务器IP列表 **(初级权限)**  
+- 微信JSAPI授权(获取ticket、获取签名) **(初级权限`暂未确定`)**
 > 备注:  
 > 初级权限:基本权限,任何正常的公众号都有此权限  
 > 菜单权限:正常的服务号、认证后的订阅号拥有此权限  
@@ -157,6 +158,10 @@ https://mp.weixin.qq.com/cgi-bin/readtemplate?t=business/course2_tmpl&lang=zh_CN
 
 ### 主动接口方法:   
  *  checkAuth($appid,$appsecret,$token) 此处传入公众后台高级接口提供的appid和appsecret, 或者手动指定$token为access_token。函数将返回access_token操作令牌
+ *  resetAuth($appid='') 删除验证数据
+ *  resetJsTicket($appid='') 删除JSAPI授权TICKET
+ *  getJsTicket($appid='',$jsapi_ticket='') 获取JSAPI授权TICKET
+ *  getJsSign($url, $timeStamp, $nonceStr, $appid='') 获取JsApi使用签名
  *  createMenu($data) 创建菜单 $data菜单结构详见 **[自定义菜单创建接口](http://mp.weixin.qq.com/wiki/index.php?title=自定义菜单创建接口)**
  *  getServerIp() 获取微信服务器IP地址列表 返回数组array('127.0.0.1','127.0.0.1')
  *  getMenu() 获取菜单 

+ 78 - 4
Thinkphp/Wechat.class.php

@@ -78,6 +78,7 @@ class Wechat
 	const MENU_CREATE_URL = '/menu/create?';
 	const MENU_GET_URL = '/menu/get?';
 	const MENU_DELETE_URL = '/menu/delete?';
+	const GET_TICKET_URL = '/ticket/getticket?';
 	const CALLBACKSERVER_GET_URL = '/getcallbackip?';
 	const QRCODE_CREATE_URL='/qrcode/create?';
 	const QR_SCENE = 0;
@@ -158,6 +159,7 @@ class Wechat
 	private $appid;
 	private $appsecret;
 	private $access_token;
+	private $jsapi_ticket;
 	private $user_token;
 	private $partnerid;
 	private $partnerkey;
@@ -277,6 +279,9 @@ class Wechat
     		}
     }
 
+    /**
+     * 设置消息的星标标志,官方已取消对此功能的支持
+     */
     public function setFuncFlag($flag) {
     		$this->_funcflag = $flag;
     		return $this;
@@ -963,8 +968,11 @@ class Wechat
 	 */
 	public function reply($msg=array(),$return = false)
 	{
-		if (empty($msg))
+		if (empty($msg)) {
+		    if (empty($this->_msg))   //防止不先设置回复内容,直接调用reply方法导致异常
+		        return false;
 			$msg = $this->_msg;
+		}
 		$xmldata=  $this->xml_encode($msg);
 		$this->log($xmldata);
 		if ($this->encrypt_type == 'aes') { //如果来源消息为加密方式
@@ -1067,7 +1075,7 @@ class Wechat
 	}
 
 	/**
-	 * 通用auth验证方法,暂时仅用于菜单更新操作
+	 * 通用auth验证方法,获取access_token
 	 * @param string $appid
 	 * @param string $appsecret
 	 * @param string $token 手动指定access_token,非必要情况不建议用
@@ -1116,6 +1124,72 @@ class Wechat
 	}
 
 	/**
+	 * 删除JSAPI授权TICKET
+	 * @param string $appid 用于多个appid时使用
+	 */
+	public function resetJsTicket($appid=''){
+		if (!$appid) $appid = $this->appid;
+		$this->jsapi_ticket = '';
+		$authname = 'wechat_jsapi_ticket'.$appid;
+		S($authname,null);
+		return true;
+	}
+
+	/**
+	 * 获取JSAPI授权TICKET
+	 * @param string $appid 用于多个appid时使用,可空
+	 * @param string $jsapi_ticket 手动指定jsapi_ticket,非必要情况不建议用
+	 */
+	public function getJsTicket($appid='',$jsapi_ticket=''){
+		if (!$this->access_token && !$this->checkAuth()) return false;
+		if ($jsapi_ticket) { //手动指定token,优先使用
+		    $this->jsapi_ticket = $jsapi_ticket;
+		    return $this->access_token;
+		}
+		$authname = 'wechat_jsapi_ticket'.$appid;
+		if ($rs = S($authname))  {
+			$this->jsapi_ticket = $rs;
+			return $rs;
+		}
+		$result = $this->http_get(self::API_URL_PREFIX.self::GET_TICKET_URL.'access_token='.$this->access_token.'&type=jsapi');
+		if ($result)
+		{
+			$json = json_decode($result,true);
+			if (!$json || !empty($json['errcode'])) {
+				$this->errCode = $json['errcode'];
+				$this->errMsg = $json['errmsg'];
+				return false;
+			}
+			$this->jsapi_ticket = $json['ticket'];
+			$expire = $json['expires_in'] ? intval($json['expires_in'])-100 : 3600;
+			S($authname,$this->access_token,$expire);
+			return $this->jsapi_ticket;
+		}
+		return false;
+	}
+
+
+	/**
+	 * 获取JsApi使用签名
+	 * @param string $url 网页的URL,不包含#及其后面部分
+	 * @param string $timeStamp 当前时间戳(需与JS输出的一致)
+	 * @param string $nonceStr 随机串(需与JS输出的一致)
+	 * @param string $appid 用于多个appid时使用,可空
+	 * @return string 返回签名字串
+	 */
+	public function getJsSign($url, $timeStamp, $nonceStr, $appid=''){
+	    if (!$this->jsapi_ticket && !$this->getJsTicket($appid)) return false;
+	    $ret = strpos($url,'#');
+	    if ($ret)
+	        $url = substr($url,0,$ret);
+	    $url = trim($url);
+	    if (empty($url))
+	        return false;
+	    $arrdata = array("timestamp" => $timeStamp, "noncestr" => $nonceStr, "url" => $url, "jsapi_ticket" => $this->jsapi_ticket);
+	    return $this->getSignature($arrdata);
+	}
+
+	/**
 	 * 微信api不支持中文转义的json结构
 	 * @param array $arr
 	 */
@@ -1512,7 +1586,7 @@ class Wechat
 	 * @return boolean|array
 	 * {
 	 *     "msg_id":201053012,     //群发消息后返回的消息id
-	 *     "msg_status":"SEND_SUCCESS" //消息发送后的状态,SEND_SUCCESS表示发送成功
+	 *     "msg_status":"SEND_SUCCESS" //消息发送后的状态,SENDING表示正在发送 SEND_SUCCESS表示发送成功
 	 * }
 	 */
 	public function queryMassMessage($msg_id){
@@ -1526,7 +1600,7 @@ class Wechat
 				$this->errMsg = $json['errmsg'];
 				return false;
 			}
-			return true;
+			return $json;
 		}
 		return false;
 	}

+ 123 - 122
errCode.php

@@ -1,139 +1,140 @@
 <?php
 /**
- *	微信公众平台PHP-SDK, 全局返回码类
+ *    微信公众平台PHP-SDK, 全局返回码类
  *  @author  binsee <binsee@163.com>
  *  @link https://github.com/binsee/wechat-php-sdk
  *  @version 1.0
  *  usage:
  *      $ret=ErrCode::getErrText(40001); //错误码可以通过公众号类库的公开变量errCode得到
  *      if ($ret)
- *      	echo $ret;
+ *          echo $ret;
  *      else
  *          echo "未找到对应的内容";
  */
 class ErrCode
 {
-	public static $errCode=array(
-	    '-1'=>'系统繁忙',
-	    '0'=>'请求成功',
-	    '40001'=>'获取access_token时AppSecret错误,或者access_token无效',
-	    '40002'=>'不合法的凭证类型',
-	    '40003'=>'不合法的OpenID',
-	    '40004'=>'不合法的媒体文件类型',
-	    '40005'=>'不合法的文件类型',
-	    '40006'=>'不合法的文件大小',
-	    '40007'=>'不合法的媒体文件id',
-	    '40008'=>'不合法的消息类型',
-	    '40009'=>'不合法的图片文件大小',
-	    '40010'=>'不合法的语音文件大小',
-	    '40011'=>'不合法的视频文件大小',
-	    '40012'=>'不合法的缩略图文件大小',
-	    '40013'=>'不合法的APPID',
-	    '40014'=>'不合法的access_token',
-	    '40015'=>'不合法的菜单类型',
-	    '40016'=>'不合法的按钮个数',
-	    '40017'=>'不合法的按钮类型',
-	    '40018'=>'不合法的按钮名字长度',
-	    '40019'=>'不合法的按钮KEY长度',
-	    '40020'=>'不合法的按钮URL长度',
-	    '40021'=>'不合法的菜单版本号',
-	    '40022'=>'不合法的子菜单级数',
-	    '40023'=>'不合法的子菜单按钮个数',
-	    '40024'=>'不合法的子菜单按钮类型',
-	    '40025'=>'不合法的子菜单按钮名字长度',
-	    '40026'=>'不合法的子菜单按钮KEY长度',
-	    '40027'=>'不合法的子菜单按钮URL长度',
-	    '40028'=>'不合法的自定义菜单使用用户',
-	    '40029'=>'不合法的oauth_code',
-	    '40030'=>'不合法的refresh_token',
-	    '40031'=>'不合法的openid列表',
-	    '40032'=>'不合法的openid列表长度',
-	    '40033'=>'不合法的请求字符,不能包含\uxxxx格式的字符',
-	    '40035'=>'不合法的参数',
-	    '40038'=>'不合法的请求格式',
-	    '40039'=>'不合法的URL长度',
-	    '40050'=>'不合法的分组id',
-	    '40051'=>'分组名字不合法',
-	    '40099'=>'该 code 已被核销',
-	    '41001'=>'缺少access_token参数',
-	    '41002'=>'缺少appid参数',
-	    '41003'=>'缺少refresh_token参数',
-	    '41004'=>'缺少secret参数',
-	    '41005'=>'缺少多媒体文件数据',
-	    '41006'=>'缺少media_id参数',
-	    '41007'=>'缺少子菜单数据',
-	    '41008'=>'缺少oauth code',
-	    '41009'=>'缺少openid',
-	    '42001'=>'access_token超时',
-	    '42002'=>'refresh_token超时',
-	    '42003'=>'oauth_code超时',
-	    '42005'=>'调用接口频率超过上限',
-	    '43001'=>'需要GET请求',
-	    '43002'=>'需要POST请求',
-	    '43003'=>'需要HTTPS请求',
-	    '43004'=>'需要接收者关注',
-	    '43005'=>'需要好友关系',
-	    '44001'=>'多媒体文件为空',
-	    '44002'=>'POST的数据包为空',
-	    '44003'=>'图文消息内容为空',
-	    '44004'=>'文本消息内容为空',
-	    '45001'=>'多媒体文件大小超过限制',
-	    '45002'=>'消息内容超过限制',
-	    '45003'=>'标题字段超过限制',
-	    '45004'=>'描述字段超过限制',
-	    '45005'=>'链接字段超过限制',
-	    '45006'=>'图片链接字段超过限制',
-	    '45007'=>'语音播放时间超过限制',
-	    '45008'=>'图文消息超过限制',
-	    '45009'=>'接口调用超过限制',
-	    '45010'=>'创建菜单个数超过限制',
-	    '45015'=>'回复时间超过限制',
-	    '45016'=>'系统分组,不允许修改',
-	    '45017'=>'分组名字过长',
-	    '45018'=>'分组数量超过上限',
-	    '45024'=>'账号数量超过上限',
-	    '46001'=>'不存在媒体数据',
-	    '46002'=>'不存在的菜单版本',
-	    '46003'=>'不存在的菜单数据',
-	    '46004'=>'不存在的用户',
-	    '47001'=>'解析JSON/XML内容错误',
-	    '48001'=>'api功能未授权',
-	    '50001'=>'用户未授权该api',
-	        '61451'=>'参数错误',
-	        '61452'=>'无效客服账号',
-	        '61453'=>'账号已存在',
-	        '61454'=>'账号名长度超过限制(前缀10个英文字符)',
-	        '61455'=>'账号名包含非法字符(英文+数字)',
-	        '61456'=>'账号个数超过限制(10个客服账号)',
-	        '61457'=>'无效头像文件类型',
-	        '7000000'=>'请求正常,无语义结果',
-	        '7000001'=>'缺失请求参数',
-	        '7000002'=>'signature 参数无效',
-	        '7000003'=>'地理位置相关配置 1 无效',
-	        '7000004'=>'地理位置相关配置 2 无效',
-	        '7000005'=>'请求地理位置信息失败',
-	        '7000006'=>'地理位置结果解析失败',
-	        '7000007'=>'内部初始化失败',
-	        '7000008'=>'非法 appid(获取密钥失败)',
-	        '7000009'=>'请求语义服务失败',
-	        '7000010'=>'非法 post 请求',
-	        '7000011'=>'post 请求 json 字段无效',
-	        '7000030'=>'查询 query 太短',
-	        '7000031'=>'查询 query 太长',
-	        '7000032'=>'城市、经纬度信息缺失',
-	        '7000033'=>'query 请求语义处理失败',
-	        '7000034'=>'获取天气信息失败',
-	        '7000035'=>'获取股票信息失败',
-	        '7000036'=>'utf8 编码转换失败',
-	);
+    public static $errCode=array(
+        '-1'=>'系统繁忙',
+        '0'=>'请求成功',
+        '40001'=>'获取access_token时AppSecret错误,或者access_token无效',
+        '40002'=>'不合法的凭证类型',
+        '40003'=>'不合法的OpenID',
+        '40004'=>'不合法的媒体文件类型',
+        '40005'=>'不合法的文件类型',
+        '40006'=>'不合法的文件大小',
+        '40007'=>'不合法的媒体文件id',
+        '40008'=>'不合法的消息类型',
+        '40009'=>'不合法的图片文件大小',
+        '40010'=>'不合法的语音文件大小',
+        '40011'=>'不合法的视频文件大小',
+        '40012'=>'不合法的缩略图文件大小',
+        '40013'=>'不合法的APPID',
+        '40014'=>'不合法的access_token',
+        '40015'=>'不合法的菜单类型',
+        '40016'=>'不合法的按钮个数',
+        '40017'=>'不合法的按钮类型',
+        '40018'=>'不合法的按钮名字长度',
+        '40019'=>'不合法的按钮KEY长度',
+        '40020'=>'不合法的按钮URL长度',
+        '40021'=>'不合法的菜单版本号',
+        '40022'=>'不合法的子菜单级数',
+        '40023'=>'不合法的子菜单按钮个数',
+        '40024'=>'不合法的子菜单按钮类型',
+        '40025'=>'不合法的子菜单按钮名字长度',
+        '40026'=>'不合法的子菜单按钮KEY长度',
+        '40027'=>'不合法的子菜单按钮URL长度',
+        '40028'=>'不合法的自定义菜单使用用户',
+        '40029'=>'不合法的oauth_code',
+        '40030'=>'不合法的refresh_token',
+        '40031'=>'不合法的openid列表',
+        '40032'=>'不合法的openid列表长度',
+        '40033'=>'不合法的请求字符,不能包含\uxxxx格式的字符',
+        '40035'=>'不合法的参数',
+        '40038'=>'不合法的请求格式',
+        '40039'=>'不合法的URL长度',
+        '40050'=>'不合法的分组id',
+        '40051'=>'分组名字不合法',
+        '40099'=>'该 code 已被核销',
+        '41001'=>'缺少access_token参数',
+        '41002'=>'缺少appid参数',
+        '41003'=>'缺少refresh_token参数',
+        '41004'=>'缺少secret参数',
+        '41005'=>'缺少多媒体文件数据',
+        '41006'=>'缺少media_id参数',
+        '41007'=>'缺少子菜单数据',
+        '41008'=>'缺少oauth code',
+        '41009'=>'缺少openid',
+        '42001'=>'access_token超时',
+        '42002'=>'refresh_token超时',
+        '42003'=>'oauth_code超时',
+        '42005'=>'调用接口频率超过上限',
+        '43001'=>'需要GET请求',
+        '43002'=>'需要POST请求',
+        '43003'=>'需要HTTPS请求',
+        '43004'=>'需要接收者关注',
+        '43005'=>'需要好友关系',
+        '44001'=>'多媒体文件为空',
+        '44002'=>'POST的数据包为空',
+        '44003'=>'图文消息内容为空',
+        '44004'=>'文本消息内容为空',
+        '45001'=>'多媒体文件大小超过限制',
+        '45002'=>'消息内容超过限制',
+        '45003'=>'标题字段超过限制',
+        '45004'=>'描述字段超过限制',
+        '45005'=>'链接字段超过限制',
+        '45006'=>'图片链接字段超过限制',
+        '45007'=>'语音播放时间超过限制',
+        '45008'=>'图文消息超过限制',
+        '45009'=>'接口调用超过限制',
+        '45010'=>'创建菜单个数超过限制',
+        '45015'=>'回复时间超过限制',
+        '45016'=>'系统分组,不允许修改',
+        '45017'=>'分组名字过长',
+        '45018'=>'分组数量超过上限',
+        '45024'=>'账号数量超过上限',
+        '46001'=>'不存在媒体数据',
+        '46002'=>'不存在的菜单版本',
+        '46003'=>'不存在的菜单数据',
+        '46004'=>'不存在的用户',
+        '47001'=>'解析JSON/XML内容错误',
+        '48001'=>'api功能未授权',
+        '50001'=>'用户未授权该api',
+        '61450'=>'系统错误',
+        '61451'=>'参数错误',
+        '61452'=>'无效客服账号',
+        '61453'=>'账号已存在',
+        '61454'=>'客服帐号名长度超过限制(仅允许10个英文字符,不包括@及@后的公众号的微信号)',
+        '61455'=>'客服账号名包含非法字符(英文+数字)',
+        '61456'=>'客服账号个数超过限制(10个客服账号)',
+        '61457'=>'无效头像文件类型',
+        '7000000'=>'请求正常,无语义结果',
+        '7000001'=>'缺失请求参数',
+        '7000002'=>'signature 参数无效',
+        '7000003'=>'地理位置相关配置 1 无效',
+        '7000004'=>'地理位置相关配置 2 无效',
+        '7000005'=>'请求地理位置信息失败',
+        '7000006'=>'地理位置结果解析失败',
+        '7000007'=>'内部初始化失败',
+        '7000008'=>'非法 appid(获取密钥失败)',
+        '7000009'=>'请求语义服务失败',
+        '7000010'=>'非法 post 请求',
+        '7000011'=>'post 请求 json 字段无效',
+        '7000030'=>'查询 query 太短',
+        '7000031'=>'查询 query 太长',
+        '7000032'=>'城市、经纬度信息缺失',
+        '7000033'=>'query 请求语义处理失败',
+        '7000034'=>'获取天气信息失败',
+        '7000035'=>'获取股票信息失败',
+        '7000036'=>'utf8 编码转换失败',
+    );
 
-	public static function getErrText($err) {
-		if (isset(self::$errCode[$err])) {
-			return self::$errCode[$err];
-		}else {
-		    return false;
-		};
-	}
+    public static function getErrText($err) {
+        if (isset(self::$errCode[$err])) {
+            return self::$errCode[$err];
+        }else {
+            return false;
+        };
+    }
 }
 
 ?>

+ 70 - 4
wechat.class.php

@@ -78,6 +78,7 @@ class Wechat
 	const MENU_CREATE_URL = '/menu/create?';
 	const MENU_GET_URL = '/menu/get?';
 	const MENU_DELETE_URL = '/menu/delete?';
+	const GET_TICKET_URL = '/ticket/getticket?';
 	const CALLBACKSERVER_GET_URL = '/getcallbackip?';
 	const QRCODE_CREATE_URL='/qrcode/create?';
 	const QR_SCENE = 0;
@@ -158,6 +159,7 @@ class Wechat
 	private $appid;
 	private $appsecret;
 	private $access_token;
+	private $jsapi_ticket;
 	private $user_token;
 	private $partnerid;
 	private $partnerkey;
@@ -961,8 +963,11 @@ class Wechat
 	 */
 	public function reply($msg=array(),$return = false)
 	{
-		if (empty($msg))
+		if (empty($msg)) {
+		    if (empty($this->_msg))   //防止不先设置回复内容,直接调用reply方法导致异常
+		        return false;
 			$msg = $this->_msg;
+		}
 		$xmldata=  $this->xml_encode($msg);
 		$this->log($xmldata);
 		if ($this->encrypt_type == 'aes') { //如果来源消息为加密方式
@@ -1065,7 +1070,7 @@ class Wechat
 	}
 
 	/**
-	 * 通用auth验证方法,暂时仅用于菜单更新操作
+	 * 通用auth验证方法,获取access_token
 	 * @param string $appid
 	 * @param string $appsecret
 	 * @param string $token 手动指定access_token,非必要情况不建议用
@@ -1109,6 +1114,67 @@ class Wechat
 	}
 
 	/**
+	 * 删除JSAPI授权TICKET
+	 * @param string $appid 用于多个appid时使用
+	 */
+	public function resetJsTicket($appid=''){
+		if (!$appid) $appid = $this->appid;
+		$this->jsapi_ticket = '';
+		//TODO: remove cache
+		return true;
+	}
+
+	/**
+	 * 获取JSAPI授权TICKET
+	 * @param string $appid 用于多个appid时使用,可空
+	 * @param string $jsapi_ticket 手动指定jsapi_ticket,非必要情况不建议用
+	 */
+	public function getJsTicket($appid='',$jsapi_ticket=''){
+		if (!$this->access_token && !$this->checkAuth()) return false;
+		if ($jsapi_ticket) { //手动指定token,优先使用
+		    $this->jsapi_ticket = $jsapi_ticket;
+		    return $this->access_token;
+		}
+		//TODO: get the cache jsapi_ticket
+		$result = $this->http_get(self::API_URL_PREFIX.self::GET_TICKET_URL.'access_token='.$this->access_token.'&type=jsapi');
+		if ($result)
+		{
+			$json = json_decode($result,true);
+			if (!$json || !empty($json['errcode'])) {
+				$this->errCode = $json['errcode'];
+				$this->errMsg = $json['errmsg'];
+				return false;
+			}
+			$this->jsapi_ticket = $json['ticket'];
+			$expire = $json['expires_in'] ? intval($json['expires_in'])-100 : 3600;
+			//TODO: cache jsapi_ticket
+			return $this->jsapi_ticket;
+		}
+		return false;
+	}
+
+
+	/**
+	 * 获取JsApi使用签名
+	 * @param string $url 网页的URL,不包含#及其后面部分
+	 * @param string $timeStamp 当前时间戳(需与JS输出的一致)
+	 * @param string $nonceStr 随机串(需与JS输出的一致)
+	 * @param string $appid 用于多个appid时使用,可空
+	 * @return string 返回签名字串
+	 */
+	public function getJsSign($url, $timeStamp, $nonceStr, $appid=''){
+	    if (!$this->jsapi_ticket && !$this->getJsTicket($appid)) return false;
+	    $ret = strpos($url,'#');
+	    if ($ret)
+	        $url = substr($url,0,$ret);
+	    $url = trim($url);
+	    if (empty($url))
+	        return false;
+	    $arrdata = array("timestamp" => $timeStamp, "noncestr" => $nonceStr, "url" => $url, "jsapi_ticket" => $this->jsapi_ticket);
+	    return $this->getSignature($arrdata);
+	}
+
+	/**
 	 * 微信api不支持中文转义的json结构
 	 * @param array $arr
 	 */
@@ -1505,7 +1571,7 @@ class Wechat
 	 * @return boolean|array
 	 * {
 	 *     "msg_id":201053012,     //群发消息后返回的消息id
-	 *     "msg_status":"SEND_SUCCESS" //消息发送后的状态,SEND_SUCCESS表示发送成功
+	 *     "msg_status":"SEND_SUCCESS" //消息发送后的状态,SENDING表示正在发送 SEND_SUCCESS表示发送成功
 	 * }
 	 */
 	public function queryMassMessage($msg_id){
@@ -1519,7 +1585,7 @@ class Wechat
 				$this->errMsg = $json['errmsg'];
 				return false;
 			}
-			return true;
+			return $json;
 		}
 		return false;
 	}

+ 1 - 1
wiki/Home.md

@@ -9,7 +9,7 @@
 ## 使用详解
 使用前需先打开微信帐号的开发模式,详细步骤请查看微信公众平台接口使用说明:  
 微信公众平台: http://mp.weixin.qq.com/wiki/
-微信企业平台: http://qy.weixin.qq.com/wiki/
+微信企业平台: http://qydev.weixin.qq.com/wiki/
 
 微信支付接入文档:https://mp.weixin.qq.com/cgi-bin/readtemplate?t=business/course2_tmpl
 

+ 5 - 0
wiki/官方API类库.md

@@ -24,6 +24,7 @@
 - 卡券管理(创建、修改、删除、发放、门店管理等) **(认证权限)**
 - 语义理解 **(服务号、认证权限)**
 - 获取微信服务器IP列表 **(初级权限)**  
+- 微信JSAPI授权(获取ticket、获取签名) **(初级权限`暂未确定`)**
 > 备注:  
 > 初级权限:基本权限,任何正常的公众号都有此权限  
 > 菜单权限:正常的服务号、认证后的订阅号拥有此权限  
@@ -128,6 +129,10 @@
 
 ### 主动接口方法:   
  *  checkAuth($appid,$appsecret,$token) 此处传入公众后台高级接口提供的appid和appsecret, 或者手动指定$token为access_token。函数将返回access_token操作令牌
+ *  resetAuth($appid='') 删除验证数据
+ *  resetJsTicket($appid='') 删除JSAPI授权TICKET
+ *  getJsTicket($appid='',$jsapi_ticket='') 获取JSAPI授权TICKET
+ *  getJsSign($url, $timeStamp, $nonceStr, $appid='') 获取JsApi使用签名
  *  createMenu($data) 创建菜单 $data菜单结构详见 **[自定义菜单创建接口](http://mp.weixin.qq.com/wiki/index.php?title=自定义菜单创建接口)**
  *  getServerIp() 获取微信服务器IP地址列表 返回数组array('127.0.0.1','127.0.0.1')
  *  getMenu() 获取菜单