Commit 3a90cc19 authored by Volkov Gherman's avatar Volkov Gherman

Finish dousign_app sending vie email

parent 2e162c01
......@@ -3,4 +3,9 @@ DATABASE_NAME='your database name'
DATABASE_USER='your database owner'
DATABASE_PASSWORD='your database password'
DATABASE_HOST='your database host'
DATABASE_PORT='your database port'
\ No newline at end of file
DATABASE_PORT='your database port'
DOCUSIGN_INTEGRATION_KEY='your integation key'
EMAIL_HOST_USER='host user mail'
EMAIL_HOST_PASSWORD='host user password'
\ No newline at end of file
import base64
from os import path
from docusign_esign import EnvelopesApi, EnvelopeDefinition, Document, Signer, CarbonCopy, SignHere, Tabs, Recipients
from docusign_esign import EnvelopesApi, EnvelopeDefinition, Document, Signer, CarbonCopy, SignHere, \
Tabs, Recipients
from ...consts import demo_docs_path, pattern
from ...jwt_helpers import create_api_client
......
from core.settings import DOCUSIGN_PRIVATE_KEY_PATH, DOCUSIGN_DOCUMENT_PATH_DOCX, DOCUSIGN_DOCUMENT_PATH_PDF
DS_JWT = {
"ds_client_id": "a2ecda0a-ebda-48f6-b784-a75a51608e07",
"ds_impersonated_user_id": "6c83e6cd-4cac-4aeb-a20e-22ab78b1f020", # The id of the user.
"private_key_file": "./app/private.key", # Create a new file in your repo source folder named private.key then copy and paste your RSA private key there and save it.
"private_key_file": DOCUSIGN_PRIVATE_KEY_PATH, # Create a new file in your repo source folder named private.key then copy and paste your RSA private key there and save it.
"authorization_server": "account-d.docusign.com",
"doc_docx": "World_Wide_Corp_Battle_Plan_Trafalgar.docx",
"doc_pdf": "World_Wide_Corp_lorem.pdf"
"doc_docx": DOCUSIGN_DOCUMENT_PATH_DOCX,
"doc_pdf": DOCUSIGN_DOCUMENT_PATH_PDF,
}
\ No newline at end of file
from .jwt_helper import create_api_client, get_jwt_token, get_private_key
\ No newline at end of file
from .jwt_helper import create_api_client, get_jwt_token, get_private_key
from docusign_esign import ApiClient
from os import path
def get_jwt_token(private_key, scopes, auth_server, client_id, impersonated_user_id):
"""Get the jwt token"""
api_client = ApiClient()
......@@ -15,6 +16,7 @@ def get_jwt_token(private_key, scopes, auth_server, client_id, impersonated_user
)
return response
def get_private_key(private_key_path):
"""
Check that the private key present in the file and if it is, get it from the file.
......@@ -30,10 +32,11 @@ def get_private_key(private_key_path):
return private_key
def create_api_client(base_path, access_token):
"""Create api client and construct API headers"""
api_client = ApiClient()
api_client.host = base_path
api_client.set_default_header(header_name="Authorization", header_value=f"Bearer {access_token}")
return api_client
\ No newline at end of file
return api_client
from os import path
import sys
import subprocess
from docusign_esign import ApiClient
from docusign_esign.client.api_exception import ApiException
from app.jwt_helpers import get_jwt_token, get_private_key
from app.eSignature.examples.eg002_signing_via_email import Eg002SigningViaEmailController
from app.jwt_config import DS_JWT
from .docusign_app.jwt_helpers import get_jwt_token, get_private_key
from .docusign_app.eSignature.examples.eg002_signing_via_email import Eg002SigningViaEmailController
from .docusign_app.jwt_config import DS_JWT
# pip install DocuSign SDK
subprocess.check_call([sys.executable, '-m', 'pip', 'install', 'docusign_esign'])
......@@ -94,6 +94,3 @@ def main():
run_example(private_key, api_client)
else:
sys.exit("Please grant consent")
main()
import sys
from docusign_esign import ApiClient, ApiException
from api.jwt_console import get_consent_url, get_token
from api.docusign_app.jwt_helpers import get_private_key
from api.models import DocumentNDA
from api.docusign_app.jwt_config import DS_JWT
from api.docusign_app.eSignature.examples.eg002_signing_via_email import Eg002SigningViaEmailController
def get_args(api_account_id, access_token, base_path):
document = DocumentNDA.objects.last()
signer_email = document.owner_email
signer_name = document.owner_name
cc_email = 'example@mail.com'
cc_name = 'name'
envelope_args = {
"signer_email": signer_email,
"signer_name": signer_name,
"cc_email": cc_email,
"cc_name": cc_name,
"status": "sent",
}
args = {
"account_id": api_account_id,
"base_path": base_path,
"access_token": access_token,
"envelope_args": envelope_args
}
return args
def run_docusign(private_key, api_client):
jwt_values = get_token(private_key, api_client)
args = get_args(jwt_values["api_account_id"], jwt_values["access_token"], jwt_values["base_path"])
envelope_id = Eg002SigningViaEmailController.worker(args, DS_JWT["doc_docx"], DS_JWT["doc_pdf"])
print("Your envelope has been sent.")
print(envelope_id)
def send_docusign_email():
api_client = ApiClient()
api_client.set_base_path(DS_JWT["authorization_server"])
api_client.set_oauth_host_name(DS_JWT["authorization_server"])
private_key = get_private_key(DS_JWT["private_key_file"]).encode("ascii").decode("utf-8")
try:
run_docusign(private_key, api_client)
except ApiException as err:
body = err.body.decode('utf8')
if "consent_required" in body:
consent_url = get_consent_url()
print("Open the following URL in your browser to grant consent to the application:")
print(consent_url)
consent_granted = input("Consent granted? Select one of the following: \n 1)Yes \n 2)No \n")
if consent_granted == "1":
run_docusign(private_key, api_client)
else:
sys.exit("Please grant consent")
return {'status': 'success'}
......@@ -10,28 +10,37 @@
crossorigin="anonymous"></script>
</head>
<body>
<form id='form' method="POST">
<div class="form-group">
<label for="formGroupExampleInput">Введите свое имя</label>
<input name="owner_name" type="text" class="form-control" id="formGroupExampleInput" placeholder="Example input" required>
</div>
<div class="form-group">
<label for="formGroupExampleInput2">Введите свою фамилию</label>
<input name="owner_surname" type="text" class="form-control" id="formGroupExampleInput2" placeholder="Another input" required>
</div>
<div class="form-group">
<label for="exampleInputEmail1">Введите свой Email</label>
<input name="owner_email" type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp"
placeholder="Enter email" required>
</div>
<button type="submit" class="btn btn-primary">Подтвердить и подписать документ</button>
</form>
<h1 style="text-align: center; margin-top: 10vh" class="display-6">DocuSign Esign <br>
<small class="text-muted">Подпишите документ с помощью docusign</small>
</h1>
<main style="background: lightgray; width: 70vh; margin-inline: auto">
<form style="width: 70vh; margin: 10vh auto; padding: 20px 30px;" id='form' method="POST">
<div class="form-group">
<label for="formGroupExampleInput">Введите свое имя</label>
<input name="owner_name" type="text" class="form-control" id="formGroupExampleInput" placeholder="Вася"
required>
</div>
<div class="form-group">
<label for="formGroupExampleInput2">Введите свою фамилию</label>
<input name="owner_surname" type="text" class="form-control" id="formGroupExampleInput2"
placeholder="Пупкин" required>
</div>
<div class="form-group">
<label for="exampleInputEmail1">Введите свой Email</label>
<input name="owner_email" type="email" class="form-control" id="exampleInputEmail1"
aria-describedby="emailHelp"
placeholder="vasyaPupkin@.mail.com" required>
</div>
<button type="submit" class="btn btn-primary">Подтвердить и подписать документ
</button>
</form>
</main>
</body>
<script>
const sendForm = (e) => {
e.preventDefault();
fetch('http://localhost:8000', {
fetch('http://localhost:8000/api/v1/', {
method: 'POST',
body: new FormData(form)
}).then(form.reset())
......
from datetime import datetime, timedelta
from http.client import HTTPException
import jwt
from django.core.mail import send_mail
from docusign_esign import ApiClient, EnvelopesApi
from django.shortcuts import redirect
from rest_framework.renderers import TemplateHTMLRenderer
from rest_framework.response import Response
from rest_framework.views import APIView
from api.serializers import DocumentNDASerializer
from core.settings import DOCUSIGN_PRIVATE_KEY_PATH, DOCUSIGN_INTEGRATION_KEY, DOCUSIGN_AUTH_SERVER, DOCUSIGN_API_SERVER
from api.services import send_docusign_email
class IndexView(APIView):
def index_view(request):
return redirect('send_email')
class SendDocumentView(APIView):
renderer_classes = [TemplateHTMLRenderer]
template_name = 'index.html'
def get(self, request):
return Response(template_name=self.template_name)
return Response(template_name=self.template_name, status=200)
def post(self, request):
serializer = DocumentNDASerializer(data=request.data)
if serializer.is_valid():
document = serializer.save()
send_docusign_email(request, document)
return Response(status=200, data=serializer.data)
serializer.save()
try:
send_docusign_email()
return Response(status=200, data=serializer.data)
except HTTPException as e:
return Response({'error': e}, status=503)
return Response({'error': 'Bad Request'}, status=400)
def gen_jwt_token(email):
with open(DOCUSIGN_PRIVATE_KEY_PATH, 'rb') as rsa_key:
private_key = rsa_key.read()
integration_key = DOCUSIGN_INTEGRATION_KEY
user_email = email
cur_time = datetime.utcnow()
exp_time = cur_time + timedelta(hours=1)
payload = {
'iss': integration_key,
'sub': user_email,
'aud': 'account-d.docusign.com',
'iat': cur_time,
'exp': exp_time,
'scope': 'signature impersonation'
}
return jwt.encode(payload, private_key, algorithm='RS256')
def send_docusign_email(request, user_data):
user = user_data
api_client = ApiClient()
api_client.host = DOCUSIGN_AUTH_SERVER
jwt_token = gen_jwt_token(user.owner_email)
api_client.set_default_header('Authorization', 'Bearer ' + jwt_token)
base_url = DOCUSIGN_API_SERVER
envelope_api = EnvelopesApi(api_client)
envelope_definition = {
'email_subject': 'Подписать документ',
'email_blurb': 'Пожалуйста, подпишите документ.',
'status': 'sent',
'recipients': {
'signers': [{
'email': user.owner_email,
'name': user.owner_name,
'recipientId': '1',
'clientUserId': user.pk,
'tabs': {
'textTabs': [{
'tabLabel': 'Name',
'value': user.owner_name
}]
}
}]
},
'documents': [{
'documentId': '1',
'name': 'document.docx',
'fileExtension': 'docx',
'documentBase64': 'BASE64_ENCODED_DOCUMENT'
}]
}
envelope_summary = envelope_api.create_envelope('1', envelope_definition=envelope_definition)
sign_url = f'{base_url}/envelopes/{envelope_summary.envelope_id}/views/recipient'
send_mail(
'Подписать документ',
f'Пожалуйста, подпишите документ по ссылке: {sign_url}',
'отправитель@example.com',
[user.email],
fail_silently=False,
)
return {'status': 'success'}
......@@ -15,6 +15,7 @@ from pathlib import Path
from dotenv import load_dotenv
load_dotenv()
# Build paths inside the project like this: BASE_DIR / 'subdir'.
......@@ -116,8 +117,8 @@ AUTH_PASSWORD_VALIDATORS = [
CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = [
'http://loaclhost:8000',
'http://127.0.0.1:8000'
'http://loaclhost:8000/api/v1/',
'http://127.0.0.1:8000/api/v1/'
]
# Internationalization
......@@ -134,10 +135,10 @@ USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/
STATIC_URL = 'static/'
STATIC_URL = '/static/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'demo')
MEDIA_URL = '/demo/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'api/docusign_app/static')
MEDIA_URL = '/api/docusign_app/static/'
# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
......@@ -145,13 +146,17 @@ MEDIA_URL = '/demo/'
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
DOCUSIGN_INTEGRATION_KEY = os.getenv('DOCUSIGN_INTEGRATION_KEY')
DOCUSIGN_PRIVATE_KEY_PATH = os.path.join(BASE_DIR, 'docusign_test_app-python/app/private.key')
DOCUSIGN_PRIVATE_KEY_PATH = os.path.join(BASE_DIR, 'api/docusign_app/private.key')
DOCUSIGN_DOCUMENT_PATH_DOCX = os.path.join(BASE_DIR, 'api/docusign_app/static/demo_documents'
'/World_Wide_Corp_Battle_Plan_Trafalgar.docx')
DOCUSIGN_DOCUMENT_PATH_PDF = os.path.join(BASE_DIR, 'api/docusign_app/static/demo_documents/World_Wide_Corp_lorem.pdf')
DOCUSIGN_AUTH_SERVER = 'https://account-d.docusign.com'
DOCUSIGN_API_SERVER = 'https://api-d.docusign.com'
EMAIL_USE_TLS = True
EMAIL_HOST = None
EMAIL_HOST_USER = None
EMAIL_HOST_PASSWORD = None
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = os.getenv('EMAIL_HOST_USER')
EMAIL_HOST_PASSWORD = os.getenv('EMAIL_HOST_PASSWORD')
EMAIL_PORT = 587
APPEND_SLASH = False
......@@ -17,10 +17,11 @@ Including another URLconf
from django.contrib import admin
from django.urls import path
from api.views import IndexView
from api.views import index_view, SendDocumentView
urlpatterns = [
path('admin/', admin.site.urls),
path('', IndexView.as_view()),
path('', index_view, name='index'),
path('api/v1/', SendDocumentView.as_view(), name='send_email'),
]
......@@ -3,4 +3,3 @@ djangorestframework==3.14.*
psycopg2-binary==2.9.*
python-dotenv==1.0.*
docusign-esign==3.22.*
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment