Canva API 与 Laravel 和 PHP 集成

问题描述 投票:0回答:1

我需要将 Canva API 与我的应用程序集成,所以我写:

public function canva()
{
    $client_id = 'asdasdasd'; // Replace with your Canva client ID
    $redirect_uri = 'https://example.com/redirect-canva'; // Your callback URI
    $scope = 'asset:write'; // Adjust scopes as necessary

    // Generate code_verifier and code_challenge
    $code_verifier = $this->generateCodeVerifier();
    $code_challenge = $this->generateCodeChallenge($code_verifier);

    // Store the code_verifier in session
    session(['code_verifier' => $code_verifier]);
    $state = bin2hex(random_bytes(16)); // Generate a random state
    session(['oauth_state' => $state]);

    // Build the authorization URL
    $authorization_url = 'https://www.canva.com/api/oauth/authorize?' . http_build_query([
        'response_type' => 'code',
        'client_id' => $client_id,
        'redirect_uri' => $redirect_uri,
        'scope' => $scope,
        'code_challenge' => $code_challenge,
        'code_challenge_method' => 'S256',
        'state' => $state,
    ]);

    // Redirect to Canva's OAuth page
    return redirect($authorization_url);
}

private function generateCodeVerifier($length = 128)
{
    return rtrim(strtr(base64_encode(random_bytes($length)), '+/', '-_'), '=');
}

private function generateCodeChallenge($code_verifier)
{
    return rtrim(strtr(base64_encode(hash('sha256', $code_verifier, true)), '+/', '-_'), '=');
}



public function redirect_canva(Request $request)
{
    // Retrieve the authorization code and state from the request
    $code = $request->input('code');
    $state = $request->input('state');

    // Retrieve the stored code_verifier and state from the session
    $stored_state = session('oauth_state');
    $code_verifier = session('code_verifier');  // Retrieve the same code_verifier

    // Ensure the state matches to prevent CSRF attacks
    if ($state !== $stored_state) {
        return response('Invalid state parameter', 400);
    }

    // Ensure the authorization code is present
    if (!$code) {
        return response('No authorization code found', 400);
    }

    // Canva API OAuth Token endpoint
    $token_url = "https://api.canva.com/rest/v1/oauth/token";

    // Base64-encode client_id:client_secret
    $client_id = 'asdasd'; // Replace with your actual Canva client ID
    $client_secret = 'asdasdasdasdasdasd'; // Replace with your actual Canva client secret
    $credentials = base64_encode("$client_id:$client_secret");

    // Construct the POST fields exactly like in the cURL command you provided
    $post_fields = "grant_type=authorization_code"
        . "&code_verifier=" . urlencode($code_verifier) // Properly URL encode the code_verifier
        . "&code=" . urlencode($code) // Properly URL encode the authorization code
        . "&redirect_uri=" . urlencode('https://example.com/redirect-canva'); // Properly URL encode the redirect_uri

    // Initialize cURL request
    $curl = curl_init();
    curl_setopt_array($curl, array(
      CURLOPT_URL => $token_url,
      CURLOPT_RETURNTRANSFER => true,
      CURLOPT_CUSTOMREQUEST => "POST",
      CURLOPT_HTTPHEADER => array(
        'Authorization: Basic ' . $credentials, // Base64-encoded client_id:client_secret
        'Content-Type: application/x-www-form-urlencoded',
      ),
      CURLOPT_POSTFIELDS => $post_fields, // Use raw POSTFIELDS string
    ));

    // Execute the cURL request
    $response = curl_exec($curl);
    $err = curl_error($curl);
    curl_close($curl);

    // Check for cURL errors
    if ($err) {
        return response('cURL Error: ' . htmlspecialchars($err), 500);
    }

    // Parse the response
    $response_data = json_decode($response, true);

    if (isset($response_data['access_token'])) {
        // Store the access token in the session or database
        session(['canva_access_token' => $response_data['access_token']]);

        // Redirect to a success page
        return redirect('/some-success-page'); // Replace with your desired redirection
    } else {
        // Output the full response for debugging
        return response('Error obtaining access token: ' . json_encode($response_data), 400);
    }
}

所以我实现了如下所示的所有内容:https://www.canva.dev/docs/connect/api-reference/authentication/generate-access-token/并且我收到了错误:

获取访问令牌时出错:
{“error”:“invalid_request”,“error_description”:“无效的代码验证器”}

这意味着代码验证器是错误的,但我存储在会话中。关于如何以其他方式解决这个问题有什么想法吗?

php laravel session
1个回答
0
投票

我花了一些时间才发现,但这是一个微妙的问题:

private function generateCodeVerifier($length = 128)
{
    return rtrim(strtr(base64_encode(random_bytes($length)), '+/', '-_'), '=');
}

将生成一个172字节长的字符串(由于base64编码)。代码验证器的长度必须在 43 到 128 字节之间。 因此,您希望

$length
介于 32 到 96 之间(含 32 和 96)。

PHP 交互式 shell 中的长度示例:

php > echo strlen(rtrim(strtr(base64_encode(random_bytes(32)), '+/', '-_'), '='));
43
php > echo strlen(rtrim(strtr(base64_encode(random_bytes(96)), '+/', '-_'), '='));
128
php > echo strlen(rtrim(strtr(base64_encode(random_bytes(128)), '+/', '-_'), '='));
171
© www.soinside.com 2019 - 2024. All rights reserved.