我正在尝试将带有角度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正常工作?
另外,我在角度应用上使用服务器端渲染,如果这会影响角度在客户端的工作方式。
答案 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;
}