Stripe: Update Metadata of Customer/Product/Invoice
This item updates metadata of a customer, product or invoice on Stripe. Metadata Fields whose keys are not specified remain unchanged.
Configs: Common
  • Step Name
  • Note
Configs
  • C1: Authorization Setting in which API Secret Key is set *
  • C2: ID of Customer/Product/Invoice *
  • C-K1: Key of Metadata Field 1 to add/update/delete
  • C-V1: New Value of Field 1 (if blank, delete the field)#{EL}
  • C-K2: Key of Metadata Field 2 to add/update/delete
  • C-V2: New Value of Field 2 (if blank, delete the field)#{EL}
  • C-K3: Key of Metadata Field 3 to add/update/delete
  • C-V3: New Value of Field 3 (if blank, delete the field)#{EL}
  • C-K4: Key of Metadata Field 4 to add/update/delete
  • C-V4: New Value of Field 4 (if blank, delete the field)#{EL}
  • C-K5: Key of Metadata Field 5 to add/update/delete
  • C-V5: New Value of Field 5 (if blank, delete the field)#{EL}
  • C-K6: Key of Metadata Field 6 to add/update/delete
  • C-V6: New Value of Field 6 (if blank, delete the field)#{EL}
  • C-K7: Key of Metadata Field 7 to add/update/delete
  • C-V7: New Value of Field 7 (if blank, delete the field)#{EL}
  • C-K8: Key of Metadata Field 8 to add/update/delete
  • C-V8: New Value of Field 8 (if blank, delete the field)#{EL}

Notes

Capture

See also

Script (click to open)
  • An XML file that contains the code below is available to download
    • stripe-metadata-update.xml (C) Questetra, Inc. (MIT License)
    • If you are using Professional, you can modify the contents of this file and use it as your own add-on


const STRIPE_API_VERSION = '2022-08-01';
const FIELD_NUM = 8; // 扱うフィールドの数
const MAX_KEY_LENGTH = 40; // メタデータの key の最大文字数(Stripe の制限)
const MAX_VALUE_LENGTH = 500; // メタデータの value の最大文字数(Stripe の制限)

main();

function main(){
    //// == Config Retrieving / 工程コンフィグの参照 ==
    const auth = configs.get('conf_Auth');
    const id = retrieveId();
    const apiUri = decideApiUri(id);
    const metadataMap = retrieveMetadataMap();

    //// == Calculating / 演算 ==
    updateMetadata(auth, apiUri, metadataMap);
}

/**
  * config から顧客/商品/請求書 ID を読み出す。空文字列の場合はエラー
  * @return {String} id 顧客/商品/請求書 ID
  */
function retrieveId() {
    let id = configs.get('conf_Id'); // 固定値の場合
    const idDef = configs.getObject('conf_Id');
    if (idDef !== null) {
        if (idDef.matchDataType('SELECT_SINGLE')) { // 選択型データ項目の場合
            const select = engine.findData(idDef);
            if (select === null || select.size() === 0) { // 未選択
                throw 'Customer/Product/Invoice ID is not selected.';
            }
            id = select.get(0).getValue();
        } else { // 文字型データ項目の場合
            id = engine.findData(idDef);
        }
    }
    if (id === null || id === '') {
        throw 'Customer/Product/Invoice ID is blank.';
    }
    return id;
}

/**
  * id から API の URI を決定する。顧客/商品/請求書 ID の形式でない場合、エラー
  * @param {String} id 顧客/商品/請求書 ID
  * @return {String} apiUri
  */
function decideApiUri(id) {
    const prefix = id.substring(0, id.indexOf('_'));
    const baseUrl = 'https://api.stripe.com/v1/';
    switch (prefix) {
        case 'cus':
            return `${baseUrl}customers/${encodeURIComponent(id)}`;
        case 'prod':
            return `${baseUrl}products/${encodeURIComponent(id)}`;
        case 'in':
            return `${baseUrl}invoices/${encodeURIComponent(id)}`;
        default:
            throw 'Customer/Product/Invoice ID must start with "cus_", "prod_" or "in_".';
    }
}

/**
  * config からメタデータの key, value を読み出し、Map に格納して返す。以下の場合はエラー
  * - value は設定されているのに key が空
  * - key の指定が重複している
  * - key の文字数が Stripe の制限を超える
  * - value の文字数が Stripe の制限を超える
  * - 更新すべきメタデータがない
  * @return {Map<String, String>} metadataMap メタデータの Map
  */
function retrieveMetadataMap() {
    const metadataMap = new Map();
    for (let i = 0; i < FIELD_NUM; i++) {
        const key = configs.get(`conf_Key${i+1}`);
        const value = configs.get(`conf_Value${i+1}`);
        if (key === '') {
            if (value === '') {
                // key, value がともに空白の組は無視
                continue;
            }
            throw `C-V${i+1} is set but C-K${i+1} is blank.`;
        }
        if (metadataMap.has(key)) { // key の指定が重複
            throw `Field Key "${key}" is set multiple times.`;
        }
        if (key.length > MAX_KEY_LENGTH) {
            throw `C-K${i+1} exceeds the limit of ${MAX_KEY_LENGTH} characters.`;
        }
        if (value.length > MAX_VALUE_LENGTH) {
            throw `C-V${i+1} exceeds the limit of ${MAX_VALUE_LENGTH} characters.`;
        }
        metadataMap.set(key, value);
    }
    if (metadataMap.size === 0) {
        throw 'No metadata fields to update.';
    }
    return metadataMap;
}

/**
  * メタデータを更新する
  * @param {String} oauth 認証設定
  * @param {String} apiUri リクエスト URI
  * @param {Map<String, String>} metadataMap メタデータの Map
  */
function updateMetadata(auth, apiUri, metadataMap) {
    let request = httpClient.begin()
        .authSetting(auth) // with "Authorization: Bearer XX"
        .header('Stripe-Version', STRIPE_API_VERSION);
    metadataMap.forEach((value, key) => {
        request = request.formParam(`metadata[${key}]`, value);
    });
    const response = request.post(apiUri);
    const status = response.getStatusCode();
    const responseStr = response.getResponseAsString();
    if (status !== 200) {
        engine.log(responseStr);
        throw `Failed to update metadata. status: ${status}`;
    }
}

    
%d bloggers like this: