You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解决.NET Core WebApi调用Zoho CRM图片API的令牌时效问题

解决.NET Core WebApi可靠调用Zoho CRM API的方案

核心问题

Self Client生成的是短期临时令牌,仅适用于测试场景,完全不适合服务器端长期自动化调用。服务器端应用必须采用Server-Based OAuth认证流程,通过刷新令牌机制获取持久有效的访问凭证。

分步实现方案

1. 创建正确类型的Zoho应用

登录Zoho开发者控制台,创建Server-Based Applications类型的应用(不要选Self Client):

  • 配置重定向URI:填写你后端可控的回调地址(例如https://your-api-domain.com/zoho-auth-callback),用于接收授权码
  • 记录生成的Client ID和Client Secret

2. 首次获取授权码与刷新令牌

  • 构造授权URL,让Zoho账户管理员访问:
    https://accounts.zoho.com/oauth/v2/auth?scope=ZohoCRM.modules.ALL&client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=YOUR_REDIRECT_URI&access_type=offline
    
    关键参数:access_type=offline必须设置,这样才能拿到长期有效的刷新令牌;scope要覆盖CRM模块权限,用ZohoCRM.modules.ALL确保包含图片访问权限
  • 管理员授权后,Zoho会重定向到你的回调地址,携带code参数
  • 在回调接口中,用code调用令牌接口获取凭证:
    POST https://accounts.zoho.com/oauth/v2/token
    Content-Type: application/x-www-form-urlencoded
    
    code=AUTHORIZATION_CODE&client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&redirect_uri=YOUR_REDIRECT_URI&grant_type=authorization_code
    
    响应中会得到access_token(有效期1小时)和refresh_token(长期有效,除非手动撤销),把refresh_token安全存储到数据库或配置中心

3. .NET Core中实现自动令牌刷新

封装Zoho API客户端,自动处理令牌过期:

public class ZohoCrmClient
{
    private readonly string _clientId;
    private readonly string _clientSecret;
    private readonly string _refreshToken;
    private string _accessToken;
    private DateTime _tokenExpiry;
    private readonly HttpClient _httpClient;

    public ZohoCrmClient(string clientId, string clientSecret, string refreshToken)
    {
        _clientId = clientId;
        _clientSecret = clientSecret;
        _refreshToken = refreshToken;
        _httpClient = new HttpClient();
    }

    // 确保令牌有效,过期自动刷新
    private async Task EnsureValidToken()
    {
        if (string.IsNullOrEmpty(_accessToken) || DateTime.UtcNow >= _tokenExpiry)
        {
            var tokenResponse = await RefreshAccessToken();
            _accessToken = tokenResponse.AccessToken;
            _tokenExpiry = DateTime.UtcNow.AddSeconds(tokenResponse.ExpiresIn);
        }
    }

    // 刷新令牌
    private async Task<ZohoTokenResponse> RefreshAccessToken()
    {
        var formData = new FormUrlEncodedContent(new[]
        {
            new KeyValuePair<string, string>("refresh_token", _refreshToken),
            new KeyValuePair<string, string>("client_id", _clientId),
            new KeyValuePair<string, string>("client_secret", _clientSecret),
            new KeyValuePair<string, string>("grant_type", "refresh_token")
        });

        var response = await _httpClient.PostAsync("https://accounts.zoho.com/oauth/v2/token", formData);
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadFromJsonAsync<ZohoTokenResponse>();
    }

    // 下载账户图片
    public async Task<Stream> DownloadAccountImage(string accountRecordId, string imageFieldId)
    {
        await EnsureValidToken();
        _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _accessToken);
        
        var response = await _httpClient.GetAsync($"https://www.zohoapis.com/crm/v6/Accounts/{accountRecordId}/Image/{imageFieldId}");
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadAsStreamAsync();
    }

    // 令牌响应模型
    private class ZohoTokenResponse
    {
        [JsonPropertyName("access_token")]
        public string AccessToken { get; set; }
        [JsonPropertyName("expires_in")]
        public int ExpiresIn { get; set; }
    }
}

4. 图片下载API调用要点

  • 请求头必须携带Authorization: Bearer {access_token}
  • API路径格式:/crm/v6/Accounts/{record_id}/Image/{image_field_id},其中image_field_id是账户模块中存储图片的字段ID(例如默认的Picture字段ID)
  • 响应为图片流,直接读取后保存到你的存储系统即可

常见问题排查

  • 权限不足:确认授权时的scope包含CRM模块权限,建议用ZohoCRM.modules.ALL覆盖所有场景
  • 刷新令牌失效:若刷新令牌被撤销,需重新走授权流程获取新的刷新令牌
  • 区域适配:如果你的Zoho账户在特定区域(如中国、欧盟),需将API域名替换为对应区域的域名(例如zohoapis.cn、zohoapis.eu)

内容的提问来源于stack exchange,提问作者Choco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 00:40:59