GMO サイン: 封筒署名依頼
この工程は GMO サイン に登録された封筒用文書ファイルを含む封筒の署名依頼を送付します。
Configs for this Auto Step
- conf_OAuth2
- C1: シークレットキー *
- cusId
- C2: 顧客ID *#{EL}
- accessUrl
- C3: アクセス先URL(例 api.gmosign.com) *#{EL}
- documentCode
- C4: ドキュメントコード が保存されている文字型データ項目 *
- envelopeName
- C5: 封筒名 が保存されている文字型データ項目 *
- documentName
- C6: ドキュメント名 が保存されている文字型データ項目 *
- signerName
- C7: 署名者名 が保存されている文字型データ項目 (複数設定する場合、1件ごとに改行してください) *
- signerEmail
- C8: 署名者アドレス が保存されている文字型データ項目 (1件ごとに改行してください) *
- signingPoint
- C9: 署名位置 x座標(左),y座標(下),x座標(右),y座標(上),ページ (パーセント指定、1件ごとに改行してください)#{EL}
- envelopeXid
- C10: 封筒トランザクションID を保存する文字型データ項目 *
Script (click to open)
/*
JSON例
・アクセストークン生成 AccessToken_Generate_Post
{
"secret_key": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"cus_id": "XXXXXXXXXX"
}
・封筒署名依頼 Envelope_SendRequest_Post
{
"secret_key": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"cus_id": "XXXXXXXXXX",
"access_token": "(取得したトークン)",
"envelope_name": "(configから、表示あり)",
"document_list": [
{
"document_code": "(文書登録で取得した値)",
"document_name": "(configから、表示あり)"
}
],
"partner_signer_list": [
{
"order_no": "(configの指定数から)",
"sign_type": "1",(立会人で固定)
"name": "(configから、表示あり)",
"email": "(configから)",
"is_send_mail": "1",(メールありで固定)
"document_list": [
{
"document_code": "(文書登録で取得した値)",
"request_type": "1",(署名で固定)
"signing_points": [
{
"signing_point_start_x": "(configから)",
"signing_point_start_y": "(configから)",
"signing_point_end_x": "(configから)",
"signing_point_end_y": "(configから)",
"page_no": "(configから)"
}
]
}
]
}
]
}
*/
main();
function main() {
//// == 工程コンフィグの参照 / Config Retrieving ==
//シークレットキーはHTTP認証設定のトークン直接指定に入れてもらう
const key = configs.getObject("conf_OAuth2").getToken();
const cusId = configs.get("cusId");
const accessUrl = configs.get("accessUrl") + "";
const dataId_envelopeXid = configs.get("envelopeXid");
//// == ワークフローデータの参照 / Data Retrieving ==
const documentCode = engine.findData(configs.getObject("documentCode")) + "";
const envelopeName = engine.findData(configs.getObject("envelopeName")) + "";
const documentName = engine.findData(configs.getObject("documentName")) + "";
const signerNamesArray = retrieveFilledArray('signerName', 'Signer Name');
const signerEmailsArray = retrieveFilledArray('signerEmail', 'Signer Email');
const signingPointsArray = retrieveFilledArray2('signingPoint', 'Signing Point');
// 件数チェック
if (signerNamesArray === null || signerNamesArray.length === 0) {
throw `No Signer Name.`;
}
if (signerEmailsArray === null || signerEmailsArray.length === 0) {
throw `No Signer Email.`;
}
//サイン位置指定なし(不可視署名を考慮)サイン位置の数はチェックしない
/* 署名者の最大数の情報はなかったのでチェックしない、ちなみに署名順は999までいける
if (signerNamesArray.length > MAX_SIGNER_NUM) {
throw `Number of Email Addresses exceeds the limit. The maximum number is ${MAX_SIGNER_NUM}.`;
}
*/
// 件数一致チェック
if (signerNamesArray.length !== signerEmailsArray.length) {
throw `Number of Signer Emails does not match the number of Signer Names.`;
}
//サイン位置指定なし(不可視署名を考慮して)サイン位置の数との一致チェックはしない
//// == 演算 / Calculating ==
//アクセストークン取得
let accessToken = getAccessToken(key, cusId, accessUrl);
//署名依頼
let envelopeXid = sendRequest(key, cusId, accessUrl, accessToken, documentCode, envelopeName, documentName, signerNamesArray, signerEmailsArray, signingPointsArray);
//// == ワークフローデータへの代入 / Data Updating ==
engine.setDataByNumber( dataId_envelopeXid, envelopeXid );
/* アクセスログがあれば
if ( dataId_log !== "" ) {
engine.setDataByNumber( dataId_log, accessLog );
}
*/
}
/**
* config から複数行のデータを読み出し、配列を生成する(configで文字型を指定するケース)
* データ項目が設定されていない場合は null を返す
* データ項目が設定されていて、中身が空の場合はエラー
* 空行を含む場合はエラー (最後に空行がひとつだけある場合は無視)
* @param {String} confName config 名
* @param {String} label エラー出力に使用するラベル
* @return {Array<String>} array 空文字列を含まない配列
*/
function retrieveFilledArray(confName, label) {
const dataDef = configs.getObject(confName);
if (dataDef === null) { // データ項目が設定されていない
return null;
}
const string = engine.findData(dataDef);
if (string === null || string === '') { // データ項目の中身が空
throw `Data item for ${label} is set but its content is empty.`;
}
const array = string.split('\n');
if (array[array.length - 1] === '') { // 最後に空行があれば削除
array.pop();
}
// 空行が残っている場合はエラー
const i = array.indexOf('');
if (i !== -1) {
throw `${label} at line ${i+1} is blank.`;
}
return array;
}
/**
* config から複数行のデータを読み出し、配列を生成する(configで直接入力のケース、空行を含む場合あり)
* @param {String} confName config 名
* @param {String} label エラー出力に使用するラベル
* @return {Array<String>} array 配列
*/
function retrieveFilledArray2(confName, label) {
const string = configs.get(confName);
if (string === null || string === '') { // データ項目の中身が空
return null;
}
const array = string.split('\n');
/* (不可視署名を考慮して)サイン位置なしを許容、空行をそのままにする
if (array[array.length - 1] === '') { // 最後に空行があれば削除
array.pop();
}
// 空行が残っている場合はエラー
const i = array.indexOf('');
if (i !== -1) {
throw `${label} at line ${i+1} is blank.`;
}
*/
return array;
}
/**
* アクセストークン取得
* @param {String} key シークレットキー
* @param {String} cusId 顧客ID
* @param {String} accessUrl 接続先URL
* @returns {String} アクセストークン
*/
function getAccessToken(key, cusId, accessUrl) {
//JSON準備
let requestObj = {};
requestObj.secret_key = key;
requestObj.cus_id = cusId;
//HTTPリクエスト送付
const url = "https://" + accessUrl + "/agree-api/v0/api/accesstoken/generate";
const response = httpClient.begin()
.body( JSON.stringify(requestObj), "application/json" )
.post(url);
const status = response.getStatusCode();
const responseStr = response.getResponseAsString();
if (status !== 200) {
engine.log(responseStr);
throw `Failed to get access token. status: ${status}`;
}
engine.log("responseStr:" + responseStr);//検証用
const json = JSON.parse(responseStr);
if ( json['status'] !== "0") {
throw `Failed to get acess token. status: ${json['status']}. message: ${json['message']}`;
}
return json['result']['access_token'];
}
/**
* 署名依頼
* @param {String} key シークレットキー
* @param {String} cusId 顧客ID
* @param {String} accessUrl 接続先URL
* @param {String} accessToken アクセストークン
* @param {String} documentCode 文書コード
* @param {String} envelopeName 封筒名
* @param {String} documentName 文書名
* @param {String} signerNamesArray 署名者名
* @param {String} signerEmailsArray 署名者メールアドレス
* @param {String} signingPointsArray 署名位置
* @returns {String} 封筒トランザクションID
*/
function sendRequest(key, cusId, accessUrl, accessToken, documentCode, envelopeName, documentName, signerNamesArray, signerEmailsArray, signingPointsArray) {
//JSON準備
let requestObj = {};
requestObj.secret_key = key;
requestObj.cus_id = cusId;
requestObj.access_token = accessToken;
requestObj.envelope_name = envelopeName;
let documentListArray = [];
let documentListObj = {};
documentListObj.document_code = documentCode;
documentListObj.document_name = documentName;
documentListArray[0] = documentListObj;
requestObj.document_list = documentListArray;
let partnerSignerListArray = [];
for (let i = 0; i < signerNamesArray.length; i++) {
let partnerSignerListObj = {};
partnerSignerListObj.order_no = i+1;//文字でなく数値で問題なし
partnerSignerListObj.sign_type = "1";
partnerSignerListObj.name = signerNamesArray[i];
partnerSignerListObj.email = signerEmailsArray[i];
partnerSignerListObj.is_send_mail = "1";
let pslDocumentListArray = [];
let pslDocumentListObj = {};
pslDocumentListObj.document_code = documentCode;
pslDocumentListObj.request_type = "1";
//サイン位置指定がある場合のみ
if (signingPointsArray) {
let signingPointArray = signingPointsArray[i].split(",");
//位置指定のパラメータ数が正しいか
if (signingPointArray.length == 5) {
let pslSigningPointsListArray = [];
let pslSigningPointsListObj = {};
pslSigningPointsListObj.signing_point_start_x = signingPointArray[0];
pslSigningPointsListObj.signing_point_start_y = signingPointArray[1];
pslSigningPointsListObj.signing_point_end_x = signingPointArray[2];
pslSigningPointsListObj.signing_point_end_y = signingPointArray[3];
pslSigningPointsListObj.page_no = signingPointArray[4];
pslSigningPointsListArray[0] = pslSigningPointsListObj;
pslDocumentListObj.signing_points = pslSigningPointsListArray;
} else {
throw `Signing Point ${i+1} Num invalid.`;
}
}
pslDocumentListArray[0] = pslDocumentListObj;
partnerSignerListObj.document_list = pslDocumentListArray;
partnerSignerListArray[i] = partnerSignerListObj;
}
requestObj.partner_signer_list = partnerSignerListArray;
engine.log("requestObj:" + JSON.stringify(requestObj));//検証用
//HTTPリクエスト送付
const url = "https://" + accessUrl + "/agree-api/v0/api/envelope/sendRequest";
const response = httpClient.begin()
.body( JSON.stringify(requestObj), "application/json" )
.post(url);
const status = response.getStatusCode();
const responseStr = response.getResponseAsString();
if (status !== 200) {
engine.log(responseStr);
throw `Failed to regist file. status: ${status}`;
}
engine.log("responseStr:" + responseStr);//検証用
const json = JSON.parse(responseStr);
if ( json['status'] !== "0") {
throw `Failed to send request. status: ${json['status']}. message: ${json['message']}`;
}
return json['result']['envelope_xid'];
}
Download
- gmo-sign-envelope-send-request.xml
- 2024-07-04 (C) Questetra, Inc. (MIT License)
自由改変可能な JavaScript (ECMAScript) コードです。いかなる保証もありません。
(アドオン自動工程のインストールは Professional editionでのみ可能です)
(アドオン自動工程のインストールは Professional editionでのみ可能です)
Notes
- 「GMO サイン」はGMOグローバルサイン・ホールディングス株式会社のサービスです。
- GMO サインで電子署名させる場合には、「GMO Sign: 封筒用文書登録」・「GMO Sign: 封筒署名依頼」・「GMO Sign: 封筒署名ステータス確認」を組み合わせて使う必要があります。また「GMO サイン: 文書ファイルURL取得」を使うと署名済ファイル取得ができます。
- 「シークレットキー」・「顧客ID」・「アクセス先URL」はGMOグローバルサイン・ホールディングス株式会社より指定された値を指定してください。「シークレットキー」は「HTTP認証設定」の「トークン直接指定」で指定してください。
- 「署名位置」を指定しない場合、「不可視署名」となります。
Capture

