sanketr43 | Posts: 14

how to add text field in pdf, while creating package

0 votes
Hello, I am uploading PDF via REST API PHP, along with signer users. I want to add an editable text/input field in the PDF, so that users during singing, can enter their account number or any other data as input. means like they can fill the form while signing and at the end they can sign the document. I am confuse here how to do that. In below code there is function "buildPackage". I tried adding documents fields option it gives error. how to add input field so user can enter details while sign process.
 'Package created from template through REST API',

		  'description' => 'Package created with the eSignLive REST API',

		  'emailMessage' => 'This message should be delivered to all signers',

		  'autocomplete' => true,

		  'type' => 'PACKAGE',

		  'visibility' => 'ACCOUNT',

		  'due' => NULL,

		  'language' => 'en',

		  'status' => 'DRAFT',

		  'roles' => 

		  array (

		    0 => 

		    array (

		      'id' => $placeholderId,

				'attachmentRequirements' => 

				  array (

				    0 => 

				    array (

				      'status' => 'INCOMPLETE',

				      'description' => 'contract',

				      'required' => false,

				      'id' => 'attachment1',

				      'comment' => '',

				      'name' => 'Upload, if you have any contract document! Or Click Done.',

				      'data' => NULL,

				    ),

				),

		      'type' => 'SIGNER',

		      'signers' => 

		      array (

		        0 => 

		        array (

		          'id' => $placeholderId,

		          'firstName' => $firstName,

		          'lastName' => $lastName,

		          'email' => $email,

		        ),

		      ),

		      'name' => 'Signer',

		    ),

		  ),

		);

		$packageJSON = json_encode($build);

		$packageId = json_decode($this->sendRequest($this->packageAppend . $templateId . '/clone', $packageJSON, NULL, 'application/json'), true);

		return $packageId;

	}



	//Create package

	public function buildPackage($application_id)

	{



		$application = Application::find($application_id);

		$title 		 = $application->entity_name.' - '.date('d-m-Y');



		/*if(empty($application->directors)){

			return redirect('home/application/'.$application->unique_id.'/signature');

		}*/

		//document fields
		$documents = array();

		$roles 		 = array();

		$i = 1;

		//directors signers  (ID: Signer1 & Signer2)

		if(!empty($application->directors)){

			foreach (unserialize($application->directors) as $key => $value) {

				if(!empty($value['email'])){

	                $roles[] = array(

	                                'id' => 'Signer'.$i,

	                                'type' => 'SIGNER',

	                                'signers' => array(

	                                    array(

	                                        'email' => trim($value['email']),

	                                        'firstName' => trim($value['f_name']),

	                                        'lastName' => trim($value['l_name']),

	                                        'id' => 'Signer'.$i,

	                                    )

	                                ) ,

	                            );

	                $i++;

	            }

			}

		}



		//manager (ID: Manager1)

		$roles[] = array(

                'id' => 'Manager1',

                'type' => 'SIGNER',

                'signers' => array(

                    array(

                        'email' 	=> '[email protected]',

                        'firstName' => 'Victor',

                        'lastName' 	=> 'GR',

                        'id' => 'Manager1',

                    )

                ) ,

            );





		$build = array(
			'autocomplete' => true,
			'type' 	   => 'PACKAGE',

			'status'   => 'DRAFT',

			'documents'=> $documents,

			'roles'    => $roles,

			'name' 	   => $title,

		);



		$packageJSON = json_encode($build);

		$packageId = json_decode($this->sendRequest($this->packageAppend, $packageJSON, NULL, NULL), true);
		return $packageId;

	}



	//Upload document

	public function buildDocument($packageId,$application_id)

	{



		$application  = Application::find($application_id);

		$payment_term = PaymentTerm::where('application_id',$application->id)->first();

		$director  	  = unserialize($application->directors);

		$user = Auth::user();

		$director_count = 1;



		$build = array(

			'fields' => array(

				array(

					'value' => $application->entity_name,

					'name' => 'customer_name',

				) ,

				array(

					'value' => $application->address,

					'name' => 'customer_address',

				) ,

				array(

					'value' => $application->phone,

					'name' => 'telephone',

				) ,

				array(

					'value' => $user->company_name,

					'name' => 'supplier_name',

				) ,

				array(

					'value' => $user->address,

					'name' => 'supplier_address',

				) ,

				array(

					'value' => $user->state.', '.$user->pincode,

					'name' => 'supplier_address2',

				) ,

				array(

					'value' => '',

					'name' => 'email',

				) ,

				array(

					'value' => $application->abn_number,

					'name' => 'abn_number',

				) ,

				array(

					'value' => $payment_term->installment,

					'name' => 'installment',

				) ,

				array(

					'value' => $payment_term->term,

					'name' => 'month',

				) ,

				array(

					'value' => $user->document_fee,

					'name' => 'handling_fee',

				)

			) ,

			'extract' => true,

			'name' => 'GRENKE - EQUIPMENT LEASE AGREEMENT FOR BUSINESS PURPOSES',

			'id' => 'contract'

		);



		if(isset($director[0]['f_name'])){

		//directors

		$build['fields'][] = array(

								'value' => $director[0]['f_name'].' '.$director[0]['l_name'],

								'name' => 'director_name_1',

							);

		}



		if(isset($director[1]['f_name'])){

		$director_count = 2;

		$build['fields'][] = array(

								'value' => $director[1]['f_name'].' '.$director[1]['l_name'],

								'name' => 'director_name_2',

							); 

		}





		//items list 1st

		foreach ($application->items as $key => $value) {

			if(($key+1) == 5){ break; }

		$build['fields'][] = array(

									'value' => $value->description,

									'name' => 'item_'.($key+1),

								);


		$build['fields'][] = array(

									'value' => $value->quantity,

									'name' => 'qty_'.($key+1),

								);

		}



		//items list 2nd full

		if(count($application->items) > 4){

			foreach ($application->items as $key => $value) {

			$build['fields'][] = array(

									'value' => $value->description,

									'name' => 'item_1_'.($key+1),

								);

			$build['fields'][] = array(

									'value' => $value->manufacturer,

									'name' => 'manufacturer_1_'.($key+1),

								);

			$build['fields'][] = array(

									'value' => $value->quantity,

									'name' => 'qty_1_'.($key+1),

								);

			}	

		}

		//items list 3rd
	if(count($application->items) <= 4){	
		foreach ($application->items as $key => $value) {

		$build['fields'][] = array(

									'value' => $value->description,

									'name' => 'item_2_'.($key+1),

								);

		$build['fields'][] = array(

									'value' => $value->manufacturer,

									'name' => 'manufacturer_2_'.($key+1),

								);

		$build['fields'][] = array(

									'value' => $value->quantity,

									'name' => 'qty_2_'.($key+1),

								);

		}
	}else{
		//enter message to first row
		$build['fields'][] = array(

									'value' => "Please see appendix",

									'name' => 'item_2_1',

								);

		$build['fields'][] = array(

									'value' => "/equipment schedule.",

									'name' => 'item_2_2',

								);
	}






		$documentJSON = json_encode($build);



	if($director_count == 2){

		$postdata = "--" . $this->MULTIPART_BOUNDARY . "\r\n";

	    $postdata .= "Content-Disposition: form-data; name=\"file\"; filename=\"application_pdf_form_d_2.pdf\"\r\n";

	    $postdata .= "Content-Type: application/pdf" . "\r\n\r\n";

	    $postdata .= file_get_contents(asset('upload/application_pdf_form_d_2.pdf'));

	    $postdata .= "\r\n\r\n";

	    $postdata .= "--" . $this->MULTIPART_BOUNDARY . "\r\n";

	    $postdata .= "Content-Disposition: form-data; name=\"payload\"\r\n\r\n";

	    $postdata .= $documentJSON;

	    $postdata .= "\r\n\r\n";

	    $postdata .= "--" . $this->MULTIPART_BOUNDARY . "--\r\n";

	}else{

		$postdata = "--" . $this->MULTIPART_BOUNDARY . "\r\n";

	    $postdata .= "Content-Disposition: form-data; name=\"file\"; filename=\"application_pdf_form_d_1.pdf\"\r\n";

	    $postdata .= "Content-Type: application/pdf" . "\r\n\r\n";

	    $postdata .= file_get_contents(asset('upload/application_pdf_form_d_1.pdf'));

	    $postdata .= "\r\n\r\n";

	    $postdata .= "--" . $this->MULTIPART_BOUNDARY . "\r\n";

	    $postdata .= "Content-Disposition: form-data; name=\"payload\"\r\n\r\n";

	    $postdata .= $documentJSON;

	    $postdata .= "\r\n\r\n";

	    $postdata .= "--" . $this->MULTIPART_BOUNDARY . "--\r\n";

	}



		$status = $this->sendRequest($this->packageAppend . $packageId . '/documents', $documentJSON, $postdata, 'multipart/form-data; boundary=' . $this->MULTIPART_BOUNDARY);



		return $status;

	}





	//Send Package

	public function buildSend($packageId)

	{

		$build = array(

			'status' => 'SENT'

		);

		$sendJSON = json_encode($build);

		$this->sendRequest($this->packageAppend . $packageId, $sendJSON, NULL, 'application/json');

		return NULL;

	}



	//Sender signs consent and contract documents

	public function buildSign($packageId)

	{

		$build = array(

			'documents' => array(

				array(

					'id' => 'contract',

					'name' => 'Application Form'

				)

			)

		);

		$signJSON = json_encode($build);

		$signatureAppend = $this->packageAppend . $packageId . '/documents/signed_documents';

		$this->sendRequest($signatureAppend, $signJSON, NULL, 'application/json');

		return NULL;

	}



	//Get a session token

	public function buildToken($packageId)

	{

		$build = array(

			'packageId' => $packageId,

			'signerId' => 'Manager1'

		);

		$tokenJSON = json_encode($build);

		$token = json_decode($this->sendRequest($this->tokenAppend, $tokenJSON, NULL, 'application/json'), true);

		return $token;

	}



	//cURL function to send requests to eSignLive

	private function sendRequest($type, $json, $document, $contentType)

	{

		if (is_null($document) && is_null($contentType))

		{

			$postfields = array(

				"payload" => $json

			);

		}

		else if (is_null($document) && !is_null($contentType))

		{

			$postfields = $json;

		}

		else

		{

			$postfields = $document;

		}



		$headerOptions = array(

			'Authorization: Basic ' . $this->key,

			'Accept: application/json,application/zip,text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'

		);

		if (!is_null($contentType))

		{

			$headerOptions[] = "Content-Type: $contentType";

		}



		$ch = curl_init();

		curl_setopt($ch, CURLOPT_URL, $this->url . $type);

		curl_setopt($ch, CURLOPT_POST, true);

		curl_setopt($ch, CURLOPT_FAILONERROR, true);

		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);



		if (!is_null($postfields))

		{

			curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);

			if (!is_array($postfields))

			{

				$headerOptions[] = 'Content-Length: ' . strlen($postfields);

			}

		}



		curl_setopt($ch, CURLOPT_HTTPHEADER, $headerOptions);

		$response = curl_exec($ch);

		$err = curl_error($ch);

		curl_close($ch);

		

		if ($err)

		{

			return $err;

		}

		else

		{

			return $response;

		};

	}



	//cURL function to send requests to eSignLive

	public function sendGetRequest($type)

	{



		$headerOptions = array(

			'Content-Type: application/pdf',

			'Authorization: Basic '.$this->key

		);



		$ch = curl_init();

		curl_setopt($ch, CURLOPT_URL, $this->url . $type);

		curl_setopt($ch, CURLOPT_FAILONERROR, true);

		curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

		curl_setopt($ch, CURLOPT_HTTPHEADER, $headerOptions);

		curl_setopt($ch, CURLOPT_HEADER, 0);

		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

		$response = curl_exec($ch);



		$name       = time().'.pdf';

		$file 		= 'upload/filled/'.$name;

		$filename 	= 'filename.pdf';

		file_put_contents($file, $response);



		header('Content-type: application/pdf');

		header('Content-Disposition: inline; filename="' . $filename . '"');

		header('Content-Transfer-Encoding: binary');

		header('Content-Length: ' . filesize($file));

		header('Accept-Ranges: bytes');

		return $name;

		

	}



}
?>

Approved Answer
Duo_Liang | Posts: 3776

Reply to: how to add text field in pdf, while creating package

0 votes
Hi Sanket, From first glance of your code, i can only see "fields" attribute in your document and there's no "approvals" attribute. It seems you are only using "Field Injection" feature where you use pdf form to locate the field and use "name":"value" to inject values into your pdf. (After your package is created, these info becomes part of your pdf before signing) So my confusion is, did you have signature on your document or I just missed something? And when you said "allow users enter their account number or any other data as input during signing", I think you are meaning "Text Field". Per your currently design, I would suggest to use "Position Extraction" feature to locate your field. And below is some sample JSON for creating such a package:
{
  "roles": [
    {
      "id": "Signer1",
      "type": "SIGNER",
      "signers": [
        {
          "firstName": "John",
          "lastName": "Smith",
          "email": "[email protected]"
        }
      ],
      "name": "Signer1"
    }
  ],
   "documents": [
    {
      "approvals": [
        {
          "fields": [
            {
              "type": "SIGNATURE",
              "extract": true,
              "subtype": "FULLNAME",
              "name": "signature1"
            },
            {
              "type": "INPUT",
              "extract": true,
              "subtype": "TEXTFIELD",
              "name": "account_number"
            }
          ],
          "role": "Signer1"
        }
      ],
      "extract": true,
      "name": "Sample Contract"
    }
  ],
  "name": "Field Position Extraction Example",
  "status": "SENT"
}
Hope this could help! Duo

sanketr43 | Posts: 14

Reply to: how to add text field in pdf, while creating package

0 votes
okay. So I tried the solution you said. But then I got an error. Here is the problem, according to my code logic, I am first creating draft package, with only roles. then after that I am uploading PDF with content depositions. So, the problem, in the second i am unable to do “Position Extraction”. Is that possible in this setp? Or I have to directly do both content deposition, “Position Extraction” & create package with PDF upload during buildPackage.?

Duo_Liang | Posts: 3776

Reply to: how to add text field in pdf, while creating package

0 votes
Hi Sanket, Yes, you can separately create package and upload documents into two steps and it allows you to apply any kind of extraction methods. Position Extraction is being processed at the moment when you upload the document, so the workflow is fine in this case. About the error, can you share your revised code and the error message you received? Duo

Duo_Liang | Posts: 3776

Reply to: how to add text field in pdf, while creating package

0 votes
Hi Sanket, Yes, you can separately create package and upload documents into two steps and it allows you to apply any kind of extraction methods. Position Extraction is being processed at the moment when you upload the document, so the workflow is fine in this case. About the error, can you share your revised code and the error message you received? Duo

sanketr43 | Posts: 14

Reply to: how to add text field in pdf, while creating package

0 votes
Hello, So, I successfully integrated position extraction fields. but I am facing new issue. When I assign signature to user, so basically it has only 3 signature fields to be signed, but it show 4 signature due to which i am unable to submit form. it happen if i keep approval array. means postion extraction part. below is my code. also attached screenshot.
	public function buildDocument($packageId,$application_id)
	{



		$application  = Application::find($application_id);

		$payment_term = PaymentTerm::where('application_id',$application->id)->first();

		$director  	  = unserialize($application->directors);

		$user = Auth::user();

		$director_count = 1;

		$approvals   = array();

		$approvals[] = array (
				  'fields' => 
				  array (
				    0 => 
				    array (
				      'type' => 'INPUT',
				      'extract' => true,
				      'subtype' => 'TEXTFIELD',
				      'name' => 'name_of_account',
				    ),
				    1 => 
				    array (
				      'type' => 'INPUT',
				      'extract' => true,
				      'subtype' => 'TEXTFIELD',
				      'name' => 'bsb_number',
				    ),
				    2 => 
				    array (
				      'type' => 'INPUT',
				      'extract' => true,
				      'subtype' => 'TEXTFIELD',
				      'name' => 'account_number',
				    ),
				    3 => 
				    array (
				      'type' => 'INPUT',
				      'extract' => true,
				      'subtype' => 'TEXTFIELD',
				      'name' => 'institution_name',
				    ),
				    4 => 
				    array (
				      'type' => 'INPUT',
				      'extract' => true,
				      'subtype' => 'TEXTFIELD',
				      'name' => 'institution_address1',
				    ),
				    5 => 
				    array (
				      'type' => 'INPUT',
				      'extract' => true,
				      'subtype' => 'TEXTFIELD',
				      'name' => 'institution_address2',
				    ),
				  ),
				  'role' => 'Signer1',
				);

		$build = array(

			'fields' => array(

				array(

					'value' => $application->entity_name,

					'name' => 'customer_name',

				) ,

				array(

					'value' => $application->address,

					'name' => 'customer_address',

				) ,

				array(

					'value' => $application->phone,

					'name' => 'telephone',

				) ,

				array(

					'value' => $user->company_name,

					'name' => 'supplier_name',

				) ,

				array(

					'value' => $user->address,

					'name' => 'supplier_address',

				) ,

				array(

					'value' => $user->state.', '.$user->pincode,

					'name' => 'supplier_address2',

				) ,

				array(

					'value' => '',

					'name' => 'email',

				) ,

				array(

					'value' => $application->abn_number,

					'name' => 'abn_number',

				) ,

				array(

					'value' => $payment_term->installment,

					'name' => 'installment',

				) ,

				array(

					'value' => $payment_term->term,

					'name' => 'month',

				) ,

				array(

					'value' => $user->document_fee,

					'name' => 'handling_fee',

				)

			) ,

			'approvals' => $approvals,

			'extract' => true,

			'name' => 'GRENKE - EQUIPMENT LEASE AGREEMENT FOR BUSINESS PURPOSES',

			'id' => 'contract'

		);



		if(isset($director[0]['f_name'])){

		//directors

		$build['fields'][] = array(

								'value' => $director[0]['f_name'].' '.$director[0]['l_name'],

								'name' => 'director_name_1',

							);

		}



		if(isset($director[1]['f_name'])){

		$director_count = 2;

		$build['fields'][] = array(

								'value' => $director[1]['f_name'].' '.$director[1]['l_name'],

								'name' => 'director_name_2',

							); 

		}





		//items list 1st

		foreach ($application->items as $key => $value) {

			if(($key+1) == 5){ break; }

		$build['fields'][] = array(

									'value' => $value->description,

									'name' => 'item_'.($key+1),

								);


		$build['fields'][] = array(

									'value' => $value->quantity,

									'name' => 'qty_'.($key+1),

								);

		}



		//items list 2nd full

		if(count($application->items) > 4){

			foreach ($application->items as $key => $value) {

			$build['fields'][] = array(

									'value' => $value->description,

									'name' => 'item_1_'.($key+1),

								);

			$build['fields'][] = array(

									'value' => $value->manufacturer,

									'name' => 'manufacturer_1_'.($key+1),

								);

			$build['fields'][] = array(

									'value' => $value->quantity,

									'name' => 'qty_1_'.($key+1),

								);

			}	

		}

		//items list 3rd
	if(count($application->items) = 4){	
		foreach ($application->items as $key => $value) {

		$build['fields'][] = array(

									'value' => $value->description,

									'name' => 'item_2_'.($key+1),

								);

		$build['fields'][] = array(

									'value' => $value->manufacturer,

									'name' => 'manufacturer_2_'.($key+1),

								);

		$build['fields'][] = array(

									'value' => $value->quantity,

									'name' => 'qty_2_'.($key+1),

								);

		}
	}else{
		//enter message to first row
		$build['fields'][] = array(

									'value' => "Please see appendix",

									'name' => 'item_2_1',

								);

		$build['fields'][] = array(

									'value' => "/equipment schedule.",

									'name' => 'item_2_2',

								);
	}






		$documentJSON = json_encode($build);



	if($director_count == 2){

		$postdata = "--" . $this->MULTIPART_BOUNDARY . "\r\n";

	    $postdata .= "Content-Disposition: form-data; name=\"file\"; filename=\"application_pdf_form_d_2.pdf\"\r\n";

	    $postdata .= "Content-Type: application/pdf" . "\r\n\r\n";

	    $postdata .= file_get_contents(asset('upload/application_pdf_form_d_2.pdf'));

	    $postdata .= "\r\n\r\n";

	    $postdata .= "--" . $this->MULTIPART_BOUNDARY . "\r\n";

	    $postdata .= "Content-Disposition: form-data; name=\"payload\"\r\n\r\n";

	    $postdata .= $documentJSON;

	    $postdata .= "\r\n\r\n";

	    $postdata .= "--" . $this->MULTIPART_BOUNDARY . "--\r\n";

	}else{

		$postdata = "--" . $this->MULTIPART_BOUNDARY . "\r\n";

	    $postdata .= "Content-Disposition: form-data; name=\"file\"; filename=\"application_pdf_form_d_1.pdf\"\r\n";

	    $postdata .= "Content-Type: application/pdf" . "\r\n\r\n";

	    $postdata .= file_get_contents(asset('upload/application_pdf_form_d_1.pdf'));

	    $postdata .= "\r\n\r\n";

	    $postdata .= "--" . $this->MULTIPART_BOUNDARY . "\r\n";

	    $postdata .= "Content-Disposition: form-data; name=\"payload\"\r\n\r\n";

	    $postdata .= $documentJSON;

	    $postdata .= "\r\n\r\n";

	    $postdata .= "--" . $this->MULTIPART_BOUNDARY . "--\r\n";

	}



		$status = $this->sendRequest($this->packageAppend . $packageId . '/documents', $documentJSON, $postdata, 'multipart/form-data; boundary=' . $this->MULTIPART_BOUNDARY);



		return $status;

	}

Attachments
Duo_Liang | Posts: 3776

Reply to: how to add text field in pdf, while creating package

0 votes
Hi Sanket, First about the issue "appears one more signature", it's because that all fields (text fields/ label fields/ date fields) has to be binded to an approval(signature), if you don't explicitly bind them to one, OneSpan Sign will create an approval for you. In your case, you are using "Document Extraction" Feature to automatically assign signature approvals if I understood correctly. So OneSpan Sign will understand it in this way: besides 3 approvals extracted by Document Extraction, you also need one approval binding with all your text fields. So the solution is simple: #1. since you are using document extraction (guidance here), you can directly use Document Extraction to add your text fields by changing your pdf form's property name in this way:
[Signer1.Signature1.Textfield1]
[Signer1.Signature1.Textfield2]
[Signer1.Signature1.Textfield3]
[Signer1.Signature1.Textfield4]
If your concern is, you can't assign name/id for these fields, you don't know how to locate these textfields and retrieve signer's input, here's the way showing you how to locate these fields: Locate your TextField A field with type of “TEXTFIELD”, however, follows a different naming structure: “TEXTFIELD{10*N}”. This structure is all upper case plus 10 multiplied by the ending number in your PDF form. For example, if your “ZIP” field is named by [Signer1.Capture1.Textfield5], your textfield’s name will be “TEXTFIELD50”. You can refer to this blog for more explanation: Document Extraction and Customized Field Validator #2. Or, you can have one approval extracted through Position Extraction (by changing it's pdf form property name to a normal name like signer_signature instead of following ESL grammar) with all your fields and rest two approvals remained in Document Extraction. Hope this could help! Duo

Hello! Looks like you're enjoying the discussion, but haven't signed up for an account.

When you create an account, we remember exactly what you've read, so you always come right back where you left off