Skip to content

Updating for October GA Release #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,4 @@ com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
.vscode/settings.json
12 changes: 6 additions & 6 deletions app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@
from flask_wtf.csrf import CSRFProtect


session_path = '/tmp/python_recipe_sessions'
session_path = "/tmp/python_recipe_sessions"

app = Flask(__name__)
app.config.from_pyfile('config.py')
app.secret_key = ds_config.DS_CONFIG['session_secret']
app.config.from_pyfile("config.py")
app.secret_key = ds_config.DS_CONFIG["session_secret"]
csrf = CSRFProtect(app) # See https://flask-wtf.readthedocs.io/en/stable/csrf.html

if 'DYNO' in os.environ: # On Heroku?
if "DYNO" in os.environ: # On Heroku?
import logging
stream_handler = logging.StreamHandler()
app.logger.addHandler(stream_handler)
app.logger.setLevel(logging.INFO)
app.logger.info('Recipe example startup')
app.config.update(dict(PREFERRED_URL_SCHEME = 'https'))
app.logger.info("Recipe example startup")
app.config.update(dict(PREFERRED_URL_SCHEME = "https"))

from app import views
35 changes: 18 additions & 17 deletions app/ds_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,28 @@
import os

DS_CONFIG = {
'ds_client_id': '{CLIENT_ID}', # The app's DocuSign integration key
'ds_client_secret': '{CLIENT_SECRET}', # The app's DocuSign integration key's secret
'signer_email': '{USER_EMAIL}',
'signer_name': '{USER_FULLNAME}',
'app_url': '{APP_URL}', # The url of the application. Eg http://localhost:5000
"ds_client_id": "{CLIENT_ID}", # The app's DocuSign integration key
"ds_client_secret": "{CLIENT_SECRET}", # The app's DocuSign integration key's secret
"signer_email": "{USER_EMAIL}",
"signer_name": "{USER_FULLNAME}",
"app_url": "{APP_URL}", # The url of the application. Eg http://localhost:5000
# NOTE: You must add a Redirect URI of appUrl/ds/callback to your Integration Key.
# Example: http:#localhost:5000/ds/callback
'authorization_server': 'https://account-d.docusign.com',
'session_secret': '{SESSION_SECRET}', # Secret for encrypting session cookie content
"authorization_server": "https://account-d.docusign.com",
"session_secret": "{SESSION_SECRET}", # Secret for encrypting session cookie content
# Use any random string of characters
'allow_silent_authentication': True, # a user can be silently authenticated if they have an
"allow_silent_authentication": True, # a user can be silently authenticated if they have an
# active login session on another tab of the same browser
'target_account_id': None, # Set if you want a specific DocuSign AccountId,
"target_account_id": None, # Set if you want a specific DocuSign AccountId,
# If None, the user's default account will be used.
'demo_doc_path': 'demo_documents',
'doc_docx': 'World_Wide_Corp_Battle_Plan_Trafalgar.docx',
'doc_pdf': 'World_Wide_Corp_lorem.pdf',
"demo_doc_path": "demo_documents",
"doc_salary_docx": "World_Wide_Corp_salary.docx",
"doc_docx": "World_Wide_Corp_Battle_Plan_Trafalgar.docx",
"doc_pdf": "World_Wide_Corp_lorem.pdf",
# Payment gateway information is optional
'gateway_account_id': '{DS_PAYMENT_GATEWAY_ID}',
'gateway_name': "stripe",
'gateway_display_name': "Stripe",
'github_example_url': 'https://github.com/docusign/eg-03-python-auth-code-grant/tree/master/app/',
'documentation': '' # Use an empty string to indicate no documentation path.
"gateway_account_id": "{DS_PAYMENT_GATEWAY_ID}",
"gateway_name": "stripe",
"gateway_display_name": "Stripe",
"github_example_url": "https://github.com/docusign/eg-03-python-auth-code-grant/tree/master/app/",
"documentation": "" # Use an empty string to indicate no documentation path.
}
102 changes: 51 additions & 51 deletions app/eg001_embedded_signing.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,27 @@
import base64
import re
from docusign_esign import *
from docusign_esign.rest import ApiException
from docusign_esign.client.api_exception import ApiException

eg = "eg001" # reference (and url) for this example
signer_client_id = 1000 # Used to indicate that the signer will use an embedded
# Signing Ceremony. Represents the signer's userId within
# your application.
authentication_method = 'None' # How is this application authenticating
# the signer? See the `authenticationMethod' definition
authentication_method = "None" # How is this application authenticating
# the signer? See the 'authenticationMethod' definition
# https://developers.docusign.com/esign-rest-api/reference/Envelopes/EnvelopeViews/createRecipient

demo_docs_path = path.abspath(path.join(path.dirname(path.realpath(__file__)), 'static/demo_documents'))
demo_docs_path = path.abspath(path.join(path.dirname(path.realpath(__file__)), "static/demo_documents"))


def controller():
"""Controller router using the HTTP method"""
if request.method == 'GET':
if request.method == "GET":
return get_controller()
elif request.method == 'POST':
elif request.method == "POST":
return create_controller()
else:
return render_template('404.html'), 404
return render_template("404.html"), 404


def create_controller():
Expand All @@ -41,53 +41,53 @@ def create_controller():
# 2. Call the worker method
# More data validation would be a good idea here
# Strip anything other than characters listed
pattern = re.compile('([^\w \-\@\.\,])+')
signer_email = pattern.sub('', request.form.get('signer_email'))
signer_name = pattern.sub('', request.form.get('signer_name'))
pattern = re.compile("([^\w \-\@\.\,])+")
signer_email = pattern.sub("", request.form.get("signer_email"))
signer_name = pattern.sub("", request.form.get("signer_name"))
envelope_args = {
'signer_email': signer_email,
'signer_name': signer_name,
'signer_client_id': signer_client_id,
'ds_return_url': url_for('ds_return', _external=True),
"signer_email": signer_email,
"signer_name": signer_name,
"signer_client_id": signer_client_id,
"ds_return_url": url_for("ds_return", _external=True),
}
args = {
'account_id': session['ds_account_id'],
'base_path': session['ds_base_path'],
'ds_access_token': session['ds_access_token'],
'envelope_args': envelope_args
"account_id": session["ds_account_id"],
"base_path": session["ds_base_path"],
"ds_access_token": session["ds_access_token"],
"envelope_args": envelope_args
}

try:
results = worker(args)
except ApiException as err:
error_body_json = err and hasattr(err, 'body') and err.body
error_body_json = err and hasattr(err, "body") and err.body
# we can pull the DocuSign error code and message from the response body
error_body = json.loads(error_body_json)
error_code = error_body and 'errorCode' in error_body and error_body['errorCode']
error_message = error_body and 'message' in error_body and error_body['message']
error_code = error_body and "errorCode" in error_body and error_body["errorCode"]
error_message = error_body and "message" in error_body and error_body["message"]
# In production, may want to provide customized error messages and
# remediation advice to the user.
return render_template('error.html',
return render_template("error.html",
err=err,
error_code=error_code,
error_message=error_message
)
if results:
# Redirect the user to the Signing Ceremony
# Don't use an iFrame!
# 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)
return redirect(results["redirect_url"])

else:
flash('Sorry, you need to re-authenticate.')
flash("Sorry, you need to re-authenticate.")
# 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.
session['eg'] = url_for(eg)
return redirect(url_for('ds_must_authenticate'))
session["eg"] = url_for(eg)
return redirect(url_for("ds_must_authenticate"))


# ***DS.snippet.0.start
Expand All @@ -105,29 +105,29 @@ def worker(args):
# 2. call Envelopes::create API method
# Exceptions will be caught by the calling function
api_client = ApiClient()
api_client.host = args['base_path']
api_client.set_default_header("Authorization", "Bearer " + args['ds_access_token'])
api_client.host = args["base_path"]
api_client.set_default_header("Authorization", "Bearer " + args["ds_access_token"])

envelope_api = EnvelopesApi(api_client)
results = envelope_api.create_envelope(args['account_id'], envelope_definition=envelope_definition)
results = envelope_api.create_envelope(args["account_id"], envelope_definition=envelope_definition)

envelope_id = results.envelope_id
app.logger.info(f'Envelope was created. EnvelopeId {envelope_id}')
app.logger.info(f"Envelope was created. EnvelopeId {envelope_id}")

# 3. Create the Recipient View request object
recipient_view_request = RecipientViewRequest(
authentication_method = authentication_method,
client_user_id = envelope_args['signer_client_id'],
recipient_id = '1',
return_url = envelope_args['ds_return_url'],
user_name = envelope_args['signer_name'], email = envelope_args['signer_email']
client_user_id = envelope_args["signer_client_id"],
recipient_id = "1",
return_url = envelope_args["ds_return_url"],
user_name = envelope_args["signer_name"], email = envelope_args["signer_email"]
)
# 4. Obtain the recipient_view_url for the signing ceremony
# Exceptions will be caught by the calling function
results = envelope_api.create_recipient_view(args['account_id'], envelope_id,
results = envelope_api.create_recipient_view(args["account_id"], envelope_id,
recipient_view_request = recipient_view_request)

return {'envelope_id': envelope_id, 'redirect_url': results.url}
return {"envelope_id": envelope_id, "redirect_url": results.url}


def make_envelope(args):
Expand All @@ -142,30 +142,30 @@ def make_envelope(args):
#
# The envelope has one recipient.
# recipient 1 - signer
with open(path.join(demo_docs_path, ds_config.DS_CONFIG['doc_pdf']), "rb") as file:
with open(path.join(demo_docs_path, ds_config.DS_CONFIG["doc_pdf"]), "rb") as file:
content_bytes = file.read()
base64_file_content = base64.b64encode(content_bytes).decode('ascii')
base64_file_content = base64.b64encode(content_bytes).decode("ascii")

# Create the document model
document = Document( # create the DocuSign document object
document_base64 = base64_file_content,
name = 'Example document', # can be different from actual file name
file_extension = 'pdf', # many different document types are accepted
name = "Example document", # can be different from actual file name
file_extension = "pdf", # many different document types are accepted
document_id = 1 # a label used to reference the doc
)

# Create the signer recipient model
signer = Signer( # The signer
email = args['signer_email'], name = args['signer_name'],
email = args["signer_email"], name = args["signer_name"],
recipient_id = "1", routing_order = "1",
# Setting the client_user_id marks the signer as embedded
client_user_id = args['signer_client_id']
client_user_id = args["signer_client_id"]
)

# Create a sign_here tab (field on the document)
sign_here = SignHere( # DocuSign SignHere field/tab
anchor_string = '/sn1/', anchor_units = 'pixels',
anchor_y_offset = '10', anchor_x_offset = '20'
anchor_string = "/sn1/", anchor_units = "pixels",
anchor_y_offset = "10", anchor_x_offset = "20"
)

# Add the tabs model (including the sign_here tab) to the signer
Expand All @@ -192,14 +192,14 @@ def get_controller():
return render_template("eg001_embedded_signing.html",
title="Embedded Signing Ceremony",
source_file=path.basename(__file__),
source_url=ds_config.DS_CONFIG['github_example_url'] + path.basename(__file__),
documentation=ds_config.DS_CONFIG['documentation'] + eg,
show_doc=ds_config.DS_CONFIG['documentation'],
signer_name=ds_config.DS_CONFIG['signer_name'],
signer_email=ds_config.DS_CONFIG['signer_email']
source_url=ds_config.DS_CONFIG["github_example_url"] + path.basename(__file__),
documentation=ds_config.DS_CONFIG["documentation"] + eg,
show_doc=ds_config.DS_CONFIG["documentation"],
signer_name=ds_config.DS_CONFIG["signer_name"],
signer_email=ds_config.DS_CONFIG["signer_email"]
)
else:
# Save the current operation so it will be resumed after authentication
session['eg'] = url_for(eg)
return redirect(url_for('ds_must_authenticate'))
session["eg"] = url_for(eg)
return redirect(url_for("ds_must_authenticate"))

Loading