集成eBay OAuth API时无法用authorization_code换取access_token
解决eBay OAuth授权码交换access_token时的invalid_grant错误
问题描述
在C#应用中集成eBay沙箱OAuth API,使用authorization_code交换access_token时,持续收到以下错误:
{ "error": "invalid_grant", "error_description": "the provided authorization grant code is invalid or was issued to another client" }
当前实现流程:
- 生成授权URL引导用户登录授权,获取authorization_code:
string authCodeUrl = BuildAuthorizationUrl(); Console.WriteLine($"Please visit this URL to provide consent: {authCodeUrl}"); System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName = authCodeUrl, UseShellExecute = true });
- 用户手动输入授权码后,调用以下方法交换令牌:
public async Task<string> GetAccessTokenAsync(string authorizationCode) { string tokenUrl = "https://api.sandbox.ebay.com/identity/v1/oauth2/token"; string clientId = "<Your Client ID>"; string clientSecret = "<Your Client Secret>"; string redirectUri = "http://localhost:8080/"; // Must match the redirect URI in eBay app settings using (var client = new HttpClient()) { var authHeader = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{clientId}:{clientSecret}")); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authHeader); var parameters = new Dictionary<string, string> { { "grant_type", "authorization_code" }, { "code", authorizationCode }, { "redirect_uri", redirectUri } }; var content = new FormUrlEncodedContent(parameters); var response = await client.PostAsync(tokenUrl, content); string responseBody = await response.Content.ReadAsStringAsync(); if (!response.IsSuccessStatusCode) { Console.WriteLine($"Error: {responseBody}"); throw new Exception($"Error retrieving the access token. Response: {responseBody}"); } var tokenResponse = JsonConvert.DeserializeObject<AccessTokenResponse>(responseBody); return tokenResponse.access_token; } }
预期成功响应格式:
{ "access_token": "v^1.1#i^1#p^3#r^1...XzMjRV4xMjg0", "expires_in": 7200, "refresh_token": "v^1.1#i^1#p^3#r^1...zYjRV4xMjg0", "refresh_token_expires_in": 47304000, "token_type": "User Access Token" }
排查与解决步骤
验证授权码有效性
- 授权码仅能使用一次,若之前尝试过交换令牌,必须重新获取新的授权码。
- 手动输入时易出现字符遗漏、多余空格或换行,建议直接复制粘贴授权码,避免手动输入错误。
确保Client凭证与环境匹配
- 沙箱环境与生产环境的Client ID/Secret完全独立,确认使用的是沙箱环境的凭证(因为令牌请求地址是沙箱的
api.sandbox.ebay.com)。 - 检查Client ID和Secret是否完整复制,无拼写错误或字符截断。
- 沙箱环境与生产环境的Client ID/Secret完全独立,确认使用的是沙箱环境的凭证(因为令牌请求地址是沙箱的
严格匹配Redirect URI
- 生成授权URL时的
redirect_uri必须与令牌交换时的redirect_uri完全一致,包括末尾的斜杠、端口、大小写(例如你代码中用的http://localhost:8080/,授权URL里的参数也要完全相同)。 - 同时要与eBay开发者平台中应用设置的Redirect URI完全匹配,任何细微差异都会导致错误。
- 生成授权URL时的
检查授权URL生成逻辑
- 确认
BuildAuthorizationUrl生成的URL包含正确参数:client_id为沙箱Client IDresponse_type必须是coderedirect_uri与后续交换时一致scope符合应用申请的权限范围
- 正确的沙箱授权URL示例:
https://auth.sandbox.ebay.com/oauth2/authorize?client_id=YOUR_SANDBOX_CLIENT_ID&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&response_type=code&scope=https%3A%2F%2Fapi.ebay.com%2Foauth%2Fapi_scope%2Fsell.inventory
- 确认
确认请求格式正确性
- Basic Auth编码使用
Encoding.ASCII是正确的,避免使用UTF-8编码导致凭证解析错误。 - 表单参数
grant_type必须为authorization_code,code参数值为用户提供的授权码,无额外修改。
- Basic Auth编码使用
保持环境一致性
- 授权URL必须使用沙箱的授权地址
https://auth.sandbox.ebay.com,令牌请求使用沙箱的令牌地址,不能混用生产环境地址。
- 授权URL必须使用沙箱的授权地址
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

