micah-remit 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. data/LICENSE +20 -0
  2. data/README.markdown +91 -0
  3. data/lib/remit.rb +135 -0
  4. data/lib/remit/common.rb +88 -0
  5. data/lib/remit/data_types.rb +164 -0
  6. data/lib/remit/error_codes.rb +118 -0
  7. data/lib/remit/get_pipeline.rb +189 -0
  8. data/lib/remit/ipn_request.rb +49 -0
  9. data/lib/remit/operations/cancel_subscription_and_refund.rb +23 -0
  10. data/lib/remit/operations/cancel_token.rb +18 -0
  11. data/lib/remit/operations/discard_results.rb +18 -0
  12. data/lib/remit/operations/fund_prepaid.rb +31 -0
  13. data/lib/remit/operations/get_account_activity.rb +60 -0
  14. data/lib/remit/operations/get_account_balance.rb +29 -0
  15. data/lib/remit/operations/get_all_credit_instruments.rb +18 -0
  16. data/lib/remit/operations/get_all_prepaid_instruments.rb +18 -0
  17. data/lib/remit/operations/get_debt_balance.rb +23 -0
  18. data/lib/remit/operations/get_outstanding_debt_balance.rb +22 -0
  19. data/lib/remit/operations/get_payment_instruction.rb +21 -0
  20. data/lib/remit/operations/get_prepaid_balance.rb +23 -0
  21. data/lib/remit/operations/get_results.rb +27 -0
  22. data/lib/remit/operations/get_token_by_caller.rb +19 -0
  23. data/lib/remit/operations/get_token_usage.rb +18 -0
  24. data/lib/remit/operations/get_tokens.rb +20 -0
  25. data/lib/remit/operations/get_total_prepaid_liability.rb +22 -0
  26. data/lib/remit/operations/get_transaction.rb +42 -0
  27. data/lib/remit/operations/install_payment_instruction.rb +22 -0
  28. data/lib/remit/operations/pay.rb +35 -0
  29. data/lib/remit/operations/refund.rb +37 -0
  30. data/lib/remit/operations/reserve.rb +30 -0
  31. data/lib/remit/operations/retry_transaction.rb +18 -0
  32. data/lib/remit/operations/settle.rb +20 -0
  33. data/lib/remit/operations/settle_debt.rb +30 -0
  34. data/lib/remit/operations/subscribe_for_caller_notification.rb +18 -0
  35. data/lib/remit/operations/unsubscribe_for_caller_notification.rb +17 -0
  36. data/lib/remit/operations/write_off_debt.rb +28 -0
  37. data/lib/remit/pipeline_response.rb +52 -0
  38. data/spec/integrations/get_account_activity_spec.rb +36 -0
  39. data/spec/integrations/get_tokens_spec.rb +38 -0
  40. data/spec/integrations/integrations_helper.rb +8 -0
  41. data/spec/spec_helper.rb +36 -0
  42. data/spec/units/get_pipeline_spec.rb +165 -0
  43. data/spec/units/get_results_spec.rb +49 -0
  44. data/spec/units/ipn_request_spec.rb +32 -0
  45. data/spec/units/pay_spec.rb +133 -0
  46. data/spec/units/units_helper.rb +4 -0
  47. metadata +120 -0
@@ -0,0 +1,37 @@
1
+ require 'remit/common'
2
+
3
+ module Remit
4
+ module Refund
5
+ class Request < Remit::Request
6
+ action :Refund
7
+ parameter :caller_description
8
+ parameter :caller_reference, :required => true
9
+ parameter :caller_token_id, :required => true
10
+ parameter :charge_fee_to, :required => true
11
+ parameter :meta_data
12
+ parameter :refund_amount, :type => Remit::RequestTypes::Amount
13
+ parameter :refund_recipient_description
14
+ parameter :refund_recipient_reference
15
+ parameter :refund_sender_description
16
+ parameter :refund_sender_reference
17
+ parameter :refund_sender_token_id, :required => true
18
+ parameter :transaction_date
19
+ parameter :transaction_id, :required => true
20
+
21
+ # The RefundAmount parameter has multiple components. It is specified on the query string like
22
+ # so: RefundAmount.Amount=XXX&RefundAmount.CurrencyCode=YYY
23
+ def convert_complex_key(key, parameter)
24
+ "#{convert_key(key).to_s}.#{convert_key(parameter).to_s}"
25
+ end
26
+ end
27
+
28
+ class Response < Remit::Response
29
+ parser :rexml
30
+ parameter :transaction_response, :namespace => 'ns3', :type => TransactionResponse
31
+ end
32
+
33
+ def refund(request = Request.new)
34
+ call(request, Response)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,30 @@
1
+ require 'remit/common'
2
+
3
+ module Remit
4
+ module Reserve
5
+ class Request < Remit::Request
6
+ action :Reserve
7
+ parameter :recipient_token_id, :required => true
8
+ parameter :sender_token_id, :required => true
9
+ parameter :caller_token_id, :required => true
10
+ parameter :sender_reference
11
+ parameter :recipient_reference
12
+ parameter :caller_reference, :required => true
13
+ parameter :transaction_date
14
+ parameter :transaction_amount, :type => Remit::RequestTypes::Amount, :required => true
15
+ parameter :charge_fee_to, :required => true
16
+ parameter :sender_description
17
+ parameter :recipient_description
18
+ parameter :caller_description
19
+ parameter :meta_data
20
+ end
21
+
22
+ class Response < Remit::Response
23
+ parameter :transaction_response, :type => TransactionResponse
24
+ end
25
+
26
+ def reserve(request = Request.new)
27
+ call(request, Response)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,18 @@
1
+ require 'remit/common'
2
+
3
+ module Remit
4
+ module RetryTransaction
5
+ class Request < Remit::Request
6
+ action :RetryTransaction
7
+ parameter :original_transaction_id, :required => true
8
+ end
9
+
10
+ class Response < Remit::Response
11
+ parameter :transaction_response, :type => TransactionResponse
12
+ end
13
+
14
+ def retry_transaction(request = Request.new)
15
+ call(request, Response)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,20 @@
1
+ require 'remit/common'
2
+
3
+ module Remit
4
+ module Settle
5
+ class Request < Remit::Request
6
+ action :Settle
7
+ parameter :reserve_transaction_id, :required => true
8
+ parameter :transaction_amount, :type => Remit::RequestTypes::Amount
9
+ parameter :transaction_date
10
+ end
11
+
12
+ class Response < Remit::Response
13
+ parameter :transaction_response, :type => TransactionResponse
14
+ end
15
+
16
+ def settle(request = Request.new)
17
+ call(request, Response)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,30 @@
1
+ require 'remit/common'
2
+
3
+ module Remit
4
+ module SettleDebt
5
+ class Request < Remit::Request
6
+ action :SettleDebt
7
+ parameter :caller_description
8
+ parameter :caller_reference, :required => true
9
+ parameter :caller_token_id, :required => true
10
+ parameter :charge_fee_to, :required => true
11
+ parameter :credit_instrument_id, :required => true
12
+ parameter :meta_data
13
+ parameter :recipient_description
14
+ parameter :recipient_reference
15
+ parameter :sender_description
16
+ parameter :sender_reference
17
+ parameter :sender_token_id, :required => true
18
+ parameter :settlement_amount, :type => Remit::RequestTypes::Amount, :required => true
19
+ parameter :transaction_date
20
+ end
21
+
22
+ class Response < Remit::Response
23
+ parameter :transaction_response, :type => TransactionResponse
24
+ end
25
+
26
+ def settle_debt(request = Request.new)
27
+ call(request, Response)
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,18 @@
1
+ require 'remit/common'
2
+
3
+ module Remit
4
+ module SubscribeForCallerNotification
5
+ class Request < Remit::Request
6
+ action :SubscribeForCallerNotification
7
+ parameter :notification_operation_name, :required => true
8
+ parameter :web_service_api_url, :required => true
9
+ end
10
+
11
+ class Response < Remit::Response
12
+ end
13
+
14
+ def subscribe_for_caller_notification(request = Request.new)
15
+ call(request, Response)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ require 'remit/common'
2
+
3
+ module Remit
4
+ module UnsubscribeForCallerNotification
5
+ class Request < Remit::Request
6
+ action :UnSubscribeForCallerNotification
7
+ parameter :notification_operation_name, :required => true
8
+ end
9
+
10
+ class Response < Remit::Response
11
+ end
12
+
13
+ def unsubscribe_for_caller_notification(request = Request.new)
14
+ call(request, Response)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,28 @@
1
+ require 'remit/common'
2
+
3
+ module Remit
4
+ module WriteOffDebt
5
+ class Request < Remit::Request
6
+ action :WriteOffDebt
7
+ parameter :caller_token_id, :required => true
8
+ parameter :credit_instrument_id, :required => true
9
+ parameter :adjustment_amount, :required => true
10
+ parameter :transaction_date
11
+ parameter :sender_reference
12
+ parameter :caller_reference, :required => true
13
+ parameter :recipient_reference
14
+ parameter :sender_description
15
+ parameter :recipient_description
16
+ parameter :caller_description
17
+ parameter :meta_data
18
+ end
19
+
20
+ class Response < Remit::Response
21
+ parameter :transaction_response, :type => TransactionResponse
22
+ end
23
+
24
+ def write_off_debt(request = Request.new)
25
+ call(request, Response)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,52 @@
1
+ module Remit
2
+ class PipelineResponse
3
+ def initialize(uri, secret_key)
4
+ @uri = URI.parse(uri)
5
+ @secret_key = secret_key
6
+ end
7
+
8
+ # Returns +true+ if the response is correctly signed (awsSignature).
9
+ #
10
+ #--
11
+ # The unescape_value method is used here because the awsSignature value
12
+ # pulled from the request is filtered through the same method.
13
+ #++
14
+ def valid?
15
+ return false unless given_signature
16
+ Relax::Query.unescape_value(correct_signature) == given_signature
17
+ end
18
+
19
+ # Returns +true+ if the response returns a successful state.
20
+ def successful?
21
+ [
22
+ Remit::PipelineStatusCode::SUCCESS_ABT,
23
+ Remit::PipelineStatusCode::SUCCESS_ACH,
24
+ Remit::PipelineStatusCode::SUCCESS_CC,
25
+ Remit::PipelineStatusCode::SUCCESS_RECIPIENT_TOKEN_INSTALLED
26
+ ].include?(request_query[:status])
27
+ end
28
+
29
+ def method_missing(method, *args) #:nodoc:
30
+ if request_query.has_key?(method.to_sym)
31
+ request_query[method.to_sym]
32
+ else
33
+ super
34
+ end
35
+ end
36
+
37
+ def request_query(reload = false)
38
+ @query ||= Remit::SignedQuery.parse(@uri, @secret_key, @uri.query || '')
39
+ end
40
+ private :request_query
41
+
42
+ def given_signature
43
+ request_query[:awsSignature]
44
+ end
45
+ private :given_signature
46
+
47
+ def correct_signature
48
+ Remit::SignedQuery.new(@uri.path, @secret_key, request_query).sign
49
+ end
50
+ private :correct_signature
51
+ end
52
+ end
@@ -0,0 +1,36 @@
1
+ require File.dirname(__FILE__) + '/integrations_helper'
2
+
3
+ describe 'a GetAccountActivity call' do
4
+ it_should_behave_like 'a successful response'
5
+
6
+ before(:all) do
7
+ request = Remit::GetAccountActivity::Request.new
8
+ request.start_date = Date.today - 7
9
+ @response = remit.get_account_activity(request)
10
+ end
11
+
12
+ it 'should have a collection of transactions' do
13
+ @response.should have_at_least(1).transactions
14
+ end
15
+
16
+ it 'should have a transaction with all of its values set' do
17
+ transaction = @response.transactions.first
18
+ transaction.caller_name.should_not be_empty
19
+ transaction.caller_token_id.should_not be_empty
20
+ transaction.caller_transaction_date.should_not be_nil
21
+ transaction.date_completed.should_not be_nil
22
+ transaction.date_received.should_not be_nil
23
+ transaction.error_code.should be_empty
24
+ transaction.error_detail.should be_nil
25
+ transaction.error_message.should be_nil
26
+ transaction.fees.should_not be_nil
27
+ transaction.operation.should_not be_empty
28
+ transaction.recipient_name.should_not be_empty
29
+ transaction.sender_name.should_not be_empty
30
+ transaction.sender_token_id.should_not be_empty
31
+ transaction.status.should_not be_empty
32
+ transaction.transaction_amount.should_not be_nil
33
+ transaction.transaction_id.should_not be_empty
34
+ transaction.transaction_parts.should_not be_empty
35
+ end
36
+ end
@@ -0,0 +1,38 @@
1
+ require File.dirname(__FILE__) + '/integrations_helper'
2
+
3
+ describe 'a GetTokens call' do
4
+ it_should_behave_like 'a successful response'
5
+
6
+ before(:all) do
7
+ @response = remit.get_tokens
8
+ end
9
+
10
+ it 'should have a collection of tokens' do
11
+ @response.should have_at_least(1).tokens
12
+ end
13
+
14
+ it 'should have a token with all of its values set' do
15
+ token = @response.tokens.first
16
+ token.token_id.should_not be_empty
17
+ token.friendly_name.should_not be_empty
18
+ token.status.should_not be_empty
19
+ token.date_installed.should_not be_nil
20
+ token.caller_installed.should_not be_empty
21
+ token.caller_reference.should_not be_empty
22
+ token.token_type.should_not be_empty
23
+ token.old_token_id.should_not be_empty
24
+ token.payment_reason.should_not be_empty
25
+ end
26
+
27
+ it 'should have a token with a token ID' do
28
+ @response.tokens.first.token_id.should_not be_empty
29
+ end
30
+
31
+ it 'should have a token with a valid token status' do
32
+ @response.tokens.first.status.should match(/^(IN)?ACTIVE$/i)
33
+ end
34
+
35
+ it 'should have a token with a valid installation date' do
36
+ @response.tokens.first.date_installed.should be_a_kind_of(Time)
37
+ end
38
+ end
@@ -0,0 +1,8 @@
1
+ ACCESS_KEY = ENV['AWS_ACCESS_KEY'] || ENV['AMAZON_ACCESS_KEY_ID']
2
+ SECRET_KEY = ENV['AWS_SECRET_KEY'] || ENV['AMAZON_SECRET_ACCESS_KEY']
3
+
4
+ unless ACCESS_KEY and SECRET_KEY
5
+ raise RuntimeError, "You must set your AWS_ACCESS_KEY and AWS_SECRET_KEY environment variables to run integration tests"
6
+ end
7
+
8
+ require File.dirname(__FILE__) + '/../spec_helper'
@@ -0,0 +1,36 @@
1
+ require 'rubygems'
2
+ require 'spec'
3
+
4
+ require File.dirname(__FILE__) + '/../lib/remit'
5
+
6
+ def remit
7
+ @remit ||= Remit::API.new(ACCESS_KEY, SECRET_KEY, true)
8
+ end
9
+
10
+ describe 'a successful response', :shared => true do
11
+ it 'should return success' do
12
+ @response.status.should == 'Success'
13
+ end
14
+
15
+ it 'should not have any errors' do
16
+ @response.errors.should be_nil
17
+ end
18
+
19
+ it 'should have a request ID' do
20
+ @response.request_id.should_not be_nil
21
+ end
22
+ end
23
+
24
+ describe 'a failed response', :shared => true do
25
+ it "is not successful" do
26
+ @response.should_not be_successful
27
+ end
28
+
29
+ it "has a request id" do
30
+ @response.request_id.should_not be_empty
31
+ end
32
+
33
+ it "has errors" do
34
+ @response.errors.should_not be_empty
35
+ end
36
+ end
@@ -0,0 +1,165 @@
1
+ require File.dirname(__FILE__) + '/units_helper'
2
+
3
+ describe 'A pipeline', :shared => true do
4
+ before do
5
+ @pipeline_options = {
6
+ :return_url => 'http://example.com/'
7
+ }
8
+ end
9
+
10
+ it 'should sign its URL' do
11
+ uri = URI.parse(@pipeline.url)
12
+ pipeline = Remit::SignedQuery.parse(uri, remit.secret_key, uri.query)
13
+ query = Relax::Query.parse(uri)
14
+
15
+ pipeline[:awsSignature].should == query[:awsSignature]
16
+ end
17
+ end
18
+
19
+ describe 'A single-use pipeline' do
20
+ it_should_behave_like 'A pipeline'
21
+
22
+ before do
23
+ @pipeline_options.merge!({
24
+ :transaction_amount => 10,
25
+ :caller_reference => 'N2PCBEIA5864E27EL7C86PJL1FGUGPBL61QTJJM5GQK265SPEN8ZKIJPMQARDVJK',
26
+ :recipient_token => 'N5PCME5A5Q6FE2QEB7CD64JLGFTUGXBE61HTCJMGGAK2R5IPEQ8EKIVP3QAVD7JP'
27
+ })
28
+
29
+ @pipeline = remit.get_single_use_pipeline(@pipeline_options)
30
+ end
31
+
32
+ it 'should ignore unused parameters' do
33
+ uri = URI.parse(@pipeline.url)
34
+ query = Relax::Query.parse(uri)
35
+
36
+ query[:paymentReason].should be_nil
37
+ end
38
+
39
+ it 'should have the right name' do
40
+ @pipeline.pipeline_name.should == Remit::PipelineName::SINGLE_USE
41
+ end
42
+ end
43
+
44
+ describe 'A multi-use pipeline' do
45
+ it_should_behave_like 'A pipeline'
46
+
47
+ before do
48
+ @pipeline_options.merge!({
49
+ :transaction_amount => 10,
50
+ :caller_reference => 'N2PCBEIA5864E27EL7C86PJL1FGUGPBL61QTJJM5GQK265SPEN8ZKIJPMQARDVJK',
51
+ :recipient_token_list => 'N5PCME5A5Q6FE2QEB7CD64JLGFTUGXBE61HTCJMGGAK2R5IPEQ8EKIVP3QAVD7JP'
52
+ })
53
+
54
+ @pipeline = remit.get_multi_use_pipeline(@pipeline_options)
55
+ end
56
+
57
+ it 'should ignore unused parameters' do
58
+ uri = URI.parse(@pipeline.url)
59
+ query = Relax::Query.parse(uri)
60
+
61
+ query[:paymentReason].should be_nil
62
+ end
63
+
64
+ it 'should have the right name' do
65
+ @pipeline.pipeline_name.should == Remit::PipelineName::MULTI_USE
66
+ end
67
+ end
68
+
69
+ describe 'A recipient pipeline' do
70
+ it_should_behave_like 'A pipeline'
71
+
72
+ before do
73
+ @validity_start = Time.now + (3600 * 24) # 1 day from now
74
+ @validity_expiry = Time.now + (2600 * 24 * 180) # ~6 months from now
75
+
76
+ @pipeline_options.merge!({
77
+ :validity_start => @validity_start,
78
+ :validity_expiry => @validity_expiry,
79
+ :caller_reference => 'N2PCBEIA5864E27EL7C86PJL1FGUGPBL61QTJJM5GQK265SPEN8ZKIJPMQARDVJK',
80
+ :max_variable_fee => '0.25',
81
+ :recipient_pays_fee => true
82
+ })
83
+
84
+ @pipeline = remit.get_recipient_pipeline(@pipeline_options)
85
+ end
86
+
87
+ it 'should have the recipient pay marketplace fees' do
88
+ @pipeline.url.should match(/recipientPaysFee=true/)
89
+ end
90
+
91
+ it 'should have the right name' do
92
+ @pipeline.pipeline_name.should == Remit::PipelineName::RECIPIENT
93
+ end
94
+ end
95
+
96
+ describe 'A recurring-use pipeline' do
97
+ it_should_behave_like 'A pipeline'
98
+
99
+ before do
100
+ @validity_start = Time.now + (3600 * 24) # 1 day from now
101
+ @validity_expiry = Time.now + (3600 * 24 * 180) # ~6 months from now
102
+ @recurring_period = '1 Month'
103
+
104
+ @pipeline_options.merge!({
105
+ :validity_start => @validity_start,
106
+ :validity_expiry => @validity_expiry,
107
+ :recurring_period => @recurring_period,
108
+ :transaction_amount => 10,
109
+ :caller_reference => 'N2PCBEIA5864E27EL7C86PJL1FGUGPBL61QTJJM5GQK265SPEN8ZKIJPMQARDVJK',
110
+ :recipient_token => 'N5PCME5A5Q6FE2QEB7CD64JLGFTUGXBE61HTCJMGGAK2R5IPEQ8EKIVP3QAVD7JP'
111
+ })
112
+
113
+ @pipeline = remit.get_recurring_use_pipeline(@pipeline_options)
114
+ end
115
+
116
+ it 'should convert times to seconds from epoch' do
117
+ uri = URI.parse(@pipeline.url)
118
+ query = Relax::Query.parse(uri)
119
+
120
+ @validity_start.to_i.to_s.should == query[:validityStart]
121
+ @validity_expiry.to_i.to_s.should == query[:validityExpiry]
122
+ end
123
+
124
+ it 'should allow time in seconds' do
125
+ options = @pipeline_options.merge({
126
+ :validity_start => @validity_start.to_i,
127
+ :validity_expiry => @validity_expiry.to_i
128
+ })
129
+ @pipeline = remit.get_recurring_use_pipeline(options)
130
+
131
+ uri = URI.parse(@pipeline.url)
132
+ query = Relax::Query.parse(uri)
133
+
134
+ @validity_start.to_i.to_s.should == query[:validityStart]
135
+ @validity_expiry.to_i.to_s.should == query[:validityExpiry]
136
+ end
137
+
138
+ it 'should have the right name' do
139
+ @pipeline.pipeline_name.should == Remit::PipelineName::RECURRING
140
+ end
141
+ end
142
+
143
+ describe 'A postpaid pipeline' do
144
+ it_should_behave_like 'A pipeline'
145
+
146
+ before do
147
+ @credit_limit = 100
148
+ @global_amount_limit = 100
149
+
150
+ @pipeline_options.merge!({
151
+ :credit_limit => @credit_limit,
152
+ :global_amount_limit => @global_amount_limit
153
+ })
154
+
155
+ @pipeline = remit.get_postpaid_pipeline(@pipeline_options)
156
+ end
157
+
158
+ it 'should create a PostpaidPipeline' do
159
+ @pipeline.class.should == Remit::GetPipeline::PostpaidPipeline
160
+ end
161
+
162
+ it 'should have the right name' do
163
+ @pipeline.pipeline_name.should == Remit::PipelineName::SETUP_POSTPAID
164
+ end
165
+ end