Safari 浏览器中未加载条纹信用卡元素

问题描述

我们使用 stripe v.3 为客户添加信用卡。它适用于所有浏览器 chrome 和 firefox。但是 safari 返回以下错误

参考错误:找不到变量:元素

在物理 iphone 设备上测试,似乎旧版本无法创建离开输入字段的条纹元素,块状且不显示 CC 信息。检查屏幕截图。

错误发生在 iOS 11.3.1 及更低版本上。 iframe 显示在源元素中,但未将 .StripeElement 类添加到 dom。

screenshot

import {
  Component,Inject,ViewChild,ElementRef,AfterViewInit,OnDestroy,ChangeDetectorRef,} from '@angular/core';
import { NgForm } from '@angular/forms';
import { MatDialogRef,MAT_DIALOG_DATA } from '@angular/material/dialog';
import { ToastrService } from 'ngx-toastr';

import { PaymentService } from '@services/http/payment.service';
import { StateService } from '@services/Logic/state.service';

import { TranslatePipe } from '@app/pipes/translate.pipe';

@Component({
  selector: 'app-add-credit-card-dialog',templateUrl: 'addCreditCard.html',styleUrls: ['addCreditCard.scss','../../dialogs.scss'],})
export class AddCreditCardDialogComponent implements AfterViewInit,OnDestroy {
  @ViewChild('cardInfo',{ static: true }) cardInfo: ElementRef;
  card: any;
  cardHandler = this.onChange.bind(this);
  error: string;
  cardholderName: string;

  constructor(
    private cd: ChangeDetectorRef,private toastr: ToastrService,private translatePipe: TranslatePipe,private stateService: StateService,private paymentService: PaymentService,public dialogRef: MatDialogRef<AddCreditCardDialogComponent>,@Inject(MAT_DIALOG_DATA) public data: any
  ) {}

  ngAfterViewInit() {
    this.card = elements.create('card');
    this.card.mount(this.cardInfo.nativeElement);

    this.card.addEventListener('change',this.cardHandler);
    // Force the Element frame to paint once it is visible on the page
    setTimeout(() => {
      this.forceReflow('.StripeElement');
    },1000);

  }

  ngOnDestroy() {
    this.card.removeEventListener('change',this.cardHandler);
    this.card.destroy();
  }

  forceReflow(selector) {
    const el = document.querySelector(selector);

    if (el) {
      const initialdisplay = el.style.display;

      el.style.display = 'none';
      el.offsetHeight;
      el.style.display = initialdisplay;
    }
  }



  onChange({ error }) {
    if (error) {
      this.error = error.message;
    } else {
      this.error = null;
    }

    this.cd.detectChanges();
  }

  async onSubmit(form: NgForm) {
    if (!this.cardholderName || this.cardholderName.length === 0) {
      return this.toastr.error(this.translatePipe.transform('TOAST_MESSAGES.ERROR.MISSING_CARDHOLDER'));
    }

    this.stateService.toggleWaitingPage(true);

    // create a Setup Intent for this card
    const { setupIntent,error } = await stripe.handleCardSetup(
      this.data.client_secret,this.card,{
        payment_method_data: {
          billing_details: { name: this.cardholderName },},}
    );

    if (error) {
      this.toastr.error(error.message);
      this.stateService.toggleWaitingPage(false);
    } else {
      // create a Payment Method from the prevIoUsly created Setup Intent and attach it to the Customer
      const paymentMethod = await this.paymentService
        .attachPaymentMethod({ payment_method: setupIntent.payment_method })
        .toPromise();

      this.close(paymentMethod);
    }
  }

  close(data: any = null): void {
    this.dialogRef.close(data);
  }
}
form {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 95%;
  margin: auto;

  .form-row {
    width: 100%;
    margin: 0 0 20px;
    Box-shadow: 0 1px 4px 0 rgba(0,0.2);
    border-radius: 5px;
    padding: 10px;
    height: 40px;

    #card-errors {
      font-size: 12px;
      color: #f82e42;
    }
  }
}

p {
  color: #707070;
}
.input_area{
  width: 100%;
  text-align: center;
  padding-bottom: 115px;
}
.body_area{
  display: block;
  height: 100%;
  .attention{
    display: flex;
    margin: 20px 0px;
    height: 100%;
    padding: 5px 0px;
    background-color: #F6F9FC;
    .notranslate {
      color: #89b153;
      font-size: 18px;
      margin-left: 8px;
      padding-top: 2px;
      padding-right: 5px;
    }
    p{
      text-align: left !important;
      margin-bottom: 0px !important;
    }
    .notranslate{
      color: #707070;
      place-self: center;
    }
  }
}

.header_wrapper{
  display: block;
  height: 100%;
  .pinpay{
    margin-bottom: unset !important;
    font-weight: bold;
    font-size: 17px;
    color: #4a4a56;
  }
  .img {
    height: 80px;
    width: 80px;
    margin-top: 10px;
    margin: auto;
    background-position: center;
    background-repeat: no-repeat;
    background-size: cover;
    Box-shadow: 0 3px 6px 0 rgba(0,0.16);
    border-radius: 500px;
    @media (max-width: 320px) and (max-height: 438px) { display: none; }
    .image-icon{
      height: 60px;
      width: 60px;
      margin-top: 3px;
      margin-left: 8.4px;
    }
  }
}

#cardholder-name {
  width: 95%;
  margin-bottom: 20px;
  Box-shadow: 0 1px 4px 0 rgba(0,0.2);
  background: transparent;
  border: none;
}
<div class="dialog_container">
  <div class="header_row">
    <div class="header_left"></div>
    <span class="close" (click)="close()">✕</span>
    <h5 id="header_title">{{ 'DIALOGS.ADD_CREDIT_CARD.TITLE' | translate }}</h5>
  </div>


  <div class="header_wrapper">
    <div class="img">
   
    </div>
    <div style="display: flex; margin-bottom: unset">
      <p class="pinpay">PinployPay</p>
      <span></span>™
    </div>
    <p class="pinpay1">Sikker handel</p>
 </div>
  <div class="body_area">
    <div class="attention">
      <mat-icon [matTooltip]="'PAGES.SETTINGS.PROFILE.COMPLETION_RATE_INFO' | translate">info</mat-icon>
      <p>{{ 'DIALOGS.ADD_CREDIT_CARD.MESSAGE' | translate }}</p>
    </div>

    <p>
      <mat-icon class="notranslate">remove_shopping_cart</mat-icon>{{
      'DIALOGS.ADD_CREDIT_CARD.MESSAGE_1' | translate }}
    </p>
  </div>

  <div class="input_area">
    <input
      id="cardholder-name"
      [(ngModel)]="cardholderName"
      [placeholder]="'DIALOGS.ADD_CREDIT_CARD.CARDHOLDER' | translate"
    />

    <form #checkout="ngForm" (ngSubmit)="onSubmit(checkout)" class="checkout">
      <div class="form-row">
        <div id="card-info" #cardInfo></div>
        <div id="card-errors" role="alert" *ngIf="error">{{ error }}</div>
      </div>

      <button type="submit" class="pinploy_button_v2_mobile_green">Ok</button>
    </form>
  </div>
</div>

index.html

<body>
    <app-root></app-root>

    <script src="https://js.stripe.com/v3/"></script>
    <script>
      const stripeKey =
        window.location.origin === "https://www.pinploy.com"
          ? "pk_live_******q"
          : "pk_test_1P******";
      let stripe = Stripe(stripeKey);
      let elements = stripe.elements();
    </script>
  </body>
</html>

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)