richnologies / ngx-stripe

Angular 6+ wrapper for StripeJS
MIT License
219 stars 77 forks source link

Typings for 'postalCode' `ElementType` missing from `@stripe/stripe-js`? #102

Closed KeithGillette closed 4 years ago

KeithGillette commented 4 years ago

Is this a feature request or a bug report? Bug Report

What's gone wrong? While the actual code seems to work, in attempting to migrate from ngx-stripe v9.0.3 to v 10.1.1 with @stripe/stripe-js@1.8.0, I get the following TypeScript linting error calling StripeElements.create('postalCode', { … }):

TS2769: No overload matches this call.
The last overload gave the following error.
Argument of type '"postalCode"' is not assignable to parameter of type '"paymentRequestButton"'.  elements.d.ts(166, 5): The last overload is declared here.

What was meant to happen? The legacy version bundled typings that included 'postalCode' as an ElementType, so the TypeScript error did not occur.

Steps to reproduce See above.

Other information

danhadzami commented 4 years ago

I encountered the same issue and resolved it by installing stripe-js:

npm install @stripe/stripe-js --save

Then, try ng serve again

KeithGillette commented 4 years ago

Thanks, @danhadzami. I installed @stripe/stripe-js@1.8.0 simultaneous with the update to ngx-stripe@10.1.1 but get the TS2769 on StripeElements.create('postalCode', { … }) on ng serve unless I // @ts-ignore it. What version of @stripe/stripe-js are you using?

richnologies commented 4 years ago

Hi @KeithGillette, thanks for the report. Seems postalCode is actually not part of the @stripe/stripe-js. Can you provide me an snippet of code, (stackblizt will be awesome) on how you are using this. Maybe we can find a way to add it to the library.

Thanks

KeithGillette commented 4 years ago

Hi @richnologies. We are using Stripe Elements in a component with our own custom styling by mounting each Stripe Element on our own form control input. Here are the related component controller class properties and initialization:

    // …
    public paymentCardHolderName: FormControl = new FormControl(undefined, [Validators.required, Validators.pattern(RegExValidateName)]);
    public paymentCardNumber: FormControl = new FormControl(undefined, [Validators.required]);
    public paymentCardCVC: FormControl = new FormControl(undefined, [Validators.required]);
    public paymentCardExpiration: FormControl = new FormControl(undefined, [Validators.required]);
    public paymentCardPostalCode: FormControl = new FormControl(undefined, [Validators.required]);
    public paymentCardForm: FormGroup = new FormGroup({
        cardHolderName: this.paymentCardHolderName,
        paymentCardNumber: this.paymentCardNumber,
        paymentCardCVC: this.paymentCardCVC,
        paymentCardExpiration: this.paymentCardExpiration,
        paymentCardPostalCode: this.paymentCardPostalCode
    });
    public stripeElementsCardNumber: StripeCardNumberElement;
    public stripeElementsCardExpiration: StripeCardExpiryElement;
    public stripeElementsCardCVC: StripeCardCvcElement;
    public stripeElementsCardPostalCode: StripeCardElement; // Couldn't find a `StripeCardPostalCodeElement`

    private stripeElementsOptions: StripeElementsOptions = { 
        // …
    };
    private stripeElementsUiStyle: StripeElementStyle = {
        // …
    };

    constructor(private stripeClientService: StripeService {
        this.stripeClientService.setKey(environment.StripeKey);
    }

Then we create, mount, and attach event handlers to each stripeElementsCard*:

    this.stripeClientService.elements(this.stripeElementsOptions)
        .subscribe((elements: StripeElements) => {
            this.stripeElementsCardNumber = elements.create('cardNumber', { // works fine
                style: this.stripeElementsUiStyle,
                placeholder: 'Card Number'
            });
            this.stripeElementsCardNumber.mount(`#${this.stripeElementsCardNumberId}`);
            this.stripeElementsCardNumber
                .on('change', (changeEvent: StripeCardNumberElementChangeEvent) => {
                    // Do stuff
                })
                .on('blur', () => {
                    // Do stuff
                });

            // …

            this.stripeElementsCardPostalCode = elements.create('postalCode', { // TS2769 Error
                style: this.stripeElementsUiStyle,
                placeholder: 'Postal Code'
            });

            // …
        }
richnologies commented 4 years ago

Hello @KeithGillette, sorry for the delay. I've been looking for an easy way to add that, but now that we link the library to @stripe/stripe-js that is not easy. So my suggestion is for you to open an issue in their repository. https://github.com/stripe/stripe-js

Sorry about that.

R

KeithGillette commented 4 years ago

Thanks for looking into this, @richnologies. Following the suggestion in the @stripe/stripe-js issue template, I contacted Stripe support and learned that the reason the postalCode typing is missing from their typings is that Stripe has deprecated the postalCode element. I've excerpted relevant parts of the response from Stripe Support in case this helps anyone else:

Creating a postalCode element works in Stripe.js, but only for legacy reasons. The postal code element has been deprecated and is undocumented. Right now, the only available element types are:

'card', 'cardNumber', 'cardExpiry', 'cardCvc', 'fpxBank', 'iban', 'idealBank', 'paymentRequestButton', 'auBankAccount'

That being said, we currently recommend not using the postalCode element (even though it still technically works) and creating your own custom input for the postal code instead. You may reference our payments demo for an example implementation of that approach: