C# DocuSign API:在 Docusign 上拉取服务器模板而不是本地模板文档
C# DocuSign API: Pulling server template instead of local template document on Docusign
我目前正在构建一个可用的 C# 项目,但我想从记录的服务器模板(托管在 docusign.com)而不是文档的本地模板副本(在我的计算机)。
我正在使用快速入门 C# 代码,但在尝试使其正常工作并用模板 ID 序列替换“World_Wide_Corp_fields.pdf”默认文件时卡住了:
更新:使用 Code-Samples-CSharp 中的 eg001 C# 代码作为基础(而不是快速入门 C# 代码)。
下面是 eg001 与 eg009 的组合,因此有一个使用服务器模板的嵌入式工作流程。
namespace eg_03_csharp_auth_code_grant_core.Views
{
[Route("eg001")]
public class Eg001EmbeddedSigningController : EgController
{
private string dsPingUrl;
private string signerClientId = "1000";
private string dsReturnUrl;
public Eg001EmbeddedSigningController(DSConfiguration config, IRequestItemsService requestItemsService)
: base(config, requestItemsService)
{
dsPingUrl = config.AppUrl + "/";
dsReturnUrl = config.AppUrl + "/dsReturn";
ViewBag.title = "Embedded Signing Ceremony";
}
// ***DS.snippet.0.start
private string DoWork(string signerEmail, string signerName,
string accessToken, string basePath, string accountId, string templateId)
{
// Data for this method
// signerEmail
// signerName
// accessToken
// basePath
// accountId
// templateId
// dsPingUrl -- class global
// signerClientId -- class global
// dsReturnUrl -- class global
// Step 1. Create the envelope definition
EnvelopeDefinition envelope = MakeEnvelope(signerEmail, signerName, ccEmail, ccName, templateId);
// Step 2. Call DocuSign to create the envelope
var config = new Configuration(new ApiClient(basePath));
config.AddDefaultHeader("Authorization", "Bearer " + accessToken);
EnvelopesApi envelopesApi = new EnvelopesApi(config);
EnvelopeSummary result = envelopesApi.CreateEnvelope(accountId, envelope);
return result.EnvelopeId;
}
// Save for future use within the example launcher
RequestItemsService.EnvelopeId = envelopeId;
// Step 3. create the recipient view, the Signing Ceremony
RecipientViewRequest viewRequest = MakeRecipientViewRequest(signerEmail, signerName);
// call the CreateRecipientView API
ViewUrl results1 = envelopesApi.CreateRecipientView(accountId, envelopeId, viewRequest);
// Step 4. Redirect the user to the Signing Ceremony
// Don't use an iFrame!
// State can be stored/recovered using the framework's session or a
// query parameter on the returnUrl (see the makeRecipientViewRequest method)
string redirectUrl = results1.Url;
return redirectUrl;
}
private RecipientViewRequest MakeRecipientViewRequest(string signerEmail, string signerName)
{
// Data for this method
// signerEmail
// signerName
// dsPingUrl -- class global
// signerClientId -- class global
// dsReturnUrl -- class global
RecipientViewRequest viewRequest = new RecipientViewRequest();
// Set the url where you want the recipient to go once they are done signing
// should typically be a callback route somewhere in your app.
// The query parameter is included as an example of how
// to save/recover state information during the redirect to
// the DocuSign signing ceremony. It's usually better to use
// the session mechanism of your web framework. Query parameters
// can be changed/spoofed very easily.
viewRequest.ReturnUrl = dsReturnUrl + "?state=123";
// How has your app authenticated the user? In addition to your app's
// authentication, you can include authenticate steps from DocuSign.
// Eg, SMS authentication
viewRequest.AuthenticationMethod = "none";
// Recipient information must match embedded recipient info
// we used to create the envelope.
viewRequest.Email = signerEmail;
viewRequest.UserName = signerName;
viewRequest.ClientUserId = signerClientId;
// DocuSign recommends that you redirect to DocuSign for the
// Signing Ceremony. There are multiple ways to save state.
// To maintain your application's session, use the pingUrl
// parameter. It causes the DocuSign Signing Ceremony web page
// (not the DocuSign server) to send pings via AJAX to your
// app,
viewRequest.PingFrequency = "600"; // seconds
// NOTE: The pings will only be sent if the pingUrl is an https address
viewRequest.PingUrl = dsPingUrl; // optional setting
return viewRequest;
}
private EnvelopeDefinition MakeEnvelope(string signerEmail, string signerName, string ccEmail, string ccName, string templateId)
{
// Data for this method
// signerEmail
// signerName
// ccEmail
// ccName
// signerClientId -- class global
// Config.docPdf replaced with templateId
EnvelopeDefinition envelopeDefinition = new EnvelopeDefinition();
envelopeDefinition.TemplateId = templateId;
envelopeDefinition.EmailSubject = "Please sign this document";
// The order in the docs array determines the order in the envelope
envelopeDefinition.Documents = new List<Document> { doc1 };
// Create a signer recipient to sign the document, identified by name and email
// We set the clientUserId to enable embedded signing for the recipient
// We're setting the parameters via the object creation
TemplateRole signer1 = new TemplateRole
{
Email = signerEmail,
Name = signerName,
ClientUserId = signerClientId,
RecipientId = "1"
RoleName = "signer";
TemplateRole cc1 = new TemplateRole();
cc1.Email = ccEmail;
cc1.Name = ccName;
cc1.RoleName = "cc";
// Create signHere fields (also known as tabs) on the documents,
// We're using anchor (autoPlace) positioning
//
// The DocuSign platform seaches throughout your envelope's
// documents for matching anchor strings.
SignHere signHere1 = new SignHere
{
AnchorString = "/sn1/",
AnchorUnits = "pixels",
AnchorXOffset = "10",
AnchorYOffset = "20"
};
// Tabs are set per recipient / signer
Tabs signer1Tabs = new Tabs
{
SignHereTabs = new List<SignHere> { signHere1 }
};
signer1.Tabs = signer1Tabs;
// Add the recipient to the envelope object
Recipients recipients = new Recipients
{
Signers = new List<TemplateRole> { signer1 }
};
envelopeDefinition.Recipients = recipients;
// Request that the envelope be sent by setting |status| to "sent".
// To request that the envelope be created as a draft, set to "created"
envelopeDefinition.Status = "sent";
return envelopeDefinition;
}
// ***DS.snippet.0.end
public override string EgName => "eg001";
[HttpPost]
public IActionResult Create(string signerEmail, string signerName)
{
// Data for this method
// signerEmail
// signerName
// dsPingUrl -- class global
// signerClientId -- class global
// dsReturnUrl -- class global
var accessToken = RequestItemsService.User.AccessToken;
var basePath = RequestItemsService.Session.BasePath + "/restapi";
var accountId = RequestItemsService.Session.AccountId;
var templateId = RequestItemsService.TemplateId;
// Check the token with minimal buffer time.
bool tokenOk = CheckToken(3);
if (!tokenOk)
{
// We could store the parameters of the requested operation
// so it could be restarted automatically.
// But since it should be rare to have a token issue here,
// we'll make the user re-enter the form data after
// authentication.
RequestItemsService.EgName = EgName;
return Redirect("/ds/mustAuthenticate");
}
string redirectUrl = DoWork(signerEmail, signerName, accessToken, basePath, accountId, templateId);
// Redirect the user to the Signing Ceremony
return Redirect(redirectUrl);
}
}
}
参考资料
对于这种情况,还有一个代码示例。 Using a template to create an envelope.
这是 C# 代码的片段:
private EnvelopeDefinition MakeEnvelope(string signerEmail, string signerName,
string ccEmail, string ccName, string templateId)
{
// Data for this method
// signerEmail
// signerName
// ccEmail
// ccName
// templateId
EnvelopeDefinition env = new EnvelopeDefinition();
env.TemplateId = templateId;
TemplateRole signer1 = new TemplateRole();
signer1.Email = signerEmail;
signer1.Name = signerName;
signer1.RoleName = "signer";
TemplateRole cc1 = new TemplateRole();
cc1.Email = ccEmail;
cc1.Name = ccName;
cc1.RoleName = "cc";
env.TemplateRoles = new List<TemplateRole> { signer1, cc1 };
env.Status = "sent";
return env;
}
我目前正在构建一个可用的 C# 项目,但我想从记录的服务器模板(托管在 docusign.com)而不是文档的本地模板副本(在我的计算机)。
我正在使用快速入门 C# 代码,但在尝试使其正常工作并用模板 ID 序列替换“World_Wide_Corp_fields.pdf”默认文件时卡住了:
更新:使用 Code-Samples-CSharp 中的 eg001 C# 代码作为基础(而不是快速入门 C# 代码)。
下面是 eg001 与 eg009 的组合,因此有一个使用服务器模板的嵌入式工作流程。
namespace eg_03_csharp_auth_code_grant_core.Views
{
[Route("eg001")]
public class Eg001EmbeddedSigningController : EgController
{
private string dsPingUrl;
private string signerClientId = "1000";
private string dsReturnUrl;
public Eg001EmbeddedSigningController(DSConfiguration config, IRequestItemsService requestItemsService)
: base(config, requestItemsService)
{
dsPingUrl = config.AppUrl + "/";
dsReturnUrl = config.AppUrl + "/dsReturn";
ViewBag.title = "Embedded Signing Ceremony";
}
// ***DS.snippet.0.start
private string DoWork(string signerEmail, string signerName,
string accessToken, string basePath, string accountId, string templateId)
{
// Data for this method
// signerEmail
// signerName
// accessToken
// basePath
// accountId
// templateId
// dsPingUrl -- class global
// signerClientId -- class global
// dsReturnUrl -- class global
// Step 1. Create the envelope definition
EnvelopeDefinition envelope = MakeEnvelope(signerEmail, signerName, ccEmail, ccName, templateId);
// Step 2. Call DocuSign to create the envelope
var config = new Configuration(new ApiClient(basePath));
config.AddDefaultHeader("Authorization", "Bearer " + accessToken);
EnvelopesApi envelopesApi = new EnvelopesApi(config);
EnvelopeSummary result = envelopesApi.CreateEnvelope(accountId, envelope);
return result.EnvelopeId;
}
// Save for future use within the example launcher
RequestItemsService.EnvelopeId = envelopeId;
// Step 3. create the recipient view, the Signing Ceremony
RecipientViewRequest viewRequest = MakeRecipientViewRequest(signerEmail, signerName);
// call the CreateRecipientView API
ViewUrl results1 = envelopesApi.CreateRecipientView(accountId, envelopeId, viewRequest);
// Step 4. Redirect the user to the Signing Ceremony
// Don't use an iFrame!
// State can be stored/recovered using the framework's session or a
// query parameter on the returnUrl (see the makeRecipientViewRequest method)
string redirectUrl = results1.Url;
return redirectUrl;
}
private RecipientViewRequest MakeRecipientViewRequest(string signerEmail, string signerName)
{
// Data for this method
// signerEmail
// signerName
// dsPingUrl -- class global
// signerClientId -- class global
// dsReturnUrl -- class global
RecipientViewRequest viewRequest = new RecipientViewRequest();
// Set the url where you want the recipient to go once they are done signing
// should typically be a callback route somewhere in your app.
// The query parameter is included as an example of how
// to save/recover state information during the redirect to
// the DocuSign signing ceremony. It's usually better to use
// the session mechanism of your web framework. Query parameters
// can be changed/spoofed very easily.
viewRequest.ReturnUrl = dsReturnUrl + "?state=123";
// How has your app authenticated the user? In addition to your app's
// authentication, you can include authenticate steps from DocuSign.
// Eg, SMS authentication
viewRequest.AuthenticationMethod = "none";
// Recipient information must match embedded recipient info
// we used to create the envelope.
viewRequest.Email = signerEmail;
viewRequest.UserName = signerName;
viewRequest.ClientUserId = signerClientId;
// DocuSign recommends that you redirect to DocuSign for the
// Signing Ceremony. There are multiple ways to save state.
// To maintain your application's session, use the pingUrl
// parameter. It causes the DocuSign Signing Ceremony web page
// (not the DocuSign server) to send pings via AJAX to your
// app,
viewRequest.PingFrequency = "600"; // seconds
// NOTE: The pings will only be sent if the pingUrl is an https address
viewRequest.PingUrl = dsPingUrl; // optional setting
return viewRequest;
}
private EnvelopeDefinition MakeEnvelope(string signerEmail, string signerName, string ccEmail, string ccName, string templateId)
{
// Data for this method
// signerEmail
// signerName
// ccEmail
// ccName
// signerClientId -- class global
// Config.docPdf replaced with templateId
EnvelopeDefinition envelopeDefinition = new EnvelopeDefinition();
envelopeDefinition.TemplateId = templateId;
envelopeDefinition.EmailSubject = "Please sign this document";
// The order in the docs array determines the order in the envelope
envelopeDefinition.Documents = new List<Document> { doc1 };
// Create a signer recipient to sign the document, identified by name and email
// We set the clientUserId to enable embedded signing for the recipient
// We're setting the parameters via the object creation
TemplateRole signer1 = new TemplateRole
{
Email = signerEmail,
Name = signerName,
ClientUserId = signerClientId,
RecipientId = "1"
RoleName = "signer";
TemplateRole cc1 = new TemplateRole();
cc1.Email = ccEmail;
cc1.Name = ccName;
cc1.RoleName = "cc";
// Create signHere fields (also known as tabs) on the documents,
// We're using anchor (autoPlace) positioning
//
// The DocuSign platform seaches throughout your envelope's
// documents for matching anchor strings.
SignHere signHere1 = new SignHere
{
AnchorString = "/sn1/",
AnchorUnits = "pixels",
AnchorXOffset = "10",
AnchorYOffset = "20"
};
// Tabs are set per recipient / signer
Tabs signer1Tabs = new Tabs
{
SignHereTabs = new List<SignHere> { signHere1 }
};
signer1.Tabs = signer1Tabs;
// Add the recipient to the envelope object
Recipients recipients = new Recipients
{
Signers = new List<TemplateRole> { signer1 }
};
envelopeDefinition.Recipients = recipients;
// Request that the envelope be sent by setting |status| to "sent".
// To request that the envelope be created as a draft, set to "created"
envelopeDefinition.Status = "sent";
return envelopeDefinition;
}
// ***DS.snippet.0.end
public override string EgName => "eg001";
[HttpPost]
public IActionResult Create(string signerEmail, string signerName)
{
// Data for this method
// signerEmail
// signerName
// dsPingUrl -- class global
// signerClientId -- class global
// dsReturnUrl -- class global
var accessToken = RequestItemsService.User.AccessToken;
var basePath = RequestItemsService.Session.BasePath + "/restapi";
var accountId = RequestItemsService.Session.AccountId;
var templateId = RequestItemsService.TemplateId;
// Check the token with minimal buffer time.
bool tokenOk = CheckToken(3);
if (!tokenOk)
{
// We could store the parameters of the requested operation
// so it could be restarted automatically.
// But since it should be rare to have a token issue here,
// we'll make the user re-enter the form data after
// authentication.
RequestItemsService.EgName = EgName;
return Redirect("/ds/mustAuthenticate");
}
string redirectUrl = DoWork(signerEmail, signerName, accessToken, basePath, accountId, templateId);
// Redirect the user to the Signing Ceremony
return Redirect(redirectUrl);
}
}
}
参考资料
对于这种情况,还有一个代码示例。 Using a template to create an envelope. 这是 C# 代码的片段:
private EnvelopeDefinition MakeEnvelope(string signerEmail, string signerName,
string ccEmail, string ccName, string templateId)
{
// Data for this method
// signerEmail
// signerName
// ccEmail
// ccName
// templateId
EnvelopeDefinition env = new EnvelopeDefinition();
env.TemplateId = templateId;
TemplateRole signer1 = new TemplateRole();
signer1.Email = signerEmail;
signer1.Name = signerName;
signer1.RoleName = "signer";
TemplateRole cc1 = new TemplateRole();
cc1.Email = ccEmail;
cc1.Name = ccName;
cc1.RoleName = "cc";
env.TemplateRoles = new List<TemplateRole> { signer1, cc1 };
env.Status = "sent";
return env;
}