C# DocuSign服务集成live帐户可以';不认证

C# DocuSign服务集成live帐户可以';不认证,c#,docusignapi,C#,Docusignapi,我已经构建了一个DocuSign集成,它可以很好地与沙盒帐户配合使用,但是我在使用live帐户时遇到了问题。我在用电话。我将授权码授权用于模拟。调试显示创建了一个LoginInformation对象,但它的LoginAccounts属性为null,这当然会中断代码,以获取后续API调用的相应基本URL。有什么建议吗 public static ApiClient GetDocuSignClient() { string accountType = SettingsKeyInfoProvi

我已经构建了一个DocuSign集成,它可以很好地与沙盒帐户配合使用,但是我在使用live帐户时遇到了问题。我在用电话。我将授权码授权用于模拟。调试显示创建了一个
LoginInformation
对象,但它的LoginAccounts属性为null,这当然会中断代码,以获取后续API调用的相应基本URL。有什么建议吗

public static ApiClient GetDocuSignClient()
{
    string accountType = SettingsKeyInfoProvider.GetValue(SiteContext.CurrentSiteName + ".DocuSignAccountType");
    string integratorKey = SettingsKeyInfoProvider.GetValue(SiteContext.CurrentSiteName + ".DocuSignIntegratorKey");
    string userID = SettingsKeyInfoProvider.GetValue(SiteContext.CurrentSiteName + ".DocuSignUserID");
    string rsaPrivate = SettingsKeyInfoProvider.GetValue(SiteContext.CurrentSiteName + ".DocuSignRSAKey");
    string basePath = accountType == "sandbox" ? "account-d.docusign.com" : "account.docusign.com";
    // this gets replaced when we communicate with the api
    string clientBasePath = accountType == "sandbox" ? "https://demo.docusign.net/restapi" : "https://www.docusign.net/restapi";
    int expirationHours = 1;

    if (accountType == "" || integratorKey == "" || userID == "" || rsaPrivate == "")
        throw new System.Configuration.ConfigurationErrorsException("All DocuSign settings must be set in Settings->Integration->DocuSign");

    ApiClient dsClient = new ApiClient(clientBasePath);
    dsClient.ConfigureJwtAuthorizationFlow(integratorKey, userID, basePath, HttpContext.Current.Server.MapPath(rsaPrivate), expirationHours);


    AuthenticationApi authClient = new AuthenticationApi(dsClient.Configuration);
    LoginInformation loginInfo = authClient.Login();

    // find the default account for this user
    foreach (LoginAccount loginAcct in loginInfo.LoginAccounts)
    {
      ...
此外,对于OAUTH(和JWT),您不应该使用登录信息API,而是需要使用API调用来获取基本URI。一旦获得了基本URI,就可以使用该基本URI访问所有其他与身份验证无关的API。演示环境仅位于一个数据中心,因此使用您当前的代码,它在沙箱中运行良好,但PROD有多个数据中心,如NA1、NA2、NA3、EU1,并且您的帐户可以位于其中任何一个数据中心,因此要知道用于创建信封的数据中心的确切URI,您需要使用API调用来了解基本URI


当前在代码中,您已经硬编码了BaseUri(或客户端基本路径)
clientBasePath=https://www.docusign.net/restapi
,在这个硬编码中,您假设您的PROD帐户在NA1中,但正如我前面提到的,它也可以在任何其他数据中心中,因此请将代码更改为调用userinfo/API调用。我们的SDK错误地编写了这段代码(错误地调用LoginInformation而不是userinfo/),我已经将其报告给DS开发中心团队以修复此流程。

我在DocuSign API文档中发现了错误或非常误导性的陈述。似乎oauth/userinfo调用以不同的格式为沙盒和live帐户返回帐户的基本URL。下面的代码有点凌乱,但它同时适用于这两种情况

public static ApiClient GetDocuSignClient()
{
    string accountType = SettingsKeyInfoProvider.GetValue(SiteContext.CurrentSiteName + ".DocuSignAccountType");
    string integratorKey = SettingsKeyInfoProvider.GetValue(SiteContext.CurrentSiteName + ".DocuSignIntegratorKey");
    string userID = SettingsKeyInfoProvider.GetValue(SiteContext.CurrentSiteName + ".DocuSignUserID");
    string rsaPrivate = SettingsKeyInfoProvider.GetValue(SiteContext.CurrentSiteName + ".DocuSignRSAKey");
    string basePath = accountType == "sandbox" ? "account-d.docusign.com" : "account.docusign.com";
    // this gets replaced when we communicate with the api
    string clientBasePath = accountType == "sandbox" ? "https://demo.docusign.net/restapi" : "https://www.docusign.net/restapi";
    int expirationHours = 1;

    if (accountType == "" || integratorKey == "" || userID == "" || rsaPrivate == "")
        throw new System.Configuration.ConfigurationErrorsException("All DocuSign settings must be set in Settings->Integration->DocuSign");

    ApiClient dsClient = new ApiClient(clientBasePath);
    dsClient.ConfigureJwtAuthorizationFlow(integratorKey, userID, basePath, HttpContext.Current.Server.MapPath(rsaPrivate), expirationHours);

    var rsUserClient = new RestSharp.RestClient("https://" + basePath); ;
    RestSharp.RestRequest acctReq = new RestSharp.RestRequest();
    acctReq.Method = RestSharp.Method.GET;
    acctReq.RequestFormat = RestSharp.DataFormat.Json;
    acctReq.Resource = "oauth/userinfo";

    // even though we're not using the SDK to get accounts, we can use the token it generates
    AuthenticationApi authClient = new AuthenticationApi(dsClient.Configuration);
    acctReq.AddHeader("Authorization", authClient.Configuration.DefaultHeader["Authorization"]);


    RestSharp.IRestResponse rsResponse = rsUserClient.Execute(acctReq);
    if (rsResponse.ResponseStatus != RestSharp.ResponseStatus.Completed || rsResponse.StatusCode != HttpStatusCode.OK)
    {
        if (rsResponse.ErrorException != null)
            throw new WebException("DocuSign login failed: " + rsResponse.ErrorException.Message, rsResponse.ErrorException);
        else if (rsResponse.StatusCode == HttpStatusCode.BadRequest)
            throw new WebException(String.Format("DocuSign login failed. StatusCode: {0} <br/>ErrorDescription: {1}", rsResponse.StatusCode, rsResponse.Content));
        else
            throw new WebException(String.Format("DocuSign login failed. StatusCode: {0} ResponseStatus: {1}", rsResponse.StatusCode, rsResponse.ResponseStatus));
    }

    DocuSignLoginInfo loginInfo = JsonConvert.DeserializeObject<DocuSignLoginInfo>(rsResponse.Content);
    DocuSignLoginAccount toUse = null;
    foreach (var loginAcct in loginInfo.Accounts)
    {
        if (toUse == null)
        {
            toUse = loginAcct; // use first account
        }
        else if (loginAcct.IsDefault && 
            ((accountType == "sandbox" && loginAcct.Base_Uri.Contains("demo.")) || 
            (accountType != "sandbox" && !loginAcct.Base_Uri.Contains("demo."))))
        {
            toUse = loginAcct; // use default account if appropriate
        }

    }

    if (toUse == null)
    {
        throw new WebException("DocuSign login failed: " + loginInfo.Email + " doesn't have a login account we can use.");
    }
    else
    {
        SettingsKeyInfoProvider.SetValue("DocuSignAccountID", SiteContext.CurrentSiteName, toUse.Account_Id);

        string[] separatingStrings = { "/v2" };

        string restUrl = toUse.Base_Uri.Split(separatingStrings, StringSplitOptions.RemoveEmptyEntries)[0];
        if (!restUrl.Contains("/restapi"))
            restUrl += "/restapi";

        // Update ApiClient with the new base url from login call
        dsClient = new ApiClient(restUrl);
    }


    return dsClient;
}

public class DocuSignLoginAccount
{
    public string Account_Id;
    public string Account_Name;
    public bool IsDefault;
    public string Base_Uri;
}

public class EnvelopeBrief
{
    public string EnvID;
    public Signer CurrentSigner;
    public string ClientUserID;
}
publicstaticapiclient GetDocuSignClient()
{
string accountType=SettingsKeyInfoProvider.GetValue(SiteContext.CurrentSiteName+“.DocuSignAccountType”);
string integratorKey=SettingsKeyInfoProvider.GetValue(SiteContext.CurrentSiteName+”.DocuSignIntegratorKey);
字符串userID=SettingsKeyInfoProvider.GetValue(SiteContext.CurrentSiteName+“.DocuSignUserID”);
字符串rsaPrivate=SettingsKeyInfoProvider.GetValue(SiteContext.CurrentSiteName+“.DocuSignRSAKey”);
字符串basePath=accountType==“sandbox”?“account-d.docusign.com”:“account.docusign.com”;
//当我们与api通信时,它被替换
字符串clientBasePath=accountType==“沙盒”?“https://demo.docusign.net/restapi" : "https://www.docusign.net/restapi";
int expirationHours=1;
如果(accountType==“”| | integratorKey==“”| | userID==“”| | rsaPrivate==“”)
抛出新的System.Configuration.ConfigurationErrorsException(“必须在设置->集成->文档签名中设置所有文档签名设置”);
ApiClient dsClient=新的ApiClient(clientBasePath);
dsClient.ConfigureJwtAuthorizationFlow(integratorKey、userID、basePath、HttpContext.Current.Server.MapPath(rsaPrivate)、expirationHours);
var rsUserClient=new RestSharp.RestClient(“https://“+basePath”);
RestSharp.RestRequest acctReq=新的RestSharp.RestRequest();
acctReq.Method=RestSharp.Method.GET;
acctReq.RequestFormat=RestSharp.DataFormat.Json;
acctReq.Resource=“oauth/userinfo”;
//即使我们不使用SDK获取帐户,我们也可以使用它生成的令牌
AuthenticationApi authClient=新的AuthenticationApi(dsClient.Configuration);
acctReq.AddHeader(“Authorization”,authClient.Configuration.DefaultHeader[“Authorization”]);
RestSharp.IRestResponse rsResponse=rsUserClient.Execute(acctReq);
if(rsResponse.ResponseStatus!=RestSharp.ResponseStatus.Completed | | rsResponse.StatusCode!=HttpStatusCode.OK)
{
if(rsResponse.ErrorException!=null)
抛出新的WebException(“DocuSign登录失败:+rsResponse.ErrorException.Message,rsResponse.ErrorException”);
else if(rsResponse.StatusCode==HttpStatusCode.BadRequest)
抛出新的WebException(String.Format(“DocuSign登录失败。状态码:{0}
错误描述:{1}”、rsResponse.StatusCode、rsResponse.Content)); 其他的 抛出新的WebException(String.Format(“DocuSign登录失败。状态码:{0}响应状态:{1}”,rsResponse.StatusCode,rsResponse.ResponseStatus)); } DocuSignLoginInfo loginInfo=JsonConvert.DeserializeObject(rsResponse.Content); DocuSignLoginAccount-tuse=null; foreach(loginInfo.Accounts中的var LoginAct) { 如果(使用==null) { toUse=LOGINACT;//使用第一个帐户 } else if(loginAcct.IsDefault&& ((accountType==“sandbox”&&loginAcct.Base_Uri.Contains(“demo”))|| (accountType!=“sandbox”&&!loginAcct.Base\u Uri.Contains(“demo”)) { toUse=LOGINACT;//如果合适,请使用默认帐户 } } 如果(使用==null) { 抛出新的WebException(“DocuSign登录失败:“+loginInfo.Email+”没有我们可以使用的登录帐户”); } 其他的 { SettingsKeyInfoProvider.SetValue(“DocuSignAccountID”,SiteContext.CurrentSiteName,usse.Account\u Id); 字符串[]分隔字符串={“/v2”}; string restUrl=use.Base_Uri.Split(分隔字符串、StringSplitOptions.RemoveEmptyEntries)[0]; 如果(!restUrl.Contains(“/restapi”)) restUrl+=“/restapi”; //从登录调用使用新的基本url更新ApiClient dsClient=新的ApiClient(restUrl); } 返回dsClient; } 公共类docusignloginacount { 公共字符串帐户Id; 公共字符串帐户名称; 公共福利是默认的; 公共字符串基Uri; } 公共类信封 { 公共字符串EnvID; 公共签名人; 公共字符串ClientUserID; }