ngx-stripe icon indicating copy to clipboard operation
ngx-stripe copied to clipboard

Unable to use confirmSetup function with a group of components

Open robert197 opened this issue 2 years ago • 1 comments

I have the following scenario:

my template looks like this:

<ng-container *ngIf="elementsOptions?.clientSecret">
  <ngx-stripe-card-group [(elementsOptions)]="elementsOptions">
    <ion-card>
      <ion-card-header>
        <ion-label> Number: </ion-label>
      </ion-card-header>
      <ion-card-content>
        <ngx-stripe-card-number
          [options]="cardOptions"
        ></ngx-stripe-card-number>
        <ion-text color="danger" *ngIf="hasNumberError">
          <p class="error-message">{{ numberErrorMessage }}</p>
        </ion-text>
      </ion-card-content>
    </ion-card>

    <ion-card>
      <ion-card-header>
        <ion-label> Expiration date: </ion-label>
      </ion-card-header>
      <ion-card-content>
        <ngx-stripe-card-expiry
          [options]="cardOptions"
        ></ngx-stripe-card-expiry>
        <ion-text color="danger" *ngIf="hasExpiryError">
          <p class="error-message">{{ expiryErrorMessage }}</p>
        </ion-text>
      </ion-card-content>
    </ion-card>

    <ion-card>
      <ion-card-header>
        <ion-label> CVC: </ion-label>
      </ion-card-header>
      <ion-card-content>
        <ngx-stripe-card-cvc [options]="cardOptions"></ngx-stripe-card-cvc>
        <ion-text color="danger" *ngIf="hasCvcError">
          <p class="error-message">{{ cvcErrorMessage }}</p>
        </ion-text>
      </ion-card-content>
    </ion-card>
  </ngx-stripe-card-group>
</ng-container>

I am having the following viewChilds in order to make custom validation in the code.

  @ViewChild(StripeCardNumberComponent) number: StripeCardNumberComponent;
  @ViewChild(StripeCardExpiryComponent) expiry: StripeCardExpiryComponent;
  @ViewChild(StripeCardCvcComponent) cvc: StripeCardCvcComponent;

in the code I am creating first the following variables:

  public cardOptions: StripeCardExpiryElementOptions = {
    style: this.baseStyle,
  };

  public elementsOptions: StripeElementsOptions = {
    locale: 'de',
  };

and then I am getting the setupIntentClient secret which works fine:

async ngOnInit() {
    try {
      const cs = await this.paymentService.getSetupIntentClientSecret();
      this.elementsOptions.clientSecret = cs;
    } catch (_) {
      this.showInitCardFormError();
    }
  }

notice I am setting the clientSecret property on the elementsOptions object. This works fine and the property is set.

Then im trying to add a credit card:

private async addCreditCard() {
    this.isLoading = true;
    try {
      const { setupIntent, error } = await this.stripeService
        .confirmSetup({
          elements: this.number.elements,
          redirect: 'if_required',
        })
        .toPromise();
      console.log(setupIntent, error);
      if (error) {
        console.error(error);
        await this.showSubmitCardFormError();
      } else {
        console.log(setupIntent);
      }
    } catch (e) {
      console.error(e);
      await this.showSubmitCardFormError();
    } finally {
      this.isLoading = false;
    }
  }

If I log this.number.elements I can see that there are 3 elements registered insider the _elements property. which probably means that the 3 elements. Card, exiration data and CVC are mounted correctly.

The problem is! when i run this code of addCreditCard function. I am getting the following error!

IntegrationError: Invalid value for stripe.confirmSetup(): elements should have a mounted Payment Element. It looks like you have other Elements on the page. Refer to https://stripe.com/docs/js/setup_intents/payment_method to confirm a Setup Intent by payment method. at f (v3:1:79863) at m.betas (v3:1:80971) at h (v3:1:81504) at v3:1:295888 at e. (v3:1:296343) at e.confirmSetup (v3:1:124038) at b.project (main.js:1:1788269) at b._next (main.js:1:1435108) at b.next (main.js:1:1409689) at G._next (main.js:1:1424661)

When I use the same logic but instead of a group using the ngix-stipe-payment component. everything works fine.

robert197 avatar Jul 22 '22 15:07 robert197

Hi @robert197,

Thanks for raising this question.

You've done a great job and I can see how the docs can be a bit confusing. So, basically, the ConfirmPayment and ConfirmSetup can only be used with the new Payment Element this is way this statement is true:

When I use the same logic but instead of a group using the ngx-stripe-payment component. everything works fine.

If you want to use the credit card element, not matter if with a group or just in one element, you need to use this other methods, for Card Payments and Card Setups

Beside the method names, the main difference is that instead of passing the whole elements object, we just need to pass the card element. You can use this.number.element instead of this.number.elements in this case.

If have any more questions, please do not hesitate to ask, happy to help

Regards

R

richnologies avatar Jul 25 '22 09:07 richnologies

I'm closing this due to inactivity

richnologies avatar Feb 05 '23 23:02 richnologies