-
Notifications
You must be signed in to change notification settings - Fork 154
Configuration options
You can set your Stripe keys in two ways:
- By setting
STRIPE_SECRET_KEY
andSTRIPE_PUBLISHABLE_KEY
environment variables to their corresponding values. - By setting the
secret_key
andpublishable_key
settings in your Payola config initializer as shown above.
# config/initializers/payola.rb
Payola.configure do |config|
config.secret_key = 'sk_live_iwillnevertell'
config.publishable_key = 'pk_live_iguessicantell'
# config.default_currency = 'gbp'
# Prevent more than one active subscription for a given user
config.charge_verifier = lambda do |event|
user = User.find_by(email: event.email)
if event.is_a?(Payola::Subscription) && user.subscriptions.active.any?
raise "Error: This user already has an active <plan_class>."
end
event.owner = user
event.save!
end
# Send create subscription email
config.subscribe("customer.subscription.created") do |event|
subscription = Payola::Subscription.find_by(stripe_id: event.data.object.id)
YourCustomMailer.new_<plan_class>_email(subscription.id).deliver
end
config.subscribe("customer.subscription.updated") do |event|
subscription = Payola::Subscription.find_by(stripe_id: event.data.object.id)
if event.as_json.dig("data", "previous_attributes").key?("items")
# Send upgrade subscription email
old_amount = event.as_json.dig("data", "previous_attributes", "items", "data").first.dig("plan").fetch("amount")
YourCustomMailer.upgrade_<plan_class>_email(old_amount, subscription.id).deliver
else
# Send cancel subscription email
YourCustomMailer.cancel_<plan_class>_email(subscription.id).deliver
end
end
end
# config/initializers/payola.rb
Payola.configure do |config|
config.secret_key = 'sk_live_iwillnevertell'
config.publishable_key = 'pk_live_iguessicantell'
# config.default_currency = 'gbp'
config.subscribe 'payola.book.sale.finished' do |sale|
YourCustomMailer.receipt(sale.guid).deliver
end
config.subscribe 'payola.book.sale.failed' do |sale|
YourCustomMailer.admin_failed(sale.guid).deliver
end
config.subscribe 'payola.book.sale.refunded' do |sale|
YourCustomMailer.admin_refunded(sale.guid).deliver
end
end
Payola wraps the StripeEvent gem for event processing and adds a few special sale-related events. Each one of these events passes the related Sale
instance instead of a Stripe::Event
. They are sent in-process so you don't have to wait for Stripe to send the corresponding webhooks.
-
payola.<product_class>.sale.finished
, when a sale completes successfully -
payola.<product_class>.sale.failed
, when a charge fails -
payola.<product_class>.sale.refunded
, when a charge is refunded
(In these examples, <product_class>
is the underscore'd version of the product's class name.)
You can also subscribe to generic events that do not have the product_class
included in them. Those are:
-
payola.sale.finished
, when a sale completes successfully -
payola.sale.failed
, when a charge fails -
payola.sale.refunded
, when a charge is refunded
You can set a callback that Payola will call immediately before attempting to make a charge. You can use this to, for example, check to see if the email address has been used already. To stop Payola from making a charge, throw a RuntimeError
. The sale will be set to errored
state and the message attached to the runtime error will be propogated back to the user.
Payola.configure do |config|
config.charge_verifier = lambda do |sale|
raise "Improper sale!" unless sale.amount > 10_000_000
end
end
You can optionally pass some data through the checkout button partial using the custom_fields
option. This will be presented as a second argument to charge_verifier
. For example:
<%= render 'payola/transactions/checkout', custom_fields: {'hi' => 'there'} %>
Payola.configure do |config|
config.charge_verifier = lambda do |sale, custom_data|
raise "Rude charge did not say hi!" unless custom_data['hi']
end
end
Whatever data you pass through the custom_data
option will be serialized and then signed with your Stripe secret key. You should stick to simple types like numbers, string, and hashes here, and try to minimize what you pass because it will end up both in the HTML you send to the user as well as the database.
You can subscribe to any webhook events you want as well. Payola will dedupe events as they come in. Make sure to set your webhook address in Stripe's management interface to:
https://www.example.com/payola/events
To subscribe to a webhook event:
Payola.configure do |config|
config.subscribe 'charge.succeeded' do |event|
sale = Payola::Sale.find_by(stripe_id: event.data.object.id)
YourCustomMailer.admin_receipt(sale.guid)
end
end
Payola uses StripeEvent#event_retriever
internally. If you would like to customize or filter the events that come through, use Payola's event_filter
:
Payola.configure do |config|
config.event_filter = lambda do |event|
return nil unless event.blah?
event
end
end
event_filter
takes an event and returns either nil
or an event. If you return nil, the event ID will be recorded in the database but no further action will be taken. Returning the event allows processing to continue.
This button sends an example event to your webhook urls, including an id of evt_00000000000000. To confirm that Stripe sent the webhook, StripeEvent attempts to retrieve the event details from Stripe using the given id. In this case the event does not exist and StripeEvent responds with 401 Unauthorized. Instead of using the 'Test Webhooks' button, trigger webhooks by using the Stripe API or Dashboard to create test payments, customers, etc.
You can read more about stripe event here.
This button re-sends a webhook, which is useful for testing your webhook subscriptions in development (using something like Ultrahook). If you resend a webhook, you'll need to delete the existing Payola::StripeWebhook
record for this webhook from your database, otherwise the Payola will treat it as a duplicate that has already been processed and will ignore it.
Payola will attempt to auto-detect the job queuing system you are using. It currently supports the following systems:
- ActiveJob (
:active_job
) - Sidekiq (
:sidekiq
) - SuckerPunch (
:sucker_punch
)
Payola will attempt ActiveJob first and then move on to try autodetecting other systems. If you want to force Payola to use a specific supported system, just set background_worker
to the appropriate symbol. For example:
Payola.background_worker = :sidekiq
You can also set this to anything with a call
method, for complete control over how Payola's jobs get queued. For example, you can run jobs in-process like this:
Payola.background_worker = lambda do |klass, *args|
klass.call(*args)
end
Payola includes basic emails that you can optionally send to your customers and yourself. Opt into them like this:
Payola.configure do |config|
config.send_email_for :receipt, :admin_receipt
end
Possible emails include:
:receipt
:refund
:admin_receipt
:admin_dispute
:admin_refund
:admin_failure
:receipt
and :refund
both send to the email address on the
Payola::Sale
instance from the support_email
address. All of
the :admin
messages are sent from and to the support_email
address.
To customize the content of the emails, copy the appropriate views (receipt, admin) into your app at the same path (app/views/payola/<whatever>
) and modify them as you like. You have access to @sale
and @product
, which is just a shortcut to @sale.product
.
You can include a PDF with your receipt by setting the pdf_receipt
option to true
. This will send the receipt_pdf.html
template to Docverter for conversion to PDF. See the Docverter README for installation instructions if you would like to run your own instance.
You can override the GUID generator that Payola uses. By default it generates a large random number and encodes it in Base32.
Payola.configure do |config|
config.guid_generator = lambda do
SecureRandom.random_number(1_000_000_000).to_s(32)
end
end
Payola::Sale
has a polymorphic belongs_to :owner
association which you can use to assign a sale to a particular business object in your application. One way to do this is in the charge_verifier
:
Payola.configure do |config|
config.charge_verifier = lambda do |sale, custom_fields|
sale.owner = User.find(custom_fields[:user_id])
sale.save!
end
end
In this example you would have set the user_id
custom field in the Checkout partial to the proper ID.