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

.NET/C#调用DocuSign REST API获取信封的认证实现问题

纯C#控制台实现DocuSign JWT认证 + 获取信封文档(无封装类)

前提准备

确保你已安装以下NuGet包:

  • System.IdentityModel.Tokens.Jwt
  • Microsoft.IdentityModel.Tokens
  • System.Security.Cryptography

完整代码示例

using System;
using System.Net.Http;
using System.Text;
using System.Security.Cryptography;
using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.Tokens;
using System.Threading.Tasks;
using System.Collections.Generic;

namespace DocuSignDirectApiCall
{
    class Program
    {
        // 替换为你的实际配置
        private const string ClientId = "你的DocuSign Client ID";
        private const string ImpersonatedUserId = "要模拟的用户ID";
        private const string AccountId = "你的DocuSign账号ID";
        private const string EnvelopeId = "目标信封ID";
        private const string PrivateKeyPath = "private.key"; // 私钥文件路径
        private const string AuthServer = "account-d.docusign.com"; // 开发环境认证地址
        private const string RestApiBaseUrl = "https://demo.docusign.net/restapi/v2";

        static async Task Main(string[] args)
        {
            // 1. 生成JWT并获取访问Token
            string accessToken = await GetDocuSignAccessTokenAsync();

            // 2. 调用API获取信封文档
            await GetEnvelopeDocumentAsync(accessToken);
        }

        private static async Task<string> GetDocuSignAccessTokenAsync()
        {
            // 读取PEM格式私钥
            string privateKeyContent = await System.IO.File.ReadAllTextAsync(PrivateKeyPath);
            RSA rsa = RSA.Create();
            rsa.ImportFromPem(privateKeyContent.ToCharArray());

            // 构建JWT Token
            var jwtHandler = new JwtSecurityTokenHandler();
            var now = DateTime.UtcNow;

            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Issuer = ClientId,
                Audience = AuthServer,
                Expires = now.AddMinutes(1), // JWT有效期不能超过1分钟
                Subject = new System.Security.Claims.ClaimsIdentity(new[]
                {
                    new System.Security.Claims.Claim("sub", ImpersonatedUserId),
                    new System.Security.Claims.Claim("scope", "signature")
                }),
                SigningCredentials = new SigningCredentials(new RsaSecurityKey(rsa), SecurityAlgorithms.RsaSha256)
            };

            SecurityToken jwtToken = jwtHandler.CreateToken(tokenDescriptor);
            string jwtAssertion = jwtHandler.WriteToken(jwtToken);

            // 请求获取访问Token
            using var httpClient = new HttpClient();
            var requestContent = new FormUrlEncodedContent(new[]
            {
                new KeyValuePair<string, string>("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"),
                new KeyValuePair<string, string>("assertion", jwtAssertion)
            });

            var response = await httpClient.PostAsync($"https://{AuthServer}/oauth/token", requestContent);
            response.EnsureSuccessStatusCode();

            // 解析返回的Token(简单字符串分割,也可使用Newtonsoft.Json等库解析)
            string responseJson = await response.Content.ReadAsStringAsync();
            return responseJson.Split(new[] { "\"access_token\":\"" }, StringSplitOptions.None)[1].Split('"')[0];
        }

        private static async Task GetEnvelopeDocumentAsync(string accessToken)
        {
            using var httpClient = new HttpClient();
            httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken}");

            // 构建正确的API地址:必须使用AccountId而非ClientId
            string apiUrl = $"{RestApiBaseUrl}/accounts/{AccountId}/envelopes/{EnvelopeId}/documents/1";

            var response = await httpClient.GetAsync(apiUrl);
            response.EnsureSuccessStatusCode();

            // 将文档保存到本地
            byte[] documentBytes = await response.Content.ReadAsByteArrayAsync();
            await System.IO.File.WriteAllBytesAsync("envelope_document.pdf", documentBytes);

            Console.WriteLine("文档已成功保存为envelope_document.pdf");
        }
    }
}

关键修正说明

  1. 原生JWT实现:完全手动构建JWT并签名,不依赖任何DocuSign封装类
  2. API地址修正:原代码误用ClientId作为账号ID,需替换为DocuSign官方分配的AccountId
  3. 请求格式修正:GET接口不需要附加StringContent,否则会触发API参数错误
  4. 私钥处理:使用原生RSA类读取PEM格式私钥,符合DocuSign的认证要求

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 12:34:53