Repository: stripe/stripe-node
Pull request #1177 (2021-06-25 14:59:41)

API Updates
Codegen for openapi d12f3f1.
r? @richardm-stripe
cc @stripe/api-libraries

## Changelog
* Added support for `boleto` on `PaymentMethodCreateParams`, `PaymentIntent.payment_method_options`, `PaymentIntentConfirmParams.payment_method_options`, `PaymentIntentConfirmParams.payment_method_data`, `PaymentIntentUpdateParams.payment_method_options`, `PaymentIntentUpdateParams.payment_method_data`, `PaymentIntentCreateParams.payment_method_options`, `PaymentIntentCreateParams.payment_method_data`, `Charge.payment_method_details` and `PaymentMethod`
* `PaymentMethodListParams.type`, `PaymentMethodCreateParams.type`, `PaymentIntentConfirmParams.payment_method_data.type`, `PaymentIntentUpdateParams.payment_method_data.type`, `PaymentIntentCreataParams.payment_method_data.type` and `PaymentMethod.type` added new enum members: `boleto`
* Added support for `boleto_display_details` on `PaymentIntent.next_action`
* `TaxIdCreateParams.type`, `Invoice.customer_tax_ids[].type`, `InvoiceLineItemListUpcomingParams.customer_details.tax_ids[].type`, `InvoiceUpcomingParams.customer_details.tax_ids[].type`, `CustomerCreateParams.tax_id_data[].type`, `Checkout.Session.customer_details.tax_ids[].type` and `TaxId.type` added new enum members: `il_vat`.





Patch:
diff --git a/lib/StripeResource.js b/lib/StripeResource.js
index 8550721a..7fb628dd 100644
--- a/lib/StripeResource.js
+++ b/lib/StripeResource.js
@@ -102,7 +102,65 @@ StripeResource.prototype = {
     };
   },
 
-  _responseHandler(req, callback) {
+  _addHeadersDirectlyToResponse(res, headers) {
+    // For convenience, make some headers easily accessible on
+    // lastResponse.
+
+    // NOTE: Stripe responds with lowercase header names/keys.
+    res.requestId = headers['request-id'];
+    res.stripeAccount = res.stripeAccount || headers['stripe-account'];
+    res.apiVersion = res.apiVersion || headers['stripe-version'];
+    res.idempotencyKey = res.idempotencyKey || headers['idempotency-key'];
+  },
+
+  _makeResponseEvent(req, res, headers) {
+    const requestEndTime = Date.now();
+    const requestDurationMs = requestEndTime - req._requestStart;
+
+    return utils.removeNullish({
+      api_version: headers['stripe-version'],
+      account: headers['stripe-account'],
+      idempotency_key: headers['idempotency-key'],
+      method: req._requestEvent.method,
+      path: req._requestEvent.path,
+      status: res.statusCode,
+      request_id: res.requestId,
+      elapsed: requestDurationMs,
+      request_start_time: req._requestStart,
+      request_end_time: requestEndTime,
+    });
+  },
+
+  /**
+   * Used by methods with spec.streaming === true. For these methods, we do not
+   * buffer successful responses into memory or do parse them into stripe
+   * objects, we delegate that all of that to the user and pass back the raw
+   * http.Response object to the callback.
+   *
+   * (Unsuccessful responses shouldn't make it here, they should
+   * still be buffered/parsed and handled by _jsonResponseHandler -- see
+   * makeRequest)
+   */
+  _streamingResponseHandler(req, callback) {
+    return (res) => {
+      const headers = res.headers || {};
+      this._addHeadersDirectlyToResponse(res, headers);
+
+      res.once('end', () => {
+        const responseEvent = this._makeResponseEvent(req, res, headers);
+        this._stripe._emitter.emit('response', responseEvent);
+        this._recordRequestMetrics(res.requestId, responseEvent.elapsed);
+      });
+      return callback(null, res);
+    };
+  },
+
+  /**
+   * Default handler for Stripe responses. Buffers the response into memory,
+   * parses the JSON and returns it (i.e. passes it to the callback) if there
+   * is no "error" field. Otherwise constructs/passes an appropriate Error.
+   */
+  _jsonResponseHandler(req, callback) {
     return (res) => {
       let response = '';
 
@@ -112,43 +170,8 @@ StripeResource.prototype = {
       });
       res.once('end', () => {
         const headers = res.headers || {};
-        // NOTE: Stripe responds with lowercase header names/keys.
-
-        // For convenience, make some headers easily accessible on
-        // lastResponse.
-        res.requestId = headers['request-id'];
-
-        const stripeAccount = headers['stripe-account'];
-        if (stripeAccount) {
-          res.stripeAccount = stripeAccount;
-        }
-
-        const apiVersion = headers['stripe-version'];
-        if (apiVersion) {
-          res.apiVersion = apiVersion;
-        }
-
-        const idempotencyKey = headers['idempotency-key'];
-        if (idempotencyKey) {
-          res.idempotencyKey = idempotencyKey;
-        }
-
-        const requestEndTime = Date.now();
-        const requestDurationMs = requestEndTime - req._requestStart;
-
-        const responseEvent = utils.removeNullish({
-          api_version: headers['stripe-version'],
-          account: headers['stripe-account'],
-          idempotency_key: headers['idempotency-key'],
-          method: req._requestEvent.method,
-          path: req._requestEvent.path,
-          status: res.statusCode,
-          request_id: res.requestId,
-          elapsed: requestDurationMs,
-          request_start_time: req._requestStart,
-          request_end_time: requestEndTime,
-        });
-
+        this._addHeadersDirectlyToResponse(res, headers);
+        const responseEvent = this._makeResponseEvent(req, res, headers);
         this._stripe._emitter.emit('response', responseEvent);
 
         try {
@@ -194,7 +217,7 @@ StripeResource.prototype = {
           );
         }
 
-        this._recordRequestMetrics(res.requestId, requestDurationMs);
+        this._recordRequestMetrics(res.requestId, responseEvent.elapsed);
 
         // Expose res object
         Object.defineProperty(response, 'lastResponse', {
@@ -458,7 +481,10 @@ StripeResource.prototype = {
             ((res || {}).headers || {})['retry-after']
           );
         } else {
-          return this._responseHandler(req, callback)(res);
+          if (options.streaming && res.statusCode <= 400) {
+            return this._streamingResponseHandler(req, callback)(res);
+          }
+          return this._jsonResponseHandler(req, callback)(res);
         }
       });
 
diff --git a/lib/makeRequest.js b/lib/makeRequest.js
index 0da41f5b..8944b30b 100644
--- a/lib/makeRequest.js
+++ b/lib/makeRequest.js
@@ -8,7 +8,6 @@ function getRequestOpts(self, requestArgs, spec, overrideData) {
   const requestMethod = (spec.method || 'GET').toUpperCase();
   const urlParams = spec.urlParams || [];
   const encode = spec.encode || ((data) => data);
-  const host = spec.host;
   const path = self.createResourcePathWithSymbols(spec.path);
 
   // Don't mutate args externally.
@@ -31,7 +30,8 @@ function getRequestOpts(self, requestArgs, spec, overrideData) {
   const dataFromArgs = utils.getDataFromArgs(args);
   const data = encode(Object.assign({}, dataFromArgs, overrideData));
   const options = utils.getOptionsFromArgs(args);
-
+  const host = options.host || spec.host;
+  const streaming = !!spec.streaming;
   // Validate that there are no more args.
   if (args.filter((x) => x != null).length) {
     throw new Error(
@@ -58,6 +58,7 @@ function getRequestOpts(self, requestArgs, spec, overrideData) {
     auth: options.auth,
     headers,
     host,
+    streaming,
     settings: options.settings,
   };
 }
@@ -99,7 +100,7 @@ function makeRequest(self, requestArgs, spec, overrideData) {
       path,
       opts.bodyData,
       opts.auth,
-      {headers, settings},
+      {headers, settings, streaming: opts.streaming},
       requestCallback
     );
   });
diff --git a/lib/utils.js b/lib/utils.js
index 5bca895a..ae4c0047 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -25,6 +25,7 @@ const OPTIONS_KEYS = [
   'apiVersion',
   'maxNetworkRetries',
   'timeout',
+  'host',
 ];
 
 const DEPRECATED_OPTIONS = {
@@ -197,6 +198,9 @@ const utils = (module.exports = {
         if (Number.isInteger(params.timeout)) {
           opts.settings.timeout = params.timeout;
         }
+        if (params.host) {
+          opts.host = params.host;
+        }
       }
     }
     return opts;
diff --git a/types/2020-08-27/Charges.d.ts b/types/2020-08-27/Charges.d.ts
index 4c3ab72c..2aedbd7f 100644
--- a/types/2020-08-27/Charges.d.ts
+++ b/types/2020-08-27/Charges.d.ts
@@ -398,6 +398,8 @@ declare module 'stripe' {
 
         bancontact?: PaymentMethodDetails.Bancontact;
 
+        boleto?: PaymentMethodDetails.Boleto;
+
         card?: PaymentMethodDetails.Card;
 
         card_present?: PaymentMethodDetails.CardPresent;
@@ -642,6 +644,13 @@ declare module 'stripe' {
           type PreferredLanguage = 'de' | 'en' | 'fr' | 'nl';
         }
 
+        interface Boleto {
+          /**
+           * Uniquely identifies this customer tax_id (CNPJ or CPF)
+           */
+          tax_id: string;
+        }
+
         interface Card {
           /**
            * Card brand. Can be `amex`, `diners`, `discover`, `jcb`, `mastercard`, `unionpay`, `visa`, or `unknown`.
diff --git a/types/2020-08-27/Checkout/Sessions.d.ts b/types/2020-08-27/Checkout/Sessions.d.ts
index 8caf9956..24f543f3 100644
--- a/types/2020-08-27/Checkout/Sessions.d.ts
+++ b/types/2020-08-27/Checkout/Sessions.d.ts
@@ -215,7 +215,7 @@ declare module 'stripe' {
 
           interface TaxId {
             /**
-             * The type of the tax ID, one of `eu_vat`, `br_cnpj`, `br_cpf`, `gb_vat`, `nz_gst`, `au_abn`, `in_gst`, `no_vat`, `za_vat`, `ch_vat`, `mx_rfc`, `sg_uen`, `ru_inn`, `ru_kpp`, `ca_bn`, `hk_br`, `es_cif`, `tw_vat`, `th_vat`, `jp_cn`, `jp_rn`, `li_uid`, `my_itn`, `us_ein`, `kr_brn`, `ca_qst`, `ca_gst_hst`, `ca_pst_bc`, `ca_pst_mb`, `ca_pst_sk`, `my_sst`, `sg_gst`, `ae_trn`, `cl_tin`, `sa_vat`, `id_npwp`, `my_frp`, or `unknown`
+             * The type of the tax ID, one of `eu_vat`, `br_cnpj`, `br_cpf`, `gb_vat`, `nz_gst`, `au_abn`, `in_gst`, `no_vat`, `za_vat`, `ch_vat`, `mx_rfc`, `sg_uen`, `ru_inn`, `ru_kpp`, `ca_bn`, `hk_br`, `es_cif`, `tw_vat`, `th_vat`, `jp_cn`, `jp_rn`, `li_uid`, `my_itn`, `us_ein`, `kr_brn`, `ca_qst`, `ca_gst_hst`, `ca_pst_bc`, `ca_pst_mb`, `ca_pst_sk`, `my_sst`, `sg_gst`, `ae_trn`, `cl_tin`, `sa_vat`, `id_npwp`, `my_frp`, `il_vat`, or `unknown`
              */
             type: TaxId.Type;
 
@@ -244,6 +244,7 @@ declare module 'stripe' {
               | 'gb_vat'
               | 'hk_br'
               | 'id_npwp'
+              | 'il_vat'
               | 'in_gst'
               | 'jp_cn'
               | 'jp_rn'
diff --git a/types/2020-08-27/Customers.d.ts b/types/2020-08-27/Customers.d.ts
index a47104a1..5a937ee6 100644
--- a/types/2020-08-27/Customers.d.ts
+++ b/types/2020-08-27/Customers.d.ts
@@ -414,7 +414,7 @@ declare module 'stripe' {
 
       interface TaxIdDatum {
         /**
-         * Type of the tax ID, one of `ae_trn`, `au_abn`, `br_cnpj`, `br_cpf`, `ca_bn`, `ca_gst_hst`, `ca_pst_bc`, `ca_pst_mb`, `ca_pst_sk`, `ca_qst`, `ch_vat`, `cl_tin`, `es_cif`, `eu_vat`, `gb_vat`, `hk_br`, `id_npwp`, `in_gst`, `jp_cn`, `jp_rn`, `kr_brn`, `li_uid`, `mx_rfc`, `my_frp`, `my_itn`, `my_sst`, `no_vat`, `nz_gst`, `ru_inn`, `ru_kpp`, `sa_vat`, `sg_gst`, `sg_uen`, `th_vat`, `tw_vat`, `us_ein`, or `za_vat`
+         * Type of the tax ID, one of `ae_trn`, `au_abn`, `br_cnpj`, `br_cpf`, `ca_bn`, `ca_gst_hst`, `ca_pst_bc`, `ca_pst_mb`, `ca_pst_sk`, `ca_qst`, `ch_vat`, `cl_tin`, `es_cif`, `eu_vat`, `gb_vat`, `hk_br`, `id_npwp`, `il_vat`, `in_gst`, `jp_cn`, `jp_rn`, `kr_brn`, `li_uid`, `mx_rfc`, `my_frp`, `my_itn`, `my_sst`, `no_vat`, `nz_gst`, `ru_inn`, `ru_kpp`, `sa_vat`, `sg_gst`, `sg_uen`, `th_vat`, `tw_vat`, `us_ein`, or `za_vat`
          */
         type: TaxIdDatum.Type;
 
@@ -443,6 +443,7 @@ declare module 'stripe' {
           | 'gb_vat'
           | 'hk_br'
           | 'id_npwp'
+          | 'il_vat'
           | 'in_gst'
           | 'jp_cn'
           | 'jp_rn'
diff --git a/types/2020-08-27/InvoiceLineItems.d.ts b/types/2020-08-27/InvoiceLineItems.d.ts
index e52280c8..9e2dacfc 100644
--- a/types/2020-08-27/InvoiceLineItems.d.ts
+++ b/types/2020-08-27/InvoiceLineItems.d.ts
@@ -369,7 +369,7 @@ declare module 'stripe' {
 
         interface TaxId {
           /**
-           * Type of the tax ID, one of `ae_trn`, `au_abn`, `br_cnpj`, `br_cpf`, `ca_bn`, `ca_gst_hst`, `ca_pst_bc`, `ca_pst_mb`, `ca_pst_sk`, `ca_qst`, `ch_vat`, `cl_tin`, `es_cif`, `eu_vat`, `gb_vat`, `hk_br`, `id_npwp`, `in_gst`, `jp_cn`, `jp_rn`, `kr_brn`, `li_uid`, `mx_rfc`, `my_frp`, `my_itn`, `my_sst`, `no_vat`, `nz_gst`, `ru_inn`, `ru_kpp`, `sa_vat`, `sg_gst`, `sg_uen`, `th_vat`, `tw_vat`, `us_ein`, or `za_vat`
+           * Type of the tax ID, one of `ae_trn`, `au_abn`, `br_cnpj`, `br_cpf`, `ca_bn`, `ca_gst_hst`, `ca_pst_bc`, `ca_pst_mb`, `ca_pst_sk`, `ca_qst`, `ch_vat`, `cl_tin`, `es_cif`, `eu_vat`, `gb_vat`, `hk_br`, `id_npwp`, `il_vat`, `in_gst`, `jp_cn`, `jp_rn`, `kr_brn`, `li_uid`, `mx_rfc`, `my_frp`, `my_itn`, `my_sst`, `no_vat`, `nz_gst`, `ru_inn`, `ru_kpp`, `sa_vat`, `sg_gst`, `sg_uen`, `th_vat`, `tw_vat`, `us_ein`, or `za_vat`
            */
           type: TaxId.Type;
 
@@ -398,6 +398,7 @@ declare module 'stripe' {
             | 'gb_vat'
             | 'hk_br'
             | 'id_npwp'
+            | 'il_vat'
             | 'in_gst'
             | 'jp_cn'
             | 'jp_rn'
diff --git a/types/2020-08-27/Invoices.d.ts b/types/2020-08-27/Invoices.d.ts
index 687d7168..1ff73ac7 100644
--- a/types/2020-08-27/Invoices.d.ts
+++ b/types/2020-08-27/Invoices.d.ts
@@ -393,7 +393,7 @@ declare module 'stripe' {
 
       interface CustomerTaxId {
         /**
-         * The type of the tax ID, one of `eu_vat`, `br_cnpj`, `br_cpf`, `gb_vat`, `nz_gst`, `au_abn`, `in_gst`, `no_vat`, `za_vat`, `ch_vat`, `mx_rfc`, `sg_uen`, `ru_inn`, `ru_kpp`, `ca_bn`, `hk_br`, `es_cif`, `tw_vat`, `th_vat`, `jp_cn`, `jp_rn`, `li_uid`, `my_itn`, `us_ein`, `kr_brn`, `ca_qst`, `ca_gst_hst`, `ca_pst_bc`, `ca_pst_mb`, `ca_pst_sk`, `my_sst`, `sg_gst`, `ae_trn`, `cl_tin`, `sa_vat`, `id_npwp`, `my_frp`, or `unknown`
+         * The type of the tax ID, one of `eu_vat`, `br_cnpj`, `br_cpf`, `gb_vat`, `nz_gst`, `au_abn`, `in_gst`, `no_vat`, `za_vat`, `ch_vat`, `mx_rfc`, `sg_uen`, `ru_inn`, `ru_kpp`, `ca_bn`, `hk_br`, `es_cif`, `tw_vat`, `th_vat`, `jp_cn`, `jp_rn`, `li_uid`, `my_itn`, `us_ein`, `kr_brn`, `ca_qst`, `ca_gst_hst`, `ca_pst_bc`, `ca_pst_mb`, `ca_pst_sk`, `my_sst`, `sg_gst`, `ae_trn`, `cl_tin`, `sa_vat`, `id_npwp`, `my_frp`, `il_vat`, or `unknown`
          */
         type: CustomerTaxId.Type;
 
@@ -422,6 +422,7 @@ declare module 'stripe' {
           | 'gb_vat'
           | 'hk_br'
           | 'id_npwp'
+          | 'il_vat'
           | 'in_gst'
           | 'jp_cn'
           | 'jp_rn'
@@ -1491,7 +1492,7 @@ declare module 'stripe' {
 
         interface TaxId {
           /**
-           * Type of the tax ID, one of `ae_trn`, `au_abn`, `br_cnpj`, `br_cpf`, `ca_bn`, `ca_gst_hst`, `ca_pst_bc`, `ca_pst_mb`, `ca_pst_sk`, `ca_qst`, `ch_vat`, `cl_tin`, `es_cif`, `eu_vat`, `gb_vat`, `hk_br`, `id_npwp`, `in_gst`, `jp_cn`, `jp_rn`, `kr_brn`, `li_uid`, `mx_rfc`, `my_frp`, `my_itn`, `my_sst`, `no_vat`, `nz_gst`, `ru_inn`, `ru_kpp`, `sa_vat`, `sg_gst`, `sg_uen`, `th_vat`, `tw_vat`, `us_ein`, or `za_vat`
+           * Type of the tax ID, one of `ae_trn`, `au_abn`, `br_cnpj`, `br_cpf`, `ca_bn`, `ca_gst_hst`, `ca_pst_bc`, `ca_pst_mb`, `ca_pst_sk`, `ca_qst`, `ch_vat`, `cl_tin`, `es_cif`, `eu_vat`, `gb_vat`, `hk_br`, `id_npwp`, `il_vat`, `in_gst`, `jp_cn`, `jp_rn`, `kr_brn`, `li_uid`, `mx_rfc`, `my_frp`, `my_itn`, `my_sst`, `no_vat`, `nz_gst`, `ru_inn`, `ru_kpp`, `sa_vat`, `sg_gst`, `sg_uen`, `th_vat`, `tw_vat`, `us_ein`, or `za_vat`
            */
           type: TaxId.Type;
 
@@ -1520,6 +1521,7 @@ declare module 'stripe' {
             | 'gb_vat'
             | 'hk_br'
             | 'id_npwp'
+            | 'il_vat'
             | 'in_gst'
             | 'jp_cn'
             | 'jp_rn'
diff --git a/types/2020-08-27/PaymentIntents.d.ts b/types/2020-08-27/PaymentIntents.d.ts
index 54e0122c..6baea7a5 100644
--- a/types/2020-08-27/PaymentIntents.d.ts
+++ b/types/2020-08-27/PaymentIntents.d.ts
@@ -325,6 +325,8 @@ declare module 'stripe' {
       interface NextAction {
         alipay_handle_redirect?: NextAction.AlipayHandleRedirect;
 
+        boleto_display_details?: NextAction.BoletoDisplayDetails;
+
         oxxo_display_details?: NextAction.OxxoDisplayDetails;
 
         redirect_to_url?: NextAction.RedirectToUrl;
@@ -365,6 +367,28 @@ declare module 'stripe' {
           url: string | null;
         }
 
+        interface BoletoDisplayDetails {
+          /**
+           * The timestamp after which the boleto expires.
+           */
+          expires_at: number | null;
+
+          /**
+           * The URL to the hosted boleto voucher page, which allows customers to view the boleto voucher.
+           */
+          hosted_voucher_url: string | null;
+
+          /**
+           * The boleto number.
+           */
+          number: string | null;
+
+          /**
+           * The URL to the downloadable boleto voucher PDF.
+           */
+          pdf: string | null;
+        }
+
         interface OxxoDisplayDetails {
           /**
            * The timestamp after which the OXXO voucher expires.
@@ -418,6 +442,8 @@ declare module 'stripe' {
 
         bancontact?: PaymentMethodOptions.Bancontact;
 
+        boleto?: PaymentMethodOptions.Boleto;
+
         card?: PaymentMethodOptions.Card;
 
         card_present?: PaymentMethodOptions.CardPresent;
@@ -494,6 +520,13 @@ declare module 'stripe' {
           type PreferredLanguage = 'de' | 'en' | 'fr' | 'nl';
         }
 
+        interface Boleto {
+          /**
+           * The number of calendar days before a Boleto voucher expires. For example, if you create a Boleto voucher on Monday and you set expires_after_days to 2, the Boleto voucher will expire on Wednesday at 23:59 America/Sao_Paulo time.
+           */
+          expires_after_days: number;
+        }
+
         interface Card {
           /**
            * Installment details for this payment (Mexico only).
@@ -916,6 +949,11 @@ declare module 'stripe' {
          */
         billing_details?: PaymentMethodData.BillingDetails;
 
+        /**
+         * If this is a `boleto` PaymentMethod, this hash contains details about the Boleto payment method.
+         */
+        boleto?: PaymentMethodData.Boleto;
+
         /**
          * If this is an `eps` PaymentMethod, this hash contains details about the EPS payment method.
          */
@@ -1081,6 +1119,13 @@ declare module 'stripe' {
           }
         }
 
+        interface Boleto {
+          /**
+           * Uniquely identifies this customer tax_id (CNPJ or CPF)
+           */
+          tax_id: string;
+        }
+
         interface Eps {
           /**
            * The customer's bank.
@@ -1250,6 +1295,7 @@ declare module 'stripe' {
           | 'au_becs_debit'
           | 'bacs_debit'
           | 'bancontact'
+          | 'boleto'
           | 'eps'
           | 'fpx'
           | 'giropay'
@@ -1284,6 +1330,11 @@ declare module 'stripe' {
          */
         bancontact?: Stripe.Emptyable<PaymentMethodOptions.Bancontact>;
 
+        /**
+         * If this is a `boleto` PaymentMethod, this sub-hash contains details about the Boleto payment method options.
+         */
+        boleto?: Stripe.Emptyable<PaymentMethodOptions.Boleto>;
+
         /**
          * Configuration for any card payments attempted on this PaymentIntent.
          */
@@ -1383,6 +1434,13 @@ declare module 'stripe' {
           type PreferredLanguage = 'de' | 'en' | 'fr' | 'nl';
         }
 
+        interface Boleto {
+          /**
+           * The number of calendar days before a Boleto voucher expires. For example, if you create a Boleto voucher on Monday and you set expires_after_days to 2, the Boleto invoice will expire on Wednesday at 23:59 America/Sao_Paulo time.
+           */
+          expires_after_days?: number;
+        }
+
         interface Card {
           /**
            * A single-use `cvc_update` Token that represents a card CVC value. When provided, the CVC value will be verified during the card payment attempt. This parameter can only be provided during confirmation.
@@ -1717,6 +1775,11 @@ declare module 'stripe' {
          */
         billing_details?: PaymentMethodData.BillingDetails;
 
+        /**
+         * If this is a `boleto` PaymentMethod, this hash contains details about the Boleto payment method.
+         */
+        boleto?: PaymentMethodData.Boleto;
+
         /**
          * If this is an `eps` PaymentMethod, this hash contains details about the EPS payment method.
          */
@@ -1882,6 +1945,13 @@ declare module 'stripe' {
           }
         }
 
+        interface Boleto {
+          /**
+           * Uniquely identifies this customer tax_id (CNPJ or CPF)
+           */
+          tax_id: string;
+        }
+
         interface Eps {
           /**
            * The customer's bank.
@@ -2051,6 +2121,7 @@ declare module 'stripe' {
           | 'au_becs_debit'
           | 'bacs_debit'
           | 'bancontact'
+          | 'boleto'
           | 'eps'
           | 'fpx'
           | 'giropay'
@@ -2085,6 +2156,11 @@ declare module 'stripe' {
          */
         bancontact?: Stripe.Emptyable<PaymentMethodOptions.Bancontact>;
 
+        /**
+         * If this is a `boleto` PaymentMethod, this sub-hash contains details about the Boleto payment method options.
+         */
+        boleto?: Stripe.Emptyable<PaymentMethodOptions.Boleto>;
+
         /**
          * Configuration for any card payments attempted on this PaymentIntent.
          */
@@ -2184,6 +2260,13 @@ declare module 'stripe' {
           type PreferredLanguage = 'de' | 'en' | 'fr' | 'nl';
         }
 
+        interface Boleto {
+          /**
+           * The number of calendar days before a Boleto voucher expires. For example, if you create a Boleto voucher on Monday and you set expires_after_days to 2, the Boleto invoice will expire on Wednesday at 23:59 America/Sao_Paulo time.
+           */
+          expires_after_days?: number;
+        }
+
         interface Card {
           /**
            * A single-use `cvc_update` Token that represents a card CVC value. When provided, the CVC value will be verified during the card payment attempt. This parameter can only be provided during confirmation.
@@ -2632,6 +2715,11 @@ declare module 'stripe' {
          */
         billing_details?: PaymentMethodData.BillingDetails;
 
+        /**
+         * If this is a `boleto` PaymentMethod, this hash contains details about the Boleto payment method.
+         */
+        boleto?: PaymentMethodData.Boleto;
+
         /**
          * If this is an `eps` PaymentMethod, this hash contains details about the EPS payment method.
          */
@@ -2797,6 +2885,13 @@ declare module 'stripe' {
           }
         }
 
+        interface Boleto {
+          /**
+           * Uniquely identifies this customer tax_id (CNPJ or CPF)
+           */
+          tax_id: string;
+        }
+
         interface Eps {
           /**
            * The customer's bank.
@@ -2966,6 +3061,7 @@ declare module 'stripe' {
           | 'au_becs_debit'
           | 'bacs_debit'
           | 'bancontact'
+          | 'boleto'
           | 'eps'
           | 'fpx'
           | 'giropay'
@@ -3000,6 +3096,11 @@ declare module 'stripe' {
          */
         bancontact?: Stripe.Emptyable<PaymentMethodOptions.Bancontact>;
 
+        /**
+         * If this is a `boleto` PaymentMethod, this sub-hash contains details about the Boleto payment method options.
+         */
+        boleto?: Stripe.Emptyable<PaymentMethodOptions.Boleto>;
+
         /**
          * Configuration for any card payments attempted on this PaymentIntent.
          */
@@ -3099,6 +3200,13 @@ declare module 'stripe' {
           type PreferredLanguage = 'de' | 'en' | 'fr' | 'nl';
         }
 
+        interface Boleto {
+          /**
+           * The number of calendar days before a Boleto voucher expires. For example, if you create a Boleto voucher on Monday and you set expires_after_days to 2, the Boleto invoice will expire on Wednesday at 23:59 America/Sao_Paulo time.
+           */
+          expires_after_days?: number;
+        }
+
         interface Card {
           /**
            * A single-use `cvc_update` Token that represents a card CVC value. When provided, the CVC value will be verified during the card payment attempt. This parameter can only be provided during confirmation.
diff --git a/types/2020-08-27/PaymentMethods.d.ts b/types/2020-08-27/PaymentMethods.d.ts
index 1bf3879d..80468017 100644
--- a/types/2020-08-27/PaymentMethods.d.ts
+++ b/types/2020-08-27/PaymentMethods.d.ts
@@ -30,6 +30,8 @@ declare module 'stripe' {
 
       billing_details: PaymentMethod.BillingDetails;
 
+      boleto?: PaymentMethod.Boleto;
+
       card?: PaymentMethod.Card;
 
       card_present?: PaymentMethod.CardPresent;
@@ -170,6 +172,13 @@ declare module 'stripe' {
         phone: string | null;
       }
 
+      interface Boleto {
+        /**
+         * Uniquely identifies the customer tax id (CNPJ or CPF)
+         */
+        tax_id: string;
+      }
+
       interface Card {
         /**
          * Card brand. Can be `amex`, `diners`, `discover`, `jcb`, `mastercard`, `unionpay`, `visa`, or `unknown`.
@@ -594,6 +603,7 @@ declare module 'stripe' {
         | 'au_becs_debit'
         | 'bacs_debit'
         | 'bancontact'
+        | 'boleto'
         | 'card'
         | 'card_present'
         | 'eps'
@@ -644,6 +654,11 @@ declare module 'stripe' {
        */
       billing_details?: PaymentMethodCreateParams.BillingDetails;
 
+      /**
+       * If this is a `boleto` PaymentMethod, this hash contains details about the Boleto payment method.
+       */
+      boleto?: PaymentMethodCreateParams.Boleto;
+
       /**
        * If this is a `card` PaymentMethod, this hash contains the user's card details. For backwards compatibility, you can alternatively provide a Stripe token (e.g., for Apple Pay, Amex Express Checkout, or legacy Checkout) into the card hash with format `card: {token: "tok_visa"}`. When providing a card number, you must meet the requirements for [PCI compliance](https://stripe.com/docs/security#validating-pci-compliance). We strongly recommend using Stripe.js instead of interacting with this API directly.
        */
@@ -829,6 +844,13 @@ declare module 'stripe' {
         }
       }
 
+      interface Boleto {
+        /**
+         * Uniquely identifies this customer tax_id (CNPJ or CPF)
+         */
+        tax_id: string;
+      }
+
       interface Card1 {
         /**
          * The card's CVC. It is highly recommended to always include this value.
@@ -1024,6 +1046,7 @@ declare module 'stripe' {
         | 'au_becs_debit'
         | 'bacs_debit'
         | 'bancontact'
+        | 'boleto'
         | 'card'
         | 'eps'
         | 'fpx'
@@ -1188,6 +1211,7 @@ declare module 'stripe' {
         | 'au_becs_debit'
         | 'bacs_debit'
         | 'bancontact'
+        | 'boleto'
         | 'card'
         | 'card_present'
         | 'eps'
diff --git a/types/2020-08-27/TaxIds.d.ts b/types/2020-08-27/TaxIds.d.ts
index 139f2d1a..2a25cdf2 100644
--- a/types/2020-08-27/TaxIds.d.ts
+++ b/types/2020-08-27/TaxIds.d.ts
@@ -39,7 +39,7 @@ declare module 'stripe' {
       livemode: boolean;
 
       /**
-       * Type of the tax ID, one of `ae_trn`, `au_abn`, `br_cnpj`, `br_cpf`, `ca_bn`, `ca_gst_hst`, `ca_pst_bc`, `ca_pst_mb`, `ca_pst_sk`, `ca_qst`, `ch_vat`, `cl_tin`, `es_cif`, `eu_vat`, `gb_vat`, `hk_br`, `id_npwp`, `in_gst`, `jp_cn`, `jp_rn`, `kr_brn`, `li_uid`, `mx_rfc`, `my_frp`, `my_itn`, `my_sst`, `no_vat`, `nz_gst`, `ru_inn`, `ru_kpp`, `sa_vat`, `sg_gst`, `sg_uen`, `th_vat`, `tw_vat`, `us_ein`, or `za_vat`. Note that some legacy tax IDs have type `unknown`
+       * Type of the tax ID, one of `ae_trn`, `au_abn`, `br_cnpj`, `br_cpf`, `ca_bn`, `ca_gst_hst`, `ca_pst_bc`, `ca_pst_mb`, `ca_pst_sk`, `ca_qst`, `ch_vat`, `cl_tin`, `es_cif`, `eu_vat`, `gb_vat`, `hk_br`, `id_npwp`, `il_vat`, `in_gst`, `jp_cn`, `jp_rn`, `kr_brn`, `li_uid`, `mx_rfc`, `my_frp`, `my_itn`, `my_sst`, `no_vat`, `nz_gst`, `ru_inn`, `ru_kpp`, `sa_vat`, `sg_gst`, `sg_uen`, `th_vat`, `tw_vat`, `us_ein`, or `za_vat`. Note that some legacy tax IDs have type `unknown`
        */
       type: TaxId.Type;
 
@@ -73,6 +73,7 @@ declare module 'stripe' {
         | 'gb_vat'
         | 'hk_br'
         | 'id_npwp'
+        | 'il_vat'
         | 'in_gst'
         | 'jp_cn'
         | 'jp_rn'
@@ -139,7 +140,7 @@ declare module 'stripe' {
 
     interface TaxIdCreateParams {
       /**
-       * Type of the tax ID, one of `ae_trn`, `au_abn`, `br_cnpj`, `br_cpf`, `ca_bn`, `ca_gst_hst`, `ca_pst_bc`, `ca_pst_mb`, `ca_pst_sk`, `ca_qst`, `ch_vat`, `cl_tin`, `es_cif`, `eu_vat`, `gb_vat`, `hk_br`, `id_npwp`, `in_gst`, `jp_cn`, `jp_rn`, `kr_brn`, `li_uid`, `mx_rfc`, `my_frp`, `my_itn`, `my_sst`, `no_vat`, `nz_gst`, `ru_inn`, `ru_kpp`, `sa_vat`, `sg_gst`, `sg_uen`, `th_vat`, `tw_vat`, `us_ein`, or `za_vat`
+       * Type of the tax ID, one of `ae_trn`, `au_abn`, `br_cnpj`, `br_cpf`, `ca_bn`, `ca_gst_hst`, `ca_pst_bc`, `ca_pst_mb`, `ca_pst_sk`, `ca_qst`, `ch_vat`, `cl_tin`, `es_cif`, `eu_vat`, `gb_vat`, `hk_br`, `id_npwp`, `il_vat`, `in_gst`, `jp_cn`, `jp_rn`, `kr_brn`, `li_uid`, `mx_rfc`, `my_frp`, `my_itn`, `my_sst`, `no_vat`, `nz_gst`, `ru_inn`, `ru_kpp`, `sa_vat`, `sg_gst`, `sg_uen`, `th_vat`, `tw_vat`, `us_ein`, or `za_vat`
        */
       type: TaxIdCreateParams.Type;
 
@@ -173,6 +174,7 @@ declare module 'stripe' {
         | 'gb_vat'
         | 'hk_br'
         | 'id_npwp'
+        | 'il_vat'
         | 'in_gst'
         | 'jp_cn'
         | 'jp_rn'


Test patch:
diff --git a/test/StripeResource.spec.js b/test/StripeResource.spec.js
index 69adf309..18b1f2a5 100644
--- a/test/StripeResource.spec.js
+++ b/test/StripeResource.spec.js
@@ -6,6 +6,10 @@ const nock = require('nock');
 
 const stripe = require('../testUtils').getSpyableStripe();
 const expect = require('chai').expect;
+const testUtils = require('../testUtils');
+
+const StripeResource = require('../lib/StripeResource');
+const stripeMethod = StripeResource.method;
 
 describe('StripeResource', () => {
   describe('createResourcePathWithSymbols', () => {
@@ -191,12 +195,13 @@ describe('StripeResource', () => {
           (req, res) => {
             // Do nothing. This will trigger a timeout.
           },
-          (err, stripe) => {
+          (err, stripe, closeServer) => {
             if (err) {
               return done(err);
             }
             stripe.charges.create(options.data, (err, result) => {
               expect(err.detail.message).to.deep.equal('ETIMEDOUT');
+              closeServer();
               done();
             });
           }
@@ -212,13 +217,14 @@ describe('StripeResource', () => {
             // Do nothing. This will trigger a timeout.
             return {shouldStayOpen: nRequestsReceived < 3};
           },
-          (err, stripe) => {
+          (err, stripe, closeServer) => {
             if (err) {
               return done(err);
             }
             stripe.charges.create(options.data, (err, result) => {
               expect(err.detail.message).to.deep.equal('ETIMEDOUT');
               expect(nRequestsReceived).to.equal(3);
+              closeServer();
               done();
             });
           }
@@ -635,4 +641,92 @@ describe('StripeResource', () => {
       done();
     });
   });
+
+  describe('streaming', () => {
+    /**
+     * Defines a fake resource with a `pdf` method
+     * with binary streaming enabled.
+     */
+    const makeResourceWithPDFMethod = (stripe) => {
+      return new (StripeResource.extend({
+        path: 'resourceWithPDF',
+
+        pdf: stripeMethod({
+          method: 'GET',
+          host: 'files.stripe.com',
+          streaming: true,
+        }),
+      }))(stripe);
+    };
+
+    it('success', (callback) => {
+      const handleRequest = (req, res) => {
+        setTimeout(() => res.write('pretend'), 10);
+        setTimeout(() => res.write(' this'), 20);
+        setTimeout(() => res.write(' is a pdf'), 30);
+        setTimeout(() => res.end(), 40);
+      };
+
+      testUtils.getTestServerStripe(
+        {},
+        handleRequest,
+        (err, stripe, closeServer) => {
+          const foos = makeResourceWithPDFMethod(stripe);
+          if (err) {
+            return callback(err);
+          }
+
+          return foos.pdf({id: 'foo_123'}, {host: 'localhost'}, (err, res) => {
+            closeServer();
+            if (err) {
+              return callback(err);
+            }
+            const chunks = [];
+            res.on('data', (chunk) => chunks.push(chunk));
+            res.on('error', callback);
+            res.on('end', () => {
+              expect(Buffer.concat(chunks).toString()).to.equal(
+                'pretend this is a pdf'
+              );
+              return callback();
+            });
+          });
+        }
+      );
+    });
+
+    it('failure', (callback) => {
+      const handleRequest = (req, res) => {
+        setTimeout(() => res.writeHead(500));
+        setTimeout(
+          () =>
+            res.write(
+              '{"error": "api_error", "error_description": "this is bad"}'
+            ),
+          10
+        );
+        setTimeout(() => res.end(), 20);
+      };
+
+      testUtils.getTestServerStripe(
+        {},
+        handleRequest,
+        (err, stripe, closeServer) => {
+          if (err) {
+            return callback(err);
+          }
+
+          const foos = makeResourceWithPDFMethod(stripe);
+
+          return foos.pdf({id: 'foo_123'}, {host: 'localhost'}, (err, res) => {
+            closeServer();
+            expect(err).to.exist;
+            expect(err.raw.type).to.equal('api_error');
+            expect(err.raw.message).to.equal('this is bad');
+            return callback();
+          });
+        }
+      );
+    });
+  });
 });
diff --git a/testUtils/index.js b/testUtils/index.js
index 581345be..e2302623 100644
--- a/testUtils/index.js
+++ b/testUtils/index.js
@@ -15,7 +15,9 @@ const utils = (module.exports = {
     const server = http.createServer((req, res) => {
       const {shouldStayOpen} = handler(req, res) || {};
       if (!shouldStayOpen) {
-        res.on('close', () => server.close());
+        res.on('close', () => {
+          server.close();
+        });
       }
     });
     server.listen(0, () => {
@@ -29,7 +31,9 @@ const utils = (module.exports = {
           ...clientOptions,
         }
       );
-      return callback(null, stripe);
+      return callback(null, stripe, () => {
+        server.close();
+      });
     });
   },