Embedded signing DocuSign laravel
Hello everyone, today we will see how we can do an embedded signing with Docusign in Laravel 8. If you are reading my blog which means you also want to integrate DocuSign with your Laravel Application. Please follow the below instruction to integrate Docusign in one shot.
To integrate Docusign in Laravel, we will follow below steps:
- Create a developer account on DocuSign
- Create an application and get the keys on DocuSign
- Install laravel project
- Install Docusign Package
- Setting up .env with DocuSign keys
- Create Routes
- Create Controller
- Create Blade File
- Test the integration
Step: 1 Create a developer account on DocuSign
To create the developer account on Docusign please click here. this link will redirect you to docusign developer account, you will have something like the below image.
After the registration, you will receive an account verification email on your registered email, verify that email and proceed.Once you logged in you have image like the below one.
From this section we need API Account ID, please copy API Account ID and place it in safe place we will use it later.
Step: 2 Create an application and get the keys on DocuSign
Now click on ADD APP AND INTEGRATION KEY button to create a new application.
Once you create the app you can see something like the below image.
From here you have to copy integration key and secret key and keep it in a safe place we will use it later.
Step: 3 Install laravel project
Open your command prompt under your htdocs and run the below command
composer create-project laravel/laravel laravel-docusign
Step: 4 Install Docusign Package
Composer require docusign/esign-client
Step: 5 Setting up .env with Docusign keys
Add the below in your .env file, and then run php artisan optimize:clear
DOCUSIGN_BASE_URL=https://demo.docusign.net/restapi DOCUSIGN_ACCOUNT_ID=Your API Account ID DOCUSIGN_CLIENT_ID= Your Integrator key DOCUSIGN_CLIENT_SECRET=Your secret key
Step:6 Create routes
Create routes for the docusign add the below route in your routes/web.php file.
Route::get('docusign',[DocusignController::class, 'index'])->name('docusign'); Route::get('connect-docusign',[DocusignController::class, 'connectDocusign'])->name('connect.docusign'); Route::get('docusign/callback',[DocusignController::class,'callback'])->name('docusign.callback'); Route::get('sign-document',[DocusignController::class,'signDocument'])->name('docusign.sign');
Step: 7 Create Controller
Now we will create a controller for our routes, to create the controller run the below command in your terminal from the project root folder.
php artisan make:controller DocusignController
After creating the controller add the controller namespace in your routes/web.php file on the top.
use App\Http\Controllers\DocusignController;
see the below image, how my routes.php looks like
Now add the below code in your DocusignController.php file
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use DocuSign\eSign\Configuration; use DocuSign\eSign\Api\EnvelopesApi; use DocuSign\eSign\Client\ApiClient; use Exception; use Session; class DocusignController extends Controller { /** hold config value */ private $config; private $signer_client_id = 1000; # Used to indicate that the signer will use embedded /** Specific template arguments */ private $args; /** * Show the html page * * @return render */ public function index() { return view('docusign.connect'); } /** * Connect your application to docusign * * @return url */ public function connectDocusign() { try { $params = [ 'response_type' => 'code', 'scope' => 'signature', 'client_id' => env('DOCUSIGN_CLIENT_ID'), 'state' => 'a39fh23hnf23', 'redirect_uri' => route('docusign.callback'), ]; $queryBuild = http_build_query($params); $url = "https://account-d.docusign.com/oauth/auth?"; $botUrl = $url . $queryBuild; return redirect()->to($botUrl); } catch (Exception $e) { return redirect()->back()->with('error', 'Something Went wrong !'); } } /** * This function called when you auth your application with docusign * * @return url */ public function callback(Request $request) { $code = $request->code; $client_id = env('DOCUSIGN_CLIENT_ID'); $client_secret = env('DOCUSIGN_CLIENT_SECRET'); $integrator_and_secret_key = "Basic " . utf8_decode(base64_encode("{$client_id}:{$client_secret}")); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://account-d.docusign.com/oauth/token'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POST, 1); $post = array( 'grant_type' => 'authorization_code', 'code' => $code, ); curl_setopt($ch, CURLOPT_POSTFIELDS, $post); $headers = array(); $headers[] = 'Cache-Control: no-cache'; $headers[] = "authorization: $integrator_and_secret_key"; curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $result = curl_exec($ch); if (curl_errno($ch)) { echo 'Error:' . curl_error($ch); } curl_close($ch); $decodedData = json_decode($result); $request->session()->put('docusign_auth_code', $decodedData->access_token); return redirect()->route('docusign')->with('success', 'Docusign Succesfully Connected'); } public function signDocument() { try{ $this->args = $this->getTemplateArgs(); $args = $this->args; $envelope_args = $args["envelope_args"]; # Create the envelope request object $envelope_definition = $this->make_envelope($args["envelope_args"]); $envelope_api = $this->getEnvelopeApi(); # Call Envelopes::create API method # Exceptions will be caught by the calling function $api_client = new \DocuSign\eSign\client\ApiClient($this->config); $envelope_api = new \DocuSign\eSign\Api\EnvelopesApi($api_client); $results = $envelope_api->createEnvelope($args['account_id'], $envelope_definition); $envelope_id = $results->getEnvelopeId(); $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 $recipient_view_request = new \DocuSign\eSign\Model\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' => 'shaiv', 'email' => 'shaivroy1@gmail.com' ]); $results = $envelope_api->createRecipientView($args['account_id'], $envelope_id,$recipient_view_request); return redirect()->to($results['url']); } catch (Exception $e) { dd($e); } } private function make_envelope($args) { $filename = 'World_Wide_Corp_lorem.pdf'; $demo_docs_path = asset('doc/'.$filename); $arrContextOptions=array( "ssl"=>array( "verify_peer"=>false, "verify_peer_name"=>false, ), ); $content_bytes = file_get_contents($demo_docs_path,false, stream_context_create($arrContextOptions)); // dd($content_bytes); $base64_file_content = base64_encode($content_bytes); // dd($base64_file_content); # Create the document model $document = new \DocuSign\eSign\Model\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 'document_id' => 1, # a label used to reference the doc ]); # Create the signer recipient model $signer = new \DocuSign\eSign\Model\Signer([# The signer 'email' => 'shaivroy1@gmail.com', 'name' => 'shaiv', 'recipient_id' => "1", 'routing_order' => "1", # Setting the client_user_id marks the signer as embedded 'client_user_id' => $args['signer_client_id'], ]); # Create a sign_here tab (field on the document) $sign_here = new \DocuSign\eSign\Model\SignHere([# DocuSign SignHere field/tab '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 # The Tabs object wants arrays of the different field/tab types $signer->settabs(new \DocuSign\eSign\Model\Tabs(['sign_here_tabs' => [$sign_here]])); # Next, create the top level envelope definition and populate it. $envelope_definition = new \DocuSign\eSign\Model\EnvelopeDefinition([ 'email_subject' => "Please sign this document sent from the CodeHunger", 'documents' => [$document], # The Recipients object wants arrays for each recipient type 'recipients' => new \DocuSign\eSign\Model\Recipients(['signers' => [$signer]]), 'status' => "sent", # requests that the envelope be created and sent. ]); return $envelope_definition; } /** * Getter for the EnvelopesApi */ public function getEnvelopeApi(): EnvelopesApi { $this->config = new Configuration(); $this->config->setHost($this->args['base_path']); $this->config->addDefaultHeader('Authorization', 'Bearer ' . $this->args['ds_access_token']); $this->apiClient = new ApiClient($this->config); return new EnvelopesApi($this->apiClient); } /** * Get specific template arguments * * @return array */ private function getTemplateArgs() { $envelope_args = [ 'signer_client_id' => $this->signer_client_id, 'ds_return_url' => route('docusign') ]; $args = [ 'account_id' => env('DOCUSIGN_ACCOUNT_ID'), 'base_path' => env('DOCUSIGN_BASE_URL'), 'ds_access_token' => Session::get('docusign_auth_code'), 'envelope_args' => $envelope_args ]; return $args; } }
Note: You must have to add callback URL in your docusign , to get your laravel application get authenticated.
See the below image.
Step:8 Create a blade file
Now create a folder named as docusign under your resouces/views under docusign folder create a file connect.blade.php and write the below code in it.
<!DOCTYPE html> <html lang="en"> <head> <title>Docusign Integration Example</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script> </head> <body> <div class="container"> @if ($message = Session::get('success')) <div class="alert alert-success alert-block"> <button type="button" class="close" data-dismiss="alert">×</button> <strong>{{ $message }}</strong> </div> @endif <div class="card"> <div class="card-header"> CodeHunger Private Limited </div> <div class="card-body"> <h5 class="card-title">Docusign Tutorial</h5> <p class="card-text">Click the button below to connect your appication with docusign</p> @if ($message = Session::get('success')) <a href="{{route('docusign.sign')}}" class="btn btn-primary">Click to sign document</a> @else <a href="{{route('connect.docusign')}}" class="btn btn-primary">Connect Docusign</a> @endif </div> </div> </div> </body>
Step-9 Test the integration
Now visit this url from your browser http://localhost/docusign/public/docusign , you will have something like the below image.
Click on connect DocuSign, you will redirect to DocuSign’s official website where they told you to enter your DocuSign email and password, after giving your credentials you will come back to your laravel application with the below image.
When you click on the button to sign the document you will have something like the below one.
Here click on continue put signature and press finish, after that you embeded signing process is done and you will come back to your laravel application.
After signing process complete you can see something like the below one.
I hope it works for you. please rate me 5 if it helps you.
https://blog.codehunger.in/embedded-signing-docusign-laravel
Hello Sir,
i need your help.
can you integrate docusign api in my crm. ?
Yes for sure, please send your details to support@codehunger.in
Please help me,
How I can share same document to multiple signers?
I want to signed same document from multiple people
anyone tell me please how i can resolve this issue?
Just create a folder named doc in public and create a file same name as in “make_envelope” method
Hi,
Please help me,
I also tried to change the file and even change the file name but it did not work,
Do you have any idea about this?
please use public_path like that
$demo_docs_path = public_path(‘doc/’.$filename);
Hi,
I need to check when the docusign is connected, so I can reconnect it.