React js Stripe checkout 不起作用



我正在尝试在 React js 应用程序中呈现条纹结帐默认表单。

<form action="/your-server-side-code" method="POST">
  <script
    src="https://checkout.stripe.com/checkout.js" className="stripe-button"
    data-key="pk_test_oDALA0jNyxDzbRz5RstV4qOr"
    data-amount="999"
    data-name="test"
    data-description="Widget"
    data-image="https://stripe.com/img/documentation/checkout/marketplace.png"
    data-locale="auto">
  </script>
</form>

它不显示任何内容,也不会出错。我如何获得付款按钮和表格。

您可能遇到的主要问题是在 React 中加载脚本。

一种方法是仅在需要时加载结帐脚本(假设某种形式的spa),然后直接调用它。这类似于文档页面上的"自定义"版本:https://stripe.com/docs/checkout#integration-custom

如果您已经在加载结帐.js例如在"app.js"之前),则可以通过不在脚本中手动加载来简化以下内容。

import React from 'react';
export default class Cards extends React.Component {
    constructor(props:Object) {
        super(props);
        this.state = {
            loading: true,
            stripeLoading: true,
        };
    }
    loadStripe(onload:Function) {
        if(! window.StripeCheckout) {
            const script = document.createElement('script');
            script.onload = function () {
                console.info("Stripe script loaded");
                onload();
            };
            script.src = 'https://checkout.stripe.com/checkout.js';
            document.head.appendChild(script);
        } else {
            onload();
        }
    }
    componentDidMount() {
        this.loadStripe(() => {
            this.stripehandler = window.StripeCheckout.configure({
                key: 'pk_test_xxxxxxxxxxxxxxxxxxxxxxxx',
                image: 'https://stripe.com/img/documentation/checkout/marketplace.png',
                locale: 'auto',
                token: (token) => {
                    this.setState({ loading: true });
                    axios.post('/your-server-side-code', {
                        stripeToken: token.id,
                    });
                }
            });
            this.setState({
                stripeLoading: false
            });
        });
    }
    componentWillUnmount() {
        if(this.stripehandler) {
            this.stripehandler.close();
        }
    }
    onStripeUpdate(e:Object) {
        this.stripehandler.open({
            name: 'test',
            description: 'widget',
            panelLabel: 'Update Credit Card',
            allowRememberMe: false,
        });
        e.preventDefault();
    }
    render() {
        const { stripeLoading, loading } = this.state;
        return (
            <div>
                {(loading || stripeLoading)
                    ? <p>loading..</p>
                    : <button onClick={this.onStripeUpdate}>Add CC</button>
                }
            </div>
        );
    }
}

Chris的回答非常好,但是我必须进行一些小的更改才能使代码正常运行。我还删除了TypeScript函数类型(对于我们这些不使用TypeScript的人)。在对答案进行更改的地方添加注释。仅供参考,这是我的第一篇文章,请让我知道这是否应该是评论而不是答案。

export default class Cards extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            loading: true,
            stripeLoading: true,
        };
        // onStripeUpdate must be bound or else clicking on button will produce error.
        this.onStripeUpdate = this.onStripeUpdate.bind(this);
        // binding loadStripe as a best practice, not doing so does not seem to cause error.
        this.loadStripe = this.loadStripe.bind(this);
    }
    loadStripe(onload) {
        if(! window.StripeCheckout) {
            const script = document.createElement('script');
            script.onload = function () {
                console.info("Stripe script loaded");
                onload();
            };
            script.src = 'https://checkout.stripe.com/checkout.js';
            document.head.appendChild(script);
        } else {
            onload();
        }
    }
    componentDidMount() {
        this.loadStripe(() => {
            this.stripeHandler = window.StripeCheckout.configure({
                key: 'pk_test_xxxxxxxxxxxxxxxxxxxxxxxx',
                image: 'https://stripe.com/img/documentation/checkout/marketplace.png',
                locale: 'auto',
                token: (token) => {
                    this.setState({ loading: true });
                    // use fetch or some other AJAX library here if you dont want to use axios
                    axios.post('/your-server-side-code', {
                        stripeToken: token.id,
                    });
                }
            });
            this.setState({
                stripeLoading: false,
                // loading needs to be explicitly set false so component will render in 'loaded' state.
                loading: false,
            });
        });
    }
    componentWillUnmount() {
        if(this.stripeHandler) {
            this.stripeHandler.close();
        }
    }
    onStripeUpdate(e) {
        this.stripeHandler.open({
            name: 'test',
            description: 'widget',
            panelLabel: 'Update Credit Card',
            allowRememberMe: false,
        });
        e.preventDefault();
    }
    render() {
        const { stripeLoading, loading } = this.state;
        return (
            <div>
                {(loading || stripeLoading)
                    ? <p>loading..</p>
                    : <button onClick={this.onStripeUpdate}>Add CC</button>
                }
            </div>
        );
    }
}

最新更新