简体   繁体   English

TS2304:找不到名称“条带”

[英]TS2304: Cannot find name 'stripe'

I'm attempting to create an Angular Stripe component following this tutorial . 我正在尝试按照本教程创建Angular Stripe组件。 It says to create typings.d.ts (Created it in the root directoy) with the content: 它说要创建具有内容的typings.d.ts (在目录typings.d.ts创建):

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

SO that's done, and stripe is included via script element in index.html , however when attempting to compile I still get these message: 这样就完成了,并且通过index.html script元素包含了stripe ,但是当尝试编译时,我仍然收到以下消息:

    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 is not painting any red lines. VSCode没有绘制任何红线。

Thoughts? 有什么想法吗?

Component Code 组件代码

    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
        }
      }
    }

Well not sure which version you are using but recently implemented latest stripe elements.. 不太确定您使用的是哪个版本,但最近实现了最新的stripe元素。

Service to load stripe script 服务加载条带脚本

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' });
      }
    });
  }
}

Component 零件

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);
          }
        });
    });
  }
}

Template 模板

<form (ngSubmit)="pay($event)" method="post" id="payment-form">
  <div class="group">
    <label>
      <span>{{ 'Order_NameOnCard' | translate }}</span>
      <div class="field">
        <input class="field" placeholder="{{ 'Order_NameOnCard' | translate }}" [formControl]="nameOnCardControl" />
      </div>
    </label>
    <label>
      <span>Card number</span>
      <div #cardNumber class="field"></div>
      <span class="brand"><i class="pf pf-credit-card" id="brand-icon"></i></span>
    </label>
    <label>
      <span>Expiry date</span>
      <div #expiry class="field"></div>
    </label>
    <label>
      <span>CVC</span>
      <div #cvc class="field"></div>
    </label>
  </div>

  <!-- Used to display form errors. -->
  <div role="alert" class="error visible ">
    <ng-container *ngIf="error$ | async">{{ error$ | async }}</ng-container>
  </div>

  <flm-button-progress
    class="w100p"
    [inProgress]="sendingRequest$ | async"
    analyticsOn="click"
    analyticsCategory="Payment"
    analyticsEvent="Stripe"
  >
    {{ 'Order_Pay' | translate }}
    <i class="fa fa-arrow-right"></i>
  </flm-button-progress>
</form>

NOTE: I am using my own safeSubscribe customization to unsubscribe on ngDestroy, please change it to subscribe and manage unsubscribe yourself. 注意:我正在使用自己的safeSubscribe自定义项来取消订阅ngDestroy,请更改它以进行订阅并自行管理取消订阅。

typings.d.ts - should also work but it depends on your setup and what root folder means for you. types.d.ts-也应该起作用,但这取决于您的设置以及根文件夹对您而言意味着什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM