This week, Authorize.net is starting its rollout of new server certificates, signed by a new certificate authority - Entrust. If you are using ActiveMerchant, this could break your stuff! It may or may not affect newer versions of ActiveMerchant - I don't know, I only have sites using old versions (like 1.18). So, even if it breaks, the solution may be different depending on your version of ActiveMerchant. Still, I'll try to keep the info detailed enough that you can find the solution yourself.
First, the problem. This affects you if, when ActiveMerchant tries to connect to Authorize.net, you receive the error:
SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
Note that you may not get this error when trying to connect to Authorize.net via manual Ruby code, but only via ActiveMerchant.
The reason for this is ActiveMerchant maintains its own list of Root CAs!
Therefore, to fix, you have to, (a) make sure that the new Root CAs for authorize.net are stored in your server's root CA list, and (b) make sure that ActiveMerchant is using your server's list rather than its own. For good measure, you can also copy ActiveMerchant's CA list to yours.
So, first, to add the Entrust root CAs to your Linux server (assuming it is a fairly recent CentOS-based distro), do the following as root:
Now you have all of the certs installed. Now we need to tell ActiveMerchant to use your own certs rather than its internal list. However, again, this is in the active_utils gem, not the activemerchant gem. Within the gem, find the file called lib/active_utils/common/connection.rb. Now look for a function called configure_ssl. Copy that function to your clipboard.
Now create a file in your own project called config/initializers/active_merchant_pem_fix.rb (the name doesn't matter as long as it is in config/initializers). In this file you need to have:
module ActiveMerchant class Connection # Paste the configure_ssl function you copied from lib/active_utils/common/connection.rb here. end end
Now, there will be a line that says something like this:
http.ca_file = File.dirname(__FILE__) + '/../../certs/cacert.pem'
This is the offending line!!! Comment that sucker out!!!
For my version of ActiveMerchant, this is what my file looks like:
def configure_ssl(http) return unless endpoint.scheme == "https" http.use_ssl = true if verify_peer http.verify_mode = OpenSSL::SSL::VERIFY_PEER # http.ca_file = File.dirname(__FILE__) + '/../../certs/cacert.pem' else http.verify_mode = OpenSSL::SSL::VERIFY_NONE end end
Now that you have the updated root CA on your server, and ActiveMerchant is using your server's list rather than your own, you are all set!