ClientCredentialsController.php 3.89 KB
<?php


namespace App\Http\Controllers\OpenApi;


use App\Helper\ErrorCode;
use App\Helper\RedisClient;
use App\Helper\Response;
use App\Models\Legal\ClientMap;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Str;

class ClientCredentialsController
{
    const CHARS = ["a", "b", "c", "d", "e", "f",
        "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
        "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5",
        "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I",
        "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
        "W", "X", "Y", "Z"];

    const EXPIRE_IN = 7200;

    const TOKEN_PREFIX = "access_token:";

    /**
     * 创建client获得id及secret
     * @return JsonResponse
     */
    public function getApp(): JsonResponse
    {
        $client_id = $this->getClientId();
        $client_secret = $this->getClientSecret($client_id);

        $rs = [
            'client_id' => $client_id,
            'client_secret' => $client_secret
        ];

        ClientMap::create($rs);

        return Response::successWithCode(ErrorCode::SERVER_OK, ErrorCode::$messages[ErrorCode::SERVER_OK], $rs);
    }

    /**
     * 获取clientId
     * @return string
     */
    public function getClientId() : string
    {
        $uuid = str_replace('-', '', Str::uuid());

        $client_id = '';
        for ($i = 0; $i < 8; $i++) {
            $s = Str::substr($uuid, $i * 4, $i * 4 + 4);
            $client_id .= self::CHARS[base_convert($s, 16, 10) % 0x3e];
        }
        return $client_id;
    }

    /**
     * 通过client_id获取client_secret
     * @param string $client_id
     * @return string
     */
    public function getClientSecret(string $client_id) : string
    {
        return sha1($client_id . Str::uuid());
    }

    /**
     * 使用client_id和secret获得access_token
     * @param Request $request
     * @return JsonResponse
     */
    public function getAccessToken(Request $request): JsonResponse
    {
        if (!$request->has('client_id')) {
            return Response::successWithCode(ErrorCode::MISSING_CLIENT_ID, ErrorCode::$messages[ErrorCode::MISSING_CLIENT_ID]);
        }

        if (!$request->has('client_secret')) {
            return Response::successWithCode(ErrorCode::MISSING_CLIENT_SECRET, ErrorCode::$messages[ErrorCode::MISSING_CLIENT_SECRET]);
        }

        $conditions = $request->only(['client_id', 'client_secret']);

        $client = ClientMap::where($conditions)->first();

        if (!$client) {
            return Response::successWithCode(ErrorCode::INVALID_CLIENT_ID, ErrorCode::$messages[ErrorCode::INVALID_CLIENT_ID]);
        }

        if (!$client->status) {
            return Response::successWithCode(ErrorCode::API_NOT_AUTHORIZED, ErrorCode::$messages[ErrorCode::API_NOT_AUTHORIZED]);
        }

        $redis = RedisClient::instance();
        $access_token = '';
        if ($client->access_token) {
            if ($redis->exists(self::TOKEN_PREFIX . $client->access_token)) {
                $access_token = $client->access_token;
            }
        }

        if (empty($access_token)) {
            $access_token = Str::uuid();
            //保存到redis和数据表
            $redis->setex(self::TOKEN_PREFIX . $access_token, self::EXPIRE_IN, $client->client_id);
            $client->access_token = $access_token;
            $client->save();
        }

        return Response::successWithCode(ErrorCode::SERVER_OK,
            ErrorCode::$messages[ErrorCode::SERVER_OK],
            [
                'access_token' => $access_token,
                'expire_in'    => self::EXPIRE_IN
            ]
        );
    }

    public function test()
    {
        $params = [
            time(),
            rand(10000, 999999),
            'i85ShUQ6'
        ];
        sort($params, SORT_STRING);

        return [$params, sha1(join('&', $params))];
    }
}