dbalatero-fpswax 0.0.1 → 0.0.2

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.
data/Rakefile CHANGED
@@ -11,6 +11,7 @@ begin
11
11
  gem.authors = ["David Balatero"]
12
12
 
13
13
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
14
+ gem.add_dependency('nokogiri', '>= 1.2.3')
14
15
  end
15
16
  rescue LoadError
16
17
  puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :minor: 0
3
- :patch: 1
3
+ :patch: 2
4
4
  :major: 0
@@ -6,7 +6,7 @@ module Fpswax
6
6
  module HmacSignature
7
7
  private
8
8
  def generate_signature_for(params, secret_key)
9
- query = params.sort_by { |k,v| k.downcase }
9
+ query = params.sort_by { |k,v| k.to_s.downcase }
10
10
  digest = OpenSSL::Digest::Digest.new('sha1')
11
11
  hmac = OpenSSL::HMAC.digest(digest, secret_key, query.to_s)
12
12
  encoded = Base64.encode64(hmac).chomp
@@ -0,0 +1,34 @@
1
+ module Fpswax
2
+ class PayResponse < Response
3
+ attr_reader :transaction_id
4
+ attr_reader :transaction_status
5
+
6
+ def initialize(xml)
7
+ super(xml)
8
+ if valid?
9
+ @transaction_id = xml.css('PayResult TransactionId')[0].content rescue nil
10
+ @transaction_status = xml.css('PayResult TransactionStatus')[0].content rescue nil
11
+ end
12
+ end
13
+
14
+ def cancelled?
15
+ @transaction_status == 'Cancelled'
16
+ end
17
+
18
+ def failure?
19
+ @transaction_status == 'Failure'
20
+ end
21
+
22
+ def pending?
23
+ @transaction_status == 'Pending'
24
+ end
25
+
26
+ def reserved?
27
+ @transaction_status == 'Reserved'
28
+ end
29
+
30
+ def success?
31
+ @transaction_status == 'Success'
32
+ end
33
+ end
34
+ end
@@ -10,14 +10,14 @@ module Fpswax
10
10
  end
11
11
 
12
12
  if @errors.empty?
13
- @request_id = xml.css('RequestId')[0].content
13
+ @request_id = xml.css('RequestId')[0].content rescue nil
14
14
  else
15
- @request_id = xml.css('RequestID')[0].content
15
+ @request_id = xml.css('RequestID')[0].content rescue nil
16
16
  end
17
17
  end
18
18
 
19
19
  def valid?
20
- @errors.empty?
20
+ @request_id && @errors.empty?
21
21
  end
22
22
  end
23
23
  end
@@ -7,16 +7,25 @@ module Fpswax
7
7
 
8
8
  include Mixins::HmacSignature
9
9
 
10
+ attr_accessor :logger
11
+
10
12
  def initialize(access_key, secret_key, sandbox = true)
11
13
  @access_key = access_key
12
14
  @secret_key = secret_key
13
15
  @sandbox = sandbox
16
+
17
+ @logger = Logger.new(STDOUT)
18
+ @logger.level = Logger::WARN
14
19
  end
15
20
 
16
21
  def in_sandbox?
17
22
  @sandbox
18
23
  end
19
24
 
25
+ def fps_url
26
+ @sandbox ? 'https://fps.sandbox.amazonaws.com' : 'https://fps.amazonaws.com'
27
+ end
28
+
20
29
  def api_version
21
30
  API_VERSION
22
31
  end
@@ -31,12 +40,60 @@ module Fpswax
31
40
  validate_required?(params,
32
41
  :CallerReference,
33
42
  :SenderTokenId,
34
- :TransactionAmount)
43
+ :"TransactionAmount.CurrencyCode",
44
+ :"TransactionAmount.Value")
35
45
 
36
- #get_response('Pay', PayResponse, params)
46
+ get_response(:Pay, PayResponse, params)
37
47
  end
38
48
 
39
49
  private
50
+ def get_response(action, response_klass, params)
51
+ add_params_for_request!(action, params)
52
+ response = self.class.post(fps_url,
53
+ :params => params)
54
+
55
+ @logger.debug("get_response") {
56
+ "Got XML response:\n#{response.body}"
57
+ }
58
+
59
+ response_klass.new(Nokogiri::XML(response.body))
60
+ end
61
+
62
+ def self.post(url, options = {})
63
+ url = URI.parse(url) if url.is_a?(String)
64
+ conn = Net::HTTP.new(url.host, url.port)
65
+ if conn.port == 443
66
+ conn.use_ssl = true
67
+ end
68
+
69
+ req = Net::HTTP::Post.new(url.request_uri)
70
+ req.form_data = options[:params]
71
+
72
+ conn.start do |http|
73
+ http.request(req)
74
+ end
75
+ end
76
+
77
+ def add_params_for_request!(action, params)
78
+ # Required params for all requests:
79
+ # http://docs.amazonwebservices.com/AmazonFPS/latest/FPSAdvancedGuide/CommonRequestParameters.html
80
+ params.merge!(:Action => action,
81
+ :AWSAccessKeyId => @access_key,
82
+ :SignatureVersion => 1,
83
+ :Timestamp => Time.now.utc.strftime('%Y-%m-%dT%H:%M:%SZ'),
84
+ :Version => api_version)
85
+
86
+ # Generate an HMAC signature.
87
+ signature = generate_signature_for(params, @secret_key)
88
+ params[:Signature] = signature
89
+
90
+ @logger.debug('add_params_for_request!') do
91
+ "Params for request (#{action}): #{params.inspect}"
92
+ end
93
+
94
+ params
95
+ end
96
+
40
97
  def validate_required?(hash, *args)
41
98
  args.each do |arg|
42
99
  raise(ParameterRequired, "This method requires #{arg} to be passed in!") if !hash[arg]
data/lib/fpswax.rb CHANGED
@@ -1,7 +1,11 @@
1
1
  $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
2
2
 
3
+ require 'logger'
3
4
  require 'openssl'
4
5
  require 'nokogiri'
6
+ require 'net/http'
7
+ require 'net/https'
8
+ require 'uri'
5
9
 
6
10
  require 'fpswax/mixins/hmac_signature'
7
11
 
@@ -10,5 +14,7 @@ require 'fpswax/ipn_request'
10
14
  require 'fpswax/response'
11
15
  require 'fpswax/session'
12
16
 
17
+ require 'fpswax/pay_response'
18
+
13
19
  module Fpswax
14
20
  end
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0"?>
2
+ <PayResponse xmlns="http://fps.amazonaws.com/doc/2008-09-17/"><PayResult><TransactionId>145ST343M4FVUENSE545EV1BL7H6OU421QP</TransactionId><TransactionStatus>Cancelled</TransactionStatus></PayResult><ResponseMetadata><RequestId>49da36a0-732a-4180-b0dd-c22fe2e0dd0b:0</RequestId></ResponseMetadata></PayResponse>
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0"?>
2
+ <Response><Errors><Error><Code>InvalidParams</Code><Message>"senderTokenId" has to be a valid token ID. Specified value: NOGNOOLIE</Message></Error></Errors><RequestID>92c73846-af37-4b36-8f31-78a26d6ea65c</RequestID></Response>
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0"?>
2
+ <PayResponse xmlns="http://fps.amazonaws.com/doc/2008-09-17/"><PayResult><TransactionId>145ST343M4FVUENSE545EV1BL7H6OU421QP</TransactionId><TransactionStatus>Failure</TransactionStatus></PayResult><ResponseMetadata><RequestId>49da36a0-732a-4180-b0dd-c22fe2e0dd0b:0</RequestId></ResponseMetadata></PayResponse>
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0"?>
2
+ <PayResponse xmlns="http://fps.amazonaws.com/doc/2008-09-17/"><PayResult><TransactionId>145ST343M4FVUENSE545EV1BL7H6OU421QP</TransactionId><TransactionStatus>Pending</TransactionStatus></PayResult><ResponseMetadata><RequestId>49da36a0-732a-4180-b0dd-c22fe2e0dd0b:0</RequestId></ResponseMetadata></PayResponse>
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0"?>
2
+ <PayResponse xmlns="http://fps.amazonaws.com/doc/2008-09-17/"><PayResult><TransactionId>145ST343M4FVUENSE545EV1BL7H6OU421QP</TransactionId><TransactionStatus>Reserved</TransactionStatus></PayResult><ResponseMetadata><RequestId>49da36a0-732a-4180-b0dd-c22fe2e0dd0b:0</RequestId></ResponseMetadata></PayResponse>
@@ -0,0 +1,2 @@
1
+ <?xml version="1.0"?>
2
+ <PayResponse xmlns="http://fps.amazonaws.com/doc/2008-09-17/"><PayResult><TransactionId>145ST343M4FVUENSE545EV1BL7H6OU421QP</TransactionId><TransactionStatus>Success</TransactionStatus></PayResult><ResponseMetadata><RequestId>49da36a0-732a-4180-b0dd-c22fe2e0dd0b:0</RequestId></ResponseMetadata></PayResponse>
@@ -0,0 +1,13 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe Fpswax::Mixins::HmacSignature do
4
+ include Fpswax::Mixins::HmacSignature
5
+
6
+ describe "generate_signature_for" do
7
+ it "should accept symboled keys" do
8
+ lambda {
9
+ generate_signature_for({:key1 => 'ok'}, 'my key')
10
+ }.should_not raise_error
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,44 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Fpswax::PayResponse do
4
+ it "should be a Response" do
5
+ pay = Fpswax::PayResponse.new(mock_xml)
6
+ pay.should be_a_kind_of(Fpswax::Response)
7
+ end
8
+
9
+ it "should handle errors correctly" do
10
+ pay = Fpswax::PayResponse.new(fixture_raw_xml('pay/error.xml'))
11
+ pay.should_not be_valid
12
+ pay.errors.should have(1).thing
13
+ end
14
+
15
+ describe "any pay response" do
16
+ before(:each) do
17
+ @pay = Fpswax::PayResponse.new(fixture_raw_xml('pay/pending.xml'))
18
+ end
19
+
20
+ it "should have its transaction status" do
21
+ @pay.transaction_status.should == 'Pending'
22
+ end
23
+
24
+ it "should have its transaction ID" do
25
+ @pay.transaction_id.should == '145ST343M4FVUENSE545EV1BL7H6OU421QP'
26
+ end
27
+ end
28
+
29
+ ['cancelled', 'failure', 'pending', 'reserved', 'success'].each do |status|
30
+ describe "a pending pay response" do
31
+ before(:each) do
32
+ @pay = Fpswax::PayResponse.new(fixture_raw_xml("pay/#{status}.xml"))
33
+ end
34
+
35
+ it "should be valid" do
36
+ @pay.should be_valid
37
+ end
38
+
39
+ it "should be #{status}" do
40
+ @pay.send("#{status}?".to_sym).should be_true
41
+ end
42
+ end
43
+ end
44
+ end
@@ -31,5 +31,10 @@ describe Fpswax::Response do
31
31
  response = Fpswax::Response.new(xml)
32
32
  response.should_not be_valid
33
33
  end
34
+
35
+ it "should be false if there was no parsed request id" do
36
+ response = Fpswax::Response.new(mock_xml)
37
+ response.should_not be_valid
38
+ end
34
39
  end
35
40
  end
@@ -1,6 +1,10 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
2
 
3
3
  describe Fpswax::Session do
4
+ before(:each) do
5
+ FakeWeb.clean_registry
6
+ end
7
+
4
8
  describe "initialize" do
5
9
  it "should take an access key, private key" do
6
10
  lambda {
@@ -45,14 +49,18 @@ describe Fpswax::Session do
45
49
  @valid_params = {
46
50
  :CallerReference => 'a',
47
51
  :SenderTokenId => 'b',
48
- :TransactionAmount => 'c'
52
+ :"TransactionAmount.CurrencyCode" => 'USD',
53
+ :"TransactionAmount.Value" => 'c'
49
54
  }
50
55
  end
51
56
 
52
57
  it "should return a PayResponse" do
53
- pending
58
+ FakeWeb.register_uri(:post,
59
+ 'https://fps.sandbox.amazonaws.com:443/',
60
+ :file => fixture_path('pay/success.xml'))
54
61
  response = @session.pay(@valid_params)
55
- response.should be_an_instance_of(PayResponse)
62
+ response.should be_an_instance_of(Fpswax::PayResponse)
63
+ response.should be_valid
56
64
  end
57
65
 
58
66
  describe "should validate parameters" do
@@ -72,5 +80,35 @@ describe Fpswax::Session do
72
80
  }.should_not raise_error(Fpswax::Session::ParameterRequired)
73
81
  end
74
82
  end
83
+
84
+ describe "fps_url" do
85
+ it "should point at the production API if we are in production" do
86
+ session = Fpswax::Session.new('a', 'b', false)
87
+ session.should_not be_in_sandbox
88
+ session.fps_url.should == 'https://fps.amazonaws.com'
89
+ end
90
+
91
+ it "should point at the sandbox API if we aren't in production" do
92
+ session = Fpswax::Session.new('a', 'b', true)
93
+ session.should be_in_sandbox
94
+ session.fps_url.should == 'https://fps.sandbox.amazonaws.com'
95
+ end
96
+ end
97
+
98
+ describe "logger" do
99
+ before(:each) do
100
+ @session = Fpswax::Session.new('a', 'b')
101
+ end
102
+
103
+ it "should return a logger object" do
104
+ @session.logger.should be_a_kind_of(Logger)
105
+ end
106
+
107
+ it "should be able to be set to something else" do
108
+ lambda {
109
+ @session.logger = Logger.new(STDOUT)
110
+ }.should_not raise_error
111
+ end
112
+ end
75
113
  end
76
114
  end
data/spec/spec_helper.rb CHANGED
@@ -4,6 +4,13 @@ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
4
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
5
  require 'fpswax'
6
6
 
7
+ begin
8
+ require 'fakeweb'
9
+ FakeWeb.allow_net_connect = false
10
+ rescue LoadError
11
+ abort "You need fakeweb installed to run specs. gem install fakeweb."
12
+ end
13
+
7
14
  Spec::Runner.configure do |config|
8
15
 
9
16
  end
@@ -15,3 +22,7 @@ end
15
22
  def fixture_raw_xml(path)
16
23
  Nokogiri::XML(File.read(fixture_path(path)))
17
24
  end
25
+
26
+ def mock_xml
27
+ Nokogiri::XML("<id>2</id>")
28
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dbalatero-fpswax
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Balatero
@@ -9,10 +9,19 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-05-23 00:00:00 -07:00
12
+ date: 2009-05-25 00:00:00 -07:00
13
13
  default_executable:
14
- dependencies: []
15
-
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: nokogiri
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.2.3
24
+ version:
16
25
  description:
17
26
  email: david@bitwax.cd
18
27
  executables: []
@@ -31,12 +40,21 @@ files:
31
40
  - lib/fpswax/error.rb
32
41
  - lib/fpswax/ipn_request.rb
33
42
  - lib/fpswax/mixins/hmac_signature.rb
43
+ - lib/fpswax/pay_response.rb
34
44
  - lib/fpswax/response.rb
35
45
  - lib/fpswax/session.rb
46
+ - spec/fixtures/pay/cancelled.xml
47
+ - spec/fixtures/pay/error.xml
48
+ - spec/fixtures/pay/failure.xml
49
+ - spec/fixtures/pay/pending.xml
50
+ - spec/fixtures/pay/reserved.xml
51
+ - spec/fixtures/pay/success.xml
36
52
  - spec/fixtures/raw/errors.xml
37
53
  - spec/fixtures/raw/request_id.xml
38
54
  - spec/fpswax/error_spec.rb
39
55
  - spec/fpswax/ipn_request_spec.rb
56
+ - spec/fpswax/mixins/hmac_signature_spec.rb
57
+ - spec/fpswax/pay_response_spec.rb
40
58
  - spec/fpswax/response_spec.rb
41
59
  - spec/fpswax/session_spec.rb
42
60
  - spec/spec_helper.rb
@@ -69,6 +87,8 @@ summary: A library for interfacing with Amazon FPS, without any "cleverness".
69
87
  test_files:
70
88
  - spec/fpswax/error_spec.rb
71
89
  - spec/fpswax/ipn_request_spec.rb
90
+ - spec/fpswax/mixins/hmac_signature_spec.rb
91
+ - spec/fpswax/pay_response_spec.rb
72
92
  - spec/fpswax/response_spec.rb
73
93
  - spec/fpswax/session_spec.rb
74
94
  - spec/spec_helper.rb