Lightrail Stripe Integration Gem
Lightrail is a modern platform for digital account credits, gift cards, promotions, and points (to learn more, visit Lightrail). The Lightrail Stripe gem provides a client library for developers to easily use Lightrail alongside Stripe.
If you are looking for specific use cases or other languages, check out related projects. For a complete list of all Lightrail libraries and integrations, check out the Lightrail Integration page.
Features
- Simple order checkout which supports Lightrail gift card redemption alongside a Stripe payment
- Convenient wrappers for making common calls to the Lightrail API using a similar interface to Stripe
This gem depends on the Lightrail Client Gem for communicating with the Lightrail API. It offers convenient wrappers for common API calls for those who are already using Stripe's Ruby gem and are familiar with that interface: Lightrail::LightrailCharge.create
, Lightrail::Refund.create
, etc. These calls will return class instance objects instead of hashes, with convenience methods and properties that can be accessed with dot notation (for a more detailed example, see the balance check code in the following section):
gift_value = Lightrail::LightrailValue.retrieve_by_card_id(<CARD ID>)
gift_value.maximum_value #=> 3500
Related Projects
Usage
Before using any parts of the library, you need to set up your Lightrail API key, and if you have not already done so, you will also need to set up your Stripe API key:
Lightrail.api_key = '<your lightrail API key>'
Stripe.api_key = '<your stripe API key>'
A note on sample code snippets: for reasons of legibility, the output for most calls has been simplified. Attributes of response objects that are not relevant here have been omitted.
Order Checkout Using StripeLightrailSplitTenderCharge
StripeLightrailSplitTenderCharge
is a class designed to resemble the interface of a Stripe Charge
class which transparently splits the transaction between Lightrail and Stripe. The Lightrail parameter could be one of the following:
code
, specifying a gift card by its code, orcardId
, specifying a gift card by its card IDcontactId
, specifying a customer by their contact ID (generated by Lightrail)shopperId
, specifying a customer by their shopper ID (generated by your ecommerce system)
The Stripe parameter could be:
source
, indicating a Stripe token, orcustomer
, indicating a Stripe customer ID
You must also pass in the amount to charge to Lightrail.
Here is a simple example:
split_tender_charge_params = {
amount: 1000,
currency: 'USD',
code: '<GIFT CODE>',
source: '<STRIPE TOKEN>',
}
lightrail_amount = 450
split_tender_charge = Lightrail::StripeLightrailSplitTenderCharge.create(split_tender_charge_params, lightrail_amount)
If you don't provide any Lightrail payment parameters and set the lightrail_amount
to 0, the entire transaction will be charged to Stripe. Similarly, if you don't provide any Stripe payment parameters and set the lightrail_amount
to the full amount, the library will attempt to charge the entire transaction to Lightrail. If the value of the gift card is not enough to cover the entire transaction amount and no Stripe payment method is included, you will receive a BadParameterError
asking you to provide a Stripe parameter.
There is also a wrapper method that can determine the Stripe/Lightrail split automatically: Lightrail::StripeLightrailSplitTenderCharge.create_with_automatic_split
. This method accepts the same charge_params
as the default .create
, but does not expect a stripe_amount
or lightrail_amount
. When both a Lightrail and a Stripe payment method are provided to this method, the library will try to split the payment in such a way that Lightrail contributes to the payment as much as possible. This usually means:
- If the Lightrail value is sufficient, the entire transaction will be charged to the gift card.
- If the transaction amount is larger than the Lightrail value, the remainder will be charged to Stripe.
Managing Lightrail Gift Cards and Accounts
A Lightrail Gift Card is a virtual device for issuing gift values. Each gift card has a specific currency
, a cardId
, and a fullCode
, which is a unique unguessable alphanumeric string, usually released to the gift recipient in confidence. The recipient of the gift card can present the fullCode
to redeem the gift value. For further explanation of cards and codes see the Lightrail API documentation.
Customer Accounts are values attached to a customer and are commonly used for customer rewards and account credit programs. For further explanation of this concept check out the Lightrail API documentation.
Balance Check
Use the Lightrail::LightrailValue
class to check the balance of gift cards or customer accounts.
For gift cards, use .retrieve_by_card
or .retrieve_by_code
:
gift_balance_details = Lightrail::LightrailValue.retrieve_card_details("<GIFT CARD ID>")
# or use the fullCode:
# gift_balance_details = Lightrail::LightrailValue.retrieve_code_details("<GIFT CODE>")
#=> <Lightrail::LightrailValue:0x007fe24b16f500
@principal=
{
'currentValue' => 3000,
'state' => 'ACTIVE',
'expires' => nil,
'startDate' => nil,
'programId' => 'program-123456',
'valueStoreId' => 'value-123456'},
@attached=[{'currentValue' => 500,
'state' => 'ACTIVE',
#...},
{'currentValue' => 250,
'state' => 'EXPIRED',
#...}],
@currency="USD",
@cardType="GIFT_CARD",
@balanceDate="2017-05-29T13:37:02.756Z",
@cardId="card-123456>
gift_maximum_value = gift_balance_details.maximum_value
#=> 3500
For accounts, use .retrieve_by_contact_id
or .retrieve_by_shopper_id
. Note that because a single contact can hold account value in several different currencies, it is also necessary to specify the account currency to perform a balance check:
account_balance_details = Lightrail::Value.retrieve_by_contact_id({
contact_id: '<CONTACT ID>',
currency: 'USD'
})
# or use a customer's shopper_id:
# account_balance_details = Lightrail::Value.retrieve_by_shopper_id({
# shopper_id: '<CONTACT ID>',
# currency: 'USD'
# })
#=> <Lightrail::LightrailValue:0x007fe24b16f500
@principal = {'currentValue' => 3000, ...}>
Charging a Gift Card or Customer Account
UseLightrail::LightrailCharge.create
to charge a gift card or a customer account. The minimum required parameters are either the gift card's fullCode
or cardId
OR the customer's contactId
or shopperId
, the currency
, and the amount
of the transaction (a positive integer in the smallest currency unit, e.g., 500 cents is 5 USD):
gift_charge = Lightrail::LightrailCharge.create({
amount: 1850,
currency: 'USD',
code: '<GIFT CODE>' # or card_id/contact_id/shopper_id
})
#=> <Lightrail::LightrailCharge:0x007fdb62206e68
@value=-1850,
@userSuppliedId="17223eff",
@transactionType="DRAWDOWN",
@currency="USD",
@transactionId="transaction-cd245",
#...>
A note on idempotency: All calls to create or act on transactions (refund, void, capture) can optionally take a userSuppliedId
parameter. The userSuppliedId
is a client-side identifier (unique string) which is used to ensure idempotency (for more details, see the API documentation). If you do not provide a userSuppliedId
, the gem will create one for you for any calls that require one.
gift_charge = Lightrail::LightrailCharge.create({
amount: 1850,
currency: 'USD',
code: '<GIFT CODE>',
userSuppliedId: 'order-13jg9s0era9023-u9a-0ea'
})
Note that Lightrail does not support currency exchange and the currency provided in this method must match the currency of the gift card or the customer's account.
For more details on the parameters that you can pass in for a charge request and the response that you will get back, see the Lightrail API documentation.
Authorize-Capture Flow
You can create a pending charge for a Lightrail gift card or customer account the same way you would with Stripe for a credit card — simply by adding capture: false
to your charge parameters. The pending charge object returned from this method call will also have convenience methods to directly #capture!
or #cancel!
that charge:
gift_charge = Lightrail::LightrailCharge.create({
amount: 1850,
currency: 'USD',
code: '<GIFT CODE>', # or card_id/contact_id/shopper_id
capture: false,
})
# later on
gift_charge.capture!
#=> <Lightrail::LightrailCharge:0x007fdb633531d0
@value=-1850,
@userSuppliedId="17223eff",
@dateCreated="2017-05-29T13:37:02.756Z",
@transactionType="DRAWDOWN",
@transactionAccessMethod="RAWCODE",
@cardId="<GIFT CARD ID>",
@currency="USD",
@transactionId="transaction-cd245",
@parentTransactionId="transaction-b9d4444">
# or
gift_charge.cancel!
#=> <Lightrail::LightrailCharge:0x007fdb62854018
@value=-1850,
@userSuppliedId="17223eff",
@dateCreated="2017-05-29T13:37:02.756Z",
@transactionType="PENDING_VOID",
@transactionAccessMethod="RAWCODE",
@cardId="<GIFT CARD ID>",
@currency="USD",
@transactionId="transaction-0ce6f05",
@parentTransactionId="transaction-b9d4444">
Note that #capture!
and #cancel!
will each return a new transaction and will not modify the instance they are called on. These new transactions will have their own transactionId
. If you need to record the transaction ID of the captured or canceled charge, you can get it from the object returned by these methods (a new instance of LightrailCharge
).
Refunding a Charge
You can undo a charge by using the Lightrail::Refund
class and passing in the transaction instance you wish to refund. This will create a new refund
transaction which will return the charged amount back to the card or account. The return object will be an instance of Lightrail::Refund
. If you need the transaction ID of the refund transaction, you can find it on this object.
gift_charge = Lightrail::LightrailCharge.create(<CHARGE PARAMS>)
# later on
Lightrail::Refund.create(gift_charge)
#=> <Lightrail::Refund:0x007fdb62854018
@value=1850,
@userSuppliedId="873b08ab",
@dateCreated="2017-05-29T13:37:02.756Z",
@transactionType="DRAWDOWN_REFUND",
@transactionAccessMethod="CARDID",
@cardId="<GIFT CARD ID>",
@currency="USD",
@transactionId="transaction-0f2a67",
@parentTransactionId="transaction-2271e3">
Note that this does not necessarily mean that the refunded amount is available for a re-charge. In the edge case where the funds for the original charge came from a promotion which has now expired, refunding will return those funds back to the now-expired value store and therefore the value will not be available for re-charge. To learn more about using value stores for temporary promotions, see the Lightrail API docs.
Funding a Gift Card or Customer Account
To add funds to a card or account, you can use the Lightrail::LightrailFund
class. Note that the Lightrail API does not permit funding a gift card by its code
and the only way to fund a card is by providing its cardId
. Customer accounts can be funded by supplying either their contact_id
or their shopper_id
along with the currency
of the account.
gift_fund = Lightrail::LightrailFund.create({
amount: 500,
currency: 'USD',
card_id: '<GIFT CARD ID>' # or contact_id/shopper_id
})
#=> <Lightrail::LightrailFund:0x007fb7b18b96b8
@value=500,
@userSuppliedId="4f86a1be",
@dateCreated="2017-05-29T13:37:02.756Z",
@transactionType="FUND",
@transactionAccessMethod="CARDID",
@cardId="<GIFT CARD ID>",
@currency="USD",
@transactionId="transaction-240eca6">
Installation
This gem is available on RubyGems.org. To use it in your project, add this line to your application's Gemfile:
gem 'lightrail_stripe'
And then execute:
$ bundle
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/Giftbit/lightrail-stripe-ruby.
Development
After checking out the repo, run bin/setup
to install dependencies, then run bundle exec rspec
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
.
License
The gem is available as open source under the terms of the MIT License.