From 19e8ed152b8344932fd6def1a4a4707e462e3b4e Mon Sep 17 00:00:00 2001 From: Dennis Theisen Date: Wed, 28 Jul 2010 12:25:34 -0400 Subject: [PATCH] Add support for DirecPay Gateway --- .../billing/integrations/direc_pay.rb | 37 +++ .../billing/integrations/direc_pay/helper.rb | 188 ++++++++++++++ .../integrations/direc_pay/notification.rb | 76 ++++++ .../billing/integrations/direc_pay/return.rb | 32 +++ .../billing/integrations/direc_pay/status.rb | 37 +++ test/fixtures.yml | 3 +- .../remote_direc_pay_integration_test.rb | 22 ++ .../integrations/direc_pay_module_test.rb | 9 + .../helpers/direc_pay_helper_test.rb | 240 ++++++++++++++++++ .../direc_pay_notification_test.rb | 69 +++++ .../returns/direc_pay_return_test.rb | 54 ++++ 11 files changed, 766 insertions(+), 1 deletion(-) create mode 100644 lib/active_merchant/billing/integrations/direc_pay.rb create mode 100644 lib/active_merchant/billing/integrations/direc_pay/helper.rb create mode 100644 lib/active_merchant/billing/integrations/direc_pay/notification.rb create mode 100644 lib/active_merchant/billing/integrations/direc_pay/return.rb create mode 100644 lib/active_merchant/billing/integrations/direc_pay/status.rb create mode 100644 test/remote/integrations/remote_direc_pay_integration_test.rb create mode 100644 test/unit/integrations/direc_pay_module_test.rb create mode 100644 test/unit/integrations/helpers/direc_pay_helper_test.rb create mode 100644 test/unit/integrations/notifications/direc_pay_notification_test.rb create mode 100644 test/unit/integrations/returns/direc_pay_return_test.rb diff --git a/lib/active_merchant/billing/integrations/direc_pay.rb b/lib/active_merchant/billing/integrations/direc_pay.rb new file mode 100644 index 00000000000..db28fd0a824 --- /dev/null +++ b/lib/active_merchant/billing/integrations/direc_pay.rb @@ -0,0 +1,37 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module DirecPay + autoload :Helper, File.dirname(__FILE__) + '/direc_pay/helper.rb' + autoload :Return, File.dirname(__FILE__) + '/direc_pay/return.rb' + autoload :Notification, File.dirname(__FILE__) + '/direc_pay/notification.rb' + autoload :Status, File.dirname(__FILE__) + '/direc_pay/status.rb' + + mattr_accessor :production_url, :test_url + + self.production_url = "https://www.timesofmoney.com/direcpay/secure/dpMerchantTransaction.jsp" + self.test_url = "https://test.timesofmoney.com/direcpay/secure/dpMerchantTransaction.jsp" + + def self.service_url + mode = ActiveMerchant::Billing::Base.integration_mode + case mode + when :production + self.production_url + when :test + self.test_url + else + raise StandardError, "Integration mode set to an invalid value: #{mode}" + end + end + + def self.notification(post) + Notification.new(post) + end + + def self.return(query_string) + Return.new(query_string) + end + end + end + end +end diff --git a/lib/active_merchant/billing/integrations/direc_pay/helper.rb b/lib/active_merchant/billing/integrations/direc_pay/helper.rb new file mode 100644 index 00000000000..b20b107a035 --- /dev/null +++ b/lib/active_merchant/billing/integrations/direc_pay/helper.rb @@ -0,0 +1,188 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module DirecPay + class Helper < ActiveMerchant::Billing::Integrations::Helper + mapping :account, 'MID' + mapping :order, 'Merchant Order No' + mapping :amount, 'Amount' + mapping :currency, 'Currency' + mapping :country, 'Country' + + mapping :billing_address, :city => 'custCity', + :address1 => 'custAddress', + :state => 'custState', + :zip => 'custPinCode', + :country => 'custCountry', + :phone2 => 'custMobileNo' + + mapping :shipping_address, :name => 'deliveryName', + :city => 'deliveryCity', + :address1 => 'deliveryAddress', + :state => 'deliveryState', + :zip => 'deliveryPinCode', + :country => 'deliveryCountry', + :phone2 => 'deliveryMobileNo' + + mapping :customer, :name => 'custName', + :email => 'custEmailId' + + mapping :description, 'otherNotes' + mapping :edit_allowed, 'editAllowed' + + mapping :return_url, 'Success URL' + mapping :failure_url, 'Failure URL' + + mapping :operating_mode, 'Operating Mode' + mapping :other_details, 'Other Details' + mapping :collaborator, 'Collaborator' + + OPERATING_MODE = 'DOM' + COUNTRY = 'IND' + CURRENCY = 'INR' + OTHER_DETAILS = 'NULL' + EDIT_ALLOWED = 'N' + + PHONE_CODES = { + 'IN' => '91', + 'US' => '01', + 'CA' => '01' + } + + ENCODED_PARAMS = [ :account, :operating_mode, :country, :currency, :amount, :order, :other_details, :return_url, :failure_url, :collaborator ] + + + def initialize(order, account, options = {}) + super + collaborator = ActiveMerchant::Billing::Base.integration_mode == :test || options[:test] ? 'TOML' : 'DirecPay' + add_field(mappings[:collaborator], collaborator) + add_field(mappings[:country], 'IND') + add_field(mappings[:operating_mode], OPERATING_MODE) + add_field(mappings[:other_details], OTHER_DETAILS) + add_field(mappings[:edit_allowed], EDIT_ALLOWED) + end + + + def customer(params = {}) + full_name = "#{params[:first_name]} #{params[:last_name]}" + add_field(mappings[:customer][:name], full_name) + add_field(mappings[:customer][:email], params[:email]) + end + + # Need to format the amount to have 2 decimal places + def amount=(money) + cents = money.respond_to?(:cents) ? money.cents : money + if money.is_a?(String) or cents.to_i <= 0 + raise ArgumentError, 'money amount must be either a Money object or a positive integer in cents.' + end + add_field(mappings[:amount], sprintf("%.2f", cents.to_f/100)) + end + + def shipping_address(params = {}) + add_street_address!(params) + super(params.dup) + add_field(mappings[:shipping_address][:name], fields[mappings[:customer][:name]]) if fields[mappings[:shipping_address][:name]].blank? + add_phone_for!(:shipping_address, params) + end + + def billing_address(params = {}) + add_street_address!(params) + super(params.dup) + add_phone_for!(:billing_address, params) + end + + def form_fields + add_failure_url + add_request_parameters + + unencoded_parameters + end + + + private + + def add_request_parameters + params = ENCODED_PARAMS.map{ |param| fields[mappings[param]] } + encoded = encode_value(params.join('|')) + + add_field('requestparameter', encoded) + end + + def unencoded_parameters + params = fields.dup + # remove all encoded params from exported fields + ENCODED_PARAMS.each{ |param| params.delete(mappings[param]) } + # remove all special characters from each field value + params = params.collect{|name, value| [name, remove_special_characters(value)] } + Hash[params] + end + + def add_failure_url + if fields[mappings[:failure_url]].nil? + add_field(mappings[:failure_url], fields[mappings[:return_url]]) + end + end + + def add_street_address!(params) + address = params[:address1] + address << " #{params[:address2]}" if params[:address2] + params.merge!(:address1 => address) + end + + def add_phone_for!(address_type, params) + address_field = address_type == :billing_address ? 'custPhoneNo' : 'deliveryPhNo' + + if params.has_key?(:phone) + country = fields[mappings[address_type][:country]] + phone = params[:phone].to_s + # Remove all non digits + phone.gsub!(/[^\d ]+/, '') + + phone_country_code, phone_area_code, phone_number = nil + + if country == 'IN' && phone =~ /(91)? *(\d{3}) *(\d{4,})$/ + phone_country_code, phone_area_code, phone_number = $1, $2, $3 + else + numbers = phone.split(' ') + case numbers.size + when 3 + phone_country_code, phone_area_code, phone_number = numbers + when 2 + phone_area_code, phone_number = numbers + else + phone =~ /(\d{3})(\d+)$/ + phone_area_code, phone_number = $1, $2 + end + end + + add_field("#{address_field}1", phone_country_code || phone_code_for_country(country) || '91') + add_field("#{address_field}2", phone_area_code) + add_field("#{address_field}3", phone_number) + end + end + + # Special characters are NOT allowed while posting transaction parameters on DirecPay system + def remove_special_characters(string) + string.gsub(/[~"'&#%]/, '-') + end + + def encode_value(value) + encoded = ActiveSupport::Base64.encode64s(value) + string_to_encode = encoded[0, 1] + "T" + encoded[1, encoded.length] + ActiveSupport::Base64.encode64s(string_to_encode) + end + + def decode_value(value) + decoded = ActiveSupport::Base64.decode64(value) + string_to_decode = decoded[0, 1] + decoded[2, decoded.length] + ActiveSupport::Base64.decode64(string_to_decode) + end + + def phone_code_for_country(country) + PHONE_CODES[country] + end + end + end + end + end +end diff --git a/lib/active_merchant/billing/integrations/direc_pay/notification.rb b/lib/active_merchant/billing/integrations/direc_pay/notification.rb new file mode 100644 index 00000000000..bf37e9ad140 --- /dev/null +++ b/lib/active_merchant/billing/integrations/direc_pay/notification.rb @@ -0,0 +1,76 @@ +require 'net/http' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module DirecPay + class Notification < ActiveMerchant::Billing::Integrations::Notification + RESPONSE_PARAMS = ['DirecPay Reference ID', 'Flag', 'Country', 'Currency', 'Other Details', 'Merchant Order No', 'Amount'] + + def acknowledge + true + end + + def complete? + status == 'Completed' || status == 'Pending' + end + + def status + case params['Flag'] + when 'SUCCESS' + 'Completed' + when 'PENDING' + 'Pending' + when 'FAIL' + 'Failed' + else + 'Error' + end + end + + def item_id + params['Merchant Order No'] + end + + def transaction_id + params['DirecPay Reference ID'] + end + + # the money amount we received in X.2 decimal + def gross + params['Amount'] + end + + def currency + params['Currency'] + end + + def country + params['Country'] + end + + def other_details + params['Other Details'] + end + + def test? + false + end + + # Take the posted data and move the relevant data into a hash + def parse(post) + super + + values = params['responseparams'].to_s.split('|') + response_params = values.size == 3 ? ['DirecPay Reference ID', 'Flag', 'Error message'] : RESPONSE_PARAMS + response_params.each_with_index do |name, index| + params[name] = values[index] + end + params + end + + end + end + end + end +end diff --git a/lib/active_merchant/billing/integrations/direc_pay/return.rb b/lib/active_merchant/billing/integrations/direc_pay/return.rb new file mode 100644 index 00000000000..2eb2497daeb --- /dev/null +++ b/lib/active_merchant/billing/integrations/direc_pay/return.rb @@ -0,0 +1,32 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + + module DirecPay + class Return < ActiveMerchant::Billing::Integrations::Return + + def initialize(post_data, options = {}) + @notification = Notification.new(treat_failure_as_pending(post_data), options) + end + + def success? + notification.complete? + end + + def message + notification.status + end + + + private + + # Work around the issue that the initial return from DirecPay is always either SUCCESS or FAIL, there is no PENDING + def treat_failure_as_pending(post_data) + post_data.sub(/FAIL/, 'PENDING') + end + end + end + + end + end +end diff --git a/lib/active_merchant/billing/integrations/direc_pay/status.rb b/lib/active_merchant/billing/integrations/direc_pay/status.rb new file mode 100644 index 00000000000..f54bd574aad --- /dev/null +++ b/lib/active_merchant/billing/integrations/direc_pay/status.rb @@ -0,0 +1,37 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module DirecPay + + class Status + include PostsData + + STATUS_TEST_URL = 'https://test.timesofmoney.com/direcpay/secure/dpPullMerchAtrnDtls.jsp' + STATUS_LIVE_URL = 'https://www.timesofmoney.com/direcpay/secure/dpPullMerchAtrnDtls.jsp' + + attr_reader :account, :options + + def initialize(account, options = {}) + @account, @options = account, options + end + + + # Use this method to manually request a status update to the provided notification_url + def update(authorization, notification_url) + url = test? ? STATUS_TEST_URL : STATUS_LIVE_URL + parameters = [ authorization, account, notification_url ] + data = PostData.new + data[:requestparams] = parameters.join('|') + + response = ssl_get("#{url}?#{data.to_post_data}") + end + + def test? + ActiveMerchant::Billing::Base.integration_mode == :test || options[:test] + end + + end + end + end + end +end diff --git a/test/fixtures.yml b/test/fixtures.yml index fe990f8a678..8ec83fab1f8 100644 --- a/test/fixtures.yml +++ b/test/fixtures.yml @@ -383,4 +383,5 @@ garanti: login: 'paymentuser' password: 'userpayment' - +direc_pay: + mid: 200904281000001 \ No newline at end of file diff --git a/test/remote/integrations/remote_direc_pay_integration_test.rb b/test/remote/integrations/remote_direc_pay_integration_test.rb new file mode 100644 index 00000000000..863b43cb708 --- /dev/null +++ b/test/remote/integrations/remote_direc_pay_integration_test.rb @@ -0,0 +1,22 @@ +require 'test_helper' + +class RemoteDirecPayIntegrationTest < Test::Unit::TestCase + include ActiveMerchant::Billing::Integrations + + def setup + @helper = DirecPay::Helper.new('#1234', fixtures(:direc_pay)[:mid], :amount => 500, :currency => 'INR') + @notification = DirecPay::Notification.new('test=dummy-value') + end + + def tear_down + ActiveMerchant::Billing::Base.integration_mode = :test + end + + def test_return_is_always_acknowledged + assert_equal "https://test.timesofmoney.com/direcpay/secure/dpMerchantTransaction.jsp", DirecPay.service_url + assert_nothing_raised do + assert_equal true, @notification.acknowledge + end + end + +end diff --git a/test/unit/integrations/direc_pay_module_test.rb b/test/unit/integrations/direc_pay_module_test.rb new file mode 100644 index 00000000000..be48ef5114b --- /dev/null +++ b/test/unit/integrations/direc_pay_module_test.rb @@ -0,0 +1,9 @@ +require 'test_helper' + +class DirecPayModuleTest < Test::Unit::TestCase + include ActiveMerchant::Billing::Integrations + + def test_notification_method + assert_instance_of DirecPay::Notification, DirecPay.notification('name=me') + end +end diff --git a/test/unit/integrations/helpers/direc_pay_helper_test.rb b/test/unit/integrations/helpers/direc_pay_helper_test.rb new file mode 100644 index 00000000000..8a2cc6ab887 --- /dev/null +++ b/test/unit/integrations/helpers/direc_pay_helper_test.rb @@ -0,0 +1,240 @@ +require 'test_helper' + +class DirecPayHelperTest < Test::Unit::TestCase + include ActiveMerchant::Billing::Integrations + + def setup + @helper = DirecPay::Helper.new('#1234', 'account id', :amount => 500, :currency => 'INR') + end + + def test_basic_helper_fields + assert_field 'MID', 'account id' + assert_field 'Merchant Order No', '#1234' + + assert_field 'Amount', '5.00' + assert_field 'Currency', 'INR' + assert_field 'Country', 'IND' + end + + def test_customer_fields + @helper.customer :first_name => 'Cody', :last_name => 'Fauser', :email => 'cody@example.com' + assert_field 'custName', 'Cody Fauser' + assert_field 'custEmailId', 'cody@example.com' + end + + def test_billing_address_mapping + @helper.billing_address :address1 => '1 My Street', + :address2 => 'apartment 8', + :city => 'Leeds', + :state => 'Yorkshire', + :zip => 'LS2 7EE', + :country => 'IN' + + assert_field 'custAddress', '1 My Street apartment 8' + assert_field 'custCity', 'Leeds' + assert_field 'custState', 'Yorkshire' + assert_field 'custPinCode', 'LS2 7EE' + assert_field 'custCountry', 'IN' + end + + def test_shipping_address_mapping + @helper.customer :first_name => 'Cody', :last_name => 'Fauser', :email => 'cody@example.com' + @helper.shipping_address :address1 => '1 My Street', + :address2 => 'apartment 8', + :city => 'Leeds', + :state => 'Yorkshire', + :zip => 'LS2 7EE', + :country => 'IN' + + assert_field 'deliveryAddress', '1 My Street apartment 8' + assert_field 'deliveryCity', 'Leeds' + assert_field 'deliveryState', 'Yorkshire' + assert_field 'deliveryPinCode', 'LS2 7EE' + assert_field 'deliveryCountry', 'IN' + assert_field 'deliveryName', 'Cody Fauser' + end + + def test_address_with_a_single_street_address_field + @helper.billing_address :address1 => "1 My Street" + @helper.shipping_address :address1 => "1 My Street" + assert_field "custAddress", "1 My Street" + assert_field "deliveryAddress", "1 My Street" + end + + def test_address_with_two_street_address_fields + @helper.billing_address :address1 => "1 My Street", :address2 => "Apt 3" + @helper.shipping_address :address1 => "1 My Street", :address2 => "Apt 3" + assert_field "custAddress", "1 My Street Apt 3" + assert_field "deliveryAddress", "1 My Street Apt 3" + end + + def test_phone_number_mapping_for_india + @helper.billing_address :phone => "+91 022 28000000", :country => 'IN' + + assert_field 'custPhoneNo1', '91' + assert_field 'custPhoneNo2', '022' + assert_field 'custPhoneNo3', '28000000' + end + + def test_phone_number_mapping_for_america + @helper.billing_address :phone => "6131234567", :country => 'CA' + + assert_field 'custPhoneNo1', '01' + assert_field 'custPhoneNo2', '613' + assert_field 'custPhoneNo3', '1234567' + end + + def test_phone_number_mapping_for_germany + @helper.billing_address :phone => "+49 2628 12345", :country => 'DE' + + assert_field 'custPhoneNo1', '49' + assert_field 'custPhoneNo2', '2628' + assert_field 'custPhoneNo3', '12345' + end + + def test_shipping_address_mapping + @helper.shipping_address :address1 => '2 My Street', + :address2 => 'apartment 8', + :city => 'Leeds', + :state => 'Yorkshire', + :zip => 'LS2 7EE', + :country => 'IN' + + assert_field 'deliveryAddress', '2 My Street apartment 8' + assert_field 'deliveryCity', 'Leeds' + assert_field 'deliveryState', 'Yorkshire' + assert_field 'deliveryPinCode', 'LS2 7EE' + assert_field 'deliveryCountry', 'IN' + end + + def test_unknown_mapping + assert_nothing_raised do + @helper.company_address :address => '500 Dwemthy Fox Road' + end + end + + def test_setting_invalid_address_field + fields = @helper.fields.dup + @helper.billing_address :street => 'My Street' + assert_equal fields, @helper.fields + end + + def test_add_request_parameters + fill_in_transaction_details!(@helper) + + transaction_params = ['account id', 'DOM', 'IND', 'INR', '5.00', "#1234", 'NULL', "http://localhost/return", "http://localhost/return", "TOML"] + @helper.expects(:encode_value).with(transaction_params.join('|')).returns("dummy encoded value").twice + + @helper.form_fields + @helper.send(:add_request_parameters) + assert_field 'requestparameter', "dummy encoded value" + end + + def test_parameters_do_not_contain_special_characters + @helper.customer :first_name => "Bob", :last_name => "B & Ob", :email => 'bob@example.com' + @helper.description "50% discount for bob's order" + + @helper.form_fields.each do |name, value| + assert_no_match %r/[~'"&#%]/, value + end + end + + + def test_exported_form_fields + fill_in_transaction_details!(@helper) + + exported_fields = [ + "custAddress", + "custCity", + "custCountry", + "custEmailId", + "custMobileNo", + "custName", + "custPhoneNo1", + "custPhoneNo2", + "custPhoneNo3", + "custPinCode", + "custState", + "deliveryAddress", + "deliveryCity", + "deliveryCountry", + "deliveryMobileNo", + "deliveryName", + "deliveryPhNo1", + "deliveryPhNo2", + "deliveryPhNo3", + "deliveryPinCode", + "deliveryState", + "editAllowed", + "otherNotes", + "requestparameter" + ] + assert_equal exported_fields, @helper.form_fields.keys.sort + end + + def test_encode_value + # outofdate_expected = 'TVRqQXdPVEEwTWpneE1EQXdNREF4ZkVSUFRYeEpUa1I4U1U1U2ZEVTRMakF3ZkRJeWZERjhhSFIwY0RvdkwyeHZZMkZzYUc5emREb3pNREF3TDI5eVpHVnljeTh4TDJWa05USXpNRFk1Tm1Ga05USTFZamxsTXpJeVlUWmhOalJpTlRZek1qSmxMMlJ2Ym1VL2RYUnRYMjV2YjNabGNuSnBaR1U5TVh4b2RIUndPaTh2YUdGeVpHTnZjbVZuWVcxbGNpNXNiMk5oYkdodmMzUTZNekF3TUh4VVQwMU0=' + expected = 'TVRqQXdPVEEwTWpneE1EQXdNREF4ZkVSUFRYeEpUa1I4U1U1U2ZEVTRMakF3ZkRJeWZFNVZURXg4YUhSMGNEb3ZMMnh2WTJGc2FHOXpkRG96TURBd0wyOXlaR1Z5Y3k4eEwyVmtOVEl6TURZNU5tRmtOVEkxWWpsbE16SXlZVFpoTmpSaU5UWXpNakpsTDJSdmJtVS9kWFJ0WDI1dmIzWmxjbkpwWkdVOU1YeG9kSFJ3T2k4dmFHRnlaR052Y21WbllXMWxjaTVzYjJOaGJHaHZjM1E2TXpBd01IeFVUMDFN' + decoded = '200904281000001|DOM|IND|INR|58.00|22|NULL|http://localhost:3000/orders/1/ed5230696ad525b9e322a6a64b56322e/done?utm_nooverride=1|http://hardcoregamer.localhost:3000|TOML' + + encoded = @helper.send(:encode_value, decoded) + assert_equal expected, encoded + end + + def test_decode_value + expected = '200904281000001|DOM|IND|INR|58.00|22|1|http://localhost:3000/orders/1/ed5230696ad525b9e322a6a64b56322e/done?utm_nooverride=1|http://hardcoregamer.localhost:3000|TOML' + encoded = 'TVRqQXdPVEEwTWpneE1EQXdNREF4ZkVSUFRYeEpUa1I4U1U1U2ZEVTRMakF3ZkRJeWZERjhhSFIwY0RvdkwyeHZZMkZzYUc5emREb3pNREF3TDI5eVpHVnljeTh4TDJWa05USXpNRFk1Tm1Ga05USTFZamxsTXpJeVlUWmhOalJpTlRZek1qSmxMMlJ2Ym1VL2RYUnRYMjV2YjNabGNuSnBaR1U5TVh4b2RIUndPaTh2YUdGeVpHTnZjbVZuWVcxbGNpNXNiMk5oYkdodmMzUTZNekF3TUh4VVQwMU0=' + + decoded = @helper.send(:decode_value, encoded) + assert_equal expected, decoded + end + + def test_failure_url + @helper.return_url = "http://localhost/return" + @helper.failure_url = "http://localhost/fail" + + assert_field 'Failure URL', "http://localhost/fail" + end + + def test_failure_url_is_set_to_return_url_if_not_provided + @helper.return_url = "http://localhost/return" + @helper.form_fields + assert_field 'Failure URL', "http://localhost/return" + end + + + def test_status_supports_ssl_get + assert DirecPay::Status.new('dummy-account').respond_to?(:ssl_get) + end + + def test_status_update_in_production_mode + ActiveMerchant::Billing::Base.integration_mode = :production + params = "dummy-authorization|1234|http://localhost/notify" + DirecPay::Status.any_instance.expects(:ssl_get).with("https://www.timesofmoney.com/direcpay/secure/dpPullMerchAtrnDtls.jsp?requestparams=#{CGI.escape(params)}") + + DirecPay::Status.new(1234, :test => false).update("dummy-authorization", "http://localhost/notify") + ActiveMerchant::Billing::Base.integration_mode = :test + end + + def test_status_update_in_test_mode + params = "dummy-authorization|1234|http://localhost/notify" + DirecPay::Status.any_instance.expects(:ssl_get).with("https://test.timesofmoney.com/direcpay/secure/dpPullMerchAtrnDtls.jsp?requestparams=#{CGI.escape(params)}") + + DirecPay::Status.new(1234, :test => true).update("dummy-authorization", "http://localhost/notify") + end + + + + private + + def fill_in_transaction_details!(helper) + helper.customer :first_name => 'Carl', :last_name => 'Carlton', :email => 'carlton@example.com' + helper.description = "blabla" + + indian_address = address(:country => "India", :phone => "9122028000000", :phone2 => '+1 613 123 4567') + helper.shipping_address(indian_address) + helper.billing_address(indian_address) + + helper.return_url = "http://localhost/return" + end +end diff --git a/test/unit/integrations/notifications/direc_pay_notification_test.rb b/test/unit/integrations/notifications/direc_pay_notification_test.rb new file mode 100644 index 00000000000..af77cb090e9 --- /dev/null +++ b/test/unit/integrations/notifications/direc_pay_notification_test.rb @@ -0,0 +1,69 @@ +require 'test_helper' + +class DirecPayNotificationTest < Test::Unit::TestCase + include ActiveMerchant::Billing::Integrations + + def setup + @direc_pay = DirecPay::Notification.new(http_raw_data_success) + end + + def test_success + assert @direc_pay.complete? + assert_equal "Completed", @direc_pay.status + assert_equal "1001010000026481", @direc_pay.transaction_id + assert_equal "1001", @direc_pay.item_id + assert_equal "1.00", @direc_pay.gross + assert_equal "INR", @direc_pay.currency + assert_equal "IND", @direc_pay.country + end + + def test_failure + @direc_pay = DirecPay::Notification.new(http_raw_data_failure) + assert !@direc_pay.complete? + assert_equal "Failed", @direc_pay.status + assert_equal "1001010000026516", @direc_pay.transaction_id + assert_equal "1001", @direc_pay.item_id + assert_equal "1.00", @direc_pay.gross + assert_equal "INR", @direc_pay.currency + assert_equal "IND", @direc_pay.country + assert @direc_pay.acknowledge + end + + def test_error + @direc_pay = DirecPay::Notification.new(http_raw_data_error) + assert !@direc_pay.complete? + assert_equal "Error", @direc_pay.status + assert_equal "1001010000026516", @direc_pay.transaction_id + end + + def test_compositions + assert_equal Money.new(100, 'INR'), @direc_pay.amount + end + + def test_acknowledgement + assert @direc_pay.acknowledge + end + + def test_respond_to_acknowledge + assert @direc_pay.respond_to?(:acknowledge) + end + + + private + + def http_raw_data_success + "responseparams=1001010000026481|SUCCESS|IND|INR|1|1001|1.00|" + end + + def http_raw_data_failure + "responseparams=1001010000026516|FAIL|IND|INR|1|1001|1.00|" + end + + def http_raw_data_pending + "responseparams=1001010000026516|PENDING|IND|INR|1|1001|1|" + end + + def http_raw_data_error + "responseparams=1001010000026516|ERROR|Record not found for this transaction reference number" + end +end diff --git a/test/unit/integrations/returns/direc_pay_return_test.rb b/test/unit/integrations/returns/direc_pay_return_test.rb new file mode 100644 index 00000000000..313b5cda7e3 --- /dev/null +++ b/test/unit/integrations/returns/direc_pay_return_test.rb @@ -0,0 +1,54 @@ +require 'test_helper' + +class DirecPayReturnTest < Test::Unit::TestCase + include ActiveMerchant::Billing::Integrations + + def test_success + direc_pay = DirecPay::Return.new(http_raw_data_success) + assert direc_pay.success? + assert_equal 'Completed', direc_pay.message + end + + def test_failure_is_successful + direc_pay = DirecPay::Return.new(http_raw_data_failure) + assert direc_pay.success? + assert_equal 'Pending', direc_pay.message + end + + def test_treat_initial_failures_as_pending + direc_pay = DirecPay::Return.new(http_raw_data_failure) + assert_equal 'Pending', direc_pay.notification.status + end + + def test_return_has_notification + direc_pay = DirecPay::Return.new(http_raw_data_success) + notification = direc_pay.notification + + assert_equal '1001010000026481', direc_pay.notification.transaction_id + assert notification.complete? + assert_equal 'Completed', notification.status + assert_equal '1001', notification.item_id + assert_equal '1.00', notification.gross + assert_equal 100, notification.gross_cents + assert_equal Money.new(100, 'INR'), notification.amount + assert_equal 'INR', notification.currency + assert_equal 'IND', notification.country + assert_equal 'NULL', notification.other_details + end + + def test_treat_failed_return_as_complete + direc_pay = DirecPay::Return.new(http_raw_data_failure) + assert direc_pay.notification.complete? + end + + private + + def http_raw_data_success + "responseparams=1001010000026481|SUCCESS|IND|INR|NULL|1001|1.00|" + end + + def http_raw_data_failure + "responseparams=1001010000026516|FAIL|IND|INR|NULL|1001|1.00|" + end + +end