richnologies / ngx-stripe

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

confirmCardSetup returns 400 error, if separated elements are used #100

Closed oksanamuz closed 4 years ago

oksanamuz commented 4 years ago

I'm using not card component, but separated elements and on confirmCardSetup passing card element instead of the card, but unfortunately, Stripe returns an error as exp_month isn't presented in the request (btw CVV is not presented as well)... in previous version everything was fine and enough to pass just 1 element, I also used separated elements, but as elements components weren't implemented in prev version I rendered them by myself. Am I doing sth wrong?

 <div class="form__control form__control_lg">
        <b class="form_label-text">{{ pageKey + 'number' | translate }}</b>
        <ngx-stripe-card-number
          [options]="cardOptions"
          [elementsOptions]="elementsOptions"
          (change)="handleStripeErrors($event, getErrorName(CardElType.NUMBER))"
        ></ngx-stripe-card-number>
        <span *ngIf="cardNumberError" class="form__error" @fadeInOut>{{ cardNumberError }}</span>
      </div>
      <div class="form__control stripe-card__child">
        <b class="form_label-text">{{ pageKey + 'date' | translate }}</b>
        <ngx-stripe-card-expiry
          [options]="cardOptions"
          [elementsOptions]="elementsOptions"
          (change)="handleStripeErrors($event, getErrorName(CardElType.EXPIRY))"
        ></ngx-stripe-card-expiry>
        <span *ngIf="cardExpiryError" class="form__error" @fadeInOut>{{ cardExpiryError }}</span>
      </div>
      <div class="form__control stripe-card__child">
        <b class="form_label-text">{{ pageKey + 'cvv' | translate }}</b>
        <ngx-stripe-card-cvc
          [options]="cardOptions"
          [elementsOptions]="elementsOptions"
          (change)="handleStripeErrors($event, getErrorName(CardElType.CVC))"
        ></ngx-stripe-card-cvc>
        <span *ngIf="cardCvcError" class="form__error" @fadeInOut>{{ cardCvcError }}</span>
      </div>
@ViewChild(StripeCardNumberComponent) cardNumber: StripeCardNumberComponent;
....

this.paymentStripeService
      .getSetupIntent(this.form.value.default)
      .pipe(
        flatMap(response => {
          console.log(this.cardNumber.element);
          return this.stripeService.confirmCardSetup(
            response.client_secret,
            {
              payment_method: {
                card: this.cardNumber.element,
                ...this.getBillingDetails()
              },
            }
          );
        })
      )
.....

image image

oksanamuz commented 4 years ago

I did everything according to doc image

richnologies commented 4 years ago

Hello @oksanamuz, first of all, sorry for the inconvenience and thanks a lot for the detailed issue. Help us a lot finding the problem when you provide such a good information.

You're completely right. We miss that and the three elements were not sharing elements, that was the cause of the problem.

To solved this, a new version 10.1.0 has been released with a new Directive called ngxStripeCardGroup. Just place this in a parent element and it should work fine. Notice that the elementsOptions are now an input for the group, not the child elements. Here is a snippet of the solution.

<div
  ngxStripeCardGroup
  [formGroup]="stripeTest"
  [elementsOptions]="elementsOptions"
>
  <input formControlName="name" />
  <input formControlName="amount" />
  <ngx-stripe-card-number [options]="cardOptions"></ngx-stripe-card-number>
  <ngx-stripe-card-expiry [options]="cardOptions"></ngx-stripe-card-expiry>
  <ngx-stripe-card-cvc [options]="cardOptions"></ngx-stripe-card-cvc>
  <button type="submit" (click)="pay()">
    PAY
  </button>
</div>

There is also a component selector: ngx-stripe-card-group if you prefer that mode:

<ngx-stripe-card-group
  [formGroup]="stripeTest"
  [elementsOptions]="elementsOptions"
>
  <input formControlName="name" />
  <input formControlName="amount" />
  <ngx-stripe-card-number [options]="cardOptions"></ngx-stripe-card-number>
  <ngx-stripe-card-expiry [options]="cardOptions"></ngx-stripe-card-expiry>
  <ngx-stripe-card-cvc [options]="cardOptions"></ngx-stripe-card-cvc>
  <button type="submit" (click)="pay()">
    PAY
  </button>
</ngx-stripe-card-group>

Also, we have updated the docs to include this case and very likely will also be included in the FAQS sections in a couple of days: https://richnologies.gitbook.io/ngx-stripe/core-concepts/element-components#card-group-directive

We've only pushed this new version to the main branch. If you're using an older version, maybe it will take a few days.

Thanks again,

R

oksanamuz commented 4 years ago

Thanks a lot, @richnologies ! I'm glad that my explanation helped. Now it works perfectly! Thank you very much for so quick fix, you saved my deadline :)