app = $app; //公众号 $config = config('wechat.official_account.default'); $official_app = new OfficialApplication($config); // $app->setCache(new Psr16Cache(app('cache.psr6'))); // $access_token_key = "mp_access_token"; // Log::info("当前access_token: {$app->getAccessToken()->getToken()}"); // if (config('app.env') == 'production') { // if (Cache::has($access_token_key)) { // $this->mp_access_token = Cache::get($access_token_key); // }else { // $app->getAccessToken()->refresh(); // $this->mp_access_token = $app->getAccessToken()->getToken(); // Cache::put($access_token_key, $this->mp_access_token, now()->addMinutes(90)); // } // } // Log::info("缓存access_token: {$this->mp_access_token}"); // $official_app->setCache(new Psr16Cache(app('cache.psr6'))); // $app->setCache(new Psr16Cache(app('cache.psr6'))); // $access_token_key = "official_access_token"; // Log::info("当前access_token: {$official_app->getAccessToken()->getToken()}"); // if (config('app.env') == 'production') { // if (Cache::has($access_token_key)) { // $this->official_access_token = Cache::get($access_token_key); // }else { // $official_app->getAccessToken()->refresh(); // $this->official_access_token = $official_app->getAccessToken()->getToken(); // Cache::put($access_token_key, $this->official_access_token, now()->addMinutes(90)); // } // } // Log::info("缓存access_token: {$this->official_access_token}"); $this->official_app = $official_app; } public function instance() { //商户号 $merchantId = config('wechat.payment.mch_id'); // 从本地文件中加载「商户API私钥」,「商户API私钥」会用来生成请求的签名 $merchantPrivateKeyFilePath = 'file://' . config('wechat.payment.private_key'); $merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE); // 「商户API证书」的「证书序列号」 $merchantCertificateSerial = config('wechat.payment.serial'); // 从本地文件中加载「微信支付平台证书」,用来验证微信支付应答的签名 $platformCertificateFilePath = 'file://' . config('wechat.payment.certificate'); $platformPublicKeyInstance = Rsa::from($platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC); // 从「微信支付平台证书」中获取「证书序列号」 $platformCertificateSerial = PemUtil::parseCertificateSerialNo($platformCertificateFilePath); // 构造一个 APIv3 客户端实例 $instance = Builder::factory([ 'mchid' => $merchantId, 'serial' => $merchantCertificateSerial, 'privateKey' => $merchantPrivateKeyInstance, 'certs' => [ $platformCertificateSerial => $platformPublicKeyInstance, ], ]); return $instance; } public function app() { return $this->app; } /** * 公众号 * @return \EasyWeChat\OfficialAccount\Application */ public function officialApp() { return $this->official_app; } /** * 企业微信 * @return WorkApplication */ public function workApp($type) { $work_config = config('wechat.' . $type); $work_app = new WorkApplication($work_config); return $work_app; } /** * 小程序code 换取session 信息 * @param $code * @param string $grant_type * @return array * @throws \Exception */ public function codeToSession($code, $grant_type = 'authorization_code') { try { $utils = $this->app->getUtils(); $response = $utils->codeToSession($code); return $response; } catch (\Throwable $e) { throw new \Exception($e->getMessage()); } } /** * 小程序code换取手机号信息 * @param $code * @return array|string[] * @throws \Exception */ public function phoneNuber($code) { try { if (env('APP_ENV') == 'local') return ['mobile' => '15872844805']; $data = ['code' => (string) $code]; $res = $this->app->getClient()->postJson('wxa/business/getuserphonenumber', $data); if ($res->isFailed()) throw new \Exception($res->getContent()); $r = json_decode($res->toJson()); return ['mobile' => $r->phone_info->phoneNumber]; } catch (\Throwable $e) { throw new \Exception($e->getMessage()); } } /** * 小程序订阅消息列表 * @return mixed|null * @throws \Exception */ public function templates() { try { $res = $this->app->getClient()->get('wxaapi/newtmpl/gettemplate'); if ($res->isFailed()) throw new \Exception($res->getContent()); return $res['data'] ?? null; } catch (\Throwable $e) { throw new \Exception($e->getMessage()); } } /** * 小程序发送订阅消息 * @param $openid * @param $template_id * @param $page * @param array $data * @return bool|int|mixed */ public function subSend($openid, $template_id, $page, $data = []) { try { if (empty($openid)) return false; $all_data = [ 'template_id' => $template_id, 'touser' => $openid, 'page' => $page, 'data' => $data, 'miniprogram_state' => (env('APP_ENV') == 'production') ? 'formal' : 'developer', 'lang' => 'zh_CN', ]; $client = $this->app->getClient(); $response = $client->postJson('cgi-bin/message/subscribe/send', $all_data); $all_data['type'] = 'mp'; if ($response['errcode']) { $all_data['err_msg'] = $response['errmsg']; $all_data['status'] = 0; } else { $all_data['err_msg'] = ''; $all_data['status'] = 1; } // $this->addTemplateMsgLog($all_data); return $response['errcode'] ?? 1; } catch (\Throwable $e) { $this->getError($e); return true; } } // public function addTemplateMsgLog($data) // { // $where = $data['type'] == 'mp'?['openid'=>$data['touser']]:['official_openid'=>$data['touser']]; // $user_id = Wechat::where($where)->value('user_id'); // $log = new TemplateMsgLog; // $log->user_id = $user_id; // $log->openid = $data['touser']; // $log->type = $data['type']; // $log->template_id = $data['template_id']; // $log->status = $data['status']; // $log->err_msg = $data['err_msg']??''; // $log->data = json_encode($data); // $log->save(); // return true; // } /** * 获取小程序二维码 * @param $scene * @param $page * @param string $env_version 正式版为 "release",体验版为 "trial",开发版为 "develop"。默认是正式版。 * @param int $width * @param bool $is_hyaline * @return string * @throws \EasyWeChat\Kernel\Exceptions\BadResponseException * @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface */ public function getMPQrcode($scene, $page, $env_version = 'release', $width = 430, $is_hyaline = true) { $app = $this->app; $response = $app->getClient()->postJson('/wxa/getwxacodeunlimit', [ 'scene' => $scene, 'page' => $page, 'width' => $width, 'is_hyaline' => $is_hyaline, 'env_version' => $env_version, 'check_path' => false ]); $file_name = uniqid() . time() . 'qrcode.png'; $path = storage_path('qrcode/' . $file_name); $response->saveAs($path); $pic = ''; if (file_exists($path)) { $pic = UploadService::uploadFile($path); @unlink($path); } return $pic; } /** * 小程序支付 * @param $trade_no * @param $openid * @param $total * @param $desc * @param $callback * @return array|false */ public function mpPay($trade_no, $openid, $total, $desc, $callback, $appId = '', $sub_mchid = '') { if (config('wechat.payment.debug')) { return false; } $sub_appid = config('wechat.payment.sub_app_id'); if ($appId) { $sub_appid = $appId; } $resp = $this->instance() ->chain('v3/pay/partner/transactions/jsapi') ->post([ 'json' => [ 'sp_mchid' => config('wechat.payment.mch_id'), 'sp_appid' => config('wechat.payment.sp_appid'), 'sub_appid' => $sub_appid, 'sub_mchid' => $sub_mchid ?: config('wechat.payment.sub_merchant_id'), 'out_trade_no' => $trade_no, 'description' => $desc, 'notify_url' => $callback, 'amount' => [ 'total' => (int) number_format($total * 100, 0, '', ''), 'currency' => 'CNY' ], 'payer' => [ 'sub_openid' => $openid, ] ] ]); $res = json_decode($resp->getBody()); $prepay_id = $res->prepay_id; $config = $this->paySign($prepay_id, $sub_appid); $config['prepay_id'] = $prepay_id; return $config; } /** * 获取jssdk配置 * @param $url * @return mixed[] * @throws \EasyWeChat\Kernel\Exceptions\HttpException * @throws \Psr\SimpleCache\InvalidArgumentException * @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface */ // public function getOfficialShareConfig($url){ // $app = $this->officialApp(); // $config = $app->getUtils()->buildJsSdkConfig($url, ['updateAppMessageShareData','updateTimelineShareData','onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareQZone', 'openLocation', 'getLocation', 'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'openAddress', 'updateAppMessageShareData', 'updateTimelineShareData', 'wx-open-launch-weapp', 'chooseVideo', 'hideMenuItems','showMenuItems'], ['wx-open-launch-weapp'], false); // return $config; // } public function buildJsSdkConfig($url) { // $app = $this->officialApp(); // $api = $app->getClient(); $token_url = config('app.url') . '/go/api/h5/v1/common/accesstoken/get'; $params = ['curr_date' => "#" . date("Y-m-d") . "@-"]; try { $res = \App\Facades\HttpService::postData($token_url, $params); $access_token = $res['data']; } catch (\Exception $e) { $access_token = ''; } // $res = $api->get("cgi-bin/ticket/getticket?access_token=$access_token&type=jsapi"); // if ($res->isFailed()) { // // } // $res = json_decode($res->toJson(),true); $ticket_url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" . $access_token . "&type=jsapi"; $res = \App\Facades\HttpService::getData($ticket_url); Log::info("获取微信ticket cgi-bin/ticket/getticket?access_token=$access_token&type=jsapi"); Log::info($res); $ticket = $res['ticket']; $nonce = Str::random(); $timestamp = time(); $signature = sha1("jsapi_ticket=$ticket&noncestr=$nonce×tamp=$timestamp&url=$url"); $jsApiList = ['updateAppMessageShareData', 'updateTimelineShareData', 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo', 'onMenuShareQZone', 'openLocation', 'getLocation', 'chooseImage', 'previewImage', 'uploadImage', 'downloadImage', 'openAddress', 'updateAppMessageShareData', 'updateTimelineShareData', 'wx-open-launch-weapp', 'chooseVideo', 'hideMenuItems', 'showMenuItems']; $openTagList = ['wx-open-launch-weapp']; return [ 'appId' => config('wechat.official_account.default.app_id'), 'beta' => false, 'debug' => false, 'jsApiList' => $jsApiList, 'nonceStr' => $nonce, 'openTagList' => $openTagList, 'signature' => $signature, 'timestamp' => $timestamp, 'url' => $url, ]; } /** * 退款 * @param $trade_no * @param $refund_trade_no * @param $total_amount * @param $refund_amount * @param array $array * @return array */ public function refund($trade_no, $refund_trade_no, $total_amount, $refund_amount, $callback, $sub_mchid = '') { if (config('wechat.payment.debug')) { return ["status" => true, 'msg' => '']; } if (!$sub_mchid) { $sub_mchid = config('wechat.payment.sub_merchant_id'); } try { $resp = $this->instance() ->chain('v3/refund/domestic/refunds') ->post([ 'json' => [ 'sub_mchid' => $sub_mchid, 'out_trade_no' => $trade_no, 'out_refund_no' => $refund_trade_no, 'notify_url' => $callback, 'amount' => [ 'total' => (int) number_format($total_amount * 100, 0, '', ''), 'refund' => (int) number_format($refund_amount * 100, 0, '', ''), 'currency' => 'CNY' ], ] ]); $res = json_decode($resp->getBody()); Log::info($resp->getBody()); if ($res->status == 'PROCESSING' || $res->status == "SUCCESS") { return ['status' => true, 'msg' => '']; } return ['status' => false, 'msg' => '打款失败']; } catch (\Exception $e) { $msg = $e->getMessage(); Log::info($msg); return ['status' => false, 'msg' => $msg]; } } /** * 退款订单查询 * @param string $refund_trade_no 退款订单号 */ public function orderRefunded($refund_trade_no, $sub_mch_id = null) { if (config('wechat.payment.debug')) { return ['status' => true, 'message' => ""]; } try { if (!$sub_mch_id) { $sub_mch_id = config('wechat.payment.sub_merchant_id'); } $resp = $this->instance() ->chain('v3/refund/domestic/refunds/' . $refund_trade_no) ->get([ 'query' => [ 'sub_mchid' => $sub_mch_id ], 'out_refund_no' => $refund_trade_no, ]); $res = json_decode($resp->getBody()); if ($res->status == 'SUCCESS') { return ['status' => true, 'message' => ""]; } return ['status' => false, 'message' => "退款失败"]; } catch (\Exception $e) { Log::debug($refund_trade_no . '订单查询退款异常:' . $e->getMessage()); return ['status' => false, 'message' => $e->getMessage()]; } } /** * 小程序-查询订单是否支付 * @param $trade_no * @return bool */ public function mpPaid($trade_no, $sub_mch_id = '') { if (config('wechat.payment.debug')) { return false; } if (empty($sub_mch_id)) { $sub_mch_id = config('wechat.payment.sub_merchant_id'); } $resp = $this->instance() ->chain('v3/pay/partner/transactions/out-trade-no/' . $trade_no) ->get([ // Query 参数 'query' => [ 'sp_mchid' => config('wechat.payment.mch_id'), 'sub_mchid' => $sub_mch_id, ], // 变量名 => 变量值 'out_trade_no' => $trade_no, ]); Log::info($resp->getBody()); $res = json_decode($resp->getBody()); if (empty($res)) return true; if ($res->trade_state == 'NOTPAY' || $res->trade_state == "CLOSED") return $res->trade_state_desc; return false; } /** * 小程序-支付签名 * @param $prepay_id * @return array */ public function paySign($prepay_id, $sub_appid) { $merchantPrivateKeyFilePath = 'file://' . config('wechat.payment.private_key'); $merchantPrivateKeyInstance = Rsa::from($merchantPrivateKeyFilePath); $params = [ // 'appId' => config('wechat.mini_program.app_id'), 'appId' => $sub_appid, 'timeStamp' => (string) Formatter::timestamp(), 'nonceStr' => Formatter::nonce(), 'package' => 'prepay_id=' . $prepay_id, ]; $params += [ 'paySign' => Rsa::sign( Formatter::joinedByLineFeed(...array_values($params)), $merchantPrivateKeyInstance ), 'signType' => 'RSA' ]; return $params; } public function sendSubscribeMessage($params) { if (config('app.env') == 'production') { $app = $this->app; // $accessToken = $app->getAccessToken(); // $accessToken->getToken(); $response = $app->getClient()->postJson('cgi-bin/message/subscribe/send', $params); // if ($response['errcode'] && $response['errcode'] != "43101") { Log::info($params); //todo 发送失败 // throw new \Exception($response['errmsg']); // } } } /** * 公众号-后台服务 * @return \Psr\Http\Message\ResponseInterface * @throws \EasyWeChat\Kernel\Exceptions\BadRequestException * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException * @throws \ReflectionException * @throws \Throwable */ public function server() { $app = $this->officialApp(); $server = $app->getServer(); $server->with(function ($message, \Closure $next) { Log::info("api server"); // 你的自定义逻辑 // Log::info($message); $openid = $message->FromUserName; //获取微信用户信息 $info = $this->wechatUserByOfficialOpenid($openid); Log::info($openid . '用户信息', $info); if ($message->MsgType == 'event') { if ($message->Event == 'subscribe' || $message->Event == 'unsubscribe') {//关注 //同步健康信息 $this->syncSubscribe($info); } } //同步创业家项目关注信息 // $this->syncEstpSubscribe($info); return $next($message); }); return $server->serve(); } /** * 同步公众号关注 * @param $info */ public function syncSubscribe($info) { $subscribe = $info['subscribe']; if ($subscribe) { //是否有本地小程序信息信息 $wechat = Wechat::where(['unionid' => $info['unionid'], 'type' => 'mp'])->first(); // if (empty($wechat)) return ; DB::beginTransaction(); //是否有本地公众号信息信息 $official_wechat = Wechat::where('type', 'official') ->where('openid', $info['openid']) ->first(); if (empty($official_wechat)) return; // if (!empty($wechat)){ // $official_wechat->user_id = $wechat->user_id; // } $official_wechat->unionid = $info['unionid']; $official_wechat->save(); } else { $official_wechat = Wechat::where(['openid' => $info['openid'], 'type' => 'official'])->first(); if (empty($official_wechat)) return; } //同步关注信息 User::where('id', $official_wechat->user_id)->update(['is_subscribe' => $subscribe]); DB::commit(); } /** * 同步创业家项目关注 * @param $info */ public function syncEstpSubscribe($info) { $subscribe = $info['subscribe']; if ($subscribe) { //关注 $user = EstpUser::query()->where('unionid', $info['unionid'])->first(); if ($user) { $user['is_subscribe'] = $subscribe; $user['openid'] = $info['openid']; $user->save(); } } else { //取关 $user = EstpUser::query()->where('openid', $info['openid'])->first(); if ($user) { $user['is_subscribe'] = $subscribe; $user['open_recommend'] = $subscribe; $user->save(); } } if ($user) { Log::info([ 'msg' => '已更新创业家' . ['取关', '关注'][$subscribe] . '信息', 'data' => $user->toArray(), ]); } } /** * 公众号-通过openid获取用户信息 * @param $openid * @return mixed * @throws \EasyWeChat\Kernel\Exceptions\BadResponseException * @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface */ public function wechatUserByOfficialOpenid($openid) { // $app = $this->officialApp(); // $api = $app->getClient(); //处理token过期报错 // $accessToken = $this->official_access_token; // $accessToken = $app->getAccessToken()->getToken(); $url = config('app.url') . '/go/api/h5/v1/common/accesstoken/get'; $params = ['curr_date' => "#" . date("Y-m-d") . "@-"]; try { $res = \App\Facades\HttpService::postData($url, $params); $access_token = $res['data']; } catch (\Exception $e) { $access_token = ''; } $url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=$access_token&openid=$openid"; $res = \App\Facades\HttpService::getData($url); return $res; // $response = $api->get('/cgi-bin/user/info', [ // "openid" => $openid, // "access_token" => $access_token, // ]); // if ($response->isFailed()) { // throw new \Exception("通过openid获取用户微信信息失败, ".$response->getContent()); // } // $content = $response->toJson(); // return json_decode($content,true); } /** * 公众号-发送模板消息 * @param $param * @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface */ public function sendTemplateNotice($param) { if (config('app.env') == 'production') { // $app = $this->officialApp(); // $api = $app->getClient(); // $accessToken = $app->getAccessToken()->getToken(); // $accessToken = $this->official_access_token; $url = config('app.url') . '/go/api/h5/v1/common/accesstoken/get'; $params = ['curr_date' => "#" . date("Y-m-d") . "@-"]; try { $res = \App\Facades\HttpService::postData($url, $params); $access_token = $res['data']; } catch (\Exception $e) { $access_token = ''; } $url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" . $access_token; $res = \App\Facades\HttpService::postData($url, $param); // $response = $api->postJson('/cgi-bin/message/template/send?access_token=' . $access_token, $param); // if ($response->isFailed()) { // $errMsg = $response->toJson(); // $errMsg = json_decode($errMsg,true); // if (isset($errMsg['errcode']) && $errMsg['errcode'] == 40001) { // $app->getAccessToken()->refresh(); // $newResponse = $api->postJson('/cgi-bin/message/template/send', $param); // Log::error("sendTemplateNotice1".$newResponse->getContent()); // throw new \Exception("发送模板消息失败, ".$response->getContent()); // } // Log::error("sendTemplateNotice" . $response->getContent()); // } } } /** * 获取公众号二维码 * @param $param * @return mixed * @throws \EasyWeChat\Kernel\Exceptions\BadResponseException * @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface */ public function getOfficialQrcode($param) { // $app = $this->officialApp(); // $api = $app->getClient(); // $accessToken = $this->official_access_token; $url = config('app.url') . '/go/api/h5/v1/common/accesstoken/get'; $params = ['curr_date' => "#" . date("Y-m-d") . "@-"]; try { $res = \App\Facades\HttpService::postData($url, $params); $access_token = $res['data']; } catch (\Exception $e) { $access_token = ''; } $url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" . $access_token; $res = \App\Facades\HttpService::postData($url, $param); return $res; // $response = $api->postJson('/cgi-bin/qrcode/create?access_token=' . $access_token, $param); // $content = $response->toJson(); // return json_decode($content,true); } /** * 发送群消息 * @param $touser * @param $msgtype * @param $content * @param string $toparty * @param string $totag * @param int $enable_duplicate_check * @param int $duplicate_check_interval * @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface */ public function sendWorkMessage($touser, $msgtype, $content, $toparty = '', $totag = '', $enable_duplicate_check = 0, $duplicate_check_interval = 1800) { $api = $this->workApp('work_application')->getClient(); $params = [ "touser" => $touser, 'toparty' => $toparty, 'totag' => $totag, "msgtype" => $msgtype, "agentid" => 1000008, "safe" => 0, $msgtype => $content, "enable_duplicate_check" => $enable_duplicate_check, "duplicate_check_interval" => $duplicate_check_interval ]; $response = $api->postJson('/cgi-bin/message/send', $params); if ($response->isFailed()) { // 出错了,处理异常 throw new \Exception($response->getContent()); } } /** * 发送应用消息 * @param $chatid * @param $msgtype * @param $content * @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface */ public function sendAppChat($chatid, $msgtype, $content) { $api = $this->workApp('work_application')->getClient(); // $access_token = $this->workApp()->getAccessToken()->getToken(); // dd($access_token); $params = [ 'chatid' => $chatid, 'msgtype' => $msgtype, 'content' => $content, 'safe' => 0 ]; $response = $api->postJson("/cgi-bin/appchat/send", $params); if ($response->isFailed()) { // 出错了,处理异常 throw new \Exception($response->getContent()); } // dd($response->getContent()); } /** * 微信公众号授权-获取code * @param $redirect_uri * @return string|void * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException */ public function connectAuth($redirect_uri) //snsapi_userinfo { $app = $this->officialApp(); $oauth = $app->getOauth(); $wechat_user = session('wechat_user'); $openid = $wechat_user['id'] ?? null; if (empty($openid)) { session(['intend_url' => $redirect_uri]); // Log::info($redirect_uri); //生成完整的授权URL $redirectUrl = $oauth->redirect($redirect_uri); // Log::info($redirectUrl); return $redirectUrl; } } /** * 微信公众号授权-获取维信息 * @param $code * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Session\SessionManager|\Illuminate\Session\Store|mixed|string * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException */ public function connectAuthByCode($code) { // Log::info("wechat code: ". $code); try { $app = $this->officialApp(); $oauth = $app->getOauth(); $user = $oauth->userFromCode($code); session(['wechat_user' => $user->toArray()]); $targetUrl = session('intend_url') ?: '/'; return $targetUrl; } catch (\Exception $e) { // 获取异常错误信息 $errorMessage = $e->getMessage(); // 进行错误处理,例如记录日志或返回给前端 Log::error("connectAuthByCode error: " . $errorMessage); } } public function connectWorkAuthByCode($code, $config = 'work_application') { Log::info("wechat code: " . $code); $app = $this->workApp($config); Log::info("缓存测试 " . $code); $user = $app->getOAuth()->detailed()->userFromCode($code); // $user = $oauth->userFromCode($code); // Log::info($user->toArray()); //缓存用户信息 Log::info("缓存用户信息"); // Log::info($user->toArray()); session(['work_wechat_user' => $user->toArray()]); $targetUrl = session('intend_url') ?: '/'; return $targetUrl; } public function connectWorkAuth($redirect_uri, $config = 'work_application') //snsapi_userinfo { Log::info("connectWorkAuth " . $redirect_uri); session(['intend_url' => $redirect_uri]); $app = $this->workApp($config); $redirect_uri = $app->getOAuth()->redirect($redirect_uri); return $redirect_uri; } /** * 获取企业微信jsSDK * @param $url * @param $type * @return array|mixed[] * @throws \EasyWeChat\Kernel\Exceptions\HttpException * @throws \Psr\SimpleCache\InvalidArgumentException * @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface * @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface */ public function workJsSdkConfig($url, $type) { $config = []; if ($type == 'work') { $utils = $this->workApp('work')->getUtils(); $config = $utils->buildJsSdkConfig( $url, [], [], false, ); // $config['jsapi_ticket'] = $this->workApp('work')->getTicket()->getTicket(); } elseif ($type == 'app') { $utils = $this->workApp('work_application')->getUtils(); $config = $utils->buildJsSdkAgentConfig( config('wechat.work_application.agent_id'), $url, [], [], false, ); // $config['jsapi_ticket'] = $this->workApp('work_application')->getTicket()->getAgentTicket(1000003); } return $config; } public function groupChats($cursor = '', $limit = 15, $status_filter = 0, $userid_list = []) { $api = $this->workApp('work')->getClient(); $response = $api->postJson('/cgi-bin/externalcontact/groupchat/list', [ 'status_filter' => $status_filter, 'owner_filter' => [ 'userid_list' => $userid_list ], 'cursor' => $cursor, 'limit' => $limit ]); if ($response->isFailed()) { // 出错了,处理异常 throw new \Exception($response->getContent()); } return json_decode($response->toJson()); } public function groupChat($chat_id, $need_name = 0) { try { $api = $this->workApp('work')->getClient(); $response = $api->postJson('/cgi-bin/externalcontact/groupchat/get', [ 'chat_id' => $chat_id, 'need_name' => $need_name ]); // if ($response->isFailed()) { // // 出错了,处理异常 // throw new \Exception($response->getContent()); // } $res = json_decode($response->toJson()); return $res; } catch (\Exception $e) { $this->getError($e); return false; } } public function workUserInfo($user_id) { $api = $this->workApp('work')->getClient(); $response = $api->get('/cgi-bin/user/get', ['userid' => $user_id]); if ($response->isFailed()) { // 出错了,处理异常 throw new \Exception($response->getContent()); } // Log::info($response->toJson()); return json_decode($response->toJson()); } public function test() { $access = $this->official_app->getAccessToken()->getToken(); dd($access); } /** * 获取小程序 url link */ public function urlLink($path, $query) { $data = [ "path" => $path, "query" => $query, ]; $res = $this->app->getClient()->post('wxa/generate_urllink', [ 'json' => $data ]); if ($res->isFailed()) throw new \Exception($res->getContent()); $r = json_decode($res->toJson()); return $r->url_link; } public function getUrlLink($url_link) { $data = [ 'url_link' => $url_link, ]; $res = $this->app->getClient()->postJson('wxa/query_urllink', $data); if ($res->isFailed()) throw new \Exception($res->getContent()); $r = json_decode($res->toJson()); return $r->url_link_info; } public function getUserStep($code, $iv, $encryptedData) { try { $app = $this->app; $utils = $app->getUtils(); $response = $utils->codeToSession($code); // 获取解密后的用户数据 $userInfo = $utils->decryptSession($response['session_key'], $iv, $encryptedData); // 用户的微信步数 $stepInfoList = $userInfo['stepInfoList']; $stepCount = end($stepInfoList); // 获取最近一天的步数 $stepCount['stepInfoList'] = $stepInfoList; return $stepCount; } catch (\Throwable $e) { throw new \Exception($e->getMessage()); } } public function getMpUrlLink($url, $query = null) { // $access_token = $this->app->getAccessToken()->getToken(); $token_url = config('app.url') . '/go/api/mp/v1/common/accesstoken_mp/get'; $params = ['curr_date' => "#" . date("Y-m-d") . "@-"]; try { $res = \App\Facades\HttpService::postData($token_url, $params); $access_token = $res['data']; } catch (\Exception $e) { $access_token = ''; } $res = $this->app->getClient()->post('wxa/generatescheme?access_token=' . $access_token, [ 'json' => [ 'jump_wxa' => [ 'path' => $url, 'query' => $query ], "is_expire" => true, "expire_time" => time() + 30 * 24 * 60 * 60 ] ]); if ($res->isFailed()) throw new \Exception($res->getContent()); $r = json_decode($res->toJson()); return $r->openlink; } }