Spree and Authorize.Net: Authorization and Capture Quick Tip
Last week I did a bit of reverse engineering on payment configuration in Spree. After I successfully setup Spree to use Authorize.net for a client, the client was unsure how to change the Authorize.Net settings to perform an authorize and capture of the credit card instead of an authorize only.
The requested settings for an Authorize.Net payment gateway on the Spree backend.
I researched in the Spree documentation for a bit and then sent out an email to the End Point team. Mark Johnson responded to my question on authorize versus authorize and capture that the Authorize.Net request type be changed from “AUTH-ONLY” to “AUTH_CAPTURE”. So, my first stop was a grep of the activemerchant gem, which is responsible for handling the payment transactions in Spree. I found the following code in the gem source:
# Performs an authorization, which reserves the funds on the customer's credit card, but does not
# charge the card.
def authorize(money, creditcard, options = {})
post = {}
add_invoice(post, options)
add_creditcard(post, creditcard)
add_address(post, options)
add_customer_data(post, options)
add_duplicate_window(post)
commit('AUTH_ONLY', money, post)
end
# Perform a purchase, which is essentially an authorization and capture in a single operation.
def purchase(money, creditcard, options = {})
post = {}
add_invoice(post, options)
add_creditcard(post, creditcard)
add_address(post, options)
add_customer_data(post, options)
add_duplicate_window(post)
commit('AUTH_CAPTURE', money, post)
end
My next stop was the Spree payment_gateway core extension. This extension is included as part of the Spree core. It acts as a layer between Spree and the payment gateway gem and can be swapped out if a different payment gateway gem is used without requiring changing the transaction logic in the Spree core. I searched for purchase and authorize in this extension and found the following:
def purchase(amount, payment)
#combined Authorize and Capture that gets processed by the ActiveMerchant gateway as one single transaction.
response = payment_gateway.purchase((amount * 100).round, self, gateway_options(payment))
...
end
def authorize(amount, payment)
# ActiveMerchant is configured to use cents so we need to multiply order total by 100
response = payment_gateway.authorize((amount * 100).round, self, gateway_options(payment))
...
end
My last stop was where I found the configuration setting I was looking for, Spree::Config[:auto_capture], by searching for authorize and purchase in the Spree application code. I found the following logic in the Spree credit card model:
def process!(payment)
begin
if Spree::Config[:auto_capture]
purchase(payment.amount.to_f, payment)
payment.finalize!
else
authorize(payment.amount.to_f, payment)
end
end
end
The auto_capture setting defaults to false, not surprisingly, so it can be updated with one of the following changes.
# *_extension.rb:
def activate
AppConfiguration.class_eval do
preference :auto_capture, :boolean, :default => true
end
end
# EXTENSION_DIR/config/initializers/*.rb:
if Preference.table_exists?
Spree::Config.set(:auto_capture => true)
end
After I found what I was looking for, I googled “Spree auto_capture” and found a few references to it and saw that it was briefly mentioned in the Spree documentation payment information. Perhaps more documentation could be added around how the Spree auto_capture preference setting trickles down through the payment gateway processing logic, or perhaps this article provides a nice overview of the payment processing layers in Spree.
Comments