micah-remit 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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