Add 3D Secure and Payment Request types to stripe-v3

This commit is contained in:
Ben Stevens
2018-02-11 17:41:29 +00:00
parent 60f5ee3a3c
commit 185f38ea6a
2 changed files with 236 additions and 17 deletions
+150 -17
View File
@@ -12,18 +12,23 @@ declare var Stripe: stripe.StripeStatic;
declare namespace stripe {
interface StripeStatic {
(publicKey: string): Stripe;
(publicKey: string, options?: StripeOptions): Stripe;
version: number;
}
interface Stripe {
elements(options?: elements.ElementsCreateOptions): elements.Elements;
createToken(element: elements.Element, options?: TokenOptions): Promise<TokenResponse>;
createToken(name: 'bank_account', options: BankAccountTokenOptions): Promise<TokenResponse>;
createToken(name: 'pii', options: PiiTokenOptions): Promise<TokenResponse>;
createSource(element: elements.Element, options?: {owner?: OwnerInfo}): Promise<SourceResponse>;
createSource(options: SourceOptions): Promise<SourceResponse>;
retrieveSource(options: RetrieveSourceOptions): Promise<SourceResponse>;
paymentRequest(options: paymentRequest.StripePaymentRequestOptions): paymentRequest.StripePaymentRequest;
}
interface StripeOptions {
stripeAccount: string;
stripeAccount?: string;
}
interface TokenOptions {
@@ -37,6 +42,33 @@ declare namespace stripe {
currency?: string;
}
interface BankAccountTokenOptions {
country: string;
currency: string;
routing_number: string;
account_number: string;
account_holder_name: string;
account_holder_type: string;
}
interface PiiTokenOptions {
personal_id_number: string;
}
interface OwnerInfo {
address?: {
city?: string;
country?: string;
line1?: string;
line2?: string;
postal_code?: string;
state?: string;
};
name?: string;
email?: string;
phone?: string;
}
interface SourceOptions {
type: string;
flow?: 'redirect' | 'receiver' | 'code_verification' | 'none';
@@ -45,19 +77,7 @@ declare namespace stripe {
};
currency?: string;
amount?: number;
owner?: {
address?: {
city?: string;
country?: string;
line1?: string;
line2?: string;
postal_code?: string;
state?: string;
};
name?: string;
email?: string;
phone?: string;
};
owner?: OwnerInfo;
metadata?: {};
statement_descriptor?: string;
redirect?: {
@@ -65,6 +85,9 @@ declare namespace stripe {
};
token?: string;
usage?: 'reusable' | 'single_use';
three_d_secure?: {
card: string;
};
}
interface Token {
@@ -106,6 +129,15 @@ declare namespace stripe {
last4: string;
mandate_reference: string;
};
card?: Card;
status?: string;
redirect?: {
status: string;
url: string;
};
three_d_secure?: {
authenticated: boolean;
};
}
interface SourceResponse {
@@ -165,6 +197,94 @@ declare namespace stripe {
metadata: any;
name?: string;
tokenization_method?: tokenizationType;
three_d_secure?: 'required' | 'recommended' | 'optional' | 'not_supported';
}
interface RetrieveSourceOptions {
id: string;
client_secret: string;
}
// Container for all payment request related types
namespace paymentRequest {
interface StripePaymentRequestUpdateOptions {
currency: string;
total: {
amount: number;
label: string;
pending?: boolean;
};
displayItems?: Array<{
amount: number;
label: string;
pending?: boolean;
}>;
shippingOptions?: ShippingOption[];
}
interface StripePaymentRequestOptions extends StripePaymentRequestUpdateOptions {
country: string;
requestPayerName?: boolean;
requestPayerEmail?: boolean;
requestPayerPhone?: boolean;
requestShipping?: boolean;
}
interface UpdateDetails {
status: 'success' | 'fail' | 'invalid_shipping_address';
total?: {
amount: number;
label: string;
pending?: boolean;
};
displayItems?: Array<{
amount: number;
label: string;
pending?: boolean;
}>;
shippingOptions?: ShippingOption[];
}
interface ShippingOption {
id: string;
label: string;
detail?: string;
amount: number;
}
interface ShippingAddress {
country: string;
addressLine: string[];
region: string;
city: string;
postalCode: string;
recipient: string;
phone: string;
sortingCode?: string;
dependentLocality?: string;
}
interface StripePaymentResponse {
token?: Token;
source?: Source;
complete: (status: string) => void;
payerName?: string;
payerEmail?: string;
payerPhone?: string;
shippingAddress?: ShippingAddress;
shippingOption?: ShippingOption;
methodName: string;
}
interface StripePaymentRequest {
canMakePayment(): Promise<{applePay?: boolean} | null>;
show(): void;
update(options: StripePaymentRequestUpdateOptions): void;
on(event: 'token' | 'source', handler: (response: StripePaymentResponse) => void): void;
on(event: 'cancel', handler: () => void): void;
on(event: 'shippingaddresschange', handler: (response: {updateWith: (options: UpdateDetails) => void, shippingAddress: ShippingAddress}) => void): void;
on(event: 'shippingoptionchange', handler: (response: {updateWith: (options: UpdateDetails) => void, shippingOption: ShippingOption}) => void): void;
}
}
// Container for all elements related types
@@ -181,6 +301,7 @@ declare namespace stripe {
// Cannot find name 'HTMLElement'
mount(domElement: any): void;
on(event: eventTypes, handler: handler): void;
on(event: 'click', handler: (response: {preventDefault: () => void}) => void): void;
focus(): void;
blur(): void;
clear(): void;
@@ -202,9 +323,9 @@ declare namespace stripe {
locale?: string;
}
type elementsType = 'card' | 'cardNumber' | 'cardExpiry' | 'cardCvc' | 'postalCode';
type elementsType = 'card' | 'cardNumber' | 'cardExpiry' | 'cardCvc' | 'postalCode' | 'paymentRequestButton';
interface Elements {
create(type: elementsType, options: ElementsOptions): Element;
create(type: elementsType, options?: ElementsOptions): Element;
}
interface ElementsOptions {
@@ -219,13 +340,16 @@ declare namespace stripe {
hidePostalCode?: boolean;
hideIcon?: boolean;
iconStyle?: 'solid' | 'default';
placeholder?: string;
style?: {
base?: Style;
complete?: Style;
empty?: Style;
invalid?: Style;
paymentRequestButton?: PaymentRequestButtonStyleOptions;
};
value?: string | { [objectKey: string]: string; };
paymentRequest?: paymentRequest.StripePaymentRequest;
}
interface Style extends StyleOptions {
@@ -234,11 +358,13 @@ declare namespace stripe {
'::placeholder'?: StyleOptions;
'::selection'?: StyleOptions;
':-webkit-autofill'?: StyleOptions;
'::-ms-clear'?: StyleOptions;
}
interface Font {
family?: string;
src?: string;
display?: string;
style?: string;
unicodeRange?: string;
weight?: string;
@@ -255,9 +381,16 @@ declare namespace stripe {
iconColor?: string;
lineHeight?: string;
letterSpacing?: string;
textAlign?: string;
textDecoration?: string;
textShadow?: string;
textTransform?: string;
}
interface PaymentRequestButtonStyleOptions {
type?: 'default' | 'donate' | 'buy';
theme: 'dark' | 'light' | 'light-outline';
height: string;
}
}
}
+86
View File
@@ -42,7 +42,93 @@ describe("Stripe", () => {
(error: stripe.Error) => {
console.error(error);
});
// test 3D secure
const threeDSecureFrame = <HTMLIFrameElement> document.getElementById('3d-secure-frame');
const ownerInfo = {
name: 'Jimmy',
address: {
line1: '1 High Street',
postal_code: 'XYZ'
}
};
stripe.createSource(card, { owner: ownerInfo }).then(result => {
if (result.error) {
console.log(result.error.message);
return Promise.resolve(null);
}
if (!result.source) {
console.log('error');
return Promise.resolve(null);
}
if (!result.source.card || result.source.card.three_d_secure === 'not_supported') {
// make regular payment...
return Promise.resolve(null);
}
return stripe.createSource({
type: 'three_d_secure',
amount: 100,
currency: 'usd',
three_d_secure: {
card: result.source.id
},
redirect: {
return_url: location.origin + '/3d-secure-processing-page'
}
});
}).then(threeDSource => {
if (!threeDSource) {
return Promise.resolve(null);
}
if (threeDSource.error) {
if (threeDSource.error.code === 'payment_method_not_available') {
// make regular payment...
return Promise.resolve(null);
}
console.log('error');
return Promise.resolve(null);
}
if (!threeDSource.source || threeDSource.source.status === 'failed' || !threeDSource.source.redirect) {
// make regular payment...
return Promise.resolve(null);
}
if (threeDSource.source.redirect.status === 'succeeded') {
// make charge...
return Promise.resolve(null);
}
threeDSecureFrame.setAttribute('src', threeDSource.source.redirect.url);
// now wait until chargeable then make the charge
return Promise.resolve(null);
});
card.destroy();
// test payment request
const paymentRequest = stripe.paymentRequest({
country: 'US',
currency: 'usd',
total: {
label: 'Demo total',
amount: 1000,
}
});
const prButton = elements.create('paymentRequestButton', { paymentRequest });
paymentRequest.canMakePayment().then(result => {
if (result) {
prButton.mount('#payment-request-button');
} else {
document.getElementById('payment-request-button')!.style.display = 'none';
}
});
paymentRequest.on('token', ev => {
const body = JSON.stringify({token: ev.token!.id});
// post to server...
Promise.resolve({ok: true})
.then(response => {
if (response.ok) {
ev.complete('success');
} else {
ev.complete('fail');
}
});
});
});
});