diff --git a/tests/types/src/invalid.ts b/tests/types/src/invalid.ts index ac300bd8..1fea7485 100644 --- a/tests/types/src/invalid.ts +++ b/tests/types/src/invalid.ts @@ -1,6 +1,5 @@ import { Stripe, - StripeElements, StripeCardElement, StripeIbanElement, StripePaymentElement, @@ -9,13 +8,23 @@ import { } from '../../../types'; declare const stripe: Stripe; -declare const elements: StripeElements; declare const cardElement: StripeCardElement; declare const ibanElement: StripeIbanElement; declare const paymentElement: StripePaymentElement; declare const cartElement: StripeCartElement; declare const expressCheckoutElement: StripeExpressCheckoutElement; +// @ts-expect-error: Passing `clientSecret` or `mode` implies different integration paths which cannot be combined +const elements = stripe.elements({ + clientSecret: '', + mode: '', +}); + +// @ts-expect-error mode must be one of payment, setup, or subscription +stripe.elements({ + mode: 'test', +}); + elements.update({ // @ts-expect-error: `clientSecret` is not updatable clientSecret: 'pk_foo_secret_bar', @@ -149,6 +158,9 @@ elements.create('expressCheckout', { }, }); +// @ts-expect-error either elements or clientSecret is required +stripe.confirmPayment({confirmParams: {return_url: ''}}); + stripe .confirmPayment({elements, confirmParams: {return_url: ''}}) .then((res) => { @@ -175,6 +187,9 @@ stripe } }); +// @ts-expect-error either elements or clientSecret is required +stripe.confirmSetup({confirmParams: {return_url: ''}}); + stripe.confirmSetup({elements, confirmParams: {return_url: ''}}).then((res) => { if (res.error) { } diff --git a/tests/types/src/valid.ts b/tests/types/src/valid.ts index cd12843e..cf65cff2 100644 --- a/tests/types/src/valid.ts +++ b/tests/types/src/valid.ts @@ -80,6 +80,32 @@ const AVENIR: CustomFontSource = { }; const elements: StripeElements = stripe.elements({ + fonts: [OPEN_SANS, AVENIR], + locale: 'auto', + mode: 'payment', + currency: 'usd', + amount: 1099, + appearance: { + disableAnimations: false, + theme: 'night', + variables: { + colorIcon: 'blue', + }, + rules: { + '.Tab--selected': { + backgroundColor: 'blue', + }, + }, + labels: 'above', + }, + loader: 'auto', + customerOptions: { + customer: 'cus_foo', + ephemeralKey: 'ek_test_foo', + }, +}); + +const elementsClientSecret: StripeElements = stripe.elements({ fonts: [OPEN_SANS, AVENIR], locale: 'auto', clientSecret: '', @@ -142,6 +168,11 @@ elements.update({ }, labels: 'floating', }, + mode: 'payment', + currency: 'usd', + amount: 1099, + setup_future_usage: 'off_session', + capture_method: 'automatic', }); const fetchUpdates = async () => { @@ -2058,6 +2089,10 @@ stripe .handleCardAction('') .then(({paymentIntent}: {paymentIntent?: PaymentIntent}) => {}); +stripe + .handleNextAction('') + .then(({paymentIntent}: {paymentIntent?: PaymentIntent}) => {}); + stripe .verifyMicrodepositsForPayment('', {amounts: [32, 45]}) .then((result: {paymentIntent?: PaymentIntent; error?: StripeError}) => null); @@ -2086,6 +2121,24 @@ stripe }) .then((result: {paymentIntent?: PaymentIntent; error?: StripeError}) => null); +stripe.createPaymentMethod({ + elements: elements, + params: { + billing_details: { + name: 'Jenny Rosen', + }, + }, +}); + +stripe.createPaymentMethod({ + element: cardElement, + params: { + billing_details: { + name: 'Jenny Rosen', + }, + }, +}); + stripe.createPaymentMethod({ type: 'us_bank_account', us_bank_account: { @@ -2543,6 +2596,29 @@ stripe if (res.paymentIntent) { } }); +stripe + .confirmPayment({ + elements, + clientSecret: '', + redirect: 'if_required', + }) + .then((res) => { + if (res.error) { + } + if (res.paymentIntent) { + } + }); +stripe + .confirmPayment({ + clientSecret: '', + redirect: 'if_required', + }) + .then((res) => { + if (res.error) { + } + if (res.paymentIntent) { + } + }); stripe .confirmPayment({ elements, @@ -2571,6 +2647,37 @@ stripe } }); +stripe + .confirmSetup({ + elements, + clientSecret: '', + confirmParams: { + return_url: '', + }, + redirect: 'if_required', + }) + .then((res) => { + if (res.error) { + } + if (res.setupIntent) { + } + }); + +stripe + .confirmSetup({ + clientSecret: '', + confirmParams: { + return_url: '', + }, + redirect: 'if_required', + }) + .then((res) => { + if (res.error) { + } + if (res.setupIntent) { + } + }); + stripe .confirmSetup({ elements, diff --git a/types/api/payment-methods.d.ts b/types/api/payment-methods.d.ts index a69472cf..95c49ae0 100644 --- a/types/api/payment-methods.d.ts +++ b/types/api/payment-methods.d.ts @@ -1,3 +1,4 @@ +import {StripeElement, StripeElements} from '../stripe-js'; import {Metadata, MetadataParam, Address} from './shared'; /** @@ -316,6 +317,19 @@ export interface PaymentMethodCreateParams { type?: string; } +export interface CreatePaymentMethodElements { + /** + * Set of key-value pairs that you can attach to an object. This can be useful for storing additional information about the object in a structured format. Individual keys can be unset by posting an empty value to them. All keys can be unset by posting an empty value to `metadata`. + */ + metadata?: MetadataParam; + + elements?: StripeElements; + + element?: StripeElement; + + params?: PaymentMethodCreateParams; +} + export namespace PaymentMethodCreateParams { export interface BillingDetails { /** diff --git a/types/stripe-js/elements-group.d.ts b/types/stripe-js/elements-group.d.ts index 11cdab49..b0ab76ce 100644 --- a/types/stripe-js/elements-group.d.ts +++ b/types/stripe-js/elements-group.d.ts @@ -619,7 +619,7 @@ export type StripeElementLocale = /** * Options to create an `Elements` instance with. */ -export interface StripeElementsOptions { +interface BaseStripeElementsOptions { /** * An array of custom fonts, which elements created from the `Elements` object can use. */ @@ -640,13 +640,6 @@ export interface StripeElementsOptions { */ appearance?: Appearance; - /** - * The client secret for a PaymentIntent or SetupIntent used by the Payment Element. - * - * @docs https://stripe.com/docs/api/payment_intents/object#payment_intent_object-client_secret - */ - clientSecret?: string; - /** * Display skeleton loader UI while waiting for Elements to be fully loaded, after they are mounted. * Supported for the `payment`, `shippingAddress`, and `linkAuthentication` Elements. @@ -664,6 +657,47 @@ export interface StripeElementsOptions { customerOptions?: CustomerOptions; } +export interface StripeElementsOptionsClientSecret + extends BaseStripeElementsOptions { + /** + * The client secret for a PaymentIntent or SetupIntent used by the Payment Element. + * + * @docs https://stripe.com/docs/api/payment_intents/object#payment_intent_object-client_secret + */ + clientSecret?: string; +} + +export interface StripeElementsOptions extends BaseStripeElementsOptions { + /** + * Whether the Payment Element will be used to create a PaymentIntent, SetupIntent, or Subscription. + */ + mode?: 'payment' | 'setup' | 'subscription'; + + /** + * Three character currency code (e.g., usd). + */ + currency?: string; + + /** + * The amount to be charged. Shown in Apple Pay, Google Pay, or Buy now pay later UIs, and influences available payment methods. + */ + amount?: number; + + /** + * Indicates that you intend to make future payments with this PaymentIntent’s payment method. + * + * @docs https://stripe.com/docs/api/payment_intents/create#create_payment_intent-setup_future_usage + */ + setup_future_usage?: 'off_session' | 'on_session'; + + /** + * Controls when the funds will be captured from the customer’s account. + * + * @docs https://stripe.com/docs/api/payment_intents/create#create_payment_intent-capture_method + */ + capture_method?: 'manual' | 'automatic'; +} + /* * Updatable options for an `Elements` instance */ @@ -682,6 +716,35 @@ export interface StripeElementsUpdateOptions { * @docs https://stripe.com/docs/stripe-js/appearance-api */ appearance?: Appearance; + + /** + * Whether the Payment Element will be used to create a PaymentIntent, SetupIntent, or Subscription. + */ + mode?: 'payment' | 'setup' | 'subscription'; + + /** + * Three character currency code (e.g., usd). + */ + currency?: string; + + /** + * The amount to be charged. Shown in Apple Pay, Google Pay, or Buy now pay later UIs, and influences available payment methods. + */ + amount?: number; + + /** + * Indicates that you intend to make future payments with this PaymentIntent’s payment method. + * + * @docs https://stripe.com/docs/api/payment_intents/create#create_payment_intent-setup_future_usage + */ + setup_future_usage?: 'off_session' | 'on_session'; + + /** + * Controls when the funds will be captured from the customer’s account. + * + * @docs https://stripe.com/docs/api/payment_intents/create#create_payment_intent-capture_method + */ + capture_method?: 'manual' | 'automatic'; } /* diff --git a/types/stripe-js/payment-intents.d.ts b/types/stripe-js/payment-intents.d.ts index 911efc0c..1e3ab340 100644 --- a/types/stripe-js/payment-intents.d.ts +++ b/types/stripe-js/payment-intents.d.ts @@ -9,7 +9,11 @@ import { StripeCardElement, StripeAuBankAccountElement, } from './elements'; -import {PaymentMethodCreateParams, PaymentIntentConfirmParams} from '../api'; +import { + PaymentMethodCreateParams, + CreatePaymentMethodElements, + PaymentIntentConfirmParams, +} from '../api'; import {Omit} from '../utils'; export type CreatePaymentMethodData = @@ -38,7 +42,8 @@ export type CreatePaymentMethodData = | CreatePaymentMethodUsBankAccountData | CreatePaymentMethodSepaDebitData | CreatePaymentMethodSofortData - | CreatePaymentMethodWechatPayData; + | CreatePaymentMethodWechatPayData + | CreatePaymentMethodElements; export interface CreatePaymentMethodAlipayData extends PaymentMethodCreateParams { diff --git a/types/stripe-js/stripe.d.ts b/types/stripe-js/stripe.d.ts index 748d1007..aba8d10a 100644 --- a/types/stripe-js/stripe.d.ts +++ b/types/stripe-js/stripe.d.ts @@ -7,7 +7,11 @@ import * as elements from './elements'; import * as financialConnections from './financial-connections'; import * as ephemeralKeys from './ephemeral-keys'; -import {StripeElements, StripeElementsOptions} from './elements-group'; +import { + StripeElements, + StripeElementsOptions, + StripeElementsOptionsClientSecret, +} from './elements-group'; import {CheckoutLocale, RedirectToCheckoutOptions} from './checkout'; import {PaymentRequestOptions, PaymentRequest} from './payment-request'; import {StripeElement, StripeElementLocale} from './elements-group'; @@ -22,6 +26,7 @@ export interface Stripe { /** * Create an `Elements` instance, which manages a group of elements. */ + elements(options?: StripeElementsOptionsClientSecret): StripeElements; elements(options?: StripeElementsOptions): StripeElements; ///////////////////////////// @@ -60,6 +65,12 @@ export interface Stripe { confirmParams?: Partial; redirect: 'if_required'; }): Promise; + confirmPayment(options: { + elements?: StripeElements; + clientSecret: string; + confirmParams?: Partial; + redirect: 'if_required'; + }): Promise; /** * Use `stripe.confirmPayment` to confirm a PaymentIntent using data collected by the [Payment Element](https://stripe.com/docs/js/element/payment_element). @@ -73,6 +84,12 @@ export interface Stripe { confirmParams: paymentIntents.ConfirmPaymentData; redirect?: 'always'; }): Promise; + confirmPayment(options: { + elements?: StripeElements; + clientSecret: string; + confirmParams: paymentIntents.ConfirmPaymentData; + redirect?: 'always'; + }): Promise; /** * Use `stripe.confirmAcssDebitPayment` in the [Accept a Canadian pre-authorized debit payment](https://stripe.com/docs/payments/acss-debit/accept-a-payment) flow when the customer submits your payment form. @@ -515,6 +532,22 @@ export interface Stripe { */ handleCardAction(clientSecret: string): Promise; + /** + * Use `stripe.handleNextAction` in the Payment Intents API finalizing payments on the server flow to finish confirmation of a [PaymentIntent](https://stripe.com/docs/api/payment_intents) or [SetupIntent](https://stripe.com/docs/api/setup_intents) with the `requires_action` status. + * It will throw an error if the `PaymentIntent` has a different status. + * + * Note that `stripe.handleNextAction` may take several seconds to complete. + * During that time, you should disable your form from being resubmitted and show a waiting indicator like a spinner. + * If you receive an error result, you should be sure to show that error to the customer, re-enable the form, and hide the waiting indicator. + * + * Additionally, `stripe.handleNextAction` may trigger a [3D Secure](https://stripe.com/docs/payments/3d-secure) authentication challenge. + * The authentication challenge requires a context switch that can be hard to follow on a screen-reader. + * Ensure that your form is accessible by ensuring that success or error messages are clearly read out. + * + * @docs https://stripe.com/docs/js/payment_intents/handle_next_action + */ + handleNextAction(clientSecret: string): Promise; + /** * Use `stripe.verifyMicrodepositsForPayment` in the [Accept a Canadian pre-authorized debit payment](https://stripe.com/docs/payments/acss-debit/accept-a-payment) flow * to verify a customer's bank account with micro-deposits. @@ -582,6 +615,12 @@ export interface Stripe { confirmParams?: Partial; redirect: 'if_required'; }): Promise; + confirmSetup(options: { + elements?: StripeElements; + clientSecret: string; + confirmParams?: Partial; + redirect: 'if_required'; + }): Promise; /** * Use `stripe.confirmSetup` to confirm a SetupIntent using data collected by the [Payment Element](https://stripe.com/docs/js/element/payment_element). @@ -595,6 +634,12 @@ export interface Stripe { confirmParams: paymentIntents.ConfirmPaymentData; redirect?: 'always'; }): Promise; + confirmSetup(options: { + elements?: StripeElements; + clientSecret: string; + confirmParams: paymentIntents.ConfirmPaymentData; + redirect?: 'always'; + }): Promise; /** * Use `stripe.confirmAcssDebitSetup` to [save details for future payments with pre-authorized debit in Canada](https://stripe.com/docs/payments/acss-debit/set-up-payment).