Giter Club home page Giter Club logo

react-stripe-checkout's Introduction

npm version Dependencies Status Gitter

React Stripe Checkout Component

Stripe's Checkout makes it almost too easy to take people's money. This should make it even easier if you're building a react application.

Installation

Get started by installing with npm

npm install react-stripe-checkout

Requires babel for compiling. If anyone is having issues with that, open an issue and I'll do my best to better document the build process.

Changes in version 2.0

There used to be a separate .styl file and respective .css output. These have been removed and are now written directly in js.

Requirements

token and stripeKey are the only required props, everything else is optional as per the stripe docs. See Checkout Docs. All props go through simple validation and are passed to stripe checkout, they're also documented in StripeCheckout.js.

import React from 'react'
import StripeCheckout from 'react-stripe-checkout';

export default class TakeMoney extends React.Component {
  onToken = (token) => {
    fetch('/save-stripe-token', {
      method: 'POST',
      body: JSON.stringify(token),
    }).then(response => {
      response.json().then(data => {
        alert(`We are in business, ${data.email}`);
      });
    });
  }

  // ...

  render() {
    return (
      // ...
      <StripeCheckout
        token={this.onToken}
        stripeKey="my_PUBLISHABLE_stripekey"
      />
    )
  }
}

This will give you a default Stripe-style button which looks like this:

stripe checkout button

Send all the props!

<StripeCheckout
  name="Three Comma Co." // the pop-in header title
  description="Big Data Stuff" // the pop-in header subtitle
  image="https://stripe.com/img/documentation/checkout/marketplace.png" // the pop-in header image (default none)
  ComponentClass="div"
  label="Buy the Thing" // text inside the Stripe button
  panelLabel="Give Money" // prepended to the amount in the bottom pay button
  amount={1000000} // cents
  currency="USD"
  stripeKey="..."
  locale="zh"
  email="[email protected]"
  // Note: Enabling either address option will give the user the ability to
  // fill out both. Addresses are sent as a second parameter in the token callback.
  shippingAddress
  billingAddress={false}
  // Note: enabling both zipCode checks and billing or shipping address will
  // cause zipCheck to be pulled from billing address (set to shipping if none provided).
  zipCode={false}
  alipay // accept Alipay (default false)
  bitcoin // accept Bitcoins (default false)
  allowRememberMe // "Remember Me" option (default true)
  token={this.onToken} // submit callback
  opened={this.onOpened} // called when the checkout popin is opened (no IE6/7)
  closed={this.onClosed} // called when the checkout popin is closed (no IE6/7)
  // Note: `reconfigureOnUpdate` should be set to true IFF, for some reason
  // you are using multiple stripe keys
  reconfigureOnUpdate={false}
  // Note: you can change the event to `onTouchTap`, `onClick`, `onTouchStart`
  // useful if you're using React-Tap-Event-Plugin
  triggerEvent="onTouchTap"
  >
  <button className="btn btn-primary">
    Use your own child component, which gets wrapped in whatever
    component you pass into as "ComponentClass" (defaults to span)
  </button>
</StripeCheckout>

Other info

This was probably terribly written, I'll look at any PR coming my way.

Resources

Contributors

  • @orhan-swe added updates to checkout after instantiation and fixed a loading error
  • @ekalvi added multiple checkout buttons per page
  • @jstaffans adding support for locale
  • @gabestein added billing and shipping options
  • @samcorcos added testing

react-stripe-checkout's People

Contributors

antoinerousseau avatar azmenak avatar bikegriffith avatar byte255 avatar chabou avatar curran avatar dav-ell avatar gabestein avatar harisibrahimkv avatar hozefaj avatar ihsane avatar jbboehr avatar jstaffans avatar kosai106 avatar mavarazy avatar michaellyons avatar minheq avatar mscoutermarsh avatar orhan-swe avatar pdeva avatar piuccio avatar rwieruch avatar samcorcos avatar tmoc avatar tpredale avatar warlo avatar waynebrantley avatar wcandillon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-stripe-checkout's Issues

"Type mismatch for option" warnings from Stripe

getConfig() returned all possible configuration options even ones that were not defined as component's properties. As a result, Stripe displayed warnings in the console about config options being undefined instead of type string, boolean, etc.

This is how it looks like in Chrome console:

image

Proposed PR #37 that fixes the issue.

Response from Stripe is not the same as documented

When I get a response from the token function, it doesn't match the response i expect to get back from Stripe according to these docs https://stripe.com/docs/checkout#integration-simple-parameters

But instead I get back something like this

{ id: 'tok_xxxxxxxxxxxxxxxx',
  object: 'token',
  card:
   { id: 'card_xxxxxxxxxxxxxxx',
     object: 'card',
     address_city: 'bill',
     address_country: 'United Kingdom',
     address_line1: 'bill',
     address_line1_check: 'pass',
     address_line2: null,
     address_state: null,
     address_zip: 'lfdkjg',
     address_zip_check: 'pass',
     brand: 'Visa',
     country: 'US',
     cvc_check: 'pass',
     dynamic_last4: null,
     exp_month: 12,
     exp_year: 2019,
     funding: 'credit',
     last4: '4242',
     metadata: {},
     name: 'Sam bill',
     tokenization_method: null },
  client_ip: '81.174.166.202',
  created: 1485639432,
  email: '[email protected]',
  livemode: false,
  type: 'card',
  used: false
 }

Do you know why this might be?

panelLabel override for working with coupons?

When using a pre-validated coupon, it does not make sense to show the price in the panel. It should just say "Pay" or something like that, since the price is dependent on whether the coupon is valid.

    // The label of the payment button in the Checkout form (e.g. “Subscribe”,
    // “Pay {{amount}}”, etc.). If you include {{amount}}, it will be replaced
    // by the provided amount. Otherwise, the amount will be appended to the
    // end of your label.
    panelLabel: React.PropTypes.string,

Is there already a way to override the appending of the amount? Or is this a PR?

LICENSE.md?

Would be great to have a license, perhaps MIT, so others can freely use/derive from this lib.

Generally speaking, the absence of a license means that the default copyright laws apply. This means that you retain all rights to your source code and that nobody else may reproduce, distribute, or create derivative works from your work.

https://help.github.com/articles/open-source-licensing/

Warning when used in isomorphic app

Very much doubt anything can be done about this but I thought I'd point it out anyway.

warning.js:45 Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
 (client) <div name="My Name" c
 (server) <div label="Pay With Card

auto open with opened property

Hi,

I have use case were I need to open the stripe form after the component mounts. It would be nice to pass in a property that does this for me vs my hacky way.

Is there a current method to do this? I couldn't see one in the code.

Calling setState() from token callback?

I'm getting the following React error when trying to call this.setState() from the token callback:

Warning: setState(...): Can only update a mounted or mounting component. This usually means you called setState() on an unmounted component. This is a no-op. Please check the code for the ReactStripeCheckout component.

I don't understand why.. I'm trying to set a variable indicating that the payment request has been sent to the backend, in order to display a loading indicator. Is there a better way to do that?

Babel compile issue

Hi,

When trying to compile the component using xcode I keep running into this issue with babel:

TransformError: /path/to/project/react-stripe-checkout/dist/main.js: Couldn't find preset 'es2015' relative to directory /path/to/project/node_modules/react-stripe-checkout

Your help would be appreciated!

support for disabling click

Sometimes when filling forms, you'd want to disable hitting the "submit" button until form is complete.

Since react-stripe-checkout wraps the button element (or any other element) and adds a click handler, it's hard to disable it.

I propose to add a new attribute disabled that, when true, will just disable the click handler.

Please let me know what you think, i'll be happy to send a PR

🍪

Animation overview

Struggling to understand the utility of this component.

What happens when a charge is made. What does the button look like for example?

Implementation Issues

I am really loving the checkout component but I am finding myself completely stuck at getting the AJAX submission to work. My submissions using ajax (using the syntax you use in your example) result in a 402 error on stripes end claiming no card data was sent.

Keep in mind that the ajax request is being posted to a php file that is already tested at handling charges normally when the checkout form is just submitted sans ajax. The php used is exactly the same php stripe provides in their samples in their documentation.

`<?php
require_once('./config.php');

$token = $_POST['stripeToken'];

$customer = \Stripe\Customer::create(array(
'email' => '[email protected]',
'source' => $token
));

$charge = \Stripe\Charge::create(array(
'customer' => $customer->id,
'amount' => 5000,
'currency' => 'usd'
));

?>`

So basically I am wondering if you have had any experience implementing this with php as the processing for charges and what did you have to do to implement it with ajax. I seem to be a bit out of my depth as to figuring out whats wrong.

Free plan without credit card

Hi,

Is there any way to use the checkout component to subscribe to free plans without giving the credit card information?

Best regards
John

Prefill billing address

If I know customer data beforehand, can I prefill the billing address in StripeCheckout form?

Error after clicking Pay button

Nice work guys, im thankful to everyone of you. But i got this error:

main.js:208 Uncaught ReferenceError: StripeCheckout is not defined

ReferenceError: StripeCheckout is not defined

The component seems to work fine, but for some reason that I just can't figure out, I always need to press button twice. The first time, it opens a new tab and shows an error message saying that there was an error and that I should try another browser if the problem persists. On subsequent clicks, it opens a new tab and correctly shows the stripe form.

autorun

so i've created a form where all the input fields must be filled before the stripe button can trigger (to show the stripe checkout form). However, if any of the fields of the first form have or have not value, the stripe button still triggers on click immediately after showing the "this field must be filled" dialogue.

I've fixed this by adding two lines of code (which caters to my needs). Here's the resulting code:

onClick: function() {
    _**if (this.props.info.pictureAmount && this.props.info.phone && this.props.info.topic) {**_
      if (ReactStripeCheckout.scriptDidError) {
        console.log('failed to load script');
      } else if (ReactStripeCheckout.stripeHandler) {
        this.showStripeDialog();
      } else {
        this.showLoadingDialog();
        this.hasPendingClick = true;
      }
    _**}**_
  },

Missing class properties transform Error

I'm getting:

While processing files with ecmascript (for target web.browser):
credits/client/credits.js:34:2: /credits/client/credits.js: Missing class properties
transform.

Line 34 is:
onToken = (token) => {

My Stripe Checkout line is:

I'm still fairly new to React so apologies if this is a very basic error.

Any ideas where I'm going wrong?

POST to load to new page after submission

Is it possible to POST the callback to a destination within the app after submission. Specifically, I want to send the user to a Thank You page after submission.
screen shot 2017-02-14 at 10 05 19 pm
screen shot 2017-02-14 at 10 06 03 pm

Promise is not a constructor

I am all of a sudden getting an error that says: Promise is not a constructor. I had the code working before, but I'm not sure what I changed that broke it.

Here is my component:

export default class CourseEnrollButton extends React.Component {
  constructor(props) {
    super(props);
    this.onToken = this.onToken.bind(this);
  }
  onToken(token) {
    console.log(token)
  }
  render() {
    const { collection } = this.props;
    const price = collection.price ? parseInt(collection.price / 100, 10) : 0;
    const key = Meteor.settings.public.STRIPE_PUBLISHABLE_KEY;
    const user = Meteor.user();
    let enrolled = false;
    if (user) {
      if (_.contains(user.isEnrolled)) {
        enrolled = true;
      }
    }
    if (enrolled) return <div></div>;
    return (
      <StripeCheckout
        name="My Site"
        description={collection.title}
        image={collection.cover}
        amount={collection.price}
        currency="USD"
        stripeKey={key}
        zipcode
        allowRememberMe
        token={this.onToken}
      >
        <div className="enroll-button">
          Enroll -&nbsp;
          <span className="enroll-cost">${price}</span>
        </div>
      </StripeCheckout>
    );
  }
}

The trace is:


TypeError: Promise is not a constructor
    at main.js:152
    at ReactStripeCheckout.componentDidMount (main.js:181)
    at ReactCompositeComponentWrapper.invokeComponentDidMountWithTimer (ReactCompositeComponent.js:60)
    at CallbackQueue.notifyAll (CallbackQueue.js:67)
    at ReactReconcileTransaction.close (ReactReconcileTransaction.js:81)
    at ReactReconcileTransaction.closeAll (Transaction.js:204)
    at ReactReconcileTransaction.perform (Transaction.js:151)
    at ReactUpdatesFlushTransaction.perform (Transaction.js:138)
    at ReactUpdatesFlushTransaction.perform (ReactUpdates.js:90)
    at Object.flushBatchedUpdates (ReactUpdates.js:173)

I am using Meteor if that makes a difference. Any help or ideas would be much appreciated. Thanks!

StripeCheckout.configure is called several times

Every time the the component is updated StripeCheckout.configure is called resulting in a new bootstrap request and a new iframe inserted on the page.
There should might be a check that a prop concerning stripe is changed before calling updateStripeHandler?

How to make email editable once passed as prop

Probably a trivial question.

render: function() {
// ...
 <input type="text" 
 className="form-control" 
 placeholder="Enter your email"  
 onChange={this.setEmail}/>

<ReactStripeCheckout currency="GBP" 
amount={100}
token={this.pay} 
stripeKey="mykey" 
email={this.state.email} />
//...
}

This opens up a stripe modal window, and the email is set. But it's not editable. I was wondering if there was a way to edit the email once it's set in the stripe modal window?

onToken issue in example

In the following code:

onToken = (token) => {
    fetch('/save-stripe-token', {
      method: 'POST',
      body: JSON.stringify(token),
    }).then(response => {
      response.json().then(data => {
        alert(`We are in business, ${data.email}`);
      });
    });
  }

I'm not sure if response.json().then is really necessary? It doesn't seem like response is a promise. I'm getting an error when I do this, and on the other hand console.log(response) seems to work fine?

No Errors in the Console but no transactions take place

Update: I realized my initial question is flawed as I haven't put in any code to then initiate the actual charge. Is it even possible to handle that when using firebase on the backend? From my initial searching I would say no without the help of a connecting service (which I would rather not use).

My apologies up front if I am just not understanding a crucial step but basically I have the component added, reference it as is described in the readme, everything seems to load well and process correctly at first and I even get a response token in my database. And yet... When I login to my stripe dashboard I see no transactions occurring and the other corresponding actions (like receipt emails) never take place.

I am getting no errors in the console so I am feeling a bit stuck on what I am doing wrong. Am I supposed to be sending something to stripe in my onToken function?

My only guess at this point is maybe I am not loading stripe itself separately correctly. I have <script src="https://js.stripe.com/v2/"></script> in the head of my index.html but if I add any references to the normal stripe functions in my component it claims they are not defined. How do I tell react about the externally loaded stripe.js? (thats ofcourse assuming thats my issue)

Below I have included the component that I have written to handle showing an invoice and incorporating checkout.

Any help or direction would be greatly appreciated. Thanks!

import React from 'react';
import base from '../../base';
import {formatPrice, formatDate} from '../helpers/Helpers';
import StripeCheckout from 'react-stripe-checkout';

class InvoiceRead extends React.Component {

constructor() {
super();

this.changeColor = this.changeColor.bind(this);
this.onToken = this.onToken.bind(this);


this.state = {
    currentInvoice: {}
}

}

componentDidMount() {
this.changeColor("invoice");
}

changeColor(color) {
this.props.addHeaderColor(color);
}

onToken(token) {
base.database().ref(invoices/invoice-${this.props.params.invoiceId}).update({
stripetoken: token,
status: "Paid"
});
}

componentWillMount() {
this.invoicedata = base.syncState(invoices/invoice-${this.props.params.invoiceId}, {
context: this,
state: 'currentInvoice'
});
}

componentWillUnmount() {
base.removeBinding(this.invoicedata);

}

render() {

return (
    
        <div className="maxWidth invoiceRead">
        
            <h1>Invoice</h1>
            <h2>{this.state.currentInvoice.posttitle}</h2>
            
            

           
            <div>Date Created: {formatDate(this.state.currentInvoice.date)}</div>
            <div>Recpient: {this.state.currentInvoice.assignedtoname}</div>
            <div>Total Amount Due: {formatPrice(this.state.currentInvoice.amount)}</div>

            <div>{this.state.currentInvoice.content}</div>

            <StripeCheckout
                name="Heroic Pixel"
                description={this.state.currentInvoice.content}
                image="https://react.heroicpixel.com/android-chrome-512x512.png"
                token={this.onToken}
                amount={10000}
                stripeKey="pk_test_Mvj9otmgnHw1pORHusbxtqdu"
            />

        
        </div>
    
)

}
}

export default InvoiceRead;

Typescript Error

Error:

error TS2605: JSX element type 'StripeCheckout' is not a constructor function for JSX elements.
  Types of property 'setState' are incompatible.
    Type '{ <K extends never>(f: (prevState: void, props: StripeCheckoutProps) => Pick<void, K>, callback?:...' is not assignable to type '{ <K extends never>(f: (prevState: {}, props: any) => Pick<{}, K>, callback?: () => any): void; <...'.
      Types of parameters 'f' and 'f' are incompatible.
        Type '(prevState: {}, props: any) => Pick<{}, any>' is not assignable to type '(prevState: void, props: StripeCheckoutProps) => Pick<void, any>'.
          Types of parameters 'prevState' and 'prevState' are incompatible.
            Type 'void' is not assignable to type '{}'.

Use:

<StripeCheckout
    name="name"
    description="description"
    image="/picture.jpg"
    ComponentClass="div"
    stripeKey="pk_test_..."
    token={token => console.log("Token received!")}
>
    <RaisedButton label="Pay for Somethin'" primary />
</StripeCheckout>

Solution:
In index.d.ts, change

export default class StripeCheckout extends React.Component<StripeCheckoutProps, void> {}

to

export default class StripeCheckout extends React.Component<StripeCheckoutProps, {}> {}

or

export default class StripeCheckout extends React.Component<StripeCheckoutProps, Object> {}

I've fixed the same problem in material-ui-number-input and will be submitting a PR momentarily.

Do not call onClosed if component is not mounted

If the closing of the component changes state in such a way that the checkout component is not shown, you will get the error below.

Warning: setState(...): Can only update a mounted or mounting component. 
This usually means you called setState() on an unmounted component. 
This is a no-op. Please check the code for the ReactStripeCheckout component.

This is because the checkout.js calls the onClosed

	  if (this..isMounted)
		this.setState({ open: false });

and set isMounted = false in componentWillUnmount solves it.

@azmenak Is there any chance you can look at this and also the other open pull requests. What you have done here is effect, just needs a few tweaks?

Email override option?

Is there a way to provide an email, but allow the user to override it during checkout?

Shipping address not coming back

The billing adress returns, but the shipping address does not... I think I have it configured right?
v ^1.8.0

 <ReactStripeCheckout
                stripeKey='bobloblaw'
                token={this.onToken}

                name="Foo Inc."
                componentClass="div"
                panelLabel = "Purchase a Gadget"
                amount={100}
                currency="USD"
                shippingAddress={true}
                allowRememberMe={true}
                />

CORS issue

Starting Sunday I started getting a CORS load error with stripe's checkout.js (via this module), no code changes on my end, so it seems like Stripe "flipped a switch"

any ideas on why this is occuring, or how to resolve it?

I am working on a root-cause analysis right now, will add details when I figure it out.

React 15.2.1 throws unknown prop warning when using ...props

warning.js:44Warning: Unknown props `token`, `email`, `currency`, `description`, `panelLabel`, `image`, `allowRememberMe`, `stripeKey`, `locale`, `componentClass` on <span> tag. Remove these props from the element. For details, see https://fb.me/react-unknown-prop
    in span (created by ReactStripeCheckout)

The error is documented here.

The issue is that you are passing ...this.props into the ComponentClass. In my case, the element is a span, but these are non-standard attributes and unrecognized by that element.

  render: function () {
    var ComponentClass = this.props.componentClass;
    return (
      !this.props.children ? this.renderStripeButton() : (
        <ComponentClass {...this.props} onClick={this.onClick}>
          {this.props.children}
        </ComponentClass>
      )
    );
  }

I'm not sure what the correct fix for this is. Perhaps you need to explicitly define the above unrecognized props as data attributes (per this documentation). The react documentation on the warning provides a few possible solutions.

Unexpected token `import`

I just updated to 2.1.1 and I'm having a compilation issue. It seems to break on the ES2015 syntax within the compiled dist/main.js file.

import React from 'react';

I downgraded back to 1.8 and it works fine. Thoughts?

A dist file for browser environment please

I was trying to use this in my Rails app where it is not a node project. It would be nice to have a compiled version of the plugin in dist. It would also be useful when you have simple html files too :)

Invoke from code?

I would like to automaticaly invoke the stripe-checkout via code (not having the user click a button) is this possible? if so, please let me know what function to invoke.

For example, I know I can get a child component via the .refs[key] so I just need to know what function to invoke from that point.

Thank you.

What about cross-origin access?

Since my React code is hosted on a static hosting domain, and my PHP is hosted on a non-static hosting domain, I’m running into the CORS issue.

Fetch API cannot load https://myapp.000webhostapp.com/charge.php. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Custom amount at checkout

Is it possible to have customers choose a variable amount to pay rather than having a pay button that pays a certain amount?

Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.