Implementing a Protx Direct payment gateway with 3D Secure verification in Ruby on Rails

Unfortunately, ActiveMerchant, the popular Ruby on Rails plugin used for payment gateway implementation doesn't have the best support for Protx, the popular UK system. In does support Protx in its basic form but it doesn't support 3D Secure authentication, which effectively makes it of no use. All Protx implementations have to support 3D Secure, the means by which gateways implement the Verified by Visa and MasterCard Secure Code. These are important verification technologies because in many cases they pass the liability for fraudulent cardholder-not-present card use to the card issuer - a very valuable thing for all online retailers.

3D Secure works by redirecting the credit card user to a Visa or Mastercard hosted site whereby they provide additional authentication details. Once the user has successfully completed this extra step they are redirected. The results of this redirection include an encoded string which itself is passed back to Protx for decoding and final processing.

Herewith are a collection of tips on a suitable Ruby on Rails implementation. These can be used to extend ActiveMerchant or create your own payment gateway.

Making an HTTPS call

You will need to make HTTPS POST calls to the Protx servers. To achieve this first create a hash called "data" which contains each of the parameters. Then:

    http = Net::HTTP.new(host, 443)
http.use_ssl = true

data_s = ""
data.each do |pair|
name = pair[0]
value = pair[1]
next unless value
data_s = data_s + "&" unless data_s.blank?

data_s = "#{data_s}#{name}=#{CGI.escape(value)}"
end

headers = {}
headers['Content-Type'] = 'application/x-www-form-urlencoded'
resp, rdata = http.post(path, data_s, headers)

Protx Response

The response from the Protx system arrives as a series of Name/Value pairs. You probably want to store these in your model of calls to Protx, like this:

 values = {}
rdata.each_line do |line|
name, value = line.split(/=/)
value.chomp! if value
name.downcase!
values[name] = value if self.has_attribute?(name)
end

self.update_attributes(values)

3D Secure

Processing the initial redirection to the 3D Secure system is simple. If the status is "3DAUTH" simply redirect the user to the URL provided in the original Protx response. This must be done as an HTTPS POST, so you'll need a self-submitting form sent to the user's browser as a response to their initial click of your Payment button. This is a simple form which an OnLoad event in the HTML's body tag. The OnLoad event causes the form to be submitted. Additionally, just in case for some reason the browser has been configured not to execute such an event, include a link for the user to click - most users will never see it. Remember that the link itself must submit the form, not be a normal link. A suitable view for the form might look like this:

<HTML>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>3D-Secure Redirect</title>
<script LANGUAGE="Javascript"> function OnLoadEvent() { document.form.submit(); } </script>

</head> <body OnLoad="OnLoadEvent();">
<FORM name="form" action="<%= @protxcall.acsurl%>" method="POST" />
<input type="hidden" name="PaReq" value="<%= @protxcall.pareq %>"/> <input type="hidden" name="TermUrl" value="<%= @protxcall.callbackurl %>"/> <input type="hidden" name="MD" value="<%= @protxcall.md %>"/>
<NOSCRIPT>
<p>Please click button below to Authenticate your card</p><input type=\"submit\" value=\"Go\"/></p>
</NOSCRIPT>
</form>
</body>
</html>  

3D Secure Results Callback

When you submit the 3D Secure request you include a field which tells the 3D Secure system where to redirect the user after they've completed the 3D process. In your case this will be back to a controller in your applicaiton which stores the results and makes a further request to Protx based on your own interpretation of the results. Alternatively you can use the Rules facility in the Protx administration tool in order to create your own rules. In this way you don't have to attempt to interpret the results in your RoR application.

Protx Error Messages

Some of the Protx error messages really aren't of a suitable form to show to an end user. The best way to provide a good user experience is to examine the Protx-returned status. Values are:

  • MALFORMED
  • INVALID
  • NOTAUTHED
  • REJECTED
  • ERROR

In the case of MALFORMED or INVALID you should invite the user to try again, but only after they've changed something about the card details they've submitted because evidently a mistake exists.

In the case of NOTAUTHED or REJECTED clearly the card has not been accepted as is - you could invite the user to submit another card.

ERROR means that the system has failed in some way and you've been unable to validate the card details and submit it for processing. You can invite the user to try again, possibly later.

Ending the Process

Once a start of "OK" has been received, the payment processing is complete and the controller should carry out the necessary actions (e.g. marking the invoice as paid, etc.). Finally the user should be redirected to a confirmation/thank you page. Provide a URL for display of the invoice, even if you're emailing them a copy as many invoice type emails may get mistakenly identified as SPAM by over aggressive filters.

Security of Card Details

If you store the credit card details before submitting them to Protx, or store the details of the exact submissions to Protx for later diagnosis, be sure to remove the credit card number from these records once the payment has been processed. You won't need the number again in most cases. If you want to do a repeat payment you can instruct that directly to Protx with just the original reference. In the case of a query or a chargeback the credit card processing company will provide the card number.

Also be sure to use RoR's facility for excluding these parameters from being logged. For example, at the top of your payments controller:

filter_parameter_logging :cc_cardnumber,  :cc_cv2