From b1ca485345a8e466990280912033b6504a591ecd Mon Sep 17 00:00:00 2001 From: James Armstead Date: Mon, 15 Aug 2011 11:00:27 -0500 Subject: [PATCH] Added Dwolla Integration Gateway --- .../billing/integrations/dwolla.rb | 30 ++++++++++ .../billing/integrations/dwolla/helper.rb | 28 ++++++++++ .../integrations/dwolla/notification.rb | 50 +++++++++++++++++ .../billing/integrations/dwolla/return.rb | 38 +++++++++++++ test/unit/integrations/dwolla_module_test.rb | 14 +++++ .../helpers/dwolla_helper_test.rb | 35 ++++++++++++ .../notifications/dwolla_notification_test.rb | 51 +++++++++++++++++ .../returns/dwolla_return_test.rb | 55 +++++++++++++++++++ 8 files changed, 301 insertions(+) create mode 100644 lib/active_merchant/billing/integrations/dwolla.rb create mode 100644 lib/active_merchant/billing/integrations/dwolla/helper.rb create mode 100644 lib/active_merchant/billing/integrations/dwolla/notification.rb create mode 100644 lib/active_merchant/billing/integrations/dwolla/return.rb create mode 100644 test/unit/integrations/dwolla_module_test.rb create mode 100644 test/unit/integrations/helpers/dwolla_helper_test.rb create mode 100644 test/unit/integrations/notifications/dwolla_notification_test.rb create mode 100644 test/unit/integrations/returns/dwolla_return_test.rb diff --git a/lib/active_merchant/billing/integrations/dwolla.rb b/lib/active_merchant/billing/integrations/dwolla.rb new file mode 100644 index 00000000000..9763c384fec --- /dev/null +++ b/lib/active_merchant/billing/integrations/dwolla.rb @@ -0,0 +1,30 @@ +# All mappings in helper.rb are required fields to be sent to Dwolla. +# :account = 'Dwolla Id of merchant' +# :credential1 = 'key from Dwolla Application' +# :credential2 = 'secret from Dwolla Application' +# :redirect_url = 'can be different that what is specified on Dwolla Application creation' +# :return_url = 'can be different that what is specified on Dwolla Application creation' +# :order_id = must be unique for each transaction + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Dwolla + autoload :Return, 'active_merchant/billing/integrations/dwolla/return.rb' + autoload :Helper, 'active_merchant/billing/integrations/dwolla/helper.rb' + autoload :Notification, 'active_merchant/billing/integrations/dwolla/notification.rb' + + mattr_accessor :service_url + self.service_url = 'https://www.dwolla.com/payment/pay' + + 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/dwolla/helper.rb b/lib/active_merchant/billing/integrations/dwolla/helper.rb new file mode 100644 index 00000000000..527d9059e70 --- /dev/null +++ b/lib/active_merchant/billing/integrations/dwolla/helper.rb @@ -0,0 +1,28 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Dwolla + class Helper < ActiveMerchant::Billing::Integrations::Helper + + def initialize(order, account, options = {}) + super + add_field('name', 'Store Purchase') + end + + # Replace with the real mapping + mapping :credential1, 'key' + mapping :credential2, 'secret' + mapping :notify_url, 'callback' + mapping :return_url, 'redirect' + mapping :test_mode, 'test' + mapping :description, 'description' + mapping :account, 'destinationid' + mapping :amount, 'amount' + mapping :tax, 'tax' + mapping :shipping, 'shipping' + mapping :order, 'orderid' + end + end + end + end +end diff --git a/lib/active_merchant/billing/integrations/dwolla/notification.rb b/lib/active_merchant/billing/integrations/dwolla/notification.rb new file mode 100644 index 00000000000..eeda24eeb43 --- /dev/null +++ b/lib/active_merchant/billing/integrations/dwolla/notification.rb @@ -0,0 +1,50 @@ +require 'net/http' + +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Dwolla + class Notification < ActiveMerchant::Billing::Integrations::Notification + def complete? + status == "Completed" + end + + def status + params["Status"] + end + + def transaction_id + params['OrderId'] + end + + def currency + "USD" + end + + def gross + params['Amount'] + end + + def error + params['Message'] + end + + # Was this a test transaction? + def test? + params['TestMode'] + end + + def acknowledge + true + end + private + # Take the posted data and move the relevant data into a hash + def parse(post) + json_post = JSON.parse(post) + params.merge!(json_post) + end + end + end + end + end +end diff --git a/lib/active_merchant/billing/integrations/dwolla/return.rb b/lib/active_merchant/billing/integrations/dwolla/return.rb new file mode 100644 index 00000000000..a93ddb72b8e --- /dev/null +++ b/lib/active_merchant/billing/integrations/dwolla/return.rb @@ -0,0 +1,38 @@ +module ActiveMerchant #:nodoc: + module Billing #:nodoc: + module Integrations #:nodoc: + module Dwolla + class Return < ActiveMerchant::Billing::Integrations::Return + + def success? + self.error.nil? && self.callback_success? + end + + def error + params['error'] + end + + def error_description + params['error_description'] + end + + def checkout_id + params['checkoutid'] + end + + def transaction + params['transaction'] + end + + def test? + params['test'] + end + + def callback_success? + params['postback'] != "failure" + end + end + end + end + end +end diff --git a/test/unit/integrations/dwolla_module_test.rb b/test/unit/integrations/dwolla_module_test.rb new file mode 100644 index 00000000000..b4b6d80ad0b --- /dev/null +++ b/test/unit/integrations/dwolla_module_test.rb @@ -0,0 +1,14 @@ +require 'test_helper' + + +class DwollaModuleTest < Test::Unit::TestCase + include ActiveMerchant::Billing::Integrations + + def test_notification_method + assert_instance_of Dwolla::Notification, Dwolla.notification('{"OrderId":"order-1", "Result": "Error", "Message": "Invalid Credentials", "TestMode":true}') + end + + def test_return + assert_instance_of Dwolla::Return, Dwolla.return("dwolla=awesome") + end +end diff --git a/test/unit/integrations/helpers/dwolla_helper_test.rb b/test/unit/integrations/helpers/dwolla_helper_test.rb new file mode 100644 index 00000000000..8c57edc0453 --- /dev/null +++ b/test/unit/integrations/helpers/dwolla_helper_test.rb @@ -0,0 +1,35 @@ +require 'test_helper' + +class DwollaHelperTest < Test::Unit::TestCase + include ActiveMerchant::Billing::Integrations + + def setup + @helper = Dwolla::Helper.new('order-500','cody@example.com', :credential2 => 'secret', :amount => 500, :currency => 'USD') + end + + def test_basic_helper_fields + assert_field 'amount', '500' + assert_field 'orderid', 'order-500' + assert_field 'secret', 'secret' + end + + def test_other_fields + @helper.credential1 "key" + @helper.return_url 'http://test.com/ecommerce/redirect.aspx' + @helper.notify_url 'http://test.com/test/callback' + @helper.test_mode true + @helper.description 'Store Purchase Description' + @helper.account '812-546-3855' + @helper.shipping 0.00 + @helper.tax 0.00 + + assert_field 'key', 'key' + assert_field 'redirect', 'http://test.com/ecommerce/redirect.aspx' + assert_field 'callback', 'http://test.com/test/callback' + assert_field 'test', 'true' + assert_field 'description', 'Store Purchase Description' + assert_field 'destinationid', '812-546-3855' + assert_field 'shipping', '0.0' + assert_field 'tax', '0.0' + end +end diff --git a/test/unit/integrations/notifications/dwolla_notification_test.rb b/test/unit/integrations/notifications/dwolla_notification_test.rb new file mode 100644 index 00000000000..ccd2555b8ce --- /dev/null +++ b/test/unit/integrations/notifications/dwolla_notification_test.rb @@ -0,0 +1,51 @@ +require 'test_helper' + +class DwollaNotificationTest < Test::Unit::TestCase + include ActiveMerchant::Billing::Integrations + + def setup + @error_dwolla = Dwolla::Notification.new(http_raw_error_data) + @dwolla = Dwolla::Notification.new(http_raw_success_data) + end + + def test_success_accessors + assert @dwolla.complete? + assert_equal "1234asdfasd567", @dwolla.transaction_id + assert_equal "Completed", @dwolla.status + assert_equal 1.00, @dwolla.gross + assert_equal "USD", @dwolla.currency + assert @dwolla.test? + end + + def test_error_accessors + assert_false @error_dwolla.complete? + assert_equal "order-1", @error_dwolla.transaction_id + assert_equal nil, @error_dwolla.status + assert_equal nil, @error_dwolla.gross + assert_equal "USD", @error_dwolla.currency + assert_equal "Invalid Credentials", @error_dwolla.error + assert @error_dwolla.test? + end + + def test_compositions + assert_equal Money.new(100, 'USD'), @dwolla.amount + end + + # Replace with real successful acknowledgement code + def test_acknowledgement + assert_equal true, @dwolla.acknowledge + end + + def test_respond_to_acknowledge + assert @dwolla.respond_to?(:acknowledge) + end + + private + def http_raw_error_data + %*{"OrderId":"order-1", "Result": "Error", "Message": "Invalid Credentials", "TestMode":true}* + end + + def http_raw_success_data + %*{"Amount":1.0, "OrderId":"1234asdfasd567", "Status":"Completed", "TransactionId":null, "TestMode":true}* + end +end diff --git a/test/unit/integrations/returns/dwolla_return_test.rb b/test/unit/integrations/returns/dwolla_return_test.rb new file mode 100644 index 00000000000..d1f5533ae45 --- /dev/null +++ b/test/unit/integrations/returns/dwolla_return_test.rb @@ -0,0 +1,55 @@ +require 'test_helper' + +class DwollaReturnTest < Test::Unit::TestCase + include ActiveMerchant::Billing::Integrations + + def setup + @error_dwolla = Dwolla::Return.new(http_raw_data_failure) + @failed_callback_dwolla = Dwolla::Return.new(http_raw_data_failed_callback) + @dwolla = Dwolla::Return.new(http_raw_data_success) + end + + def test_error_return + assert_false @error_dwolla.success? + end + + def test_error_accessors + assert_equal "failure", @error_dwolla.error + assert_equal "Invalid application credentials.", @error_dwolla.error_description + end + + def test_failed_callback_return + assert_false @failed_callback_dwolla.success? + end + + def test_failed_callback_accessors + assert_equal "4ac56e71-8a45-4be2-be5e-03a2db87f418", @failed_callback_dwolla.checkout_id + assert_equal "1", @failed_callback_dwolla.transaction + assert @failed_callback_dwolla.test? + end + + def test_success_return + assert @dwolla.success? + end + + def test_success_accessors + assert_equal "4ac56e71-8a45-4be2-be5e-03a2db87f418", @dwolla.checkout_id + assert_equal "1", @dwolla.transaction + assert @dwolla.test? + end + + private + def http_raw_data_success + "checkoutid=4ac56e71-8a45-4be2-be5e-03a2db87f418&transaction=1&postback=success&test=true" + end + + def http_raw_data_failed_callback + "checkoutid=4ac56e71-8a45-4be2-be5e-03a2db87f418&transaction=1&postback=failure&test=true" + end + + def http_raw_data_failure + "error=failure&error_description=Invalid+application+credentials." + end +end + +