Skip to content

Commit

Permalink
Add Citrus gateway
Browse files Browse the repository at this point in the history
  • Loading branch information
viatechs authored and Caleb Simpson committed Sep 23, 2013
1 parent ebc41ca commit ad75bcf
Show file tree
Hide file tree
Showing 8 changed files with 525 additions and 0 deletions.
55 changes: 55 additions & 0 deletions lib/active_merchant/billing/integrations/citrus.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
module Integrations #:nodoc:
module Citrus
autoload :Helper, File.dirname(__FILE__) + '/citrus/helper.rb'
autoload :Notification, File.dirname(__FILE__) + '/citrus/notification.rb'
autoload :Return, File.dirname(__FILE__) + '/citrus/return.rb'

mattr_accessor :sandbox_url
mattr_accessor :staging_url
mattr_accessor :production_url
mattr_accessor :pmt_url


self.sandbox_url = 'https://sandbox.citruspay.com/'
self.staging_url = 'https://stg.citruspay.com/'
self.production_url = 'https://www.citruspay.com/'


def self.service_url
mode = ActiveMerchant::Billing::Base.integration_mode
case mode
when :production
self.production_url + self.pmt_url
when :test
self.sandbox_url + self.pmt_url
when :staging
self.staging_url + self.pmt_url
else
raise StandardError, "Integration mode set to an invalid value: #{mode}"
end
end

def self.helper(order, account, options = {})
Helper.new(order, account, options)
end

def self.notification(post, options = {})
Notification.new(post)
end

def self.return(query_string, options = {})
Return.new(query_string)
end

def self.checksum(secret_key, payload_items )
digest = OpenSSL::Digest::Digest.new('sha1')
sig=OpenSSL::HMAC.hexdigest(digest, secret_key, payload_items)
return sig
end

end
end
end
end
42 changes: 42 additions & 0 deletions lib/active_merchant/billing/integrations/citrus/helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
module Integrations #:nodoc:
module Citrus
class Helper < ActiveMerchant::Billing::Integrations::Helper

mapping :order, 'merchantTxnId'
mapping :amount, 'orderAmount'
mapping :account, 'merchantAccessKey'
mapping :credential2, 'secret_key'
mapping :credential3, 'pmt_url'
mapping :currency, 'currency'

mapping :customer, :first_name => 'firstName',:last_name => 'lastName', :email => 'email', :phone => 'mobileNo'

mapping :billing_address, :city => 'addressCity', :address1 => 'addressStreet1', :address2 => 'addressStreet2',:state => 'addressState',:zip => 'addressZip', :country => 'addressCountry'

mapping :checksum, 'secSignature'
mapping :return_url, 'returnUrl'


def initialize(order, account, options = {})
super
add_field 'paymentMode', 'NET_BANKING'
add_field 'reqtime', (Time.now.to_i * 1000).to_s
end

def form_fields
@fields.merge(mappings[:checksum] => generate_checksum)
end

def generate_checksum()
checksum_fields = @fields["pmt_url"] + @fields["orderAmount"].to_s + @fields["merchantTxnId"] + @fields["currency"]
Citrus.checksum(@fields["secret_key"], checksum_fields )
end

end

end
end
end
end
145 changes: 145 additions & 0 deletions lib/active_merchant/billing/integrations/citrus/notification.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
module Integrations #:nodoc:
module Citrus
class Notification < ActiveMerchant::Billing::Integrations::Notification

def initialize(post, options = {})
super(post, options)
@secret_key = options[:credential2]
end

def complete?
status == "success" || status == 'canceled'
end

# Status of the transaction. List of possible values:
# <tt>invalid</tt>:: transaction id is not present
# <tt>tampered</tt>:: transaction data has been tampered
# <tt>success</tt>:: transaction successful
# <tt>canceled</tt>:: transaction is pending for some approval
def status
@status ||= if checksum_ok?
if transaction_id.blank?
'invalid'
else
transaction_status.downcase
end
else
'tampered'
end
end

def invoice_ok?( order_id )
order_id.to_s == invoice.to_s
end

# Order amount should be equal to gross - discount
def amount_ok?( order_amount )
BigDecimal.new( amount ) == order_amount
end

# capture Citrus response parameters

# This is the invoice which you passed to Citrus
def invoice
params['TxId']
end

# Status of transaction return from the Citrus. List of possible values:
# <tt>SUCCESS</tt>::
# <tt>CANCELED</tt>::
def transaction_status
params['TxStatus']
end

# amount paid by customer
def amount
params['amount']
end

# ID of this transaction returned by Citrus
def transaction_id
params['pgTxnNo']
end

# for future use
def issuerrefno
params['issuerRefNo']
end

# authorization code by Citrus
def authidcode
params['authIdCode']
end

# gateway resp code by Citrus
def pgrespcode
params['pgRespCode']
end

# by Citrus
def checksum
params['signature']
end

def paymentmode
params['paymentMode']
end

# payment currency
def currency
params['currency']
end


# Email of the customer
def customer_email
params['email']
end

# Phone of the customer
def customer_phone
params['mobileNo']
end

# Firstname of the customer
def customer_first_name
params['firstName']
end

# Lastname of the customer
def customer_last_name
params['lastName']
end

# Full address of the customer
def customer_address
{ :address1 => params['addressStreet1'], :address2 => params['addressStreet2'],
:city => params['addressCity'], :state => params['addressState'],
:country => params['addressCountry'], :zip => params['addressZip'] }
end


def message
@message || params['TxMsg']
end

def acknowledge
checksum_ok?
end

def checksum_ok?
fields = invoice + transaction_status + amount.to_s + transaction_id + issuerrefno + authidcode + customer_first_name + customer_last_name + pgrespcode + customer_address[:zip]

unless Citrus.checksum(@secret_key, fields ) == checksum
@message = 'checksum mismatch...'
return false
end
true
end
end
end
end
end
end
40 changes: 40 additions & 0 deletions lib/active_merchant/billing/integrations/citrus/return.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
module Integrations #:nodoc:
module Citrus
class Return < ActiveMerchant::Billing::Integrations::Return

def initialize(query_string, options = {})
super
@notification = Notification.new(query_string, options)
end

# Citrus Transaction Id
#
def transaction_id
@notification.transaction_id
end

def status( order_id, order_amount )
if @notification.invoice_ok?( order_id ) && @notification.amount_ok?( BigDecimal.new(order_amount) )
@notification.status
else
'mismatch'
end
end

# check success of the transaction
# check order_id and
def success?
status( @params['TxId'], @params['amount'] ) == 'success'
end

def message
@notification.message
end

end
end
end
end
end
44 changes: 44 additions & 0 deletions test/unit/integrations/citrus_module_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
require 'test_helper'

class CitrusModuleTest < Test::Unit::TestCase
include ActiveMerchant::Billing::Integrations

def setup
ActiveMerchant::Billing::Base.integration_mode = :test
@access_key = 'G0JW45KCS3630NX335YX'
@secret_key = '2c71a4ea7d2b88e151e60d9da38b2d4552568ba9'
@pmt_url = 'gqwnliur74'
end

def test_service_url_method
Citrus.pmt_url=@pmt_url
ActiveMerchant::Billing::Base.integration_mode = :test
assert_equal 'https://sandbox.citruspay.com/gqwnliur74', Citrus.service_url
p Citrus.service_url
end

def test_production_service_url_method
Citrus.pmt_url=@pmt_url
ActiveMerchant::Billing::Base.integration_mode = :production
assert_equal 'https://www.citruspay.com/gqwnliur74', Citrus.service_url
p Citrus.service_url
end

def test_helper_method
assert_instance_of Citrus::Helper, Citrus.helper('ORD01','G0JW45KCS3630NX335YX', :amount => 10.0, :currency => 'USD', :credential2 => '2c71a4ea7d2b88e151e60d9da38b2d4552568ba9', :credential3 => 'gqwnliur74')
end

def test_return_method
assert_instance_of Citrus::Return, Citrus.return('name=foo', {})
end

def test_notification_method
assert_instance_of Citrus::Notification, Citrus.notification('name=cody')
end

def test_checksum_method
payu_load = @pmt_url+"10"+"ORD123"+"USD"
assert_equal "ecf7eaafec270b9b91b898e7f8e794c30245eb7f", Citrus.checksum(@secret_key, payu_load)
end

end
Loading

0 comments on commit ad75bcf

Please sign in to comment.