diff --git a/types/stripe-v3/index.d.ts b/types/stripe-v3/index.d.ts index a961b3250e..20ca0a4053 100644 --- a/types/stripe-v3/index.d.ts +++ b/types/stripe-v3/index.d.ts @@ -27,11 +27,67 @@ declare namespace stripe { createSource(options: SourceOptions): Promise; retrieveSource(options: RetrieveSourceOptions): Promise; paymentRequest(options: paymentRequest.StripePaymentRequestOptions): paymentRequest.StripePaymentRequest; + createPaymentMethod(type: paymentMethodType, element: elements.Element, data?: StripePaymentMethodIncomplete): Promise; + redirectToCheckout(options: StripeCheckoutOptions): Promise; + retrievePaymentIntent(clientSecret: string): Promise; + handleCardPayment(clientSecret: string, element: elements.Element, data?: paymentIntent.CardPaymentData): Promise; + handleCardPayment(clientSecret: string, data?: paymentIntent.CardPaymentData): Promise; + handleCardAction(clientSecret: string): Promise; + confirmPaymentIntent(clientSecret: string, element: elements.Element, data: paymentIntent.PaymentIntentConfirmationData): Promise; + confirmPaymentIntent(clientSecret: string, data: paymentIntent.PaymentIntentConfirmationData): Promise; + } + + type StripeRedirectResponse = never | { + error: Error; + }; + + interface StripePaymentMethodResponse { + paymentMethod?: StripePaymentMethod; + error?: Error; + } + + type paymentMethodType = 'card' | 'card_present'; + interface StripePaymentMethod extends StripePaymentMethodIncomplete { + id: string; + type: paymentMethodType; + } + + interface StripePaymentMethodIncomplete { + type?: paymentMethodType; + billing_details?: OwnerInfo; + card?: StripePaymentMethodCard; + metadata?: any; + } + + type billingAddressCollectionType = 'required' | 'auto' | ''; + interface StripeCheckoutOptions { + items: StripeCheckoutItem[]; + successUrl: string; + cancelUrl: string; + clientReferenceId?: string; + customerEmail?: string; + billingAddressCollection?: billingAddressCollectionType; + sessionId?: string; + locale?: string; + } + + interface StripeCheckoutItem { + sku?: string; + plan?: string; + quantity: number; + } + + interface StripePaymentMethodCard { + exp_month: number; + exp_year: number; + number: string; + cvc?: string; } interface StripeOptions { - stripeAccount?: string; - betas?: string[]; + stripeAccount?: string; + betas?: string[]; + locale?: string; } interface TokenOptions { @@ -210,6 +266,67 @@ declare namespace stripe { client_secret: string; } + namespace paymentIntent { + interface PaymentIntentResponse { + paymentIntent?: StripePaymentIntent; + error?: Error; + } + + type paymentIntentStatus = 'requires_payment_method' | 'requires_confirmation' | 'requires_action' | 'processing' | 'requires_capture' | 'canceled' | 'succeeded'; + interface StripePaymentIntent { + id: string; + object: 'payment_intent'; + amount: number; + canceled_at: number; + client_secret: string; + created: number; + currency: string; + description: string; + livemode: boolean; + next_action: NextAction; + payment_method: string; + receipt_email: string; + shipping: ShippingInformation; + status: paymentIntentStatus; + } + + type nextActionType = 'redirect_to_url' | 'use_stripe_sdk'; + interface NextAction { + redirect_to_url: RedirectOptions; + type: nextActionType; + } + + interface RedirectOptions { + return_url: string; + url: string; + } + + interface ShippingInformation { + address: OwnerAddress; + carrier: string; + name: string; + phone: string; + tracking_number: string; + } + + interface CardPaymentData { + payment_method?: string; + payment_method_data?: PaymentMethodData; + shipping?: ShippingInformation; + receipt_email?: string; + save_payment_method?: boolean; + } + + interface PaymentMethodData { + billing_details?: OwnerInfo; + card?: {[token: string]: string}; + } + + interface PaymentIntentConfirmationData extends CardPaymentData { + return_url?: string; + } + } + // Container for all payment request related types namespace paymentRequest { interface DisplayItem { diff --git a/types/stripe-v3/stripe-v3-tests.ts b/types/stripe-v3/stripe-v3-tests.ts index d9888a60a4..0a36db11a5 100644 --- a/types/stripe-v3/stripe-v3-tests.ts +++ b/types/stripe-v3/stripe-v3-tests.ts @@ -1,41 +1,54 @@ -/// - declare function describe(desc: string, fn: () => void): void; declare function it(desc: string, fn: () => void): void; -describe("Stripe", () => { - it("should excercise all Stripe API", () => { - const stripe = Stripe('public-key'); - const stripeWithBetaOption = Stripe('public-key', { betas: ['beta-feature'] }); - const elements = stripe.elements(); - const style = { - base: { - color: '#32325d', - lineHeight: '24px', - fontFamily: 'Roboto, "Helvetica Neue", sans-serif', - fontSmoothing: 'antialiased', - fontSize: '16px', - fontWeight: 'bold', - '::placeholder': { - color: '#aab7c4' - } +const style = { + base: { + color: '#32325d', + lineHeight: '24px', + fontFamily: 'Roboto, "Helvetica Neue", sans-serif', + fontSmoothing: 'antialiased', + fontSize: '16px', + fontWeight: 'bold', + '::placeholder': { + color: '#aab7c4' + } + }, + invalid: { + color: '#B71C1C', + iconColor: '#B71C1C' + } +}; + +describe("Stripe object", () => { + it("should exercise alternative ways to create Stripe object", () => { + const stripeWithBetaOption: stripe.Stripe = Stripe('pk_test_TYooMQauvdEDq54NiTphI7jx', { betas: ['beta-feature'] }); // This looks deprecated + const stripeWithLocale: stripe.Stripe = Stripe('pk_test_TYooMQauvdEDq54NiTphI7jx', { locale: 'zh' }); + const stripeWithAccount: stripe.Stripe = Stripe('pk_test_TYooMQauvdEDq54NiTphI7jx', { stripeAccount: 'acct_24BFMpJ1svR5A89k' }); + }); +}); + +describe("Stripe elements", () => { + const stripe = Stripe('pk_test_TYooMQauvdEDq54NiTphI7jx'); + const elements = stripe.elements(); + + it("should create a cards element", () => { + const card = elements.create('card', { + hidePostalCode: false, + style, + value: { + postalCode: '94110', }, - invalid: { - color: '#B71C1C', - iconColor: '#B71C1C' - } - }; - const card = elements.create('card', { hidePostalCode: true, style }); + }); card.mount(document.createElement('div')); card.on('ready', () => { console.log('ready'); }); - card.on('change', (resp: stripe.elements.ElementChangeResponse) => { - console.log(resp.elementType); - }); - card.on('change', (resp: stripe.elements.ElementChangeResponse) => { - console.log(resp.brand); + card.on('change', (response) => { + if (response) { + console.log(response.elementType, response.brand); + } }); + stripe.createToken(card, { name: 'Jimmy', address_city: 'Toronto', @@ -47,6 +60,7 @@ describe("Stripe", () => { (error: stripe.Error) => { console.error(error); }); + // test 3D secure const threeDSecureFrame = document.getElementById('3d-secure-frame'); const ownerInfo = { @@ -105,7 +119,26 @@ describe("Stripe", () => { return Promise.resolve(null); }); card.destroy(); - // test payment request + }); + + it("should create an iban element", () => { + elements.create('iban', { + supportedCountries: ['SEPA'], + placeholderCountry: 'AT' + }); + }); + + it("should create an idealBank element", () => { + const idealBank = elements.create('idealBank'); + idealBank.on('change', (resp: stripe.elements.ElementChangeResponse) => { + if (resp.value && typeof resp.value !== 'object') { + console.log(resp.value.length); + const string: string = resp.value; + } + }); + }); + + it ("should use payment request API", () => { const paymentRequest = stripe.paymentRequest({ country: 'US', currency: 'usd', @@ -147,83 +180,73 @@ describe("Stripe", () => { }); }); }); -}); -describe("Stripe v2 & v3", () => { - it("should excercise all Stripe API", () => { - function success(card: stripe.StripeCard) { - console.log(card.brand && card.brand.toString()); - } - - const cardNumber = '4242424242424242'; - - const isValid = Stripe.validateCardNumber(cardNumber); - if (isValid) { - const tokenData: stripe.StripeCardTokenData = { - number: cardNumber, - exp_month: 1, - exp_year: 2100, - cvc: '111' - }; - Stripe.card.createToken(tokenData, (status, response) => { - if (response.error) { - console.error(response.error.message); - if (response.error.param) { - console.error(response.error.param); - } - } else { - success(response.card); - } - }); - } - const stripe = Stripe('public-key'); - const elements = stripe.elements(); - const style = { - base: { - color: '#32325d', - lineHeight: '24px', - fontFamily: 'Roboto, "Helvetica Neue", sans-serif', - fontSmoothing: 'antialiased', - fontSize: '16px', - fontWeight: 500, - '::placeholder': { - color: '#aab7c4' - } + it("should use payment method API", () => { + const card = elements.create('card'); + stripe.createPaymentMethod('card', card, { + billing_details: { + name: 'Jenny Rosen', }, - invalid: { - color: '#B71C1C', - iconColor: '#B71C1C' + }).then(result => { + if (result.error) { + console.error(result.error.param); + } else if (result.paymentMethod) { + console.log(result.paymentMethod.card && result.paymentMethod.card.number); } - }; - const card = elements.create('card', { hidePostalCode: true, style }); - card.mount(document.createElement('div')); - card.on('ready', () => { - console.log('ready'); }); - card.on('change', (resp: stripe.elements.ElementChangeResponse) => { - console.log(resp.brand); + }); + + it("should use checkout API", () => { + stripe.redirectToCheckout({ + items: [ + {sku: 'sku_123', quantity: 1} + ], + successUrl: 'https://example.com/success', + cancelUrl: 'https://example.com/canceled', + }).then(errorResult => { + console.log(errorResult.error.param); }); - stripe.createToken(card, { - name: 'Jimmy', - address_city: 'Toronto', - address_country: 'Canada' - }) - .then((result: stripe.TokenResponse) => { - console.log(result.token); - }, - (error: stripe.Error) => { - console.error(error); + }); + + it("should use payment intents", () => { + stripe.retrievePaymentIntent('pi_18eYalAHEMiOZZp1l9ZTjSU0_secret_NibvRz4PMmJqjfb0sqmT7aq2') + .then(result => { + if (result.error) { + console.error(result.error.message); + } else if (result.paymentIntent) { + console.log(result.paymentIntent.description); + } }); - elements.create('iban', { - supportedCountries: ['SEPA'], - placeholderCountry: 'AT' + const card = elements.create('card'); + stripe.handleCardPayment( + 'pi_18eYalAHEMiOZZp1l9ZTjSU0_secret_NibvRz4PMmJqjfb0sqmT7aq2', + card, + { + payment_method_data: { + billing_details: { + name: 'Jenny Rosen' + } + } + } + ).then(result => { + if (result.error) { + console.error(result.error.message); + } else if (result.paymentIntent) { + console.log(result.paymentIntent.receipt_email); + } }); - const idealBank = elements.create('idealBank'); - idealBank.on('change', (resp: stripe.elements.ElementChangeResponse) => { - if (resp.value && typeof resp.value !== 'object') { - console.log(resp.value.length); - const string: string = resp.value; + + stripe.handleCardPayment( + '{PAYMENT_INTENT_CLIENT_SECRET}', + { + payment_method: '{PAYMENT_METHOD_ID}', + } + ).then(result => { + if (result.error) { + console.error(result.error.message); + } else if (result.paymentIntent) { + console.log(result.paymentIntent.shipping.address); } }); });