DocuSign API embedded signature implementation Symfony

208 Views Asked by At

Trying to implement the DocuSign embedded signature into our web application and I have a hard time getting it right. The documentation is a bit scattered so I'm not able to get the correct flow of API calls. Though I set up the quickstart project from Docusign but that didn't help in getting me right.

Here's the scenario: We want the user's(might be multiple) to be able to sign documents from our website. The document has the following fields to be filled along with the signature field: Date, Name, additional comments, and number. The document would be provided from within the app. Now I need to know the correct sequence of steps to be followed to achieve this scenario via PHP SDK.

I've created the App and Integration keys via Developer account.

Update

I've been able to put together this code:


$accessToken = $this->generate_jwt_token();
        $config = new Configuration();
        $config->setHost('https://demo.docusign.net/restapi');
        $config->addDefaultHeader('Authorization', 'Bearer ' . $accessToken);
        $api_client = new ApiClient($config);
        $api_client->getOAuth()->setOAuthBasePath('https://account-d.docusign.com');
        $api_client->getConfig()->setAccessToken($accessToken);
        $api_client->getConfig()->addDefaultHeader('Authorization', 'Bearer ' . $accessToken);


        // Create an envelope from a template
        $relativePath = "/../web/dummy.pdf";
        $basePath = $this->container->get('kernel')->getRootDir() . $relativePath;
        $signer_name = 'John Smith';
        $signer_email = '[email protected]';
        $envelope_summary = $this->create_envelope_from_pdf($basePath, $signer_name, $signer_email, 'Dummy PDF', $api_client);

// Generate the URL for the embedded signing ceremony
        $envelope_id = $envelope_summary->getEnvelopeId();
        $recipient_name = 'John Smith';
        $recipient_email = '[email protected]';
        $signing_ceremony_url = $this->generate_signing_ceremony_url($envelope_id, $recipient_name, $recipient_email, $api_client);

// Redirect the user to the signing ceremony URL
        header('Location: ' . $signing_ceremony_url);
        exit;


function generate_jwt_token() {
        $private_key_path = 'PRIVATE_KEY';
        $jwt = array(
            'iss' => 'ACCOUNT_ID',
            'sub' => 'USER_ID',
            'aud' => 'https://demo.docusign.net/restapi',
            'exp' => time() + 3600
        );
        $jwt = JWT::encode($jwt, $private_key_path, 'RS256');
        return $jwt;
    }

    /**
     * @throws ApiException
     */
    function create_envelope_from_pdf($pdf_path, $signer_name, $signer_email, $document_name, $apiClient)
    {
        // Set up the envelope definition
        $envelope_definition = new EnvelopeDefinition();
        $envelope_definition->setEmailSubject('Please sign this document');
        $envelope_definition->setStatus('sent');

        // Add the document to the envelope
        $document = new Document();
        $document->setDocumentBase64(base64_encode(file_get_contents($pdf_path)));
        $document->setName($document_name);
        $document->setFileExtension('pdf');
        $envelope_definition->setDocuments([$document]);

        // Add the signer to the envelope
        $signer = new Signer();
        $signer->setName($signer_name);
        $signer->setEmail($signer_email);
        $signer->setRecipientId('1');
        $signer->setClientUserId('1234');

        // Add a sign here tab to the signer
        $sign_here = new SignHere();
        $sign_here->setDocumentId('1');
        $sign_here->setPageNumber('1');
        $sign_here->setRecipientId('1');
        $sign_here->setTabLabel('Sign Here');
        $sign_here->setXPosition('100');
        $sign_here->setYPosition('100');
        $signer->setTabs(new Tabs(['sign_here_tabs' => [$sign_here]]));
        $envelope_definition->setRecipients(new Recipients(['signers' => [$signer]]));

        // Create the envelope
        $envelopes_api = new EnvelopesApi($apiClient);
        $envelope_summary = $envelopes_api->createEnvelope('ACCOUNT_ID', $envelope_definition, new CreateEnvelopeOptions(['cdse_mode' => 'true']));

        return $envelope_summary;
    }

    /**
     * @throws ApiException
     */
    function generate_signing_ceremony_url($envelope_id, $recipient_name, $recipient_email, $apiClient) {
        global $api_client;
        $recipient_view_request = new RecipientViewRequest();
        $recipient_view_request->setReturnUrl('https://example.com/');
        $recipient_view_request->setClientUserId('1234');
        $recipient_view_request->setAuthenticationMethod('none');
        $recipient_view_request->setUserName($recipient_name);
        $recipient_view_request->setEmail($recipient_email);
        $recipient_view_request->setRecipientId('1');
//        $recipient_view_request->set('https://www.example.com');
        $envelopes_api = new EnvelopesApi($apiClient);
        $recipient_view = $envelopes_api->createRecipientView('ACCOUNT_ID', $envelope_id, $recipient_view_request);
        return $recipient_view->getUrl();

and now I'm getting this error:

Error while requesting server, received a non successful HTTP code [401] with response Body: O:8:"stdClass":2:{s:9:"errorCode";s:27:"AUTHORIZATION_INVALID_TOKEN";s:7:"message";s:59:"The access token provided is expired, revoked or malformed.";}

The JWT token is generated correctly. The error occurs when call to EnvelopesApi ->createEnvelope happens.

2

There are 2 best solutions below

0
DavidG On BEST ANSWER

So I was able to solve the problem of generating an access token via requestJWTUserToken DocgSign PHP SDK method by specifying the OAuthBasePath explicitly via the below code:

$api_client->getOAuth()->setOAuthBasePath('account-d.docusign.com');

In the absence of this code, it was set to production OAuthBasePath i.e. account.docusign.com.

Updated Code for JWT token generation method:

function generate_jwt_token(ApiClient $apiClient) {

        $relativePath = "/../web/private.key";
        $basePath = $this->container->get('kernel')->getRootDir() . $relativePath;
        $jwt = $apiClient->requestJWTUserToken('Integration_Key', 'USER_ID', file_get_contents($basePath), ['signature', 'impersonation']);
        return $jwt;
    }
1
Adrian DocuSign Support On

Adrian from DocuSign Developer Support here,

Your code looks good, however, your JWT section has some incorrect values:

This:

 $private_key_path = 'PRIVATE_KEY';
        $jwt = array(
            'iss' => 'ACCOUNT_ID',
            'sub' => 'USER_ID',
            'aud' => 'https://demo.docusign.net/restapi',
            'exp' => time() + 3600

The iss should be your integration Key, not the Account iD,

The aud should be "account-d.docusign.com".

And don't forget to add the scopes: "scope": "signature impersonation"

Here is our PHP JWT Guide with a good code sample, just in case:

https://developers.docusign.com/docs/esign-rest-api/sdks/php/auth/

This is how we code it:

 self::$apiClient->getOAuth()->setOAuthBasePath($GLOBALS['JWT_CONFIG']['authorization_server']);
    true);
    $privateKey = file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/' . $GLOBALS['JWT_CONFIG']['private_key_file'], true);

    $scope = DocuSign::getDefaultScopes()[0];
    $jwt_scope = $scope . " impersonation"; 

    $response = self::$apiClient->requestJWTUserToken(
       $aud = $GLOBALS['JWT_CONFIG']['ds_client_id'],
       $aud = $GLOBALS['JWT_CONFIG']['ds_impersonated_user_id'],
       $aud = $privateKey,
       $aud = $jwt_scope
    );

We hope this information helps.

Regards Adrian DocuSign Developer Support