Skip to content
This repository has been archived by the owner on May 27, 2021. It is now read-only.

Commit

Permalink
Merge pull request activemerchant#920 from Shopify/payu_checksum
Browse files Browse the repository at this point in the history
Payu(Paisa) refactor
  • Loading branch information
odorcicd committed Dec 4, 2013
2 parents 6a0df1a + 6f54aec commit 86cb6cf
Show file tree
Hide file tree
Showing 16 changed files with 96 additions and 104 deletions.
11 changes: 2 additions & 9 deletions lib/active_merchant/billing/integrations/payu_in.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,8 @@ def self.return(post, options = {})
Return.new(post, options)
end

def self.checksum(merchant_id, secret_key, *payload_items )
options = payload_items.pop if Hash === payload_items.last
options ||= {}
payload = if options[:reverse] then
payload_items.dup.push( merchant_id || "" ).unshift( secret_key || "" ).collect{ |x| x.to_s }.join("|")
else
payload_items.dup.unshift( merchant_id || "" ).push( secret_key || "" ).collect{ |x| x.to_s }.join("|")
end
Digest::SHA512.hexdigest( payload )
def self.checksum(merchant_id, secret_key, payload_items )
Digest::SHA512.hexdigest([merchant_id, *payload_items, secret_key].join("|"))
end
end
end
Expand Down
28 changes: 15 additions & 13 deletions lib/active_merchant/billing/integrations/payu_in/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ module Integrations #:nodoc:
module PayuIn
class Helper < ActiveMerchant::Billing::Integrations::Helper

CHECKSUM_FIELDS = [ 'txnid', 'amount', 'productinfo', 'firstname', 'email', 'udf1', 'udf2', 'udf3', 'udf4',
'udf5', 'udf6', 'udf7', 'udf8', 'udf9', 'udf10']

mapping :amount, 'amount'
mapping :account, 'key'
mapping :order, 'txnid'
mapping :credential2, 'productinfo'
mapping :description, 'productinfo'

mapping :customer, :first_name => 'firstname',
:last_name => 'lastname',
Expand Down Expand Up @@ -44,26 +47,25 @@ class Helper < ActiveMerchant::Billing::Integrations::Helper

def initialize(order, account, options = {})
super
@options = options
self.pg = 'CC'
end

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

def generate_checksum( options = {} )
checksum_fields = [ :order, :amount, :credential2, { :customer => [ :first_name, :email ] },
{ :user_defined => [ :var1, :var2, :var3, :var4, :var5, :var6, :var7, :var8, :var9, :var10 ] } ]
checksum_payload_items = checksum_fields.inject( [] ) do | items, field |
if Hash === field then
key = field.keys.first
field[key].inject( items ){ |s,x| items.push( @fields[ mappings[key][x] ] ) }
else
items.push( @fields[ mappings[field] ] )
end
def generate_checksum
checksum_payload_items = CHECKSUM_FIELDS.map { |field| @fields[field] }

PayuIn.checksum(@fields["key"], @options[:credential2], checksum_payload_items )
end

def sanitize_fields
['address1', 'address2', 'city', 'state', 'country', 'productinfo', 'email', 'phone'].each do |field|
@fields[field].gsub!(/[^a-zA-Z0-9\-_@\/\s.]/, '') if @fields[field]
end
checksum_payload_items.push( options )
PayuIn.checksum(@fields["key"], @fields["productinfo"], *checksum_payload_items )
end

end
Expand Down
29 changes: 9 additions & 20 deletions lib/active_merchant/billing/integrations/payu_in/notification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,10 @@ def complete?
end

def status
@status ||= if checksum_ok?
if transaction_id.blank?
'Invalid'
else
case transaction_status.downcase
when 'success' then 'Completed'
when 'failure' then 'Failed'
when 'pending' then 'Pending'
end
end
else
'Tampered'
case transaction_status.downcase
when 'success' then 'Completed'
when 'failure' then 'Failed'
when 'pending' then 'Pending'
end
end

Expand All @@ -36,7 +28,7 @@ def invoice_ok?( order_id )

# Order amount should be equal to gross - discount
def amount_ok?( order_amount, order_discount = BigDecimal.new( '0.0' ) )
BigDecimal.new( gross ) == order_amount && BigDecimal.new( discount ) == order_discount
BigDecimal.new( gross ) == order_amount && BigDecimal.new( discount.to_s ) == order_discount
end

# Status of transaction return from the PayU. List of possible values:
Expand Down Expand Up @@ -129,10 +121,7 @@ def customer_address
end

def user_defined
return @user_defined if @user_defined
@user_defined = []
10.times{ |i| @user_defined.push( params[ "udf#{i+1}" ] ) }
@user_defined
@user_defined ||= 10.times.map { |i| params["udf#{i + 1}"] }
end

def checksum
Expand All @@ -148,9 +137,9 @@ def acknowledge(authcode = nil)
end

def checksum_ok?
fields = user_defined.dup.push( customer_email, customer_first_name, product_info, gross, invoice, :reverse => true )
fields.unshift( transaction_status )
unless PayuIn.checksum(@merchant_id, @secret_key, *fields ) == checksum
checksum_fields = [transaction_status, *user_defined.reverse, customer_email, customer_first_name, product_info, gross, invoice]

unless Digest::SHA512.hexdigest([@secret_key, *checksum_fields, @merchant_id].join("|")) == checksum
@message = 'Return checksum not matching the data provided'
return false
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class Helper < PayuIn::Helper
mapping :service_provider, 'service_provider'

def initialize(order, account, options = {})
super order, account, options
super
self.service_provider = 'payu_paisa'
self.user_defined = { :var2 => order }
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,6 @@ class Notification < PayuIn::Notification
def item_id
params['udf2']
end

def checksum_ok?
fields = user_defined.reverse.push( customer_email, customer_first_name, product_info, gross, invoice, :reverse => true )
fields.unshift( transaction_status )
unless PayuIn.checksum(@merchant_id, @secret_key, *fields ) == checksum
@message = 'Return checksum not matching the data provided'
return false
end
true
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ module PayuInPaisa

class Return < PayuIn::Return
def initialize(query_string, options = {})
super query_string, options
super
@notification = Notification.new(query_string, options)
end
end
Expand Down
4 changes: 4 additions & 0 deletions test/fixtures.yml
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,10 @@ paypal_signature:
password: PASSWORD
signature: SIGNATURE

payu_in:
login: C0Dr8m
secret: 3sf0jURk

payway:
username:
password:
Expand Down
4 changes: 2 additions & 2 deletions test/remote/integrations/remote_payu_in_integration_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class RemotePayuInIntegrationTest < Test::Unit::TestCase
include ActiveMerchant::Billing::Integrations

def setup
@payu_in = PayuIn::Notification.new(http_raw_data, :credential1 => 'C0Dr8m', :credential2 => '3sf0jURk')
@payu_in = PayuIn::Notification.new(http_raw_data, :credential1 => 'merchant_id', :credential2 => 'secret')
end

def test_raw
Expand All @@ -21,6 +21,6 @@ def test_raw

private
def http_raw_data
"mihpayid=403993715508030204&mode=CC&status=success&unmappedstatus=captured&key=C0Dr8m&txnid=4ba4afe87f7e73468f2a&amount=10.00&discount=0.00&addedon=2013-05-10 18 32 30&productinfo=Product Info&firstname=Payu-Admin&lastname=&address1=&address2=&city=&state=&country=&zipcode=&[email protected]&phone=1234567890&udf1=&udf2=&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=ef0c1b509a42b802a4938c25dc9bb9efe40b75a7dfb8bde1a6f126fa1f86cee264c5e5a17e87db85150d6d8912eafda838416e669712f1989dcb9cbdb8c24219&field1=313069903923&field2=999999&field3=59117331831301&field4=-1&field5=&field6=&field7=&field8=&PG_TYPE=HDFC&bank_ref_num=59117331831301&bankcode=CC&error=E000&cardnum=512345XXXXXX2346&cardhash=766f0227cc4b4c5f773a04cb31d8d1c5be071dd8d08fe365ecf5e2e5c947546d"
"mihpayid=403993715508030204&mode=CC&status=success&unmappedstatus=captured&key=merchant_id&txnid=4ba4afe87f7e73468f2a&amount=10.00&discount=0.00&addedon=2013-05-10 18 32 30&productinfo=Product Info&firstname=Payu-Admin&lastname=&address1=&address2=&city=&state=&country=&zipcode=&[email protected]&phone=1234567890&udf1=&udf2=&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=ef0c1b509a42b802a4938c25dc9bb9efe40b75a7dfb8bde1a6f126fa1f86cee264c5e5a17e87db85150d6d8912eafda838416e669712f1989dcb9cbdb8c24219&field1=313069903923&field2=999999&field3=59117331831301&field4=-1&field5=&field6=&field7=&field8=&PG_TYPE=HDFC&bank_ref_num=59117331831301&bankcode=CC&error=E000&cardnum=512345XXXXXX2346&cardhash=766f0227cc4b4c5f773a04cb31d8d1c5be071dd8d08fe365ecf5e2e5c947546d"
end
end
20 changes: 14 additions & 6 deletions test/unit/integrations/helpers/payu_in_helper_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ class PayuInHelperTest < Test::Unit::TestCase
include ActiveMerchant::Billing::Integrations

def setup
@helper = PayuIn::Helper.new( 'jh34h53kj4h5hj34kh5', 'C0Dr8m', :amount => '10.00', :credential2 => 'Product Info')
@helper = PayuIn::Helper.new( 'order_id', 'merchant_id', :amount => '10.00', :credential2 => 'secret_key')
end

def test_basic_helper_fields
assert_equal '10.00', @helper.fields['amount']
assert_equal 'C0Dr8m', @helper.fields['key']
assert_equal 'jh34h53kj4h5hj34kh5', @helper.fields['txnid']
assert_equal 'Product Info', @helper.fields['productinfo']
assert_equal 'merchant_id', @helper.fields['key']
assert_equal 'order_id', @helper.fields['txnid']
end

def test_customer_fields
Expand Down Expand Up @@ -56,11 +55,20 @@ def test_user_defined_fields
end

def test_add_checksum_method
options = { :mode => 'CC' }
@helper.customer :first_name => 'Payu-Admin', :email => '[email protected]'
@helper.description "Product Info"
@helper.user_defined :var1 => 'var_one', :var2 => 'var_two', :var3 => 'var_three', :var4 => 'var_four', :var5 => 'var_five', :var6 => 'var_six', :var7 => 'var_seven', :var8 => 'var_eight', :var9 => 'var_nine', :var10 => 'var_ten'

assert_equal "032606d7fb5cfe357d9e6b358b4bb8db1d34e9dfa30f039cb7dec75ae6d77f7d1f67a58c123ea0ee358bf040554d5e3048066a369ae63888132e27c14e79ee5a", @helper.form_fields["hash"]
fields = ["txnid", "amount", "productinfo", "firstname", "email", "udf1", "udf2", "udf3", "udf4", "udf5", "udf6", "udf7", "udf8", "udf9", "udf10"].map { |field| @helper.fields[field] }
assert_equal Digest::SHA512.hexdigest(['merchant_id', *fields, 'secret_key'].join("|")), @helper.form_fields["hash"]
end

def test_sanitize_fields_in_form_fields
@helper.description '{[Valid Description!]}'
@helper.form_fields

assert_equal 'Valid Description', @helper.fields['productinfo']
assert_nil @helper.fields['email']
end

end
13 changes: 7 additions & 6 deletions test/unit/integrations/helpers/payu_in_paisa_helper_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ class PayuInPaisaHelperTest < Test::Unit::TestCase
include ActiveMerchant::Billing::Integrations

def setup
@helper = PayuInPaisa::Helper.new( 'jh34h53kj4h5hj34kh5', 'C0Dr8m', :amount => '10.00', :credential2 => 'Product Info')
@helper = PayuInPaisa::Helper.new( 'order_id', 'merchant_id', :amount => '10.00', :credential2 => 'secret')
end

def test_basic_helper_fields
assert_equal '10.00', @helper.fields['amount']
assert_equal 'C0Dr8m', @helper.fields['key']
assert_equal 'jh34h53kj4h5hj34kh5', @helper.fields['txnid']
assert_equal 'Product Info', @helper.fields['productinfo']
assert_equal 'merchant_id', @helper.fields['key']
assert_equal 'order_id', @helper.fields['txnid']
end

def test_customer_fields
Expand Down Expand Up @@ -56,10 +55,12 @@ def test_user_defined_fields
end

def test_add_checksum_method
options = { :mode => 'CC' }
@helper.customer :first_name => 'Payu-Admin', :email => '[email protected]'
@helper.user_defined :var1 => 'var_one', :var2 => 'var_two', :var3 => 'var_three', :var4 => 'var_four', :var5 => 'var_five', :var6 => 'var_six', :var7 => 'var_seven', :var8 => 'var_eight', :var9 => 'var_nine', :var10 => 'var_ten'
@helper.description 'Product Info'

assert_equal "032606d7fb5cfe357d9e6b358b4bb8db1d34e9dfa30f039cb7dec75ae6d77f7d1f67a58c123ea0ee358bf040554d5e3048066a369ae63888132e27c14e79ee5a", @helper.form_fields["hash"]
payload = 'merchant_id|order_id|10.00|Product Info|Payu-Admin|[email protected]|var_one|var_two|var_three|var_four|var_five|var_six|var_seven|var_eight|var_nine|var_ten|secret'
checksum = Digest::SHA512.hexdigest(payload)
assert_equal checksum, @helper.form_fields["hash"]
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class PayuInNotificationTest < Test::Unit::TestCase
include ActiveMerchant::Billing::Integrations

def setup
@payu = PayuIn::Notification.new(http_raw_data, :credential1 => 'C0Dr8m', :credential2 => '3sf0jURk')
@payu = PayuIn::Notification.new(http_raw_data, :credential1 => 'merchant_id', :credential2 => 'secret')
end

def test_accessors
Expand All @@ -19,13 +19,13 @@ def test_accessors
assert_equal true, @payu.amount_ok?(BigDecimal.new('10.00'),BigDecimal.new('0.00'))
assert_equal "CC", @payu.type
assert_equal "4ba4afe87f7e73468f2a", @payu.invoice
assert_equal "C0Dr8m", @payu.account
assert_equal "merchant_id", @payu.account
assert_equal "0.00", @payu.discount
assert_equal "[email protected]", @payu.customer_email
assert_equal "1234567890", @payu.customer_phone
assert_equal "Payu-Admin", @payu.customer_first_name
assert_equal "", @payu.customer_last_name
assert_equal "ef0c1b509a42b802a4938c25dc9bb9efe40b75a7dfb8bde1a6f126fa1f86cee264c5e5a17e87db85150d6d8912eafda838416e669712f1989dcb9cbdb8c24219", @payu.checksum
assert_equal "d6a5544072d036dc422d1c6393a8da75233d5e30ffc848f11682f121d67cd80c0d4fed1067b99918b5a377b7dcf1c8c9c79975abdf9f444692b35bf34d494105", @payu.checksum
assert_equal "E000", @payu.message
assert_equal true, @payu.checksum_ok?
end
Expand All @@ -38,12 +38,8 @@ def test_acknowledgement
assert @payu.acknowledge
end

def test_respond_to_acknowledge
assert @payu.respond_to?(:acknowledge)
end

private
def http_raw_data
"mihpayid=403993715508030204&mode=CC&status=success&unmappedstatus=captured&key=C0Dr8m&txnid=4ba4afe87f7e73468f2a&amount=10.00&discount=0.00&addedon=2013-05-10 18 32 30&productinfo=Product Info&firstname=Payu-Admin&lastname=&address1=&address2=&city=&state=&country=&zipcode=&[email protected]&phone=1234567890&udf1=&udf2=&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=ef0c1b509a42b802a4938c25dc9bb9efe40b75a7dfb8bde1a6f126fa1f86cee264c5e5a17e87db85150d6d8912eafda838416e669712f1989dcb9cbdb8c24219&field1=313069903923&field2=999999&field3=59117331831301&field4=-1&field5=&field6=&field7=&field8=&PG_TYPE=HDFC&bank_ref_num=59117331831301&bankcode=CC&error=E000&cardnum=512345XXXXXX2346&cardhash=766f0227cc4b4c5f773a04cb31d8d1c5be071dd8d08fe365ecf5e2e5c947546d"
"mihpayid=403993715508030204&mode=CC&status=success&unmappedstatus=captured&key=merchant_id&txnid=4ba4afe87f7e73468f2a&amount=10.00&discount=0.00&addedon=2013-05-10 18 32 30&productinfo=Product Info&firstname=Payu-Admin&lastname=&address1=&address2=&city=&state=&country=&zipcode=&[email protected]&phone=1234567890&udf1=&udf2=&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=d6a5544072d036dc422d1c6393a8da75233d5e30ffc848f11682f121d67cd80c0d4fed1067b99918b5a377b7dcf1c8c9c79975abdf9f444692b35bf34d494105&field1=313069903923&field2=999999&field3=59117331831301&field4=-1&field5=&field6=&field7=&field8=&PG_TYPE=HDFC&bank_ref_num=59117331831301&bankcode=CC&error=E000&cardnum=512345XXXXXX2346&cardhash=766f0227cc4b4c5f773a04cb31d8d1c5be071dd8d08fe365ecf5e2e5c947546d"
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class PayuInPaisaNotificationTest < Test::Unit::TestCase
include ActiveMerchant::Billing::Integrations

def setup
@payu = PayuInPaisa::Notification.new(http_raw_data, :credential1 => 'C0Dr8m', :credential2 => '3sf0jURk')
@payu = PayuInPaisa::Notification.new(http_raw_data, :credential1 => 'merchant_id', :credential2 => 'secret')
end

def test_accessors
Expand All @@ -19,13 +19,13 @@ def test_accessors
assert_equal true, @payu.amount_ok?(BigDecimal.new('10.00'),BigDecimal.new('0.00'))
assert_equal "CC", @payu.type
assert_equal "4ba4afe87f7e73468f2a", @payu.invoice
assert_equal "C0Dr8m", @payu.account
assert_equal "merchant_id", @payu.account
assert_equal "0.00", @payu.discount
assert_equal "[email protected]", @payu.customer_email
assert_equal "1234567890", @payu.customer_phone
assert_equal "Payu-Admin", @payu.customer_first_name
assert_equal "", @payu.customer_last_name
assert_equal "e35f67dc7232d12caa28b16ba31b509f62bdea1e930bb6766a4f71036cc1af34debb8afc0fdd89be50f0604c1e6bca7209dfffe6b3a893c575492edcab3444ee", @payu.checksum
assert_equal checksum, @payu.checksum
assert_equal "E000", @payu.message
assert_equal true, @payu.checksum_ok?
end
Expand All @@ -38,16 +38,16 @@ def test_acknowledgement
assert @payu.acknowledge
end

def test_respond_to_acknowledge
assert @payu.respond_to?(:acknowledge)
end

def test_item_id_gives_the_original_item_id
assert 'original_item_id', @payu.item_id
end

private
def http_raw_data
"mihpayid=403993715508030204&mode=CC&status=success&unmappedstatus=captured&key=C0Dr8m&txnid=4ba4afe87f7e73468f2a&amount=10.00&discount=0.00&addedon=2013-05-10 18 32 30&productinfo=Product Info&firstname=Payu-Admin&lastname=&address1=&address2=&city=&state=&country=&zipcode=&[email protected]&phone=1234567890&udf1=&udf2=original_item_id&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=e35f67dc7232d12caa28b16ba31b509f62bdea1e930bb6766a4f71036cc1af34debb8afc0fdd89be50f0604c1e6bca7209dfffe6b3a893c575492edcab3444ee&field1=313069903923&field2=999999&field3=59117331831301&field4=-1&field5=&field6=&field7=&field8=&PG_TYPE=HDFC&bank_ref_num=59117331831301&bankcode=CC&error=E000&cardnum=512345XXXXXX2346&cardhash=766f0227cc4b4c5f773a04cb31d8d1c5be071dd8d08fe365ecf5e2e5c947546d"
"mihpayid=403993715508030204&mode=CC&status=success&unmappedstatus=captured&key=merchant_id&txnid=4ba4afe87f7e73468f2a&amount=10.00&discount=0.00&addedon=2013-05-10 18 32 30&productinfo=Product Info&firstname=Payu-Admin&lastname=&address1=&address2=&city=&state=&country=&zipcode=&[email protected]&phone=1234567890&udf1=&udf2=original_item_id&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=#{checksum}&field1=313069903923&field2=999999&field3=59117331831301&field4=-1&field5=&field6=&field7=&field8=&PG_TYPE=HDFC&bank_ref_num=59117331831301&bankcode=CC&error=E000&cardnum=512345XXXXXX2346&cardhash=766f0227cc4b4c5f773a04cb31d8d1c5be071dd8d08fe365ecf5e2e5c947546d"
end

def checksum
Digest::SHA512.hexdigest("secret|success|||||||||original_item_id||[email protected]|Payu-Admin|Product Info|10.00|4ba4afe87f7e73468f2a|merchant_id")
end
end
9 changes: 5 additions & 4 deletions test/unit/integrations/payu_in_module_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ class PayuInModuleTest < Test::Unit::TestCase

def setup
ActiveMerchant::Billing::Base.integration_mode = :test
@merchant_id = 'C0Dr8m'
@secret_key = '3sf0jURk'
@merchant_id = 'merchant_id'
@secret_key = 'secret'
end

def test_service_url_method
Expand All @@ -26,7 +26,8 @@ def test_notification_method
end

def test_checksum_method
payu_load = "4ba4afe87f7e73468f2a|10.00|Product Info|Payu-Admin|[email protected]||||||||||"
assert_equal "cd324f64891b07d95492a2fd80ae469092e302faa3d3df5ba1b829936fd7497b6e89c3e48fd70e2a131cdd4f17d14bc20f292e9408650c085bc3bedb32f44266", PayuIn.checksum(@merchant_id, @secret_key, payu_load)
payu_load = "order_id|10.00|Product Info|Payu-Admin|[email protected]||||||||||"
checksum = Digest::SHA512.hexdigest([@merchant_id, payu_load, @secret_key].join("|"))
assert_equal checksum, PayuIn.checksum(@merchant_id, @secret_key, payu_load.split("|", -1))
end
end
Loading

0 comments on commit 86cb6cf

Please sign in to comment.