├── LICENSE ├── MpWechat.php ├── QyWechat.php ├── README.md ├── Wechat.php ├── components ├── BaseWechat.php ├── MessageCrypt.php ├── WechatComponent.php └── messageCrypt │ ├── ReadMe.txt │ ├── demo.php │ ├── errorCode.php │ ├── pkcs7Encoder.php │ ├── sha1.php │ ├── wxBizMsgCrypt.php │ └── xmlparse.php ├── composer.json └── mp ├── Card.php ├── CustomService.php ├── DataCube.php ├── Merchant.php └── ShakeAround.php /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 callmez 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MpWechat.php: -------------------------------------------------------------------------------- 1 | 开发者中心 42 | * @var string 43 | */ 44 | public $token; 45 | /** 46 | * 公众号消息加密键值 47 | * @var string 48 | */ 49 | public $encodingAesKey; 50 | 51 | /** 52 | * @inheritdoc 53 | * @throws InvalidConfigException 54 | */ 55 | public function init() 56 | { 57 | if ($this->appId === null) { 58 | throw new InvalidConfigException('The "appId" property must be set.'); 59 | } elseif ($this->appSecret === null) { 60 | throw new InvalidConfigException('The "appSecret" property must be set.'); 61 | } elseif ($this->token === null) { 62 | throw new InvalidConfigException('The "token" property must be set.'); 63 | } elseif ($this->encodingAesKey === null) { 64 | throw new InvalidConfigException('The "encodingAesKey" property must be set.'); 65 | } 66 | } 67 | 68 | /** 69 | * 获取缓存键值 70 | * @param $name 71 | * @return string 72 | */ 73 | protected function getCacheKey($name) 74 | { 75 | return $this->cachePrefix . '_' . $this->appId . '_' . $name; 76 | } 77 | 78 | /** 79 | * 增加微信基本链接 80 | * @inheritdoc 81 | */ 82 | protected function httpBuildQuery($url, array $options) 83 | { 84 | if (stripos($url, 'http://') === false && stripos($url, 'https://') === false) { 85 | $url = self::WECHAT_BASE_URL . $url; 86 | } 87 | return parent::httpBuildQuery($url, $options); 88 | } 89 | 90 | /** 91 | * @inheritdoc 92 | * @param bool $force 是否强制获取access_token, 该设置会在access_token使用错误时, 是否再获取一次access_token并再重新提交请求 93 | */ 94 | public function parseHttpRequest(callable $callable, $url, $postOptions = null, $force = true) 95 | { 96 | $result = call_user_func_array($callable, [$url, $postOptions]); 97 | if (isset($result['errcode']) && $result['errcode']) { 98 | $this->lastError = $result; 99 | Yii::warning([ 100 | 'url' => $url, 101 | 'result' => $result, 102 | 'postOptions' => $postOptions 103 | ], __METHOD__); 104 | switch ($result ['errcode']) { 105 | case 40001: //access_token 失效,强制更新access_token, 并更新地址重新执行请求 106 | if ($force) { 107 | $url = preg_replace_callback("/access_token=([^&]*)/i", function(){ 108 | return 'access_token=' . $this->getAccessToken(true); 109 | }, $url); 110 | $result = $this->parseHttpRequest($callable, $url, $postOptions, false); // 仅重新获取一次,否则容易死循环 111 | } 112 | break; 113 | } 114 | } 115 | return $result; 116 | } 117 | 118 | /** 119 | * 解析微信服务器请求的xml数据, 如果是加密数据直接自动解密 120 | * @param string $xml 微信请求的XML信息主体, 默认取$_GET数据 121 | * @param string $messageSignature 加密签名, 默认取$_GET数据 122 | * @param string $timestamp 加密时间戳, 默认取$_GET数据 123 | * @param string $nonce 加密随机串, 默认取$_GET数据 124 | * @param string $encryptType 加密类型, 默认取$_GET数据 125 | * @return array 126 | */ 127 | public function parseRequestXml($xml = null, $messageSignature = null, $timestamp = null , $nonce = null, $encryptType = null) 128 | { 129 | $xml === null && $xml = Yii::$app->request->getRawBody(); 130 | $return = []; 131 | if (!empty($xml)) { 132 | $messageSignature === null && isset($_GET['msg_signature']) && $messageSignature = $_GET['msg_signature']; 133 | $encryptType === null && isset($_GET['encrypt_type']) && $encryptType = $_GET['encrypt_type']; 134 | if ($messageSignature !== null && $encryptType == 'aes') { // 自动解密 135 | $timestamp === null && isset($_GET['timestamp']) && $timestamp = $_GET['timestamp']; 136 | $nonce === null && isset($_GET['nonce']) && $nonce = $_GET['nonce']; 137 | $xml = $this->decryptXml($xml, $messageSignature, $timestamp, $nonce); 138 | if ($xml === false) { 139 | return $return; 140 | } 141 | } 142 | $return = (array)simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA); 143 | } 144 | return $return; 145 | } 146 | 147 | /** 148 | * 创建消息加密类 149 | * @return object 150 | */ 151 | protected function createMessageCrypt() 152 | { 153 | return Yii::createObject(MessageCrypt::className(), [$this->token, $this->encodingAesKey, $this->appId]); 154 | } 155 | 156 | /* =================== 基础接口 =================== */ 157 | 158 | /** 159 | * access token获取 160 | */ 161 | const WECHAT_ACCESS_TOKEN_PREFIX = '/cgi-bin/token'; 162 | /** 163 | * 请求服务器access_token 164 | * @param string $grantType 165 | * @return array|bool 166 | */ 167 | protected function requestAccessToken($grantType = 'client_credential') 168 | { 169 | $result = $this->httpGet(self::WECHAT_ACCESS_TOKEN_PREFIX, [ 170 | 'appid' => $this->appId, 171 | 'secret' => $this->appSecret, 172 | 'grant_type' => $grantType 173 | ]); 174 | return isset($result['access_token']) ? $result : false; 175 | } 176 | 177 | /** 178 | * 获取微信服务器IP地址 179 | */ 180 | const WECHAT_IP_PREFIX = '/cgi-bin/getcallbackip'; 181 | /** 182 | * 获取微信服务器IP地址 183 | * @return array|bool 184 | * @throws \yii\web\HttpException 185 | */ 186 | public function getIp() 187 | { 188 | $result = $this->httpGet(self::WECHAT_IP_PREFIX, [ 189 | 'access_token' => $this->getAccessToken() 190 | ]); 191 | return isset($result['ip_list']) ? $result['ip_list'] : false; 192 | } 193 | 194 | /* =================== 接收消息 =================== */ 195 | 196 | /** 197 | * 微信服务器请求签名检测 198 | * @param string $signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。 199 | * @param string $timestamp 时间戳 200 | * @param string $nonce 随机数 201 | * @return bool 202 | */ 203 | public function checkSignature($signature = null, $timestamp = null, $nonce = null) 204 | { 205 | $signature === null && isset($_GET['signature']) && $signature = $_GET['signature']; 206 | $timestamp === null && isset($_GET['timestamp']) && $timestamp = $_GET['timestamp']; 207 | $nonce === null && isset($_GET['nonce']) && $nonce = $_GET['nonce']; 208 | $tmpArr = [$this->token, $timestamp, $nonce]; 209 | sort($tmpArr, SORT_STRING); 210 | $tmpStr = implode($tmpArr); 211 | return sha1($tmpStr) == $signature; 212 | } 213 | 214 | /* =================== 发送消息 =================== */ 215 | 216 | // 多客服部分 @see self::getCustomService() 217 | 218 | /** 219 | * 发送客服消息 220 | */ 221 | const WECHAT_CUSTOM_MESSAGE_SEND_PREFIX = '/cgi-bin/message/custom/send'; 222 | /** 223 | * 发送客服消息 224 | * @param array $data 225 | * @return bool 226 | * @throws \yii\web\HttpException 227 | */ 228 | public function sendMessage(array $data) 229 | { 230 | $result = $this->httpRaw(self::WECHAT_CUSTOM_MESSAGE_SEND_PREFIX, $data, [ 231 | 'access_token' => $this->getAccessToken() 232 | ]); 233 | return isset($result['errmsg']) && $result['errmsg'] == 'ok'; 234 | } 235 | 236 | /** 237 | * 消息上传 238 | */ 239 | const WECHAT_ARTICLES_UPLOAD_PREFIX = '/cgi-bin/media/uploadnews'; 240 | /** 241 | * 上传图文消息素材【订阅号与服务号认证后均可用】 242 | * @param array $articles 243 | * ~~~ 244 | * $articles = [ 245 | * [ 246 | * 'thumb_media_id' => 'qI6_Ze_6PtV7svjolgs-rN6stStuHIjs9_DidOHaj0Q-mwvBelOXCFZiq2OsIU-p', 247 | * 'author' => 'xxx', 248 | * 'title' => 'Happy Day', 249 | * 'content_source_url' => 'www.qq.com', 250 | * 'content' => 'content', 251 | * 'digest' => 'digest', 252 | * 'show_cover_pic' => '1' 253 | * ] 254 | * ... 255 | * ]; 256 | * 257 | * ~~~ 258 | * @return array|bool 259 | */ 260 | public function uploadArticles(array $articles) 261 | { 262 | $result = $this->httpRaw(self::WECHAT_ARTICLES_UPLOAD_PREFIX, [ 263 | 'articles' => $articles 264 | ], [ 265 | 'access_token' => $this->getAccessToken() 266 | ]); 267 | return isset($result['media_id']) ? $result : false; 268 | } 269 | 270 | /** 271 | * 上传视频 272 | */ 273 | const WECHAT_VIDEO_UPLOAD_URL = 'https://file.api.weixin.qq.com/cgi-bin/media/uploadvideo'; 274 | /** 275 | * 上传视频 276 | * @param $videoPath 277 | * @return bool|mixed 278 | * @throws \yii\web\HttpException 279 | */ 280 | public function uploadVideo($videoPath) 281 | { 282 | $result = $this->httpPost(self::WECHAT_VIDEO_UPLOAD_URL, [ 283 | 'media' => $this->uploadFile($videoPath) 284 | ], [ 285 | 'access_token' => $this->getAccessToken() 286 | ]); 287 | return isset($result['media_id']) ? $result : false; 288 | } 289 | 290 | /** 291 | * 高级群发接口 292 | */ 293 | const WECHAT_SEND_ALL_PREFIX = '/cgi-bin/message/mass/sendall'; 294 | /** 295 | * 高级群发接口 296 | * @return bool 297 | * @throws \yii\web\HttpException 298 | */ 299 | public function sendAll(array $data) 300 | { 301 | $result = $this->httpRaw(self::WECHAT_SEND_ALL_PREFIX, $data, [ 302 | 'access_token' => $this->getAccessToken() 303 | ]); 304 | return isset($result['errcode']) && !$result['errcode']; 305 | } 306 | 307 | /** 308 | * 删除群发【订阅号与服务号认证后均可用】 309 | */ 310 | const WECHAT_SENDED_ALL_DELETE_PREFIX = '/cgi-bin/message/mass/delete'; 311 | /** 312 | * 删除群发【订阅号与服务号认证后均可用】 313 | * @param $messageId 314 | * @return bool 315 | * @throws \yii\web\HttpException 316 | */ 317 | public function deleteSendedAll($messageId) 318 | { 319 | $result = $this->httpRaw(self::WECHAT_SENDED_ALL_DELETE_PREFIX, [ 320 | 'msgid' => $messageId 321 | ], [ 322 | 'access_token' => $this->getAccessToken() 323 | ]); 324 | return isset($result['errmsg']) && $result['errmsg'] == 'ok'; 325 | } 326 | 327 | /** 328 | * 群发预览接口【订阅号与服务号认证后均可用】 329 | */ 330 | const WECHAT_SEND_ALL_PREVIEW_PREFIX = '/cgi-bin/message/mass/preview'; 331 | /** 332 | * 群发预览接口【订阅号与服务号认证后均可用】 333 | * @param array $data 334 | * @return bool 335 | * @throws \yii\web\HttpException 336 | */ 337 | public function previewSendAll(array $data) 338 | { 339 | $result = $this->httpRaw(self::WECHAT_SEND_ALL_PREVIEW_PREFIX, $data, [ 340 | 'access_token' => $this->getAccessToken() 341 | ]); 342 | return isset($result['errcode']) && !$result['errcode']; 343 | } 344 | 345 | /** 346 | * 查询群发消息发送状态【订阅号与服务号认证后均可用】 347 | */ 348 | const WECHAT_SEND_ALL_STATUS = '/cgi-bin/message/mass/get'; 349 | /** 350 | * 查询群发消息发送状态【订阅号与服务号认证后均可用】 351 | * @param $messageId 352 | * @return bool|mixed 353 | * @throws \yii\web\HttpException 354 | */ 355 | public function getSendAllStatus($messageId) 356 | { 357 | $result = $this->httpRaw(self::WECHAT_SEND_ALL_STATUS, [ 358 | 'msgid' => $messageId 359 | ], [ 360 | 'access_token' => $this->getAccessToken() 361 | ]); 362 | return isset($result['msg_status']) ? $result : false; 363 | } 364 | 365 | /** 366 | * 设置所属行业 367 | */ 368 | const WECHAT_TEMPLATE_INDUSTRY_SET_PREFIX = '/cgi-bin/template/api_set_industry'; 369 | /** 370 | * 设置所属行业 371 | * @param array $data 372 | * @return bool 373 | * @throws \yii\web\HttpException 374 | */ 375 | public function setTemplateIndustry(array $data) 376 | { 377 | $result = $this->httpRaw(self::WECHAT_TEMPLATE_INDUSTRY_SET_PREFIX, $data, [ 378 | 'access_token' => $this->getAccessToken() 379 | ]); 380 | return isset($result['errcode']) && !$result['errcode']; 381 | } 382 | 383 | /** 384 | *获得模板ID 385 | */ 386 | const WECHAT_TEMPLATE_ID_GET_PREFIX = '/cgi-bin/template/api_add_template'; 387 | /** 388 | * 获得模板ID 389 | * @param $shortId 390 | * @return bool 391 | * @throws \yii\web\HttpException 392 | */ 393 | public function getTemplateId($shortId) 394 | { 395 | $result = $this->httpRaw(self::WECHAT_TEMPLATE_ID_GET_PREFIX, [ 396 | 'template_id_short' => $shortId 397 | ], [ 398 | 'access_token' => $this->getAccessToken() 399 | ]); 400 | return isset($result['template_id']) ? $result['template_id'] : false; 401 | } 402 | 403 | /** 404 | * 发送模板消息 405 | */ 406 | const WECHAT_TEMPLATE_MESSAGE_SEND_PREFIX = '/cgi-bin/message/template/send'; 407 | /** 408 | * 发送模板消息 409 | * @param array $data 模板需要的数据 410 | * @return int|bool 411 | */ 412 | public function sendTemplateMessage(array $data) 413 | { 414 | $result = $this->httpRaw(self::WECHAT_TEMPLATE_MESSAGE_SEND_PREFIX, array_merge([ 415 | 'url' => null, 416 | 'topcolor' => '#FF0000' 417 | ], $data), [ 418 | 'access_token' => $this->getAccessToken() 419 | ]); 420 | return isset($result['msgid']) ? $result['msgid'] : false; 421 | } 422 | 423 | /** 424 | * 获取自动回复规则 425 | */ 426 | const WECHAT_AUTO_REPLY_INFO_GET_PREFIX = '/cgi-bin/get_current_autoreply_info'; 427 | /** 428 | * 获取自动回复规则 429 | * @return bool|mixed 430 | * @throws \yii\web\HttpException 431 | */ 432 | public function getAutoReplyInfo() 433 | { 434 | $result = $this->httpGet(self::WECHAT_AUTO_REPLY_INFO_GET_PREFIX, [ 435 | 'access_token' => $this->getAccessToken() 436 | ]); 437 | return !array_key_exists('errcode', $result) ? $result : false; 438 | } 439 | 440 | /* =================== 素材管理 =================== */ 441 | 442 | /** 443 | * 新增临时素材(上传临时多媒体文件) 444 | */ 445 | const WECHAT_MEDIA_UPLOAD_PREFIX = '/cgi-bin/media/upload'; 446 | /** 447 | * 新增临时素材(上传临时多媒体文件) 448 | * @param $mediaPath 449 | * @param $type 450 | * @return bool|mixed 451 | * @throws \yii\web\HttpException 452 | */ 453 | public function uploadMedia($mediaPath, $type) 454 | { 455 | $result = $this->httpPost(self::WECHAT_MEDIA_UPLOAD_PREFIX, [ 456 | 'media' => $this->uploadFile($mediaPath) 457 | ], [ 458 | 'access_token' => $this->getAccessToken(), 459 | 'type' => $type 460 | ]); 461 | return isset($result['media_id']) ? $result : false; 462 | } 463 | 464 | /** 465 | * 获取临时素材(下载多媒体文件) 466 | */ 467 | const WECHAT_MEDIA_GET_PREFIX = '/cgi-bin/media/get'; 468 | /** 469 | * 获取临时素材(下载多媒体文件) 470 | * @param $mediaId 471 | * @return bool|string 472 | * @throws \yii\web\HttpException 473 | */ 474 | public function getMedia($mediaId) 475 | { 476 | $result = $this->httpGet(self::WECHAT_MEDIA_GET_PREFIX, [ 477 | 'access_token' => $this->getAccessToken(), 478 | 'media_id' => $mediaId 479 | ]); 480 | return is_string($result) ? $result : false; 481 | } 482 | 483 | /** 484 | * 新增永久图文素材 485 | */ 486 | const WECHAT_NEWS_MATERIAL_ADD_PREFIX = '/cgi-bin/material/add_news'; 487 | /** 488 | * 新增永久图文素材 489 | * @param array $articles 490 | * @return string|bool 491 | * @throws \yii\web\HttpException 492 | */ 493 | public function addNewsMaterial(array $articles) 494 | { 495 | $result = $this->httpRaw(self::WECHAT_NEWS_MATERIAL_ADD_PREFIX, [ 496 | 'articles' => $articles 497 | ], [ 498 | 'access_token' => $this->getAccessToken() 499 | ]); 500 | return isset($result['media_id']) ? $result['media_id'] : false; 501 | } 502 | 503 | /** 504 | * 新增其他类型永久素材 505 | */ 506 | const WECHAT_MATERIAL_ADD_PREFIX = '/cgi-bin/material/add_material'; 507 | /** 508 | * 新增其他类型永久素材 509 | * @param string $mediaPath 510 | * @param string $type 511 | * @param array $data 视频素材需要description 512 | * @return bool|mixed 513 | * @throws \yii\web\HttpException 514 | */ 515 | public function addMaterial($mediaPath, $type, $data = []) 516 | { 517 | $result = $this->httpPost(self::WECHAT_MATERIAL_ADD_PREFIX, array_merge($data, [ 518 | 'media' => $this->uploadFile($mediaPath) 519 | ]), [ 520 | 'access_token' => $this->getAccessToken(), 521 | 'type' => $type 522 | ]); 523 | return isset($result['media_id']) ? $result : false; 524 | } 525 | 526 | /** 527 | * 获取永久素材 528 | */ 529 | const WECHAT_MATERIAL_GET_PREFIX = '/cgi-bin/material/get_material'; 530 | /** 531 | * 获取永久素材 532 | * @param $mediaId 533 | * @return bool|string 534 | * @throws \yii\web\HttpException 535 | */ 536 | public function getMaterial($mediaId) 537 | { 538 | $result = $this->httpGet(self::WECHAT_MATERIAL_GET_PREFIX, [ 539 | 'access_token' => $this->getAccessToken(), 540 | 'media_id' => $mediaId 541 | ]); 542 | return !array_key_exists('errcode', $result) ? $result : false; 543 | } 544 | 545 | /** 546 | * 删除永久素材 547 | */ 548 | const WECHAT_MATERIAL_DELETE_PREFIX = '/cgi-bin/material/del_material'; 549 | /** 550 | * 删除永久素材 551 | * @param $mediaId 552 | * @return bool 553 | * @throws \yii\web\HttpException 554 | */ 555 | public function deleteMaterial($mediaId) 556 | { 557 | $result = $this->httpRaw(self::WECHAT_MATERIAL_DELETE_PREFIX, [ 558 | 'media_id' => $mediaId 559 | ], [ 560 | 'access_token' => $this->getAccessToken() 561 | ]); 562 | return isset($result['errcode']) && !$result['errcode']; 563 | } 564 | 565 | /** 566 | * 修改永久图文素材 567 | */ 568 | const WECHAT_NEWS_MATERIAL_UPDATE_PREFIX = '/cgi-bin/material/update_news'; 569 | /** 570 | * 修改永久图文素材 571 | * @param array $data 572 | * @return bool 573 | * @throws \yii\web\HttpException 574 | */ 575 | public function updateNewsMaterial(array $data) 576 | { 577 | $result = $this->httpRaw(self::WECHAT_MATERIAL_DELETE_PREFIX, $data, [ 578 | 'access_token' => $this->getAccessToken() 579 | ]); 580 | return isset($result['errcode']) && !$result['errcode']; 581 | } 582 | 583 | /** 584 | * 获取素材总数 585 | */ 586 | const WECHAT_MATERIAL_COUNT_GET_PREFIX = '/cgi-bin/material/get_materialcount'; 587 | /** 588 | * 获取素材总数 589 | * @return bool|mixed 590 | * @throws \yii\web\HttpException 591 | */ 592 | public function getMaterialCount() 593 | { 594 | $result = $this->httpGet(self::WECHAT_MATERIAL_COUNT_GET_PREFIX, [ 595 | 'access_token' => $this->getAccessToken() 596 | ]); 597 | return !array_key_exists('errorcode', $result) ? $result : false; 598 | } 599 | 600 | /** 601 | * 获取素材列表 602 | */ 603 | const WECHAT_MATERIAL_LIST_GET_PREFIX = '/cgi-bin/material/batchget_material'; 604 | /** 605 | * 获取素材列表 606 | * @param $data 607 | * @return bool|mixed 608 | * @throws \yii\web\HttpException 609 | */ 610 | public function getMaterialList($data) 611 | { 612 | $result = $this->httpRaw(self::WECHAT_MATERIAL_LIST_GET_PREFIX, $data, [ 613 | 'access_token' => $this->getAccessToken() 614 | ]); 615 | return !isset($result['errodcode']) ? $result : false; 616 | } 617 | 618 | /* =================== 用户管理 =================== */ 619 | 620 | /** 621 | * 创建分组 622 | */ 623 | const WECHAT_GROUP_CREATE_PREFIX = '/cgi-bin/groups/create'; 624 | /** 625 | * 创建分组 626 | * @param $group 627 | * @return bool 628 | * @throws \yii\web\HttpException 629 | */ 630 | public function createGroup($group) 631 | { 632 | $result = $this->httpRaw(self::WECHAT_GROUP_CREATE_PREFIX, [ 633 | 'group' => $group 634 | ], [ 635 | 'access_token' => $this->getAccessToken() 636 | ]); 637 | return isset($result['group']) ? $result['group'] : false; 638 | } 639 | 640 | /** 641 | * 查询所有分组 642 | */ 643 | const WECHAT_GROUP_LIST_GET_PREFIX = '/cgi-bin/groups/get'; 644 | /** 645 | * 查询所有分组 646 | * @return bool 647 | * @throws \yii\web\HttpException 648 | */ 649 | public function getGroupList() 650 | { 651 | $result = $this->httpGet(self::WECHAT_GROUP_LIST_GET_PREFIX, [ 652 | 'access_token' => $this->getAccessToken() 653 | ]); 654 | return isset($result['groups']) ? $result['groups'] : false; 655 | } 656 | 657 | /** 658 | * 查询用户所在分组 659 | */ 660 | const WECHAT_USER_GROUP_ID_GET_PREFIX = '/cgi-bin/groups/getid'; 661 | /** 662 | * 查询用户所在分组 663 | * @param $openId 664 | * @return bool 665 | * @throws \yii\web\HttpException 666 | */ 667 | public function getUserGroupId($openId) 668 | { 669 | $result = $this->httpRaw(self::WECHAT_USER_GROUP_ID_GET_PREFIX, [ 670 | 'openid' => $openId 671 | ], [ 672 | 'access_token' => $this->getAccessToken() 673 | ]); 674 | return isset($result['groupid']) ? $result['groupid'] : false; 675 | } 676 | 677 | /** 678 | * 修改分组名 679 | */ 680 | const WECHAT_GROUP_UPDATE_PREFIX = '/cgi-bin/groups/update'; 681 | /** 682 | * 修改分组名 683 | * @param array $group 684 | * @return bool 685 | * @throws \yii\web\HttpException 686 | */ 687 | public function updateGroup(array $group) 688 | { 689 | $result = $this->httpRaw(self::WECHAT_GROUP_UPDATE_PREFIX, [ 690 | 'group' => $group 691 | ], [ 692 | 'access_token' => $this->getAccessToken() 693 | ]); 694 | return isset($result['errmsg']) && $result['errmsg'] == 'ok'; 695 | } 696 | 697 | /** 698 | * 移动用户分组 699 | */ 700 | const WECHAT_USER_GROUP_UPDATE_PREFIX = '/cgi-bin/groups/members/update'; 701 | /** 702 | * 移动用户分组 703 | * @param array $data 704 | * @return bool 705 | * @throws \yii\web\HttpException 706 | */ 707 | public function updateUserGroup(array $data) 708 | { 709 | $result = $this->httpRaw(self::WECHAT_MEMBER_GROUP_UPDATE_PREFIX, $data, [ 710 | 'access_token' => $this->getAccessToken() 711 | ]); 712 | return isset($result['errmsg']) && $result['errmsg'] == 'ok'; 713 | } 714 | 715 | /** 716 | * 批量移动用户分组 717 | */ 718 | const WECHAT_USERS_GROUP_UPDATE_PREFIX = '/cgi-bin/groups/members/batchupdate'; 719 | /** 720 | * 批量移动用户分组 721 | * @param array $data 722 | * @return bool 723 | * @throws \yii\web\HttpException 724 | */ 725 | public function updateUsersGroup(array $data) 726 | { 727 | $result = $this->httpRaw(self::WECHAT_USERS_GROUP_UPDATE_PREFIX, $data, [ 728 | 'access_token' => $this->getAccessToken() 729 | ]); 730 | return isset($result['errmsg']) && $result['errmsg'] == 'ok'; 731 | } 732 | 733 | /** 734 | * 删除分组 735 | */ 736 | const WECHAT_GROUP_DELETE_PREFIX = '/cgi-bin/groups/delete'; 737 | /** 738 | * 删除分组 739 | * @param $groupId 740 | * @return bool 741 | * @throws \yii\web\HttpException 742 | */ 743 | public function deletGroup($groupId) 744 | { 745 | $result = $this->httpRaw(self::WECHAT_GROUP_DELETE_PREFIX, [ 746 | 'group' => [ 747 | 'id' => $groupId 748 | ] 749 | ], [ 750 | 'access_token' => $this->getAccessToken() 751 | ]); 752 | return isset($result['errmsg']) && $result['errmsg'] == 'ok'; 753 | } 754 | 755 | /** 756 | * 设置用户备注名 757 | */ 758 | const WEHCAT_USER_MARK_UPDATE = '/cgi-bin/user/info/updateremark'; 759 | /** 760 | * 设置用户备注名 761 | * @param array $data 762 | * @return bool 763 | * @throws \yii\web\HttpException 764 | */ 765 | public function updateUserMark(array $data) 766 | { 767 | $result = $this->httpRaw(self::WEHCAT_USER_MARK_UPDATE, $data, [ 768 | 'access_token' => $this->getAccessToken() 769 | ]); 770 | return isset($result['errmsg']) && $result['errmsg'] == 'ok'; 771 | } 772 | 773 | /** 774 | * 获取用户基本信息(UnionID机制) 775 | */ 776 | const WECHAT_USER_INFO_GET = '/cgi-bin/user/info'; 777 | /** 778 | * 获取用户基本信息(UnionID机制) 779 | * @param $openId 780 | * @param string $lang 781 | * @return bool|mixed 782 | * @throws \yii\web\HttpException 783 | */ 784 | public function getUserInfo($openId, $lang = 'zh_CN') 785 | { 786 | $result = $this->httpGet(self::WECHAT_USER_INFO_GET, [ 787 | 'access_token' => $this->getAccessToken(), 788 | 'openid' => $openId, 789 | 'lang' => $lang 790 | ]); 791 | return !array_key_exists('errcode', $result) ? $result : false; 792 | } 793 | 794 | /** 795 | * 获取用户列表 796 | */ 797 | const WECHAT_USER_LIST_GET_PREFIX = '/cgi-bin/user/get'; 798 | /** 799 | * 获取用户列表 800 | * @param $nextOpenId 801 | * @return bool|mixed 802 | * @throws \yii\web\HttpException 803 | */ 804 | public function getUserList($nextOpenId) 805 | { 806 | $result = $this->httpGet(self::WECHAT_USER_LIST_GET_PREFIX, [ 807 | 'access_token' => $this->getAccessToken(), 808 | 'next_openid' => $nextOpenId, 809 | ]); 810 | return array_key_exists('errcode', $result) ? $result : false; 811 | } 812 | 813 | /* ==== 网页授权 ===== */ 814 | 815 | /** 816 | * 用户同意授权,获取code 817 | */ 818 | const WECHAT_OAUTH2_AUTHORIZE_URL = 'https://open.weixin.qq.com/connect/oauth2/authorize'; 819 | /** 820 | * 用户同意授权,获取code:第一步 821 | * 通过此函数生成授权url 822 | * @param $redirectUrl 授权后重定向的回调链接地址,请使用urlencode对链接进行处理 823 | * @param string $state 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值 824 | * @param string $scope 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid), 825 | * snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息) 826 | * @return string 827 | */ 828 | public function getOauth2AuthorizeUrl($redirectUrl, $state = 'authorize', $scope = 'snsapi_base') 829 | { 830 | return $this->httpBuildQuery(self::WECHAT_OAUTH2_AUTHORIZE_URL, [ 831 | 'appid' => $this->appId, 832 | 'redirect_uri' => $redirectUrl, 833 | 'response_type' => 'code', 834 | 'scope' => $scope, 835 | 'state' => $state, 836 | ]) . '#wechat_redirect'; 837 | } 838 | 839 | /** 840 | * 通过code换取网页授权access_token 841 | */ 842 | const WECHAT_OAUTH2_ACCESS_TOKEN_PREFIX = '/sns/oauth2/access_token'; 843 | /** 844 | * 通过code换取网页授权access_token:第二步 845 | * 通过跳转到getOauth2AuthorizeUrl返回的授权code获取用户资料 (该函数和getAccessToken函数作用不同.请参考文档) 846 | * @param $code 847 | * @param string $grantType 848 | * @return array 849 | */ 850 | public function getOauth2AccessToken($code, $grantType = 'authorization_code') 851 | { 852 | $result = $this->httpGet(self::WECHAT_OAUTH2_ACCESS_TOKEN_PREFIX, [ 853 | 'appid' => $this->appId, 854 | 'secret' => $this->appSecret, 855 | 'code' => $code, 856 | 'grant_type' => $grantType 857 | ]); 858 | return !array_key_exists('errcode', $result) ? $result : false; 859 | } 860 | 861 | /** 862 | * 刷新access_token 863 | */ 864 | const WECHAT_OAUTH2_ACCESS_TOKEN_REFRESH_PREFIX = '/sns/oauth2/refresh_token'; 865 | /** 866 | * 刷新access_token:第三步(非必须) 867 | * 由于access_token拥有较短的有效期,当access_token超时后,可以使用refresh_token进行刷新 868 | * refresh_token拥有较长的有效期(7天、30天、60天、90天),当refresh_token失效的后,需要用户重新授权。 869 | * @param $refreshToken 870 | * @param string $grantType 871 | * @return array|bool 872 | */ 873 | public function refreshOauth2AccessToken($refreshToken, $grantType = 'refresh_token') 874 | { 875 | $result = $this->httpGet(self::WECHAT_OAUTH2_ACCESS_TOKEN_REFRESH_PREFIX, [ 876 | 'appid' => $this->appId, 877 | 'grant_type' => $grantType, 878 | 'refresh_token' => $refreshToken 879 | ]); 880 | return !array_key_exists('errcode', $result) ? $result : false; 881 | } 882 | 883 | /** 884 | * 拉取用户信息(需scope为 snsapi_userinfo) 885 | */ 886 | const WEHCAT_SNS_USER_INFO_PREFIX = '/sns/userinfo'; 887 | /** 888 | * 拉取用户信息(需scope为 snsapi_userinfo):第四步 889 | * @param $openId 890 | * @param string $oauth2AccessToken 891 | * @param string $lang 892 | * @return array|bool 893 | */ 894 | public function getSnsUserInfo($openId, $oauth2AccessToken, $lang = 'zh_CN') 895 | { 896 | $result = $this->httpGet(self::WEHCAT_SNS_USER_INFO_PREFIX, [ 897 | 'access_token' => $oauth2AccessToken, 898 | 'openid' => $openId, 899 | 'lang' => $lang 900 | ]); 901 | return !array_key_exists('errcode', $result) ? $result : false; 902 | } 903 | 904 | /** 905 | * 检验授权凭证(access_token)是否有效 906 | */ 907 | const WECHAT_SNS_AUTH_PREFIX = '/sns/auth'; 908 | /** 909 | * 检验授权凭证(access_token)是否有效 910 | * @param $accessToken 911 | * @param $openId 912 | * @return bool 913 | */ 914 | public function checkOauth2AccessToken($accessToken, $openId) 915 | { 916 | $result = $this->httpGet(self::WECHAT_SNS_AUTH_PREFIX, [ 917 | 'access_token' => $accessToken, 918 | 'openid' => $openId 919 | ]); 920 | return isset($result['errmsg']) && $result['errmsg'] == 'ok'; 921 | } 922 | 923 | /* =================== 自定义管理 =================== */ 924 | 925 | /** 926 | * 自定义菜单创建接口 927 | */ 928 | const WECHAT_MENU_CREATE_PREFIX = '/cgi-bin/menu/create'; 929 | /** 930 | * 自定义菜单创建接口(创建菜单) 931 | * @param array $buttons 菜单结构字符串 932 | * ~~~ 933 | * $this->createMenu([ 934 | * [ 935 | * 'type' => 'click', 936 | * 'name' => '今日歌曲', 937 | * 'key' => 'V1001_TODAY_MUSIC' 938 | * ], 939 | * [ 940 | * 'type' => 'view', 941 | * 'name' => '搜索', 942 | * 'url' => 'http://www.soso.com' 943 | * ] 944 | * ... 945 | * ]); 946 | * ~~~ 947 | * @return bool 948 | */ 949 | public function createMenu(array $buttons) 950 | { 951 | $result = $this->httpRaw(self::WECHAT_MENU_CREATE_PREFIX, [ 952 | 'button' => $buttons 953 | ], [ 954 | 'access_token' => $this->getAccessToken() 955 | ]); 956 | return isset($result['errmsg']) && $result['errmsg'] == 'ok'; 957 | } 958 | 959 | /** 960 | * 自定义菜单查询 961 | */ 962 | const WECHAT_MENU_GET_PREFIX = '/cgi-bin/menu/get'; 963 | /** 964 | * 自定义菜单查询接口(获取菜单) 965 | * @return bool 966 | */ 967 | public function getMenu() 968 | { 969 | $result = $this->httpGet(self::WECHAT_MENU_GET_PREFIX, [ 970 | 'access_token' => $this->getAccessToken() 971 | ]); 972 | return isset($result['menu']['button']) ? $result['menu']['button'] : false; 973 | } 974 | 975 | /** 976 | * 自定义菜单删除接口(删除菜单) 977 | */ 978 | const WECHAT_MENU_DELETE_PREFIX = '/cgi-bin/menu/delete'; 979 | /** 980 | * 自定义菜单删除接口(删除菜单) 981 | * @return bool 982 | */ 983 | public function deleteMenu() 984 | { 985 | $result = $this->httpGet(self::WECHAT_MENU_DELETE_PREFIX, [ 986 | 'access_token' => $this->getAccessToken() 987 | ]); 988 | return isset($result['errmsg']) && $result['errmsg'] == 'ok'; 989 | } 990 | 991 | /** 992 | * 获取自定义菜单配置接口 993 | */ 994 | const WECHAT_MENU_INFO_GET_PREFIX = '/cgi-bin/get_current_selfmenu_info'; 995 | /** 996 | * 获取自定义菜单配置接口 997 | * @return bool|mixed 998 | * @throws \yii\web\HttpException 999 | */ 1000 | public function getMenuInfo() 1001 | { 1002 | $result = $this->httpGet(self::WECHAT_MENU_INFO_GET_PREFIX, [ 1003 | 'access_token' => $this->getAccessToken() 1004 | ]); 1005 | return !array_key_exists('errcode', $result) ? $result : false; 1006 | } 1007 | 1008 | /* =================== 账号管理 =================== */ 1009 | 1010 | /** 1011 | * 创建二维码ticket 1012 | */ 1013 | const WECHAT_QR_CODE_CREATE_PREFIX = '/cgi-bin/qrcode/create'; 1014 | /** 1015 | * 创建二维码ticket 1016 | * @param arary $data 1017 | * @return bool|mixed 1018 | * @throws \yii\web\HttpException 1019 | */ 1020 | public function createQrCode(array $data) 1021 | { 1022 | $result = $this->httpRaw(self::WECHAT_QR_CODE_CREATE_PREFIX, $data, [ 1023 | 'access_token' => $this->getAccessToken() 1024 | ]); 1025 | return !array_key_exists('errcode', $result) ? $result : false; 1026 | } 1027 | 1028 | /** 1029 | * 通过ticket换取二维码 1030 | */ 1031 | const WECHAT_QR_CODE_GET_URL = 'https://mp.weixin.qq.com/cgi-bin/showqrcode'; 1032 | /** 1033 | * 通过ticket换取二维码 1034 | * ticket正确情况下,http 返回码是200,是一张图片,可以直接展示或者下载。 1035 | * @param $ticket 1036 | * @return string 1037 | */ 1038 | public function getQrCode($ticket) 1039 | { 1040 | return $this->httpBuildQuery(self::WECHAT_QR_CODE_GET_URL, ['ticket' => $ticket]); 1041 | } 1042 | 1043 | /** 1044 | * 长链接转短链接接口 1045 | */ 1046 | const WECHAT_SHORT_URL_CREATE_PREFIX = '/cgi-bin/shorturl'; 1047 | /** 1048 | * 长链接转短链接接口 1049 | * @param $longUrl 需要转换的长链接,支持http://、https://、weixin://wxpay 格式的url 1050 | * @return bool 1051 | */ 1052 | public function getShortUrl($longUrl) 1053 | { 1054 | $result = $this->httpRaw(self::WECHAT_SHORT_URL_CREATE_PREFIX, [ 1055 | 'action' => 'long2short', 1056 | 'long_url' => $longUrl, 1057 | ], [ 1058 | 'access_token' => $this->getAccessToken() 1059 | ]); 1060 | return isset($result['errmsg']) && $result['errmsg'] == 'ok' ? $result['short_url'] : false; 1061 | } 1062 | 1063 | /* =================== 数据统计接口 =================== */ 1064 | 1065 | /** 1066 | * @var object 1067 | */ 1068 | private $_dataCube; 1069 | /** 1070 | * 数据统计组件 1071 | * @return object 1072 | */ 1073 | public function getDataCube() 1074 | { 1075 | if ($this->_dataCube === null) { 1076 | $this->_dataCube = Yii::createObject(DataCube::className(), [$this]); 1077 | } 1078 | return $this->_dataCube; 1079 | } 1080 | 1081 | /* =================== 微信JS-SDK =================== */ 1082 | 1083 | /** 1084 | * js api ticket 获取 1085 | */ 1086 | const WECHAT_JS_API_TICKET_PREFIX = '/cgi-bin/ticket/getticket'; 1087 | /** 1088 | * 请求服务器jsapi_ticket 1089 | * @param string $type 1090 | * @return array|bool 1091 | */ 1092 | protected function requestJsApiTicket($type = 'jsapi') 1093 | { 1094 | $result = $this->httpGet(self::WECHAT_JS_API_TICKET_PREFIX, [ 1095 | 'access_token' => $this->getAccessToken(), 1096 | 'type' => $type 1097 | ]); 1098 | return isset($result['ticket']) ? $result : false; 1099 | } 1100 | 1101 | /** 1102 | * 生成js 必需的config 1103 | * 只需在视图文件输出JS代码: 1104 | * wx.config(jsApiConfig()) ?>); // 默认全权限 1105 | * wx.config(jsApiConfig([ // 只允许使用分享到朋友圈功能 1106 | * 'jsApiList' => [ 1107 | * 'onMenuShareTimeline' 1108 | * ] 1109 | * ])) ?>); 1110 | * @param array $config 1111 | * @return array 1112 | * @throws HttpException 1113 | */ 1114 | public function jsApiConfig(array $config = []) 1115 | { 1116 | $data = [ 1117 | 'jsapi_ticket' => $this->getJsApiTicket(), 1118 | 'noncestr' => Yii::$app->security->generateRandomString(16), 1119 | 'timestamp' => $_SERVER['REQUEST_TIME'], 1120 | 'url' => explode('#', Yii::$app->request->getAbsoluteUrl())[0] 1121 | ]; 1122 | return array_merge([ 1123 | 'debug' => YII_DEBUG, 1124 | 'appId' => $this->appId, 1125 | 'timestamp' => $data['timestamp'], 1126 | 'nonceStr' => $data['noncestr'], 1127 | 'signature' => sha1(urldecode(http_build_query($data))), 1128 | 'jsApiList' => [ 1129 | 'checkJsApi', 1130 | 'onMenuShareTimeline', 1131 | 'onMenuShareAppMessage', 1132 | 'onMenuShareQQ', 1133 | 'onMenuShareWeibo', 1134 | 'hideMenuItems', 1135 | 'showMenuItems', 1136 | 'hideAllNonBaseMenuItem', 1137 | 'showAllNonBaseMenuItem', 1138 | 'translateVoice', 1139 | 'startRecord', 1140 | 'stopRecord', 1141 | 'onRecordEnd', 1142 | 'playVoice', 1143 | 'pauseVoice', 1144 | 'stopVoice', 1145 | 'uploadVoice', 1146 | 'downloadVoice', 1147 | 'chooseImage', 1148 | 'previewImage', 1149 | 'uploadImage', 1150 | 'downloadImage', 1151 | 'getNetworkType', 1152 | 'openLocation', 1153 | 'getLocation', 1154 | 'hideOptionMenu', 1155 | 'showOptionMenu', 1156 | 'closeWindow', 1157 | 'scanQRCode', 1158 | 'chooseWXPay', 1159 | 'openProductSpecificView', 1160 | 'addCard', 1161 | 'chooseCard', 1162 | 'openCard' 1163 | ] 1164 | ], $config); 1165 | } 1166 | 1167 | /* =================== 微信小店接口(基于手册V1.15) =================== */ 1168 | 1169 | /** 1170 | * @var object 1171 | */ 1172 | private $_merchant; 1173 | /** 1174 | * 微信小店组件 1175 | * @return object 1176 | */ 1177 | public function getMerchant() 1178 | { 1179 | if ($this->_merchant === null) { 1180 | $this->_merchant = Yii::createObject(Merchant::className(), [$this]); 1181 | } 1182 | return $this->_merchant; 1183 | } 1184 | 1185 | /* =================== 微信卡卷接口 =================== */ 1186 | 1187 | /** 1188 | * @var object 1189 | */ 1190 | private $_card; 1191 | /** 1192 | * @return object 1193 | */ 1194 | public function getCard() 1195 | { 1196 | if ($this->_card === null) { 1197 | $this->_card = Yii::createObject(Card::className(), [$this]); 1198 | } 1199 | return $this->_card; 1200 | } 1201 | 1202 | /* =================== 微信智能接口 =================== */ 1203 | 1204 | /** 1205 | * 语义理解 1206 | */ 1207 | const WECHAT_SEMANTIC_SEMPROXY_PREFIX = '/semantic/semproxy/search'; 1208 | /** 1209 | * 语义理解 1210 | * @param array $data 1211 | * @return bool|mixed 1212 | * @throws \yii\web\HttpException 1213 | */ 1214 | public function searchSemantic(array $data) 1215 | { 1216 | $result = $this->httpRaw(self::WECHAT_SEMANTIC_SEMPROXY_PREFIX, $data, [ 1217 | 'access_token' => $this->getAccessToken() 1218 | ]); 1219 | return isset($result['errcode']) && !$result['errcode'] ? $result : false; 1220 | } 1221 | 1222 | /* =================== 设备功能(物联网, 欢迎PR) =================== */ 1223 | 1224 | /* =================== 多客服功能(部分功能实现在[发送消息]区域内) =================== */ 1225 | 1226 | /** 1227 | * @var object 1228 | */ 1229 | private $_customService; 1230 | /** 1231 | * 多客服组件 1232 | * @return object 1233 | */ 1234 | public function getCustomService() 1235 | { 1236 | if ($this->_customService === null) { 1237 | $this->_customService = Yii::createObject(CustomService::className(), [$this]); 1238 | } 1239 | return $this->_customService; 1240 | } 1241 | 1242 | /* =================== 摇一摇周边 =================== */ 1243 | 1244 | /** 1245 | * @var object 1246 | */ 1247 | private $_shakeAround; 1248 | /** 1249 | * 摇一摇组件 1250 | * @return object 1251 | */ 1252 | public function getShakeAround() 1253 | { 1254 | if ($this->_shakeAround === null) { 1255 | $this->_shakeAround = Yii::createObject(ShakeAround::className(), [$this]); 1256 | } 1257 | return $this->_shakeAround; 1258 | } 1259 | } -------------------------------------------------------------------------------- /QyWechat.php: -------------------------------------------------------------------------------- 1 | httpGet(self::WECHAT_ACCESS_TOKEN_PREFIX, [ 57 | 'corpid' => $this->corpId, 58 | 'corpsecret' => $this->secret 59 | ]); 60 | return isset($result['access_token']) ? $result : false; 61 | } 62 | 63 | /** 64 | * 获取微信服务器IP地址 65 | */ 66 | const WECHAT_IP_PREFIX = '/cgi-bin/getcallbackip'; 67 | /** 68 | * 获取微信服务器IP地址 69 | * @return array|bool 70 | * @throws \yii\web\HttpException 71 | */ 72 | public function getIp() 73 | { 74 | $result = $this->httpGet(self::WECHAT_IP_PREFIX, [ 75 | 'access_token' => $this->getAccessToken() 76 | ]); 77 | return isset($result['ip_list']) ? $result['ip_list'] : false; 78 | } 79 | 80 | /* =================== 管理通讯录 =================== */ 81 | 82 | /** 83 | * 二次验证 84 | */ 85 | const WECHAT_USER_AUTH_SUCCESS_PREFIX = '/cgi-bin/user/authsucc'; 86 | /** 87 | * 二次验证 88 | * @param $userId 89 | * @return bool 90 | * @throws \yii\web\HttpException 91 | */ 92 | public function userAuthSuccess($userId) 93 | { 94 | $result = $this->httpGet(self::WECHAT_USER_AUTH_SUCCESS_PREFIX, [ 95 | 'access_token' => $this->getAccessToken(), 96 | 'userid' => $userId 97 | ]); 98 | return isset($result['errmsg']) && $result['errmsg'] == 'ok'; 99 | } 100 | 101 | /** 102 | * 创建部门 103 | */ 104 | const WECHAT_DEPARTMENT_CREATE_PREFIX = '/cgi-bin/department/create'; 105 | /** 106 | * 创建部门 107 | * @param array $data 108 | * @return bool 109 | * @throws \yii\web\HttpException 110 | */ 111 | public function createDepartment(array $data) 112 | { 113 | $result = $this->httpRaw(self::WECHAT_DEPARTMENT_CREATE_PREFIX, $data, [ 114 | 'access_token' => $this->getAccessToken() 115 | ]); 116 | return isset($result['errcode']) && !$result['errcode'] ? $result['id'] : false; 117 | } 118 | 119 | /** 120 | * 创建部门 121 | */ 122 | const WECHAT_DEPARTMENT_UPDATE_PREFIX = '/cgi-bin/department/update'; 123 | /** 124 | * 创建部门 125 | * @param array $data 126 | * @return bool 127 | * @throws \yii\web\HttpException 128 | */ 129 | public function updateDepartment(array $data) 130 | { 131 | $result = $this->httpRaw(self::WECHAT_DEPARTMENT_CREATE_PREFIX, $data, [ 132 | 'access_token' => $this->getAccessToken() 133 | ]); 134 | return isset($result['errcode']) && !$result['errcode']; 135 | } 136 | 137 | /** 138 | * 删除部门 139 | */ 140 | const WECHAT_DEPARTMENT_DELETE_PREFIX = '/cgi-bin/department/delete'; 141 | /** 142 | * 删除部门 143 | * @param $id 144 | * @return bool 145 | * @throws \yii\web\HttpException 146 | */ 147 | public function deleteDepartment($id) 148 | { 149 | $result = $this->httpGet(self::WECHAT_DEPARTMENT_DELETE_PREFIX, [ 150 | 'access_token' => $this->getAccessToken(), 151 | 'id' => $id 152 | ]); 153 | return isset($result['errcode']) && !$result['errcode']; 154 | } 155 | 156 | /** 157 | * 获取部门列表 158 | */ 159 | const WECHAT_DEPARTMENT_LIST = '/cgi-bin/department/list'; 160 | /** 161 | * 获取部门列表 162 | * @param null $id 部门id。获取指定部门id下的子部门 163 | * @return bool 164 | * @throws \yii\web\HttpException 165 | */ 166 | public function getDepartmentList($id = null) 167 | { 168 | $result = $this->httpGet(self::WECHAT_DEPARTMENT_DELETE_PREFIX, [ 169 | 'access_token' => $this->getAccessToken(), 170 | ] + ($id === null ? [] : [ 171 | 'id' => $id 172 | ])); 173 | return isset($result['errmsg']) && $result['errmsg'] == 'ok' ? $result['department'] : false; 174 | } 175 | 176 | /** 177 | * 创建成员 178 | */ 179 | const WECHAT_USER_CREATE_PREFIX = '/cgi-bin/user/create'; 180 | /** 181 | * 创建成员 182 | * @param array $data 183 | * @return bool 184 | * @throws \yii\web\HttpException 185 | */ 186 | public function createUser(array $data) 187 | { 188 | $result = $this->httpRaw(self::WECHAT_USER_CREATE_PREFIX, $data, [ 189 | 'access_token' => $this->getAccessToken() 190 | ]); 191 | return isset($result['errcode']) && !$result['errcode']; 192 | } 193 | 194 | /** 195 | * 创建成员 196 | */ 197 | const WECHAT_USER_UPDATE_PREFIX = '/cgi-bin/user/create'; 198 | /** 199 | * 创建成员 200 | * @param array $data 201 | * @return bool 202 | * @throws \yii\web\HttpException 203 | */ 204 | public function updateUser(array $data) 205 | { 206 | $result = $this->httpRaw(self::WECHAT_USER_UPDATE_PREFIX, $data, [ 207 | 'access_token' => $this->getAccessToken() 208 | ]); 209 | return isset($result['errcode']) && !$result['errcode']; 210 | } 211 | 212 | /** 213 | * 删除成员 214 | */ 215 | const WECHAT_USER_DELETE_PREFIX = '/cgi-bin/user/delete'; 216 | /** 217 | * 删除成员 218 | * @param $userId 219 | * @return bool 220 | * @throws \yii\web\HttpException 221 | */ 222 | public function deleteUser($userId) 223 | { 224 | $result = $this->httpGet(self::WECHAT_USER_DELETE_PREFIX, [ 225 | 'access_token' => $this->getAccessToken(), 226 | 'userid' => $userId 227 | ]); 228 | return isset($result['errcode']) && !$result['errcode']; 229 | } 230 | 231 | /** 232 | * 批量删除成员 233 | */ 234 | const WECHAT_USER_BATCH_DELETE_PREFIX = '/cgi-bin/user/batchdelete'; 235 | /** 236 | * 批量删除成员 237 | * @param array $userIdList 238 | * @return bool 239 | * @throws \yii\web\HttpException 240 | */ 241 | public function batchDeleteUser(array $userIdList) 242 | { 243 | $result = $this->httpRaw(self::WECHAT_USER_BATCH_DELETE_PREFIX, [ 244 | 'useridlist' => $userIdList 245 | ], [ 246 | 'access_token' => $this->getAccessToken() 247 | ]); 248 | return isset($result['errcode']) && !$result['errcode']; 249 | } 250 | 251 | /** 252 | * 获取部门成员(详情) 253 | */ 254 | const WECHAT_USER_GET_PREFIX = '/cgi-bin/user/get'; 255 | /** 256 | * 获取部门成员(详情) 257 | * @param $userId 258 | * @return bool|mixed 259 | * @throws \yii\web\HttpException 260 | */ 261 | public function getUser($userId) 262 | { 263 | $result = $this->httpGet(self::WECHAT_USER_GET_PREFIX, [ 264 | 'access_token' => $this->getAccessToken(), 265 | 'userid' => $userId 266 | ]); 267 | return isset($result['errmsg']) && $result['errmsg'] == 'ok' ? $result : false; 268 | } 269 | 270 | /** 271 | * 获取部门成员 272 | */ 273 | const WECHAT_DEPARTMENT_USER_LIST_GET_PREFIX = '/cgi-bin/user/simplelist'; 274 | /** 275 | * 获取部门成员 276 | * @param $departmentId 277 | * @param int $fetchChild 278 | * @param int $status 279 | * @return bool|mixed 280 | * @throws \yii\web\HttpException 281 | */ 282 | public function getDepartmentUserList($departmentId, $fetchChild = 0, $status = 0) 283 | { 284 | $result = $this->httpGet(self::WECHAT_DEPARTMENT_USER_LIST_GET_PREFIX, [ 285 | 'access_token' => $this->getAccessToken(), 286 | 'department_id' => $departmentId, 287 | 'fetch_child' => $fetchChild, 288 | 'status' => $status, 289 | ]); 290 | return isset($result['errmsg']) && $result['errmsg'] == 'ok' ? $result['userlist'] : false; 291 | } 292 | 293 | /** 294 | * 获取部门成员(详情) 295 | */ 296 | const WECHAT_DEPARTMENT_USERS_INFO_LIST_GET_PREFIX = '/cgi-bin/user/list'; 297 | /** 298 | * 获取部门成员(详情) 299 | * @param $departmentId 300 | * @param int $fetchChild 301 | * @param int $status 302 | * @return bool|mixed 303 | * @throws \yii\web\HttpException 304 | */ 305 | public function getDepartmentUserInfoList($departmentId, $fetchChild = 0, $status = 0) 306 | { 307 | $result = $this->httpGet(self::WECHAT_DEPARTMENT_USERS_INFO_LIST_GET_PREFIX, [ 308 | 'access_token' => $this->getAccessToken(), 309 | 'department_id' => $departmentId, 310 | 'fetch_child' => $fetchChild, 311 | 'status' => $status, 312 | ]); 313 | return isset($result['errmsg']) && $result['errmsg'] == 'ok' ? $result['userlist'] : false; 314 | } 315 | 316 | /** 317 | * 邀请成员关注 318 | */ 319 | const WECHAT_USER_INVITE_PREFIX = '/cgi-bin/invite/send'; 320 | /** 321 | * 邀请成员关注 322 | * @param $userId 323 | * @return bool 324 | * @throws \yii\web\HttpException 325 | */ 326 | public function inviteUser($userId) 327 | { 328 | $result = $this->httpRaw(self::WECHAT_USER_INVITE_PREFIX, [ 329 | 'userid' => $userId 330 | ], [ 331 | 'access_token' => $this->getAccessToken(), 332 | ]); 333 | return isset($result['errmsg']) && $result['errmsg'] == 'ok' ? $result['type'] : false; 334 | } 335 | 336 | /** 337 | * 创建标签 338 | */ 339 | const WECHAT_TAG_CREATE_PREFIX = '/cgi-bin/tag/create'; 340 | /** 341 | * 创建标签 342 | * @param $tagName 343 | * @return int|bool 344 | * @throws \yii\web\HttpException 345 | */ 346 | public function createTag($tagName) 347 | { 348 | $result = $this->httpRaw(self::WECHAT_TAG_CREATE_PREFIX, [ 349 | 'tagname' => $tagName 350 | ], [ 351 | 'access_token' => $this->getAccessToken() 352 | ]); 353 | return isset($result['errmsg']) && $result['errmsg'] == 'ok' ? $result['tagid'] : false; 354 | } 355 | 356 | /** 357 | * 更新标签名字 358 | */ 359 | const WECHAT_TAG_NAME_UPDATE_PREFIX = '/cgi-bin/tag/update'; 360 | /** 361 | * 更新标签名字 362 | * @param $tagId 363 | * @param $tagName 364 | * @return bool 365 | * @throws \yii\web\HttpException 366 | */ 367 | public function updateTagName($tagId, $tagName) 368 | { 369 | $result = $this->httpRaw(self::WECHAT_TAG_CREATE_PREFIX, [ 370 | 'tagid' => $tagId, 371 | 'tagname' => $tagName 372 | ], [ 373 | 'access_token' => $this->getAccessToken() 374 | ]); 375 | return isset($result['errcode']) && !$result['errcode']; 376 | } 377 | 378 | /** 379 | * 删除标签 380 | */ 381 | const WECHAT_TAG_DELETE_PREFIX = '/cgi-bin/tag/delete'; 382 | /** 383 | * 删除标签 384 | * @param $tagId 385 | * @return bool 386 | * @throws \yii\web\HttpException 387 | */ 388 | public function deleteTag($tagId) 389 | { 390 | $result = $this->httpGet(self::WECHAT_TAG_DELETE_PREFIX, [ 391 | 'access_token' => $this->getAccessToken(), 392 | 'tagid' => $tagId 393 | ]); 394 | return isset($result['errcode']) && !$result['errcode']; 395 | } 396 | 397 | /** 398 | * 获取标签成员 399 | */ 400 | const WECHAT_TAG_USER_LIST_GET_PREFIX = '/cgi-bin/tag/get'; 401 | /** 402 | * 获取标签成员 403 | * @param $tagId 404 | * @return bool|mixed 405 | * @throws \yii\web\HttpException 406 | */ 407 | public function getTagUserList($tagId) 408 | { 409 | $result = $this->httpGet(self::WECHAT_TAG_USER_LIST_GET_PREFIX, [ 410 | 'access_token' => $this->getAccessToken(), 411 | 'tagid' => $tagId 412 | ]); 413 | return isset($result['errmsg']) && $result['errmsg'] == 'ok' ? $result : false; 414 | } 415 | 416 | /** 417 | * 增加标签成员 418 | */ 419 | const WECHAT_TAG_USERS_ADD_PREFIX = '/cgi-bin/tag/addtagusers'; 420 | /** 421 | * 增加标签成员 422 | * @param array $data 423 | * @return bool 424 | * @throws \yii\web\HttpException 425 | */ 426 | public function addTagUsers(array $data) 427 | { 428 | $result = $this->httpRaw(self::WECHAT_TAG_USERS_ADD_PREFIX, $data, [ 429 | 'access_token' => $this->getAccessToken(), 430 | ]); 431 | return isset($result['errmsg']) && $result['errmsg'] == 'ok'; 432 | } 433 | 434 | /** 435 | * 删除标签成员 436 | */ 437 | const WECHAT_TAG_USERS_DELETE_PREFIX = '/cgi-bin/tag/deltagusers'; 438 | /** 439 | * 删除标签成员 440 | * @param array $data 441 | * @return bool 442 | * @throws \yii\web\HttpException 443 | */ 444 | public function deleteTagUsers(array $data) 445 | { 446 | $result = $this->httpRaw(self::WECHAT_TAG_USERS_DELETE_PREFIX, $data, [ 447 | 'access_token' => $this->getAccessToken(), 448 | ]); 449 | return isset($result['errmsg']) && $result['errmsg'] == 'ok'; 450 | } 451 | 452 | /** 453 | * 获取标签列表 454 | */ 455 | const WECHAT_TAG_LIST_GET_PREFIX = '/cgi-bin/tag/list'; 456 | /** 457 | * 获取标签列表 458 | * @return bool|mixed 459 | * @throws \yii\web\HttpException 460 | */ 461 | public function getTagList() 462 | { 463 | $result = $this->httpGet(self::WECHAT_TAG_LIST_GET_PREFIX, [ 464 | 'access_token' => $this->getAccessToken() 465 | ]); 466 | return isset($result['errmsg']) && $result['errmsg'] == 'ok' ? $result['taglist'] : false; 467 | } 468 | 469 | /** 470 | * 邀请成员关注 471 | */ 472 | const WECHAT_USER_BATCH_INVITE_PREFIX = '/cgi-bin/batch/inviteuser'; 473 | /** 474 | * 邀请成员关注 475 | * @param array $data 476 | * @return bool 477 | * @throws \yii\web\HttpException 478 | */ 479 | public function batchInviteUser(array $data) 480 | { 481 | $result = $this->httpRaw(self::WECHAT_TAG_USERS_DELETE_PREFIX, $data, [ 482 | 'access_token' => $this->getAccessToken() 483 | ]); 484 | return isset($result['errmsg']) && $result['errmsg'] == 'ok' ? $result['jobid'] : false; 485 | } 486 | 487 | /** 488 | * 增量更新成员 489 | */ 490 | const WECHAT_USER_BATCH_SYNC_PREFIX = '/cgi-bin/batch/syncuser'; 491 | /** 492 | * 增量更新成员 493 | * @param array $data 494 | * @return bool 495 | * @throws \yii\web\HttpException 496 | */ 497 | public function batchSyncUser(array $data) 498 | { 499 | $result = $this->httpRaw(self::WECHAT_USER_BATCH_SYNC_PREFIX, $data, [ 500 | 'access_token' => $this->getAccessToken() 501 | ]); 502 | return isset($result['errmsg']) && $result['errmsg'] == 'ok' ? $result['jobid'] : false; 503 | } 504 | 505 | /** 506 | * 全量覆盖成员 507 | */ 508 | const WECHAT_USER_BATCH_REPLACE_PREFIX = '/cgi-bin/batch/replaceuser'; 509 | /** 510 | * 全量覆盖成员 511 | * @param array $data 512 | * @return bool 513 | * @throws \yii\web\HttpException 514 | */ 515 | public function batchReplaceUser(array $data) 516 | { 517 | $result = $this->httpRaw(self::WECHAT_USER_BATCH_REPLACE_PREFIX, $data, [ 518 | 'access_token' => $this->getAccessToken(), 519 | ]); 520 | return isset($result['errmsg']) && $result['errmsg'] == 'ok' ? $result['jobid'] : false; 521 | } 522 | 523 | /** 524 | * 全量覆盖部门 525 | */ 526 | const WECHAT_PARTY_BATCH_REPLACE_PREFIX = '/cgi-bin/batch/replaceparty'; 527 | /** 528 | * 全量覆盖部门 529 | * @param array $data 530 | * @return bool 531 | * @throws \yii\web\HttpException 532 | */ 533 | public function batchReplaceParty(array $data) 534 | { 535 | $result = $this->httpRaw(self::WECHAT_PARTY_BATCH_REPLACE_PREFIX, $data, [ 536 | 'access_token' => $this->getAccessToken() 537 | ]); 538 | return isset($result['errmsg']) && $result['errmsg'] == 'ok' ? $result['jobid'] : false; 539 | } 540 | 541 | /** 542 | * 获取异步任务结果 543 | */ 544 | const WECHAT_BATCH_RESULT_GET_PREFIX = '/cgi-bin/batch/getresult'; 545 | /** 546 | * 获取异步任务结果 547 | * @param $jobId 548 | * @return bool|mixed 549 | * @throws \yii\web\HttpException 550 | */ 551 | public function getBatchResult($jobId) 552 | { 553 | $result = $this->httpGet(self::WECHAT_BATCH_RESULT_GET_PREFIX, [ 554 | 'access_token' => $this->getAccessToken(), 555 | 'jobid' => $jobId 556 | ]); 557 | return isset($result['errmsg']) && $result['errmsg'] == 'ok' ? $result : false; 558 | } 559 | 560 | /* =================== 管理多媒体文件 =================== */ 561 | 562 | /** 563 | * 上传媒体文件 564 | */ 565 | const WECHAT_MEDIA_UPLOAD_PREFIX = '/cgi-bin/media/upload'; 566 | /** 567 | * 上传媒体文件 568 | * @param $mediaPath 569 | * @param $type 570 | * @return bool|mixed 571 | * @throws \yii\web\HttpException 572 | */ 573 | public function updateMedia($mediaPath, $type) 574 | { 575 | $result = $this->httpPost(self::WECHAT_MEDIA_UPLOAD_PREFIX, [ 576 | 'media' => $this->uploadFile($mediaPath) 577 | ], [ 578 | 'access_token' => $this->getAccessToken(), 579 | 'type' => $type 580 | ]); 581 | return isset($result['media_id']) ? $result : false; 582 | } 583 | 584 | /** 585 | * 获取媒体文件 586 | */ 587 | const WECHAT_MEDIA_GET_PREFIX = '/cgi-bin/media/get'; 588 | /** 589 | * 获取媒体文件 590 | * @param $mediaId 591 | * @return bool|string 592 | * @throws \yii\web\HttpException 593 | */ 594 | public function getMedia($mediaId) 595 | { 596 | $result = $this->httpGet(self::WECHAT_MEDIA_GET_PREFIX, [ 597 | 'access_token' => $this->getAccessToken(), 598 | 'media_id' => $mediaId 599 | ]); 600 | return !isset($result['errcode']) ? $result : false; 601 | } 602 | 603 | /* =================== 管理企业号应用 =================== */ 604 | 605 | /** 606 | * 获取企业号应用 607 | */ 608 | const WECHAT_AGENT_GET_PREFIX = '/cgi-bin/agent/get'; 609 | /** 610 | * 获取企业号应用 611 | * @param $agentId 612 | * @return bool|mixed 613 | * @throws \yii\web\HttpException 614 | */ 615 | public function getAgent($agentId) 616 | { 617 | $result = $this->httpGet(self::WECHAT_AGENT_GET_PREFIX, [ 618 | 'access_token' => $this->getAccessToken(), 619 | 'agent_id' => $agentId 620 | ]); 621 | return isset($result['errmsg']) && $result['errmsg'] == 'ok' ? $result : false; 622 | } 623 | 624 | /** 625 | * 设置企业号应用 626 | */ 627 | const WECHAT_AGENT_SET_PREFIX = '/cgi-bin/agent/set'; 628 | /** 629 | * 设置企业号应用 630 | * @param array $data 631 | * @return bool 632 | * @throws \yii\web\HttpException 633 | */ 634 | public function setAgent(array $data) 635 | { 636 | $result = $this->httpRaw(self::WECHAT_AGENT_SET_PREFIX, $data, [ 637 | 'access_token' => $this->getAccessToken() 638 | ]); 639 | return isset($result['errmsg']) && $result['errmsg'] == 'ok'; 640 | } 641 | 642 | /** 643 | * 获取应用概况列表 644 | */ 645 | const WECHAT_AGENT_LIST_GET_PREFIX = '/cgi-bin/agent/list'; 646 | /** 647 | * 获取应用概况列表 648 | * @return bool 649 | * @throws \yii\web\HttpException 650 | */ 651 | public function getAgentList() 652 | { 653 | $result = $this->httpGet(self::WECHAT_AGENT_SET_PREFIX, [ 654 | 'access_token' => $this->getAccessToken() 655 | ]); 656 | return isset($result['errmsg']) && $result['errmsg'] == 'ok' ? $result['agentlist'] : false; 657 | } 658 | 659 | /* =================== 发送消息 =================== */ 660 | 661 | /** 662 | * 发送消息 663 | */ 664 | const WECHAT_MESSAGE_SEND_PREFIX = '/cgi-bin/message/send'; 665 | /** 666 | * 发送消息 667 | * @param array $data 668 | * @return bool 669 | * @throws \yii\web\HttpException 670 | */ 671 | public function sendMessage(array $data) 672 | { 673 | $result = $this->httpRaw(self::WECHAT_CUSTOM_MESSAGE_SEND_PREFIX, $data, [ 674 | 'access_token' => $this->getAccessToken() 675 | ]); 676 | return isset($result['errmsg']) && $result['errmsg'] == 'ok' ? $result : false; 677 | } 678 | 679 | /* =================== 自定义菜单 =================== */ 680 | 681 | /** 682 | * 创建应用菜单 683 | */ 684 | const WECHAT_MENU_CREATE_PREFIX = '/cgi-bin/menu/create'; 685 | /** 686 | * 创建应用菜单 687 | * @param $agentId 688 | * @param array $data 689 | * @return bool 690 | * @throws \yii\web\HttpException 691 | */ 692 | public function createMenu($agentId, array $data) 693 | { 694 | $result = $this->httpRaw(self::WECHAT_MENU_CREATE_PREFIX, $data, [ 695 | 'access_token' => $this->getAccessToken(), 696 | 'agentid' => $agentId 697 | ]); 698 | return isset($result['errmsg']) && $result['errmsg'] == 'ok'; 699 | } 700 | 701 | /** 702 | * 删除菜单 703 | */ 704 | const WECHAT_MENU_DELETE_PREFIX = '/cgi-bin/menu/delete'; 705 | /** 706 | * 删除菜单 707 | * @param $agentId 708 | * @return bool 709 | * @throws \yii\web\HttpException 710 | */ 711 | public function deleteMenu($agentId) 712 | { 713 | $result = $this->httpGet(self::WECHAT_MENU_DELETE_PREFIX, [ 714 | 'access_token' => $this->getAccessToken(), 715 | 'agentid' => $agentId 716 | ]); 717 | return isset($result['errmsg']) && $result['errmsg'] == 'ok'; 718 | } 719 | 720 | /** 721 | * 获取菜单列表 722 | */ 723 | const WECHAT_MENU_GET_PREFIX = '/cgi-bin/menu/get'; 724 | /** 725 | * 获取菜单列表 726 | * @param $agentId 727 | * @return bool 728 | * @throws \yii\web\HttpException 729 | */ 730 | public function getMenu($agentId) 731 | { 732 | $result = $this->httpGet(self::WECHAT_MENU_GET_PREFIX, [ 733 | 'access_token' => $this->getAccessToken(), 734 | 'agentid' => $agentId 735 | ]); 736 | return isset($result['menu']['button']) ? $result['menu']['button'] : false; 737 | } 738 | 739 | /* =================== OAuth2验证接口 =================== */ 740 | 741 | /** 742 | * 企业获取code 743 | */ 744 | const WECHAT_OAUTH2_AUTHORIZE_URL = 'https://open.weixin.qq.com/connect/oauth2/authorize'; 745 | /** 746 | * 企业获取code:第 747 | * 通过此函数生成授权url 748 | * @param $redirectUrl 授权后重定向的回调链接地址,请使用urlencode对链接进行处理 749 | * @param string $state 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值 750 | * @param string $scope 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid), 751 | * snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且,即使在未关注的情况下,只要用户授权,也能获取其信息) 752 | * @return string 753 | */ 754 | public function getOauth2AuthorizeUrl($redirectUrl, $state = 'authorize', $scope = 'snsapi_base') 755 | { 756 | return $this->httpBuildQuery(self::WECHAT_OAUTH2_AUTHORIZE_URL, [ 757 | 'appid' => $this->corpId, 758 | 'redirect_uri' => $redirectUrl, 759 | 'response_type' => 'code', 760 | 'scope' => $scope, 761 | 'state' => $state, 762 | ]) . '#wechat_redirect'; 763 | } 764 | 765 | /** 766 | * 根据code获取成员信息 767 | */ 768 | const WECHAT_USER_IFNO_GET_PREFIX = '/cgi-bin/user/getuserinfo'; 769 | /** 770 | * 根据code获取成员信息 771 | * @param $agentId 772 | * @param $code 773 | * @return bool|mixed 774 | * @throws \yii\web\HttpException 775 | */ 776 | public function getUserInfo($agentId, $code) 777 | { 778 | $result = $this->httpGet(self::WECHAT_USER_IFNO_GET_PREFIX, [ 779 | 'access_token' => $this->getAccessToken(), 780 | 'code' => $code, 781 | 'agentid' => $agentId 782 | ]); 783 | return !isset($result['errcode']) ? $result : false; 784 | } 785 | 786 | /* =================== 微信JS接口 =================== */ 787 | 788 | /** 789 | * js api ticket 获取 790 | */ 791 | const WECHAT_JS_API_TICKET_PREFIX = '/cgi-bin/get_jsapi_ticket'; 792 | /** 793 | * 请求服务器jsapi_ticket 794 | * @return array 795 | */ 796 | protected function requestJsApiTicket() 797 | { 798 | return $this->httpGet(self::WECHAT_JS_API_TICKET_PREFIX, [ 799 | 'access_token' => $this->getAccessToken(), 800 | ]); 801 | } 802 | 803 | /** 804 | * 生成js 必需的config 805 | * 只需在视图文件输出JS代码: 806 | * wx.config(jsApiConfig()) ?>); // 默认全权限 807 | * wx.config(jsApiConfig([ // 只允许使用分享到朋友圈功能 808 | * 'jsApiList' => [ 809 | * 'onMenuShareTimeline' 810 | * ] 811 | * ])) ?>); 812 | * @param array $config 813 | * @return array 814 | * @throws HttpException 815 | */ 816 | public function jsApiConfig(array $config = []) 817 | { 818 | $data = [ 819 | 'jsapi_ticket' => $this->getJsApiTicket(), 820 | 'noncestr' => Yii::$app->security->generateRandomString(16), 821 | 'timestamp' => $_SERVER['REQUEST_TIME'], 822 | 'url' => explode('#', Yii::$app->request->getAbsoluteUrl())[0] 823 | ]; 824 | return array_merge([ 825 | 'debug' => YII_DEBUG, 826 | 'appId' => $this->corpId, 827 | 'timestamp' => $data['timestamp'], 828 | 'nonceStr' => $data['noncestr'], 829 | 'signature' => sha1(urldecode(http_build_query($data))), 830 | 'jsApiList' => [ 831 | 'onMenuShareTimeline', 832 | 'onMenuShareAppMessage', 833 | 'onMenuShareQQ', 834 | 'onMenuShareWeibo', 835 | 'startRecord', 836 | 'stopRecord', 837 | 'onVoiceRecordEnd', 838 | 'playVoice', 839 | 'pauseVoice', 840 | 'stopVoice', 841 | 'onVoicePlayEnd', 842 | 'uploadVoice', 843 | 'downloadVoice', 844 | 'chooseImage', 845 | 'previewImage', 846 | 'uploadImage', 847 | 'downloadImage', 848 | 'translateVoice', 849 | 'getNetworkType', 850 | 'openLocation', 851 | 'getLocation', 852 | 'hideOptionMenu', 853 | 'showOptionMenu', 854 | 'hideMenuItems', 855 | 'showMenuItems', 856 | 'hideAllNonBaseMenuItem', 857 | 'showAllNonBaseMenuItem', 858 | 'closeWindow', 859 | 'scanQRCode' 860 | ] 861 | ], $config); 862 | } 863 | 864 | /* =================== 第三方应用授权 =================== */ 865 | 866 | 867 | 868 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | yii2-wechat-sdk 2 | =============== 3 | 4 | 感谢选择 yii2-wechat-sdk 扩展, 该扩展是基于[Yii2](https://github.com/yiisoft/yii2)框架基础开发,借助Yii2的强劲特性可以定制开发属于您自己的微信公众号 5 | 6 | [![Latest Stable Version](https://poser.pugx.org/callmez/yii2-wechat-sdk/v/stable.svg)](https://packagist.org/packages/callmez/yii2-wechat-sdk) [![Total Downloads](https://poser.pugx.org/callmez/yii2-wechat-sdk/downloads.svg)](https://packagist.org/packages/callmez/yii2-wechat-sdk) [![Latest Unstable Version](https://poser.pugx.org/callmez/yii2-wechat-sdk/v/unstable.svg)](https://packagist.org/packages/callmez/yii2-wechat-sdk) [![License](https://poser.pugx.org/callmez/yii2-wechat-sdk/license.svg)](https://packagist.org/packages/callmez/yii2-wechat-sdk) 7 | 8 | 注意 9 | --- 10 | ** 新版本正在重构中, 直到1.0正式版发布前.你依然可以继续使用功能 ** 11 | 12 | 目前有3个主要文件可以使用 13 | - `Wechat.php` 旧版微信公众号操作类(在新版[1.0]发布后会删除) 14 | - `MpWechat.php` 新版微信公众号操作类(更标准,更完善), 如果您是新使用该库请按照文档说明替换旧版`Wechat.php`使用 15 | - `QyWechat.php` 新版微信企业号操作类(为了更加全面的微信功能操作, 将在[1.1版本中完善发布]), 强势集成企业号功能 16 | 17 | 环境条件 18 | -------- 19 | - >= php5.4 20 | - Yii2 21 | 22 | 安装 23 | ---- 24 | 25 | 您可以使用composer来安装, 添加下列代码在您的``composer.json``文件中并执行``composer update``操作 26 | 27 | ```json 28 | { 29 | "require": { 30 | "callmez/yii2-wechat-sdk": "dev-master" 31 | } 32 | } 33 | ``` 34 | 35 | 使用示例 36 | -------- 37 | 在使用前,请先参考微信公众平台的[开发文档](http://mp.weixin.qq.com/wiki/index.php?title=%E9%A6%96%E9%A1%B5) 38 | 39 | Wechat定义方式 40 | ```php 41 | //在config/web.php配置文件中定义component配置信息 42 | 'components' => [ 43 | ..... 44 | 'wechat' => [ 45 | 'class' => 'callmez\wechat\sdk\Wechat', 46 | 'appId' => '微信公众平台中的appid', 47 | 'appSecret' => '微信公众平台中的secret', 48 | 'token' => '微信服务器对接您的服务器验证token' 49 | ] 50 | .... 51 | ] 52 | // 全局公众号sdk使用 53 | $wechat = Yii::$app->wechat; 54 | 55 | 56 | //多公众号使用方式 57 | $wechat = Yii::createObject([ 58 | 'class' => 'callmez\wechat\sdk\Wechat', 59 | 'appId' => '微信公众平台中的appid', 60 | 'appSecret' => '微信公众平台中的secret', 61 | 'token' => '微信服务器对接您的服务器验证token' 62 | ]); 63 | ``` 64 | 65 | Wechat方法使用(部分示例) 66 | ```php 67 | //获取access_token 68 | var_dump($wechat->accessToken); 69 | 70 | //获取二维码ticket 71 | $qrcode = $wechat->createQrCode([ 72 | 'expire_seconds' => 604800, 73 | 'action_name' => 'QR_SCENE', 74 | 'action_info' => ['scene' => ['scene_id' => rand(1, 999999999)]] 75 | ]); 76 | var_dump($qrcode); 77 | 78 | //获取二维码 79 | $imgRawData = $wechat->getQrCodeUrl($qrcode['ticket']); 80 | 81 | //获取群组列表 82 | var_dump($wechat->getGroups()); 83 | 84 | 85 | //创建分组 86 | $group = $wechat->createGroup('测试分组'); 87 | echo $group ? '测试分组创建成功' : '测试分组创建失败'; 88 | 89 | //修改分组 90 | echo $wechat->updateGroupName($group['id'], '修改测试分组') ? '修改测试分组成功' : '测试分组创建失败'; 91 | 92 | 93 | //根据关注者ID获取关注者所在分组ID 94 | $openID = 'oiNHQjh-8k4DrQgY5H7xofx_ayfQ'; //此处应填写公众号关注者的唯一openId 95 | 96 | //修改关注者所在分组 97 | echo $wechat->updateMemberGroup($openID, 1) ? '修改关注者分组成功' : '修改关注者分组失败'; 98 | 99 | //获取关注者所在分组 100 | echo $wechat->getGroupId($openID); 101 | 102 | //修改关注者备注 103 | echo $wechat->updateMemberRemark($openID, '测试更改备注') ? '关注者备注修改成功' : '关注者备注修改失败'; 104 | 105 | //获取关注者基本信息 106 | var_dump($wechat->getMemberInfo($openID)); 107 | 108 | //获取关注者列表 109 | var_dump($wechat->getMemberList()); 110 | 111 | //获取关注者的客服聊天记录, 112 | var_dump($wechat->getCustomerServiceRecords($openID, mktime(0, 0, 0, 1, 1, date('Y')), time())); //获取今年的聊天数据(可能获取不到数据) 113 | 114 | //上传媒体文件 115 | $filePath = '图片绝对路径'; //目前微信只开发jpg上传 116 | var_dump($media = $wechat->uploadMedia(realpath($filePath), 'image')); 117 | 118 | //下载媒体文件 119 | echo $wechat->getMedia($media['media_id']) ? 'media下载成功' : 'media下载失败'; 120 | 121 | ``` 122 | 123 | 反馈或贡献代码 124 | -------------- 125 | 您可以在[这里](https://github.com/callmez/yii2-wechat-sdk/issues)给我提出在使用中碰到的问题或Bug. 126 | 我会在第一时间回复您并修复. 127 | 128 | 您也可以 发送邮件callme-z@qq.com给我并且说明您的问题. 129 | 130 | 如果你有更好代码实现,请fork项目并发起您的pull request.我会及时处理. 感谢! 131 | -------------------------------------------------------------------------------- /components/BaseWechat.php: -------------------------------------------------------------------------------- 1 | 'xxx', 57 | * 'expirs_in' => 7200 58 | * ] 59 | * @return array|bool 60 | */ 61 | abstract protected function requestAccessToken(); 62 | 63 | /** 64 | * 获取AccessToken 65 | * 超时后会自动重新获取AccessToken并触发self::EVENT_AFTER_ACCESS_TOKEN_UPDATE事件 66 | * @param bool $force 是否强制获取 67 | * @return mixed 68 | * @throws HttpException 69 | */ 70 | public function getAccessToken($force = false) 71 | { 72 | $time = time(); // 为了更精确控制.取当前时间计算 73 | if ($this->_accessToken === null || $this->_accessToken['expire'] < $time || $force) { 74 | $result = $this->_accessToken === null && !$force ? $this->getCache('access_token', false) : false; 75 | if ($result === false) { 76 | if (!($result = $this->requestAccessToken())) { 77 | throw new HttpException(500, 'Fail to get access_token from wechat server.'); 78 | } 79 | $result['expire'] = $time + $result['expires_in']; 80 | $this->trigger(self::EVENT_AFTER_ACCESS_TOKEN_UPDATE, new Event(['data' => $result])); 81 | $this->setCache('access_token', $result, $result['expires_in']); 82 | } 83 | $this->setAccessToken($result); 84 | } 85 | return $this->_accessToken['access_token']; 86 | } 87 | 88 | /** 89 | * 设置AccessToken 90 | * @param array $accessToken 91 | * @throws InvalidParamException 92 | */ 93 | public function setAccessToken(array $accessToken) 94 | { 95 | if (!isset($accessToken['access_token'])) { 96 | throw new InvalidParamException('The wechat access_token must be set.'); 97 | } elseif(!isset($accessToken['expire'])) { 98 | throw new InvalidParamException('Wechat access_token expire time must be set.'); 99 | } 100 | $this->_accessToken = $accessToken; 101 | } 102 | 103 | /** 104 | * 请求微信服务器获取JsApiTicket 105 | * 必须返回以下格式内容 106 | * [ 107 | * 'ticket => 'xxx', 108 | * 'expirs_in' => 7200 109 | * ] 110 | * @return array|bool 111 | */ 112 | abstract protected function requestJsApiTicket(); 113 | 114 | /** 115 | * 生成js 必要的config 116 | */ 117 | abstract public function jsApiConfig(array $config = []); 118 | 119 | /** 120 | * 获取js api ticket 121 | * 超时后会自动重新获取JsApiTicket并触发self::EVENT_AFTER_JS_API_TICKET_UPDATE事件 122 | * @param bool $force 是否强制获取 123 | * @return mixed 124 | * @throws HttpException 125 | */ 126 | public function getJsApiTicket($force = false) 127 | { 128 | $time = time(); // 为了更精确控制.取当前时间计算 129 | if ($this->_jsApiTicket === null || $this->_jsApiTicket['expire'] < $time || $force) { 130 | $result = $this->_jsApiTicket === null && !$force ? $this->getCache('js_api_ticket', false) : false; 131 | if ($result === false) { 132 | if (!($result = $this->requestJsApiTicket())) { 133 | throw new HttpException(500, 'Fail to get jsapi_ticket from wechat server.'); 134 | } 135 | $result['expire'] = $time + $result['expires_in']; 136 | $this->trigger(self::EVENT_AFTER_JS_API_TICKET_UPDATE, new Event(['data' => $result])); 137 | $this->setCache('js_api_ticket', $result, $result['expires_in']); 138 | } 139 | $this->setJsApiTicket($result); 140 | } 141 | return $this->_jsApiTicket['ticket']; 142 | } 143 | 144 | /** 145 | * 设置JsApiTicket 146 | * @param array $jsApiTicket 147 | */ 148 | public function setJsApiTicket(array $jsApiTicket) 149 | { 150 | $this->_jsApiTicket = $jsApiTicket; 151 | } 152 | 153 | /** 154 | * 创建消息加密类 155 | * @return mixed 156 | */ 157 | abstract protected function createMessageCrypt(); 158 | 159 | /** 160 | * 设置消息加密处理类 161 | * @return MessageCrypt 162 | */ 163 | public function getMessageCrypt() 164 | { 165 | if ($this->_messageCrypt === null) { 166 | $this->setMessageCrypt($this->createMessageCrypt()); 167 | } 168 | return $this->_messageCrypt; 169 | } 170 | 171 | /** 172 | * 设置消息加密处理类 173 | * @param MessageCrypt $messageCrypt 174 | */ 175 | public function setMessageCrypt(MessageCrypt $messageCrypt) 176 | { 177 | $this->_messageCrypt = $messageCrypt; 178 | } 179 | 180 | /** 181 | * 加密XML数据 182 | * @param string $xml 加密的XML 183 | * @param string $timestamp 加密时间戳 184 | * @param string $nonce 加密随机串 185 | * @return string|bool 186 | */ 187 | public function encryptXml($xml, $timestamp , $nonce) 188 | { 189 | $errorCode = $this->getMessageCrypt()->encryptMsg($xml, $timestamp, $nonce, $xml); 190 | if ($errorCode) { 191 | $this->lastError = [ 192 | 'errcode' => $errorCode, 193 | 'errmsg' => 'XML数据加密失败!' 194 | ]; 195 | return false; 196 | } 197 | return $xml; 198 | } 199 | 200 | /** 201 | * 解密XML数据 202 | * @param string $xml 解密的XML 203 | * @param string $messageSignature 加密签名 204 | * @param string $timestamp 加密时间戳 205 | * @param string $nonce 加密随机串 206 | * @return string|bool 207 | */ 208 | public function decryptXml($xml, $messageSignature, $timestamp , $nonce) 209 | { 210 | $errorCode = $this->getMessageCrypt()->decryptMsg($messageSignature, $timestamp, $nonce, $xml, $xml); 211 | if ($errorCode) { 212 | $this->lastError = [ 213 | 'errcode' => $errorCode, 214 | 'errmsg' => 'XML数据解密失败!' 215 | ]; 216 | return false; 217 | } 218 | return $xml; 219 | } 220 | 221 | /** 222 | * 创建微信格式的XML 223 | * @param array $data 224 | * @param null $charset 225 | * @return string 226 | */ 227 | public function xml(array $data, $charset = null) 228 | { 229 | $dom = new DOMDocument('1.0', $charset === null ? Yii::$app->charset : $charset); 230 | $root = new DOMElement('xml'); 231 | $dom->appendChild($root); 232 | $this->buildXml($root, $data); 233 | $xml = $dom->saveXML(); 234 | return trim(substr($xml, strpos($xml, '?>') + 2)); 235 | } 236 | 237 | /** 238 | * @var string the name of the elements that represent the array elements with numeric keys. 239 | */ 240 | public $itemTag = 'item'; 241 | 242 | /** 243 | * @see yii\web\XmlResponseFormatter::buildXml() 244 | */ 245 | protected function buildXml($element, $data) 246 | { 247 | if (is_object($data)) { 248 | $child = new DOMElement(StringHelper::basename(get_class($data))); 249 | $element->appendChild($child); 250 | if ($data instanceof Arrayable) { 251 | $this->buildXml($child, $data->toArray()); 252 | } else { 253 | $array = []; 254 | foreach ($data as $name => $value) { 255 | $array[$name] = $value; 256 | } 257 | $this->buildXml($child, $array); 258 | } 259 | } elseif (is_array($data)) { 260 | foreach ($data as $name => $value) { 261 | if (is_int($name) && is_object($value)) { 262 | $this->buildXml($element, $value); 263 | } elseif (is_array($value) || is_object($value)) { 264 | $child = new DOMElement(is_int($name) ? $this->itemTag : $name); 265 | $element->appendChild($child); 266 | $this->buildXml($child, $value); 267 | } else { 268 | $child = new DOMElement(is_int($name) ? $this->itemTag : $name); 269 | $element->appendChild($child); 270 | $child->appendChild(new DOMText((string) $value)); 271 | } 272 | } 273 | } else { 274 | $element->appendChild(new DOMText((string) $data)); 275 | } 276 | } 277 | 278 | /** 279 | * 微信数据缓存基本键值 280 | * @param $name 281 | * @return string 282 | */ 283 | abstract protected function getCacheKey($name); 284 | 285 | /** 286 | * 缓存微信数据 287 | * @param $name 288 | * @param $value 289 | * @param null $duration 290 | * @return bool 291 | */ 292 | protected function setCache($name, $value, $duration = null) 293 | { 294 | $duration === null && $duration = $this->cacheTime; 295 | return Yii::$app->cache->set($this->getCacheKey($name), $value, $duration); 296 | } 297 | 298 | /** 299 | * 获取微信缓存数据 300 | * @param $name 301 | * @return mixed 302 | */ 303 | protected function getCache($name) 304 | { 305 | return Yii::$app->cache->get($this->getCacheKey($name)); 306 | } 307 | 308 | /** 309 | * Api url 组装 310 | * @param $url 311 | * @param array $options 312 | * @return string 313 | */ 314 | protected function httpBuildQuery($url, array $options) 315 | { 316 | if (!empty($options)) { 317 | $url .= (stripos($url, '?') === null ? '&' : '?') . http_build_query($options); 318 | } 319 | return $url; 320 | } 321 | 322 | /** 323 | * Http Get 请求 324 | * @param $url 325 | * @param array $options 326 | * @return mixed 327 | */ 328 | public function httpGet($url, array $options = []) 329 | { 330 | Yii::info([ 331 | 'url' => $url, 332 | 'options' => $options 333 | ], __METHOD__); 334 | return $this->parseHttpRequest(function($url) { 335 | return $this->http($url); 336 | }, $this->httpBuildQuery($url, $options)); 337 | } 338 | 339 | /** 340 | * Http Post 请求 341 | * @param $url 342 | * @param array $postOptions 343 | * @param array $options 344 | * @return mixed 345 | */ 346 | public function httpPost($url, array $postOptions, array $options = []) 347 | { 348 | Yii::info([ 349 | 'url' => $url, 350 | 'postOptions' => $postOptions, 351 | 'options' => $options 352 | ], __METHOD__); 353 | return $this->parseHttpRequest(function($url, $postOptions) { 354 | return $this->http($url, [ 355 | CURLOPT_POST => true, 356 | CURLOPT_POSTFIELDS => $postOptions 357 | ]); 358 | }, $this->httpBuildQuery($url, $options), $postOptions); 359 | } 360 | 361 | /** 362 | * Http Raw数据 Post 请求 363 | * @param $url 364 | * @param $postOptions 365 | * @param array $options 366 | * @return mixed 367 | */ 368 | public function httpRaw($url, $postOptions, array $options = []) 369 | { 370 | Yii::info([ 371 | 'url' => $url, 372 | 'postOptions' => $postOptions, 373 | 'options' => $options 374 | ], __METHOD__); 375 | return $this->parseHttpRequest(function($url, $postOptions) { 376 | return $this->http($url, [ 377 | CURLOPT_POST => true, 378 | CURLOPT_POSTFIELDS => is_array($postOptions) ? json_encode($postOptions, JSON_UNESCAPED_UNICODE) : $postOptions 379 | ]); 380 | }, $this->httpBuildQuery($url, $options), $postOptions); 381 | } 382 | 383 | /** 384 | * 解析微信请求响应内容 385 | * @param callable $callable Http请求主体函数 386 | * @param string $url Api地址 387 | * @param array|string|null $postOptions Api地址一般所需要的post参数 388 | * @return array|bool 389 | */ 390 | abstract public function parseHttpRequest(callable $callable, $url, $postOptions = null); 391 | 392 | /** 393 | * Http基础库 使用该库请求微信服务器 394 | * @param $url 395 | * @param array $options 396 | * @return bool|mixed 397 | */ 398 | protected function http($url, $options = []) 399 | { 400 | $options = [ 401 | CURLOPT_URL => $url, 402 | CURLOPT_TIMEOUT => 30, 403 | CURLOPT_CONNECTTIMEOUT => 30, 404 | CURLOPT_RETURNTRANSFER => true, 405 | ] + (stripos($url, "https://") !== false ? [ 406 | CURLOPT_SSL_VERIFYPEER => false, 407 | CURLOPT_SSL_VERIFYHOST => false, 408 | CURLOPT_SSLVERSION => CURL_SSLVERSION_TLSv1 // 微信官方屏蔽了ssl2和ssl3, 启用更高级的ssl 409 | ] : []) + $options; 410 | 411 | $curl = curl_init(); 412 | curl_setopt_array($curl, $options); 413 | $content = curl_exec($curl); 414 | $status = curl_getinfo($curl); 415 | curl_close($curl); 416 | if (isset($status['http_code']) && $status['http_code'] == 200) { 417 | return json_decode($content, true) ?: false; // 正常加载应该是只返回json字符串 418 | } 419 | Yii::error([ 420 | 'result' => $content, 421 | 'status' => $status 422 | ], __METHOD__); 423 | return false; 424 | } 425 | 426 | /** 427 | * 上传文件请使用该类来解决curl版本兼容问题 428 | * @param $filePath 429 | * @return \CURLFile|string 430 | */ 431 | protected function uploadFile($filePath) 432 | { 433 | // php 5.5将抛弃@写法,引用CURLFile类来实现 @see http://segmentfault.com/a/1190000000725185 434 | return class_exists('\CURLFile') ? new \CURLFile($filePath) : '@' . $filePath; 435 | } 436 | } 437 | -------------------------------------------------------------------------------- /components/MessageCrypt.php: -------------------------------------------------------------------------------- 1 | wechat = $wechat; 24 | parent::__construct($config); 25 | } 26 | } -------------------------------------------------------------------------------- /components/messageCrypt/ReadMe.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/callmez/yii2-wechat-sdk/6c3c9fbeecb5ad67741238ed67e80fd1016c18c7/components/messageCrypt/ReadMe.txt -------------------------------------------------------------------------------- /components/messageCrypt/demo.php: -------------------------------------------------------------------------------- 1 | 1407743423"; 12 | 13 | 14 | $pc = new WXBizMsgCrypt($token, $encodingAesKey, $appId); 15 | $encryptMsg = ''; 16 | $errCode = $pc->encryptMsg($text, $timeStamp, $nonce, $encryptMsg); 17 | if ($errCode == 0) { 18 | print("加密后: " . $encryptMsg . "\n"); 19 | } else { 20 | print($errCode . "\n"); 21 | } 22 | 23 | $xml_tree = new DOMDocument(); 24 | $xml_tree->loadXML($encryptMsg); 25 | $array_e = $xml_tree->getElementsByTagName('Encrypt'); 26 | $array_s = $xml_tree->getElementsByTagName('MsgSignature'); 27 | $encrypt = $array_e->item(0)->nodeValue; 28 | $msg_sign = $array_s->item(0)->nodeValue; 29 | 30 | $format = ""; 31 | $from_xml = sprintf($format, $encrypt); 32 | 33 | // 第三方收到公众号平台发送的消息 34 | $msg = ''; 35 | $errCode = $pc->decryptMsg($msg_sign, $timeStamp, $nonce, $from_xml, $msg); 36 | if ($errCode == 0) { 37 | print("解密后: " . $msg . "\n"); 38 | } else { 39 | print($errCode . "\n"); 40 | } 41 | -------------------------------------------------------------------------------- /components/messageCrypt/errorCode.php: -------------------------------------------------------------------------------- 1 | 6 | *
  • -40001: 签名验证错误
  • 7 | *
  • -40002: xml解析失败
  • 8 | *
  • -40003: sha加密生成签名失败
  • 9 | *
  • -40004: encodingAesKey 非法
  • 10 | *
  • -40005: appid 校验错误
  • 11 | *
  • -40006: aes 加密失败
  • 12 | *
  • -40007: aes 解密失败
  • 13 | *
  • -40008: 解密后得到的buffer非法
  • 14 | *
  • -40009: base64加密失败
  • 15 | *
  • -40010: base64解密失败
  • 16 | *
  • -40011: 生成xml失败
  • 17 | * 18 | */ 19 | class ErrorCode 20 | { 21 | public static $OK = 0; 22 | public static $ValidateSignatureError = -40001; 23 | public static $ParseXmlError = -40002; 24 | public static $ComputeSignatureError = -40003; 25 | public static $IllegalAesKey = -40004; 26 | public static $ValidateAppidError = -40005; 27 | public static $EncryptAESError = -40006; 28 | public static $DecryptAESError = -40007; 29 | public static $IllegalBuffer = -40008; 30 | public static $EncodeBase64Error = -40009; 31 | public static $DecodeBase64Error = -40010; 32 | public static $GenReturnXmlError = -40011; 33 | } 34 | 35 | ?> -------------------------------------------------------------------------------- /components/messageCrypt/pkcs7Encoder.php: -------------------------------------------------------------------------------- 1 | 32) { 47 | $pad = 0; 48 | } 49 | return substr($text, 0, (strlen($text) - $pad)); 50 | } 51 | 52 | } 53 | 54 | /** 55 | * Prpcrypt class 56 | * 57 | * 提供接收和推送给公众平台消息的加解密接口. 58 | */ 59 | class Prpcrypt 60 | { 61 | public $key; 62 | 63 | function Prpcrypt($k) 64 | { 65 | $this->key = base64_decode($k . "="); 66 | } 67 | 68 | /** 69 | * 对明文进行加密 70 | * @param string $text 需要加密的明文 71 | * @return string 加密后的密文 72 | */ 73 | public function encrypt($text, $appid) 74 | { 75 | 76 | try { 77 | //获得16位随机字符串,填充到明文之前 78 | $random = $this->getRandomStr(); 79 | $text = $random . pack("N", strlen($text)) . $text . $appid; 80 | // 网络字节序 81 | $size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); 82 | $module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, ''); 83 | $iv = substr($this->key, 0, 16); 84 | //使用自定义的填充方式对明文进行补位填充 85 | $pkc_encoder = new PKCS7Encoder; 86 | $text = $pkc_encoder->encode($text); 87 | mcrypt_generic_init($module, $this->key, $iv); 88 | //加密 89 | $encrypted = mcrypt_generic($module, $text); 90 | mcrypt_generic_deinit($module); 91 | mcrypt_module_close($module); 92 | 93 | //print(base64_encode($encrypted)); 94 | //使用BASE64对加密后的字符串进行编码 95 | return array(ErrorCode::$OK, base64_encode($encrypted)); 96 | } catch (Exception $e) { 97 | //print $e; 98 | return array(ErrorCode::$EncryptAESError, null); 99 | } 100 | } 101 | 102 | /** 103 | * 对密文进行解密 104 | * @param string $encrypted 需要解密的密文 105 | * @return string 解密得到的明文 106 | */ 107 | public function decrypt($encrypted, $appid) 108 | { 109 | 110 | try { 111 | //使用BASE64对需要解密的字符串进行解码 112 | $ciphertext_dec = base64_decode($encrypted); 113 | $module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, ''); 114 | $iv = substr($this->key, 0, 16); 115 | mcrypt_generic_init($module, $this->key, $iv); 116 | 117 | //解密 118 | $decrypted = mdecrypt_generic($module, $ciphertext_dec); 119 | mcrypt_generic_deinit($module); 120 | mcrypt_module_close($module); 121 | } catch (Exception $e) { 122 | return array(ErrorCode::$DecryptAESError, null); 123 | } 124 | 125 | 126 | try { 127 | //去除补位字符 128 | $pkc_encoder = new PKCS7Encoder; 129 | $result = $pkc_encoder->decode($decrypted); 130 | //去除16位随机字符串,网络字节序和AppId 131 | if (strlen($result) < 16) 132 | return ""; 133 | $content = substr($result, 16, strlen($result)); 134 | $len_list = unpack("N", substr($content, 0, 4)); 135 | $xml_len = $len_list[1]; 136 | $xml_content = substr($content, 4, $xml_len); 137 | $from_appid = substr($content, $xml_len + 4); 138 | } catch (Exception $e) { 139 | //print $e; 140 | return array(ErrorCode::$IllegalBuffer, null); 141 | } 142 | if ($from_appid != $appid) 143 | return array(ErrorCode::$ValidateAppidError, null); 144 | return array(0, $xml_content); 145 | 146 | } 147 | 148 | 149 | /** 150 | * 随机生成16位字符串 151 | * @return string 生成的字符串 152 | */ 153 | function getRandomStr() 154 | { 155 | 156 | $str = ""; 157 | $str_pol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; 158 | $max = strlen($str_pol) - 1; 159 | for ($i = 0; $i < 16; $i++) { 160 | $str .= $str_pol[mt_rand(0, $max)]; 161 | } 162 | return $str; 163 | } 164 | 165 | } 166 | 167 | ?> -------------------------------------------------------------------------------- /components/messageCrypt/sha1.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/messageCrypt/wxBizMsgCrypt.php: -------------------------------------------------------------------------------- 1 | token = $token; 34 | $this->encodingAesKey = $encodingAesKey; 35 | $this->appId = $appId; 36 | } 37 | 38 | /** 39 | * 将公众平台回复用户的消息加密打包. 40 | *
      41 | *
    1. 对要发送的消息进行AES-CBC加密
    2. 42 | *
    3. 生成安全签名
    4. 43 | *
    5. 将消息密文和安全签名打包成xml格式
    6. 44 | *
    45 | * 46 | * @param $replyMsg string 公众平台待回复用户的消息,xml格式的字符串 47 | * @param $timeStamp string 时间戳,可以自己生成,也可以用URL参数的timestamp 48 | * @param $nonce string 随机串,可以自己生成,也可以用URL参数的nonce 49 | * @param &$encryptMsg string 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串, 50 | * 当return返回0时有效 51 | * 52 | * @return int 成功0,失败返回对应的错误码 53 | */ 54 | public function encryptMsg($replyMsg, $timeStamp, $nonce, &$encryptMsg) 55 | { 56 | $pc = new Prpcrypt($this->encodingAesKey); 57 | 58 | //加密 59 | $array = $pc->encrypt($replyMsg, $this->appId); 60 | $ret = $array[0]; 61 | if ($ret != 0) { 62 | return $ret; 63 | } 64 | 65 | if ($timeStamp == null) { 66 | $timeStamp = time(); 67 | } 68 | $encrypt = $array[1]; 69 | 70 | //生成安全签名 71 | $sha1 = new SHA1; 72 | $array = $sha1->getSHA1($this->token, $timeStamp, $nonce, $encrypt); 73 | $ret = $array[0]; 74 | if ($ret != 0) { 75 | return $ret; 76 | } 77 | $signature = $array[1]; 78 | 79 | //生成发送的xml 80 | $xmlparse = new XMLParse; 81 | $encryptMsg = $xmlparse->generate($encrypt, $signature, $timeStamp, $nonce); 82 | return ErrorCode::$OK; 83 | } 84 | 85 | 86 | /** 87 | * 检验消息的真实性,并且获取解密后的明文. 88 | *
      89 | *
    1. 利用收到的密文生成安全签名,进行签名验证
    2. 90 | *
    3. 若验证通过,则提取xml中的加密消息
    4. 91 | *
    5. 对消息进行解密
    6. 92 | *
    93 | * 94 | * @param $msgSignature string 签名串,对应URL参数的msg_signature 95 | * @param $timestamp string 时间戳 对应URL参数的timestamp 96 | * @param $nonce string 随机串,对应URL参数的nonce 97 | * @param $postData string 密文,对应POST请求的数据 98 | * @param &$msg string 解密后的原文,当return返回0时有效 99 | * 100 | * @return int 成功0,失败返回对应的错误码 101 | */ 102 | public function decryptMsg($msgSignature, $timestamp = null, $nonce, $postData, &$msg) 103 | { 104 | if (strlen($this->encodingAesKey) != 43) { 105 | return ErrorCode::$IllegalAesKey; 106 | } 107 | 108 | $pc = new Prpcrypt($this->encodingAesKey); 109 | 110 | //提取密文 111 | $xmlparse = new XMLParse; 112 | $array = $xmlparse->extract($postData); 113 | $ret = $array[0]; 114 | 115 | if ($ret != 0) { 116 | return $ret; 117 | } 118 | 119 | if ($timestamp == null) { 120 | $timestamp = time(); 121 | } 122 | 123 | $encrypt = $array[1]; 124 | $touser_name = $array[2]; 125 | 126 | //验证安全签名 127 | $sha1 = new SHA1; 128 | $array = $sha1->getSHA1($this->token, $timestamp, $nonce, $encrypt); 129 | $ret = $array[0]; 130 | 131 | if ($ret != 0) { 132 | return $ret; 133 | } 134 | 135 | $signature = $array[1]; 136 | if ($signature != $msgSignature) { 137 | return ErrorCode::$ValidateSignatureError; 138 | } 139 | 140 | $result = $pc->decrypt($encrypt, $this->appId); 141 | if ($result[0] != 0) { 142 | return $result[0]; 143 | } 144 | $msg = $result[1]; 145 | 146 | return ErrorCode::$OK; 147 | } 148 | 149 | } 150 | 151 | -------------------------------------------------------------------------------- /components/messageCrypt/xmlparse.php: -------------------------------------------------------------------------------- 1 | loadXML($xmltext); 22 | $array_e = $xml->getElementsByTagName('Encrypt'); 23 | $array_a = $xml->getElementsByTagName('ToUserName'); 24 | $encrypt = $array_e->item(0)->nodeValue; 25 | $tousername = $array_a->item(0)->nodeValue; 26 | return array(0, $encrypt, $tousername); 27 | } catch (Exception $e) { 28 | //print $e . "\n"; 29 | return array(ErrorCode::$ParseXmlError, null, null); 30 | } 31 | } 32 | 33 | /** 34 | * 生成xml消息 35 | * @param string $encrypt 加密后的消息密文 36 | * @param string $signature 安全签名 37 | * @param string $timestamp 时间戳 38 | * @param string $nonce 随机字符串 39 | */ 40 | public function generate($encrypt, $signature, $timestamp, $nonce) 41 | { 42 | $format = " 43 | 44 | 45 | %s 46 | 47 | "; 48 | return sprintf($format, $encrypt, $signature, $timestamp, $nonce); 49 | } 50 | 51 | } 52 | 53 | 54 | ?> -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "callmez/yii2-wechat-sdk", 3 | "type": "yii2-extension", 4 | "description": "The wechat api for the Yii framework", 5 | "keywords": ["yii2", "wechat", "weixin", "sdk"], 6 | "license": "MIT", 7 | "support": { 8 | "issues": "https://github.com/callmez/yii2-wechat-sdk/issues", 9 | "wiki": "https://github.com/callmez/yii2-wechat-sdk/wiki", 10 | "source": "https://github.com/callmez/yii2-wechat-sdk" 11 | }, 12 | "authors": [ 13 | { 14 | "name": "CallMeZ", 15 | "email": "callme-z@qq.com" 16 | } 17 | ], 18 | "require": { 19 | "yiisoft/yii2": "*" 20 | }, 21 | "autoload": { 22 | "psr-4": { 23 | "callmez\\wechat\\sdk\\": "" 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /mp/Card.php: -------------------------------------------------------------------------------- 1 | wechat->httpPost(self::WECHAT_IMG_UPLOAD_PREFIX, [ 26 | 'buffer' => class_exists('\CURLFile') ? new \CURLFile($filePath) : '@' . $filePath 27 | ], [ 28 | 'access_token' => $this->wechat->getAccessToken() 29 | ]); 30 | 31 | return isset($result['url']) ? $result['url'] : false; 32 | } 33 | 34 | /* ==== 门店管理(文档V2.2.3) ===== */ 35 | 36 | /** 37 | * 创建门店 38 | */ 39 | const WECHAT_POI_ADD_PREFIX = '/cgi-bin/poi/addpoi'; 40 | /** 41 | * 创建门店 42 | * @param array $data 43 | * @return bool 44 | */ 45 | public function addPoi(array $data) 46 | { 47 | $result = $this->wechat->httpPost(self::WECHAT_POI_ADD_PREFIX, $data, [ 48 | 'access_token' => $this->wechat->getAccessToken() 49 | ]); 50 | return isset($result['errmsg']) && $result['errmsg'] === 'ok'; 51 | } 52 | 53 | /** 54 | * 查询单个门店 55 | */ 56 | const WECHAT_POI_GET_PREFIX = '/cgi-bin/poi/getpoi'; 57 | /** 58 | * 查询单个门店 59 | * @param $poiId 60 | * @return bool 61 | * @throws \yii\web\HttpException 62 | */ 63 | public function getPoi($poiId) 64 | { 65 | $result = $this->wechat->httpRaw(self::WECHAT_POI_GET_PREFIX, [ 66 | 'poi_id' => $poiId 67 | ], [ 68 | 'access_token' => $this->wechat->getAccessToken() 69 | ]); 70 | return isset($result['errmsg']) && $result['errmsg'] === 'ok' ? $result['business'] : false; 71 | } 72 | 73 | /** 74 | * 查询门店列表 75 | */ 76 | const WECHAT_POI_LIST_GET_PREFIX = '/cgi-bin/poi/getpoilist'; 77 | /** 78 | * 查询门店列表 79 | * @param array $data 80 | * @return bool 81 | * @throws \yii\web\HttpException 82 | */ 83 | public function getPoiList(array $data) 84 | { 85 | $result = $this->wechat->httpRaw(self::WECHAT_POI_LIST_GET_PREFIX, $data, [ 86 | 'access_token' => $this->wechat->getAccessToken() 87 | ]); 88 | return isset($result['errmsg']) && $result['errmsg'] === 'ok' ? $result['business_list'] : false; 89 | } 90 | 91 | /** 92 | * 删除门店 93 | */ 94 | const WECHAT_POI_DELETE_PREFIX = '/cgi-bin/poi/delpoi'; 95 | /** 96 | * 删除门店 97 | * @param $poiId 98 | * @return bool 99 | * @throws \yii\web\HttpException 100 | */ 101 | public function deletePoi($poiId) 102 | { 103 | $result = $this->wechat->httpRaw(self::WECHAT_POI_GET_PREFIX, [ 104 | 'poi_id' => $poiId 105 | ], [ 106 | 'access_token' => $this->wechat->getAccessToken() 107 | ]); 108 | return isset($result['errmsg']) && $result['errmsg'] === 'ok'; 109 | } 110 | 111 | /** 112 | * 更新门店信息 113 | */ 114 | const WECHAT_POI_UPDATE_PREFIX = '/cgi-bin/poi/updatepoi'; 115 | /** 116 | * 更新门店信息 117 | * @param array $data 118 | * @return bool 119 | * @throws \yii\web\HttpException 120 | */ 121 | public function updatePoi(array $data) 122 | { 123 | $result = $this->wechat->httpRaw(self::WECHAT_POI_UPDATE_PREFIX, $data, [ 124 | 'access_token' => $this->wechat->getAccessToken() 125 | ]); 126 | return isset($result['errmsg']) && $result['errmsg'] === 'ok'; 127 | } 128 | 129 | /* ==== 卡卷管理 ===== */ 130 | 131 | /** 132 | * 获取微信卡券颜色列表 133 | */ 134 | const WECHAT_CARD_COLORS_GET_PREFIX = '/card/getcolors'; 135 | /** 136 | * 获取微信卡券颜色列表 137 | * @return bool 138 | * @throws \yii\web\HttpException 139 | */ 140 | public function getColorList() 141 | { 142 | $result = $this->wechat->httpGet(self::WECHAT_CARD_COLORS_GET_PREFIX, [ 143 | 'access_token' => $this->wechat->getAccessToken() 144 | ]); 145 | return isset($result['errmsg']) && $result['errmsg'] === 'ok' ? $result['colors'] : false; 146 | } 147 | 148 | /** 149 | * 创建卡券 150 | */ 151 | const WECHAT_CARD_CREATE_PREFIX = '/card/create'; 152 | /** 153 | * 创建卡券 154 | * @param array $data 155 | * @return bool 156 | * @throws \yii\web\HttpException 157 | */ 158 | public function createCard(array $data) 159 | { 160 | $result = $this->wechat->httpRaw(self::WECHAT_CARD_CREATE_PREFIX, $data, [ 161 | 'access_token' => $this->wechat->getAccessToken() 162 | ]); 163 | return isset($result['errmsg']) && $result['errmsg'] === 'ok' ? $result['card_id'] : false; 164 | } 165 | 166 | /** 167 | * 创建二维码 168 | */ 169 | const WECHAT_QR_CODE_CREATE_PREFIX = '/card/qrcode/create'; 170 | /** 171 | * 创建二维码 172 | * @param array $data 173 | * @return bool 174 | * @throws \yii\web\HttpException 175 | */ 176 | public function createQrCode(array $data) 177 | { 178 | $result = $this->wechat->httpRaw(self::WECHAT_QR_CODE_CREATE_PREFIX, $data, [ 179 | 'access_token' => $this->wechat->getAccessToken() 180 | ]); 181 | return isset($result['errmsg']) && $result['errmsg'] === 'ok' ? $result['ticket'] : false; 182 | } 183 | 184 | /** 185 | * JS API更新后事件 186 | */ 187 | const EVENT_AFTER_JS_API_TICKET_UPDATE = 'afterJsApiTicketUpdate'; 188 | /** 189 | * @var array 190 | */ 191 | private $_jsApiTicket; 192 | /** 193 | * 获取JsApiTicket(添加卡券JS-SDK) 194 | * 超时后会自动重新获取JsApiTicket并触发self::EVENT_AFTER_JS_API_TICKET_UPDATE事件 195 | * @param bool $force 是否强制获取 196 | * @return mixed 197 | * @throws HttpException 198 | */ 199 | public function getJsApiTicket($force = false) 200 | { 201 | $time = time(); // 为了更精确控制.取当前时间计算 202 | $type = 'wx_card'; 203 | if ($this->_jsApiTicket === null || $this->_jsApiTicket['expire'] < $time || $force) { 204 | $result = $this->_jsApiTicket === null && !$force ? $this->wechat->getCache('card_js_api_ticket', false) : false; 205 | if ($result === false) { 206 | if (!($result = $this->wechat->requestJsApiTicket($type))) { 207 | throw new HttpException(500, 'Fail to get card jsapi_ticket from wechat server.'); 208 | } 209 | $result['expire'] = $time + $result['expires_in']; 210 | $this->trigger(self::EVENT_AFTER_JS_API_TICKET_UPDATE, new Event(['data' => $result])); 211 | $this->setCache('card_js_api_ticket', $result, $result['expires_in']); 212 | } 213 | $this->setJsApiTicket($result); 214 | } 215 | return $this->_jsApiTicket['ticket']; 216 | } 217 | 218 | /** 219 | * 设置JsApiTicket(添加卡券JS-SDK) 220 | * @param array $jsApiTicket 221 | */ 222 | public function setJsApiTicket(array $jsApiTicket) 223 | { 224 | $this->_jsApiTicket = $jsApiTicket; 225 | } 226 | 227 | /** 228 | * 核销卡券 229 | */ 230 | const WECHAT_CODE_CONSUME_PREFIX = '/card/code/consume'; 231 | 232 | /** 233 | * 核销卡券 234 | * @param array $data 235 | * @return bool 236 | * @throws \yii\web\HttpException 237 | */ 238 | public function consumeCode(array $data) 239 | { 240 | $result = $this->wechat->httpRaw(self::WECHAT_QR_CODE_CREATE_PREFIX, $data, [ 241 | 'access_token' => $this->wechat->getAccessToken() 242 | ]); 243 | return isset($result['errmsg']) && $result['errmsg'] === 'ok' ? $result['ticket'] : false; 244 | } 245 | /** 246 | * CODE解码 247 | */ 248 | const WECHAT_CARD_CODE_DECRYPT_URL = '/card/code/decrypt'; 249 | /** 250 | * CODE解码 251 | * @param $encryptCode 252 | * @return bool 253 | * @throws \yii\web\HttpException 254 | */ 255 | public function decryptCode($encryptCode) 256 | { 257 | $result = $this->wechat->httpRaw(self::WECHAT_QR_CODE_CREATE_PREFIX, [ 258 | 'encrypt_code' => $encryptCode 259 | ], [ 260 | 'access_token' => $this->wechat->getAccessToken() 261 | ]); 262 | return isset($result['errmsg']) && $result['errmsg'] === 'ok' ? $result['ticket'] : false; 263 | } 264 | 265 | /** 266 | * 删除卡券 267 | */ 268 | const WECHAT_CARD_DELETE_PREFIX = '/card/delete'; 269 | /** 270 | * 删除卡券 271 | * @param $cardId 272 | * @return bool 273 | * @throws \yii\web\HttpException 274 | */ 275 | public function deleteCard($cardId) 276 | { 277 | $result = $this->wechat->httpPost(self::WECHAT_DELETE_CARD_URL, [ 278 | 'card_id' => $cardId 279 | ], [ 280 | 'access_token' => $this->wechat->getAccessToken() 281 | ]); 282 | return isset($result['errmsg']) && $result['errmsg'] === 'ok' ? true : false; 283 | } 284 | 285 | /** 286 | * 查询code 287 | */ 288 | const WECHAT_CODE_GET_PREFIX = '/card/code/get'; 289 | /** 290 | * 查询code 291 | * @param $code 292 | * @return bool 293 | * @throws \yii\web\HttpException 294 | */ 295 | public function getCode($code) 296 | { 297 | $result = $this->wechat->httpPost(self::WECHAT_DELETE_CARD_URL, [ 298 | 'code' => $code 299 | ], [ 300 | 'access_token' => $this->wechat->getAccessToken() 301 | ]); 302 | return isset($result['errmsg']) && $result['errmsg'] === 'ok' ? $result : false; 303 | } 304 | 305 | /** 306 | * 批量查询卡列表 307 | */ 308 | const WECHAT_CARD_LIST_GET_PREFIX = '/card/batchget'; 309 | /** 310 | * 批量查询卡列表 311 | * @param array $data 312 | * @return bool|mixed 313 | * @throws \yii\web\HttpException 314 | */ 315 | public function getCardList(array $data) 316 | { 317 | $result = $this->wechat->httpPost(self::WECHAT_CARD_LIST_GET_PREFIX, $data, [ 318 | 'access_token' => $this->wechat->getAccessToken() 319 | ]); 320 | return isset($result['errmsg']) && $result['errmsg'] === 'ok' ? $result : false; 321 | } 322 | 323 | /** 324 | * 查询卡券详情 325 | */ 326 | const WECHAT_CARD_GET_PREFIX = '/card/get'; 327 | /** 328 | * 查询卡券详情 329 | * @param $cardId 330 | * @return bool|mixed 331 | * @throws \yii\web\HttpException 332 | */ 333 | public function getCard($cardId) 334 | { 335 | $result = $this->wechat->httpPost(self::WECHAT_CARD_LIST_GET_PREFIX, [ 336 | 'card_id' => $cardId 337 | ], [ 338 | 'access_token' => $this->wechat->getAccessToken() 339 | ]); 340 | return isset($result['errmsg']) && $result['errmsg'] === 'ok' ? $result : false; 341 | } 342 | 343 | /** 344 | * 更改code 345 | */ 346 | const WECHAT_CODE_UPDATE_PREFIX = '/card/code/update'; 347 | /** 348 | * 更改code 349 | * @param array $data 350 | * @return bool 351 | * @throws \yii\web\HttpException 352 | */ 353 | public function updateCode(array $data) 354 | { 355 | $result = $this->wechat->httpPost(self::WECHAT_CARD_LIST_GET_PREFIX, $data, [ 356 | 'access_token' => $this->wechat->getAccessToken() 357 | ]); 358 | return isset($result['errmsg']) && $result['errmsg'] === 'ok'; 359 | } 360 | 361 | /** 362 | * 设置卡券失效接口 363 | */ 364 | const WECHAT_CODE_UNAVAILABLE_SET_PREFIX = '/card/code/unavailable'; 365 | public function setCodeUnavailable(array $data) 366 | { 367 | $result = $this->wechat->httpPost(self::WECHAT_CARD_LIST_GET_PREFIX, $data, [ 368 | 'access_token' => $this->wechat->getAccessToken() 369 | ]); 370 | return isset($result['errmsg']) && $result['errmsg'] === 'ok'; 371 | } 372 | 373 | /** 374 | * 更改卡券信息接口 375 | */ 376 | const WECHAT_CARD_UPDATE_PREFIX = '/card/update'; 377 | /** 378 | * 更改卡券信息接口 379 | * @param array $data 380 | * @return bool 381 | * @throws \yii\web\HttpException 382 | */ 383 | public function updateCard(array $data) 384 | { 385 | $result = $this->wechat->httpPost(self::WECHAT_CARD_LIST_GET_PREFIX, $data, [ 386 | 'access_token' => $this->wechat->getAccessToken() 387 | ]); 388 | return isset($result['errmsg']) && $result['errmsg'] === 'ok'; 389 | } 390 | 391 | /** 392 | * 库存修改接口 393 | */ 394 | const WECHAT_CARD_STOCK_UPDATE = '/card/modifystock'; 395 | /** 396 | * 库存修改接口 397 | * @param array $data 398 | * @return bool 399 | * @throws \yii\web\HttpException 400 | */ 401 | public function updateCardStock(array $data) 402 | { 403 | $result = $this->wechat->httpPost(self::WECHAT_CARD_LIST_GET_PREFIX, $data, [ 404 | 'access_token' => $this->wechat->getAccessToken() 405 | ]); 406 | return isset($result['errmsg']) && $result['errmsg'] === 'ok'; 407 | } 408 | 409 | /** 410 | * 激活/绑定会员卡 411 | */ 412 | const WECHAT_MEMBER_CARD_ACTIVATE_PREFIX = '/card/membercard/activate'; 413 | /** 414 | * 激活/绑定会员卡 415 | * @param array $data 416 | * @return bool 417 | * @throws \yii\web\HttpException 418 | */ 419 | public function activateMemberCard(array $data) 420 | { 421 | $result = $this->wechat->httpPost(self::WECHAT_CARD_LIST_GET_PREFIX, $data, [ 422 | 'access_token' => $this->wechat->getAccessToken() 423 | ]); 424 | return isset($result['errmsg']) && $result['errmsg'] === 'ok'; 425 | } 426 | 427 | /** 428 | * 会员卡交易 429 | */ 430 | const WECHAT_MEMBER_CARD_USER_UPDATE_PREFIX = '/card/membercard/updateuser'; 431 | 432 | /** 433 | * 会员卡交易 434 | * @param array $data 435 | * @return bool 436 | * @throws \yii\web\HttpException 437 | */ 438 | public function userUpdateMemberCard(array $data) 439 | { 440 | $result = $this->wechat->httpPost(self::WECHAT_CARD_LIST_GET_PREFIX, $data, [ 441 | 'access_token' => $this->wechat->getAccessToken() 442 | ]); 443 | return isset($result['errmsg']) && $result['errmsg'] === 'ok' ? $result : false; 444 | } 445 | 446 | /** 447 | * 更新电影票 448 | */ 449 | const WECHAT_USER_UPDATE_MOVIE_TICKET_PREFIX = '/card/movieticket/updateuser'; 450 | /** 451 | * 更新电影票 452 | * @param array $data 453 | * @return bool|mixed 454 | * @throws \yii\web\HttpException 455 | */ 456 | public function userUpdateMovieTicket(array $data) 457 | { 458 | $result = $this->wechat->httpPost(self::WECHAT_CARD_LIST_GET_PREFIX, $data, [ 459 | 'access_token' => $this->wechat->getAccessToken() 460 | ]); 461 | return isset($result['errmsg']) && $result['errmsg'] === 'ok' ? $result : false; 462 | } 463 | 464 | /** 465 | * 飞机票 466 | */ 467 | const WECHAT_BOARDINGPASS_CHECKIN_PREFIX = '/card/boardingpass/checkin'; 468 | /** 469 | * 飞机票 470 | * @param array $data 471 | * @return bool|mixed 472 | * @throws \yii\web\HttpException 473 | */ 474 | public function checkinBoardingpass(array $data) 475 | { 476 | $result = $this->wechat->httpPost(self::WECHAT_CARD_LIST_GET_PREFIX, $data, [ 477 | 'access_token' => $this->wechat->getAccessToken() 478 | ]); 479 | return isset($result['errmsg']) && $result['errmsg'] === 'ok'; 480 | } 481 | 482 | /** 483 | * 会议门票 484 | */ 485 | const WECHAT_METTING_TICKET_USER_UPDATE_PREFIX = '/card/meetingticket/updateuser'; 486 | /** 487 | * 会议门票 488 | * @param array $data 489 | * @return bool 490 | * @throws \yii\web\HttpException 491 | */ 492 | public function userUpateMeetingTicket(array $data) 493 | { 494 | $result = $this->wechat->httpPost(self::WECHAT_CARD_LIST_GET_PREFIX, $data, [ 495 | 'access_token' => $this->wechat->getAccessToken() 496 | ]); 497 | return isset($result['errmsg']) && $result['errmsg'] === 'ok'; 498 | } 499 | 500 | /** 501 | * 设置测试用户白名单 502 | */ 503 | const WECHAT_TEST_WHITE_LIST_SET_PREFIX = '/card/testwhitelist/set'; 504 | /** 505 | * 设置测试用户白名单 506 | * @param array $data 507 | * @return bool 508 | * @throws \yii\web\HttpException 509 | */ 510 | public function setTestWhiteList(array $data) 511 | { 512 | $result = $this->wechat->httpPost(self::WECHAT_CARD_LIST_GET_PREFIX, $data, [ 513 | 'access_token' => $this->wechat->getAccessToken() 514 | ]); 515 | return isset($result['errmsg']) && $result['errmsg'] === 'ok'; 516 | } 517 | } -------------------------------------------------------------------------------- /mp/CustomService.php: -------------------------------------------------------------------------------- 1 | wechat->httpRaw(self::WECHAT_ACCOUNT_ADD_PREFIX, $account, [ 25 | 'access_token' => $this->wechat->getAccessToken() 26 | ]); 27 | return isset($result['errmsg']) && $result['errmsg'] == 'ok'; 28 | } 29 | 30 | /** 31 | * 修改客服帐号 32 | */ 33 | const WECHAT_ACCOUNT_UPDATE_PREFIX = '/customservice/kfaccount/update'; 34 | /** 35 | * 修改客服帐号 36 | * @param array $account 37 | * @return bool 38 | * @throws \yii\web\HttpException 39 | */ 40 | public function updateAccount(array $account) 41 | { 42 | $result = $this->wechat->httpRaw(self::WECHAT_ACCOUNT_UPDATE_PREFIX, $account, [ 43 | 'access_token' => $this->wechat->getAccessToken() 44 | ]); 45 | return isset($result['errmsg']) && $result['errmsg'] == 'ok'; 46 | } 47 | 48 | /** 49 | * 删除客服帐号 50 | */ 51 | const WECHAT_ACCOUNT_DELETE_PREFIX = '/customservice/kfaccount/del'; 52 | /** 53 | * 删除客服帐号 54 | * @param array $account 55 | * @return bool 56 | * @throws \yii\web\HttpException 57 | */ 58 | public function deleteAccount(array $account) 59 | { 60 | $result = $this->wechat->httpRaw(self::WECHAT_ACCOUNT_DELETE_PREFIX, $account, [ 61 | 'access_token' => $this->wechat->getAccessToken() 62 | ]); 63 | return isset($result['errmsg']) && $result['errmsg'] == 'ok'; 64 | } 65 | 66 | /** 67 | * 设置客服账号头像 68 | */ 69 | const WECHAT_ACCOUNT_AVATAR_SET_PREFIX = '/customservice/kfaccount/uploadheadimg'; 70 | /** 71 | * 设置客服账号头像 72 | * @param string $accountName 73 | * @param string $avatarPath 74 | * @return bool 75 | * @throws \yii\web\HttpException 76 | */ 77 | public function setAccountAvatar($accountName, $avatarPath) 78 | { 79 | $result = $this->wechat->httpPost(self::WECHAT_ACCOUNT_AVATAR_SET_PREFIX, [ 80 | 'media' => $this->wechat->uploadFile($avatarPath) 81 | ], [ 82 | 'access_token' => $this->wechat->getAccessToken(), 83 | 'kf_account' => $accountName 84 | ]); 85 | return isset($result['errmsg']) && $result['errmsg'] == 'ok'; 86 | } 87 | 88 | /** 89 | * 获取所有客服账号 90 | */ 91 | const WECHAT_ACCOUNT_LIST_GET_PREFIX = '/cgi-bin/customservice/getkflist'; 92 | /** 93 | * 获取所有客服账号 94 | * @return bool 95 | * @throws \yii\web\HttpException 96 | */ 97 | public function getAccountList() 98 | { 99 | $result = $this->wechat->httpGet(self::WECHAT_ACCOUNT_LIST_GET_PREFIX, [ 100 | 'access_token' => $this->wechat->getAccessToken() 101 | ]); 102 | return isset($result['kf_list']) ? $result['kf_list'] : false; 103 | } 104 | 105 | /** 106 | * 获取客服聊天记录 107 | */ 108 | const WECHAT_MESSAGE_RECORD_GET_PREFIX = '/customservice/msgrecord/getrecord'; 109 | /** 110 | * 获取客服聊天记录 111 | * @param array $data 112 | * @return bool 113 | * @throws \yii\web\HttpException 114 | */ 115 | public function getMessageRecord(array $data) 116 | { 117 | $result = $this->wechat->httpRaw(self::WECHAT_MESSAGE_RECORD_GET_PREFIX, $data, [ 118 | 'access_token' => $this->wechat->getAccessToken() 119 | ]); 120 | return isset($result['errcode']) && !$result['errcode'] ? $result['recordlist'] : false; 121 | } 122 | } -------------------------------------------------------------------------------- /mp/DataCube.php: -------------------------------------------------------------------------------- 1 | wechat->httpRaw(self::WECHAT_USER_SUMMARY_GET_PREFIX, $data, [ 25 | 'access_token' => $this->wechat->getAccessToken() 26 | ]); 27 | return isset($result['list']) ? $result['list'] : false; 28 | } 29 | 30 | /** 31 | * 获取累计用户数据 32 | */ 33 | const WECHAT_USER_CUMULATE_GET_PREFIX = '/datacube/getusercumulate'; 34 | /** 35 | * 获取累计用户数据 36 | * @param array $data 37 | * @return bool 38 | * @throws \yii\web\HttpException 39 | */ 40 | public function getUserCumulate(array $data) 41 | { 42 | $result = $this->wechat->httpRaw(self::WECHAT_USER_CUMULATE_GET_PREFIX, $data, [ 43 | 'access_token' => $this->wechat->getAccessToken() 44 | ]); 45 | return isset($result['list']) ? $result['list'] : false; 46 | } 47 | 48 | /** 49 | * 获取图文群发每日数据 50 | */ 51 | const WECHAT_ARTICLES_SUMMARY_GET_PREFIX = '/datacube/getarticlesummary'; 52 | /** 53 | * 获取图文群发每日数据 54 | * @param array $data 55 | * @return bool 56 | * @throws \yii\web\HttpException 57 | */ 58 | public function getArticleSummary(array $data) 59 | { 60 | $result = $this->wechat->httpRaw(self::WECHAT_ARTICLES_SUMMARY_GET_PREFIX, $data, [ 61 | 'access_token' => $this->wechat->getAccessToken() 62 | ]); 63 | return isset($result['list']) ? $result['list'] : false; 64 | } 65 | 66 | /** 67 | * 获取图文群发总数据 68 | */ 69 | const WECHAT_ARTICLES_TOTAL_GET_PREFIX = '/datacube/getarticletotal'; 70 | /** 71 | * 获取图文群发总数据 72 | * @param array $data 73 | * @return bool 74 | * @throws \yii\web\HttpException 75 | */ 76 | public function getArticleTotal(array $data) 77 | { 78 | $result = $this->wechat->httpRaw(self::WECHAT_ARTICLES_TOTAL_GET_PREFIX, $data, [ 79 | 'access_token' => $this->wechat->getAccessToken() 80 | ]); 81 | return isset($result['list']) ? $result['list'] : false; 82 | } 83 | 84 | /** 85 | * 获取图文统计数据 86 | */ 87 | const WECHAT_USER_READ_GET_PREFIX = '/datacube/getuserread'; 88 | /** 89 | * 获取图文统计数据 90 | * @param array $data 91 | * @return bool 92 | * @throws \yii\web\HttpException 93 | */ 94 | public function getUserRead(array $data) 95 | { 96 | $result = $this->wechat->httpRaw(self::WECHAT_USER_READ_GET_PREFIX, $data, [ 97 | 'access_token' => $this->wechat->getAccessToken() 98 | ]); 99 | return isset($result['list']) ? $result['list'] : false; 100 | } 101 | 102 | /** 103 | * 获取图文统计分时数据 104 | */ 105 | const WECHAT_USER_READ_HOUR_GET_PREFIX = '/datacube/getuserreadhour'; 106 | /** 107 | * 获取图文统计分时数据 108 | * @param array $data 109 | * @return bool 110 | * @throws \yii\web\HttpException 111 | */ 112 | public function getUserReadHour(array $data) 113 | { 114 | $result = $this->wechat->httpRaw(self::WECHAT_USER_READ_HOUR_GET_PREFIX, $data, [ 115 | 'access_token' => $this->wechat->getAccessToken() 116 | ]); 117 | return isset($result['list']) ? $result['list'] : false; 118 | } 119 | 120 | /** 121 | * 获取图文分享转发数据 122 | */ 123 | const WECHAT_USER_SHARE_GET_PREFIX = '/datacube/getusershare'; 124 | /** 125 | * 获取图文分享转发数据 126 | * @param array $data 127 | * @return bool 128 | * @throws \yii\web\HttpException 129 | */ 130 | public function getUserShare(array $data) 131 | { 132 | $result = $this->wechat->httpRaw(self::WECHAT_USER_SHARE_GET_PREFIX, $data, [ 133 | 'access_token' => $this->wechat->getAccessToken() 134 | ]); 135 | return isset($result['list']) ? $result['list'] : false; 136 | } 137 | 138 | /** 139 | * 获取图文分享转发分时数据 140 | */ 141 | const WECHAT_USER_SHARE_HOUR_GET_PREFIX = '/datacube/getusersharehour'; 142 | /** 143 | * 获取图文分享转发分时数据 144 | * @param array $data 145 | * @return bool 146 | * @throws \yii\web\HttpException 147 | */ 148 | public function getUserShareUour(array $data) 149 | { 150 | $result = $this->wechat->httpRaw(self::WECHAT_USER_SHARE_HOUR_GET_PREFIX, $data, [ 151 | 'access_token' => $this->wechat->getAccessToken() 152 | ]); 153 | return isset($result['list']) ? $result['list'] : false; 154 | } 155 | 156 | /** 157 | * 获取消息发送概况数据 158 | */ 159 | const WECHAT_UP_STREAM_MESSAGE_GET_PREFIX = '/datacube/getupstreammsg'; 160 | /** 161 | * 获取消息发送概况数据 162 | * @param array $data 163 | * @return bool 164 | * @throws \yii\web\HttpException 165 | */ 166 | public function getUpStreamMessage(array $data) 167 | { 168 | $result = $this->wechat->httpRaw(self::WECHAT_UP_STREAM_MESSAGE_GET_PREFIX, $data, [ 169 | 'access_token' => $this->wechat->getAccessToken() 170 | ]); 171 | return isset($result['list']) ? $result['list'] : false; 172 | } 173 | 174 | /** 175 | * 获取消息分送分时数据 176 | */ 177 | const WECHAT_UP_STREAM_MESSAGE_HOUR_GET_PREFIX = '/datacube/getupstreammsghour'; 178 | /** 179 | * 获取消息分送分时数据 180 | * @param array $data 181 | * @return bool 182 | * @throws \yii\web\HttpException 183 | */ 184 | public function getUpStreamMessageHour(array $data) 185 | { 186 | $result = $this->wechat->httpRaw(self::WECHAT_UP_STREAM_MESSAGE_HOUR_GET_PREFIX, $data, [ 187 | 'access_token' => $this->wechat->getAccessToken() 188 | ]); 189 | return isset($result['list']) ? $result['list'] : false; 190 | } 191 | 192 | /** 193 | * 获取消息发送周数据 194 | */ 195 | const WECHAT_UP_STREAM_MESSAGE_WEEK_GET_PREFIX = '/datacube/getupstreammsgweek'; 196 | /** 197 | * 获取消息发送周数据 198 | * @param array $data 199 | * @return bool 200 | * @throws \yii\web\HttpException 201 | */ 202 | public function getUpStreamMessageWeek(array $data) 203 | { 204 | $result = $this->wechat->httpRaw(self::WECHAT_UP_STREAM_MESSAGE_WEEK_GET_PREFIX, $data, [ 205 | 'access_token' => $this->wechat->getAccessToken() 206 | ]); 207 | return isset($result['list']) ? $result['list'] : false; 208 | } 209 | 210 | /** 211 | * 获取消息发送月数据 212 | */ 213 | const WECHAT_UP_STREAM_MESSAGE_MONTH_GET_PREFIX = '/datacube/getupstreammsgmonth'; 214 | /** 215 | * 获取消息发送月数据 216 | * @param array $data 217 | * @return bool 218 | * @throws \yii\web\HttpException 219 | */ 220 | public function getUpStreamMessageMonth(array $data) 221 | { 222 | $result = $this->wechat->httpRaw(self::WECHAT_UP_STREAM_MESSAGE_MONTH_GET_PREFIX, $data, [ 223 | 'access_token' => $this->wechat->getAccessToken() 224 | ]); 225 | return isset($result['list']) ? $result['list'] : false; 226 | } 227 | 228 | /** 229 | * 获取消息发送分布数据 230 | */ 231 | const WECHAT_UP_STREAM_MESSAGE_DIST_GET_PREFIX = '/datacube/getupstreammsgdist'; 232 | /** 233 | * 获取消息发送分布数据 234 | * @param array $data 235 | * @return bool 236 | * @throws \yii\web\HttpException 237 | */ 238 | public function getUpStreamMessageDist(array $data) 239 | { 240 | $result = $this->wechat->httpRaw(self::WECHAT_UP_STREAM_MESSAGE_DIST_GET_PREFIX, $data, [ 241 | 'access_token' => $this->wechat->getAccessToken() 242 | ]); 243 | return isset($result['list']) ? $result['list'] : false; 244 | } 245 | 246 | /** 247 | * 获取消息发送分布周数据 248 | */ 249 | const WECHAT_UP_STREAM_MESSAGE_DIST_WEEK_GET_PREFIX = '/datacube/getupstreammsgdistweek'; 250 | /** 251 | * 获取消息发送分布周数据 252 | * @param array $data 253 | * @return bool 254 | * @throws \yii\web\HttpException 255 | */ 256 | public function getUpStreamMessageDistWeek(array $data) 257 | { 258 | $result = $this->wechat->httpRaw(self::WECHAT_UP_STREAM_MESSAGE_DIST_WEEK_GET_PREFIX, $data, [ 259 | 'access_token' => $this->wechat->getAccessToken() 260 | ]); 261 | return isset($result['list']) ? $result['list'] : false; 262 | } 263 | 264 | /** 265 | * 获取消息发送分布月数据 266 | */ 267 | const WECHAT_UP_STREAM_MESSAGE_DIST_MONTH_GET_PREFIX = '/datacube/getupstreammsgdistmonth'; 268 | /** 269 | * 获取消息发送分布月数据 270 | * @param array $data 271 | * @return bool 272 | * @throws \yii\web\HttpException 273 | */ 274 | public function getUpStreamMessageDistMonth(array $data) 275 | { 276 | $result = $this->wechat->httpRaw(self::WECHAT_UP_STREAM_MESSAGE_DIST_MONTH_GET_PREFIX, $data, [ 277 | 'access_token' => $this->wechat->getAccessToken() 278 | ]); 279 | return isset($result['list']) ? $result['list'] : false; 280 | } 281 | 282 | /** 283 | * 获取接口分析数据 284 | */ 285 | const WECHAT_INTERFACE_SUMMARY_GET_PREFIX = '/datacube/getinterfacesummary'; 286 | /** 287 | * 获取接口分析数据 288 | * @param array $data 289 | * @return bool 290 | * @throws \yii\web\HttpException 291 | */ 292 | public function getInterfaceSummary(array $data) 293 | { 294 | $result = $this->wechat->httpRaw(self::WECHAT_INTERFACE_SUMMARY_GET_PREFIX, $data, [ 295 | 'access_token' => $this->wechat->getAccessToken() 296 | ]); 297 | return isset($result['list']) ? $result['list'] : false; 298 | } 299 | 300 | /** 301 | * 获取接口分析分时数据 302 | */ 303 | const WECHAT_INTERFACE_SUMMARY_HOUR_GET_PREFIX = '/datacube/getinterfacesummaryhour'; 304 | /** 305 | * 获取接口分析分时数据 306 | * @param array $data 307 | * @return bool 308 | * @throws \yii\web\HttpException 309 | */ 310 | public function getInterfaceSummaryHour(array $data) 311 | { 312 | $result = $this->wechat->httpRaw(self::WECHAT_INTERFACE_SUMMARY_HOUR_GET_PREFIX, $data, [ 313 | 'access_token' => $this->wechat->getAccessToken() 314 | ]); 315 | return isset($result['list']) ? $result['list'] : false; 316 | } 317 | } -------------------------------------------------------------------------------- /mp/Merchant.php: -------------------------------------------------------------------------------- 1 | wechat->httpRaw(self::WECHAT_PRODUCT_ADD_PREFIX, $data, [ 26 | 'access_token' => $this->wechat->getAccessToken() 27 | ]); 28 | return isset($result['errmsg']) && $result['errmsg'] == 'success' ? $result['product_id'] : false; 29 | } 30 | 31 | /** 32 | * 商品删除 33 | */ 34 | const WECHAT_PRODUCT_DELETE_PREFIX = '/merchant/del'; 35 | /** 36 | * 删除商品 37 | * @param $productId 38 | * @return bool 39 | */ 40 | public function deleteProduct($productId) 41 | { 42 | $result = $this->wechat->httpRaw(self::WECHAT_PRODUCT_DELETE_PREFIX, [ 43 | 'product_id' => $productId 44 | ], [ 45 | 'access_token' => $this->wechat->getAccessToken() 46 | ]); 47 | return isset($result['errmsg']) && $result['errmsg'] == 'success'; 48 | } 49 | 50 | /** 51 | * 商品修改 52 | */ 53 | const WECHAT_PRODUCT_UPDATE_PREFIX = '/merchant/update'; 54 | /** 55 | * 商品修改 56 | * @param array $data 57 | * @return bool 58 | * @throws \yii\web\HttpException 59 | */ 60 | public function updateProduct(array $data) 61 | { 62 | $result = $this->wechat->httpRaw(self::WECHAT_PRODUCT_UPDATE_PREFIX, $data, [ 63 | 'access_token' => $this->wechat->getAccessToken() 64 | ]); 65 | return isset($result['errmsg']) && $result['errmsg'] == 'success'; 66 | } 67 | 68 | /** 69 | * 查询商品信息 70 | */ 71 | const WECHAT_PRODUCT_GET_PREFIX = '/merchant/get'; 72 | /** 73 | * 查询商品信息 74 | * @param $productId 75 | * @return bool 76 | * @throws \yii\web\HttpException 77 | */ 78 | public function getProduct($productId) 79 | { 80 | $result = $this->wechat->httpRaw(self::WECHAT_PRODUCT_GET_PREFIX, [ 81 | 'product_id' => $productId 82 | ], [ 83 | 'access_token' => $this->wechat->getAccessToken() 84 | ]); 85 | return isset($result['errmsg']) && $result['errmsg'] == 'success' ? $result['product_info'] : false; 86 | } 87 | 88 | /** 89 | * 获取指定状态的商品 90 | */ 91 | const WECHAT_PRODUCT_STATUS_GET_PREFIX = '/merchant/getbystatus'; 92 | /** 93 | * 获取指定状态的商品 94 | * @param $status 商品状态(0-全部, 1-上架, 2-下架) 95 | * @return array|bool 96 | */ 97 | public function getProductByStatus($status) 98 | { 99 | $result = $this->wechat->httpRaw(self::WECHAT_PRODUCT_STATUS_GET_PREFIX, [ 100 | 'status' => $status 101 | ], [ 102 | 'access_token' => $this->wechat->getAccessToken() 103 | ]); 104 | return isset($result['errmsg']) && $result['errmsg'] == 'success' ? $result['product_info'] : false; 105 | } 106 | 107 | /** 108 | * 更改商品状态(上下架) 109 | */ 110 | const WECHAT_PRODUCT_STATUS_UPDATE_PREFIX = '/merchant/modproductstatus'; 111 | /** 112 | * 更改商品状态(上下架) 113 | * @param array $data 114 | * @return bool 115 | * @throws \yii\web\HttpException 116 | */ 117 | public function updateProductStatus(array $data) 118 | { 119 | $result = $this->wechat->httpRaw(self::WECHAT_PRODUCT_STATUS_UPDATE_PREFIX, $data, [ 120 | 'access_token' => $this->wechat->getAccessToken() 121 | ]); 122 | return isset($result['errmsg']) && $result['errmsg'] == 'success'; 123 | } 124 | 125 | /** 126 | * 获取指定分类的所有子分类 127 | */ 128 | const WECHAT_CATEGORY_SUB_CATEGROIES_GET_PREFIX = '/merchant/category/getsub'; 129 | /** 130 | * 获取指定分类的所有子分类 131 | * @param $cateId 132 | * @return bool 133 | * @throws \yii\web\HttpException 134 | */ 135 | public function getCategorySubCategories($cateId) 136 | { 137 | $result = $this->wechat->httpRaw(self::WECHAT_CATEGORY_SUB_CATEGROIES_GET_PREFIX, [ 138 | 'cate_id' => $cateId 139 | ], [ 140 | 'access_token' => $this->wechat->getAccessToken() 141 | ]); 142 | return isset($result['errmsg']) && $result['errmsg'] == 'success' ? $result['cate_list'] : false; 143 | } 144 | 145 | /** 146 | * 获取指定子分类的所有SKU 147 | */ 148 | const WECHAT_CATEGORY_SKU_LIST_PREFIX = '/merchant/category/getsku'; 149 | /** 150 | * 获取指定分类的单品 151 | * @param $cateId 152 | * @return bool 153 | * @throws \yii\web\HttpException 154 | */ 155 | public function getCategorySkuList($cateId) 156 | { 157 | $result = $this->wechat->httpRaw(self::WECHAT_CATEGORY_SKU_LIST_PREFIX, [ 158 | 'cate_id' => $cateId 159 | ], [ 160 | 'access_token' => $this->wechat->getAccessToken() 161 | ]); 162 | return isset($result['errmsg']) && $result['errmsg'] == 'success' ? $result['sku_table'] : false; 163 | } 164 | 165 | /** 166 | * 获取指定分类的所有属性 167 | */ 168 | const WECHAT_CATEGORY_PROPERTY_GET_PREFIX = '/merchant/category/getproperty'; 169 | /** 170 | * 获取指定分类的所有属性 171 | * @param $cateId 分类ID 172 | * @return array|bool 173 | */ 174 | public function getCategoryProperty($cateId) 175 | { 176 | $result = $this->wechat->httpRaw(self::WECHAT_CATEGORY_PROPERTY_GET_PREFIX, [ 177 | 'cate_id' => $cateId 178 | ], [ 179 | 'access_token' => $this->wechat->getAccessToken() 180 | ]); 181 | return isset($result['errmsg']) && $result['errmsg'] == 'success' ? $result['properties'] : false; 182 | } 183 | 184 | /** 185 | * 商品增加库存 186 | */ 187 | const WECHAT_PRODUCT_STOCK_ADD_PREFIX = '/merchant/stock/add'; 188 | /** 189 | * 增加库存 190 | * @param array $data 191 | * @return bool 192 | * @throws \yii\web\HttpException 193 | */ 194 | public function addProductStock(array $data) 195 | { 196 | $result = $this->wechat->httpRaw(self::WECHAT_PRODUCT_STOCK_ADD_PREFIX, $data, [ 197 | 'access_token' => $this->wechat->getAccessToken() 198 | ]); 199 | return isset($result['errmsg']) && $result['errmsg'] == 'success'; 200 | } 201 | 202 | /** 203 | * 减少库存 204 | */ 205 | const WECHAT_PRODUCT_STOCK_REDUCE_URL = '/merchant/stock/reduce'; 206 | /** 207 | * 减少库存 208 | * @param array $data 209 | * @return bool 210 | * @throws \yii\web\HttpException 211 | */ 212 | public function reduceProductStock(array $data) 213 | { 214 | $result = $this->wechat->httpRaw(self::WECHAT_PRODUCT_STOCK_REDUCE_URL, $data, [ 215 | 'access_token' => $this->wechat->getAccessToken() 216 | ]); 217 | return isset($result['errmsg']) && $result['errmsg'] == 'success'; 218 | } 219 | 220 | /** 221 | * 增加邮费模板 222 | */ 223 | const WECHAT_DELIVERY_TEMPLATE_ADD_PREFIX = '/merchant/express/add'; 224 | /** 225 | * @param array $deliveryTemplate 226 | * @return bool 227 | * @throws \yii\web\HttpException 228 | */ 229 | public function addDeliveryTemplate(array $deliveryTemplate) 230 | { 231 | $result = $this->wechat->httpRaw(self::WECHAT_DELIVERY_TEMPLATE_ADD_PREFIX, [ 232 | 'delivery_template' => $deliveryTemplate 233 | ], [ 234 | 'access_token' => $this->wechat->getAccessToken() 235 | ]); 236 | return isset($result['errmsg']) && $result['errmsg'] == 'success' ? $result['template_id'] : false; 237 | } 238 | 239 | /** 240 | * 删除邮费模板 241 | */ 242 | const WECHAT_DELIVERY_TEMPLATE_DELETE_PREFIX = '/merchant/express/del'; 243 | /** 244 | * 删除邮费模板 245 | * @param int $templateId 邮费模板ID 246 | * @return bool 247 | */ 248 | public function deleteDeliverTemplate($templateId) 249 | { 250 | $result = $this->wechat->httpRaw(self::WECHAT_DELIVERY_TEMPLATE_DELETE_PREFIX, [ 251 | 'template_id' => $templateId 252 | ], [ 253 | 'access_token' => $this->wechat->getAccessToken() 254 | ]); 255 | return isset($result['errmsg']) && $result['errmsg'] == 'success'; 256 | } 257 | 258 | /** 259 | * 修改邮费模板 260 | */ 261 | const WECHAT_DELIVERY_TEMPLATE_UPDATE_PREFIX = '/merchant/express/update'; 262 | /** 263 | * 修改邮费模板 264 | * @param array $data 265 | * @return bool 266 | * @throws \yii\web\HttpException 267 | */ 268 | public function updateDeliverTemplate(array $data) 269 | { 270 | $result = $this->wechat->httpRaw(self::WECHAT_DELIVERY_TEMPLATE_UPDATE_PREFIX, $data, [ 271 | 'access_token' => $this->wechat->getAccessToken() 272 | ]); 273 | return isset($result['errmsg']) && $result['errmsg'] == 'success'; 274 | } 275 | 276 | /** 277 | * 获取指定ID的邮费模板 278 | */ 279 | const WECHAT_DELIVERY_TEMPLATE_ID_GET_PREFIX = '/merchant/express/getbyid'; 280 | /** 281 | * 获取指定ID的邮费模板 282 | * @param $templateId 283 | * @return bool 284 | */ 285 | public function getDeliverTemplate($templateId) 286 | { 287 | $result = $this->wechat->httpRaw(self::WECHAT_DELIVERY_TEMPLATE_ID_GET_PREFIX, [ 288 | 'template_id' => $templateId 289 | ]); 290 | return isset($result['errmsg']) && $result['errmsg'] == 'success' ? $result['template_info'] : false; 291 | } 292 | 293 | /** 294 | * 获取所有邮费模板 295 | */ 296 | const WECHAT_DELIVERY_TEMPLATE_LIST_GET_PREFIX = '/merchant/express/getall'; 297 | /** 298 | * 获取所有邮费模板 299 | * @return bool 300 | * @throws \yii\web\HttpException 301 | */ 302 | public function getDeliverTemplateList() 303 | { 304 | $result = $this->wechat->httpGet(self::WECHAT_DELIVERY_TEMPLATE_LIST_GET_PREFIX, [ 305 | 'access_token' => $this->wechat->getAccessToken() 306 | ]); 307 | return isset($result['errmsg']) && $result['errmsg'] == 'success' ? $result['templates_info'] : false; 308 | } 309 | 310 | /** 311 | * 增加分组 312 | */ 313 | const WECHAT_GROUP_ADD_PREFIX = '/merchant/group/add'; 314 | /** 315 | * 增加分组 316 | * @param array $groupDetail 317 | * @return bool 318 | * @throws \yii\web\HttpException 319 | */ 320 | public function addGroup(array $groupDetail) 321 | { 322 | $result = $this->wechat->httpRaw(self::WECHAT_GROUP_ADD_PREFIX, [ 323 | 'group_detail' => $groupDetail 324 | ], [ 325 | 'access_token' => $this->wechat->getAccessToken() 326 | ]); 327 | return isset($result['errmsg']) && $result['errmsg'] == 'success' ? $result['group_id'] : false; 328 | } 329 | 330 | /** 331 | * 删除分组 332 | */ 333 | const WECHAT_GROUP_DELETE_PREFIX = '/merchant/group/del'; 334 | /** 335 | * 删除店铺分组 336 | * @param $groupId 337 | * @return bool 338 | * @throws \yii\web\HttpException 339 | */ 340 | public function deleteGroup($groupId) 341 | { 342 | $result = $this->wechat->httpRaw(self::WECHAT_GROUP_DELETE_PREFIX, [ 343 | 'group_id' => $groupId 344 | ], [ 345 | 'access_token' => $this->wechat->getAccessToken() 346 | ]); 347 | return isset($result['errmsg']) && $result['errmsg'] == 'success'; 348 | } 349 | 350 | /** 351 | * 修改分组属性 352 | */ 353 | const WECHAT_GROUP_UPDATE_PREFIX = '/merchant/group/propertymod'; 354 | /** 355 | * 修改分组属性 356 | * @param array $data 357 | * @return bool 358 | * @throws \yii\web\HttpException 359 | */ 360 | public function updateGroup(array $data) 361 | { 362 | $result = $this->wechat->httpRaw(self::WECHAT_GROUP_UPDATE_PREFIX, $data, [ 363 | 'access_token' => $this->wechat->getAccessToken() 364 | ]); 365 | return isset($result['errmsg']) && $result['errmsg'] == 'success'; 366 | } 367 | 368 | /** 369 | * 修改分组商品 370 | */ 371 | const WECHAT_GROUP_PRODUCT_UPDATE_PREFIX = '/merchant/group/productmod'; 372 | /** 373 | * 修改分组商品 374 | * @param array $data 375 | * @return bool 376 | * @throws \yii\web\HttpException 377 | */ 378 | public function updateGroupProduct(array $data) 379 | { 380 | $result = $this->wechat->httpRaw(self::WECHAT_GROUP_PRODUCT_UPDATE_PREFIX, $data, [ 381 | 'access_token' => $this->wechat->getAccessToken() 382 | ]); 383 | return isset($result['errmsg']) && $result['errmsg'] == 'success'; 384 | } 385 | 386 | /** 387 | * 获取所有分组 388 | */ 389 | const WECHAT_GROUP_LIST_PREFIX = '/merchant/group/getall'; 390 | /** 391 | * 获取所有分组 392 | * @return bool 393 | * @throws \yii\web\HttpException 394 | */ 395 | public function getGroupList() 396 | { 397 | $result = $this->wechat->httpGet(self::WECHAT_GROUP_LIST_PREFIX, [ 398 | 'access_token' => $this->wechat->getAccessToken() 399 | ]); 400 | return isset($result['errmsg']) && $result['errmsg'] == 'success' ? $result['groups_detail'] : false; 401 | } 402 | 403 | /** 404 | * 根据分组ID获取分组信息 405 | */ 406 | const WECHAT_GROUP_ID_GET_PREFIX = '/merchant/group/getbyid'; 407 | /** 408 | * 根据分组ID获取分组信息 409 | * @param $groupId 410 | * @return bool 411 | * @throws \yii\web\HttpException 412 | */ 413 | public function getGroup($groupId) 414 | { 415 | $result = $this->wechat->httpRaw(self::WECHAT_GROUP_ID_GET_PREFIX, [ 416 | 'group_id' => $groupId 417 | ], [ 418 | 'access_token' => $this->wechat->getAccessToken() 419 | ]); 420 | return isset($result['errmsg']) && $result['errmsg'] == 'success' ? $result['groups_detail'] : false; 421 | } 422 | 423 | /** 424 | * 增加货架 425 | */ 426 | const WECHAT_SHELF_ADD_PREFIX = '/merchant/shelf/add'; 427 | /** 428 | * 增加货架 429 | * @param array $data 430 | * @return bool 431 | * @throws \yii\web\HttpException 432 | */ 433 | public function addShelf(array $data) 434 | { 435 | $result = $this->wechat->httpRaw(self::WECHAT_SHELF_ADD_PREFIX, $data, [ 436 | 'access_token' => $this->wechat->getAccessToken() 437 | ]); 438 | return isset($result['errmsg']) && $result['errmsg'] == 'success' ? $result['shelf_id'] : false; 439 | } 440 | 441 | /** 442 | * 删除货架 443 | */ 444 | const WECHAT_SHELF_DELETE_PREFIX = '/merchant/shelf/del'; 445 | /** 446 | * 删除货架 447 | * @param $shelfId 448 | * @return bool 449 | */ 450 | public function deleteShelf($shelfId) 451 | { 452 | $result = $this->wechat->httpRaw(self::WECHAT_SHELF_DELETE_PREFIX, [ 453 | 'shelf_id' => $shelfId 454 | ], [ 455 | 'access_token' => $this->wechat->getAccessToken() 456 | ]); 457 | return isset($result['errmsg']) && $result['errmsg'] == 'success'; 458 | } 459 | 460 | /** 461 | * 修改货架 462 | */ 463 | const WECHAT_SHELF_UPDATE_PREFIX = '/merchant/shelf/mod'; 464 | /** 465 | * 修改货架 466 | * @param array $data 467 | * @return bool 468 | * @throws \yii\web\HttpException 469 | */ 470 | public function updateShelf(array $data) 471 | { 472 | $result = $this->wechat->httpRaw(self::WECHAT_SHELF_UPDATE_PREFIX, $data, [ 473 | 'access_token' => $this->wechat->getAccessToken() 474 | ]); 475 | return isset($result['errmsg']) && $result['errmsg'] == 'success'; 476 | } 477 | 478 | /** 479 | * 获取所有货架 480 | */ 481 | const WECHAT_SHELF_LIST_PREFIX = '/merchant/shelf/getall'; 482 | /** 483 | * 获取所有货架 484 | * @return bool 485 | * @throws \yii\web\HttpException 486 | */ 487 | public function getShelfList() 488 | { 489 | $result = $this->wechat->httpGet(self::WECHAT_SHELF_LIST_PREFIX, [ 490 | 'access_token' => $this->wechat->getAccessToken() 491 | ]); 492 | return isset($result['errmsg']) && $result['errmsg'] == 'success' ? $result['shelves'] : false; 493 | } 494 | 495 | /** 496 | * 根据货架ID获取货架信息 497 | */ 498 | const WECHAT_SHELF_ID_GET_PREFIX = '/merchant/shelf/getbyid'; 499 | /** 500 | * 根据货架ID获取货架信息 501 | * @param $shelfId 502 | * @return array|bool 503 | */ 504 | public function getShelf($shelfId) 505 | { 506 | $result = $this->wechat->httpRaw(self::WECHAT_SHELF_ID_GET_PREFIX, [ 507 | 'shelf_id' => $shelfId 508 | ], [ 509 | 'access_token' => $this->wechat->getAccessToken() 510 | ]); 511 | return isset($result['errmsg']) && $result['errmsg'] == 'success' ? $result['shelf_info'] : false; 512 | } 513 | 514 | /** 515 | * 根据订单ID获取订单详情 516 | */ 517 | const WECHAT_ORDER_GET_PREFIX = '/merchant/order/getbyid'; 518 | /** 519 | * 根据订单ID获取订单详情 520 | * @param $orderId 521 | * @return bool 522 | * @throws HttpException 523 | */ 524 | public function getOrder($orderId) 525 | { 526 | $result = $this->wechat->httpRaw(self::WECHAT_ORDER_GET_PREFIX, [ 527 | 'order_id' => $orderId 528 | ], [ 529 | 'access_token' => $this->wechat->getAccessToken() 530 | ]); 531 | return isset($result['errmsg']) && $result['errmsg'] == 'success' ? $result['order'] : false; 532 | } 533 | 534 | /** 535 | * 根据订单状态/创建时间获取订单详情 536 | */ 537 | const WECHAT_ORDER_FILTER_GET_PREFIX = '/merchant/order/getbyfilter'; 538 | /** 539 | * 根据订单状态/创建时间获取订单详情 540 | * @param array $data 541 | * @return bool 542 | */ 543 | public function getOrderByFilter(array $data) 544 | { 545 | $result = $this->wechat->httpRaw(self::WECHAT_ORDER_FILTER_GET_PREFIX, $data, [ 546 | 'access_token' => $this->wechat->getAccessToken() 547 | ]); 548 | return isset($result['errmsg']) && $result['errmsg'] == 'success' ? $result['order_list'] : false; 549 | } 550 | 551 | /** 552 | * 设置订单发货信息 553 | */ 554 | const WECHAT_ORDER_DELIVERY_SET_PREFIX = '/merchant/order/setdelivery'; 555 | /** 556 | * 设置订单发货信息 557 | * 注: 物流公司ID 558 | * 邮政EMS Fsearch_code 559 | * 申通快递 002shentong 560 | * 中通速递 066zhongtong 561 | * 圆通速递 056yuantong 562 | * 天天快递 042tiantian 563 | * 顺丰速运 003shunfeng 564 | * 韵达快运 059Yunda 565 | * 宅急送 064zhaijisong 566 | * 汇通快运 020huitong 567 | * 易迅快递 zj001yixun 568 | * @param array $data 569 | * @return bool 570 | * @throws \yii\web\HttpException 571 | */ 572 | public function setOrderDelivery(array $data) 573 | { 574 | $result = $this->wechat->httpRaw(self::WECHAT_ORDER_DELIVERY_SET_PREFIX, $data, [ 575 | 'access_token' => $this->wechat->getAccessToken() 576 | ]); 577 | return isset($result['errmsg']) && $result['errmsg'] == 'success' ? $result['order_list'] : false; 578 | } 579 | 580 | /** 581 | * 关闭订单 582 | */ 583 | const WECHAT_ORDER_CLOSE_PREFIX = '/merchant/order/close'; 584 | /** 585 | * 关闭订单 586 | * @param $orderId 587 | * @return bool 588 | * @throws \yii\web\HttpException 589 | */ 590 | public function closeOrder($orderId) 591 | { 592 | $result = $this->wechat->httpRaw(self::WECHAT_ORDER_CLOSE_PREFIX, [ 593 | 'order_id' => $orderId, 594 | ], [ 595 | 'access_token' => $this->wechat->getAccessToken() 596 | ]); 597 | return isset($result['errmsg']) && $result['errmsg'] == 'success'; 598 | } 599 | 600 | /** 601 | * 上传图片(小店接口) 602 | */ 603 | const WECHAT_IMAGE_UPLOAD_PREFIX = '/merchant/common/upload_img'; 604 | /** 605 | * 上传图片(小店接口) 606 | * @param $filePath 文件完整路径 607 | * @param null $fileName 文件名 如不填写.则使用文件路径里的名称 608 | * @return bool 609 | */ 610 | public function uploadImage($filePath, $fileName = null) 611 | { 612 | $fileName === null && $fileName = pathinfo($filePath, PATHINFO_BASENAME); 613 | $result = $this->wechat->httpRaw(self::WECHAT_IMAGE_UPLOAD_PREFIX, [ 614 | 'media' => $this->wechat->uploadFile($filePath) 615 | ], [ 616 | 'access_token' => $this->wechat->getAccessToken(), 617 | 'filename' => $fileName 618 | ]); 619 | return isset($result['errmsg']) && $result['errmsg'] == 'success' ? $result['image_url'] : false; 620 | } 621 | 622 | } -------------------------------------------------------------------------------- /mp/ShakeAround.php: -------------------------------------------------------------------------------- 1 | wechat->httpRaw(self::WECHAT_DEVICE_APPLY_ID_PREFIX, $data, [ 25 | 'access_token' => $this->wechat->getAccessToken() 26 | ]); 27 | return isset($result['errcode']) && !$result['errcode'] ? $result['data'] : false; 28 | } 29 | 30 | /** 31 | * 编辑设备信息 32 | */ 33 | const WECHAT_DEVICE_UPDATE_PREFIX = '/shakearound/device/update'; 34 | /** 35 | * 编辑设备信息 36 | * @param array $data 37 | * @return bool 38 | * @throws \yii\web\HttpException 39 | */ 40 | public function updateDevice(array $data) 41 | { 42 | $result = $this->wechat->httpRaw(self::WECHAT_DEVICE_UPDATE_PREFIX, $data, [ 43 | 'access_token' => $this->wechat->getAccessToken() 44 | ]); 45 | return isset($result['errcode']) && !$result['errcode'] ? $result['data'] : false; 46 | } 47 | 48 | /** 49 | * 配置设备与门店的关联关系 50 | */ 51 | const WECHAT_DEVICE_LOCATION_BIND_PREFIX = '/shakearound/device/bindlocation'; 52 | /** 53 | * 配置设备与门店的关联关系 54 | * @param array $data 55 | * @return bool 56 | * @throws \yii\web\HttpException 57 | */ 58 | public function deviceBindLocation(array $data) 59 | { 60 | $result = $this->wechat->httpRaw(self::WECHAT_DEVICE_LOCATION_BIND_PREFIX, $data, [ 61 | 'access_token' => $this->wechat->getAccessToken() 62 | ]); 63 | return isset($result['errcode']) && !$result['errcode'] ? $result['data'] : false; 64 | } 65 | 66 | /** 67 | * 查询设备列表 68 | */ 69 | const WECHAT_DEVICE_SEARCH_PREFIX = '/shakearound/device/search'; 70 | /** 71 | * 查询设备列表 72 | * @param array $data 73 | * @return bool 74 | * @throws \yii\web\HttpException 75 | */ 76 | public function searchDevice(array $data) 77 | { 78 | $result = $this->wechat->httpRaw(self::WECHAT_DEVICE_SEARCH_PREFIX, $data, [ 79 | 'access_token' => $this->wechat->getAccessToken() 80 | ]); 81 | return isset($result['errcode']) && !$result['errcode'] ? $result['data'] : false; 82 | } 83 | 84 | /** 85 | * 新增页面 86 | */ 87 | const WECHAT_PAGE_ADD_PREFIX = '/shakearound/page/add'; 88 | /** 89 | * 新增页面 90 | * @param array $data 91 | * @return bool 92 | * @throws \yii\web\HttpException 93 | */ 94 | public function addPage(array $data) 95 | { 96 | $result = $this->wechat->httpRaw(self::WECHAT_PAGE_ADD_PREFIX, $data, [ 97 | 'access_token' => $this->wechat->getAccessToken() 98 | ]); 99 | return isset($result['errcode']) && !$result['errcode'] ? $result['data'] : false; 100 | } 101 | 102 | /** 103 | * 编辑页面信息 104 | */ 105 | const WECHAT_UPDATE_PREFIX= '/shakearound/page/update'; 106 | /** 107 | * 编辑页面信息 108 | * @param array $data 109 | * @return bool 110 | * @throws \yii\web\HttpException 111 | */ 112 | public function updatePage(array $data) 113 | { 114 | $result = $this->wechat->httpRaw(self::WECHAT_UPDATE_PREFIX, $data, [ 115 | 'access_token' => $this->wechat->getAccessToken() 116 | ]); 117 | return isset($result['errcode']) && !$result['errcode'] ? $result['data'] : false; 118 | } 119 | 120 | /** 121 | * 查询页面列表 122 | */ 123 | const WECHAT_PAGE_SEARCH_PREFIX = '/shakearound/page/search'; 124 | /** 125 | * 查询页面列表 126 | * @param array $data 127 | * @return bool 128 | * @throws \yii\web\HttpException 129 | */ 130 | public function searchPage(array $data) 131 | { 132 | $result = $this->wechat->httpRaw(self::WECHAT_PAGE_SEARCH_PREFIX, $data, [ 133 | 'access_token' => $this->wechat->getAccessToken() 134 | ]); 135 | return isset($result['errcode']) && !$result['errcode'] ? $result['data'] : false; 136 | } 137 | 138 | /** 139 | * 删除页面 140 | */ 141 | const WECHAT_PAGE_DELETE_PREFIX = '/shakearound/page/delete'; 142 | /** 143 | * 删除页面 144 | * @param array $data 145 | * @return bool 146 | * @throws \yii\web\HttpException 147 | */ 148 | public function deletePage(array $data) 149 | { 150 | $result = $this->wechat->httpRaw(self::WECHAT_PAGE_DELETE_PREFIX, $data, [ 151 | 'access_token' => $this->wechat->getAccessToken() 152 | ]); 153 | return isset($result['errcode']) && !$result['errcode'] ? $result['data'] : false; 154 | } 155 | 156 | /** 157 | * 上传图片素材 158 | */ 159 | const WECHAT_MATERIAL_ADD_PREFIX = '/shakearound/material/add'; 160 | /** 161 | * 上传图片素材 162 | * @param $mediaPath 163 | * @return bool 164 | * @throws \yii\web\HttpException 165 | */ 166 | public function addMaterial($mediaPath) 167 | { 168 | $result = $this->wechat->httpPost(self::WECHAT_MATERIAL_ADD_PREFIX, [ 169 | 'media' => $this->wechat->uploadFile($mediaPath) 170 | ], [ 171 | 'access_token' => $this->getAccessToken() 172 | ]); 173 | return isset($result['errcode']) && !$result['errcode'] ? $result['data'] : false; 174 | } 175 | 176 | /** 177 | * 配置设备与页面的关联关系 178 | */ 179 | const WECHAT_DEVICE_PAGE_BIND_PREFIX = '/shakearound/device/bindpage'; 180 | /** 181 | * 配置设备与页面的关联关系 182 | * 配置设备与页面的关联关系 183 | * @return bool 184 | * @throws \yii\web\HttpException 185 | */ 186 | public function devicePageBind(array $data) 187 | { 188 | $result = $this->wechat->httpPost(self::WECHAT_DEVICE_PAGE_BIND_PREFIX, $data, [ 189 | 'access_token' => $this->wechat->getAccessToken() 190 | ]); 191 | return isset($result['errcode']) && !$result['errcode'] ? $result['data'] : false; 192 | } 193 | 194 | /** 195 | * 获取摇周边的设备及用户信息 196 | */ 197 | const WECHAT_USER_SHAKE_INFO_GET_PREFIX = '/shakearound/user/getshakeinfo'; 198 | /** 199 | * 获取摇周边的设备及用户信息 200 | * @param array $data 201 | * @return bool 202 | * @throws \yii\web\HttpException 203 | */ 204 | public function getUserShakeInfo(array $data) 205 | { 206 | $result = $this->wechat->httpPost(self::WECHAT_USER_SHAKE_INFO_GET_PREFIX, $data, [ 207 | 'access_token' => $this->wechat->getAccessToken() 208 | ]); 209 | return isset($result['errcode']) && !$result['errcode'] ? $result['data'] : false; 210 | } 211 | 212 | /** 213 | * 以设备为维度的数据统计接口 214 | */ 215 | const WECHAT_DEVICE_STATISTICS_PREFIX = '/shakearound/statistics/device'; 216 | /** 217 | * 以设备为维度的数据统计接口 218 | * @param array $data 219 | * @return bool 220 | * @throws \yii\web\HttpException 221 | */ 222 | public function deviceStatistics(array $data) 223 | { 224 | $result = $this->wechat->httpPost(self::WECHAT_DEVICE_STATISTICS_PREFIX, $data, [ 225 | 'access_token' => $this->wechat->getAccessToken() 226 | ]); 227 | return isset($result['errcode']) && !$result['errcode'] ? $result['data'] : false; 228 | } 229 | 230 | /** 231 | * 以页面为维度的数据统计接口 232 | */ 233 | const WECHAT_PAGE_STATISTICS_PREFIX = '/shakearound/statistics/page'; 234 | /** 235 | * 以页面为维度的数据统计接口 236 | * @param array $data 237 | * @return bool 238 | * @throws \yii\web\HttpException 239 | */ 240 | public function pageStatistics(array $data) 241 | { 242 | $result = $this->wechat->httpPost(self::WECHAT_PAGE_STATISTICS_PREFIX, $data, [ 243 | 'access_token' => $this->wechat->getAccessToken() 244 | ]); 245 | return isset($result['errcode']) && !$result['errcode'] ? $result['data'] : false; 246 | } 247 | } --------------------------------------------------------------------------------