簡體   English   中英

react-stripe-elements 錯誤:您必須提供條紋元素或有效的令牌類型才能創建令牌

[英]react-stripe-elements Error: You must provide a Stripe Element or a valid token type to create a Token

我正在使用 react-stripe-elements 創建一個用於支付的令牌。 但是,根據文檔,當卡片形式包含在 Elements 組件中時,它應該自動選擇要標記化的條紋元素。

但是,在這種情況下,我們會遇到錯誤

You must provide a Stripe Element or a valid token type to create a Token.

這是代碼:

import React from 'react';
import {CardCVCElement, CardExpiryElement, CardNumberElement, PostalCodeElement, StripeProvider, Elements} from 'react-stripe-elements';

class CheckoutForm extends React.Component {
  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleSubmit(ev) {
    ev.preventDefault();

    this.props.stripe.createToken({email: 'test@test.com'}).then(({token }) => {console.log('Received Stripe token:', token)});
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Card details
          <CardNumberElement />
          <CardExpiryElement />
          <CardCVCElement />
          <PostalCodeElement />
        </label>
        <button>Confirm order</button>
      </form>
    );
  }
}


class App extends React.Component {
  constructor() {
    super();
    this.state = { stripe: null };
  }

  componentDidMount() {
    this.setState({ stripe: window.Stripe('test_key') });
  }

  render() {
    return (
      <StripeProvider stripe={this.state.stripe}>
        <Elements>
          <CheckoutForm stripe={this.state.stripe} />
        </Elements>
      </StripeProvider>
    );
  }
}

export default App;

根據文檔,以下內容應該是正確的:

“在Elements的上下文中,對 createToken 的調用知道要標記哪個 Element,因為該組中只有一個。”

然而,情況似乎並非如此。 我也嘗試過使用單一的“卡片元素”,但沒有發現任何成功。

事實證明,我從未設法使用 react-stripe-element 解決這個問題。 我結束了使用標准 JS 版本(來自條帶文檔)。 這是我目前的工作解決方案:

import React from 'react';

class CheckoutForm extends React.Component {
  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);

    this.state = {
      elements: null,
      card: null
    };
  }

  componentWillReceiveProps() {
    this.setState({ elements: this.props.stripe.elements() }, () => {
      this.setState({ card: this.state.elements.create('card') }, () => {
        this.state.card.mount('#card-element');
      });
    });
  }

  handleSubmit(ev) {
    ev.preventDefault();
    this.props.stripe.createToken(this.state.card).then((token) => {
      console.log('Received Stripe token:', token);
    });
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <div className="row">
          <label >
            Credit or debit card
          </label>
          <div id="card-element"/>
          <div id="card-errors" role="alert"/>
        </div>
        <button>Submit Payment</button>
      </form>
    );
  }
}

class App extends React.Component {
  constructor() {
    super();
    this.state = {stripe: window.Stripe('test_key')};
  }

  render() {
    return (
      <CheckoutForm stripe={this.state.stripe}/>
    );
  }
}

export default App;

在評論中,他們正確地說您需要使用 HOC injectStripe

stripe.createToken文檔提到您需要傳遞要從中標記數據的元素。

同樣來自github repo README

⚠️ 注意 injectStripe 不能在渲染 Elements 組件的同一個元素上使用; 它必須用在 Elements 的子組件上。 injectStripe 返回一個包裝的組件,該組件需要位於您想要訪問 this.props.stripe 的任何代碼之下。

在我的特定情況下,我使用的是 Mobx 商店,我需要在同一個地方處理createToken和我的表單提交。 盡管自初始化以來我有對 stripe 的引用,但它不起作用。 createToken調用需要來自 Elements 的子組件並注入了條帶。

我最終擁有:

@inject('signupStore')
@observer
class CardInput extends React.Component {
componentDidMount() {
    const { signupStore } = this.props;
    const handleCard = async name => {
        return await this.props.stripe.createToken({ name: name });
    };
    signupStore.assignHandleCard(handleCard);
}

render() {
    return (
        <label>
            Card details
            <CardElement style={{ base: { fontSize: '18px' } }} />
        </label>
    );
 }
}

export default injectStripe(CardInput);

將處理程序傳遞回商店,然后從那里使用它。

signupStore

@action
async submitForm(formValues) {
    if (this.stripe && this.handleCard) {
        const tokenResponse = await this.handleCard(
            `${formValues.firstName} ${formValues.lastName}`
        );

        runInAction(() => {
            console.log('Card token received ', tokenResponse);
            if (tokenResponse) {
                this.cardToken = tokenResponse.token.id;
                formValues.cardToken = this.cardToken;
            }
        });

        const response = await request.signup.submit(formValues);

        return response;
    }
    return null;
}

反應它的工作對我來說卡組件JS,得到錯誤,卡明細,並生成令牌

import React, { useState, useEffect } from "react";
import {loadStripe} from '@stripe/stripe-js';
import {CardElement,Elements,useStripe,useElements} from '@stripe/react-stripe-js';
const stripePromise = loadStripe('pk_test_YOUR_STRIPE_KYE');
const CheckoutForm = () => {
const stripe = useStripe();
const elements = useElements();

const handleSubmit = async (event) => {
  event.preventDefault();
  const {error, paymentMethod} = await stripe.createPaymentMethod({
    type: 'card',
    card: elements.getElement(CardElement),
  });
    console.log("paymentMethod",paymentMethod);  
    console.log("error", error);
    if (paymentMethod) {
            const cardElement = elements.getElement(CardElement);
            let token  = await stripe.createToken(cardElement);
            console.log(token);
    }
};

return (
     
    <div>
    <form onSubmit={ handleSubmit }>
     <div className="login-box" id="step2"  >

              
             <div className="form-row">
                  <label for="card-element" style={ { color:" #76bbdf" } }>
                      Credit or debit card
                  </label>
              </div>
              
                  <div  >
                      <CardElement
                          className="StripeElement"
                            options={{
                                style: {
                                base: {
                                    fontSize: '16px',
                                    color: '#424770',
                                    '::placeholder': {
                                    color: '#aab7c4',
                                    },
                                },
                                invalid: {
                                    color: '#9e2146',
                                },
                                },
                            }}
                      />
                    </div>
                    <button name="submintbtn2" className="btn btn-primary"  > SUBSCRIBE </button>
                </div>
                </form>
    </div>
)};
const Registration = () => (
<div>
<Elements stripe={stripePromise}>
  <CheckoutForm />
    </Elements>
    </div>
); 
export default Registration;

使用新的@stripe/react-stripe-js庫,情況有點不同。 我們需要使用ElementsConsumer組件。 使用loadStripe方法加載條帶並使用Elements組件將您的表單與 Stripe 一起使用。

這是一個基本的例子。

import { Elements, loadStripe } from "@stripe/react-stripe-js"

const stripePromise = loadStripe(STRIPEKEY)

<Elements stripe={stripePromise}>
   <CardForm />
</Elements>

CardForm.js

import {
  CardNumberElement,
  CardExpiryElement,
  CardCvcElement,
  ElementsConsumer,
} from "@stripe/react-stripe-js"

const StripeForm = ({ stripe, elements }) => {

  const handleSubmit = async () => {
    if (!stripe || !elements) {
      return
    }
    const cardNumberElement = elements.getElement(CardNumberElement)
    const res = await stripe.createToken(cardNumberElement)
  }

  return (
      <form>
        <div>
          <label htmlFor="cardNumber">Card Number</label>
          <div>
            <CardNumberElement />
          </div>
        </div>
        <div>
          <label htmlFor="cardName">Card Name</label>
          <input
            type="text"
            name="cardName"
            required
            placeholder="Please Enter"
            pattern="[A-Za-z]"
          />
        </div>
        <div>
          <label htmlFor="expDate">Exp. Date</label>
          <div>
            <CardExpiryElement />
          </div>
        </div>
        <div>
          <label htmlFor="CVC">CVC</label>
          <div>
            <CardCvcElement />
          </div>
        </div>
      </form>
  )
}

const CardForm = () => {
  return (
    <ElementsConsumer>
      {({ stripe, elements }) => (
        <StripeForm stripe={stripe} elements={elements} />
      )}
    </ElementsConsumer>
  )
}

export default CardForm

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM