ThinkPHP5集成微信公众号接口开发
一、使用方法
首先使用控制器所在命名空间,我这个控制器放在公共模块下:
use app\common\controller\Weixin;实例化:
$weixin = new Weixin;OAuth 授权跳转接口:
$get = input('get.');
#带上当前请求的参数
$get_var_param = http_build_query($get);
#授权成功跳转地址
$url = 'http://' . $_SERVER['HTTP_HOST'] . '/index/login/dologin?' . $get_var_param;
#OAuth 授权跳转接口 获取code
$wx_url = $weixin->getOAuthRedirect($url,'','snsapi_userinfo');
$this->redirect($wx_url); 获取用户信息:#通过code获取Access Token $jsonStr=$weixin->getOauthAccessToken(); #网页获取用户信息(没有关注公众号也可以获取用户基本信息) $info=$weixin->getOauthUserInfo($jsonStr['access_token'],$jsonStr["openid"]);
二、接口集成控制器代码
<?php
namespace app\common\controller;
use think\Controller;
class Weixin extends Controller {
/* 获取ACCESS_TOKEN URL */
const AUTH_URL = 'https://api.weixin.qq.com/cgi-bin/token';
/* 用户及用户分组URL */
const USER_GET_URL = 'https://api.weixin.qq.com/cgi-bin/user/get';
const USER_INFO_URL = 'https://api.weixin.qq.com/cgi-bin/user/info';
/* 二维码生成 URL*/
const QRCODE_URL = 'https://api.weixin.qq.com/cgi-bin/qrcode/create';
const QRCODE_SHOW_URL = 'https://mp.weixin.qq.com/cgi-bin/showqrcode';
/* OAuth2.0授权地址 */
const OAUTH_AUTHORIZE_URL = 'https://open.weixin.qq.com/connect/oauth2/authorize';
const OAUTH_USER_TOKEN_URL = 'https://api.weixin.qq.com/sns/oauth2/access_token';
const OAUTH_GET_USERINFO = 'https://api.weixin.qq.com/sns/userinfo';
/* 获取模板ID */
const GET_TEMPLATE_ID = 'https://api.weixin.qq.com/cgi-bin/template/api_add_template';
/* 消息模板 */
const TEMPLATE_SEND = 'https://api.weixin.qq.com/cgi-bin/message/template/send';
/* JSAPI_TICKET获取地址 */
const JSAPI_TICKET_URL = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket';
/* 企业付款 用户提现*/
const PAY_TRANSFERS_URL = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';
private $account;
private $token;
private $appid;
private $secret;
private $access_token;
private $error;
private $ticket;
private $result;
private $mch_id;
private $payKey;
private $pemCret;
private $pemKey;
public function __construct($options = array()) {
$this->account = '';
$this->token = '';
$this->appid = isset($options['appid'])?$options['appid']:config('wx_appid');// 微信appid,读取配置
$this->secret = isset($options['secret'])?$options['secret']:config('wx_appsecret');// 微信appsecret,读取配置;
$this->pem = 'apiclient';
}
/**
* 动态设置参数
* @param string $config 配置名称
* @param string $value 配置内容
*/
public function setConfig($config, $value) {
$this->$config = $value;
}
public function __get($key) {
return $this->$key;
}
public function __set($key, $value) {
$this->$key = $value;
}
/**
* 取得 access_token
* @return string|boolean
*/
public function getToken() {
$access_token = $this->access_token;
if (!empty($access_token)) {
return $this->access_token;
}else {
if ($this->getAccessToken()) {
return $this->access_token;
}else {
return false;
}
}
}
/**
* 从远端接口获取ACCESS_TOKEN
* @return string|boolean
*/
private function getAccessToken() {
$data = db('token')->where(array('type'=>1))->find();
if ($data['expire_time'] < time()){
$params = array(
'grant_type' => 'client_credential',
'appid' => $this->appid,
'secret' => $this->secret
);
$jsonStr = $this->http(self::AUTH_URL, $params);
if ($jsonStr) {
$jsonArr = $this->parseJson($jsonStr);
if ($jsonArr) {
$data['type'] = 1;
$data['expire_time'] = time() + 3600;
$data['access_token'] = $jsonArr['access_token'];
/*写入数据库*/
if(db('token')->where(array('type'=>1))->update($data) == 0){
db('token')->insertGetId($data);
}
return $this->access_token = $jsonArr['access_token'];
}else {
return false;
}
}else {
return false;
}
}else{
return $this->access_token = $data['access_token'];
}
}
/**
* 获取jsapi_ticket
*/
public function getJsapiTicket() {
$data = db('token')->where(array('type'=>2))->find();
if ($data['expire_time'] < time()){
$params = array(
'access_token' => $this->access_token,
'type' => 'jsapi'
);
$jsonStr = $this->http(self::JSAPI_TICKET_URL, $params);
$jsonArr = $this->parseJson($jsonStr);
if ($jsonArr) {
$data['type'] = 2;
$data['expire_time'] = time() + 3600;
$data['access_token'] = $this->result['ticket'];
/*写入数据库*/
if(db('token')->where(array('type'=>2))->update($data) == 0){
db('token')->insertGetId($data);
}
return $this->ticket = $this->result['ticket'];
}else {
return false;
}
}else{
return $this->ticket = $data['access_token'];
}
}
/*
* JS-SDK签名算法
*/
public function getSignPackage() {
$jsapiTicket = $this->getJsapiTicket();
$url = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$timestamp = time();
$nonceStr = self::_getRandomStr();
// 这里参数的顺序要按照 key 值 ASCII 码升序排序
$string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr×tamp=$timestamp&url=$url";
$signature = sha1($string);
$signPackage = array(
"appId" => $this->appid,
"nonceStr" => $nonceStr,
"timestamp" => $timestamp,
"url" => $url,
"signature" => $signature,
"rawString" => $string
);
return $signPackage;
}
/**
* 获取关注者列表
* @param sting $next_openid 第一个拉取的OPENID,不填默认从头开始拉取
* @return array|boolean 返回用户信息的一个数组
*/
public function users($next_openid = '') {
!empty($next_openid) && $params['next_openid'] = $next_openid;
$params['access_token'] = $this->access_token;
$jsonStr = $this->http(self::USER_GET_URL, $params);
$jsonArr = $this->parseJson($jsonStr);
if ($jsonArr) {
//优化返回数组的结构
$openId = $jsonArr['data']['openid'];
unset($jsonArr['data']);
while ($jsonArr['count'] == 10000) {
$next = self::users($jsonArr['next_openid']);
$openId = array_merge($openId, $next);
}
unset($jsonArr['count']);
unset($jsonArr['next_openid']);
$jsonArr['openid'] = $openId;
return $jsonArr;
}else {
return false;
}
}
/**
* 获取用户基本信息
* @param string $openid 用户的OPENID
* @return array|boolean 返回用户信息的一个数组
*/
public function user($openid = '') {
if (empty($openid)) {
$this->error = '请输入一个用户的OpenID';
return false;
}
$params = array(
'access_token' => $this->access_token,
'lang' => 'zh_CN',
'openid' => $openid
);
$jsonStr = $this->http(self::USER_INFO_URL, $params);
$jsonArr = $this->parseJson($jsonStr);
return $jsonArr;
if ($jsonArr['subscribe'] == 1) {
return true;
} else {
// $this->error = '用户未关注';
return false;
}
}
/**
* XML文档解析成数组,并将键值转成小写
* @param xml $xml
* @return array
*/
private function _extractXml($xml) {
$data = (array)simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
return array_change_key_case($data, CASE_LOWER);
}
/**
* 对数据进行SHA1签名
* @return string
*/
public function getSHA1($encrypt_msg, $nonce = '') {
$array = array($encrypt_msg, $this->token, NOW_TIME, $nonce);
sort($array, SORT_STRING);
$str = implode($array);
return sha1($str);
}
/**
* 将数组转换成XML
*/
private function _array2Xml($array) {
$xml = new \SimpleXMLElement('<xml></xml>');
$this->_data2xml($xml, $array);
return $xml->asXML();
}
/**
* 数据XML编码
* @param object $xml XML对象
* @param mixed $data 数据
* @param string $item 数字索引时的节点名称
* @return string xml
*/
private function _data2xml($xml, $data, $item = 'item') {
foreach ($data as $key => $value) {
/* 指定默认的数字key */
is_numeric($key) && $key = $item;
/* 添加子元素 */
if(is_array($value) || is_object($value)){
$child = $xml->addChild($key);
$this->_data2xml($child, $value, $item);
} else {
if(is_numeric($value)){
$child = $xml->addChild($key, $value);
} else {
$child = $xml->addChild($key);
$node = dom_import_simplexml($child);
$node->appendChild($node->ownerDocument->createCDATASection($value));
}
}
}
}
/**
* 获取模板ID
* @param string $tplId MP中的模板编号
* @return string 模板ID
*/
public function getTemplateId($tplId) {
$params = array(
'template_id_short:' => $tplId
);
$params = json_encode($params);
$url = self::GET_TEMPLATE_ID . '?access_token=' . $this->access_token;
$jsonStr = $this->http($url, $params, 'POST');
$jsonArr = $this->parseJson($jsonStr);
if ($jsonArr) {
return $jsonArr['template_id'];
}else {
return false;
}
}
/**
* 发送模板消息
* @param array
* @return boolean
*/
public function sendTemplate($content) {
$params = self::json_encode($content);
$url = self::TEMPLATE_SEND . '?access_token=' . $this->access_token;
$jsonStr = $this->http($url, $params, 'POST');
$jsonArr = $this->parseJson($jsonStr);
if ($jsonArr) {
return true;
}else {
return false;
}
}
/**
* OAuth 授权跳转接口
* @param string $callback 回调URI,填写完整地址,带http://
* @param sting $state 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值
* @param string snsapi_userinfo获取用户授权信息,snsapi_base直接返回openid
* @return string
*/
public function getOAuthRedirect($callback, $state='', $scope='snsapi_base'){
return self::OAUTH_AUTHORIZE_URL.'?appid='.$this->appid.'&redirect_uri='.urlencode($callback).'&response_type=code&scope='.$scope.'&state='.$state.'#wechat_redirect';
}
/**
* 通过code获取Access Token
* @return array|boolean
*/
public function getOauthAccessToken(){
$code = isset($_GET['code']) ? $_GET['code'] : '';
if (!$code) return false;
$params = array(
'appid' => $this->appid,
'secret'=> $this->secret,
'code' => $code,
'grant_type' => 'authorization_code'
);
$jsonStr = $this->http(self::OAUTH_USER_TOKEN_URL, $params);
$jsonArr = $this->parseJson($jsonStr);
if ($jsonArr) {
return $jsonArr;
}else {
return false;
}
}
/**
* 网页获取用户信息(没有关注公众号也可以获取用户基本信息)
* @param string $access_token 通过getOauthAccessToken方法获取到的token
* @param string $openid 用户的OPENID
* @return array
*/
public function getOauthUserInfo($access_token, $openid) {
$params = array(
'access_token' => $access_token,
'openid' => $openid,
'lang' => 'zh_CN'
);
$jsonStr = $this->http(self::OAUTH_GET_USERINFO, $params);
$jsonArr = $this->parseJson($jsonStr);
if ($jsonArr) {
return $jsonArr;
}else {
return false;
}
}
/**
* 不转义中文字符和\/的 json 编码方法
* @param array $array
* @return json
*/
private function json_encode($array = array()) {
$array = str_replace("\\/", "/", json_encode($array));
$search = '#\\\u([0-9a-f]+)#ie';
if (strpos(strtoupper(PHP_OS), 'WIN') === false) {
$replace = "iconv('UCS-2BE', 'UTF-8', pack('H4', '\\1'))";//LINUX
} else {
$replace = "iconv('UCS-2', 'UTF-8', pack('H4', '\\1'))";//WINDOWS
}
return preg_replace($search, $replace, $array);
}
/**
* 解析JSON编码,如果有错误,则返回错误并设置错误信息d
* @param json $json json数据
* @return array
*/
private function parseJson($json) {
$jsonArr = json_decode($json, true);
if (isset($jsonArr['errcode'])) {
if ($jsonArr['errcode'] == 0) {
$this->result = $jsonArr;
return true;
} else {
$this->error = $this->ErrorCode($jsonArr['errcode']);
return false;
}
}else {
return $jsonArr;
}
}
/**
* @param appid 是 公众号的唯一标识
* @param redirect_uri 是 授权后重定向的回调链接地址,请使用urlencode对链接进行处理
* @param response_type 是 返回类型,请填写code
* @param scope 是 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (未关注也可以得到信息)
* @param state 否 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值
* @param fun 授权成功以后的地址
* #wechat_redirect 是 无论直接打开还是做页面302重定向时候,必须带此参数
*/
public function oauth2($userid = '', $scope='snsapi_base',$fun){
$arr = array(
"appid" => $this->appid,
"redirect_uri" => 'http://wx.cnskl.com/'.$fun,
"response_type" => 'code',
"scope" => $scope,
'state' => $userid
);
return self::OAUTH_AUTHORIZE_URL . '?' . http_build_query($arr).'#wechat_redirect';
}
/**
* AES 解密方法
* @param string $encrypted 加密后的字符串
* @return xml|boolean
*/
public function AESdecode($encrypted) {
$key = base64_decode($this->AESKey . "=");
// 使用BASE64对需要解密的字符串进行解码
$ciphertext_dec = base64_decode($encrypted);
$module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
$iv = substr($key, 0, 16);
mcrypt_generic_init($module, $key, $iv);
// 解密
$decrypted = mdecrypt_generic($module, $ciphertext_dec);
mcrypt_generic_deinit($module);
mcrypt_module_close($module);
// 去除补位字符
$pad = ord(substr($decrypted, -1));
if ($pad < 1 || $pad > 32) {
$pad = 0;
}
$result = substr($decrypted, 0, (strlen($decrypted) - $pad));
// 去除16位随机字符串,网络字节序和AppId
if (strlen($result) < 16) {
$this->error = 'AESdecode Result Length Error';
return false;
}
$content = substr($result, 16);
$len_list = unpack("N", substr($content, 0, 4));
$xml_len = $len_list[1];
$xml_content = substr($content, 4, $xml_len);
$from_appid = substr($content, $xml_len + 4);
if ($from_appid != $this->appid) {
$this->errir = 'AESdecode AppId Error';
return false;
} else {
return self::_extractXml($xml_content);
}
}
/**
* AES 加密方法
* @param string $text 需要加密的字符串
* @return boolean
*/
public function AESencode($text) {
$key = base64_decode($this->AESKey . "=");
$random = self::_getRandomStr();
$text = $random . pack("N", strlen($text)) . $text . $this->appid;
$size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
$iv = substr($key, 0, 16);
// 使用自定义的填充方式对明文进行补位填充
$text_length = strlen($text);
//计算需要填充的位数
$amount_to_pad = 32 - ($text_length % 32);
if ($amount_to_pad == 0) {
$amount_to_pad = 32;
}
//获得补位所用的字符
$pad_chr = chr($amount_to_pad);
$tmp = "";
for ($index = 0; $index < $amount_to_pad; $index++) {
$tmp .= $pad_chr;
}
$text = $text . $tmp;
mcrypt_generic_init($module, $key, $iv);
// 加密
$encrypted = mcrypt_generic($module, $text);
mcrypt_generic_deinit($module);
mcrypt_module_close($module);
// 使用BASE64对加密后的字符串进行编码
return base64_encode($encrypted);
}
/**
* 返回随机填充的字符串
*/
private function _getRandomStr($lenght = 16) {
$str_pol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
return substr(str_shuffle($str_pol), 0, $lenght);
}
/**
* 发送HTTP请求方法,目前只支持CURL发送请求
* @param string $url 请求URL
* @param array $params 请求参数
* @param string $method 请求方法GET/POST
* @param boolean $ssl 是否进行SSL双向认证
* @return array $data 响应数据
*/
private function http($url, $params = array(), $method = 'GET', $ssl = false){
$opts = array(
CURLOPT_TIMEOUT => 30,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false
);
/* 根据请求类型设置特定参数 */
switch(strtoupper($method)){
case 'GET':
$getQuerys = !empty($params) ? '?'. http_build_query($params) : '';
$opts[CURLOPT_URL] = $url . $getQuerys;
break;
case 'POST':
$opts[CURLOPT_URL] = $url;
$opts[CURLOPT_POST] = 1;
$opts[CURLOPT_POSTFIELDS] = $params;
break;
}
if ($ssl) {
$pemPath = dirname(SITE_PATH).'/Wx/Apps/Common/Library/WxPayPubHelper/cert/';
$pemCret = $pemPath.$this->pem.'_cert.pem';
$pemKey = $pemPath.$this->pem.'_key.pem';
if (!file_exists($pemCret)) {
$this->error = '证书不存在';
return false;
}
if (!file_exists($pemKey)) {
$this->error = '密钥不存在';
return false;
}
$opts[CURLOPT_SSLCERTTYPE] = 'PEM';
$opts[CURLOPT_SSLCERT] = $pemCret;
$opts[CURLOPT_SSLKEYTYPE] = 'PEM';
$opts[CURLOPT_SSLKEY] = $pemKey;
}
/* 初始化并执行curl请求 */
$ch = curl_init();
curl_setopt_array($ch, $opts);
$data = curl_exec($ch);
$err = curl_errno($ch);
$errmsg = curl_error($ch);
curl_close($ch);
if ($err > 0) {
$this->error = $errmsg;
return false;
}else {
return $data;
}
}
/**
* 创建一个商户订单号
* @return integer 28位订单号
*/
private function createMchBillNo() {
$micro = microtime(true) * 100;
$micro = ceil($micro);
$rand = substr($micro, -8) . sprintf("%02d", mt_rand(0, 99));
return $this->mch_id . date('Ymd') . $rand;
}
/**
* 向用户付款
* @param string $openid 收款用户OPENID
* @param float $amount 付款金额
* @param string $check_name 真实姓名校验
* NO_CHECK:不校验真实姓名
* FORCE_CHECK:强校验真实姓名(未实名认证的用户会校验失败,无法转账)
* OPTION_CHECK:针对已实名认证的用户才校验真实姓名(未实名认证用户不校验,可以转账成功)
* @param string $desc 描述
* @return boolean|array
*/
public function transfers($openid, $amount, $desc, $check_name = 'NO_CHECK') {
$params['openid'] = $openid;
if ($check_name == 'NO_CHECK') {
$params['check_name'] = $check_name;
} else {
$params['check_name'] = 'OPTION_CHECK';
$params['re_user_name'] = $check_name;
}
$params['amount'] = $amount * 100;
$params['desc'] = $desc;
$params['spbill_create_ip'] = get_client_ip();
$params['partner_trade_no'] = self::createMchBillNo(); //商户订单号
$params['mch_appid'] = $this->appid; //商户appid
$params['mchid'] = $this->mch_id; //商户号
$params['nonce_str'] = self::_getRandomStr(); //随机字符串
$params['sign'] = self::_getOrderMd5($params);//签名
$data = self::_array2Xml($params);
$data = $this->http(self::PAY_TRANSFERS_URL, $data, 'POST', true);
return self::parsePayRequest($data);
}
/**
* 解析支付接口的返回结果
*/
public function parsePayRequest($data) {
$data = self::_extractXml($data);
if (empty($data)) {
$this->error = '支付返回内容解析失败';
return false;
}
// 有返回结果 并且是SUCCESS的时候
if ($data['return_code'] == 'SUCCESS') {
if (!self::_checkSign($data)) {
return false;
} elseif ($data['result_code'] == 'SUCCESS') {
return $data;
} else {
$this->error = $data['err_code'];
return false;
}
} else {
$this->error = $data['return_msg'];
return false;
}
return true;
}
/**
* 接口通知接收
*/
public function getNotify() {
$data = $GLOBALS["HTTP_RAW_POST_DATA"];
return self::parsePayRequest($data);
}
/**
* 接收数据签名校验
*/
private function _checkSign($data) {
// $sign = $data['sign'];
// unset($data['sign']);
// echo $sign;
// if (self::_getOrderMd5($data) != $sign) {
// $this->error = '签名校验失败';
// return false;
// } else {
// return true;
// }
return true;
}
/**
* 本地MD5签名
*/
private function _getOrderMd5($params) {
ksort($params);
$params['key'] = $this->payKey;
return strtoupper(md5(urldecode(http_build_query($params))));
}
/**
* 捕获错误信息
* @return string 中文错误信息
* @author 、小陈叔叔 <cjango@163.com>
*/
public function getError() {
return $this->error;
}
/**
* 获取全局返回错误码
* @param integer $code 错误码
* @return string 错误信息
* @author 、小陈叔叔 <cjango@163.com>
*/
private function ErrorCode($code) {
switch ($code) {
case -1 : return '系统繁忙 ';
case 40001 : return '获取access_token时AppSecret错误,或者access_token无效 ';
case 40002 : return '不合法的凭证类型';
case 40003 : return '不合法的OpenID ';
case 40004 : return '不合法的媒体文件类型';
case 40005 : return '不合法的文件类型';
case 40006 : return '不合法的文件大小';
case 40007 : return '不合法的媒体文件id ';
case 40008 : return '不合法的消息类型 ';
case 40009 : return '不合法的图片文件大小';
case 40010 : return '不合法的语音文件大小';
case 40011 : return '不合法的视频文件大小';
case 40012 : return '不合法的缩略图文件大小';
case 40013 : return '不合法的APPID';
case 40014 : return '不合法的access_token ';
case 40015 : return '不合法的菜单类型 ';
case 40016 : return '不合法的按钮个数 ';
case 40017 : return '不合法的按钮个数';
case 40018 : return '不合法的按钮名字长度';
case 40019 : return '不合法的按钮KEY长度 ';
case 40020 : return '不合法的按钮URL长度 ';
case 40021 : return '不合法的菜单版本号';
case 40022 : return '不合法的子菜单级数';
case 40023 : return '不合法的子菜单按钮个数';
case 40024 : return '不合法的子菜单按钮类型';
case 40025 : return '不合法的子菜单按钮名字长度';
case 40026 : return '不合法的子菜单按钮KEY长度 ';
case 40027 : return '不合法的子菜单按钮URL长度 ';
case 40028 : return '不合法的自定义菜单使用用户';
case 40029 : return '不合法的oauth_code';
case 40030 : return '不合法的refresh_token';
case 40031 : return '不合法的openid列表 ';
case 40032 : return '不合法的openid列表长度 ';
case 40033 : return '不合法的请求字符,不能包含\uxxxx格式的字符 ';
case 40035 : return '不合法的参数';
case 40038 : return '不合法的请求格式';
case 40039 : return '不合法的URL长度 ';
case 40050 : return '不合法的分组id';
case 40051 : return '分组名字不合法';
case 41001 : return '缺少access_token参数';
case 41002 : return '缺少appid参数';
case 41003 : return '缺少refresh_token参数';
case 41004 : return '缺少secret参数';
case 41005 : return '缺少多媒体文件数据';
case 41006 : return '缺少media_id参数';
case 41007 : return '缺少子菜单数据';
case 41008 : return '缺少oauth code';
case 41009 : return '缺少openid';
case 42001 : return 'access_token超时';
case 42002 : return 'refresh_token超时';
case 42003 : return 'oauth_code超时';
case 43001 : return '需要GET请求';
case 43002 : return '需要POST请求';
case 43003 : return '需要HTTPS请求';
case 43004 : return '需要接收者关注';
case 43005 : return '需要好友关系';
case 44001 : return '多媒体文件为空';
case 44002 : return 'POST的数据包为空';
case 44003 : return '图文消息内容为空';
case 44004 : return '文本消息内容为空';
case 45001 : return '多媒体文件大小超过限制';
case 45002 : return '消息内容超过限制';
case 45003 : return '标题字段超过限制';
case 45004 : return '描述字段超过限制';
case 45005 : return '链接字段超过限制';
case 45006 : return '图片链接字段超过限制';
case 45007 : return '语音播放时间超过限制';
case 45008 : return '图文消息超过限制';
case 45009 : return '接口调用超过限制';
case 45010 : return '创建菜单个数超过限制';
case 45015 : return '回复时间超过限制';
case 45016 : return '系统分组,不允许修改';
case 45017 : return '分组名字过长';
case 45018 : return '分组数量超过上限';
case 46001 : return '不存在媒体数据';
case 46002 : return '不存在的菜单版本';
case 46003 : return '不存在的菜单数据';
case 46004 : return '不存在的用户';
case 47001 : return '解析JSON/XML内容错误';
case 48001 : return 'api功能未授权';
case 50001 : return '用户未授权该api';
default : return '未知错误';
}
}
}