Stripe Plugin for Corona SDK

I created the Stripe plugin for Corona SDK to give Corona developers an easy way to accept online payments from inside their apps with as little as a single line of code.

This page contains the documentation for the plugin, as well as a sample project you can download and run to see the plugin in action for yourself. Please check back, as I will continue to update this page whenever bug fixes or new features are added.

Change Log

2/22/2016 : Initial public release.

About Stripe

Stripe is a startup that allows private individuals and businesses to accept online payments on websites and apps. They are a competitor to businesses like PayPal, and since being founded in 2010 they have grown at a rapid pace to become a major player in the mobile payments arena. If you regularly make online purchases, there’s a good chance that you’ve had your money move through their servers at some point. The bottom line is that Stripe makes it possible for you to securely accept payments in your app with Stripe doing most of the heavy lifting. I am a fan of their clean and easy-to-understand API, and the fact that they accept all sorts of payment types, from credit cards to Bitcoin.

I am in no way affiliated with Stripe, and they had nothing to do with the creation of this plugin. I’m just a fan of their API and thought it would be a useful tool for the Corona community – that’s why I built it.

Fees

Like all online payment processors, Stripe takes a percentage of each transaction to cover their costs and earn profit. This is not unlike Apple and Google Play’s 30% commission on app sales. As of February 2016, Stripe charges 2.9% plus 30 cents (USD) per successful charge, with lower rates in certain circumstances for European customers. There are no setup or monthly fees – they only collect a fee when you accept a payment. For the most up-to-date details on Stripe’s pricing structure, please visit stripe.com/pricing.

Please know that there is no usage fee associated with the Stripe plugin for Corona SDK – while I may charge a one-time fee for buying the plugin in the future, I make absolutely zero dollars from transactions processed using the plugin. Any fees that are collected are collected by Stripe, and the rates are set at Stripe’s discretion. Fortunately, the Stripe dashboard makes it easy to view the status of your account, along with any fees incurred, at a glance.

The Stripe API

While I designed this plugin to make it easy to use the Stripe API in your app, it would still behoove you to spend some time exploring Stripe’s easy-to-understand API Reference guide. This page should provide enough information to use the plugin on a basic level, but if you really want to make the most of Stripe’s functionality, I strongly advise you spend some time reading up on their API.

As you read up on the Stripe API, you may notice that there are endpoints and functions in the API that are not accounted for in the plugin. That’s because there are certain functionalities, such as processing refunds, that are simply better handled via the Stripe dashboard in my opinion. That said, there’s no technical reason why the plugin couldn’t be expanded to include features that are currently missing. If you have a particular need to access additional endpoints using the plugin, let me know and I’ll consider making additions. But I’m confident that almost every conceivable use for Stripe in a Corona app can be achieved with the current plugin capabilities.

Stripe Account Setup

Before you can use the Stripe plugin, you need to set up a free account with Stripe and obtain your account’s “API keys.” These keys are string values that ensure that charges made in your app are deposited into your Stripe account. Here’s a quick primer on setting up a new Stripe account and obtaining your keys (it only takes a minute or two):

Go to stripe.com and click the “sign up” button. (If you already have a Stripe account, just sign in and skip ahead to step 3.)

Once you are on your Stripe dashboard, go to your account settings and choose the “API Keys” option. You’ll see two sets of keys: a “test” set and a “live” set. You can only use one set of keys at a time (test or live) with the Stripe plugin. It’s best to use your test keys while you are developing your app to prevent accidental “real world” charges, but be sure to use the live keys on the version you release, or else you won’t actually get paid for any charges made in your app.

The API keys section of Stripe’s account settings panel. You’ll need one set of keys when calling stripe.init().

Adding the Plugin to Your App

Before you can require the plugin for use in your app, you’ll need to do two things:

Add an entry into a plugins table of your build.settings. The following is an example of a minimal build.settings file with the required entry for the Stripe plugin:

Lua

1

2

3

4

5

6

7

8

9

10

settings=

{

plugins=

{

-- @schroederapps' Stripe plugin:

["plugin.stripe"]={

publisherId="com.jasonschroeder",

},

},

}

After you’ve taken the above steps, you can require the plugin in your app with just one line of code:

Lua

1

localstripe=require("plugin.stripe")

Initializing the Plugin

Now that you have your Stripe account’s API keys handy, call stripe.init() in your code, preferably just after requiring the plugin. stripe.init() requires a single argument: a table with two key-value pairs. In this table, “secretKey” is a string containing your Stripe account’s secret API key, and “publishableKey” is a string containing your Stripe account’s publishable key. You can use either test or live keys, depending on your needs, but make sure that the keys you input are both from the same set (test or live). Your code should look something like this:

Lua

1

2

3

4

5

6

7

localstripe=require("plugin.stripe")

stripe.init({

secretKey="sk_test_abc123",

publishableKey="pk_test_abc123"

})

-- replace these keys with your test or live Stripe API keys

IMPORTANT!!! Be sure to NEVER use your live keys unless you are ready to accept real-world charges. Likewise, never user your test keys in an app that you are releasing for real-world usage. Calling stripe.init() with the wrong set of keys makes the difference between getting paid in real or pretend dollars – so proceed carefully!

Single Line of Code? Prove It!

There is a lot of functionality in the Stripe plugin, and it can get a little complicated to access every nook and cranny. But I want to show you a basic, minimum main.lua that would create a charge in as little code as possible. The code below, if you enter in valid API keys, will prompt the user to pay you $1.00 – and it’s for real! If you use live API keys, that $1.00 will actually make its way to your real-life bank account. It’s that easy!

Lua

1

2

3

4

5

6

localstripe=require("plugin.stripe")

stripe.init({

secretKey="sk_test_ABC123",

publishableKey="pk_test_ABC123"

})

stripe.checkout({amount=100,currency="usd"})

Syntax & Usage

All of the functions in the Stripe plugin are designed to have a common syntax. Toward that end, each function only accepts a single Lua table as the sole argument, which I refer to as params in the documentation. The properties of that table will vary depending on the function being called, but there are two specific key/value pairs that you should always include in your params table: an onSuccess function and an onFail function.

onSuccess Functions

Every params table should include an onSuccess property that points to a function to be called after a successful request to Stripe’s servers. An onSuccess function can optionally accept two two Lua tables as arguments. The first argument will always take the form of a Stripe object Lua table (more on that below). The second is a standard Corona networkRequest event table with details on the Stripe API request.

onFail Functions

Every params table should also include an onFail property that points to a function to be called if the request to Stripe’s servers fails. Request failure could be because of a network connection issue, or because Stripe’s servers reported an error (for example, if you attempted to charge an invalid or expired credit card). An onFail function can optionally accept one argument: a standard Corona networkRequest event table. (If your request was rejected by Stripe, details on the cause of the rejection will be found in event.response, a JSON string that you can convert into a Lua table using Corona’s built-in JSON library.)

The below sample requests details on a Stripe charge with the ID
ch_17dAujELWHyjUdjW854zZ7yR using stripe.getCharge(). If the request is successful, the onSuccess function will print the amount of the charge to the terminal as well as the currency. If the request is unsuccessful, the onFail function will print details on the failed request to the terminal:

Lua

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

localfunction_onSuccess(charge,event)

print("stripe.getCharge() succeeded!")

print("Amount: "..charge.amount.." "..charge.currency)

end

localfunction_onFail(event)

print("stripe.getCharge() failed!")

fork,vinpairs(event)do

print(k,v)

end

end

stripe.getCharge({

charge="ch_17dAujELWHyjUdjW854zZ7yR",

onSuccess=_onSuccess,

onFail=_onFail,

})

Stripe Objects

When you make a successful API call to Stripe’s servers via the plugin, a Stripe “object” is always returned to your onSuccess function. These objects contain data about the successful transaction and always take one of three forms: Charges, Customers, or Tokens.

Charges

Charge objects are tables containing complete details on any successful charge attempt on your Stripe account. Calling stripe.checkout() or stripe.newCharge() creates a new charge object, while other functions like stripe.getCharge() retrieve or manipulate an existing charge. The most important property of a charge object is the “id” string, which is a unique identifier for the object. For a complete list of charge object properties, please visit Stripe’s API Reference docs.

Here is an example of a charge object table that might be returned after calling stripe.newCharge():

Lua

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

{

id="ch_17g5qRELWHyjUdjWPM4TudYU",

object="charge",

amount=50,

amount_refunded=0,

balance_transaction="txn_17fwVZELWHyjUdjWnsgnZzZF",

captured=true,

created=1455855979,

currency="usd",

fraud_details={},

livemode=false,

metadata={},

paid=true,

refunded=false,

refunds={

object="list",

data={},

has_more=false,

total_count=0,

url="/v1/charges/ch_17g5qRELWHyjUdjWPM4TudYU/refunds"

},

source={

id="card_17g5qRELWHyjUdjWnmOFzst8",

object="card",

brand="Visa",

country="US",

cvc_check="pass",

exp_month=1,

exp_year=2020,

funding="credit",

last4="4242",

metadata={},

},

status="succeeded"

}

The following plugin functions return charge objects to their onSuccess functions:

Customers

Customer objects are tables containing complete details on a customer record in your Stripe account. Calling stripe.newCustomer() creates a new customer object, while other functions like stripe.updateCustomer() retrieve or manipulate an existing customer record. The most important property of a customer object is the “id” string, which is a unique identifier for the object. For a complete list of customer object properties, please visit Stripe’s API Reference docs.

Here is an example of a customer object table that might be returned after calling stripe.newCustomer():

Lua

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

{

id="cus_7uoSw2DHrv47t8",

object="customer",

account_balance=0,

created=1455590661,

currency="usd",

delinquent=false,

livemode=false,

metadata={},

sources={

object="list",

data={},

has_more=false,

total_count=0,

url="/v1/customers/cus_7uoSw2DHrv47t8/sources"

},

subscriptions={

object="list",

data={},

has_more=false,

total_count=0,

url="/v1/customers/cus_7uoSw2DHrv47t8/subscriptions"

}

}

The following plugin functions return customer objects to their onSuccess functions:

Tokens

Stripe tokens are objects that can be used anywhere in the Stripe API that a card or bank account is accepted, allowing you to charge a card without knowing the card numbers. Note that tokens are not meant to be stored or used more than once — you cannot make multiple charges using the same token. Calling newToken() creates a new token object, while stripe.getToken() retrieves an existing token object. The most important property of a token object is the “id” string, which is a unique identifier for the object. For a complete list of token object properties, please visit Stripe’s API Reference docs.

Here is an example of a token object table that might be returned after calling stripe.newToken():

Lua

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

{

id="tok_17g5VNELWHyjUdjWdaoe160q",

object="token",

card={

id="card_17g5VNELWHyjUdjWTI97Qd3H",

object="card",

brand="Visa",

country="US",

exp_month=8,

exp_year=2017,

funding="credit",

last4="4242",

metadata={},

},

created=1455854673,

livemode=false,

type="card",

used=false

}

The following plugin functions return token objects to their onSuccess functions:

* stripe.checkout() only returns a token if you specify
chargeNow=false in the params table. Otherwise, the card is charged and a charge object is returned instead.

Plugin Functions

stripe.checkout(params)*

*NOTE: currently stripe.checkout() is only available on Mac OS X and iOS because of limitations with how Corona SDK handles webViews and stripe’s Checkout javascript template. I hope to add support for Android soon. But you can achieve the same functionality using a combination of stripe.newToken() and stripe.newCharge() – you’d just need to build your own form for collecting credit card data.

Description:Displays a Stripe Checkout payment form and makes a new charge immediately. This is a two-step process. First, a token is created for the payment method entered by the user, and then a charge is created using that token. (You can elect to skip the second step and only create a token if you wish.) This is the easiest way to process a charge using the Stripe plugin, as it handles collecting customer data for you, securely using Stripe’s servers. See stripe.com/checkout for more details on the Stripe Checkout platform.

Arguments:stripe.checkout() accepts a single params table as an argument, with the below key/value pairs. See Stripe’s Checkout documentation for more details.

description:(optional, but strongly suggested) An arbitrary string which you can attach to a charge object. Note that if you use Stripe to send automatic email receipts to your customers, your receipt emails will include the description of the charge(s) that they are describing.

chargeNow:(boolean)(optional) Whether or not to process the charge immediately upon the user completing the Checkout form. Defaults to true.

data:(optional, but strongly suggested) a table containing key/value pairs that correspond to the configuration options listed in Stripe’s Checkout documentation. Here are the available key/value pairs:

image: A relative or absolute URL pointing to a square image of your brand or product. The recommended minimum size is 128x128px. The recommended image types are .gif, .jpeg, and .png.

name: The name of your company or website.

description: A description of the product or service being purchased. Defaults to the description specified in your params table.

amount: The amount (in cents) that’s shown to the user on the Checkout form. Default to the charge amount specified in your params table.

locale: The language to used in the Checkout form. Defaults to the user’s preferred language, if available, or English if not available.

currency: The currency of the amount (3-letter ISO code). Defaults to the currency specified in your params table.

panel-label: 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. Checkout does not translate custom labels to the user’s preferred language.

alipay-reusable: Specify if you need reusable access to the customer’s Alipay account (true or false). The default is false.

capture:(boolean)(optional) Whether or not to immediately capture the charge. Defaults to true. When false, the charge issues an authorization (or pre-authorization), and will need to be captured later. Uncaptured charges expire in 7 days. For more information, see authorizing charges and settling later.

metadata:(optional) an A table of key/value pairs that you can attach to a charge object. It can be useful for storing additional information about the customer in a structured format.

receipt_email:(optional) A string representing the email address to send this charge’s receipt to. The receipt will not be sent until the charge is paid. Receipts will not be sent for test mode charges. If receipt_email is specified for a charge in live mode, a receipt will be sent regardless of your email settings.

statement_descriptor:(optional) An arbitrary string to be displayed on your customer’s credit card statement. This may be up to 22 characters. As an example, if your website is RunClub and the item you’re charging for is a race ticket, you may want to specify a statement_descriptor of RunClub 5K race ticket. The statement description may not include
<>"' characters, and will appear on your customer’s statement in capital letters. Non-ASCII characters are automatically stripped. While most banks display this information consistently, some may display it incorrectly or not at all.

onSuccess:(optional, but strongly suggested) an onSuccess function triggered after a successful connection to Stripe.

onFail:(optional, but strongly suggested) an onFail function triggered after an unsuccessful connection to Stripe, or if Stripe returns an error.

onCancel:(optional, but strongly suggested) a function triggered when a user manually closes the Checkout form without completing the checkout process.

Returns:A Stripe charge object to your onSuccess listener if you elect to process the charge immediately (this is the default behavior). If you specify
chargeNow=false in your params table, a Stripe token object will be returned to your onSuccess function instead. A Corona networkRequest table to your onFail listener in an error occurs.

source:(string or table)(either source or customer is required) A payment source to be charged, such as a credit card. If you also pass a customer ID, the source must be the ID of a source belonging to the customer. Otherwise, if you do not pass a customer ID, the source you provide must either be a token (string), or a table containing a user’s credit card details, with the options described below. Although not all information is required, the extra info helps prevent fraud.

exp_month: (string)(required) Two digit number representing the card’s expiration month.

exp_year: (string)(required) Two or four digit number representing the card’s expiration year.

number: (string)(required) The card number, as a string without any separators.

object: (string)(required) The type of payment source. Should be “card”.

cvc: (string)(required) Card security code.

address_city(optional)

address_country(optional)

address_line1(optional)

address_line2(optional)

name: Cardholder’s full name (optional)

address_state(optional)

address_zip(optional)

customer:(string)(either source or customer is required) The ID of an existing customer that will be charged in this request.

capture:(boolean)(optional) Whether or not to immediately capture the charge. Defaults to true. When false, the charge issues an authorization (or pre-authorization), and will need to be captured later. Uncaptured charges expire in 7 days. For more information, see authorizing charges and settling later.

description:(optional, but strongly suggested) An arbitrary string which you can attach to a charge object. Note that if you use Stripe to send automatic email receipts to your customers, your receipt emails will include the description of the charge(s) that they are describing.

metadata:(optional) an A table of key/value pairs that you can attach to a charge object. It can be useful for storing additional information about the customer in a structured format.

receipt_email:(optional) A string representing the email address to send this charge’s receipt to. The receipt will not be sent until the charge is paid. Receipts will not be sent for test mode charges. If receipt_email is specified for a charge in live mode, a receipt will be sent regardless of your email settings.

statement_descriptor:(optional) An arbitrary string to be displayed on your customer’s credit card statement. This may be up to 22 characters. As an example, if your website is RunClub and the item you’re charging for is a race ticket, you may want to specify a statement_descriptor of RunClub 5K race ticket. The statement description may not include
<>"' characters, and will appear on your customer’s statement in capital letters. Non-ASCII characters are automatically stripped. While most banks display this information consistently, some may display it incorrectly or not at all.

onSuccess:(optional, but strongly suggested) an onSuccess function triggered after a successful connection to Stripe.

onFail:(optional, but strongly suggested) an onFail function triggered after an unsuccessful connection to Stripe, or if Stripe returns an error.

stripe.updateCharge(params)

Description:Adds or edits data for an existing charge on Stripe’s servers.

Arguments:stripe.updateCharge() accepts a single params table as an argument, with the below key/value pairs. See Stripe’s update a charge documentation for more details.

charge:(string)(required) The identifier of the charge to be updated.

description:(string)(optional) An arbitrary string which you can attach to a charge object. It is displayed when in the web interface alongside the charge. Note that if you use Stripe to send automatic email receipts to your customers, your receipt emails will include the description of the charge(s) that they are describing. This will be unset if you POST an empty value.

fraud_details:(table)(optional) A set of key/value pairs you can attach to a charge giving information about its riskiness. If you believe a charge is fraudulent, include a user_report key with a value of fraudulent. If you believe a charge is safe, include a user_report key with a value of safe. Note that you must refund a charge before setting the user_report to fraudulent. Stripe will use the information you send to improve our fraud detection algorithms.

metadata:(table)(optional) A set of key/value pairs that you can attach to a charge object. It can be useful for storing additional information about the charge in a structured format. You can unset individual keys if you POST an empty value for that key. You can clear all keys if you POST an empty value for metadata.

receipt_email:(string)(optional) This is the email address that the receipt for this charge will be sent to. If this field is updated, then a new email receipt will be sent to the updated address.

stripe.captureCharge(params)

Description:Capture the payment of an existing, uncaptured, charge. This is the second half of the two-step payment flow, where first you created a charge with the capture option set to false. Uncaptured payments expire exactly seven days after they are created. If they are not captured by that point in time, they will be marked as refunded and will no longer be capturable.

Arguments:stripe.captureCharge() accepts a single params table as an argument, with the below key/value pairs. See Stripe’s capture a charge documentation for more details.

charge:(string)(required) The identifier of the charge to be captured.

amount:(integer)(optional) The amount to capture, which must be less than or equal to the original amount. Any additional amount will be automatically refunded.

receipt_email:(string)(optional) The email address to send this charge’s receipt to. This will override the previously-specified email address for this charge, if one was set. Receipts will not be sent in test mode.

statement_descriptor:(string)(optional) An arbitrary string to be displayed on your customer’s credit card statement. This may be up to 22 characters.

onSuccess:(optional, but strongly suggested) an onSuccess function triggered after a successful connection to Stripe.

onFail:(optional, but strongly suggested) an onFail function triggered after an unsuccessful connection to Stripe, or if Stripe returns an error.

stripe.listCharges(params)

Description:Retrieves a list of charges you’ve previously created. The charges are returned in sorted order, with the most recent charges appearing first.

Arguments:stripe.listCharges() accepts a single params table as an argument, with the below key/value pairs. See Stripe’s list all charges documentation for more details.

created:(string or table)(optional) A filter on the list based on the object created field. The value can be a string with an integer Unix timestamp, or it can be a table with key/value pairs as described on Stripe’s API documentation.

customer:(string)(optional) Only return charges for the customer specified by this customer ID.

ending_before:(string)(optional) A cursor for use in pagination. ending_before is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_bar, your subsequent call can include ending_before=obj_bar in order to fetch the previous page of the list.

limit:(number)(optional) A limit on the number of objects to be returned. Limit can range between 1 and 100 items. Defaults to 10.

source:(table)(optional) A filter on the list based on the source of the charge. The table should contain one entry with the key “object” and a value of “all”, “alipay_account”, “bitcoin_receiver”, or “card.” Defaults to
{object="all"}

starting_after:(string)(optional) A cursor for use in pagination. starting_after is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include starting_after=obj_foo in order to fetch the next page of the list.

onSuccess:(optional, but strongly suggested) an onSuccess function triggered after a successful connection to Stripe.

onFail:(optional, but strongly suggested) an onFail function triggered after an unsuccessful connection to Stripe, or if Stripe returns an error.

Returns:A table containing at least one Stripe charge object to your onSuccess listener, in a numerically-indexed subtable called “data.” (see sample code below.) In the event of an error, a Corona networkRequest table is returned to your onFail listener.

NOTE: The table returned to your onSuccess function will contain a boolean “has_more” property. If
has_more==true then there will also be a “getMore” property that is a function you can call to get the next “page” of results (using the same onSuccess and onFail functions), until there are no more.

Sample Code:

Lua

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

localfunction_onSuccess(charges,event)

-- print charge IDs for all charges in the returned list

fori=1,#charges.data do

localcharge=charges.data[i]

print(charge.id)

end

-- retrieve more results if they exist:

ifcharges.has_more==truethen

charges.getMore()

end

end

stripe.listCharges({

limit=5,

onSuccess=_onSuccess,

onFail=_onFail,

})

stripe.newCustomer(params)

Description:Creates a new customer object on your Stripe account.

Arguments:stripe.newCustomer() accepts a single params table as an argument, with the below key/value pairs. See Stripe’s create a customer documentation for more details.

account_balance:(integer)(optional) An integer amount in cents that is the starting account balance for your customer. A negative amount represents a credit that will be used before attempting any charges to the customer’s card; a positive amount will be added to the next invoice.

description:(string)(optional) An arbitrary string that you can attach to a customer object. It is displayed alongside the customer in the dashboard.

email:(string)(optional) Customer’s email address. It’s displayed alongside the customer in your dashboard and can be useful for searching and tracking.

metadata:(table)(optional) A set of key/value pairs that you can attach to a customer object. It can be useful for storing additional information about the customer in a structured format.

shipping:(table)(optional) A table containing contact information about the customer. See Stripe’s API documentation for a complete list of available “shipping” fields.

source:(table)(optional) The source can either be a Stripe token ID, or a table containing a user’s credit card details. See Stripe’s API documentation for a complete list of available “source” fields.

onSuccess:(optional, but strongly suggested) an onSuccess function triggered after a successful connection to Stripe.

onFail:(optional, but strongly suggested) an onFail function triggered after an unsuccessful connection to Stripe, or if Stripe returns an error.

stripe.updateCustomer(params)

Description:Updates the specified customer by setting the values of the parameters passed. Any parameters not provided will be left unchanged.

Arguments:stripe.updateCustomer() accepts a single params table as an argument, with the below key/value pairs. See Stripe’s update a customer documentation for more details.

customer:(string)(required) The identifier of the customer to be updated.

account_balance:(integer)(optional) An integer amount in cents that represents the account balance for your customer. Account balances only affect invoices. A negative amount represents a credit that decreases the amount due on an invoice; a positive amount increases the amount due on an invoice.

description:(string)(optional) An arbitrary string that you can attach to a customer object. It is displayed alongside the customer in the dashboard.

email:(string)(optional) Customer’s email address. It’s displayed alongside the customer in your dashboard and can be useful for searching and tracking.

metadata:(table)(optional) A set of key/value pairs that you can attach to a customer object. It can be useful for storing additional information about the customer in a structured format.

shipping:(table)(optional) A table containing contact information about the customer. See Stripe’s API documentation for a complete list of available “shipping” fields.

source:(table)(optional) The source can either be a Stripe token ID, or a table containing a user’s credit card details. See Stripe’s API documentation for a complete list of available “source” fields.

onSuccess:(optional, but strongly suggested) an onSuccess function triggered after a successful connection to Stripe.

onFail:(optional, but strongly suggested) an onFail function triggered after an unsuccessful connection to Stripe, or if Stripe returns an error.

stripe.deleteCustomer(params)

Arguments:stripe.deleteCustomer() accepts a single params table as an argument, with the below key/value pairs. See Stripe’s delete a customer documentation for more details.

customer:(string)(required) The identifier of the customer to be deleted.

onSuccess:(optional, but strongly suggested) an onSuccess function triggered after a successful connection to Stripe.

onFail:(optional, but strongly suggested) an onFail function triggered after an unsuccessful connection to Stripe, or if Stripe returns an error.

Returns:A table with two parameters (“deleted”, which will always be true, and “id” which is the identifier of the newly-deleted customer) to your onSuccess listener, or a Corona networkRequest table to your onFail listener.

Sample Code:

Lua

1

2

3

4

5

stripe.deleteCustomer({

customer="cus_7xQAtp4v9hte0V",

onSuccess=_onSuccess,

onFail=_onFail,

})

stripe.listCustomers(params)

Description:Retrieves a list of your customers. The customers are returned sorted by creation date, with the most recent customers appearing first.

Arguments:stripe.listCustomers() accepts a single params table as an argument, with the below key/value pairs. See Stripe’s list all customers documentation for more details.

created:(string or table)(optional) A filter on the list based on the object created field. The value can be a string with an integer Unix timestamp, or it can be a table with key/value pairs as described on Stripe’s API documentation.

ending_before:(string)(optional) A cursor for use in pagination. ending_before is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, starting with obj_bar, your subsequent call can include ending_before=obj_bar in order to fetch the previous page of the list.

limit:(number)(optional) A limit on the number of objects to be returned. Limit can range between 1 and 100 items. Defaults to 10.

starting_after:(string)(optional) A cursor for use in pagination. starting_after is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include starting_after=obj_foo in order to fetch the next page of the list.

onSuccess:(optional, but strongly suggested) an onSuccess function triggered after a successful connection to Stripe.

onFail:(optional, but strongly suggested) an onFail function triggered after an unsuccessful connection to Stripe, or if Stripe returns an error.

Returns:A table containing at least one Stripe customer object to your onSuccess listener, in a numerically-indexed subtable called “data.” (see sample code below.) In the event of an error, a Corona networkRequest table is returned to your onFail listener.

NOTE: The table returned to your onSuccess function will contain a boolean “has_more” property. If
has_more==true then there will also be a “getMore” property that is a function you can call to get the next “page” of results (using the same onSuccess and onFail functions), until there are no more.

Sample Code:

Lua

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

localfunction_onSuccess(customers,event)

-- print customer IDs for all customers in the returned list

fori=1,#customers.data do

localcustomer=customers.data[i]

print(customer.id)

end

-- retrieve more results if they exist:

ifcustomers.has_more==truethen

customers.getMore()

end

end

stripe.listCharges({

limit=5,

onSuccess=_onSuccess,

onFail=_onFail,

})

stripe.newToken(params)

Description:Creates a single use token that wraps the details of a credit card or bank account.

Arguments:stripe.newToken() accepts a single params table as an argument, with the below key/value pairs. See Stripe’s create a token documentation for more details. Note that either a “card” or “bank_account” table is required, but you can only submit one or the other.

card:(table)(either card or bank_account are required) The card this token will represent.

exp_month: (string)(required) Two digit number representing the card’s expiration month.

exp_year: (string)(required) Two or four digit number representing the card’s expiration year.

number: (string)(required) The card number, as a string without any separators.

cvc: (string)(required) Card security code.

address_city(optional)

address_country(optional)

address_line1(optional)

address_line2(optional)

name: Cardholder’s full name (optional)

address_state(optional)

address_zip(optional)

bank_account:(table)(either card or bank_account are required) The bank account this token will represent.

account_number: (string)(required) The account number for the bank account in string form. Must be a checking account.

country: (string)(required) The country the bank account is in..

currency: (string)(required) The currency the bank account is in. This must be a country/currency pairing that Stripe supports.

routing_number: (string)(required for US bank accounts) The routing number, sort code, or other country-appropriate institution number for the bank account. For US bank accounts, this is required and should be the ACH routing number, not the wire routing number. If you are providing an IBAN for account_number, this field is not required.

account_holder_name: (string)(optional) The name of the person or business that owns the bank account.

account_holder_type: (string)(optional) The type of entity that holds the account. This can be either “individual” or “company”.

onSuccess:(optional, but strongly suggested) an onSuccess function triggered after a successful connection to Stripe.

onFail:(optional, but strongly suggested) an onFail function triggered after an unsuccessful connection to Stripe, or if Stripe returns an error.

stripe.donate(params)

Description:Displays a Stripe Checkout form that results in a charge being deposited into the Stripe account of Jason Schroeder (the guy who wrote the Stripe plugin).

Okay, so this isn’t something that you’d really want to put in your own app, but if you really love the plugin and wanted to give me a few bucks for the effort, this is a way to do that. It’s also built into the sample app.

Arguments:stripe.donate() accepts a single params table as an argument, with the below key/value pairs.

amount:(number)(required) a positive integer representing the amount to be charged, in the lowest currency unit.

currency:(string)(optional) a 3-letter ISO code for currency. Defaults to “usd”.

onSuccess:(optional, but strongly suggested) an onSuccess function triggered after a successful connection to Stripe.

onFail:(optional, but strongly suggested) an onFail function triggered after an unsuccessful connection to Stripe, or if Stripe returns an error.

onCancel:(optional, but strongly suggested) a function triggered when a user manually closes the Checkout form without completing the checkout process.

Gotchas

Charge Amounts Must Be Integers

It is important to note that Stripe only handles charge amounts as integers – so all your charge amounts must represent the charge value in the lowest currency unit (for US dollars, this means cents). If you wanted to charge a customer fifty dollars, you would need to submit that amount as “5000” – were you to submit “50” or even “50.00”, the customer would only be charged fifty cents!

Test Card Numbers

When you are using the plugin with test API keys, Stripe’s servers will refuse any attempt to charge an actual credit card. However, Stripe provides a list of “dummy” card numbers for all supported card types so you can see first-hand how your app is handling charges while still in test mode. Additionally, Stripe provides other numbers that will trigger specific non-successful server responses, so you can test your app’s error handling. For example, entering card # “4000 0000 0000 0127” in test mode will cause a decline on account of an incorrect CVC security code, and card # “4000 0000 0000 0069” will cause a decline on account of an expired card. For a complete list of these “dummy” card numbers, please go to stripe.com/docs/testing.

Demo Project

I’ve created a free demonstration project that you can load in the simulator or build for device to see the Stripe plugin in action. The project is fully self-contained, so all you need to do is download it and open it in the simulator. However, you will need to open a Stripe account and add your API keys to the stripe.init() function call on line 5 of the project’s main.lua for it to work properly.

Thanks for commenting, Christian! In an ideal world, that’s true – you should be making calls from a secure server, and the secret key should not be in your app’s code.

I designed the plugin to operate without the need for a separate server to make the actual API requests to Stripe. It’s worth noting that there is another Lua-based Stripe library that Stripe links to on its official list of API Libraries (https://stripe.com/docs/libraries) that operates in much the same way, at least in regards to your secret key.

I would say that your Lua code gets converted into bytecode when you build for device with Corona, so there’s at least some measure of obfuscation going on. But if you really wanted to keep the key out of your code, you could come up with your own way of securely obtaining it via network request. This would prevent the key from actually appearing in your code (and could also give you the ability to generate a new set of API keys and push them to your app without having to submit an app update).

Alternatively, if you do have a server that you want to make the actual charges from, you can still use the plugin to generate tokens without an actual secret key. Since generating tokens can be done with only the publishable key, you could call stripe.init() with your actual publishable key and a “dummy” secret key. This would render all but stripe.newToken() and stripe.checkout() inoperable (and stripe.checkout would only work if you set chargeNow=false), since those functions require a working secret key. But doing so would allow you to obtain a token ID that you could then pass to your own server, to have the final charge API call make from a server (where the secret key is not user-facing).

Thanks Jason, I did think about getting the secret key from my secure server upon launch of my app, not ideal but not terrible. So I can create new customers, add cards etc. without the secret key, which actually maybe all I need as I have the server side process the payments as they are automated upon completion of a job.

No time soon unfortunately as stripe.checkout() requires a webview to run, and the Android version of Stripe’s “stripe.js” library that the webview loads requires the checkout page to open in a new window – something that doesn’t play nice with embedded app webviews. Check this CoronaLabs forum thread for more details on this topic: https://forums.coronalabs.com/topic/64547-stripe-plugin-javascript-modal-issue/

It looks like you attempted to require a plugin specifically for stripe.checkout, which would cause that warning.

At any point in your code do you include require(“plugin.stripe.checkout”)? If so, that’s your problem. There is no “plugin.stripe.checkout” – just “plugin.stripe” – remove any attempt to require anything besides “plugin.stripe” and you should be good to go.

Thanks Kevin. At least it’s working, but I’ll do some digging and see if I can eliminate that error message. CoronaLabs changed the way they distribute plugins in the last week or so, which could be part of the issue? Stay tuned.

@Kevin: I’m not able to replicate the issue, at least in the Corona simulator. Are you seeing this in the simulator or only on device? What OS are you running it on (Windows Simulator / OS X Simulator / iOS / Android)? Also, please download the latest daily build from Corona Labs first and confirm you are still seeing that error after doing so. Thanks!

Unfortunately this isn’t something I’d be able to do directly in the plugin, at least not that I am aware of. The plugin is coded purely in Lua, and makes use of Corona’s built-in network.request() API for all network calls. To support this, you’d need to make sure that Corona updates their APIs to force TLS 1.2 compliance in earlier versions of Android.

I was unable to reproduce the issue you reported. I successfully made a test transaction using 4242424242424242 – but in any case, the plugin worked as expected if you received a response from Stripe’s servers. The plugin simply sends and receives data from Stripe, so if the response is not as expected, you’d need to take it up with them, I’m afraid.

Your email address will not be published. Required fields are marked *

Comment

Name *

Email *

Website

Please Do Not Feed The Developers

The Corona SDK tutorials, modules and code snippets that I post on this site are free for you to use, with no expectation of repayment. But a few kind souls have told me that they wanted to toss me a few bucks as a way of saying "thanks," so I've added this donation button. If you like what I'm doing here, and wanted to contribute, feel free. And if not, that's cool too. I'm just glad you're here.