条纹元素与角2

时间:2017-05-14 18:40:15

标签: angular stripe-payments

我正在尝试将带有角度2的Stripe元素与接受信用卡信息的元素卡集成。请注意,我不打算使用条纹检查,因为有几个例子可以将条带与角度2进行整合。

declare var Stripe:any;

@Component({
  selector: 'app-account',
  templateUrl: './account.component.html',
  styleUrls: ['./account.component.scss']
})
export class AccountComponent implements OnInit {

  constructor(
    private _zone: NgZone
  ) { }

  private cardToken:any;

  ngOnInit() {

    if (typeof window !== 'undefined') {
      this.setUpCard();
    }
  }


  setUpCard() {
    var stripe = Stripe('TEST_API_KEY');
    var elements = stripe.elements();
    var style = {
      base: {
        fontSize: '16px',
        lineHeight: '24px'
      }
    };

    var card = elements.create('card', {style: style});

    card.mount('#card-element');
  }

  getCardData(number, month, year, cvc) {
      this.getCardToken(number, month, year, cvc);
  }

  getCardToken(number, month, year, cvc) {
    var dataObj = {"number": number, "exp_month": month, "exp_year": year, "cvc": cvc};

    Stripe.card.createToken(dataObj,
      (status, response) => { 

        this._zone.run(() => {
          if (status === 200) {
            this.cardToken = response;
            console.log("the card token: ", this.cardToken);
          }
          else {
            console.log("error in getting card data: ", response.error)
          }
        });
      }
    );
  }

HTML

<form role="form" id="payment-form">
  <div id="card-element">
    <!-- a Stripe Element will be inserted here. -->
  </div>
</form>

当我的组件加载时,我收到此错误:

  

您指定的选择器(#card-element)不适用于任何DOM元素   目前在页面上。确保元素存在于   调用mount()之前的页面。

如何访问角度2中的dom元素以使用Stripe正常工作?

另外,我在角度应用上使用服务器端渲染,如果这会影响角度在客户端的工作方式。

2 个答案:

答案 0 :(得分:7)

我希望您已经找到了解决问题的方法。但是,由于你的问题没有答案,我会尽力帮助。

您所犯的错误表明问题出在您调用setUpCard()的组件生命周期中。 您应该在AfterViewInit事件之后调用该方法,即在初始化组件视图时。 因此,您需要将您在ngOnInit()中使用的代码移动到ngAfterViewInit()钩子实现。

另请参阅https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#hooks-purpose-timing

答案 1 :(得分:0)

index.html

<script src="https://js.stripe.com/v3/"></script>

typings.d.ts

declare var Stripe: any;

StripeElementsComponent.ts

export class StripeElementsComponent implements AfterViewInit, OnDestroy { // import AfterViewInit, OnDestroy
    stripe: any;
    elements: any;
    card: any;
    apiKey = 'pk_test______________________'; //replace with your api key
    cardHandler = this.onChange.bind(this);
    error: string;
    @ViewChild('cardInfo') cardInfo: ElementRef; //import viewChild ElementRef

    constructor(private cdr: ChangeDetectorRef) {} //import ChangeDetectorRef

    ngAfterViewInit() {
        this.stripe = Stripe(this.apiKey);
        this.elements = this.stripe.elements();
        const style = { // input card style optional
            base: {
                fontSize: '16px',
                color: '#32325d',
            },
        };
        this.card = this.elements.create('card', {
            style
        });
        this.card.mount(this.cardInfo.nativeElement);
        this.card.addEventListener('change', this.cardHandler);
    }

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

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

    async onSubmitStripe(form: NgForm) { // import NgForm
        const {
            token,
            error
        } = await this.stripe.createToken(this.card);

        if (error) {
            console.log('Something is wrong:', error);
        } else {
            console.log('Success!', token); //response 
        }
    }
}

StripeElementsComponent.html

<form #checkout="ngForm" (ngSubmit)="onSubmitStripe(checkout)">
    <div class="form-row">
        <label for="card-element">Credit or debit card</label>
        <div id="card-element" #cardInfo></div>
        <div id="card-errors" role="alert" *ngIf="error">{{ error }</div>
    </div>
<button>Submit Payment</button>

StripeElementsComponent.css

.StripeElement {
  transition: box-shadow 150ms ease;
  border: solid 3px #e3e3e3;
  border-radius: 0.5em;
  padding: 1.143em 1em;
}

.StripeElement--focus {
  border-color: #85b7d9;
}

.StripeElement--invalid {
  border-color: #fa755a;
}

.StripeElement--webkit-autofill {
  background-color: #fefde5 !important;
}