Skip to content

Commit 651cf90

Browse files
committed
branch for Paige to review
1 parent 354a2c6 commit 651cf90

6 files changed

Lines changed: 265 additions & 0 deletions

File tree

app/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@
111111
app.register_blueprint(esignature_views.eg036)
112112
app.register_blueprint(esignature_views.eg037)
113113
app.register_blueprint(esignature_views.eg038)
114+
app.register_blueprint(esignature_views.eg039)
114115
if "DYNO" in os.environ: # On Heroku?
115116
import logging
116117

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import base64
2+
from os import path
3+
4+
from docusign_esign import EnvelopesApi, RecipientViewRequest, Document, Signer, EnvelopeDefinition, SignHere, Tabs, \
5+
Recipients
6+
from flask import session, url_for, request
7+
8+
from ...consts import authentication_method, demo_docs_path, pattern, signer_client_id
9+
from ...docusign import create_api_client, DSClient
10+
from ...ds_config import DS_CONFIG
11+
12+
13+
class Eg039InPersonSigner:
14+
@staticmethod
15+
def get_args():
16+
"""Get request and session arguments"""
17+
# More data validation would be a good idea here
18+
# Strip anything other than characters listed
19+
# 1. Parse request arguments
20+
#response = DSClient.get_user(session["ds_access_token"])
21+
#print(response)
22+
host_name = "host_name"
23+
signer_name = "signer_name"
24+
envelope_args = {
25+
"host_email": "raileendr@gmail.com",
26+
"host_name": "Raileen",
27+
"signer_name": "Fred",
28+
"ds_return_url": url_for("ds.ds_return", _external=True),
29+
}
30+
args = {
31+
"account_id": session["ds_account_id"],
32+
"base_path": session["ds_base_path"],
33+
"access_token": session["ds_access_token"],
34+
"envelope_args": envelope_args
35+
}
36+
return args
37+
38+
@classmethod
39+
def worker(cls, args):
40+
"""
41+
1. Create the envelope request object
42+
2. Send the envelope
43+
3. Create the Recipient View request object
44+
4. Obtain the recipient_view_url for the embedded signing
45+
"""
46+
envelope_args = args["envelope_args"]
47+
# 1. Create the envelope request object
48+
envelope_definition = cls.make_envelope(envelope_args)
49+
50+
# 2. call Envelopes::create API method
51+
# Exceptions will be caught by the calling function
52+
api_client = create_api_client(base_path=args["base_path"], access_token=args["access_token"])
53+
54+
envelope_api = EnvelopesApi(api_client)
55+
results = envelope_api.create_envelope(account_id=args["account_id"], envelope_definition=envelope_definition)
56+
57+
envelope_id = results.envelope_id
58+
59+
# 3. Create the Recipient View request object
60+
recipient_view_request = RecipientViewRequest(
61+
authentication_method=authentication_method,
62+
client_user_id=envelope_args["signer_client_id"],
63+
recipient_id="1",
64+
return_url=envelope_args["ds_return_url"],
65+
user_name=envelope_args["host_name"],
66+
email=envelope_args["host_email"]
67+
)
68+
# 4. Obtain the recipient_view_url for the embedded signing
69+
# Exceptions will be caught by the calling function
70+
results = envelope_api.create_recipient_view(
71+
account_id=args["account_id"],
72+
envelope_id=envelope_id,
73+
recipient_view_request=recipient_view_request
74+
)
75+
76+
return {"envelope_id": envelope_id, "redirect_url": results.url}
77+
78+
@classmethod
79+
def make_envelope(cls, args):
80+
"""
81+
Creates envelope
82+
args -- parameters for the envelope:
83+
signer_email, signer_name, signer_client_id
84+
returns an envelope definition
85+
"""
86+
87+
# document 1 (pdf) has tag /sn1/
88+
#
89+
# The envelope has one recipient.
90+
# recipient 1 - signer
91+
with open(path.join(demo_docs_path, DS_CONFIG["doc_pdf"]), "rb") as file:
92+
content_bytes = file.read()
93+
base64_file_content = base64.b64encode(content_bytes).decode("ascii")
94+
95+
# Create the document model
96+
document = Document( # create the DocuSign document object
97+
document_base64=base64_file_content,
98+
name="Example document", # can be different from actual file name
99+
file_extension="pdf", # many different document types are accepted
100+
document_id=1 # a label used to reference the doc
101+
)
102+
103+
# Create the signer recipient model
104+
signer = Signer(
105+
# The signer
106+
host_name = args["host_name"],
107+
host_email = args["host_email"],
108+
signer_name = args["signer_name"],
109+
recipient_id="1",
110+
routing_order="1",
111+
112+
# Setting the client_user_id marks the signer as embedded
113+
#client_user_id=args["signer_client_id"]
114+
)
115+
116+
# Create a sign_here tab (field on the document)
117+
sign_here = SignHere(
118+
# DocuSign SignHere field/tab
119+
anchor_string="/sn1/",
120+
anchor_units="pixels",
121+
anchor_y_offset="10",
122+
anchor_x_offset="20"
123+
)
124+
125+
# Add the tabs model (including the sign_here tab) to the signer
126+
# The Tabs object wants arrays of the different field/tab types
127+
signer.tabs = Tabs(sign_here_tabs=[sign_here])
128+
129+
# Next, create the top level envelope definition and populate it.
130+
envelope_definition = EnvelopeDefinition(
131+
email_subject="Please host this in-person signing session",
132+
documents=[document],
133+
# The Recipients object wants arrays for each recipient type
134+
recipients=Recipients(signers=[signer]),
135+
status="sent" # requests that the envelope be created and sent.
136+
)
137+
138+
return envelope_definition

app/eSignature/views/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@
3535
from .eg036_delayed_routing import eg036
3636
from .eg037_sms_delivery import eg037
3737
from .eg038_responsive_signing import eg038
38+
from .eg039_in_person_signer import eg039
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
""" Example 039: In Person Signer """
2+
3+
from os import path
4+
5+
from docusign_esign.client.api_exception import ApiException
6+
from flask import render_template, session, Blueprint, request
7+
8+
from ..examples.eg039_in_person_signer import Eg039InPersonSigner
9+
from ...docusign import authenticate
10+
from ...ds_config import DS_CONFIG
11+
from ...error_handlers import process_error
12+
from ...consts import pattern
13+
14+
eg = "eg039" # reference (and url) for this example
15+
eg039 = Blueprint("eg039", __name__)
16+
17+
# def get_args():
18+
# """Get request and session arguments"""
19+
20+
# # More data validation would be a good idea here
21+
# # Strip anything other than characters listed
22+
# host_email = pattern.sub("", session.get("host_email"))
23+
# host_name = pattern.sub("", session.get("host_name"))
24+
# signer_email = pattern.sub("", session.get("signer_email"))
25+
# signer_name = pattern.sub("", session.get("signer_name"))
26+
# envelope_args = {
27+
# "host_email": host_email,
28+
# "host_name": host_name,
29+
# #"signer_email": signer_email,
30+
# "signer_name": signer_name,
31+
# "status": "sent",
32+
# }
33+
# args = {
34+
# "account_id": session["ds_account_id"],
35+
# "base_path": session["ds_base_path"],
36+
# "access_token": session["ds_access_token"],
37+
# "envelope_args": envelope_args
38+
# }
39+
# return args
40+
41+
@eg039.route("/eg039", methods=["POST"])
42+
@authenticate(eg=eg)
43+
def in_person_signer():
44+
"""
45+
1. Get required arguments
46+
2. Call the worker method
47+
3. Render success response with envelopeId
48+
"""
49+
50+
# 1. Get required arguments
51+
args = Eg039InPersonSigner.get_args()
52+
try:
53+
# 1. Call the worker method
54+
results = Eg039InPersonSigner.worker(args)
55+
except ApiException as err:
56+
return process_error(err)
57+
58+
session["envelope_id"] = results["envelope_id"] # Save for use by other examples which need an envelopeId
59+
60+
# 2. Render success response with envelopeId
61+
return render_template(
62+
"example_done.html",
63+
title="Envelope sent",
64+
h1="Envelope sent",
65+
message=f"The envelope has been created and sent!<br/>Envelope ID {results['envelope_id']}."
66+
)
67+
68+
69+
@eg039.route("/eg039", methods=["GET"])
70+
@authenticate(eg=eg)
71+
def get_view():
72+
"""responds with the form for the example"""
73+
74+
return render_template(
75+
"eg039_in_person_signer.html",
76+
title="Signing via email",
77+
source_file="eg039_in_person_signer.py",
78+
source_url=DS_CONFIG["github_example_url"] + "eg039_in_person_signer.py",
79+
documentation=DS_CONFIG["documentation"] + eg,
80+
show_doc=DS_CONFIG["documentation"],
81+
signer_name=DS_CONFIG["signer_name"],
82+
#signer_email=DS_CONFIG["signer_email"]
83+
)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<!-- extend base layout --> {% extends "base.html" %} {% block content %}
2+
3+
<h4>Send an envelope to an In Person Signer</h4>
4+
<p>Demonstrates how to host an In Person Signing session with embedded signing.</p>
5+
6+
{% if show_doc %}
7+
<p><a target='_blank' href='{{ documentation | safe }}'>Documentation</a> about this example.</p>
8+
{% endif %}
9+
10+
<p>API method used:
11+
<a target ='_blank' href="https://developers.docusign.com/docs/esign-rest-api/reference/envelopes/envelopes/create/">Envelopes::create</a> and
12+
<a target ='_blank' href="https://developers.docusign.com/docs/esign-rest-api/reference/envelopes/envelopeviews/createrecipient/">EnvelopeViews::createRecipient</a>.
13+
</p>
14+
15+
<p>
16+
View source file <a target="_blank" href="{{ source_url | safe }}">{{ source_file }}</a> on GitHub.
17+
</p>
18+
19+
<form class="eg" action="" method="post" data-busy="form">
20+
<div class="form-group">
21+
<label for="signerName">Signer Name</label>
22+
<input type="text" class="form-control" id="signerName" placeholder="Pat Johnson" name="signerName"
23+
required />
24+
</div>
25+
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
26+
<button type="submit" class="btn btn-docu">Submit</button>
27+
</form>
28+
29+
30+
{% endblock %}

app/templates/home.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,18 @@ <h4 id="example038">38. <a href="eg038">Create a signable HTML document</a></h4>
376376
href="https://developers.docusign.com/docs/esign-rest-api/reference/envelopes/envelopeviews/createrecipient/">EnvelopeViews::createRecipient</a>.
377377
</p>
378378

379+
<h2>In person signing</h2>
380+
381+
<h4 id="example039"><a href="eg039">Send an envelope to an In Person Signer</a></h4>
382+
<p>
383+
Demonstrates how to host an In Person Signing session with embedded signing.
384+
<p>
385+
API methods used:
386+
<a target="_blank" href="https://developers.docusign.com/docs/esign-rest-api/reference/envelopes/envelopes/create/">Envelopes::create</a>,
387+
<a target='_blank'
388+
href="https://developers.docusign.com/docs/esign-rest-api/reference/envelopes/envelopeviews/createrecipient/">EnvelopeViews::createRecipient</a>.
389+
</p>
390+
379391
</div>
380392

381393
<!-- anchor-js is only for the index page -->

0 commit comments

Comments
 (0)