crypt = new WxBizMsgCrypt(self::TOKEN, self::KEY, self::APPID); } /** * @notes:保存Ticket * @param string $xml * @return mixed|string * @author: wanghousheng */ public function getVerifyTicket(string $xml) { $ticket = ''; $xmlData = $this->crypt->fromXml($xml); if (!empty($xmlData['Encrypt'])) { //解密 $encryptXml = $this->crypt->decryptMsg($xmlData['Encrypt']); $data = $this->crypt->fromXml($encryptXml); if (!empty($data['ComponentVerifyTicket'])) { $ticket = $data['ComponentVerifyTicket']; Cache::set('component_verify_ticket', $ticket); } } return $ticket; } /** * @notes:获取令牌 * @return mixed|string * @author: wanghousheng */ public function getComponentAccessToken() { if (Cache::has('ComponentAccessToken')) { return Cache::get('ComponentAccessToken'); } $url = 'https://api.weixin.qq.com/cgi-bin/component/api_component_token'; $ticket = Cache::get('component_verify_ticket'); if (!empty($ticket)) { $data = []; $data['component_appid'] = self::APPID; $data['component_appsecret'] = self::SECRET; $data['component_verify_ticket'] = $ticket; $result = $this->curlPost($url, json_encode($data), 10); $result = json_decode($result, true); if (!empty($result['component_access_token'])) { Cache::set('ComponentAccessToken', $result['component_access_token'], 6200); return $result['component_access_token']; } } return ''; } /** * @notes:生成H5授权链接 * @param string $redirect_uri //授权后重定向的回调链接地址 * @param string $biz_appid //业务公众号appid * @return string * @author: wanghousheng */ public function jumpH5Url(string $redirect_uri, string $biz_appid = ''): string { $url = ''; $auth_code = $this->getPreAuthCode(); if ($auth_code) { $url = "'https://open.weixin.qq.com/wxaopen/safe/bindcomponent?action=bindcomponent&no_scan=1"; $url .= "&component_appid=" . self::APPID . '&pre_auth_code=' . $auth_code . '&redirect_uri=' . $redirect_uri; $url .= '&auth_type=3&biz_appid=' . $biz_appid . '#wechat_redirect'; } return $url; } /** * @notes:获取预授权码 * @return false|mixed * @author: wanghousheng */ public function getPreAuthCode() { $token = $this->getComponentAccessToken(); if ($token) { $url = 'https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=' . $token; $data['component_appid'] = self::APPID; $result = $this->curlPost($url, json_encode($data)); $result = json_decode($result, true); if ($result && !empty($result['pre_auth_code'])) { return $result['pre_auth_code']; } } return false; } /** * @notes:发布版本 * @param $appid * @param $template_id * @return true|void * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException|BaseException * @author: wanghousheng */ public function commit($appid, $template_id) { $version = ''; $desc = ''; $model = new WxserverAccount(); $info = $model->where(['appid' => $appid])->find(); if (!empty($info)) { $info = $info->toArray(); $access_token = $this->authorizerAccessToken($appid, $info['refresh_token']); //获取模板 $templatelist = $this->getTemplatelist(); if ($templatelist) { foreach ($templatelist as $value) { if (!empty($value['user_version']) && !empty($value['user_desc']) && $value['template_id'] == $template_id) { $version = $value['user_version']; $desc = $value['user_desc']; break; } } } if ($version == '' || $desc == '') { throwError('模板不存在'); } $data['template_id'] = $template_id; $data['user_version'] = $version; $data['user_desc'] = $desc; $ext_json['extAppid'] = $appid; $ext_json['ext']['store_id'] = $info['store_id']; $ext_json['window'] = []; $data['ext_json'] = json_encode($ext_json); $url = 'https://api.weixin.qq.com/wxa/commit?access_token=' . $access_token; $result = $this->curlPost($url, json_encode($data)); $result = json_decode($result, true); if ($result && !empty($result['errmsg']) && $result['errmsg'] == 'ok') { $model->update(['version' => $version . $desc], ['id' => $info['id']]); return true; } } } /** * @notes:获取/刷新接口调用令牌 * @param $appid * @param $refresh_token * @return false|mixed * @author: wanghousheng */ public function authorizerAccessToken($appid, $refresh_token) { if (Cache::has($appid . '_authorizer_access_token')) { return Cache::get($appid . '_authorizer_access_token'); } $token = $this->getComponentAccessToken(); if ($token) { $url = 'https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token=' . $token; $data['component_appid'] = self::APPID; $data['authorizer_appid'] = $appid; $data['authorizer_refresh_token'] = $refresh_token; $result = $this->curlPost($url, json_encode($data)); $result = json_decode($result, true); if ($result && !empty($result['authorizer_access_token'])) { Cache::set($appid . '_authorizer_access_token', $result['authorizer_access_token'], 6200); return $result['authorizer_access_token']; } } return false; } private function getAuditStatusText($status): string { $status = intval($status); switch ($status) { case 0: $text = '未提交审核'; break; case 1: $text = '审核中'; break; case 2: $text = '审核驳回'; break; case 3: $text = '审核通过'; break; case 4: $text = '提审中'; break; case 5: $text = '提审失败'; break; default: $text = '未知'; break; } return $text; } /** * @notes:获取草稿箱列表 * @return array|mixed * @author: wanghousheng */ public function getTemplatedraftlist() { if (Cache::has('templatedraftlist')) { return Cache::get('templatedraftlist'); } $token = $this->getComponentAccessToken(); $list = []; if ($token) { $url = 'https://api.weixin.qq.com/wxa/gettemplatedraftlist?access_token=' . $token; $result = $this->curlGet($url); $result = json_decode($result, true); if ($result && !empty($result['draft_list'])) { $draft_list = $result['draft_list']; foreach ($draft_list as $value) { $list[] = [ 'create_time' => date('Y-m-d H:i:s', $value['create_time']), 'user_version' => $value['user_version'], 'user_desc' => $value['user_desc'], 'id' => $value['draft_id'], ]; } Cache::set('templatelist', $list, 86400); } } return $list; } /** * @notes:添加草稿箱到模板中 * @param $draft_id * @return bool * @author: wanghousheng */ public function addTotemplate($draft_id): bool { $templateList = $this->getTemplatelist(); if ($templateList) { $draft_ids = array_column($templateList, 'draft_id'); if (in_array($draft_id, $draft_ids)) { return true; } } $token = $this->getComponentAccessToken(); if ($token) { $url = 'https://api.weixin.qq.com/wxa/addtotemplate?access_token=' . $token; $data['draft_id'] = $draft_id; $data['template_type'] = 1; $res = $this->curlPost($url, json_encode($data)); $res = json_decode($res, true); if ($res && !empty($res['errmsg']) && $res['errmsg'] == 'ok') { Cache::delete('templatelist'); return true; } } return false; } /** * @notes:删除模板 * @param $template_id * @return bool * @author: wanghousheng */ public function deleTetemplate($template_id): bool { $token = $this->getComponentAccessToken(); if ($token) { $url = 'https://api.weixin.qq.com/wxa/deletetemplate?access_token=' . $token; $data['template_id'] = $template_id; $res = $this->curlPost($url, json_encode($data)); $res = json_decode($res, true); if ($res && !empty($res['errmsg']) && $res['errmsg'] == 'ok') { Cache::delete('templatelist'); return true; } } return false; } /** * @notes:代码模板列表 * @return array * @author: wanghousheng */ public function getTemplatelist(): array { if (Cache::has('templatelist')) { return Cache::get('templatelist'); } $token = $this->getComponentAccessToken(); $list = []; if ($token) { $url = 'https://api.weixin.qq.com/wxa/gettemplatelist?access_token=' . $token; $data['template_type'] = 1; $result = $this->curlGet($url, $data); $result = json_decode($result, true); if ($result && !empty($result['template_list'])) { $template_list = $result['template_list']; foreach ($template_list as $value) { $list[] = [ 'create_time' => date('Y-m-d H:i:s', $value['create_time']), 'user_version' => $value['user_version'], 'user_desc' => $value['user_desc'], 'template_id' => $value['template_id'], 'audit_status' => $value['audit_status'], 'audit_status_text' => $this->getAuditStatusText($value['audit_status']), 'reason' => $value['reason'], 'draft_id' => $value['draft_id'], ]; } Cache::set('templatelist', $list, 86400); } } return $list; } /** * @notes:获取授权信息 * @param $authorization_code * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException * @author: wanghousheng */ public function authorizationInfo($authorization_code) { $url = 'https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=' . $this->getComponentAccessToken(); $data = []; $data['component_appid'] = self::APPID; $data['authorization_code'] = $authorization_code; $result = $this->curlPost($url, json_encode($data)); $result = json_decode($result, true); if ($result && !empty($result['authorization_info']) && !empty($result['authorization_info']['authorizer_appid'])) { $url = 'https://api.weixin.qq.com/cgi-bin/component/api_get_authorizer_info?component_access_token=' . $this->getComponentAccessToken(); $data = []; $data['component_appid'] = self::APPID; $data['authorizer_appid'] = $result['authorization_info']['authorizer_appid']; $res = $this->curlPost($url, json_encode($data)); $res = json_decode($res, true); if ($res && !empty($res['authorizer_info']) && !empty($res['authorization_info'])) { $authorizer_info = $res['authorizer_info']; $authorization_info = $res['authorization_info']; $insert_data['appid'] = $authorization_info['authorizer_appid']; $model = new WxserverAccount(); $account_info = $model->where(['appid' => $insert_data['appid']])->find(); if (!empty($account_info)) { return; } $insert_data['access_token'] = $result['authorization_info']['authorizer_access_token']; $insert_data['refresh_token'] = $authorization_info['authorizer_refresh_token']; $insert_data['nick_name'] = $authorizer_info['nick_name']; $insert_data['head_image'] = $authorizer_info['head_img']; $insert_data['user_name'] = $authorizer_info['user_name']; $insert_data['qrcode_image'] = $authorizer_info['qrcode_url']; $insert_data['principal_name'] = $authorizer_info['principal_name']; $insert_data['signature'] = $authorizer_info['signature']; $insert_data['store_id'] = $this->getStoreId($authorization_info['authorizer_appid']); $insert_data['create_time'] = time(); $insert_data['update_time'] = time(); $model->insertGetId($insert_data); } } } /** * @notes:获取店铺ID * @param $appid * @return int|mixed * @throws DataNotFoundException * @throws DbException * @throws ModelNotFoundException * @author: wanghousheng */ public function getStoreId($appid) { $list = Db::table('yoshop_wxapp_setting')->where(['key' => 'basic'])->select(); if (!$list->isEmpty()) { $list = $list->toArray(); foreach ($list as $value) { if ($value['values']) { $item = json_decode($value['values'], true); if (!empty($item['app_id']) && $item['app_id'] == $appid) { return $value['store_id']; } } } } return 0; } private function curlPost($url, $post_data, $timeout = 5) { $ch = curl_init(); if (stripos($url, 'https://') !== false) { curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSLVERSION, 1); } if (is_string($post_data)) { $strPOST = $post_data; } else { $aPOST = array(); foreach ($post_data as $key => $val) { $aPOST[] = $key . '=' . urlencode($val); } $strPOST = join('&', $aPOST); } curl_setopt($ch, CURLOPT_HTTP_VERSION, 1); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $strPOST); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); $result = curl_exec($ch); $aStatus = curl_getinfo($ch); curl_close($ch); if (intval($aStatus['http_code']) == 200) { return $result; } else { return false; } } protected function curlGet(string $url, array $data = []) { if (!empty($data)) { $url = $url . '?' . http_build_query($data); } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); $result = curl_exec($ch); curl_close($ch); return $result; } }