[stripe-v3] Update Stripe interface for new APIs (#35807)

* [stripe-v3] Update Stripe interface

* Add methods for new APIs:
    - PaymentMethod
    - Checkout
    - PaymentIntent

* [stripe-v3] Use named type instead of union type

* [stripe-v3] Update and fix tests to use stripe v3

* [stripe-v3] Add tests for new API and fix  some types

* [stripe-v3] Remove unnecessary reference
This commit is contained in:
Victor Gaudard 2019-06-04 22:11:10 +02:00 committed by Andrew Casey
parent 3e7758937b
commit 257fb84ce2
2 changed files with 241 additions and 101 deletions

View File

@ -27,11 +27,67 @@ declare namespace stripe {
createSource(options: SourceOptions): Promise<SourceResponse>;
retrieveSource(options: RetrieveSourceOptions): Promise<SourceResponse>;
paymentRequest(options: paymentRequest.StripePaymentRequestOptions): paymentRequest.StripePaymentRequest;
createPaymentMethod(type: paymentMethodType, element: elements.Element, data?: StripePaymentMethodIncomplete): Promise<StripePaymentMethodResponse>;
redirectToCheckout(options: StripeCheckoutOptions): Promise<StripeRedirectResponse>;
retrievePaymentIntent(clientSecret: string): Promise<paymentIntent.PaymentIntentResponse>;
handleCardPayment(clientSecret: string, element: elements.Element, data?: paymentIntent.CardPaymentData): Promise<paymentIntent.PaymentIntentResponse>;
handleCardPayment(clientSecret: string, data?: paymentIntent.CardPaymentData): Promise<paymentIntent.PaymentIntentResponse>;
handleCardAction(clientSecret: string): Promise<paymentIntent.PaymentIntentResponse>;
confirmPaymentIntent(clientSecret: string, element: elements.Element, data: paymentIntent.PaymentIntentConfirmationData): Promise<paymentIntent.PaymentIntentResponse>;
confirmPaymentIntent(clientSecret: string, data: paymentIntent.PaymentIntentConfirmationData): Promise<paymentIntent.PaymentIntentResponse>;
}
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 {

View File

@ -1,41 +1,54 @@
/// <reference types="stripe-v2" />
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 = <HTMLIFrameElement> 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);
}
});
});