2022-09-12
(C) Questetra, Inc. (MIT License)
2
https://support.questetra.com/bpmn-icons/service-task-stripe-invoice-create/
https://support.questetra.com/ja/bpmn-icons/service-task-stripe-invoice-create/
This item creates a draft invoice on Stripe. The created invoice remains a draft until you finalize it,
which allows you to send the invoice or charge the customer.
この工程は、Stripe 上に請求書のドラフト(下書き)を作成します。顧客に請求書の送付やの課金を行うには、 別途、ドラフト状態の請求書を確定させる必要があります。
-
-
-
-
-
-
-
-
-
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAvJJREFUWEfF
l19I01EUxz/XKZqWNbVS6cH+UfSUGQlCD0EQRCkoFDkDUzENi6IgkB4sKEgjDStFnVlzalC9+BBR
IEFBEeVbFP3R/lhRpLRpKHO78dtv021u+pszfnv87Zzv+dxzzj33XoHOP6E1fvleGe9KJF/CDiSZ
CDIAo8d/BMkggn4BfVE27rX0ir9atOcEKC6WqdEOTkuoAOK0iALjAponY7jY0SF+zOYzK0CJSVYI
uAQkaAwcaDYm4VS7VTSH8g8JUFokryOpnGdgfzdBk7lTHAmmFRSgxCS7BBxYkOAeEQnd7VZRGKg5
A2BBVz4z2oxM+AF4at60kCsP1JJQ6dsTUwBKtxscvI+g4bRyjzljWOfdHVMAZSZZL+G4VpVI7AQ0
tFnFCUXDDaAMGWciv8PY55HEV3zHDTaSlWHlBigzySIJlvmoxsbBxHj4ngIOtllFpxug1CTNQMls
MjnbIS0d7t6etmpshe9DcKEmfACg3WwVpSpAoXyFIDNQZuMm2J2rfk1Ng6XL4NlTSE4Blwt6LOB0
QtEhkBKGvsCdHli9FnLzoe8h9L8MASfpN3eJLd4MDPscLFMeTTcgOhocDjXNi5fAr5+wYqUa+NOA
ClF9FiYnVdtHD2DnLpiYgNhYqKmGr5+DQoyYrSLJCyCDmdQ1gtEIdpv6r7LKbgscroKr9ZC/Dzpa
VIBr9VBeBYYoiDKotkLA/V7/svnGMVuFYuLugaAAx05C+ipIWa4KShe8eA7ZOdB4GQr2TwMMfoSM
NfDuLazfALY/YLdD9y148zp4GXwBgpag9goYk2BkGJ48hj15MDoK8QnQUAtZ26DrJrRaVMBRO9Sd
h7wC2JylAp87A9+G5ipBiCbU0ttbs6HiqFqCkA0XTCigCefchqFgFsWrO2TggxZcP5vpbRjJIAo7
rMfBbxDpPoo941i/w0gB0P04ViB0vZB4m0nXK5kXQtdL6X/JRLjXcp9M6Pcw8ULo+jTznXK6PU7n
O2q1+v0D2nRCMMki7aoAAAAASUVORK5CYII=
{
configs.put('conf_Auth', 'Stripe');
// 顧客 ID が保存されている文字型データ項目(単一行)を準備し、設定
const customerIdDef = engine.createDataDefinition('顧客 ID', 1, 'q_customerId', 'STRING_TEXTFIELD');
engine.setData(customerIdDef, customerId);
configs.putObject('conf_CustomerId_V2', customerIdDef);
configs.put('conf_Description', description);
configs.put('conf_Currency', '');
// ラインアイテムの情報を保存したテーブル型データ項目を準備し、設定
const tableDef = engine.createDataDefinition('商品名、単価、数量の一覧', 2, 'q_lineItems', 'LIST');
tableDef.addSubDataDefinition('商品名', 'q_description', 'STRING');
// 単価、数量は DECIMAL 型、小数点以下の桁数 2、小数点ピリオド、桁区切りなしで設定
tableDef.addDecimalSubDataDefinition('単価', 'q_unitAmount', 2, true, false);
tableDef.addDecimalSubDataDefinition('数量', 'q_quantity', 2, true, false);
configs.putObject('conf_LineItems', tableDef);
if (lineItems.length > 0) {
const table = tableDef.createListArray(); // ScriptListArray
lineItems.forEach(lineItem => {
const newRow = table.addRow();
lineItem.forEach((cellString, i) => {
newRow.setCol(i, cellString);
});
});
engine.setData(tableDef, table);
}
// 請求書ドラフトの ID を保存する文字型データ項目(単一行)を準備し、設定
const invoiceIdDef = engine.createDataDefinition('請求書 ID', 3, 'q_invoiceId', 'STRING_TEXTFIELD');
engine.setData(invoiceIdDef, '事前文字列');
configs.putObject('conf_InvoiceId', invoiceIdDef);
// 請求書ドラフトの URL を保存する文字型データ項目(単一行)を準備し、設定
const invoiceUrlDef = engine.createDataDefinition('請求書 URL', 4, 'q_invoiceUrl', 'STRING_TEXTFIELD');
engine.setData(invoiceUrlDef, '事前文字列');
configs.putObject('conf_InvoiceUrl', invoiceUrlDef);
return {invoiceIdDef, invoiceUrlDef};
}
const SAMPLE_LINE_ITEMS = [
['テスト商品', '50', '1']
];
/**
* 顧客 ID が空
*/
test('Customer ID is blank', () => {
prepareConfigs('', '請求書の説明', SAMPLE_LINE_ITEMS);
expect(execute).toThrow('Customer ID is blank.');
});
/**
* ラインアイテムが多すぎて HTTP リクエスト数制限を超える
*/
test('Too many line items', () => {
const lineItems = [];
for (let i = 0; i < httpClient.getRequestingLimit(); i++) {
lineItems.push([`テスト商品 ${i + 1}`, '50', '1']);
}
prepareConfigs('cus_000001', '請求書の説明', lineItems);
expect(execute).toThrow('Too many line items. Number of necessary HTTP requests exceeds the limit.');
});
/**
* ラインアイテムの形式が不正 - 2 列以下
*/
test('Invalid line items - too few columns', () => {
prepareConfigs('cus_000001', '請求書の説明', []);
// 新しいテーブル型データ項目を作成し、設定
const tableDef = engine.createDataDefinition('新しいテーブル', 5, 'q_newTable', 'LIST');
tableDef.addSubDataDefinition('商品名', 'q_description', 'STRING');
tableDef.addSubDataDefinition('単価', 'q_unitAmount', 'DECIMAL');
// 数量の列がない
const table = tableDef.createListArray(); // ScriptListArray
const newRow = table.addRow();
newRow.setCol(0, 'テスト商品');
newRow.setCol(1, '50');
engine.setData(tableDef, table);
configs.putObject('conf_LineItems', tableDef);
expect(execute).toThrow('The line items must include item description, unit amount, and quantity.');
});
/**
* ラインアイテムの形式が不正 - 1 列目が文字列型でない
*/
test('Invalid line items - 1st column is not STRING', () => {
prepareConfigs('cus_000001', '請求書の説明', []);
// 新しいテーブル型データ項目を作成し、設定
const tableDef = engine.createDataDefinition('新しいテーブル', 5, 'q_newTable', 'LIST');
tableDef.addSubDataDefinition('商品名', 'q_description', 'DECIMAL'); // STRING でない
tableDef.addSubDataDefinition('単価', 'q_unitAmount', 'DECIMAL');
tableDef.addSubDataDefinition('数量', 'q_quantity', 'DECIMAL');
const table = tableDef.createListArray(); // ScriptListArray
const newRow = table.addRow();
newRow.setCol(0, '0');
newRow.setCol(1, '50');
newRow.setCol(2, '1');
engine.setData(tableDef, table);
configs.putObject('conf_LineItems', tableDef);
expect(execute).toThrow('Line item name (1st column) must be STRING.');
});
/**
* ラインアイテムの形式が不正 - 2 列目が数値型でない
*/
test('Invalid line items - 2nd column is not DECIMAL', () => {
prepareConfigs('cus_000001', '請求書の説明', []);
// 新しいテーブル型データ項目を作成し、設定
const tableDef = engine.createDataDefinition('新しいテーブル', 5, 'q_newTable', 'LIST');
tableDef.addSubDataDefinition('商品名', 'q_description', 'STRING');
tableDef.addSubDataDefinition('単価', 'q_unitAmount', 'STRING'); // DECIMAL でない
tableDef.addSubDataDefinition('数量', 'q_quantity', 'DECIMAL');
const table = tableDef.createListArray(); // ScriptListArray
const newRow = table.addRow();
newRow.setCol(0, 'テスト商品');
newRow.setCol(1, '50');
newRow.setCol(2, '1');
engine.setData(tableDef, table);
configs.putObject('conf_LineItems', tableDef);
expect(execute).toThrow('Line item unit amount (2nd column) must be DECIMAL.');
});
/**
* ラインアイテムの形式が不正 - 3 列目が数値型でない
*/
test('Invalid line items - 3rd column is not DECIMAL', () => {
prepareConfigs('cus_000001', '請求書の説明', []);
// 新しいテーブル型データ項目を作成し、設定
const tableDef = engine.createDataDefinition('新しいテーブル', 5, 'q_newTable', 'LIST');
tableDef.addSubDataDefinition('商品名', 'q_description', 'STRING');
tableDef.addSubDataDefinition('単価', 'q_unitAmount', 'DECIMAL');
tableDef.addSubDataDefinition('数量', 'q_quantity', 'STRING'); // DECIMAL でない
const table = tableDef.createListArray(); // ScriptListArray
const newRow = table.addRow();
newRow.setCol(0, 'テスト商品');
newRow.setCol(1, '50');
newRow.setCol(2, '1');
engine.setData(tableDef, table);
configs.putObject('conf_LineItems', tableDef);
expect(execute).toThrow('Line item quantity (3rd column) must be DECIMAL.');
});
/**
* ラインアイテムの形式が不正 - 商品名が空の行がある
*/
test('Invalid line items - Item name is blank', () => {
const lineItems = [
['テスト商品 1', '50', '1'],
['', '150', '2'],
['テスト商品 3', '100', '3']
];
prepareConfigs('cus_000001', '請求書の説明', lineItems);
expect(execute).toThrow('Line item 2 is invalid. Item name must not be blank.');
});
/**
* ラインアイテムの形式が不正 - 単価が小数
*/
test('Invalid line items - Unit amount is decimal', () => {
const lineItems = [
['テスト商品 1', '50.00', '1'], // 小数点以下が 0 の行ではエラーにならない
['テスト商品 2', '150', '2'],
['テスト商品 3', '100.05', '3'] // この行でエラー
];
prepareConfigs('cus_000001', '請求書の説明', lineItems);
expect(execute).toThrow('Line item 3 is invalid. Unit amount must be integer.');
});
/**
* ラインアイテムの形式が不正 - 単価が負の整数
*/
test('Invalid line items - Unit amount is negative', () => {
const lineItems = [
['テスト商品 1', '-50', '1'],
['テスト商品 2', '150', '2'],
['テスト商品 3', '100', '3']
];
prepareConfigs('cus_000001', '請求書の説明', lineItems);
expect(execute).toThrow('Line item 1 is invalid. Unit amount must not be negative.');
});
/**
* ラインアイテムの形式が不正 - 数量が小数
*/
test('Invalid line items - Quantity is decimal', () => {
const lineItems = [
['テスト商品 1', '50', '1.0'], // 小数点以下が 0 の行ではエラーにならない
['テスト商品 2', '150', '2.5'], // この行でエラー
['テスト商品 3', '100', '3']
];
prepareConfigs('cus_000001', '請求書の説明', lineItems);
expect(execute).toThrow('Line item 2 is invalid. Quantity must be integer.');
});
/**
* ラインアイテムの形式が不正 - 数量が負の整数
*/
test('Invalid line items - Quantity is negative', () => {
const lineItems = [
['テスト商品 1', '50', '1'],
['テスト商品 2', '150', '2'],
['テスト商品 3', '100', '-3']
];
prepareConfigs('cus_000001', '請求書の説明', lineItems);
expect(execute).toThrow('Line item 3 is invalid. Quantity must not be negative.');
});
/**
* 合計額が上限を超える - ラインアイテム 1 つ
*/
test('Total amount exceeds the limit - one line item', () => {
const lineItems = [
['テスト商品 1', '10000', '10000']
];
prepareConfigs('cus_000001', '請求書の説明', lineItems);
expect(execute).toThrow('The total amount of line items must be less than 100000000.');
});
/**
* 合計額が上限を超える - 複数のラインアイテム
*/
test('Total amount exceeds the limit - multiple line items', () => {
const lineItems = [
['テスト商品 1', '10000000', '9'],
['テスト商品 2', '1000000', '9'],
['テスト商品 3', '100000', '10'] // ここで上限を超える
];
prepareConfigs('cus_000001', '請求書の説明', lineItems);
expect(execute).toThrow('The total amount of line items must be less than 100000000.');
});
/**
* 請求書ドラフトを作成する API リクエストのテスト - 通貨を指定しない場合
* @param {Object} request
* @param request.url
* @param request.method
* @param request.headers
* @param request.contentType
* @param request.body
* @param customerId
* @param description
*/
const assertCreateInvoiceRequest = ({url, method, headers, contentType, body}, customerId, description) => {
expect(url).toEqual('https://api.stripe.com/v1/invoices');
expect(method).toEqual('POST');
expect(headers.get('Stripe-Version')).toEqual(STRIPE_VERSION);
expect(contentType).startsWith('application/x-www-form-urlencoded');
let expectedBody = `customer=${encodeURIComponent(customerId)}`
+ `&description=${encodeURIComponent(description)}`
+ '&auto_advance=false';
expectedBody = expectedBody.replace(/%20/g, '+'); // HttpRequestWrapper#formParam() はスペースを + に置き換える
expect(body).toEqual(expectedBody);
};
/**
* 請求書ドラフトを作成する HTTP リクエストで失敗
*/
test('Fail to create invoice', () => {
prepareConfigs('cus_000001', '請求書の説明', SAMPLE_LINE_ITEMS);
httpClient.setRequestHandler((request) => {
assertCreateInvoiceRequest(request, 'cus_000001', '請求書の説明');
return httpClient.createHttpResponse(400, 'application/json', '{}');
});
expect(execute).toThrow('Failed to create draft invoice. status: 400');
});
/**
* 成功 - ラインアイテムが 1 行もない
*/
test('Success - No line items', () => {
const {invoiceIdDef, invoiceUrlDef} = prepareConfigs('cus_000001', '請求書の説明', []);
const invoiceId = 'in_000101';
httpClient.setRequestHandler((request) => {
assertCreateInvoiceRequest(request, 'cus_000001', '請求書の説明');
return httpClient.createHttpResponse(200, 'application/json', `{"id": "${invoiceId}"}`);
});
execute();
// 文字型データ項目の値をチェック
expect(engine.findData(invoiceIdDef)).toEqual(invoiceId);
expect(engine.findData(invoiceUrlDef)).toEqual(`https://dashboard.stripe.com/invoices/${invoiceId}`);
});
/**
* 成功 - ラインアイテムをあらわすテーブル型データ項目の設定なし
*/
test('Success - No list-type data item is set', () => {
const {invoiceIdDef, invoiceUrlDef} = prepareConfigs('cus_000001', '請求書の説明', SAMPLE_LINE_ITEMS);
configs.put('conf_LineItems', '');
const invoiceId = 'in_000102';
httpClient.setRequestHandler((request) => {
assertCreateInvoiceRequest(request, 'cus_000001', '請求書の説明');
return httpClient.createHttpResponse(200, 'application/json', `{"id": "${invoiceId}"}`);
});
execute();
// 文字型データ項目の値をチェック
expect(engine.findData(invoiceIdDef)).toEqual(invoiceId);
expect(engine.findData(invoiceUrlDef)).toEqual(`https://dashboard.stripe.com/invoices/${invoiceId}`);
});
/**
* 請求書ドラフトにラインアイテムを追加する API リクエストのテスト
* @param {Object} request
* @param request.url
* @param request.method
* @param request.headers
* @param request.contentType
* @param request.body
* @param customerId
* @param invoiceId
* @param lineItem
*/
const assertAttachInvoiceItemRequest = ({url, method, headers, contentType, body},
customerId, invoiceId, lineItem) => {
expect(url).toEqual('https://api.stripe.com/v1/invoiceitems');
expect(method).toEqual('POST');
expect(headers.get('Stripe-Version')).toEqual(STRIPE_VERSION);
expect(contentType).startsWith('application/x-www-form-urlencoded');
let expectedBody = `customer=${encodeURIComponent(customerId)}`
+ `&invoice=${invoiceId}`
+ `&description=${encodeURIComponent(lineItem[0])}`
+ `&unit_amount=${lineItem[1]}`
+ `&quantity=${lineItem[2]}`;
expectedBody = expectedBody.replace(/%20/g, '+'); // HttpRequestWrapper#formParam() はスペースを + に置き換える
expect(body).toEqual(expectedBody);
};
/**
* 請求書ドラフトにラインアイテムを追加する HTTP リクエストで失敗
*/
test('Fail to attach an invoice item', () => {
prepareConfigs('cus_000001', '請求書の説明', SAMPLE_LINE_ITEMS);
let reqCount = 0;
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertCreateInvoiceRequest(request, 'cus_000001', '請求書の説明');
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', '{"id": "in_000001"}');
}
assertAttachInvoiceItemRequest(request, 'cus_000001', 'in_000001', SAMPLE_LINE_ITEMS[0]);
return httpClient.createHttpResponse(400, 'application/json', '{}');
});
expect(execute).toThrow('Failed to attach an invoice item. status: 400');
});
/**
* 成功 - 顧客 ID を文字型データ項目で指定し、ラインアイテムが 1 つの場合
*/
test('Success - customer ID set by string-type data item, one line item', () => {
const {invoiceIdDef, invoiceUrlDef} = prepareConfigs('cus_000001', '請求書の説明', SAMPLE_LINE_ITEMS);
let reqCount = 0;
const invoiceId = 'in_000001';
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertCreateInvoiceRequest(request, 'cus_000001', '請求書の説明');
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', `{"id": "${invoiceId}"}`);
}
assertAttachInvoiceItemRequest(request, 'cus_000001', invoiceId, SAMPLE_LINE_ITEMS[0]);
return httpClient.createHttpResponse(200, 'application/json', '{}');
});
execute();
// 文字型データ項目の値をチェック
expect(engine.findData(invoiceIdDef)).toEqual(invoiceId);
expect(engine.findData(invoiceUrlDef)).toEqual(`https://dashboard.stripe.com/invoices/${invoiceId}`);
});
/**
* 成功 - 顧客 ID を選択型データ項目で指定
*/
test('Success - customer ID set by select-type data item', () => {
const {invoiceIdDef, invoiceUrlDef} = prepareConfigs('', '請求書の説明', SAMPLE_LINE_ITEMS);
// 選択型データ項目を準備し、設定
const customerId = 'cus_000010';
const customerIdDef = engine.createDataDefinition('顧客 ID を選択', 5, 'q_customerIdSelect', 'SELECT_SINGLE');
const select = new java.util.ArrayList();
const item = engine.createItem(customerId, `${customerId} を選択`);
select.add(item);
engine.setData(customerIdDef, select);
configs.putObject('conf_CustomerId_V2', customerIdDef);
let reqCount = 0;
const invoiceId = 'in_000011';
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertCreateInvoiceRequest(request, 'cus_000010', '請求書の説明');
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', `{"id": "${invoiceId}"}`);
}
assertAttachInvoiceItemRequest(request, 'cus_000010', invoiceId, SAMPLE_LINE_ITEMS[0]);
return httpClient.createHttpResponse(200, 'application/json', '{}');
});
execute();
// 文字型データ項目の値をチェック
expect(engine.findData(invoiceIdDef)).toEqual(invoiceId);
expect(engine.findData(invoiceUrlDef)).toEqual(`https://dashboard.stripe.com/invoices/${invoiceId}`);
});
/**
* 成功 - 顧客 ID を選択型データ項目で指定し、選択されていない
*/
test('Customer ID is set by select-type data item and not selected', () => {
const {invoiceIdDef, invoiceUrlDef} = prepareConfigs('dummyString', '請求書の説明', SAMPLE_LINE_ITEMS);
// 選択型データ項目を準備し、未選択のまま設定
const customerIdDef = engine.createDataDefinition('顧客 ID を選択', 5, 'q_customerIdSelect', 'SELECT_SINGLE');
configs.putObject('conf_CustomerId_V2', customerIdDef);
expect(execute).toThrow('Customer ID is not selected.');
});
/**
* 成功 - 顧客 ID を固定値で指定
*/
test('Success - customer ID set as fixed value', () => {
const {invoiceIdDef, invoiceUrlDef} = prepareConfigs('', '請求書の説明', SAMPLE_LINE_ITEMS);
configs.put('conf_CustomerId_V2', 'cus_000020');
let reqCount = 0;
const invoiceId = 'in_000021';
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertCreateInvoiceRequest(request, 'cus_000020', '請求書の説明');
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', `{"id": "${invoiceId}"}`);
}
assertAttachInvoiceItemRequest(request, 'cus_000020', invoiceId, SAMPLE_LINE_ITEMS[0]);
return httpClient.createHttpResponse(200, 'application/json', '{}');
});
execute();
// 文字型データ項目の値をチェック
expect(engine.findData(invoiceIdDef)).toEqual(invoiceId);
expect(engine.findData(invoiceUrlDef)).toEqual(`https://dashboard.stripe.com/invoices/${invoiceId}`);
});
/**
* 成功 - ラインアイテムが複数で、合計額が上限を超えないぎりぎりの値の場合
*/
test('Success - multiple line items, maximum total amount', () => {
const lineItems = [ // 合計額が上限を超えないぎりぎりの値になるように
['テスト商品 1', '10000000', '9'],
['テスト商品 2', '1000000', '9'],
['テスト商品 3', '999999', '1']
];
const {invoiceIdDef, invoiceUrlDef} = prepareConfigs('cus_000002', '上限額ぎりぎりの請求書', lineItems);
let reqCount = 0;
let itemCount = 0;
const invoiceId = 'in_000002';
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertCreateInvoiceRequest(request, 'cus_000002', '上限額ぎりぎりの請求書');
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', `{"id": "${invoiceId}"}`);
}
assertAttachInvoiceItemRequest(request, 'cus_000002', invoiceId, lineItems[itemCount]);
itemCount++;
return httpClient.createHttpResponse(200, 'application/json', '{}');
});
execute();
// 文字型データ項目の値をチェック
expect(engine.findData(invoiceIdDef)).toEqual(invoiceId);
expect(engine.findData(invoiceUrlDef)).toEqual(`https://dashboard.stripe.com/invoices/${invoiceId}`);
});
/**
* 成功 - ラインアイテムが複数で、HTTP リクエスト数上限を超えないぎりぎりの数の場合
*/
test('Success - maximum number of line items', () => {
const lineItems = [];
for (let i = 0; i < httpClient.getRequestingLimit() - 1; i++) {
lineItems.push([`テスト商品 ${i + 1}`, '50', '1']);
}
const {invoiceIdDef, invoiceUrlDef} = prepareConfigs('cus_000001', '上限個数ぎりぎりの請求書', lineItems);
let reqCount = 0;
let itemCount = 0;
const invoiceId = 'in_000003';
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertCreateInvoiceRequest(request, 'cus_000001', '上限個数ぎりぎりの請求書');
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', `{"id": "${invoiceId}"}`);
}
assertAttachInvoiceItemRequest(request, 'cus_000001', invoiceId, lineItems[itemCount]);
itemCount++;
return httpClient.createHttpResponse(200, 'application/json', '{}');
});
execute();
// 文字型データ項目の値をチェック
expect(engine.findData(invoiceIdDef)).toEqual(invoiceId);
expect(engine.findData(invoiceUrlDef)).toEqual(`https://dashboard.stripe.com/invoices/${invoiceId}`);
});
/**
* 成功 - 請求書の説明が空の場合
*/
test('Success - invoice description is blank', () => {
const {invoiceIdDef, invoiceUrlDef} = prepareConfigs('cus_000001', '', SAMPLE_LINE_ITEMS);
let reqCount = 0;
const invoiceId = 'in_000004';
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertCreateInvoiceRequest(request, 'cus_000001', '');
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', `{"id": "${invoiceId}"}`);
}
assertAttachInvoiceItemRequest(request, 'cus_000001', invoiceId, SAMPLE_LINE_ITEMS[0]);
return httpClient.createHttpResponse(200, 'application/json', '{}');
});
execute();
// 文字型データ項目の値をチェック
expect(engine.findData(invoiceIdDef)).toEqual(invoiceId);
expect(engine.findData(invoiceUrlDef)).toEqual(`https://dashboard.stripe.com/invoices/${invoiceId}`);
});
/**
* 成功 - 請求書ドラフトの ID, URL を保存しない場合
*/
test('Success - draft invoice ID and URL not saved', () => {
prepareConfigs('cus_000003', 'ID と URL を保存しない', SAMPLE_LINE_ITEMS);
configs.put('conf_InvoiceId', '');
configs.put('conf_InvoiceUrl', '');
let reqCount = 0;
const invoiceId = 'in_000005';
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertCreateInvoiceRequest(request, 'cus_000003', 'ID と URL を保存しない');
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', `{"id": "${invoiceId}"}`);
}
assertAttachInvoiceItemRequest(request, 'cus_000003', invoiceId, SAMPLE_LINE_ITEMS[0]);
return httpClient.createHttpResponse(200, 'application/json', '{}');
});
execute();
});
/**
* 請求書ドラフトを作成する API リクエストのテスト - 通貨を指定する場合
* @param {Object} request
* @param request.url
* @param request.method
* @param request.headers
* @param request.contentType
* @param request.body
* @param customerId
* @param description
* @param currency
*/
const assertCreateInvoiceRequestWithCurrency = ({url, method, headers, contentType, body},
customerId, description, currency) => {
expect(url).toEqual('https://api.stripe.com/v1/invoices');
expect(method).toEqual('POST');
expect(headers.get('Stripe-Version')).toEqual(STRIPE_VERSION);
expect(contentType).startsWith('application/x-www-form-urlencoded');
let expectedBody = `customer=${encodeURIComponent(customerId)}`
+ `&description=${encodeURIComponent(description)}`
+ '&auto_advance=false'
+ `¤cy=${currency}`;
expectedBody = expectedBody.replace(/%20/g, '+'); // HttpRequestWrapper#formParam() はスペースを + に置き換える
expect(body).toEqual(expectedBody);
};
/**
* 成功 - 通貨を指定する場合
*/
test('Success - currency is selected', () => {
const {invoiceIdDef, invoiceUrlDef} = prepareConfigs('cus_000001', '通貨を指定', SAMPLE_LINE_ITEMS);
configs.put('conf_Currency', 'USD');
let reqCount = 0;
const invoiceId = 'in_000006';
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertCreateInvoiceRequestWithCurrency(request, 'cus_000001', '通貨を指定', 'USD');
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', `{"id": "${invoiceId}"}`);
}
assertAttachInvoiceItemRequest(request, 'cus_000001', invoiceId, SAMPLE_LINE_ITEMS[0]);
return httpClient.createHttpResponse(200, 'application/json', '{}');
});
execute();
// 文字型データ項目の値をチェック
expect(engine.findData(invoiceIdDef)).toEqual(invoiceId);
expect(engine.findData(invoiceUrlDef)).toEqual(`https://dashboard.stripe.com/invoices/${invoiceId}`);
});
/**
* 成功 - deprecated の設定を使用して顧客 ID を指定
*/
test('Success - customer ID set by deprecated config', () => {
const {invoiceIdDef, invoiceUrlDef} = prepareConfigs('dummyString', '請求書の説明', SAMPLE_LINE_ITEMS);
configs.put('conf_CustomerId', 'cus_000100'); // deprecated の設定
let reqCount = 0;
const invoiceId = 'in_000007';
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertCreateInvoiceRequest(request, 'cus_000100', '請求書の説明');
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', `{"id": "${invoiceId}"}`);
}
assertAttachInvoiceItemRequest(request, 'cus_000100', invoiceId, SAMPLE_LINE_ITEMS[0]);
return httpClient.createHttpResponse(200, 'application/json', '{}');
});
execute();
// 文字型データ項目の値をチェック
expect(engine.findData(invoiceIdDef)).toEqual(invoiceId);
expect(engine.findData(invoiceUrlDef)).toEqual(`https://dashboard.stripe.com/invoices/${invoiceId}`);
});
]]>