|
|
@@ -0,0 +1,160 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace app\extra\wechat;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 微信接口调度服务
|
|
|
+ * @package app\extra\wechat
|
|
|
+ * @method \WeChat\Oauth WeChatOauth() static 微信网页授权
|
|
|
+ */
|
|
|
+class WechatService
|
|
|
+{
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 静态初始化对象
|
|
|
+ * @param string $name
|
|
|
+ * @param array $arguments
|
|
|
+ * @return mixed
|
|
|
+ * @throws \think\admin\Exception
|
|
|
+ */
|
|
|
+ public static function __callStatic(string $name, array $arguments)
|
|
|
+ {
|
|
|
+ [$type, $base, $class] = static::parseName($name);
|
|
|
+ if ("{$type}{$base}" !== $name) {
|
|
|
+ throw new \Exception("抱歉,实例 {$name} 不符合规则!");
|
|
|
+ }
|
|
|
+ if (class_exists($class)) {
|
|
|
+ return new $class(static::getConfig());
|
|
|
+ } else {
|
|
|
+ throw new \Exception("抱歉,接口模式无法实例 {$class} 对象!");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解析调用对象名称
|
|
|
+ * @param string $name
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ private static function parseName(string $name): array
|
|
|
+ {
|
|
|
+ foreach (['WeChat', 'WeMini', 'WeOpen', 'WePayV3', 'WePay', 'ThinkService'] as $type) {
|
|
|
+ if (strpos($name, $type) === 0) {
|
|
|
+ [, $base] = explode($type, $name);
|
|
|
+ return [$type, $base, "\\{$type}\\{$base}"];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ['-', '-', $name];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前微信APPID
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ public static function getAppid(): string
|
|
|
+ {
|
|
|
+ return sConf('wechat.appid');
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取接口授权模式
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ public static function getType(): string
|
|
|
+ {
|
|
|
+ $type = strtolower(sConf('wechat.type'));
|
|
|
+ if (in_array($type, ['api', 'thr'])) return $type;
|
|
|
+ throw new \Exception('请在后台配置微信对接授权模式');
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 获取公众号配置参数
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ public static function getConfig(): array
|
|
|
+ {
|
|
|
+ return [
|
|
|
+ 'appid' => static::getAppid(),
|
|
|
+ 'token' => sConf('wechat.token'),
|
|
|
+ 'appsecret' => sConf('wechat.secret'),
|
|
|
+ 'encodingaeskey' => sConf('wechat.aeskey'),
|
|
|
+ 'mch_id' => sConf('wechat.mch_id'),
|
|
|
+ 'mch_key' => sConf('wechat.mch_key')
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通过网页授权获取粉丝信息
|
|
|
+ * @param string $source 回跳URL地址
|
|
|
+ * @param integer $isfull 获取资料模式
|
|
|
+ * @param boolean $redirect 是否直接跳转
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ public static function getWebOauthInfo(string $source, int $isfull = 0, bool $redirect = true): array
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ $appid = static::getAppid();
|
|
|
+ $openid = request()->session()->get("{$appid}_openid");
|
|
|
+ $userinfo = request()->session()->get("{$appid}_fansinfo");
|
|
|
+ if ((empty($isfull) && !empty($openid)) || (!empty($isfull) && !empty($openid) && !empty($userinfo))) {
|
|
|
+ return ['openid' => $openid,"url" => "", 'fansinfo' => $userinfo];
|
|
|
+ }
|
|
|
+ // 解析 GET 参数
|
|
|
+ $queryString = parse_url($source, PHP_URL_QUERY);
|
|
|
+ // 初始化参数数组
|
|
|
+ $params = [];
|
|
|
+ // 只有当有查询字符串时才解析
|
|
|
+ if ($queryString !== null && $queryString !== '') {
|
|
|
+ parse_str($queryString, $params);
|
|
|
+ }
|
|
|
+// parse_str(parse_url($source, PHP_URL_QUERY), $params);
|
|
|
+ $getVars = [
|
|
|
+ 'code' => $params['code'] ?? input('code', ''),
|
|
|
+ 'rcode' => $params['rcode'] ?? input('rcode', ''),
|
|
|
+ 'state' => $params['state'] ?? input('state', ''),
|
|
|
+ ];
|
|
|
+ $wechat = static::WeChatOauth();
|
|
|
+ if ($getVars['state'] !== $appid || empty($getVars['code'])) {
|
|
|
+ $params['rcode'] = enbase64url($source);
|
|
|
+ $location = strstr("{$source}?", '?', true) . '?' . http_build_query($params);
|
|
|
+ $oauthurl = $wechat->getOauthRedirect($location, $appid, $isfull ? 'snsapi_userinfo' : 'snsapi_base');
|
|
|
+ return ['openid' => "","url" => $oauthurl ,"fansinfo" => ""];
|
|
|
+ } elseif (($token = $wechat->getOauthAccessToken($getVars['code'])) && isset($token['openid'])) {
|
|
|
+ request()->session()->set("{$appid}_openid", $openid = $token['openid']);
|
|
|
+ if ($isfull && isset($token['access_token'])) {
|
|
|
+ $userinfo = $wechat->getUserInfo($token['access_token'], $openid);
|
|
|
+ request()->session()->set("{$appid}_fansinfo", $userinfo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if ($getVars['rcode']) {
|
|
|
+ $location = debase64url($getVars['rcode']);
|
|
|
+ return ['openid' => "","url" => $location ,"fansinfo" => ""];
|
|
|
+ } elseif ((empty($isfull) && !empty($openid)) || (!empty($isfull) && !empty($openid) && !empty($userinfo))) {
|
|
|
+ return ['openid' => $openid, 'url' => '', 'fansinfo' => $userinfo];
|
|
|
+ } else {
|
|
|
+ throw new \Exception('Query params [rcode] not find.');
|
|
|
+ }
|
|
|
+ } catch (\Throwable $th) {
|
|
|
+ echo $th->getMessage();
|
|
|
+ }
|
|
|
+ }
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * 获取微信网页JSSDK签名参数
|
|
|
+// * @param null|string $location 签名地址
|
|
|
+// * @return array
|
|
|
+// * @throws \WeChat\Exceptions\InvalidResponseException
|
|
|
+// * @throws \WeChat\Exceptions\LocalCacheException
|
|
|
+// * @throws \think\admin\Exception
|
|
|
+// */
|
|
|
+// public static function getWebJssdkSign(?string $location = null): array
|
|
|
+// {
|
|
|
+// $location = $location ?: Library::$sapp->request->url(true);
|
|
|
+// if (static::getType() === 'api') {
|
|
|
+// return static::WeChatScript()->getJsSign($location);
|
|
|
+// } else {
|
|
|
+// return static::ThinkServiceConfig()->jsSign($location);
|
|
|
+// }
|
|
|
+// }
|
|
|
+
|
|
|
+
|
|
|
+}
|