mirror of
https://github.com/gosticks/DefinitelyTyped.git
synced 2025-10-16 12:05:41 +00:00
* Update react-stripe-elements definitions to allow BankAccountOptions to be passed to createToken Also add some tests for the Iban, IdealBank and PaymentRequestButton elements * Update stripe-v3 to accept BankAccountOptions on createToken
425 lines
13 KiB
TypeScript
425 lines
13 KiB
TypeScript
import * as React from 'react';
|
|
import {
|
|
StripeProvider,
|
|
CardElement,
|
|
Elements,
|
|
injectStripe,
|
|
CardNumberElement,
|
|
CardExpiryElement,
|
|
CardCvcElement,
|
|
CardCVCElement,
|
|
IbanElement,
|
|
IdealBankElement,
|
|
PostalCodeElement,
|
|
PaymentRequestButtonElement,
|
|
ReactStripeElements,
|
|
} from 'react-stripe-elements';
|
|
import InjectedStripeProps = ReactStripeElements.InjectedStripeProps;
|
|
|
|
import ElementChangeResponse = stripe.elements.ElementChangeResponse;
|
|
import ElementsOptions = stripe.elements.ElementsOptions;
|
|
import ElementsCreateOptions = stripe.elements.ElementsCreateOptions;
|
|
import HTMLStripeElement = ReactStripeElements.HTMLStripeElement;
|
|
import TokenResponse = ReactStripeElements.TokenResponse;
|
|
|
|
const cardElementProps: ElementsOptions = {
|
|
iconStyle: 'solid',
|
|
style: {
|
|
base: {
|
|
color: '#32325d',
|
|
lineHeight: '24px',
|
|
fontFamily: 'Roboto, "Helvetica Neue", sans-serif',
|
|
fontSmoothing: 'antialiased',
|
|
fontSize: '16px',
|
|
'::placeholder': {
|
|
color: '#aab7c4',
|
|
},
|
|
},
|
|
invalid: {
|
|
color: '#B71C1C',
|
|
iconColor: '#B71C1C',
|
|
},
|
|
},
|
|
hidePostalCode: true,
|
|
classes: {
|
|
base: 'field',
|
|
complete: 'complete',
|
|
empty: 'is-empty',
|
|
focus: 'is-focused',
|
|
invalid: 'is-invalid',
|
|
webkitAutofill: 'webkit-autofill',
|
|
},
|
|
hideIcon: true,
|
|
};
|
|
|
|
const fontElementsProps: ElementsCreateOptions = {
|
|
fonts: [
|
|
{
|
|
cssSrc: 'https://fonts.googleapis.com/css?family=Dosis',
|
|
},
|
|
{
|
|
family: 'Dosis, sanz',
|
|
src: 'url(https://somewebsite.com/path/to/font.woff)',
|
|
style: 'normal',
|
|
weight: 'bold',
|
|
unicodeRange: 'U+26',
|
|
},
|
|
],
|
|
locale: 'es',
|
|
};
|
|
|
|
const ElementsWithPropsTest: React.FC = () => (
|
|
<div>
|
|
<CardElement
|
|
{...cardElementProps}
|
|
onChange={(event: ElementChangeResponse) => void 0}
|
|
onBlur={(event: ElementChangeResponse) => void 0}
|
|
onReady={(el: HTMLStripeElement) => void 0}
|
|
onFocus={(event: ElementChangeResponse) => void 0}
|
|
/>
|
|
<CardNumberElement
|
|
{...cardElementProps}
|
|
onChange={(event: ElementChangeResponse) => void 0}
|
|
onBlur={(event: ElementChangeResponse) => void 0}
|
|
onReady={(el: HTMLStripeElement) => void 0}
|
|
onFocus={(event: ElementChangeResponse) => void 0}
|
|
/>
|
|
<CardExpiryElement
|
|
{...cardElementProps}
|
|
onChange={(event: ElementChangeResponse) => void 0}
|
|
onBlur={(event: ElementChangeResponse) => void 0}
|
|
onReady={(el: HTMLStripeElement) => void 0}
|
|
onFocus={(event: ElementChangeResponse) => void 0}
|
|
/>
|
|
<CardCvcElement
|
|
{...cardElementProps}
|
|
onChange={(event: ElementChangeResponse) => void 0}
|
|
onBlur={(event: ElementChangeResponse) => void 0}
|
|
onReady={(el: HTMLStripeElement) => void 0}
|
|
onFocus={(event: ElementChangeResponse) => void 0}
|
|
/>
|
|
<CardCVCElement
|
|
{...cardElementProps}
|
|
onChange={(event: ElementChangeResponse) => void 0}
|
|
onBlur={(event: ElementChangeResponse) => void 0}
|
|
onReady={(el: HTMLStripeElement) => void 0}
|
|
onFocus={(event: ElementChangeResponse) => void 0}
|
|
/>
|
|
<IbanElement
|
|
{...cardElementProps}
|
|
onChange={(event: ElementChangeResponse) => void 0}
|
|
onBlur={(event: ElementChangeResponse) => void 0}
|
|
onReady={(el: HTMLStripeElement) => void 0}
|
|
onFocus={(event: ElementChangeResponse) => void 0}
|
|
/>
|
|
<IdealBankElement
|
|
{...cardElementProps}
|
|
onChange={(event: ElementChangeResponse) => void 0}
|
|
onBlur={(event: ElementChangeResponse) => void 0}
|
|
onReady={(el: HTMLStripeElement) => void 0}
|
|
onFocus={(event: ElementChangeResponse) => void 0}
|
|
/>
|
|
<PostalCodeElement
|
|
{...cardElementProps}
|
|
onChange={(event: ElementChangeResponse) => void 0}
|
|
onBlur={(event: ElementChangeResponse) => void 0}
|
|
onReady={(el: HTMLStripeElement) => void 0}
|
|
onFocus={(event: ElementChangeResponse) => void 0}
|
|
/>
|
|
<PaymentRequestButtonElement
|
|
{...cardElementProps}
|
|
onChange={(event: ElementChangeResponse) => void 0}
|
|
onBlur={(event: ElementChangeResponse) => void 0}
|
|
onReady={(el: HTMLStripeElement) => void 0}
|
|
onFocus={(event: ElementChangeResponse) => void 0}
|
|
onClick={(event: ElementChangeResponse) => void 0}
|
|
/>
|
|
</div>
|
|
);
|
|
|
|
interface ComponentProps {
|
|
tokenCallback(token: TokenResponse): void;
|
|
}
|
|
|
|
class WrappedComponent extends React.Component<ComponentProps & InjectedStripeProps> {
|
|
constructor(props: ComponentProps & InjectedStripeProps) {
|
|
super(props);
|
|
// Test for paymentRequest
|
|
const paymentRequest =
|
|
props.stripe &&
|
|
props.stripe.paymentRequest({
|
|
country: 'US',
|
|
currency: 'usd',
|
|
total: {
|
|
label: 'Demo total',
|
|
amount: 1,
|
|
},
|
|
});
|
|
if (paymentRequest) {
|
|
paymentRequest.on('token', ({ complete, token, ...data }) => undefined);
|
|
paymentRequest.canMakePayment().then(res => undefined);
|
|
}
|
|
}
|
|
|
|
onSubmit = () => {
|
|
const elements = this.props.elements;
|
|
|
|
// createToken(options?: TokenOptions)
|
|
this.props
|
|
.stripe!.createToken({
|
|
name: '',
|
|
address_line1: '',
|
|
address_line2: '',
|
|
address_city: '',
|
|
address_state: '',
|
|
address_zip: '',
|
|
address_country: '',
|
|
currency: '',
|
|
})
|
|
.then((response: TokenResponse) => this.props.tokenCallback(response));
|
|
|
|
// createToken(options?: BankAccountTokenOptions)
|
|
this.props
|
|
.stripe!.createToken({
|
|
country: '',
|
|
currency: '',
|
|
routing_number: '',
|
|
account_number: '',
|
|
account_holder_name: '',
|
|
account_holder_type: '',
|
|
})
|
|
.then((response: TokenResponse) => this.props.tokenCallback(response));
|
|
}
|
|
|
|
isFormValid = () => {
|
|
// use onChange callbacks from *Element components to detect if form is valid for submission
|
|
return false;
|
|
}
|
|
|
|
render() {
|
|
return (
|
|
<form onSubmit={this.onSubmit}>
|
|
<ElementsWithPropsTest />
|
|
<button disabled={!this.isFormValid()} />
|
|
</form>
|
|
);
|
|
}
|
|
}
|
|
|
|
const ExportedComponent: React.ComponentType<ComponentProps> = injectStripe(WrappedComponent);
|
|
|
|
class MainComponent extends React.Component {
|
|
onTokenReceived = (token: TokenResponse) => void 0;
|
|
|
|
render() {
|
|
return <ExportedComponent tokenCallback={this.onTokenReceived} />;
|
|
}
|
|
}
|
|
|
|
class TestHOCs extends React.Component {
|
|
render() {
|
|
return (
|
|
<StripeProvider apiKey="">
|
|
<Elements {...fontElementsProps}>
|
|
<MainComponent />
|
|
</Elements>
|
|
</StripeProvider>
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Just an extra test to check default props
|
|
*/
|
|
const ElementsDefaultPropsTest: React.FC = () => (
|
|
<div>
|
|
<CardElement />
|
|
<CardNumberElement />
|
|
<CardExpiryElement />
|
|
<CardCvcElement />
|
|
<CardCVCElement />
|
|
<PostalCodeElement />
|
|
</div>
|
|
);
|
|
|
|
/**
|
|
* StripeProvider should either receive `apiKey` or `stripe`, but not both.
|
|
* See: https://github.com/stripe/react-stripe-elements/blob/d30b32b6b8df282dd8880a3521667c371e90083f/src/components/Provider.js#L83-L86
|
|
*/
|
|
const TestStripeProviderProps1: React.FC = () => <StripeProvider apiKey="" />;
|
|
|
|
const TestStripeProviderProps2: React.FC<{
|
|
stripe: stripe.Stripe;
|
|
}> = props => <StripeProvider stripe={props.stripe} />;
|
|
|
|
/**
|
|
* props.stripe is null until loaded.
|
|
* See: https://github.com/stripe/react-stripe-elements#props-shape
|
|
*/
|
|
const TestStripeProviderProps3: React.FC<{
|
|
stripe: stripe.Stripe;
|
|
}> = props => <StripeProvider stripe={null} />;
|
|
|
|
/**
|
|
* End-to-end usage of loading stripe.js asynchronously.
|
|
* See: https://github.com/stripe/react-stripe-elements#loading-stripejs-asynchronously
|
|
*/
|
|
const TestStripeProviderProps4: React.FC<{
|
|
stripe: null | stripe.Stripe;
|
|
}> = props => (
|
|
<StripeProvider stripe={props.stripe}>
|
|
<Elements>
|
|
<div />
|
|
</Elements>
|
|
</StripeProvider>
|
|
);
|
|
|
|
/**
|
|
* StripeProvider should be able to accept options.
|
|
* See: https://stripe.com/docs/stripe-js/reference#stripe-function for options.
|
|
*/
|
|
const TestStripeProviderOptions: React.FC = () => <StripeProvider apiKey="" stripeAccount="" />;
|
|
|
|
class CreatePaymentMethod extends React.Component<InjectedStripeProps> {
|
|
testCreatePaymentMethod = () => {
|
|
this.props
|
|
.stripe!.createPaymentMethod('card')
|
|
.then((response) => response.paymentMethod);
|
|
}
|
|
|
|
testCreatePaymentMethodWithData = () => {
|
|
this.props
|
|
.stripe!.createPaymentMethod('card', {
|
|
billing_details: {
|
|
name: 'John Doe'
|
|
},
|
|
metadata: {
|
|
foo: 'bar'
|
|
}
|
|
})
|
|
.then((response) => response.paymentMethod);
|
|
}
|
|
|
|
testCreatePaymentMethodWithNewData = () => {
|
|
const cardEl = this.props.elements!.getElement('card') || undefined;
|
|
this.props
|
|
.stripe!.createPaymentMethod({
|
|
type: 'card',
|
|
card: cardEl,
|
|
billing_details: {
|
|
name: 'Jenny Rosen'
|
|
}
|
|
})
|
|
.then((response) => response.paymentMethod);
|
|
}
|
|
|
|
testCreatePaymentMethodWithError = () => {
|
|
this.props
|
|
.stripe!.createPaymentMethod('card')
|
|
.then((response) => response.error);
|
|
}
|
|
}
|
|
|
|
class HandleCardPayment extends React.Component<InjectedStripeProps> {
|
|
testHandleCardAction = () => {
|
|
this.props
|
|
.stripe!.handleCardAction('{PAYMENT_INTENT_CLIENT_SECRET}')
|
|
.then((response) => response.paymentIntent);
|
|
}
|
|
|
|
testHandleCardPayment = () => {
|
|
this.props
|
|
.stripe!.handleCardPayment('clientSecret')
|
|
.then((response) => response.paymentIntent);
|
|
}
|
|
|
|
testHandleCardPaymentWithOptions = () => {
|
|
this.props
|
|
.stripe!.handleCardPayment('clientSecret', {
|
|
payment_method_data: {
|
|
billing_details: {
|
|
name: 'John Doe'
|
|
}
|
|
},
|
|
receipt_email: 'john@doe.com'
|
|
})
|
|
.then((response) => response.paymentIntent);
|
|
}
|
|
|
|
testHandleCardPaymentWithError = () => {
|
|
this.props
|
|
.stripe!.handleCardPayment('clientSecret')
|
|
.then((response) => response.error);
|
|
}
|
|
}
|
|
|
|
class HandleCardSetup extends React.Component<InjectedStripeProps> {
|
|
testHandleCardSetup = () => {
|
|
this.props
|
|
.stripe!.handleCardSetup('clientSecret')
|
|
.then((response) => response.setupIntent);
|
|
}
|
|
|
|
testHandleCardSetupWithData = () => {
|
|
this.props
|
|
.stripe!.handleCardSetup('clientSecret', {
|
|
payment_method_data: {
|
|
billing_details: {
|
|
name: 'John Doe'
|
|
}
|
|
}
|
|
})
|
|
.then((response) => response.setupIntent);
|
|
}
|
|
|
|
testHandleCardSetupWithError = () => {
|
|
this.props
|
|
.stripe!.handleCardSetup('clientSecret')
|
|
.then((response) => response.error);
|
|
}
|
|
}
|
|
|
|
class ConfirmPaymentPayment extends React.Component<InjectedStripeProps> {
|
|
testConfirmCardPayment = () => {
|
|
const el = this.props.elements!.getElement('card');
|
|
this.props
|
|
.stripe!.confirmCardPayment('clientSecret', {
|
|
payment_method: {
|
|
card: el || { token: 'test token' },
|
|
billing_details: {
|
|
name: 'Jenny Rosen'
|
|
}
|
|
}
|
|
})
|
|
.then((response) => response.paymentIntent);
|
|
}
|
|
|
|
testConfirmCardPaymentWithError = () => {
|
|
this.props
|
|
.stripe!.handleCardSetup('clientSecret')
|
|
.then((response) => response.error);
|
|
}
|
|
}
|
|
|
|
class ConfirmCardSetup extends React.Component<InjectedStripeProps> {
|
|
testConfirmCardSetup = () => {
|
|
const el = this.props.elements!.getElement('cardNumber');
|
|
this.props
|
|
.stripe!.confirmCardSetup('clientSecret', {
|
|
payment_method: {
|
|
card: el || { token: 'test with token' },
|
|
billing_details: {
|
|
name: 'Jenny Rosen'
|
|
}
|
|
}
|
|
})
|
|
.then((response) => response.setupIntent);
|
|
}
|
|
|
|
testConfirmCardSetupWithError = () => {
|
|
this.props
|
|
.stripe!.handleCardSetup('clientSecret')
|
|
.then((response) => response.error);
|
|
}
|
|
}
|