Node.js中的協定工作流
許多業務應用程式和流程都需要諸如建議書和協定之類的文檔。 PDF文檔確保檔案更安全,修改更少。 它們還提供數字簽名支援,以便您的客戶能夠快速、輕鬆地完成其文檔。 Adobe Acrobat Services個API可輕鬆將PDF功能納入Web應用程式。
你能學到的
在本操作教程中,瞭解如何將PDF服務添加到Node.js應用程式以數字化協定進程。
相關API和資源
正在設定Adobe Acrobat Services
若要開始,請設定憑據以使用Adobe Acrobat Services。 註冊帳戶並使用Node.js Quickstart驗證憑據是否有效,然後再將該功能整合到較大的應用程式中。
首先,獲取Adobe開發商帳戶。 然後,在開始頁面上,在「建立新憑據」下選擇「開始」選項。 您可以註冊免費試用版,該版本提供1,000個可在6個月內使用的文檔交易記錄。
在以下「建立新身份證明」頁中,系統將提示您在PDF嵌入API和PDF服務API之間做出選擇。
選擇PDF服務API。
輸入應用程式的名稱並選中標有 建立個性化代碼示例 的框。 選中此框會在代碼示例中自動嵌入您的憑據。 如果未選中此框,則必須手動將憑據添加到應用程式。
為應用程式類型選擇Node.js,然後按一下建立憑據。
幾分鐘後,.zip檔案開始下載,其中包含您的憑據的示例項目。 Acrobat Services的Node.js包已作為示例項目代碼的一部分包含。
手動配置示例項目
如果選擇不從「建立新身份證明」頁下載示例項目,則還可以手動設定項目。
從GitHub下載代碼(未嵌入憑據)。 如果使用此版本的代碼,則必須先將憑據添加到pdftools-api-credentials.json檔案中,然後才能使用:
{
"client_credentials": {
"client_id": "<client_id>",
"client_secret": "<client_secret>"
},
"service_account_credentials": {
"organization_id": "<organization_id>",
"account_id": "<technical_account_id>",
"private_key_file": "<private_key_file_path>"
}
}
對於您自己的應用程式,您需要將私鑰檔案和憑據檔案複製到您的應用程式源。
必須為Acrobat Services安裝Node.js包。 要安裝軟體包,請使用以下命令:
npm install --save @adobe/documentservices-pdftools-node-sdk
設定日誌記錄
此處的示例使用Express作為應用程式框架。 它們還使用log4js進行應用程式日誌記錄。 使用log4js ,您可以輕鬆將日誌記錄直接到控制台或輸出到檔案:
const log4js = require('log4js');
const logger = log4js.getLogger();
log4js.configure( {
appenders: { fileAppender: { type:'file', filename: './logs/applicationlog.txt'}},
categories: { default: {appenders: ['fileAppender'], level:'info'}}
});
logger.level = 'info';
logger.info('Application started')
上述代碼將記錄的資料寫入檔案。/logs/applicationlog.txt。 如果希望它寫入控制台,則可以注釋掉對log4js.configure的調用。
將Word檔案轉換為PDF
協定和建議通常都寫在生產力應用程式中,比如Microsoft·Word。 要接受此格式的文檔並將文檔轉換為PDF,您可以為應用程式添加功能。 讓我們看一下如何在Express應用程式中上載和保存文檔並將其保存到檔案系統。
在應用程式的HTML中,添加一個檔案元素和一個用於開始上載的按鈕:
<input type="file" name="source" id="source" />
<button onclick="upload()" >Upload</button>
在頁的JavaScript中,使用fetch函式非同步上載檔案:
function upload()
{
let formData = new FormData();
var selectedFile = document.getElementById('source').files[0];
formData.append("source", selectedFile);
fetch('documentUpload', {method:"POST", body:formData});
}
選擇一個資料夾以接受上載的檔案。 應用程式需要指向此資料夾的路徑。 使用與__dirname聯接的相對路徑查找絕對路徑:
const uploadFolder = path.join(__dirname, "../uploads");
由於檔案是通過帖子提交的,因此您必須對伺服器端的帖子消息做出響應:
router.post('/', (req, res, next) => {
console.log('uploading')
if(!req.files || Object.keys(req.files).length === 0) {
return res.status(400).send('No files were uploaded');
}
const uploadPath = path.join(uploadFolder, req.files.source.name);
var buffer = req.files.source.data;
var result = {"success":true};
fs.writeFile(uploadPath, buffer, 'binary', (err)=> {
if(err) {
result.success = false;
}
res.json(result);
});
});
執行此函式後,檔案將保存在應用程式上載資料夾中,並可供進一步處理。
接下來,將檔案從其本機格式轉換為PDF。 您以前下載的示例代碼包含名為create-pdf-from-docx.js的指令碼,用於將文檔轉換為PDF。 以下函式convertDocumentToPDF將上載的文檔轉換為其他資料夾中的PDF:
function convertDocumentToPDF(sourcePath, destinationPath)
{
try {
const credentials = PDFToolsSDK.Credentials
.serviceAccountCredentialsBuilder()
.fromFile("pdftools-api-credentials.json")
.build();
const executionContext =
PDFToolsSDK.ExecutionContext.create(credentials),
createPdfOperation = PDFToolsSDK.CreatePDF.Operation.createNew();
const docxReadableStream = fs.createReadStream(sourcePath);
const input = PDFToolsSDK.FileRef.createFromStream(
docxReadableStream,
PDFToolsSDK.CreatePDF.SupportedSourceFormat.docx);
createPdfOperation.setInput(input);
createPdfOperation.execute(executionContext)
.then(result => result.saveAsFile(destinationPath))
.catch(err => {
logger.erorr('Exception encountered while executing operation');
})
}
catch(err) {
logger.error(err);
}
}
您可以注意到帶有代碼的一般模式:
該代碼生成證書對象和執行上下文,初始化一些操作,然後使用執行上下文執行該操作。 在整個示例代碼中,您可以看到這種模式。
通過對上載函式進行一些添加,以便調用此函式,用戶上載的Word文檔現在將自動轉換為PDF。
以下代碼為轉換的PDF生成目標路徑並啟動轉換:
const documentFolder = path.join(__dirname, "../docs");
var extPosition = req.files.source.name.lastIndexOf('.') - 1;
if(extPosition < 0 ) {
extPosition = req.files.source.name.length
}
const destinationName = path.join(documentFolder,
req.files.source.name.substring(0, extPosition) + '.pdf');
console.log(destinationName);
logger.info('converting to ${destinationName}')
convertDocumentToPDF(uploadPath, destinationName);
將其他檔案類型轉換為PDF
文檔工具包將其它格式轉換為PDF,如靜態HTML,另一種常用文檔類型。 該工具包接受打包為.zip檔案的HTML文檔,該文檔引用的所有資源(CSS檔案、影像和其他檔案)都位於同一.zip檔案中。 HTML文檔本身必須命名index.html,並放置在.zip檔案的根中。
要轉換包含HTML的.zip檔案,請使用以下代碼:
//Create an HTML to PDF operation and provide the source file to it
htmlToPDFOperation = PDFToolsSdk.CreatePDF.Operation.createNew();
const input = PDFToolsSdk.FileRef.createFromLocalFile(sourceZipFile);
htmlToPDFOperation.setInput(input);
// custom function for setting options
setCustomOptions(htmlToPDFOperation);
// Execute the operation and Save the result to the specified location.
htmlToPDFOperation.execute(executionContext)
.then(result => result.saveAsFile(destinationPdfFile))
.catch(err => {
logger.error('Exception encountered while executing operation');
});
函式setCustomOptions指定其他PDF設定,如頁面大小。 在此,您可以看到將頁面大小設定為11.5 x 11英吋的函式:
const setCustomOptions = (htmlToPDFOperation) => {
const pageLayout = new PDFToolsSdk.CreatePDF.options.PageLayout();
pageLayout.setPageSize(11.5, 8);
const htmlToPdfOptions =
new PDFToolsSdk.CreatePDF.options.html.CreatePDFFromHtmlOptions.Builder()
.includesHeaderFooter(true)
.withPageLayout(pageLayout)
.build();
htmlToPDFOperation.setOptions(htmlToPdfOptions);
};
開啟包含某些術語的HTML文檔時,在瀏覽器中可獲得以下內容:
此文檔的源由CSS檔案和HTML檔案組成:
處理HTML檔案後,您的PDF格式相同:
添加頁面
使用PDF檔案的另一個常見操作是將可能具有標準文本(如術語清單)的頁面附加到末尾。 文檔工具包可以將多個PDF文檔合併為單個文檔。 如果您有文檔路徑清單(在sourceFileList中),則可以將每個檔案的檔案引用添加到組合操作的對象。
當執行組合操作時,它提供一個包含源內容的單個檔案。 您可以在對象上使用saveAsFile將檔案保留到儲存。
const executionContext = PDFToolsSDK.ExecutionContext.create(credentials);
var combineOperation = PDFToolsSDK.CombineFiles.Operation.createNew();
sourceFileList.forEach(f => {
var combinedSource = PDFToolsSDK.FileRef.createFromLocalFile(f);
console.log(f);
combineOperation.addInput(combinedSource);
});
combineOperation.execute(executionContext)
.then(result=>result.saveAsFile(destinationFile))
.catch(err => {
logger.error(err.message);
});
顯示PDF文檔
您已對PDF檔案執行了多項操作,但最終,您的用戶必須查看文檔。 可以使用Adobe的PDF嵌入API將文檔嵌入到網頁中。
在顯示PDF的頁面上,添加一個<div />元素以保存文檔,並為其提供ID。 您很快就使用此ID。 在網頁中,包括對AdobeJavaScript庫的<script />引用:
<script src="https://documentcloud.adobe.com/view-sdk/main.js"></script>
您最後需要的代碼位是一個函式,在載入Adobe PDF嵌入API JavaScript後,該函式將顯示文檔。 當您收到通過adobe_dc_view_sdk.ready事件載入指令碼的通知時,請建立新的AdobeDC.View對象。 此對象需要您的客戶端ID和先前建立的元素的ID。 在Adobe Developer Console中查找您的客戶端ID。 當您查看先前生成憑據時建立的應用程式的設定時,將顯示客戶端ID。
其他PDF選項
Adobe PDF嵌入API演示使您能夠預覽嵌入PDF文檔的各種其他選項。
您可以開啟和關閉各種選項,並立即查看它們的呈現方式。 當您找到喜歡的組合時,按一下 </>生成代碼 按鈕,使用這些選項生成實際的HTML代碼。
添加數字簽名和安全性
文檔準備好後,您可以使用Adobe Sign添加數字簽名以供批准。 此功能與您到目前為止使用的功能有一點不同。 對於數字簽名,必須將應用程式配置為使用OAuth進行用戶身份驗證。
設定應用程式的第一步是註冊您的應用程式以將OAuth用於Adobe Sign。 登錄後,通過按一下 帳戶 導航到用於建立應用程式的螢幕,然後開啟 Adobe SignAPI 部分,然後按一下 API應用程式 以開啟已註冊的應用程式清單。
要建立新應用程式條目,請按一下右上角的加號表徵圖。
在開啟的窗口中,輸入應用程式名稱和顯示名稱。 為域選擇客戶,然後按一下保存。
建立應用程式後,可以從清單中選擇它,然後按一下 為應用程式 配置OAuth。 選擇選項。 在重定向URL中,輸入應用程式的URL。 可以在此處輸入多個URL。 對於您正在測試的應用程式,其值為:
http://localhost:3000/signed-in
使用OAuth獲取令牌的過程是標準的。 您的應用程式將用戶引導到要登錄的URL。 用戶成功登錄後,
在頁面的查詢參數中包含附加資訊時,會將它們重定向回應用程式。
對於登錄URL,您的應用程式必須傳遞您的客戶端ID、重定向URL以及所需作用域的清單。
URL的模式如下所示:
https://secure.adobesign.com/public/oauth?
redirect_uri=&
response_type=code&
client_id=&
scope=
系統提示用戶登錄其Adobe Sign的ID。 登錄後,系統會詢問他們是否向應用程式提供權限。
如果用戶按一下重定向URL上的允許訪問,則名為代碼的查詢參數將傳遞授權代碼:
https://YourServer.com/?code=<授權代碼>&api_access_point=https://api.adobesign.com&web_access_point=https://secure.adobesign.com
將此代碼連同您的客戶端ID和客戶端密鑰一起發佈到Adobe Sign伺服器,提供了訪問該服務的訪問令牌。 保存參數api_access_point和web_access_point中的值。 這些值用於進一步的請求。
var requestURL = ' ${api_access_point}oauth/token?code=${code}'
+'&client_id=${client_id}'
+'&client_secret=${client_secret}&'
+'redirect_uri=${redirect_url}&'
+'grant_type=authorization_code';
request.post(requestURL, {form: { }
}, (err,response,body)=>{
var token_response = JSON.parse(body)
var access_token = token_response.access_token;
console.log(access_token);
});
當文檔需要簽名時,必須首先上載文檔。 您的應用程式可以將文檔上載到請求OAUTH令牌時收到的api_access_point值。 終結點為/api/rest/v6/transientDocuments。 請求資料如下所示:
POST /api/rest/v6/transientDocuments HTTP/1.1
Host: api.na1.adobesign.com
Authorization: Bearer MvyABjNotARealTokenHkYyi
Content-Type: multipart/form-data
Content-Disposition: form-data; name=";File"; filename="MyPDF.pdf"
<PDF CONTENT>
在您的應用程式中,使用以下代碼生成請求:
var uploadRequest = {
'method': 'POST',
'url': '${oauthParameters.signin_domain}/api/rest/v6/transientDocuments',
'headers': {
'Authorization': 'Bearer ${auth_token}'
},
formData: {
'File': {
'value': fs.createReadStream(documentPath),
'options': {
'filename': fileName,
'contentType': null
}
}
}
};
request(uploadRequest, (error, response) => {
if (error) throw new Error(error);
var jsonResponse = JSON.parse(response.body);
var transientDocumentId = jsonResponse.transientDocumentId;
logger.info('transientDocumentId:', transientDocumentId)
});
請求返回transientID值。 文檔已上載,但尚未發送。 若要發送文檔,請使用transientID請求發送文檔。
首先構建包含要簽名的文檔資訊的JSON對象。 在下面的代碼中,變數transientDocumentId包含來自上述代碼的ID,而agreementDescription包含描述需要簽名的協定的文本。 要簽署文檔的人員在participantSetsInfo中按其電子郵件地址和角色列出。
var requestBody = {
"fileInfos":[
{"transientDocumentId":transientDocumentId}],
"name":agreementDescription,
"participantSetsInfo":[
{"memberInfos":[{"email":"user@domain.com"}],
"order":1,"role":"SIGNER"}
],
"signatureType":"ESIGN","state":"IN_PROCESS"
};
發送此Web請求將生成簽名請求並返回JSON對象,其ID為協定請求:
request(requestBody, function (error, response) {
if (error) throw new Error(error);
var JSONResponse = JSON.parse(response.body);
var requestId = JSONResponse.id;
});
如果簽名者忘記簽名並需要另一封通知電子郵件,請使用先前收到的ID再次發送通知。 唯一的區別是您還必須添加參與方的參與方ID。 您可以通過向/agreements/{agreementID}/members發送GET請求來獲取參與者ID。
要請求發送提醒,請首先生成描述該請求的JSON對象。 最小對象需要參與者ID的清單和提醒狀態(「ACTIVE」、「COMPLETE」或「CANCELLED」)。
請求可以有附加資訊,例如將顯示給用戶的「注釋」值。 或者,等待發送提醒的延遲(以小時為單位)(在firstReminderDelay中),以及提醒頻率(在欄位"frequency"中),該提醒頻率接受DAILY_UNTIL_SIGNED、EVERY_THIRD_DAY_UNTIL_SIGNED或WEEKLY_UNTIL_UNTIL_SIGNED_SINTIN_SIGNED_S_S。
var requestBody = {
//participantList is an array of participant ID strings
"recipientParticipantIds":participantList
,"status":"ACTIVE",
"note":"This is a reminder to sign out important agreement."
}
var reminderRequest = {
'method': 'POST',
'url': '${oauthParameters.signin_domain}/api/rest/v6/agreements/${agreementID}/reminders',
'headers': {
'Authorization': `Bearer ${access_token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(requestBody)
};
request(reminderRequest, function (error, response) {
});
這就是發出提醒請求的全部。
建立Web表單
您還可以使用Adobe SignAPI建立Web表單。 Web表單使您能夠將表單嵌入到網頁中或直接連結到該網頁。 建立Web表單後,它還會顯示在Adobe Sign控制台的Web表單中。 可以建立具有DRAFT狀態的Web表單以用於增量構建、用於編輯Web表單域的AUTHORING狀態以及立即托管表單的ACTIVE狀態。
要建立Web表單,請使用表單transientDocumentId。 確定窗體的標題和初始化窗體的狀態。
var requestBody = {
"fileInfos": [
{
"transientDocumentId": transientDocumentId
}
],
"name": webFormTitle,
"state": status,
"widgetParticipantSetInfo": {
"memberInfos": [ { "email": "" } ],
"role": "SIGNER"
}
}
var createWebFormRequest = {
'method': 'POST',
'url': `${oauthParameters.signin_domain}/api/rest/v6/widgets`,
'headers': {
'Authorization': `Bearer ${access_token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(requestBody)
}
request(createWebFormRequest, function (error, response) {
var jsonResp = JSON.parse(response.body);
var webFormID = jsonResp.id;
});
您現在可以嵌入或連結到文檔。
後續步驟
如您從快速啟動和提供的代碼中所看到的,使用帶有Adobe Acrobat Services個API的Node可輕鬆實現PDF和數字文檔批准過程。 Adobe的API無縫整合到您現有的客戶端應用程式中。
要發現調用所需的作用域,或查看如何生成調用,可以從Rest API文檔生成示例調用。 Quickstarts還演示了Adobe Acrobat Services API進程的其他功能和檔案格式。
您可以向應用程式添加多種PDF功能,使用戶能夠快速、輕鬆地查看和簽署其文檔等。 若要開始,請立即簽出Adobe Acrobat Services。