global_collect 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. data/COPYING +11 -0
  2. data/README.markdown +109 -0
  3. data/Rakefile +34 -0
  4. data/VERSION +1 -0
  5. data/examples/cancel_payment.rb +14 -0
  6. data/examples/convert_amount.rb +14 -0
  7. data/examples/get_order_status.rb +15 -0
  8. data/examples/insert_order_with_payment.rb +37 -0
  9. data/examples/process_challenged.rb +13 -0
  10. data/examples/set_payment.rb +23 -0
  11. data/examples/test_connection.rb +13 -0
  12. data/global_collect.gemspec +170 -0
  13. data/lib/global_collect/api_client.rb +71 -0
  14. data/lib/global_collect/builders/do_refund/credit_card_payment.rb +12 -0
  15. data/lib/global_collect/builders/do_refund/payment.rb +39 -0
  16. data/lib/global_collect/builders/insert_order_with_payment/credit_card_online_payment.rb +38 -0
  17. data/lib/global_collect/builders/insert_order_with_payment/hosted_credit_card_online_payment.rb +4 -0
  18. data/lib/global_collect/builders/insert_order_with_payment/order.rb +75 -0
  19. data/lib/global_collect/builders/insert_order_with_payment/payment.rb +25 -0
  20. data/lib/global_collect/builders/set_payment/payment.rb +23 -0
  21. data/lib/global_collect/const/payment_product.rb +38 -0
  22. data/lib/global_collect/const/payment_status.rb +90 -0
  23. data/lib/global_collect/field_validator.rb +47 -0
  24. data/lib/global_collect/request_models/base.rb +37 -0
  25. data/lib/global_collect/request_models/do_refund/credit_card_payment.rb +12 -0
  26. data/lib/global_collect/request_models/do_refund/payment.rb +39 -0
  27. data/lib/global_collect/request_models/insert_order_with_payment/credit_card_online_payment.rb +44 -0
  28. data/lib/global_collect/request_models/insert_order_with_payment/hosted_credit_card_online_payment.rb +19 -0
  29. data/lib/global_collect/request_models/insert_order_with_payment/order.rb +67 -0
  30. data/lib/global_collect/request_models/insert_order_with_payment/payment.rb +17 -0
  31. data/lib/global_collect/request_models/set_payment/payment.rb +17 -0
  32. data/lib/global_collect/requests/base.rb +43 -0
  33. data/lib/global_collect/requests/cancel_payment.rb +22 -0
  34. data/lib/global_collect/requests/composite.rb +23 -0
  35. data/lib/global_collect/requests/convert_amount.rb +29 -0
  36. data/lib/global_collect/requests/do_refund.rb +8 -0
  37. data/lib/global_collect/requests/get_order_status.rb +24 -0
  38. data/lib/global_collect/requests/insert_order_with_payment.rb +10 -0
  39. data/lib/global_collect/requests/process_challenged.rb +22 -0
  40. data/lib/global_collect/requests/set_payment.rb +9 -0
  41. data/lib/global_collect/requests/simple.rb +39 -0
  42. data/lib/global_collect/requests/test_connection.rb +8 -0
  43. data/lib/global_collect/responses/base.rb +73 -0
  44. data/lib/global_collect/responses/convert_amount/response_methods.rb +8 -0
  45. data/lib/global_collect/responses/do_refund/response_methods.rb +24 -0
  46. data/lib/global_collect/responses/get_order_status/v1_response_methods.rb +49 -0
  47. data/lib/global_collect/responses/get_order_status/v2_response_methods.rb +67 -0
  48. data/lib/global_collect/responses/insert_order_with_payment/credit_card_online_payment_response_methods.rb +31 -0
  49. data/lib/global_collect/responses/insert_order_with_payment/hosted_merchant_link_payment_response_methods.rb +16 -0
  50. data/lib/global_collect/responses/success_row.rb +15 -0
  51. data/lib/global_collect.rb +81 -0
  52. data/spec/api_client_spec.rb +93 -0
  53. data/spec/builders/do_refund/credit_card_payment_spec.rb +32 -0
  54. data/spec/builders/do_refund/payment_spec.rb +51 -0
  55. data/spec/builders/insert_order_with_payment/credit_card_online_payment_spec.rb +59 -0
  56. data/spec/builders/insert_order_with_payment/hosted_credit_card_online_payment_spec.rb +59 -0
  57. data/spec/builders/insert_order_with_payment/order_spec.rb +88 -0
  58. data/spec/builders/insert_order_with_payment/payment_spec.rb +37 -0
  59. data/spec/builders/set_payment/payment_spec.rb +35 -0
  60. data/spec/field_validator_spec.rb +79 -0
  61. data/spec/global_collect_spec.rb +43 -0
  62. data/spec/request_models/base_spec.rb +31 -0
  63. data/spec/request_models/insert_order_with_payment/credit_card_online_payment_spec.rb +11 -0
  64. data/spec/request_models/insert_order_with_payment/hosted_credit_card_online_payment_spec.rb +38 -0
  65. data/spec/requests/base_spec.rb +40 -0
  66. data/spec/requests/composite_spec.rb +48 -0
  67. data/spec/requests/convert_amount.rb +34 -0
  68. data/spec/requests/insert_order_with_payment_spec.rb +60 -0
  69. data/spec/requests/simple_spec.rb +37 -0
  70. data/spec/responses/base_spec.rb +59 -0
  71. data/spec/responses/convert_amount/response_methods_spec.rb +13 -0
  72. data/spec/responses/do_refund/response_methods_spec.rb +15 -0
  73. data/spec/responses/get_order_status/v1_response_methods_spec.rb +28 -0
  74. data/spec/responses/get_order_status/v2_response_methods_spec.rb +28 -0
  75. data/spec/responses/insert_order_with_payment/credit_card_online_payment_response_methods_spec.rb +13 -0
  76. data/spec/responses/insert_order_with_payment/hosted_merchant_link_payment_response_methods_spec.rb +13 -0
  77. data/spec/responses/succcess_row_spec.rb +26 -0
  78. data/spec/spec_helper.rb +130 -0
  79. data/spec/support/challenged_iowp_response.xml +51 -0
  80. data/spec/support/successful_convert_amount_response.xml +29 -0
  81. data/spec/support/successful_do_refund_response.xml +36 -0
  82. data/spec/support/successful_get_order_status_v1_response.xml +72 -0
  83. data/spec/support/successful_get_order_status_v2_response.xml +50 -0
  84. data/spec/support/successful_hosted_iowp_response.xml +60 -0
  85. data/spec/support/successful_iowp_response.xml +49 -0
  86. data/spec/support/successful_process_challenged_response.xml +26 -0
  87. data/spec/support/unsuccessful_do_refund_response.xml +29 -0
  88. data/spec/support/unsuccessful_iowp_response.xml +42 -0
  89. data/spec/support/unsuccessful_process_challenged_response.xml +30 -0
  90. metadata +213 -0
@@ -0,0 +1,9 @@
1
+ module GlobalCollect::Requests
2
+ class SetPayment < GlobalCollect::Requests::Composite
3
+ # WDL §5.33 requires a PAYMENT node and allows more optional nodes
4
+ def initialize(payment_and_builder, *extra_pairs)
5
+ all_pairs = [payment_and_builder] + extra_pairs
6
+ super("SET_PAYMENT", all_pairs)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,39 @@
1
+ module GlobalCollect::Requests
2
+ class Simple < GlobalCollect::Requests::Base
3
+
4
+ def initialize(action, fields_hash)
5
+ super(action)
6
+ @contents = fields_hash
7
+ end
8
+
9
+ def to_xml
10
+ validate!
11
+ super do |params_node|
12
+ if wrapper
13
+ params_node.tag!(wrapper) {|wrapper_node| build_keys(wrapper_node) }
14
+ else
15
+ build_keys(params_node)
16
+ end
17
+ end
18
+ end
19
+
20
+ protected
21
+ def fields; {}; end
22
+
23
+ def wrapper; nil; end
24
+
25
+ def validate!
26
+ fields.each do |key, validations|
27
+ validator = GlobalCollect::FieldValidator.new(*validations)
28
+ raise "Invalid field '#{key}'!" unless validator.validate(@contents[key])
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def build_keys(node)
35
+ fields.keys.each {|key| node.tag!(key, @contents[key]) }
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,8 @@
1
+ module GlobalCollect::Requests
2
+ class TestConnection < GlobalCollect::Requests::Simple
3
+ # WDL §5.36
4
+ def initialize
5
+ super("TEST_CONNECTION", {})
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,73 @@
1
+ require 'time'
2
+
3
+ module GlobalCollect::Responses
4
+ # WDL §4 specifies the generalized response
5
+ # This base class is sufficient for many responses that don't include anything
6
+ # more than the basic META, RESULT and/or ERROR nodes.
7
+ # It is also a useful fallback if you want basic hash access to the actual
8
+ # content of the response with just a few helper methods for traversal.
9
+ class Base
10
+ attr_reader :response_hash, :raw_response
11
+ def initialize(response_hash, raw_response)
12
+ @response_hash = response_hash
13
+ @raw_response = raw_response
14
+ end
15
+
16
+ def success?
17
+ RESPONSE_STATUS_SUCCESS[result]
18
+ end
19
+
20
+ def action
21
+ request['ACTION']
22
+ end
23
+
24
+ def response_datetime
25
+ Time.parse(meta['RESPONSEDATETIME']) if meta['RESPONSEDATETIME']
26
+ end
27
+
28
+ def request_id
29
+ meta['REQUESTID']
30
+ end
31
+
32
+ def version
33
+ meta['VERSION']
34
+ end
35
+
36
+ def errors
37
+ return [] if success?
38
+ errs = response['ERROR'].is_a?(Array) ? response['ERROR'] : [response['ERROR']]
39
+ return errs.map{|err| RequestError.new(err['CODE'].to_i, err['MESSAGE']) }
40
+ end
41
+
42
+ def malformed?
43
+ !response_hash['XML']
44
+ end
45
+
46
+ protected
47
+
48
+ def result
49
+ response['RESULT']
50
+ end
51
+
52
+ def meta
53
+ response['META']
54
+ end
55
+
56
+ # this structure is general to successful and unsuccessful response
57
+ def response
58
+ request['RESPONSE']
59
+ end
60
+
61
+ def request
62
+ response_hash['XML']['REQUEST']
63
+ end
64
+
65
+ private
66
+
67
+ RESPONSE_STATUS_SUCCESS = {
68
+ 'OK' => true,
69
+ 'NOK' => false
70
+ }
71
+ class RequestError < Struct.new(:code, :message); end
72
+ end
73
+ end
@@ -0,0 +1,8 @@
1
+ module GlobalCollect::Responses::ConvertAmount
2
+ # WDL §5.7.2 specifies the possible return keys
3
+ module ResponseMethods
4
+ def converted_amount
5
+ row["CONVERTEDAMOUNT"]
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,24 @@
1
+ module GlobalCollect::Responses::DoRefund
2
+ # WDL §5.16.2 specifies the possible return keys
3
+ module ResponseMethods
4
+ [
5
+ "MERCHANT ID" ,
6
+ "ORDER ID" ,
7
+ "EFFORT ID" ,
8
+ "ATTEMPT ID" ,
9
+ "STATUS ID" ,
10
+ "STATUS DATE" ,
11
+ "PAYMENT REFERENCE" ,
12
+ "ADDITIONAL REFERENCE" ,
13
+ "EXTERNAL REFERENCE"
14
+ ].each do |meth|
15
+ define_method meth.downcase.gsub(/\s+/, "_") do
16
+ row[meth.gsub(/\s+/, "")]
17
+ end
18
+ end
19
+
20
+ def payment_status
21
+ GlobalCollect::Const::PaymentStatus.from_code(status_id)
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,49 @@
1
+ module GlobalCollect::Responses::GetOrderStatus
2
+ # WDL §5.23.2 specifies the possible return keys
3
+ module V1ResponseMethods
4
+
5
+ def statuses
6
+ row_hashes.map{|row_hash| OrderStatus.new(row_hash) }
7
+ end
8
+
9
+ private
10
+
11
+ def row_hashes
12
+ response['ROW'].is_a?(Array) ? response['ROW'] : [response['ROW']]
13
+ end
14
+
15
+ class OrderStatus < Struct.new(:row_hash)
16
+ [
17
+ "MERCHANT ID" ,
18
+ "ORDER ID" ,
19
+ "EFFORT ID" ,
20
+ "ATTEMPT ID" ,
21
+ "PAYMENT REFERENCE" ,
22
+ "MERCHANT REFERENCE" ,
23
+ "STATUS ID" ,
24
+ "STATUS DATE" ,
25
+ "AMOUNT" ,
26
+ "CURRENCY CODE" ,
27
+ "PAYMENT METHOD ID" ,
28
+ "PAYMENT PRODUCT ID"
29
+ ].each do |meth|
30
+ define_method meth.downcase.gsub(/\s+/, "_") do
31
+ row_hash[meth.gsub(/\s+/, "")]
32
+ end
33
+ end
34
+
35
+ def payment_status
36
+ GlobalCollect::Const::PaymentStatus.from_code(status_id)
37
+ end
38
+
39
+ # NOTE: these error fields correspond to the potential errors on the order
40
+ # or payment, not on this response.
41
+ # Those can be found in the #error object of the response.
42
+ def errors
43
+ return [] unless row_hash['ERRORNUMBER'] || row_hash['ERRORMESSAGE']
44
+ [OrderStatusError.new(row_hash['ERRORNUMBER'].to_i, row_hash['ERRORMESSAGE'])]
45
+ end
46
+ end
47
+ class OrderStatusError < Struct.new(:code, :message); end
48
+ end
49
+ end
@@ -0,0 +1,67 @@
1
+ module GlobalCollect::Responses::GetOrderStatus
2
+ # WDL §5.23.3 specifies the possible return keys
3
+ module V2ResponseMethods
4
+
5
+ def statuses
6
+ status_hashes.map{|status_hash| OrderStatus.new(status_hash) }
7
+ end
8
+
9
+ private
10
+
11
+ def status_hashes
12
+ response['STATUS'].is_a?(Array) ? response['STATUS'] : [response['STATUS']]
13
+ end
14
+
15
+ class OrderStatus < Struct.new(:status_hash)
16
+ [
17
+ "MERCHANT ID" ,
18
+ "ORDER ID" ,
19
+ "EFFORT ID" ,
20
+ "ATTEMPT ID" ,
21
+ "PAYMENT METHOD ID" ,
22
+ "PAYMENT PRODUCT ID" ,
23
+ "PAYMENT REFERENCE" ,
24
+ "MERCHANT REFERENCE" ,
25
+ "STATUS ID" ,
26
+ "STATUS DATE" ,
27
+ "CURRENCY CODE" ,
28
+ "AMOUNT" ,
29
+ "TOTAL AMOUNT PAID" ,
30
+ "TOTAL AMOUNT REFUNDED" ,
31
+ "FRAUD RESULT" ,
32
+ "FRAUD CODE" ,
33
+ "FRAUD NEURAL" ,
34
+ "FRAUD RCF" ,
35
+ "AVS RESULT" ,
36
+ "CVV RESULT" ,
37
+ "AUTHORISATION CODE" ,
38
+ "ECI" ,
39
+ "CAVV" ,
40
+ "XID"
41
+ ].each do |meth|
42
+ define_method meth.downcase.gsub(/\s+/, "_") do
43
+ status_hash[meth.gsub(/\s+/, "")]
44
+ end
45
+ end
46
+
47
+ def payment_status
48
+ GlobalCollect::Const::PaymentStatus.from_code(status_id)
49
+ end
50
+
51
+ def payment_product
52
+ GlobalCollect::Const::PaymentProduct.from_code(payment_product_id)
53
+ end
54
+
55
+ # NOTE: these error fields correspond to the potential errors on the order
56
+ # or payment, not on this response.
57
+ # Those can be found in the #error object of the response.
58
+ def errors
59
+ return [] unless status_hash['ERRORS']
60
+ errs = status_hash['ERRORS']['ERROR'].is_a?(Array) ? status_hash['ERRORS']['ERROR'] : [status_hash['ERRORS']['ERROR']]
61
+ errs.map{|err| OrderStatusError.new(err['CODE'].to_i, err['MESSAGE']) }
62
+ end
63
+ end
64
+ class OrderStatusError < Struct.new(:code, :message); end
65
+ end
66
+ end
67
+
@@ -0,0 +1,31 @@
1
+ module GlobalCollect::Responses::InsertOrderWithPayment
2
+ # WDL §5.28.2 TABLE 115 specifies the possible return keys
3
+ module CreditCardOnlinePaymentResponseMethods
4
+ [
5
+ "PAYMENT REFERENCE" ,
6
+ "ADDITIONAL REFERENCE" ,
7
+ "EXTERNAL REFERENCE" ,
8
+ "ORDER ID" ,
9
+ "STATUS ID" ,
10
+ "EFFORT ID" ,
11
+ "MERCHANT ID" ,
12
+ "ATTEMPT ID" ,
13
+ "STATUS DATE" ,
14
+ "AVS RESULT" ,
15
+ "CVV RESULT" ,
16
+ "FRAUD RESULT" ,
17
+ "FRAUD CODE" ,
18
+ "FRAUD NEURAL" ,
19
+ "FRAUD RCF" ,
20
+ "AUTHORISATION CODE"
21
+ ].each do |meth|
22
+ define_method meth.downcase.gsub(/\s+/, "_") do
23
+ row[meth.gsub(/\s+/, "")]
24
+ end
25
+ end
26
+
27
+ def payment_status
28
+ GlobalCollect::Const::PaymentStatus.from_code(status_id)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,16 @@
1
+ module GlobalCollect::Responses::InsertOrderWithPayment
2
+ # WDL §5.28.2 TABLE 125 specifies the possible return keys
3
+ module HostedMerchantLinkPaymentResponseMethods
4
+ [
5
+ "FORM METHOD" ,
6
+ "FORM ACTION" ,
7
+ "REF" ,
8
+ "MAC" ,
9
+ "RETURN MAC"
10
+ ].each do |meth|
11
+ define_method meth.downcase.gsub(/\s+/, "_") do
12
+ row[meth.gsub(/\s+/, "")]
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ module GlobalCollect::Responses
2
+ # This is one of the classes of response that you can get from the API, which
3
+ # if successful returns a structure like:
4
+ # <RESPONSE>
5
+ # <META>...</META>
6
+ # <RESULT>...</RESULT>
7
+ # <ROW> RELEVANT NODES HERE </ROW>
8
+ # </RESPONSE>
9
+ module SuccessRow
10
+ def row
11
+ return nil unless success?
12
+ response['ROW']
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,81 @@
1
+ require 'builder'
2
+ require 'httparty'
3
+ require 'find'
4
+ require 'logger'
5
+ require 'benchmark'
6
+
7
+ module GlobalCollect;end
8
+ module GlobalCollect::Builders;end
9
+ module GlobalCollect::RequestModels;end
10
+ module GlobalCollect::Responses;end
11
+
12
+ lib_dir = File.dirname(__FILE__)
13
+ [
14
+ %w[api_client] ,
15
+ %w[builders do_refund payment] ,
16
+ %w[builders do_refund credit_card_payment] ,
17
+ %w[builders insert_order_with_payment order] ,
18
+ %w[builders insert_order_with_payment payment] ,
19
+ %w[builders insert_order_with_payment credit_card_online_payment] ,
20
+ %w[builders insert_order_with_payment hosted_credit_card_online_payment] ,
21
+ %w[builders set_payment payment] ,
22
+ %w[const payment_product] ,
23
+ %w[const payment_status] ,
24
+ %w[field_validator] ,
25
+ %w[request_models base] ,
26
+ %w[request_models insert_order_with_payment order] ,
27
+ %w[request_models insert_order_with_payment payment] ,
28
+ %w[request_models insert_order_with_payment credit_card_online_payment] ,
29
+ %w[request_models insert_order_with_payment hosted_credit_card_online_payment] ,
30
+ %w[request_models do_refund payment] ,
31
+ %w[request_models do_refund credit_card_payment] ,
32
+ %w[request_models set_payment payment] ,
33
+ %w[requests base] ,
34
+ %w[requests simple] ,
35
+ %w[requests composite] ,
36
+ %w[requests insert_order_with_payment] ,
37
+ %w[requests get_order_status] ,
38
+ %w[requests test_connection] ,
39
+ %w[requests do_refund] ,
40
+ %w[requests set_payment] ,
41
+ %w[requests cancel_payment] ,
42
+ %w[requests process_challenged] ,
43
+ %w[requests convert_amount] ,
44
+ %w[responses base] ,
45
+ %w[responses success_row] ,
46
+ %w[responses insert_order_with_payment credit_card_online_payment_response_methods] ,
47
+ %w[responses insert_order_with_payment hosted_merchant_link_payment_response_methods],
48
+ %w[responses do_refund response_methods] ,
49
+ %w[responses get_order_status v1_response_methods] ,
50
+ %w[responses get_order_status v2_response_methods] ,
51
+ %w[responses convert_amount response_methods]
52
+
53
+ ].each do |f|
54
+ require File.join(lib_dir, 'global_collect', *f)
55
+ end
56
+
57
+ module GlobalCollect
58
+ extend self
59
+
60
+ attr_accessor :merchant_id
61
+ attr_accessor :authentication_scheme
62
+ attr_accessor :ip_address # only used if authentication_scheme is :ip_check
63
+ attr_accessor :environment
64
+ attr_accessor :default_api_version
65
+ attr_accessor :wire_log_file
66
+ attr_accessor :wire_logger
67
+
68
+ def merchant_link_client
69
+ GlobalCollect::ApiClient.new(:merchant_link, environment, authentication_scheme)
70
+ end
71
+
72
+ def wire_logger
73
+ @wire_logger ||= if self.wire_log_file
74
+ Logger.new(self.wire_log_file)
75
+ else
76
+ Logger.new(STDOUT)
77
+ end
78
+ end
79
+ end
80
+
81
+ GlobalCollect.default_api_version ||= "1.0"
@@ -0,0 +1,93 @@
1
+ require 'spec_helper'
2
+
3
+ module TestResponseMethods
4
+ def foobar;end
5
+ end
6
+
7
+ describe 'the api client' do
8
+ it "should not accept an invalid environment" do
9
+ lambda {
10
+ GlobalCollect::ApiClient.new(:merchant_link, :foo, :ip_check)
11
+ }.should raise_error(ArgumentError)
12
+ end
13
+ it "should not accept an invalid service" do
14
+ lambda {
15
+ GlobalCollect::ApiClient.new(:foo, :test, :ip_check)
16
+ }.should raise_error(ArgumentError)
17
+ end
18
+ it "should not accept an invalid auth scheme" do
19
+ lambda {
20
+ GlobalCollect::ApiClient.new(:merchant_link, :test, :foo)
21
+ }.should raise_error(ArgumentError)
22
+ end
23
+
24
+ it "should post to the correct url" do
25
+ FakeWeb.register_uri(:post, "https://ps.gcsip.nl/wdl/wdl", :body => read_canned_response('successful_iowp_response.xml'))
26
+ client = GlobalCollect::ApiClient.new(:merchant_link, :test, :ip_check)
27
+
28
+ request = mock(
29
+ :action => 'foo',
30
+ :version => '1.0',
31
+ :to_xml => "<XML></XML>",
32
+ :suggested_response_mixins => []
33
+ )
34
+ response = client.make_request(request)
35
+ response.success?.should == true
36
+ end
37
+
38
+ it "should mix in the proper mixins to the response by default" do
39
+ FakeWeb.register_uri(:post, "https://ps.gcsip.nl/wdl/wdl", :body => read_canned_response('successful_iowp_response.xml'))
40
+ client = GlobalCollect::ApiClient.new(:merchant_link, :test, :ip_check)
41
+
42
+ request = mock(
43
+ :action => 'foo',
44
+ :version => '1.0',
45
+ :to_xml => "<XML></XML>",
46
+ :suggested_response_mixins => [TestResponseMethods]
47
+ )
48
+ response = client.make_request(request)
49
+ lambda { response.foobar }.should_not raise_error
50
+ end
51
+
52
+ it "should not mix in anything if directed not to" do
53
+ FakeWeb.register_uri(:post, "https://ps.gcsip.nl/wdl/wdl", :body => read_canned_response('successful_iowp_response.xml'))
54
+ client = GlobalCollect::ApiClient.new(:merchant_link, :test, :ip_check)
55
+
56
+ request = mock(
57
+ :action => 'foo',
58
+ :version => '1.0',
59
+ :to_xml => "<XML></XML>",
60
+ :suggested_response_mixins => [TestResponseMethods]
61
+ )
62
+ response = client.make_request(request, false)
63
+ lambda { response.foobar }.should raise_error(NoMethodError)
64
+ end
65
+
66
+ it "should error on no response" do
67
+ FakeWeb.register_uri(:post, "https://ps.gcsip.nl/wdl/wdl", :body => read_canned_response('successful_iowp_response.xml'))
68
+ client = GlobalCollect::ApiClient.new(:merchant_link, :test, :ip_check)
69
+ client.class.should_receive(:post).and_return(nil)
70
+ request = mock(
71
+ :action => 'foo',
72
+ :version => '1.0',
73
+ :to_xml => "<XML></XML>",
74
+ :suggested_response_mixins => []
75
+ )
76
+ lambda { client.make_request(request) }.should raise_error(Exception, /No response/)
77
+ end
78
+
79
+ it "should error on a malformed response" do
80
+ FakeWeb.register_uri(:post, "https://ps.gcsip.nl/wdl/wdl", :body => read_canned_response('successful_iowp_response.xml'))
81
+ client = GlobalCollect::ApiClient.new(:merchant_link, :test, :ip_check)
82
+ response = mock(:response, :body => "Foo bar", :code => "200", :delegate => {})
83
+ client.class.should_receive(:post).and_return(response)
84
+
85
+ request = mock(
86
+ :action => 'foo',
87
+ :version => '1.0',
88
+ :to_xml => "<XML></XML>",
89
+ :suggested_response_mixins => []
90
+ )
91
+ lambda { client.make_request(request) }.should raise_error(Exception, /Malformed/)
92
+ end
93
+ end