コード例 #1
0
    protected override async Task <OAuthTokenResponse> ExchangeCodeAsync([NotNull] OAuthCodeExchangeContext context)
    {
        // See https://opendocs.alipay.com/apis/api_9/alipay.system.oauth.token for details.
        var tokenRequestParameters = new SortedDictionary <string, string?>()
        {
            ["app_id"]     = Options.ClientId,
            ["charset"]    = "utf-8",
            ["code"]       = context.Code,
            ["format"]     = "JSON",
            ["grant_type"] = "authorization_code",
            ["method"]     = "alipay.system.oauth.token",
            ["sign_type"]  = "RSA2",
            ["timestamp"]  = Clock.UtcNow.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture),
            ["version"]    = "1.0",
        };

        tokenRequestParameters.Add("sign", GetRSA2Signature(tokenRequestParameters));

        // PKCE https://tools.ietf.org/html/rfc7636#section-4.5, see BuildChallengeUrl
        if (context.Properties.Items.TryGetValue(OAuthConstants.CodeVerifierKey, out var codeVerifier))
        {
            tokenRequestParameters.Add(OAuthConstants.CodeVerifierKey, codeVerifier);
            context.Properties.Items.Remove(OAuthConstants.CodeVerifierKey);
        }

        var address = QueryHelpers.AddQueryString(Options.TokenEndpoint, tokenRequestParameters);

        using var response = await Backchannel.GetAsync(address, HttpCompletionOption.ResponseHeadersRead, Context.RequestAborted);

        if (!response.IsSuccessStatusCode)
        {
            await Log.AccessTokenError(Logger, response, Context.RequestAborted);

            return(OAuthTokenResponse.Failed(new Exception("An error occurred while retrieving an access token.")));
        }

        using var stream = await response.Content.ReadAsStreamAsync(Context.RequestAborted);

        using var document = JsonDocument.Parse(stream);

        var mainElement = document.RootElement.GetProperty("alipay_system_oauth_token_response");

        if (!ValidateReturnCode(mainElement, out var code))
        {
            return(OAuthTokenResponse.Failed(new Exception($"An error (Code:{code}) occurred while retrieving an access token.")));
        }

        var payload = JsonDocument.Parse(mainElement.GetRawText());

        return(OAuthTokenResponse.Success(payload));
    }