diff --git a/app/admin/controller/Wxwholesaler.php b/app/admin/controller/Wxwholesaler.php new file mode 100644 index 00000000..9d74136b --- /dev/null +++ b/app/admin/controller/Wxwholesaler.php @@ -0,0 +1,244 @@ +request->domain(true) . '/api/wxserver/redirect'; + $jumUrl = $obj->jumpH5Url($url); + $savePath = root_path() . "public/wxserve"; + !is_dir($savePath) && mkdir($savePath, 0755, true); + $savePath .= '/auth_qrcode.png'; + QRcode::png($jumUrl, $savePath, 'L', 8, 1); + return $this->renderSuccess(['img_url' => $this->request->domain(true) . '/wxserve/auth_qrcode.png?time=' . time()]); + } + + /** + * @notes:授权列表 + * @return Json + * @throws DbException + * @author: wanghousheng + */ + public function authList(): Json + { + $store_ids = []; + $where = []; + $store_id = intval($this->request->get('store_id')); + if ($store_id) { + $where[] = ['store_id', '=', $store_id]; + } + $nick_name = $this->request->get('nick_name'); + if ($nick_name) { + $where[] = ['nick_name', 'like', "%$nick_name%"]; + } + $appid = $this->request->get('appid'); + if ($appid) { + $where[] = ['nick_name', '=', "%$appid%"]; + } + $result = Db::table('yoshop_wxwholesaler_account') + ->where($where) + ->paginate(15); + $list = $result->items(); + $total = $result->total(); + if ($total) { + foreach ($list as &$item) { + $store_ids[] = $item['store_id']; + $item['create_time'] = date('Y-m-d H:i:s', $item['create_time']); + if ($item['exp_info']) { + $item['exp_info'] = json_decode($item['exp_info'], true); + if (!empty($item['exp_info']['exp_time'])) { + $item['exp_info']['exp_time'] = date('Y-m-d H:i:s', $item['exp_info']['exp_time']); + } + } else { + $item['exp_info']['exp_time'] = '无'; + $item['exp_info']['exp_version'] = '无'; + } + if ($item['release_info']) { + $item['release_info'] = json_decode($item['release_info'], true); + if (!empty($item['release_info']['release_time'])) { + $item['release_info']['release_time'] = date('Y-m-d H:i:s', $item['release_info']['release_time']); + } + } else { + $item['release_info']['release_time'] = '无'; + $item['release_info']['release_version'] = '无'; + } + if (!empty($item['experience_code'])) { + $item['experience_code'] = $this->request->domain(true) . $item['experience_code'] . '?time=' . time(); + } + if ($item['audit_status'] == 0) { + $item['audit_status_text'] = '--'; + } elseif ($item['audit_status'] == 1) { + $item['audit_status_text'] = '审核中'; + } elseif ($item['audit_status'] == 2) { + $item['audit_status_text'] = '审核通过'; + } elseif ($item['audit_status'] == 3) { + $item['audit_status_text'] = '审核失败'; + } elseif ($item['audit_status'] == 4) { + $item['audit_status_text'] = '延时审核'; + } + unset($item['access_token']); + unset($item['refresh_token']); + unset($item['signature']); + } + $store_list = Db::table('yoshop_store') + ->whereIn('store_id', $store_ids) + ->column('store_name', 'store_id'); + foreach ($list as &$item) { + $item['store_name'] = $store_list[$item['store_id']] ?? ''; + } + } + return $this->renderSuccess(['list' => $list, 'total' => $total]); + } + + /** + * @notes:草稿箱列表 + * @return Json + * @author: wanghousheng + */ + public function templatedraftlist(): Json + { + $type = intval($this->request->get('type', 0)); + $obj = new Wholesaler(); + $list = $obj->getTemplateDraftList($type); + return $this->renderSuccess($list); + } + + + /** + * @notes:添加草稿到模板中 + * @return Json + * @author: wanghousheng + */ + public function addTotemplate(): Json + { + $draft_id = $this->request->get('draft_id'); + if ($draft_id) { + $obj = new Wholesaler(); + $res = $obj->addTotemplate($draft_id); + if ($res) { + return $this->renderSuccess('success'); + } + } + return $this->renderError('操作失败'); + } + + /** + * @notes:获取模板列表 + * @return Json + * @author: wanghousheng + */ + public function templatelist(): Json + { + $type = intval($this->request->get('type', 0)); + $obj = new Wholesaler(); + $list = $obj->getTemplatelist($type); + return $this->renderSuccess($list); + } + + /** + * @notes:删除模板 + * @return Json + * @author: wanghousheng + */ + public function delTemplatelist(): Json + { + $template_id = $this->request->get('template_id'); + if ($template_id) { + $obj = new Wholesaler(); + $res = $obj->deleTetemplate($template_id); + if ($res) { + return $this->renderSuccess('success'); + } + } + return $this->renderError('操作失败'); + } + + /** + * @notes:提交体验版 + * @return Json + * @author: wanghousheng + */ + public function commit(): Json + { + $appid = $this->request->get('appid'); + $template_id = $this->request->get('template_id'); + $appids = explode(',', $appid); + if ($appids && $template_id) { + foreach ($appids as $item) { + WxserverJob::dispatch(['appid' => $item, 'template_id' => $template_id]); + } + return $this->renderSuccess('success'); + } + return $this->renderError('操作失败'); + } + + /** + * @notes:获取版本信息 + * @return Json + * @author: wanghousheng + */ + public function getVersion(): Json + { + $appid = $this->request->get('appid'); + if ($appid) { + $obj = new Wholesaler(); + if ($obj->getVersioninfo($appid)) { + return $this->renderSuccess('success'); + } + } + return $this->renderError('操作失败'); + } + + /** + * @notes:提交正式版审核 + * @return Json + * @author: wanghousheng + */ + public function audit(): Json + { + $appid = $this->request->get('appid'); + $appids = explode(',', $appid); + if ($appids) { + foreach ($appids as $item) { + WxserverJob::dispatch(['appid' => $item]); + } + return $this->renderSuccess('success'); + } + return $this->renderError('操作失败'); + } + + /** + * @notes:发布正式版前检查 + * @return Json + * @author: wanghousheng + */ + public function auditBeforeCheck(): Json + { + $msg = '操作失败'; + $appid = $this->request->get('appid'); + if ($appid) { + $obj = new Wholesaler(); + $msg = $obj->privacyInfo($appid); + if ($msg == 'ok') { + return $this->renderSuccess('success'); + } + } + return $this->renderError($msg); + } +} \ No newline at end of file diff --git a/app/api/controller/Wxwholesaler.php b/app/api/controller/Wxwholesaler.php new file mode 100644 index 00000000..a07630be --- /dev/null +++ b/app/api/controller/Wxwholesaler.php @@ -0,0 +1,100 @@ +getVerifyTicket($xmlData); + echo 'success'; + } + + /** + * @notes:授权回调 + * @throws DataNotFoundException + * @throws DbException + * @throws ModelNotFoundException + * @author: wanghousheng + */ + public function redirect() + { + $authorization_code = $this->request->get('auth_code'); + if ($authorization_code) { + $obj = new \app\common\library\wxserver\Wholesaler(); + $obj->authorizationInfo($authorization_code, $this->request->domain(true)); + } + echo 'success'; + } + + public function callback($appid) + { + $obj = new \app\common\library\wxserver\Wholesaler(); + $signature = $this->request->get('signature'); + $timestamp = $this->request->get('timestamp'); + $nonce = $this->request->get('nonce'); + if ($signature && $timestamp && $nonce) { + if ($obj->checkSignature($signature, $timestamp, $nonce)) { + $xmlData = file_get_contents("php://input"); + if ($xmlData) { + $data = $obj->decryptXml($xmlData); + if (!empty($data['MsgType'])) { + if ($data['MsgType'] == 'event' && !empty($data['Event'])) { + $up = []; + if ($data['Event'] == 'weapp_audit_success') { + $up['audit_status'] = 2; + $obj->release($appid);//审核通过发布版本 + } elseif ($data['Event'] == 'weapp_audit_fail') { + $up['audit_status'] = 3; + } elseif ($data['Event'] == 'weapp_audit_delay') { + $up['audit_status'] = 4; + } + if (!empty($data['Reason'])) { + $up['audit_reason'] = $data['Reason']; + } + if ($up && $appid) { + $model = new WxwholesalerAccount(); + $model->update($up, ['appid' => $appid]); + } + echo 'success'; + } elseif ($data['MsgType'] == 'text' && !empty($data['Content'])) { + if ($data['Content'] == 'TESTCOMPONENT_MSG_TYPE_TEXT') { + $data['Content'] = 'TESTCOMPONENT_MSG_TYPE_TEXT_callback'; + } elseif (strpos($data['Content'], 'QUERY_AUTH_CODE:') !== false) { + $query_auth_code = trim(str_replace("QUERY_AUTH_CODE:", "", $data['Content'])); + $obj->apiText($query_auth_code, $data['FromUserName']); + } + echo $this->responseText($data); + } + } + } + } + } + } + + private function responseText($data): string + { + $template = " + + + %s + + + "; + $fromUser = $data['ToUserName']; + $toUser = $data['FromUserName']; + $content = !empty($data['Content']) ? $data['Content'] : 'success'; + $time = time(); + $msgType = 'text'; + return sprintf($template, $toUser, $fromUser, $time, $msgType, $content); + } +} \ No newline at end of file diff --git a/app/common/library/wxserver/Wholesaler.php b/app/common/library/wxserver/Wholesaler.php index 9c4c4329..eecdf4d6 100644 --- a/app/common/library/wxserver/Wholesaler.php +++ b/app/common/library/wxserver/Wholesaler.php @@ -1,8 +1,835 @@ crypt = new WxBizMsgCrypt(self::TOKEN, self::KEY, self::APPID); + } + + public function checkSignature($signature, $timestamp, $nonce): bool + { + $token = self::TOKEN; + $tmpArr = array($token, $timestamp, $nonce); + sort($tmpArr, SORT_STRING); + $tmpStr = implode($tmpArr); + $tmpStr = sha1($tmpStr); + + if ($tmpStr == $signature) { + return true; + } else { + return false; + } + } + + /** + * @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']; + } + } + return $ticket; + } + + public function decryptXml($xml) + { + $data = []; + $xmlData = $this->crypt->fromXml($xml); + if (!empty($xmlData['Encrypt'])) { + $encryptXml = $this->crypt->decryptMsg($xmlData['Encrypt']); + $data = $this->crypt->fromXml($encryptXml); + } + return $data; + } + + public function getStableAccessToken() + { + $url = 'https://api.weixin.qq.com/cgi-bin/stable_token'; + $data['grant_type'] = 'client_credential'; + $data['appid'] = self::APPID; + $data['secret'] = self::SECRET; + $result = $this->curlPost($url, json_encode($data), 10); + $result = json_decode($result, true); + if (!empty($result['access_token'])) { + return $result['access_token']; + } + } + + /** + * @notes:获取令牌 + * @return mixed|string + * @author: wanghousheng + */ + public function getComponentAccessToken() + { + if (Cache::has('wholesaler_component_access_token')) { + return Cache::get('wholesaler_component_access_token'); + } + $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('wholesaler_component_access_token', $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; + } + + private function getRefreshToken($appid) + { + $model = new WxwholesalerAccount(); + return $model->where(['appid' => $appid])->value('refresh_token'); + } + + private function storeId($appid) + { + $model = new WxwholesalerAccount(); + return $model->where(['appid' => $appid])->value('store_id'); + } + + /** + * @notes:获取体验码 + * @param $appid + * @return string + * @author: wanghousheng + */ + public function getQrcode($appid): string + { + $savePath = root_path() . "public/wxserve/experience"; + !is_dir($savePath) && mkdir($savePath, 0755, true); + $savePath .= '/' . $appid . '.jpg'; + if (file_exists($savePath)) { + return '/wxserve/experience/' . $appid . '.jpg'; + } + $access_token = $this->authorizerAccessToken($appid); + if ($access_token) { + $url = 'https://api.weixin.qq.com/wxa/get_qrcode?access_token=' . $access_token; + $client = new Client(); + $response = $client->get($url); + $res = $response->body(); + if ($res) { + $newFile = fopen($savePath, "a"); + fwrite($newFile, $res); + fclose($newFile); + return '/wxserve/experience/' . $appid . '.jpg'; + } + } + return ''; + } + + /** + * @notes:发布体验版 + * @param $appid + * @param $template_id + * @return bool + * @throws BaseException + * @author: wanghousheng + */ + public function commit($appid, $template_id): bool + { + $version = ''; + $access_token = $this->authorizerAccessToken($appid); + //获取模板 + $templatelist = $this->getTemplatelist(); + if ($templatelist) { + foreach ($templatelist as $value) { + if (!empty($value['user_version']) && $value['template_id'] == $template_id) { + $version = $value['user_version']; + break; + } + } + } + if ($version == '') { + throwError('模板不存在'); + } + $data['template_id'] = $template_id; + $data['user_version'] = $version; + $data['user_desc'] = 'updated'; + $ext_json['extAppid'] = $appid; + $ext_json['ext']['store_id'] = $this->storeId($appid); + $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') { + //体验码 + $qr_code = $this->getQrcode($appid); + if ($qr_code) { + $model = new WxwholesalerAccount(); + $model->update(['experience_code' => $qr_code], ['appid' => $appid]); + } + return true; + } + return false; + } + + /** + * @notes:发布已经审核通过的小程序 + * @param $appid + * @return bool + * @author: wanghousheng + */ + public function release($appid): bool + { + $access_token = $this->authorizerAccessToken($appid); + if ($access_token) { + $url = 'https://api.weixin.qq.com/wxa/release?access_token=' . $access_token; + $result = $this->curlPost($url, '{}'); + $result = json_decode($result, true); + if ($result && !empty($result['errmsg']) && $result['errmsg'] == 'ok') { + return true; + } + } + return false; + } + + /** + * @notes:获取版本信息 + * @param $appid + * @return bool + * @author: wanghousheng + */ + public function getVersioninfo($appid): bool + { + $access_token = $this->authorizerAccessToken($appid); + $url = 'https://api.weixin.qq.com/wxa/getversioninfo?access_token=' . $access_token; + $result = $this->curlPost($url, '{}'); + $result = json_decode($result, true); + if ($result && !empty($result['errmsg']) && $result['errmsg'] == 'ok') { + $up = []; + if (!empty($result['exp_info'])) { + $up['exp_info'] = json_encode($result['exp_info']); + } + if (!empty($result['release_info'])) { + $up['release_info'] = json_encode($result['release_info']); + } + if ($up) { + $model = new WxwholesalerAccount(); + $model->update($up, ['appid' => $appid]); + } + return true; + } + return false; + } + + /** + * @notes:获取隐私接口检测结果 + * @param $appid + * @return mixed|string + * @author: wanghousheng + */ + public function privacyInfo($appid) + { + $errmsg = ''; + $access_token = $this->authorizerAccessToken($appid); + $url = 'https://api.weixin.qq.com/wxa/security/get_code_privacy_info?access_token=' . $access_token; + $result = $this->curlGet($url); + $result = json_decode($result, true); + if ($result && !empty($result['errmsg'])) { + $errmsg = $result['errmsg']; + } + return $errmsg; + } + + /** + * @notes:获取/刷新接口调用令牌 + * @param $appid + * @return false|mixed + * @author: wanghousheng + */ + public function authorizerAccessToken($appid) + { + if (Cache::has($appid . '_wholesaler_authorizer_access_token')) { + return Cache::get($appid . '_wholesaler_authorizer_access_token'); + } + $refresh_token = $this->getRefreshToken($appid); + if ($refresh_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 . '_wholesaler_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($type) + { + if (!$type && Cache::has('wx_wholesaler_drafttemplatelist')) { + return Cache::get('wx_wholesaler_drafttemplatelist'); + } + $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('wx_wholesaler_drafttemplatelist', $list, 7200); + } + } + return $list; + } + + /** + * @notes:添加草稿箱到模板中 + * @param $draft_id + * @return bool + * @author: wanghousheng + */ + public function addTotemplate($draft_id): bool + { + $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('wx_wholesaler_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('wx_wholesaler_templatelist'); + return true; + } + } + return false; + } + + /** + * @notes:代码模板列表 + * @param int $type + * @return array + * @author: wanghousheng + */ + public function getTemplatelist(int $type = 0): array + { + if (!$type && Cache::has('wx_wholesaler_templatelist')) { + return Cache::get('wx_wholesaler_templatelist'); + } + $token = $this->getComponentAccessToken(); + $list = []; + if ($token) { + $url = 'https://api.weixin.qq.com/wxa/gettemplatelist?access_token=' . $token . '&template_type=1'; + $result = $this->curlGet($url); + $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' => !empty($value['reason']) ? $value['reason'] : '', + 'draft_id' => $value['draft_id'], + ]; + } + Cache::set('wx_wholesaler_templatelist', $list, 7200); + } + } + return $list; + } + + /** + * @notes:设置域名 + * @param $appid + * @param $domain + * @return bool + * @author: wanghousheng + */ + public function setDomain($appid, $domain) + { + $token = $this->authorizerAccessToken($appid); + if ($token) { + $url = "https://api.weixin.qq.com/wxa/modify_domain_directly?access_token=$token"; + $data['action'] = 'set'; + $data['requestdomain'] = $domain; + $data['uploaddomain'] = $domain; + $data['downloaddomain'] = $domain; + $result = $this->curlPost($url, json_encode($data)); + $result = json_decode($result, true); + if ($result && !empty($result['errmsg']) && $result['errmsg'] == 'ok') { + return true; + } + } + return false; + } + + /** + * @notes:设置隐私 + * @param $appid + * @return bool + * @author: wanghousheng + */ + public function getPrivacySetting($appid): bool + { + $token = $this->authorizerAccessToken($appid); + if ($token) { + $url = "https://api.weixin.qq.com/cgi-bin/component/setprivacysetting?access_token=$token"; + $setting_list = [ + ['privacy_key' => 'PhoneNumber', 'privacy_text' => '用于用户一键登录'], + ['privacy_key' => 'Location', 'privacy_text' => '用于用户选择自提点'], + ['privacy_key' => 'AlbumWriteOnly', 'privacy_text' => '用于用户保存海报'], + ['privacy_key' => 'Address', 'privacy_text' => '用于用户快速获取微信地址'], + ['privacy_key' => 'Invoice', 'privacy_text' => '用于用户申请开票'], + ['privacy_key' => 'Album', 'privacy_text' => '用于用户上传图片'], + ['privacy_key' => 'Clipboard', 'privacy_text' => '用于用户复制粘贴'], + ]; + $data['setting_list'] = $setting_list; + $data['owner_setting']['contact_qq'] = '527264601'; + $data['owner_setting']['notice_method'] = '公告'; + $result = $this->curlPost($url, json_encode($data)); + $result = json_decode($result, true); + if ($result && !empty($result['errmsg']) && $result['errmsg'] == 'ok') { + return true; + } + } + return false; + } + + public function apiText($authorization_code, $touser) + { + $url = 'https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=' . $this->getComponentAccessToken(); + $data['component_appid'] = self::APPID; + $data['authorization_code'] = $authorization_code; + $result = $this->curlPost($url, json_encode($data)); + $result = json_decode($result, true); + if (!empty($result['authorization_info']['authorizer_access_token'])) { + $token = $result['authorization_info']['authorizer_access_token']; + $url = 'https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=' . $token; + $data = [ + 'touser' => $touser, + 'msgtype' => 'text', + 'text' => ['content' => $authorization_code . '_from_api'], + ]; + $this->curlPost($url, json_encode($data)); + } + + } + + /** + * @notes:获取授权信息 + * @param $authorization_code + * @param string $domain + * @throws DataNotFoundException + * @throws DbException + * @throws ModelNotFoundException + * @author: wanghousheng + */ + public function authorizationInfo($authorization_code, string $domain = '') + { + $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']; + $model = new WxwholesalerAccount(); + $appid = $authorization_info['authorizer_appid']; + $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['update_time'] = time(); + $exit_id = $model->where(['appid' => $appid])->value('id'); + if ($exit_id) { + $model->update($insert_data, ['id' => $exit_id]); + } else { + $insert_data['appid'] = $appid; + $insert_data['create_time'] = time(); + $model->insertGetId($insert_data); + } + $this->setOther($appid, $domain); + } + } + } + + private function setOther($appid, $domain) + { + $up = []; + //设置域名信息 + if ($this->setDomain($appid, $domain)) { + $up['domain_status'] = 1; + } + //设置隐私 + if ($this->getPrivacySetting($appid)) { + $up['privacy_status'] = 1; + } + //设置业务域名 + if ($this->modifyJumpDomain($appid)) { + $up['jump_domain_status'] = 1; + } + if ($up) { + $model = new WxwholesalerAccount(); + $model->update($up, ['appid' => $appid]); + } + } + + private function modifyJumpDomain($appid, $domain): bool + { + $token = $this->authorizerAccessToken($appid); + if ($token) { + $url = "https://api.weixin.qq.com/wxa/setwebviewdomain?access_token=$token"; + $data['action'] = 'set'; + $data['webviewdomain'] = $domain; + $result = $this->curlPost($url, json_encode($data)); + $result = json_decode($result, true); + if ($result && !empty($result['errmsg']) && $result['errmsg'] == 'ok') { + return true; + } + } + return false; + } + + /** + * @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) { + $store_id = Db::table('yoshop_store')->where(['store_id' => $value['store_id'], 'is_recycle' => 0])->value('store_id'); + if ($store_id) { + return $store_id; + } + } + } + } + } + return 0; + } + + public function submitAudit($appid): bool + { + $access_token = $this->authorizerAccessToken($appid); + if ($access_token) { + $url = 'https://api.weixin.qq.com/wxa/submit_audit?access_token=' . $access_token; + $data['item_list'] = $this->getAllCategory($appid); + if (!empty($data['item_list'])) { + $data = '{}'; + } else { + $data = json_encode($data); + } + $result = $this->curlPost($url, $data); + $result = json_decode($result, true); + if (!empty($result) && intval($result['errcode']) == 0 && !empty($result['auditid'])) { + $model = new WxwholesalerAccount(); + $up['audit_status'] = 1; + $up['audit_reason'] = ''; + $up['audit_time'] = date('Y-m-d H:i:s'); + $up['auditid'] = $result['auditid']; + $model->update($up, ['appid' => $appid]); + return true; + } + + } + return false; + } + + /** + * @notes:检测审核状态 + * @param $appid + * @param $auditid + * @return array|mixed + * @author: wanghousheng + */ + public function getAuditStatus($appid, $auditid) + { + $access_token = $this->authorizerAccessToken($appid); + if ($access_token && $auditid) { + $url = 'https://api.weixin.qq.com/wxa/get_auditstatus?access_token=' . $access_token; + $data['auditid'] = $auditid; + $result = $this->curlPost($url, json_encode($data)); + $result = json_decode($result, true); + if (!empty($result) && intval($result['errcode']) == 0 && isset($result['status'])) { + $status = intval($result['status']); + $up = []; + if ($status == 0) { + $up['audit_status'] = 2; + } elseif ($status == 1) { + $up['audit_status'] = 3; + } elseif ($status == 2) { + $up['audit_status'] = 1; + } elseif ($status == 4) { + $up['audit_status'] = 4; + } + if (!empty($result['reason'])) { + $up['audit_reason'] = $result['reason']; + } + if ($up) { + $model = new WxwholesalerAccount(); + $model->update($up, ['appid' => $appid]); + } + return $result; + } + } + return []; + } + + public function getAllCategory($appid): array + { + $data = []; + $access_token = $this->authorizerAccessToken($appid); + if ($access_token) { + $url = 'https://api.weixin.qq.com/wxa/get_category?access_token=' . $access_token; + $result = $this->curlGet($url); + $result = json_decode($result, true); + if ($result && !empty($result['category_list'])) { + $category_list = $result['category_list']; + foreach ($category_list as $value) { + $arr = []; + if (!empty($value['first_class'])) { + $arr['first_class'] = $value['first_class']; + } + if (!empty($value['second_class'])) { + $arr['second_class'] = $value['second_class']; + } + if (!empty($value['third_class'])) { + $arr['third_class'] = $value['third_class']; + } + if (!empty($value['first_id'])) { + $arr['first_id'] = $value['first_id']; + } + if (!empty($value['second_id'])) { + $arr['second_id'] = $value['second_id']; + } + if (!empty($value['third_id'])) { + $arr['third_id'] = $value['third_id']; + } + if ($arr) { + $data[] = $arr; + } + } + } + } + return $data; + } + + 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; + } } \ No newline at end of file diff --git a/app/common/model/WxwholesalerAccount.php b/app/common/model/WxwholesalerAccount.php index 2eea6c67..e9c3ad7d 100644 --- a/app/common/model/WxwholesalerAccount.php +++ b/app/common/model/WxwholesalerAccount.php @@ -2,7 +2,13 @@ namespace app\common\model; -class WxwholesalerAccount +use cores\BaseModel; + +class WxwholesalerAccount extends BaseModel { + // 定义表名 + protected $name = 'wxwholesaler_account'; + // 定义主键 + protected $pk = 'id'; } \ No newline at end of file diff --git a/app/job/controller/Wxholesaler.php b/app/job/controller/Wxholesaler.php new file mode 100644 index 00000000..8bdae6f0 --- /dev/null +++ b/app/job/controller/Wxholesaler.php @@ -0,0 +1,58 @@ +sendTestVersion($data['appid'], $data['template_id']); + } else { + $this->sendOfficialVersion($data['appid']); + } + } + return true; + } + + /** + * @notes:发布正式版 + * @param $appid + * @author: wanghousheng + */ + private function sendOfficialVersion($appid) + { + $obj = new Server(); + $res = $obj->privacyInfo($appid); + if ($res == 'ok') { + $obj->submitAudit($appid); + } + } + + /** + * @notes:发布体验版 + * @param $appid + * @param $template_id + * @throws BaseException + * @author: wanghousheng + */ + private function sendTestVersion($appid, $template_id) + { + $obj = new Server(); + $res = $obj->commit($appid, $template_id); + } +} \ No newline at end of file