2017-01-06 32 views
8

Próbuję renderować domyślny formularz kasowania paska w aplikacji React js.Reakcja js Stripe Checkout nie działa

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

Nie wyświetla niczego i nie otrzymuje również błędu. Jak uzyskać przycisk i formularz płatności.

+1

Wykorzystanie 'react' obsługiwanych wtyczek jak https://www.npmjs.com/package/react-stripe-checkout –

Odpowiedz

7

Głównym problemem, który prawdopodobnie masz, jest ładowanie skryptu w React.

Jednym ze sposobów jest załadowanie skryptu kasowania tylko wtedy, gdy jest to potrzebne (zakładając, że jest jakaś forma spa), a następnie po prostu wywołaj go bezpośrednio. Jest to podobne do "niestandardowej" wersji na stronie dokumentacji: https://stripe.com/docs/checkout#integration-custom

Jeśli już ładujesz plik checkout.js (na przykład przed swoim "app.js"), to poniżej można nieco uprościć, nie ręcznie ładowanie w skrypcie.

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

Odpowiedź Chrisa była doskonała, jednak musiałem wprowadzić kilka drobnych zmian, aby kod mógł funkcjonować. Usunąłem także typy funkcji TypeScript (dla tych z nas, którzy nie używają TypeScript). Komentarze są dodawane w miejscach, w których wprowadzono zmiany w odpowiedzi. FYI to mój pierwszy post, proszę dać mi znać, czy to powinien być komentarz zamiast odpowiedzi.

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

To jest dokładnie to, co potrzebne! wielkie dzięki. Przy okazji, powinieneś potwierdzić odpowiedź, aby post rozwiązać – ekqnp

+0

dzięki za podzielenie się tym! –