├── README.md └── wgate.class.php /README.md: -------------------------------------------------------------------------------- 1 | wgate-php-sdk 2 | ============== 3 | 4 | 微信之门平台API PHP版本SDK. 5 | 6 | 微信之门官方网站: http://www.weixingate.com 7 | 8 | ### 下载 9 | 10 | ```sh 11 | git clone https://github.com/cnhuye/wgate-php-sdk.git 12 | ``` 13 | 14 | 微信之门 的 wgate sdk 只控制微信之门相关的API. 15 | 16 | 连接微信的API请下载微信之门改版的 wechat-php-sdk : 17 | 18 | ```sh 19 | git clone https://github.com/cnhuye/wechat-php-sdk.git 20 | ``` 21 | 详情请查看: https://github.com/cnhuye/wechat-php-sdk 22 | 23 | ### 调用方式 24 | 25 | ```php 26 | require_once 'wgate-php-sdk/wgate.class.php'; 27 | 28 | $options = array( 29 | "key"=>$wgate_key, // 微信之门中生成的KEY 30 | "secret"=>$wgate_secret, // 相应的secret 31 | "appid"=>$appid, // 公众号的APPID 32 | "weixin_account_id"=>$wgate_weixin_account_id // 微信之门中公众号对应的ID 33 | ); 34 | $wgate = new WGate($options); 35 | 36 | 37 | // wechat sdk 配合 wgate sdk 38 | $weObj = new Wechat(["wgate"=>$wgate]); 39 | 40 | ``` 41 | 42 | ### 方法 43 | 44 | * getWgateToken($key='',$secret="",$token='') // 获取 wgate_token. 45 | * getOauthUrl($options) // 使用自定义服务号, 得到微信之门授权URL. $options为array. 46 | 需要设置微信中oAuth授权域名为微信之门域名. 具体请看微信之门文档 47 | * getOauthUserInfo($code) // 根据授权返回的code获得当前用户信息. 48 | * getWgateOauthUrl($options) // 没有服务号, 使用用微信之门授权网关. 49 | * getWgateOauthUserInfo($code) // 根据 wgate_oauth 接口授权返回的code 获得用户信息 50 | * getAccessToken() // 获取微信access_token 51 | * getAccessTokenExpireTime() // 获取上一步得到的access_token 过期时间 52 | * createPayment($options) // 创建微信支付. 返回创建的支付 payment_id 53 | * getPaymentUrl($payment_id) // 根据上一步创建的支付 payment_id 得到支付页面URL 54 | * verifyPaymentNotify($params) // 校验用户支付完成后, 后端返回的支付通知 55 | * getPaymentNotifyReturn($successed=true,$msg="") // 生成返回给通知的内容 56 | * getJsApiTicket() // 得到jsapi_ticket 57 | * getJsApiTicketExpireTime() // 得到 jsapi_ticket 过期时间 58 | * getJsSign($url, $timestamp=0, $noncestr='') // 根据当前URL获得 js sign 59 | * getCardApiTicket() // 获得卡券 api ticket 60 | * getCardApiTicketExpireTime() // 获得卡券 api ticket 过期时间 61 | * getCardSign($shopid=null, $card_type=null, $cardid=null, $timestamp=0, $noncestr='') // 获得卡券签名 62 | * getCardExtSign($cardid=null, $openid=null, $code=null, $timestamp=0, $noncestr='') // 获得卡券签名 ext 信息 63 | 64 | WGate 为所有需要绑定的微信接口提供了一个中央控制器, 例如 access_token, OAuth, js ticket等. 65 | 66 | 并且给不同开发者提供了一个公众号下的不同 key/secret 作为接入凭据. 67 | 68 | 不同开发者共享中央控制器中的内容. 因此需要检查相应的 expire time, 如过期, 需要重新获取. 69 | 70 | 不过微信之门改版的 wechat-php-sdk 已经加入了自动获取更新 access_token 的功能, 如果过期会自动重试, 并重新调用接口. 详情请见 https://github.com/cnhuye/wechat-php-sdk 主动接口方法部分说明. 71 | 72 | 73 | 74 | ### 错误处理 75 | 76 | 当方法返回 false 时, 说明调用微信之门接口出错. 可使用使用errMsg属性获取微信之门服务器返回的错误消息. 77 | ```php 78 | $error = $wgate->errMsg; 79 | echo $error; 80 | ``` 81 | 82 | 83 | ### 示例 84 | 85 | ```php 86 | ... 上面调用初始化 ... 87 | 88 | // 跳转绑定服务号授权 89 | $url = $wgate->getOauthUrl(["info"=>"force", "back"=> 'http://..."]); 90 | 91 | // 根据返回的 code 得到用户信息 92 | $userinfo = $wgate->getOauthUserInfo($_GET["code"]); 93 | 94 | // 获取微信 access_token 95 | $access_token = $wgate->getAccessToken(); 96 | 97 | // 获取 wgate_token 98 | echo $wgate->getWgateToken(); 99 | 100 | // 调用出错时获取错误信息 101 | $result = $wgate->getJsApiTicket(); 102 | if($result==false){ 103 | echo $wgate->errMsg; 104 | } 105 | ``` 106 | 107 | License 108 | ------- 109 | This is licensed under the GNU LGPL, version 2.1 or later. 110 | For details, see: http://creativecommons.org/licenses/LGPL/2.1/ 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /wgate.class.php: -------------------------------------------------------------------------------- 1 | 5 | * @link https://github.com/cnhuye/wgate-php-sdk.git 6 | * @version 1.0 7 | * usage: 8 | * $options = array( 9 | * 'key'=>'xxxxxxx', //微信之门中创建的key 10 | * 'secret'=>'xxxxxxxxxxxxxxxxxxx' //key 相应的 secret 11 | * 'appid'=>'wxxxxxxxxxxx', //公众号的 app id 12 | * 'weixin_account_id'=>'xxx' //公众号在微信之门平台上相应的 id 13 | * ); 14 | * $wgate = new WGate($options); 15 | * 16 | */ 17 | class WGate 18 | { 19 | const OAUTH_GATE_URL = 'http://www.weixingate.com/api/v1/oauth'; 20 | const WGATE_OAUTH_GATE_URL = 'http://www.weixingate.com/api/v1/wgate_oauth'; 21 | 22 | // for local env 23 | // const WGATE_HOST = 'http://huye.ngrok.natapp.cn/members'; 24 | // const API_URL_PREFIX = 'http://huye.ngrok.natapp.cn/members/api/v1'; 25 | // const WGATE_PAYMENT_URL = "http://huye.ngrok.natapp.cn/members/wx/pays/"; 26 | 27 | // for production 28 | const WGATE_HOST = 'http://www.weixingate.com'; 29 | const API_URL_PREFIX = 'http://api.weixingate.com/v1'; 30 | const WGATE_PAYMENT_URL = "http://www.weixingate.com/members/wx/pays/"; 31 | 32 | const API_OAUTH_USERINFO_URL = '/oauth/userinfo'; 33 | 34 | const API_WGATE_OAUTH_VERIFY_URL = '/wgate_oauth/verify'; 35 | const API_WGATE_OAUTH_USERINFO_URL = '/wgate_oauth/userinfo'; 36 | 37 | const API_WGATE_TOKEN_URL = '/weixin_account/wgate_token'; 38 | const API_TOKEN_URL = '/weixin_account/token'; 39 | const API_JSAPI_TICKET_URL = '/weixin_account/jsapi_ticket'; 40 | const API_CARD_API_TICKET_URL = '/weixin_account/card_api_ticket'; 41 | const API_PAYMENTS_URL = '/weixin_account/payments'; 42 | const API_PAYMENT_SHOW_URL = '/weixin_account/payments/show'; 43 | 44 | 45 | private $appid; 46 | private $weixin_account_id; 47 | private $key; 48 | private $secret; 49 | private $wgate_token; 50 | private $access_token; 51 | private $access_token_expire_at; 52 | private $postxml; 53 | private $jsapi_ticket; 54 | 55 | public $debug = false; 56 | public $errCode = 0; 57 | public $errMsg = ""; 58 | 59 | public function __construct($options) 60 | { 61 | $this->appid = isset($options['appid'])?$options['appid']:''; 62 | $this->weixin_account_id = isset($options['weixin_account_id'])?$options['weixin_account_id']:''; 63 | $this->key= isset($options['key'])?$options['key']:''; 64 | $this->secret = isset($options['secret'])?$options['secret']:''; 65 | $this->debug = isset($options['debug'])?$options['debug']:false; 66 | } 67 | 68 | /** 69 | * 获取wgate_token 70 | * @param string $key 如在类初始化时已提供,则可为空 71 | * @param string $secret 如在类初始化时已提供,则可为空 72 | * @param string $token 手动指定wgate_token,非必要情况不建议用 73 | */ 74 | public function getWgateToken($key='',$secret="",$token=''){ 75 | if (!$key || !$secret) { 76 | $key = $this->key; 77 | $secret = $this->secret; 78 | } 79 | if ($token) { //手动指定token,优先使用 80 | $this->wgate_token=$token; 81 | return $this->wgate_token; 82 | } 83 | 84 | $authname = 'wgate_token'.$key; 85 | if ($rs = $this->getCache($authname)) { 86 | $this->wgate_token = $rs; 87 | return $rs; 88 | } 89 | 90 | $timestamp = time(); 91 | $verify = md5($timestamp.$key.$secret); 92 | $params = http_build_query(["weixin_account_id"=>$this->weixin_account_id,"key"=>$key,"timestamp"=>$timestamp,"verify"=>$verify]); 93 | $result = $this->http_get(self::API_URL_PREFIX.self::API_WGATE_TOKEN_URL.'?'.$params); 94 | if ($result) 95 | { 96 | $json = json_decode($result,true); 97 | if (!$json || isset($json['error'])) { 98 | $this->errCode = $json['error']; 99 | $this->errMsg = $json['error']; 100 | return false; 101 | } 102 | $this->wgate_token = $json['token']; 103 | $expire = $json['expire_at'] ? intval($json['expire_at'])-100 : 3600; 104 | $this->setCache($authname,$this->wgate_token,$expire); 105 | return $this->wgate_token; 106 | } 107 | return false; 108 | } 109 | 110 | 111 | 112 | /** 113 | * 获取授权网关跳转URL 114 | * @param array $options 授权网关所需参数, http://doc.weixingate.com/reference/auth/ 115 | */ 116 | public function getOauthUrl($options){ 117 | $qs = http_build_query(array_merge($options,["weixin_account_id"=>$this->weixin_account_id])); 118 | $url = self::OAUTH_GATE_URL."?".$qs; 119 | return $url; 120 | } 121 | 122 | 123 | 124 | 125 | /** 126 | * 根据 code 获取授权后用户信息 127 | * @param string $wgateid 128 | */ 129 | public function getOauthUserInfo($code){ 130 | if (!$this->wgate_token && !$this->getWgateToken()) return false; 131 | $qs = http_build_query(["code"=>$code,"token"=>$this->wgate_token]); 132 | $result = $this->http_get(self::API_URL_PREFIX.self::API_OAUTH_USERINFO_URL."?".$qs); 133 | if ($result) 134 | { 135 | $json = json_decode($result,true); 136 | if (!$json || isset($json['error'])) { 137 | $this->errCode = $json['error']; 138 | $this->errMsg = $json['error']; 139 | return false; 140 | } 141 | return $json; 142 | } 143 | return false; 144 | 145 | } 146 | 147 | 148 | 149 | /** 150 | * 获取授权网关跳转URL 151 | * @param array $options 授权网关所需参数, http://doc.weixingate.com/reference/auth/ 152 | */ 153 | public function getWgateOauthUrl($options){ 154 | $qs = http_build_query(array_merge($options,[])); 155 | $url = self::WGATE_OAUTH_GATE_URL."?".$qs; 156 | return $url; 157 | } 158 | 159 | 160 | 161 | 162 | /** 163 | * 根据 wgateid 获取用户信息 164 | * @param string $wgateid 165 | */ 166 | public function getWgateOauthUserInfo($code){ 167 | $qs = http_build_query(["code"=>$code]); 168 | $result = $this->http_get(self::API_URL_PREFIX.self::API_WGATE_OAUTH_USERINFO_URL."?".$qs); 169 | if ($result) 170 | { 171 | $json = json_decode($result,true); 172 | if (!$json || isset($json['error'])) { 173 | $this->errCode = $json['error']; 174 | $this->errMsg = $json['error']; 175 | return false; 176 | } 177 | return $json; 178 | } 179 | return false; 180 | 181 | } 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | /** 195 | * 获取微信access_token 196 | * @param string $token 手动指定access_token,非必要情况不建议用 197 | */ 198 | public function getAccessToken($token=''){ 199 | if ($token) { //手动指定token,优先使用 200 | $this->access_token=$token; 201 | return $this->access_token; 202 | } 203 | 204 | if (!$this->wgate_token && !$this->getWgateToken()) return false; 205 | 206 | 207 | $authname = 'wgate_access_token'.$this->appid; 208 | if ($rs = $this->getCache($authname)) { 209 | $this->access_token = $rs; 210 | return $rs; 211 | } 212 | 213 | $qs = http_build_query(["token"=>$this->wgate_token,"weixin_account_id"=>$this->weixin_account_id]); 214 | $result = $this->http_get(self::API_URL_PREFIX.self::API_TOKEN_URL.'?'.$qs); 215 | 216 | 217 | if ($result) 218 | { 219 | $json = json_decode($result,true); 220 | if (!$json || isset($json['error'])) { 221 | $this->errCode = $json['error']; 222 | $this->errMsg = $json['error']; 223 | return false; 224 | } 225 | $this->access_token = $json['token']; 226 | $expire = $json['expire_at']; 227 | $this->access_token_expire_at = $expire; 228 | $this->setCache($authname,$this->access_token,time()-intval($expire)); 229 | return $this->access_token; 230 | } 231 | return false; 232 | } 233 | 234 | 235 | /** 236 | * 获取微信 access_tokem 过期时间戳 237 | */ 238 | public function getAccessTokenExpireTime(){ 239 | if ($this->access_token_expire_at && $this->access_token_expire_at>time()) { 240 | return $this->access_token_expire_at; 241 | } 242 | null; 243 | } 244 | 245 | 246 | /** 247 | * 创建Payment, 获取payment_id 248 | * @param array $options 支付所需参数, 同微信支付参数 249 | */ 250 | public function createPayment($options){ 251 | if (!$this->wgate_token && !$this->getWgateToken()) return false; 252 | 253 | $options = array_merge($options,["token"=>$this->wgate_token,"weixin_account_id"=>$this->weixin_account_id]); 254 | $sign = $this->genSignature($options,"md5","&secret=".$this->secret); 255 | $options["sign"] = $sign; 256 | $qs = http_build_query($options); 257 | $result = $this->http_post(self::API_URL_PREFIX.self::API_PAYMENTS_URL,$qs); 258 | if ($result) 259 | { 260 | $json = json_decode($result,true); 261 | if (!$json || isset($json['error'])) { 262 | $this->errCode = $json['error']; 263 | $this->errMsg = $json['error']; 264 | return false; 265 | } 266 | return $json["payment_id"]; 267 | } 268 | return false; 269 | } 270 | 271 | 272 | 273 | 274 | /** 275 | * 根据payment_id, 返回payment跳转URL 276 | * @param string $payment_id 支付所需参数, 同微信支付参数 277 | */ 278 | public function getPaymentUrl($payment_id){ 279 | return self::WGATE_PAYMENT_URL.$payment_id; 280 | } 281 | 282 | 283 | /** 284 | * 根据payment_id, 返回payment跳转URL 285 | * @param string $payment_id 支付所需参数, 同微信支付参数 286 | */ 287 | public function verifyPaymentNotify($params){ 288 | 289 | 290 | $signature = $params["sign"]; 291 | unset($params["sign"]); 292 | 293 | ksort($params); 294 | $paramstring = ""; 295 | foreach($params as $key => $value) 296 | { 297 | if(strlen($paramstring) == 0) 298 | $paramstring .= $key . "=" . $value; 299 | else 300 | $paramstring .= "&" . $key . "=" . $value; 301 | } 302 | $paramstring .= "&secret=" . $this->secret; 303 | // print_r($paramstring."\n"); 304 | $tmpStr = md5($paramstring); 305 | // echo $tmpStr."|".$signature; 306 | if( $tmpStr == $signature ){ 307 | return true; 308 | }else{ 309 | return false; 310 | } 311 | 312 | } 313 | 314 | 315 | 316 | 317 | /** 318 | * 返回 payment notify 的返回内容 319 | * @param string $payment_id 支付所需参数, 同微信支付参数 320 | */ 321 | public function getPaymentNotifyReturn($successed=true,$msg=""){ 322 | return "".($successed ? "SUCCESS" : "FAIL")."".$msg.""; 323 | } 324 | 325 | 326 | 327 | 328 | 329 | 330 | /** 331 | * 获取JSAPI授权TICKET 332 | * @param string $jsapi_ticket 手动指定jsapi_ticket,非必要情况不建议用 333 | */ 334 | public function getJsApiTicket($jsapi_ticket=''){ 335 | if (!$this->wgate_token && !$this->getWgateToken()) return false; 336 | if ($jsapi_ticket) { //手动指定token,优先使用 337 | $this->jsapi_ticket = $jsapi_ticket; 338 | return $this->jsapi_ticket; 339 | } 340 | $authname = 'wgate_jsapi_ticket'.$this->appid; 341 | if ($rs = $this->getCache($authname)) { 342 | $this->jsapi_ticket = $rs; 343 | return $rs; 344 | } 345 | $qs = http_build_query(["token"=>$this->wgate_token,"weixin_account_id"=>$this->weixin_account_id]); 346 | $result = $this->http_get(self::API_URL_PREFIX.self::API_JSAPI_TICKET_URL.'?'.$qs); 347 | if ($result) 348 | { 349 | $json = json_decode($result,true); 350 | if (!$json || isset($json['error'])) { 351 | $this->errCode = $json['error']; 352 | $this->errMsg = $json['error']; 353 | return false; 354 | } 355 | $this->jsapi_ticket = $json['ticket']; 356 | $expire = $json['expire_at']; 357 | $this->jsapi_ticket_expire_at = $expire; 358 | $this->setCache($authname,$this->jsapi_ticket,time()-intval($expire)); 359 | return $this->jsapi_ticket; 360 | } 361 | return false; 362 | } 363 | 364 | /** 365 | * 获取微信 jsapi_ticket 过期时间戳 366 | */ 367 | public function getJsApiTicketExpireTime(){ 368 | if ($this->jsapi_ticket_expire_at && $this->jsapi_ticket_expire_at>time()) { 369 | return $this->jsapi_ticket_expire_at; 370 | } 371 | null; 372 | } 373 | 374 | 375 | /** 376 | * 获取JsApi使用签名 377 | * @param string $url 网页的URL,自动处理#及其后面部分 378 | * @param string $timestamp 当前时间戳 (为空则自动生成) 379 | * @param string $noncestr 随机串 (为空则自动生成) 380 | * @return array|bool 返回签名字串 381 | */ 382 | public function getJsSign($url, $timestamp=0, $noncestr=''){ 383 | if (!$this->jsapi_ticket && !$this->getJsApiTicket($this->appid) || !$url) return false; 384 | if (!$timestamp) 385 | $timestamp = time(); 386 | if (!$noncestr) 387 | $noncestr = $this->generateNonceStr(); 388 | $ret = strpos($url,'#'); 389 | if ($ret) 390 | $url = substr($url,0,$ret); 391 | $url = trim($url); 392 | if (empty($url)) 393 | return false; 394 | $arrdata = array("timestamp" => $timestamp, "noncestr" => $noncestr, "url" => $url, "jsapi_ticket" => $this->jsapi_ticket); 395 | $sign = $this->genSignature($arrdata); 396 | if (!$sign) 397 | return false; 398 | $signPackage = array( 399 | "appid" => $this->appid, 400 | "noncestr" => $noncestr, 401 | "timestamp" => $timestamp, 402 | "url" => $url, 403 | "signature" => $sign 404 | ); 405 | return $signPackage; 406 | } 407 | 408 | 409 | 410 | 411 | 412 | /** 413 | * 获取卡券API授权TICKET 414 | * @param string $jsapi_ticket 手动指定jsapi_ticket,非必要情况不建议用 415 | */ 416 | public function getCardApiTicket($card_api_ticket=''){ 417 | if (!$this->wgate_token && !$this->getWgateToken()) return false; 418 | if ($card_api_ticket) { //手动指定token,优先使用 419 | $this->card_api_ticket = $card_api_ticket; 420 | return $this->card_api_ticket; 421 | } 422 | $authname = 'wgate_card_api_ticket'.$this->appid; 423 | if ($rs = $this->getCache($authname)) { 424 | $this->card_api_ticket = $rs; 425 | return $rs; 426 | } 427 | $qs = http_build_query(["token"=>$this->wgate_token,"weixin_account_id"=>$this->weixin_account_id]); 428 | $result = $this->http_get(self::API_URL_PREFIX.self::API_CARD_API_TICKET_URL.'?'.$qs); 429 | if ($result) 430 | { 431 | $json = json_decode($result,true); 432 | if (!$json || isset($json['error'])) { 433 | $this->errCode = $json['error']; 434 | $this->errMsg = $json['error']; 435 | return false; 436 | } 437 | $this->card_api_ticket = $json['ticket']; 438 | $expire = $json['expire_at']; 439 | $this->card_api_ticket_expire_at = $expire; 440 | $this->setCache($authname,$this->card_api_ticket,time()-intval($expire)); 441 | return $this->card_api_ticket; 442 | } 443 | return false; 444 | } 445 | 446 | /** 447 | * 获取微信 jsapi_ticket 过期时间戳 448 | */ 449 | public function getCardApiTicketExpireTime(){ 450 | if ($this->card_api_ticket_expire_at && $this->card_api_ticket_expire_at>time()) { 451 | return $this->card_api_ticket_expire_at; 452 | } 453 | null; 454 | } 455 | 456 | 457 | 458 | 459 | /** 460 | * 获取CardApi使用签名 461 | * @param string $url 网页的URL,自动处理#及其后面部分 462 | * @param string $timestamp 当前时间戳 (为空则自动生成) 463 | * @param string $noncestr 随机串 (为空则自动生成) 464 | * @return array|bool 返回签名字串 465 | */ 466 | public function getCardSign($shopid=null, $card_type=null, $cardid=null, $timestamp=0, $noncestr=''){ 467 | 468 | if (!$this->card_api_ticket && !$this->getCardApiTicket($this->appid)) return false; 469 | if (!$timestamp) 470 | $timestamp = time(); 471 | if (!$noncestr) 472 | $noncestr = $this->generateNonceStr(); 473 | 474 | 475 | $arrdata = array($this->appid, $shopid, $card_type,$cardid, $timestamp, $noncestr, $this->jsapi_ticket); 476 | $sign = $this->genCardSignature($arrdata); 477 | if (!$sign) 478 | return false; 479 | $signPackage = array( 480 | "appid" => $this->appid, 481 | "noncestr" => $noncestr, 482 | "timestamp" => $timestamp, 483 | "signature" => $sign 484 | ); 485 | return $signPackage; 486 | } 487 | 488 | 489 | 490 | /** 491 | * 获取CardApiTicket使用签名 cardExt信息 492 | * @param string $url 网页的URL,自动处理#及其后面部分 493 | * @param string $timestamp 当前时间戳 (为空则自动生成) 494 | * @param string $noncestr 随机串 (为空则自动生成) 495 | * @param string $appid 用于多个appid时使用,可空 496 | * @return array|bool 返回签名字串 497 | */ 498 | public function getCardExtSign($cardid=null, $openid=null, $code=null, $timestamp=0, $noncestr=''){ 499 | if (!$this->card_api_ticket && !$this->getCardApiTicket($this->appid)) return false; 500 | if (!$timestamp) 501 | $timestamp = time(); 502 | if (!$noncestr) 503 | $noncestr = $this->generateNonceStr(); 504 | 505 | $arrdata = array($this->appid,$openid, $code, $cardid, $timestamp, $noncestr, $this->card_api_ticket); 506 | $sign = $this->genCardSignature($arrdata); 507 | if (!$sign) 508 | return false; 509 | $signPackage = array( 510 | "appid" => $this->appid, 511 | "noncestr" => $noncestr, 512 | "timestamp" => $timestamp, 513 | "signature" => $sign 514 | ); 515 | return $signPackage; 516 | } 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | /** 525 | * 微信api不支持中文转义的json结构 526 | * @param array $arr 527 | */ 528 | static function json_encode($arr) { 529 | $parts = array (); 530 | $is_list = false; 531 | //Find out if the given array is a numerical array 532 | $keys = array_keys ( $arr ); 533 | $max_length = count ( $arr ) - 1; 534 | if (($keys [0] === 0) && ($keys [$max_length] === $max_length )) { //See if the first key is 0 and last key is length - 1 535 | $is_list = true; 536 | for($i = 0; $i < count ( $keys ); $i ++) { //See if each key correspondes to its position 537 | if ($i != $keys [$i]) { //A key fails at position check. 538 | $is_list = false; //It is an associative array. 539 | break; 540 | } 541 | } 542 | } 543 | foreach ( $arr as $key => $value ) { 544 | if (is_array ( $value )) { //Custom handling for arrays 545 | if ($is_list) 546 | $parts [] = self::json_encode ( $value ); /* :RECURSION: */ 547 | else 548 | $parts [] = '"' . $key . '":' . self::json_encode ( $value ); /* :RECURSION: */ 549 | } else { 550 | $str = ''; 551 | if (! $is_list) 552 | $str = '"' . $key . '":'; 553 | //Custom handling for multiple data types 554 | if (!is_string ( $value ) && is_numeric ( $value ) && $value<2000000000) 555 | $str .= $value; //Numbers 556 | elseif ($value === false) 557 | $str .= 'false'; //The booleans 558 | elseif ($value === true) 559 | $str .= 'true'; 560 | else 561 | $str .= '"' . addslashes ( $value ) . '"'; //All other things 562 | // :TODO: Is there any more datatype we should be in the lookout for? (Object?) 563 | $parts [] = $str; 564 | } 565 | } 566 | $json = implode ( ',', $parts ); 567 | if ($is_list) 568 | return '[' . $json . ']'; //Return numerical JSON 569 | return '{' . $json . '}'; //Return associative JSON 570 | } 571 | 572 | /** 573 | * 获取签名 574 | * @param array $arrdata 签名数组 575 | * @param string $method 签名方法 576 | * @return boolean|string 签名值 577 | */ 578 | public function genSignature($arrdata,$method="sha1",$suffix=null) { 579 | if (!function_exists($method)) return false; 580 | ksort($arrdata); 581 | $paramstring = ""; 582 | foreach($arrdata as $key => $value) 583 | { 584 | if(strlen($paramstring) == 0) 585 | $paramstring .= $key . "=" . $value; 586 | else 587 | $paramstring .= "&" . $key . "=" . $value; 588 | } 589 | $paramstring = $paramstring.$suffix; 590 | // print_r($paramstring); 591 | // echo "\n"; 592 | $Sign = $method($paramstring); 593 | return $Sign; 594 | } 595 | 596 | 597 | 598 | /** 599 | * 计算签名 600 | * @param array $arrdata 签名数组 601 | * @param string $method 签名方法 602 | * @return boolean|string 签名值 603 | */ 604 | public function genCardSignature($arrdata,$method="sha1") { 605 | if (!function_exists($method)) return false; 606 | sort($arrdata); 607 | $paramstring = join("",$arrdata); 608 | $sign = $method($paramstring); 609 | return $sign; 610 | } 611 | 612 | 613 | 614 | /** 615 | * 生成随机字串 616 | * @param number $length 长度,默认为16,最长为32字节 617 | * @return string 618 | */ 619 | public function generateNonceStr($length=16){ 620 | // 密码字符集,可任意添加你需要的字符 621 | $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; 622 | $str = ""; 623 | for($i = 0; $i < $length; $i++) 624 | { 625 | $str .= $chars[mt_rand(0, strlen($chars) - 1)]; 626 | } 627 | return $str; 628 | } 629 | 630 | /** 631 | * 获取微信服务器IP地址列表 632 | * @return array('127.0.0.1','127.0.0.1') 633 | */ 634 | public function getServerIp(){ 635 | if (!$this->wgate_token && !$this->getWgateToken()) return false; 636 | $result = $this->http_get(self::API_URL_PREFIX.self::CALLBACKSERVER_GET_URL.'wgate_token='.$this->wgate_token); 637 | if ($result) 638 | { 639 | $json = json_decode($result,true); 640 | if (!$json || isset($json['errcode'])) { 641 | $this->errCode = $json['errcode']; 642 | $this->errMsg = $json['errmsg']; 643 | return false; 644 | } 645 | return $json['ip_list']; 646 | } 647 | return false; 648 | } 649 | 650 | /** 651 | * For weixin server validation 652 | */ 653 | private function checkSignature($str='') 654 | { 655 | $signature = isset($_GET["signature"])?$_GET["signature"]:''; 656 | $signature = isset($_GET["msg_signature"])?$_GET["msg_signature"]:$signature; //如果存在加密验证则用加密验证段 657 | $timestamp = isset($_GET["timestamp"])?$_GET["timestamp"]:''; 658 | $nonce = isset($_GET["nonce"])?$_GET["nonce"]:''; 659 | 660 | $token = $this->token; 661 | $tmpArr = array($token, $timestamp, $nonce,$str); 662 | sort($tmpArr, SORT_STRING); 663 | $tmpStr = implode( $tmpArr ); 664 | $tmpStr = sha1( $tmpStr ); 665 | 666 | if( $tmpStr == $signature ){ 667 | return true; 668 | }else{ 669 | return false; 670 | } 671 | } 672 | 673 | 674 | 675 | /** 676 | * 日志记录,可被重载。 677 | * @param mixed $log 输入日志 678 | * @return mixed 679 | */ 680 | protected function log($log){ 681 | if ($this->debug && function_exists($this->logcallback)) { 682 | if (is_array($log)) $log = print_r($log,true); 683 | return call_user_func($this->logcallback,$log); 684 | } 685 | } 686 | 687 | 688 | 689 | /** 690 | * GET 请求 691 | * @param string $url 692 | */ 693 | private function http_get($url){ 694 | $oCurl = curl_init(); 695 | if(stripos($url,"https://")!==FALSE){ 696 | curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE); 697 | curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, FALSE); 698 | curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1 699 | } 700 | curl_setopt($oCurl, CURLOPT_URL, $url); 701 | curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 ); 702 | $sContent = curl_exec($oCurl); 703 | $aStatus = curl_getinfo($oCurl); 704 | curl_close($oCurl); 705 | return $sContent; 706 | if(intval($aStatus["http_code"])==200){ 707 | return $sContent; 708 | }else{ 709 | return false; 710 | } 711 | } 712 | 713 | /** 714 | * POST 请求 715 | * @param string $url 716 | * @param array $param 717 | * @param boolean $post_file 是否文件上传 718 | * @return string content 719 | */ 720 | private function http_post($url,$param,$post_file=false){ 721 | $oCurl = curl_init(); 722 | if(stripos($url,"https://")!==FALSE){ 723 | curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE); 724 | curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false); 725 | curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1 726 | } 727 | if (is_string($param) || $post_file) { 728 | $strPOST = $param; 729 | } else { 730 | $aPOST = array(); 731 | foreach($param as $key=>$val){ 732 | $aPOST[] = $key."=".urlencode($val); 733 | } 734 | $strPOST = join("&", $aPOST); 735 | } 736 | curl_setopt($oCurl, CURLOPT_URL, $url); 737 | curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 ); 738 | curl_setopt($oCurl, CURLOPT_POST,true); 739 | curl_setopt($oCurl, CURLOPT_POSTFIELDS,$strPOST); 740 | $sContent = curl_exec($oCurl); 741 | $aStatus = curl_getinfo($oCurl); 742 | curl_close($oCurl); 743 | return $sContent; 744 | if(intval($aStatus["http_code"])==200){ 745 | return $sContent; 746 | }else{ 747 | return false; 748 | } 749 | } 750 | 751 | /** 752 | * 设置缓存,按需重载 753 | * @param string $cachename 754 | * @param mixed $value 755 | * @param int $expired 756 | * @return boolean 757 | */ 758 | protected function setCache($cachename,$value,$expired){ 759 | //TODO: set cache implementation 760 | return false; 761 | } 762 | 763 | /** 764 | * 获取缓存,按需重载 765 | * @param string $cachename 766 | * @return mixed 767 | */ 768 | protected function getCache($cachename){ 769 | //TODO: get cache implementation 770 | return false; 771 | } 772 | 773 | /** 774 | * 清除缓存,按需重载 775 | * @param string $cachename 776 | * @return boolean 777 | */ 778 | protected function removeCache($cachename){ 779 | //TODO: remove cache implementation 780 | return false; 781 | } 782 | 783 | } 784 | 785 | /** 786 | * error code 787 | * 仅用作类内部使用,不用于官方API接口的errCode码 788 | */ 789 | class WgateErrorCode 790 | { 791 | public static $OK = 0; 792 | public static $ValidateSignatureError = 40001; 793 | public static $ParseXmlError = 40002; 794 | public static $ComputeSignatureError = 40003; 795 | public static $IllegalAesKey = 40004; 796 | public static $ValidateAppidError = 40005; 797 | public static $EncryptAESError = 40006; 798 | public static $DecryptAESError = 40007; 799 | public static $IllegalBuffer = 40008; 800 | public static $EncodeBase64Error = 40009; 801 | public static $DecodeBase64Error = 40010; 802 | public static $GenReturnXmlError = 40011; 803 | public static $errCode=array( 804 | '0' => '处理成功', 805 | '40001' => '校验签名失败', 806 | '40002' => '解析xml失败', 807 | '40003' => '计算签名失败', 808 | '40004' => '不合法的AESKey', 809 | '40005' => '校验AppID失败', 810 | '40006' => 'AES加密失败', 811 | '40007' => 'AES解密失败', 812 | '40008' => '公众平台发送的xml不合法', 813 | '40009' => 'Base64编码失败', 814 | '40010' => 'Base64解码失败', 815 | '40011' => '公众帐号生成回包xml失败' 816 | ); 817 | public static function getErrText($err) { 818 | if (isset(self::$errCode[$err])) { 819 | return self::$errCode[$err]; 820 | }else { 821 | return false; 822 | }; 823 | } 824 | } 825 | --------------------------------------------------------------------------------