TS2304:找不到名称“条带”

时间:2019-08-18 23:28:16

标签: javascript angular typescript stripe-payments

我正在尝试创建一个Angular Stripe组件following this tutorial。它说要创建typings.d.ts(在目录directoy中创建),其内容如下:

declare var stripe: any;
declare var elements: any;

已完成,stripe中的脚本元素包含了index.html,但是在尝试编译时,我仍然收到以下消息:

    ERROR in src/app/stripe/stripe.component.ts:26:17 - error TS2552: Cannot find name 'elements'. Did you mean 'Element'?

    26     this.card = elements.create('card');
                    ~~~~~~~~

    node_modules/typescript/lib/lib.dom.d.ts:5063:13
        5063 declare var Element: {
                        ~~~~~~~
        'Element' is declared here.
    src/app/stripe/stripe.component.ts:47:36 - error TS2304: Cannot find name 'stripe'.

    47     const { token, error } = await stripe.createToken(this.card);

VSCode没有绘制任何红线。

有想法吗?

组件代码

    import {
      Component,
      AfterViewInit,
      OnDestroy,
      ViewChild,
      ElementRef,
      ChangeDetectorRef
    } from '@angular/core';

    import { NgForm } from '@angular/forms';
    @Component({
      selector: 'app-stripe',
      templateUrl: './stripe.component.html',
      styleUrls: ['./stripe.component.scss']
    })
    export class StripeComponent implements AfterViewInit, OnDestroy {
      @ViewChild('cardInfo', {static: true}) cardInfo: ElementRef;

      card: any;
      cardHandler = this.onChange.bind(this);
      error: string;

      constructor(private cd: ChangeDetectorRef) { }

      ngAfterViewInit() {
        this.card = elements.create('card');
        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.cd.detectChanges();
      }

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

        if (error) {
          console.log('Something is wrong:', error);
        } else {
          console.log('Success!', token);
          // ...send the token to the your backend to process the charge
        }
      }
    }

1 个答案:

答案 0 :(得分:2)

不太确定您使用的是哪个版本,但最近实现了最新的stripe元素。

加载条带脚本的服务

lazy val core = RootProject(file("../coreProject"))

val main = Project(id = "application", base = file(".")).dependsOn(core)

组件

import { Injectable } from '@angular/core';

interface Scripts {
  name: string;
  src: string;
}

declare var document: any;

@Injectable({ providedIn: 'root' })
export class DynamicScriptLoaderService {
  private scripts: any = {};

  constructor() {}

  loadScript(src: string) {
    return new Promise((resolve, reject) => {
      if (!this.scripts[src]) {
        this.scripts[src] = true;
        //load script
        let script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = src;
        if (script.readyState) {
          //IE
          script.onreadystatechange = () => {
            if (script.readyState === 'loaded' || script.readyState === 'complete') {
              script.onreadystatechange = null;
              resolve({ script: src, loaded: true, status: 'Loaded' });
            }
          };
        } else {
          //Others
          script.onload = () => {
            resolve({ script: name, loaded: true, status: 'Loaded' });
          };
        }
        script.onerror = (error: any) => resolve({ script: name, loaded: false, status: 'Loaded' });
        document.getElementsByTagName('head')[0].appendChild(script);
      } else {
        resolve({ script: name, loaded: true, status: 'Already Loaded' });
      }
    });
  }
}

模板

import { Component, OnInit, ChangeDetectionStrategy, Input, ViewChild, Inject, Output, EventEmitter } from '@angular/core';
import { UserService } from 'shared-components/lib/app-material/user.service';
import { PublicProductService } from '../../public-product.service';
import { DynamicScriptLoaderService } from 'shared-components/lib/app-material/script-loader';
import { BehaviorSubject } from 'rxjs';
import { FormControl, Validators } from '@angular/forms';
import { STRIPE_PUBLIC_KEY } from 'shared-components/lib/common';
declare var Stripe: any;
@Component({
  selector: 'flm-stripe',
  templateUrl: './stripe.component.html',
  styleUrls: ['./stripe.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class StripeComponent implements OnInit {
  @Input() order;
  stripe: any;
  card: any;
  sendingRequest$ = new BehaviorSubject(false);
  error$ = new BehaviorSubject(null);
  nameOnCardControl = new FormControl(null, Validators.required);
  @Output() complete = new EventEmitter();
  @ViewChild('cardNumber') cardNumber;
  @ViewChild('expiry') expiry;
  @ViewChild('cvc') cvc;
  constructor(
    private productService: PublicProductService,
    private scriptoader: DynamicScriptLoaderService,
    private userservice: UserService,
    @Inject(STRIPE_PUBLIC_KEY) private publicKey: string
  ) {
    super();
    this.nameOnCardControl.setValue(this.userservice.user.fullName);
  }

  ngOnInit() {
    this.scriptoader.loadScript('https://js.stripe.com/v3/').then(() => {
      this.stripe = Stripe(this.publicKey);
      var elements = this.stripe.elements();

      // Custom styling can be passed to options when creating an Element.
      // (Note that this demo uses a wider set of styles than the guide below.)
      var style = {
        base: {
          iconColor: '#666EE8',
          color: '#3eb5f1',
          lineHeight: '40px',
          fontWeight: 300,
          fontFamily: 'Roboto, "Helvetica Neue", sans-serif',
          fontSize: '16px',

          '::placeholder': {
            color: '#3eb5f1'
          }
        },
        invalid: {
          color: '#e4584c',
          iconColor: '#e4584c'
        }
      };

      // Create an instance of the card Element.
      this.card = elements.create('cardNumber', { style: style });
      // Add an instance of the card Element into the `card-element` <div>.
      this.card.mount(this.cardNumber.nativeElement);
      elements.create('cardExpiry', { style: style }).mount(this.expiry.nativeElement);
      elements.create('cardCvc', { style: style }).mount(this.cvc.nativeElement);
    });
  }
  pay(event) {
    if (event) {
      event.preventDefault();
    }
    this.sendingRequest$.next(true);
    /// REad this how to create intent https://stripe.com/docs/payments/payment-intents
    this.productService.getPaymentData(this.order.Id, 'Stripe').safeSubscribe(this, resp => {
      this.stripe
        .handleCardPayment(resp.Data, this.card, {
          payment_method_data: {
            billing_details: {
              name: this.nameOnCardControl.value
            }
          }
        })
        .then(result => {
          this.error$.next(null);
          this.sendingRequest$.next(false);
          if (result.error) {
            this.error$.next(result.error.message);
          } else {
            this.complete.next(true);
          }
        });
    });
  }
}

注意:我正在使用自己的safeSubscribe定制来取消对ngDestroy的订阅,请更改为订阅并自行管理退订。

typings.d.ts-也可以使用,但这取决于您的设置以及根文件夹对您的意义。