Thursday, December 24, 2009

Implementing Payson API Integration 1.0 in Ruby

To do payment using Payson API integration 1.0 you need to follow 3 steps.
  1. Request to initiate a pay request (in return it will send you back a token)
  2. Redirect client to Payson site using that token
  3. After client completes the payment, Payson will redirect the client back to your site and you can check the payment status and update status of payment on your application
Payson api cycle

Plugin used

RestClient is nice API to handle http request and response.

Step 1 (Request to initiate a pay request)

To be able to use Payson API integration you must have,
AgentID: XXXX
MD5-key: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
For a pay initiate request you can see the specification here. Before you integrate the API in your application you can make a curl http call just to check if every thing works.
curl -H "PAYSON-SECURITY-USERID:XXXX" \
-H "PAYSON-SECURITY-PASSWORD:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" \
-d "receiverList.receiver(0).email=test@gmail.com&receiverList.receiver(0).amount=10&returnUrl=http://localhost:3000/payson_return/56&cancelUrl=http://localhost:3000/payson_cancel/56&memo=test&senderEmail=sender@gmail.com&senderFirstName=A.K.M.&senderLastName=Ashrafuzzaman" https://api.payson.se/1.0/Pay/ -o payson.out
Here PAYSON-SECURITY-USERID is AgentID and PAYSON-SECURITY-PASSWORD MD5-key. And as you can see PAYSON-SECURITY-USERID and PAYSON-SECURITY-PASSWORD (the authentication fields) will have to be send in the headers of the request. Now it should return a message which looks like,
responseEnvelope.ack=SUCCESS&responseEnvelope.timestamp=2009-11-15T17%3a14%3a03&responseEnvelope.version=1.0&TOKEN=4ecce14b-a4c7-4990-9814-db8aa2e97553
The response will contain a token which will be used to do the pay request.
Now let us see the ruby version of the curl request,
params_list = { 'receiverList.receiver(0).email' => reciever_email,
  'receiverList.receiver(0).amount' => recieving_amount,
  'receiverList.receiver(1).email' => more_receiver_email, #you can send money to more then one account
  'receiverList.receiver(1).amount' => more_receive_amount,
  'returnUrl' => callback_url,
  'cancelUrl' => cancel_url,
  'memo' => description,
  'senderEmail' => sender_email,
  'senderFirstName' => first_name,
  'senderLastName' => last_name }

header_list = {'PAYSON-SECURITY-USERID' => 'XXXX', 'PAYSON-SECURITY-PASSWORD' => 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'}

response = RestClient.post 'https://api.payson.se/1.0/Pay/', params_list, header_list

Step 2 (Redirect client to Payson site)

Now parse the response and redirect to Payson site for client to complete the payment.
response_hash = parse_response(response)

if response_hash['responseEnvelope.ack'] == 'SUCCESS'
  logger.info "Payson pay response #{response}"
  @signup.payson_token = response_hash['TOKEN']
  @signup.save!
  redirect_to "https://www.payson.se/PaySecure?token=#{response_hash['TOKEN']}"
elsif response_hash['responseEnvelope.ack'] == 'FAILURE'
  redirect_to @signup.event.home_path
end
This will redirect to Payson paysecure page. And client will complete the payment which will redirect the client back to returnUrl. If the client cancels the payment then he will be redirected to cancel url.

Step 3 (complete the process)

Now it is time to nail it ;)
In the return action you should check that the payment is done.
response = RestClient.get "https://api.payson.se/1.0/PaymentDetails?token=#{signup.payson_token}",
              {'PAYSON-SECURITY-USERID' => 'XXXX', 'PAYSON-SECURITY-PASSWORD' => 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX'}
response_hash = parse_response(response)
@signup.payson_params = response_hash
@signup.payson_status = response_hash['responseEnvelope.status']
@signup.save!
if @signup.payson_status == Payment::PaysonClient::COMPLETED
  confirm_signup
else
  @signup.fail!
  ErrorNotifier.deliver_notification("Payment failed with status #{@signup.payson_status} for signup #{@signup.inspect}")
end
You can check the reference for pay details request here.

1 comment:

Christopher said...

I have just finished writing a gem that can handle all communication with the Payson API. Check it out at Github: https://github.com/stoffus/payson_api