【问题标题】:react-stripe-elements Error: You must provide a Stripe Element or a valid token type to create a Tokenreact-stripe-elements 错误:您必须提供 Stripe 元素或有效的令牌类型才能创建令牌
【发布时间】:2018-07-09 05:33:08
【问题描述】:

我正在使用 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 的调用知道要标记哪个元素,因为这个组中只有一个。'

但是,情况似乎并非如此。我也尝试过使用单一的“卡片元素”,但没有发现任何成功。

【问题讨论】:

  • 结尾处缺少'this.props.stripe.createToken({email: 'test@test.com
  • 谢谢 - 更新(同样的错误)
  • 对 react-stripe 不太了解,但似乎您需要使用 HOC injectStripe(CheckoutForm) 而不是直接在 ChekoutForm props 中传递 stripe
  • 在这种情况下,我已经通过 props 手动传递了条带对象,我认为结果是相同的(条带已加载,并且在控制台中打印时存在功能。
  • 当我使用 injectStripe 方法时,它对我来说很好。我尝试做与您类似的事情,因为我正在使用 Redux,但我无法让它工作。我回到只在任何connect() 调用下方的组件中使用条带,但使用自述文件github.com/stripe/react-stripe-elements#getting-started 中的主要方法。

标签: javascript reactjs stripe.js stripe-payments


【解决方案1】:

事实证明,我从来没有设法使用 react-stripe-elements 解决这个问题。我结束了使用标准 JS 版本(来自 stripe 文档)。这是我目前的工作解决方案:

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;

【讨论】:

  • @Sachin_Karia 您能否分享一下您是如何设法从输入中获取卡值,然后使用信息进行支付的。
【解决方案2】:

在 cmets 中,他们正确地说您需要使用 HOC injectStripe

stripe.createTokendocs 提到您需要传递要从中标记数据的元素。

同样来自github repo README

⚠️ 注意 injectStripe 不能用在渲染 Elements 组件的同一元素上;它必须用于 Elements 的子组件。 injectStripe 返回一个包装的组件,该组件需要位于您想要访问 this.props.stripe 的任何代码之下但之上。

在我的特定情况下,我使用的是 Mobx 商店,我需要在同一个地方处理 createToken 和我的表单提交。 即使我在初始化后引用了条带,它也不起作用。 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;
}

【讨论】:

【解决方案3】:

React 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;

【讨论】:

    【解决方案4】:

    使用新的 @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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-02-03
      • 2020-04-03
      • 2017-09-28
      • 2016-08-21
      • 2019-01-12
      • 2019-03-31
      • 2020-12-06
      • 1970-01-01
      相关资源
      最近更新 更多