amazon_flex_pay 0.9.14 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -7,7 +7,6 @@ task :default => :test
7
7
 
8
8
  desc 'Test the AmazonFlexPay plugin.'
9
9
  Rake::TestTask.new(:test) do |t|
10
- t.libs << 'lib'
11
10
  t.libs << 'test'
12
11
  t.pattern = 'test/**/*_test.rb'
13
12
  t.verbose = true
@@ -9,19 +9,35 @@ require 'active_support' # camelcase, underscore
9
9
  require 'active_support/inflector'
10
10
  require 'active_support/notifications'
11
11
 
12
- require 'amazon_flex_pay/signing'
13
- require 'amazon_flex_pay/model'
14
- require 'amazon_flex_pay/enumerations'
15
- require 'amazon_flex_pay/data_types'
12
+ require_relative 'amazon_flex_pay/util'
13
+ require_relative 'amazon_flex_pay/signature'
14
+ require_relative 'amazon_flex_pay/model'
15
+ require_relative 'amazon_flex_pay/enumerations'
16
+ require_relative 'amazon_flex_pay/data_types'
16
17
 
17
- require 'amazon_flex_pay/api'
18
- require 'amazon_flex_pay/pipelines'
18
+ require_relative 'amazon_flex_pay/api'
19
+ require_relative 'amazon_flex_pay/pipelines'
19
20
 
20
21
  module AmazonFlexPay
21
- VERSION = '0.9.14'
22
+ VERSION = '0.10.0'
22
23
  API_VERSION = '2011-09-20'
23
24
  PIPELINE_VERSION = '2009-01-09'
24
25
 
26
+ ENDPOINTS = {
27
+ :sandbox => {
28
+ :api => 'https://fps.sandbox.amazonaws.com/',
29
+ :cbui => 'https://authorize.payments-sandbox.amazon.com/cobranded-ui/actions/start'
30
+ }.freeze,
31
+ :live => {
32
+ :api => 'https://fps.amazonaws.com/',
33
+ :cbui => 'https://authorize.payments.amazon.com/cobranded-ui/actions/start'
34
+ }.freeze
35
+ }
36
+
37
+ extend Util
38
+ extend AmazonFlexPay::API
39
+ extend AmazonFlexPay::Pipelines
40
+
25
41
  class << self
26
42
  attr_accessor :access_key
27
43
  attr_accessor :secret_key
@@ -30,7 +46,7 @@ module AmazonFlexPay
30
46
  #
31
47
  # Defaults to the sandbox unless you set it explicitly or call <tt>go_live!</tt>.
32
48
  def api_endpoint
33
- @api_endpoint ||= 'https://fps.sandbox.amazonaws.com/'
49
+ @api_endpoint ||= ENDPOINTS[:sandbox][:api]
34
50
  end
35
51
  attr_writer :api_endpoint
36
52
 
@@ -38,7 +54,7 @@ module AmazonFlexPay
38
54
  #
39
55
  # Defaults to the sandbox unless you set it explicitly or call <tt>go_live!</tt>.
40
56
  def pipeline_endpoint
41
- @pipeline_endpoint ||= 'https://authorize.payments-sandbox.amazon.com/cobranded-ui/actions/start'
57
+ @pipeline_endpoint ||= ENDPOINTS[:sandbox][:cbui]
42
58
  end
43
59
  attr_writer :pipeline_endpoint
44
60
 
@@ -46,9 +62,14 @@ module AmazonFlexPay
46
62
  #
47
63
  # Call <tt>AmazonFlexPay.go_live!</tt> to enable live transactions and real money in this environment.
48
64
  def go_live!
49
- self.api_endpoint = 'https://fps.amazonaws.com/'
50
- self.pipeline_endpoint = 'https://authorize.payments.amazon.com/cobranded-ui/actions/start'
65
+ self.api_endpoint = ENDPOINTS[:live][:api]
66
+ self.pipeline_endpoint = ENDPOINTS[:live][:cbui]
51
67
  end
68
+
69
+ def sign(endpoint, params)
70
+ Signature.new(secret_key, endpoint, params).generate
71
+ end
72
+
52
73
  end
53
74
 
54
75
  end
@@ -1,21 +1,20 @@
1
- # load all api classes
2
- require 'amazon_flex_pay/api/base_request'
3
- Dir[File.dirname(__FILE__) + '/api/*'].each do |p| require "amazon_flex_pay/api/#{File.basename(p)}" end
1
+ require_relative 'api/base_request'
2
+ Dir[File.dirname(__FILE__) + '/api/*'].each do |p| require_relative "api/#{File.basename(p)}" end
4
3
 
5
4
  module AmazonFlexPay
6
- class << self
5
+ module API
7
6
  # Cancels a transaction.
8
7
  #
9
8
  # See http://docs.amazonwebservices.com/AmazonFPS/latest/FPSAdvancedGuide/Cancel.html
10
9
  def cancel(transaction_id, options = {})
11
- API::Cancel.new(options.merge(:transaction_id => transaction_id)).submit
10
+ submit Cancel.new(options.merge(:transaction_id => transaction_id))
12
11
  end
13
12
 
14
13
  # Cancels a token.
15
14
  #
16
15
  # See http://docs.amazonwebservices.com/AmazonFPS/latest/FPSAdvancedGuide/CancelToken.html
17
16
  def cancel_token(token_id, options = {})
18
- API::CancelToken.new(options.merge(:token_id => token_id)).submit
17
+ submit CancelToken.new(options.merge(:token_id => token_id))
19
18
  end
20
19
 
21
20
  # Searches through transactions on your account. Helpful if you want to compare vs your own records,
@@ -23,21 +22,21 @@ module AmazonFlexPay
23
22
  #
24
23
  # See http://docs.amazonwebservices.com/AmazonFPS/latest/FPSAccountManagementGuide/GetAccountActivity.html
25
24
  def get_account_activity(start_date, end_date, options = {})
26
- API::GetAccountActivity.new(options.merge(:start_date => start_date, :end_date => end_date)).submit
25
+ submit GetAccountActivity.new(options.merge(:start_date => start_date, :end_date => end_date))
27
26
  end
28
27
 
29
28
  # Gets your Amazon Payments account balance.
30
29
  #
31
30
  # See http://docs.amazonwebservices.com/AmazonFPS/latest/FPSAccountManagementGuide/GetAccountBalance.html
32
31
  def get_account_balance
33
- API::GetAccountBalance.new.submit
32
+ submit GetAccountBalance.new
34
33
  end
35
34
 
36
35
  # Returns the status of a recipient's Amazon account.
37
36
  #
38
37
  # See http://docs.amazonwebservices.com/AmazonFPS/latest/FPSAdvancedGuide/GetRecipientVerificationStatus.html
39
38
  def get_recipient_verification_status(recipient_token_id)
40
- API::GetRecipientVerificationStatus.new(:recipient_token_id => recipient_token_id).submit
39
+ submit GetRecipientVerificationStatus.new(:recipient_token_id => recipient_token_id)
41
40
  end
42
41
 
43
42
  # Returns information about a token's state from a caller reference.
@@ -48,21 +47,21 @@ module AmazonFlexPay
48
47
  #
49
48
  # See http://docs.amazonwebservices.com/AmazonFPS/latest/FPSAdvancedGuide/GetTokensByCaller.html
50
49
  def get_token_by_caller_reference(ref)
51
- API::GetTokenByCaller.new(:caller_reference => ref).submit
50
+ submit GetTokenByCaller.new(:caller_reference => ref)
52
51
  end
53
52
 
54
53
  # Returns information about a token's state from a token id.
55
54
  #
56
55
  # See http://docs.amazonwebservices.com/AmazonFPS/latest/FPSAdvancedGuide/GetTokensByCaller.html
57
56
  def get_token_by_id(id)
58
- API::GetTokenByCaller.new(:token_id => id).submit
57
+ submit GetTokenByCaller.new(:token_id => id)
59
58
  end
60
59
 
61
60
  # Returns information about how much of the token has been used, and what remains.
62
61
  #
63
62
  # See http://docs.amazonwebservices.com/AmazonFPS/latest/FPSAccountManagementGuide/GetTokenUsage.html
64
63
  def get_token_usage(id)
65
- API::GetTokenUsage.new(:token_id => id).submit
64
+ submit GetTokenUsage.new(:token_id => id)
66
65
  end
67
66
 
68
67
  # Returns all of your tokens. Note that when you send someone through a recipient pipeline, that registers
@@ -74,7 +73,7 @@ module AmazonFlexPay
74
73
  #
75
74
  # See http://docs.amazonwebservices.com/AmazonFPS/latest/FPSAccountManagementGuide/GetTokens.html
76
75
  def get_tokens(options = {})
77
- API::GetTokens.new(options).submit
76
+ submit GetTokens.new(options)
78
77
  end
79
78
 
80
79
  # Returns all of Amazon's details about a transaction, such as its status and when it began and finished
@@ -82,7 +81,7 @@ module AmazonFlexPay
82
81
  #
83
82
  # See http://docs.amazonwebservices.com/AmazonFPS/latest/FPSAccountManagementGuide/GetTransaction.html
84
83
  def get_transaction(id)
85
- API::GetTransaction.new(:transaction_id => id).submit
84
+ submit GetTransaction.new(:transaction_id => id)
86
85
  end
87
86
 
88
87
  # Returns the current status of the transaction. Note that this information is also available from
@@ -90,7 +89,7 @@ module AmazonFlexPay
90
89
  #
91
90
  # See http://docs.amazonwebservices.com/AmazonFPS/latest/FPSAccountManagementGuide/GetTransactionStatus.html
92
91
  def get_transaction_status(id)
93
- API::GetTransactionStatus.new(:transaction_id => id).submit
92
+ submit GetTransactionStatus.new(:transaction_id => id)
94
93
  end
95
94
 
96
95
  # Begins a Pay request for a sender token. If you are not also the recipient (this is a three-party marketplace
@@ -100,11 +99,11 @@ module AmazonFlexPay
100
99
  #
101
100
  # See http://docs.amazonwebservices.com/AmazonFPS/latest/FPSAdvancedGuide/Pay.html
102
101
  def pay(value, currency, sender_token_id, caller_reference, options = {})
103
- API::Pay.new(options.merge(
102
+ submit Pay.new(options.merge(
104
103
  :transaction_amount => {:value => value, :currency_code => currency},
105
104
  :sender_token_id => sender_token_id,
106
105
  :caller_reference => caller_reference
107
- )).submit
106
+ ))
108
107
  end
109
108
 
110
109
  # Begins a Reserve request for the sender token. Very similar to <tt>pay</tt>.
@@ -113,11 +112,11 @@ module AmazonFlexPay
113
112
  #
114
113
  # See http://docs.amazonwebservices.com/AmazonFPS/latest/FPSAdvancedGuide/Reserve.html
115
114
  def reserve(value, currency, sender_token_id, caller_reference, options = {})
116
- API::Reserve.new(options.merge(
115
+ submit Reserve.new(options.merge(
117
116
  :transaction_amount => {:value => value, :currency_code => currency},
118
117
  :sender_token_id => sender_token_id,
119
118
  :caller_reference => caller_reference
120
- )).submit
119
+ ))
121
120
  end
122
121
 
123
122
  # Refunds a transaction. By default it will refund the entire transaction, but you can
@@ -127,7 +126,7 @@ module AmazonFlexPay
127
126
  #
128
127
  # See http://docs.amazonwebservices.com/AmazonFPS/latest/FPSAdvancedGuide/Refund.html
129
128
  def refund(transaction_id, caller_reference, options = {})
130
- API::Refund.new(options.merge(:transaction_id => transaction_id, :caller_reference => caller_reference)).submit
129
+ submit Refund.new(options.merge(:transaction_id => transaction_id, :caller_reference => caller_reference))
131
130
  end
132
131
 
133
132
  # If you have a Reserve transaction, use this to Settle (capture) it.
@@ -136,7 +135,7 @@ module AmazonFlexPay
136
135
  #
137
136
  # See http://docs.amazonwebservices.com/AmazonFPS/latest/FPSAdvancedGuide/Settle.html
138
137
  def settle(transaction_id, options = {})
139
- API::Settle.new(options.merge(:reserve_transaction_id => transaction_id)).submit
138
+ submit Settle.new(options.merge(:reserve_transaction_id => transaction_id))
140
139
  end
141
140
 
142
141
  # This is how you verify IPNs and pipeline responses.
@@ -154,7 +153,35 @@ module AmazonFlexPay
154
153
  #
155
154
  # Please use <tt>verify_request</tt> instead to make sure the URL and params remain properly formatted.
156
155
  def verify_signature(url, params)
157
- API::VerifySignature.new(:url_end_point => url, :http_parameters => params).submit
156
+ submit VerifySignature.new(:url_end_point => url, :http_parameters => params)
157
+ end
158
+
159
+ protected
160
+
161
+ # This compiles an API request object into a URL, sends it to Amazon, and processes
162
+ # the response.
163
+ def submit(request)
164
+ url = request.to_url
165
+ ActiveSupport::Notifications.instrument("amazon_flex_pay.api", :action => request.action_name, :request => url) do |payload|
166
+ begin
167
+ http = RestClient.get(url)
168
+
169
+ payload[:response] = http.body
170
+ payload[:code] = http.code
171
+
172
+ response = request.class::Response.from_xml(http.body)
173
+ response.request = request
174
+ response
175
+
176
+ rescue RestClient::BadRequest, RestClient::Unauthorized, RestClient::Forbidden => e
177
+ payload[:response] = e.http_body
178
+ payload[:code] = e.http_code
179
+
180
+ er = AmazonFlexPay::API::BaseRequest::ErrorResponse.from_xml(e.response.body)
181
+ klass = AmazonFlexPay::API.const_get(er.errors.first.code)
182
+ raise klass.new(er.errors.first.code, er.errors.first.message, er.request_id, request)
183
+ end
184
+ end
158
185
  end
159
186
  end
160
187
  end
@@ -1,45 +1,30 @@
1
1
  module AmazonFlexPay::API #:nodoc:
2
2
  class BaseRequest < AmazonFlexPay::Model
3
- # This compiles an API request object into a URL, sends it to Amazon, and processes
4
- # the response.
5
- def submit
6
- url = AmazonFlexPay.api_endpoint + '?' + AmazonFlexPay.query_string(self.to_params)
7
- ActiveSupport::Notifications.instrument("amazon_flex_pay.api", :action => action_name, :request => url) do |payload|
8
- begin
9
- http = RestClient.get(url)
10
-
11
- payload[:response] = http.body
12
- payload[:code] = http.code
13
-
14
- response = self.class::Response.from_xml(http.body)
15
- response.request = self
16
- response
17
-
18
- rescue RestClient::BadRequest, RestClient::Unauthorized, RestClient::Forbidden => e
19
- payload[:response] = e.http_body
20
- payload[:code] = e.http_code
3
+ def to_url
4
+ AmazonFlexPay.api_endpoint + '?' + self.to_param
5
+ end
21
6
 
22
- er = ErrorResponse.from_xml(e.response.body)
23
- klass = AmazonFlexPay::API.const_get(er.errors.first.code)
24
- raise klass.new(er.errors.first.code, er.errors.first.message, er.request_id, self)
25
- end
26
- end
7
+ def to_param
8
+ params = to_hash.merge(
9
+ 'AWSAccessKeyId' => AmazonFlexPay.access_key,
10
+ 'Timestamp' => format_value(Time.now),
11
+ 'SignatureVersion' => 2,
12
+ 'SignatureMethod' => 'HmacSHA256'
13
+ )
14
+ params['Signature'] = AmazonFlexPay.sign(AmazonFlexPay.api_endpoint, params)
15
+ AmazonFlexPay::Util.query_string(params)
27
16
  end
28
17
 
29
18
  # Converts the API request object into parameters and signs them.
30
- def to_params
31
- params = self.to_hash.merge(
19
+ def to_hash
20
+ super.merge(
32
21
  'Action' => action_name,
33
- 'AWSAccessKeyId' => AmazonFlexPay.access_key,
34
- 'Version' => AmazonFlexPay::API_VERSION,
35
- 'Timestamp' => format_value(Time.now)
22
+ 'Version' => AmazonFlexPay::API_VERSION
36
23
  )
24
+ end
37
25
 
38
- params['SignatureVersion'] = 2
39
- params['SignatureMethod'] = 'HmacSHA256'
40
- params['Signature'] = AmazonFlexPay.signature(AmazonFlexPay.api_endpoint, params)
41
-
42
- params
26
+ def action_name #:nodoc:
27
+ self.class.to_s.split('::').last
43
28
  end
44
29
 
45
30
  class BaseResponse < AmazonFlexPay::Model
@@ -77,12 +62,5 @@ module AmazonFlexPay::API #:nodoc:
77
62
  attribute :message
78
63
  end
79
64
  end
80
-
81
-
82
- protected
83
-
84
- def action_name #:nodoc:
85
- self.class.to_s.split('::').last
86
- end
87
65
  end
88
66
  end
@@ -1,15 +1,15 @@
1
- require 'amazon_flex_pay/pipelines/base'
2
- Dir[File.dirname(__FILE__) + '/pipelines/*'].each do |p| require "amazon_flex_pay/pipelines/#{File.basename(p)}" end
1
+ require_relative 'pipelines/base'
2
+ Dir[File.dirname(__FILE__) + '/pipelines/*'].each do |p| require_relative "pipelines/#{File.basename(p)}" end
3
3
 
4
4
  module AmazonFlexPay
5
- class << self
5
+ module Pipelines
6
6
  # Creates a pipeline that may be used to change the payment method of a token.
7
7
  #
8
8
  # Note that this does not allow changing a token's limits or recipients or really anything but the method.
9
9
  #
10
10
  # See http://docs.amazonwebservices.com/AmazonFPS/latest/FPSAdvancedGuide/EditTokenPipeline.html
11
- def edit_token_pipeline(caller_reference, options = {})
12
- AmazonFlexPay::Pipelines::EditToken.new(options.merge(:caller_reference => caller_reference))
11
+ def edit_token_pipeline(caller_reference, return_url, options = {})
12
+ cbui EditToken.new(options.merge(:caller_reference => caller_reference, :return_url => return_url))
13
13
  end
14
14
 
15
15
  # Creates a pipeline that will authorize you to send money _from_ the user multiple times.
@@ -18,15 +18,15 @@ module AmazonFlexPay
18
18
  # you only plan to collect from the token once.
19
19
  #
20
20
  # See http://docs.amazonwebservices.com/AmazonFPS/latest/FPSAdvancedGuide/MultiUsePipeline.html
21
- def multi_use_pipeline(caller_reference, options = {})
22
- AmazonFlexPay::Pipelines::MultiUse.new(options.merge(:caller_reference => caller_reference))
21
+ def multi_use_pipeline(caller_reference, return_url, options = {})
22
+ cbui MultiUse.new(options.merge(:caller_reference => caller_reference, :return_url => return_url))
23
23
  end
24
24
 
25
25
  # Creates a pipeline that will authorize you to send money _to_ the user.
26
26
  #
27
27
  # See http://docs.amazonwebservices.com/AmazonFPS/latest/FPSAdvancedGuide/CBUIapiMerchant.html
28
- def recipient_pipeline(caller_reference, options = {})
29
- AmazonFlexPay::Pipelines::Recipient.new(options.merge(:caller_reference => caller_reference))
28
+ def recipient_pipeline(caller_reference, return_url, options = {})
29
+ cbui Recipient.new(options.merge(:caller_reference => caller_reference, :return_url => return_url))
30
30
  end
31
31
 
32
32
  # Creates a pipeline that will authorize you to send money _from_ the user one time.
@@ -34,8 +34,14 @@ module AmazonFlexPay
34
34
  # Note that if this payment fails, you must create another pipeline to get another token.
35
35
  #
36
36
  # See http://docs.amazonwebservices.com/AmazonFPS/2010-08-28/FPSBasicGuide/SingleUsePipeline.html
37
- def single_use_pipeline(caller_reference, options = {})
38
- AmazonFlexPay::Pipelines::SingleUse.new(options.merge(:caller_reference => caller_reference))
37
+ def single_use_pipeline(caller_reference, return_url, options = {})
38
+ cbui SingleUse.new(options.merge(:caller_reference => caller_reference, :return_url => return_url))
39
+ end
40
+
41
+ protected
42
+
43
+ def cbui(pipeline)
44
+ pipeline.to_url
39
45
  end
40
46
  end
41
47
  end
@@ -1,29 +1,32 @@
1
1
  module AmazonFlexPay::Pipelines #:nodoc:
2
2
  class Base < AmazonFlexPay::Model
3
+ attribute :'returnURL' # required
3
4
  attribute :caller_reference # required
4
5
  attribute :cobranding_style
5
6
  attribute :cobranding_url
6
7
  attribute :website_description
7
8
 
8
9
  # Returns a full redirectable URL for this pipeline.
9
- def url(return_url)
10
- AmazonFlexPay.pipeline_endpoint + '?' + AmazonFlexPay.query_string(to_params(return_url))
10
+ def to_url
11
+ AmazonFlexPay.pipeline_endpoint + '?' + self.to_param
11
12
  end
12
13
 
13
14
  # Converts the Pipeline object into parameters and signs them.
14
- def to_params(return_url)
15
- params = self.to_hash.merge(
16
- 'pipelineName' => pipeline_name,
15
+ def to_param
16
+ params = to_hash.merge(
17
17
  'callerKey' => AmazonFlexPay.access_key,
18
- 'version' => AmazonFlexPay::PIPELINE_VERSION,
19
- 'returnURL' => return_url
18
+ 'signatureVersion' => 2,
19
+ 'signatureMethod' => 'HmacSHA256'
20
20
  )
21
+ params['signature'] = AmazonFlexPay.sign(AmazonFlexPay.pipeline_endpoint, params)
22
+ AmazonFlexPay::Util.query_string(params)
23
+ end
21
24
 
22
- params['signatureVersion'] = 2
23
- params['signatureMethod'] = 'HmacSHA256'
24
- params['signature'] = AmazonFlexPay.signature(AmazonFlexPay.pipeline_endpoint, params)
25
-
26
- params
25
+ def to_hash
26
+ super().merge(
27
+ 'pipelineName' => pipeline_name,
28
+ 'version' => AmazonFlexPay::PIPELINE_VERSION
29
+ )
27
30
  end
28
31
 
29
32
  protected
@@ -0,0 +1,24 @@
1
+ module AmazonFlexPay
2
+ # Generates a signature for the given URL and parameters.
3
+ class Signature
4
+ def initialize(secret_key, endpoint, params)
5
+ @secret_key, @endpoint, @params = secret_key, endpoint, params
6
+ end
7
+
8
+ def generate
9
+ Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, @secret_key, signable)).strip
10
+ end
11
+
12
+ private
13
+
14
+ def signable
15
+ uri = URI.parse(@endpoint)
16
+ [
17
+ 'GET',
18
+ uri.host,
19
+ uri.path,
20
+ AmazonFlexPay::Util.query_string(@params)
21
+ ].join("\n")
22
+ end
23
+ end
24
+ end