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

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, or
  • cardId, specifying a gift card by its card ID
  • contactId, 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, or
  • customer, 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.