dpickett-agcod 0.0.0

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/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
6
+ features/support/app_root/config/agcod.yml
7
+ log
8
+ agcod_cucumber.log
9
+ features/support/certification_requests
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Dan Pickett
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,7 @@
1
+ = agcod
2
+
3
+ Description goes here.
4
+
5
+ == Copyright
6
+
7
+ Copyright (c) 2009 Dan Pickett. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,67 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "agcod"
8
+ gem.summary = %Q{TODO}
9
+ gem.email = "dpickett@enlightsolutions.com"
10
+ gem.homepage = "http://github.com/dpickett/agcod"
11
+ gem.authors = ["Dan Pickett"]
12
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
13
+ end
14
+
15
+ rescue LoadError
16
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
17
+ end
18
+
19
+ require 'rake/testtask'
20
+ Rake::TestTask.new(:test) do |test|
21
+ test.libs << 'lib' << 'test'
22
+ test.pattern = 'test/**/*_test.rb'
23
+ test.verbose = true
24
+ end
25
+
26
+ begin
27
+ require 'rcov/rcovtask'
28
+ Rcov::RcovTask.new do |test|
29
+ test.libs << 'test'
30
+ test.pattern = 'test/**/*_test.rb'
31
+ test.verbose = true
32
+ test.rcov_opts << "-x /Gems/"
33
+ end
34
+ rescue LoadError
35
+ task :rcov do
36
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
37
+ end
38
+ end
39
+
40
+ begin
41
+ require 'cucumber/rake/task'
42
+ Cucumber::Rake::Task.new(:features)
43
+ rescue LoadError
44
+ task :features do
45
+ abort "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
46
+ end
47
+ end
48
+
49
+ require File.join(File.dirname(__FILE__), "lib", "agcod", "tasks")
50
+
51
+ task :default => :spec
52
+
53
+ require 'rake/rdoctask'
54
+ Rake::RDocTask.new do |rdoc|
55
+ if File.exist?('VERSION.yml')
56
+ config = YAML.load(File.read('VERSION.yml'))
57
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
58
+ else
59
+ version = ""
60
+ end
61
+
62
+ rdoc.rdoc_dir = 'rdoc'
63
+ rdoc.title = "agcod #{version}"
64
+ rdoc.rdoc_files.include('README*')
65
+ rdoc.rdoc_files.include('lib/**/*.rb')
66
+ end
67
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
data/agcod.gemspec ADDED
@@ -0,0 +1,66 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{agcod}
5
+ s.version = "0.0.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Dan Pickett"]
9
+ s.date = %q{2009-07-02}
10
+ s.email = %q{dpickett@enlightsolutions.com}
11
+ s.extra_rdoc_files = [
12
+ "LICENSE",
13
+ "README.rdoc"
14
+ ]
15
+ s.files = [
16
+ ".document",
17
+ ".gitignore",
18
+ "LICENSE",
19
+ "README.rdoc",
20
+ "Rakefile",
21
+ "VERSION",
22
+ "agcod.gemspec",
23
+ "features/create_a_giftcard.feature",
24
+ "features/step_definitions/agcod_steps.rb",
25
+ "features/support/app_root/config/agcod.example.yml",
26
+ "features/support/env.rb",
27
+ "lib/agcod.rb",
28
+ "lib/agcod/cancel_gift_card.rb",
29
+ "lib/agcod/configuration.rb",
30
+ "lib/agcod/create_gift_card.rb",
31
+ "lib/agcod/error/configuration_error.rb",
32
+ "lib/agcod/error/invalid_parameter.rb",
33
+ "lib/agcod/health_check.rb",
34
+ "lib/agcod/option_validators.rb",
35
+ "lib/agcod/request.rb",
36
+ "lib/agcod/tasks.rb",
37
+ "lib/agcod/tasks/certification.rake",
38
+ "lib/agcod/void_gift_card_creation.rb",
39
+ "tasks/agcod.rake",
40
+ "test/agcod/configuration_test.rb",
41
+ "test/app_root/config/agcod.yml",
42
+ "test/macros/configuration.rb",
43
+ "test/test_helper.rb"
44
+ ]
45
+ s.has_rdoc = true
46
+ s.homepage = %q{http://github.com/dpickett/agcod}
47
+ s.rdoc_options = ["--charset=UTF-8"]
48
+ s.require_paths = ["lib"]
49
+ s.rubygems_version = %q{1.3.2}
50
+ s.summary = %q{TODO}
51
+ s.test_files = [
52
+ "test/agcod/configuration_test.rb",
53
+ "test/macros/configuration.rb",
54
+ "test/test_helper.rb"
55
+ ]
56
+
57
+ if s.respond_to? :specification_version then
58
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
59
+ s.specification_version = 3
60
+
61
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
62
+ else
63
+ end
64
+ else
65
+ end
66
+ end
@@ -0,0 +1,11 @@
1
+ Feature: As a user of the AGCOD web service
2
+ I want create a gift card
3
+ So that I can remit payment to a third party
4
+
5
+ Scenario: Pay someone $35 successfully
6
+ Given I have access to the AGCOD web service
7
+ And I want to create a gift card in the amount of $35.00
8
+ When I send the request
9
+ Then it should be successful
10
+ And I should get a response id
11
+ And I should get a claim code
@@ -0,0 +1,121 @@
1
+ Given /^I have access to the AGCOD web service$/ do
2
+ Agcod::Configuration.load(File.join(File.dirname(__FILE__), "..", "support", "app_root"), "cucumber")
3
+ assert_not_nil Agcod::Configuration.access_key
4
+ end
5
+
6
+ Given /^I want to send request \"(.*)\"/ do |request_number|
7
+ req = get_request(request_number)
8
+ @options ||= {}
9
+ @request = Agcod::CreateGiftCard.new(req.merge(@options))
10
+ end
11
+
12
+ Given /^I am logging transactions$/ do
13
+ @logger = Logger.new(File.join(FileUtils.pwd, "agcod_cucumber.log"))
14
+ Agcod::Configuration.logger = @logger
15
+ end
16
+
17
+ Given /^I want to send a health check request$/ do
18
+ @request = Agcod::HealthCheck.new
19
+ end
20
+
21
+ Given /^I've sent request \"(.*)\"$/ do |request_number|
22
+ req = get_request(request_number)
23
+ @prior_request = Agcod::CreateGiftCard.new("value" => req["value"].to_f,
24
+ "request_id" => req["request_id"])
25
+ @prior_request.submit
26
+ dump_request(@prior_request)
27
+ end
28
+
29
+ Given /^I want to cancel the gift card requested$/ do
30
+ @request = Agcod::CancelGiftCard.new("request_id" => @prior_request.request_id,
31
+ "response_id" => @prior_request.response_id)
32
+ end
33
+
34
+ Given /^I want to void the gift card requested$/ do
35
+ @request = Agcod::VoidGiftCardCreation.new("request_id" => @prior_request.request_id)
36
+ end
37
+
38
+
39
+ Given /^the request was successful$/ do
40
+ assert @prior_request.successful?
41
+ end
42
+
43
+ Given /^I want to create a gift card with the same request id$/ do
44
+ @request = Agcod::CreateGiftCard.new("value" => 40, "request_id" => @prior_request.request_id)
45
+ @dont_dump_request = true
46
+ end
47
+
48
+ Given /^I want to cancel request "([^\"]*)"$/ do |req_num|
49
+ req = get_request(req_num)
50
+ @options ||= {}
51
+ @request = Agcod::CancelGiftCard.new(req.merge(@options))
52
+ end
53
+
54
+ Given /^I want to void request "([^\"]*)"$/ do |req_num|
55
+ req = get_request(req_num)
56
+ @options ||= {}
57
+ @request = Agcod::VoidGiftCardCreation.new(req.merge(@options))
58
+ end
59
+
60
+
61
+ Given /^I specify response_id "([^\"]*)"$/ do |response_id|
62
+ @options ||= {}
63
+ @options["response_id"] = response_id
64
+ end
65
+
66
+ Given /^I specify the currency of "([^\"]*)"$/ do |currency|
67
+ @options ||= {}
68
+ @options["currency_code"] = currency
69
+ end
70
+
71
+
72
+
73
+ Then /^I should not receive a successful response$/ do
74
+ assert !@request.successful?
75
+ end
76
+
77
+ When /^I send the request$/ do
78
+ @request.submit
79
+ dump_request(@request) if @request.is_a?(Agcod::CreateGiftCard) && !@dont_dump_request
80
+ @dont_dump_request = false if @dont_dump_request
81
+ end
82
+
83
+ Then /^I should receive a successful response$/ do
84
+ assert @request.successful?
85
+ end
86
+
87
+ Then /^I should get a response id$/ do
88
+ assert_not_nil @request.response_id
89
+ end
90
+
91
+ Then /^I should get a claim code$/ do
92
+ assert_not_nil @request.claim_code
93
+ end
94
+
95
+
96
+ def cert_fixture(req_num)
97
+ File.join(
98
+ File.dirname(__FILE__), "..", "support", "certification_requests", "#{req_num}.yml"
99
+ )
100
+ end
101
+
102
+ def get_request(req_num)
103
+ YAML.load(File.read(cert_fixture(req_num)))
104
+ end
105
+
106
+ def dump_request(req)
107
+ req_num = req.request_id[0..0]
108
+
109
+
110
+ req_hash = {
111
+ "request_id" => req.request_id,
112
+ "value" => req.value,
113
+ "response_id" => req.response_id,
114
+ "claim_code" => req.claim_code
115
+ }
116
+
117
+ FileUtils.rm_f(cert_fixture(req_num))
118
+ File.open(cert_fixture(req_num), "w") do |f|
119
+ f.puts req_hash.to_yaml
120
+ end
121
+ end
@@ -0,0 +1,6 @@
1
+ test:
2
+ access_key: fadsfasdgt2434
3
+ secret_key: dfasdf
4
+ partner_id: SomebodyImportant
5
+ uri: https://agcws-gamma.amazon.com/
6
+ discount_percentage: 0.04
@@ -0,0 +1,8 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+
3
+ require 'test/unit/assertions'
4
+ require "shoulda"
5
+
6
+ require 'agcod'
7
+
8
+ World(Test::Unit::Assertions)
@@ -0,0 +1,21 @@
1
+ module Agcod
2
+ class CancelGiftCard < Agcod::Request
3
+ include Agcod::OptionValidators
4
+
5
+ def initialize(options = {})
6
+ @action = "CancelGiftCard"
7
+ @required_options = ["request_id", "response_id"]
8
+ @options = options
9
+ @required_options.each do |r|
10
+ validate_length_of(r, "min" => 1, "max" => 19)
11
+ end
12
+
13
+ super
14
+
15
+ @parameters["gcCreationRequestId"] = Agcod::Configuration.partner_id.to_s + options["request_id"].to_s
16
+ @parameters["gcCreationResponseId"] = options["response_id"]
17
+
18
+ end
19
+ end
20
+
21
+ end
@@ -0,0 +1,76 @@
1
+ module Agcod
2
+ class Configuration
3
+ REQUIRED_OPTIONS = ["access_key",
4
+ "secret_key",
5
+ "partner_id",
6
+ "uri",
7
+ "discount_percentage"
8
+ ]
9
+
10
+ class << self
11
+ attr_reader :options
12
+ attr_accessor :logger
13
+
14
+ def load(app_root = nil, env = nil)
15
+ if app_root
16
+ @app_root = app_root
17
+ else
18
+ @app_root = RAILS_ROOT if defined?(RAILS_ROOT)
19
+ end
20
+
21
+ if @app_root.nil? ||
22
+ !FileTest.exists?(config_filename = File.join(@app_root, 'config', 'agcod.yml'))
23
+
24
+ raise Error::ConfigurationError, "Configuration for AGCOD not found"
25
+ end
26
+
27
+ config_file = File.read(config_filename)
28
+
29
+ environment = RAILS_ENV if defined?(RAILS_ENV)
30
+ environment = env if env
31
+
32
+ @options = YAML.load(config_file)[environment]
33
+ validate_options
34
+ @options
35
+ end
36
+
37
+ def set(opt = {})
38
+ @options ||= {}
39
+ @options.merge!(opt)
40
+
41
+ validate_options
42
+ @options
43
+ end
44
+
45
+ def access_key
46
+ @options["access_key"]
47
+ end
48
+
49
+ def secret_key
50
+ @options["secret_key"]
51
+ end
52
+
53
+ def partner_id
54
+ @options["partner_id"]
55
+ end
56
+
57
+ def uri
58
+ @options["uri"]
59
+ end
60
+
61
+ def discount_percentage
62
+ @options["discount_percentage"]
63
+ end
64
+
65
+ private
66
+
67
+ def validate_options
68
+ REQUIRED_OPTIONS.each do |opt|
69
+ if options[opt].nil? || options[opt] == ""
70
+ raise Error::ConfigurationError, "#{opt} was not specified"
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,43 @@
1
+ module Agcod
2
+ class CreateGiftCard < Agcod::Request
3
+ include Agcod::OptionValidators
4
+
5
+ def initialize(options = {})
6
+ @action = "CreateGiftCard"
7
+ super
8
+
9
+ validate_greater_than("value", 0)
10
+ validate_length_of("request_id", {"max" => 19, "min" => 1})
11
+
12
+ #can't have a nonexistant or 0 value for the gift card
13
+ @parameters["gcValue.amount"] = options["value"]
14
+
15
+ @value = options["value"]
16
+
17
+ #must have a unique identifier for the request
18
+ @parameters["gcCreationRequestId"] = Agcod::Configuration.partner_id + options["request_id"].to_s
19
+
20
+ @parameters["gcValue.currencyCode"] = options["currency_code"] || "USD"
21
+
22
+ end
23
+
24
+ def process_response
25
+ super
26
+ if self.successful?
27
+ @claim_code = self.xml_response.root.elements["gcClaimCode"].text
28
+ @response_id = self.xml_response.root.elements["gcCreationResponseId"].text
29
+ end
30
+ end
31
+
32
+ attr_reader :claim_code, :response_id, :value
33
+
34
+ def to_yaml(name)
35
+ {"response_id" => self.response_id,
36
+ "request_id" => self.request_id,
37
+ "claim_code" => self.claim_code,
38
+ "value" => self.value,
39
+ "timestamp" => self.timestamp
40
+ }.to_yaml(name)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,7 @@
1
+ module Agcod
2
+ module Error
3
+ class ConfigurationError < RuntimeError
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Agcod
2
+ module Error
3
+ class InvalidParameter < RuntimeError
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ module Agcod
2
+ class HealthCheck < Agcod::Request
3
+ def initialize
4
+ @action = "HealthCheck"
5
+ super
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,33 @@
1
+ module Agcod
2
+ module OptionValidators
3
+ def validate_timestamp
4
+ if @options["timestamp"].nil? || !@options["timestamp"].instance_of?(Time)
5
+ raise Agcod::Error::InvalidParameter, "Invalid Timestamp for record #{@options["record_id"]}"
6
+ end
7
+ end
8
+
9
+ private
10
+ def validate_presence_of(option_name)
11
+ if @options[option_name].nil? || @options[option_name].to_s.blank?
12
+ raise Agcod::Error::InvalidParameter, "#{option_name} not specified"
13
+ end
14
+ end
15
+
16
+ def validate_length_of(option_name, size_options)
17
+ size_options["min"] ||= 0
18
+ size_options["max"] ||= 10000
19
+ if @options[option_name].nil? ||
20
+ @options[option_name].to_s.size < size_options["min"] ||
21
+ @options[option_name].to_s.size > size_options["max"]
22
+
23
+ raise Agcod::Error::InvalidParameter, "#{option_name} has an invalid length"
24
+ end
25
+ end
26
+
27
+ def validate_greater_than(option_name, number)
28
+ if @options[option_name].nil? || @options[option_name].to_f <= number
29
+ raise Agcod::Error::InvalidParameter, "#{option_name} must be greater than #{number} for record #{@options["record_id"]}"
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,147 @@
1
+ module Agcod
2
+ class Request
3
+ def initialize(options = {})
4
+ @request = ""
5
+ @response = ""
6
+ @status = ""
7
+ @parameters = {}
8
+ @options = options
9
+ end
10
+
11
+ def submit
12
+ #action must be specified so raise an exception if it has not been populated
13
+ if self.action.nil?
14
+ raise "Action not specified"
15
+ end
16
+
17
+ #form the request GET parameter string
18
+ @request = build_sorted_and_signed_request_string
19
+
20
+ send_request
21
+
22
+ process_response
23
+ log if Agcod::Configuration.logger
24
+ end
25
+
26
+ def successful?
27
+ self.sent && self.errors.size == 0 && self.status == "SUCCESS"
28
+ end
29
+
30
+ attr_reader :errors, :request_id, :sent, :action, :request, :parameters, :response, :xml_response, :status, :timestamp
31
+
32
+ def sign_string(string_to_sign)
33
+ #remove all the = and & from the serialized string
34
+ sanitized_string = string_to_sign.gsub(/=|&/, "")
35
+ # puts sanitized_string
36
+ sha1 = HMAC::SHA1::digest(Agcod::Configuration.secret_key, sanitized_string)
37
+
38
+ #Base64 encoding adds a linefeed to the end of the string so chop the last character!
39
+ CGI.escape(Base64.encode64(sha1).chomp)
40
+ end
41
+
42
+ def request_id
43
+ @options["request_id"]
44
+ end
45
+
46
+ def response_id
47
+ @response_id || @options["response_id"]
48
+ end
49
+
50
+ protected
51
+
52
+ def process_response
53
+ parse_response
54
+
55
+ #check for retry error
56
+ if self.xml_response.root.elements["Status/errorCode"] &&
57
+ self.xml_response.root.elements["Status/errorCode"].text == "E100" &&
58
+ !@sent_retry
59
+
60
+ @sent_retry = true
61
+ submit
62
+ end
63
+
64
+ @errors = []
65
+
66
+ self.xml_response.root.elements.each("Error") do |e|
67
+ @errors << e.elements["Message"].text
68
+ end
69
+
70
+ @status = self.xml_response.root.elements["Status/statusCode"].text unless xml_response.root.elements["Status/statusCode"].nil?
71
+
72
+ #something happened before it got to ACGWS (most likely a signature problem)
73
+ @status = "FAILURE" if self.errors.size > 0 && self.status.blank?
74
+
75
+ @request_id = xml_response.root.elements["RequestID"].text unless xml_response.root.elements["RequestID"].nil?
76
+ end
77
+
78
+ def parse_response
79
+ @xml_response ||= REXML::Document.new(self.response)
80
+ end
81
+
82
+ private
83
+ def send_request
84
+ #send the request
85
+ uri = URI.parse(Agcod::Configuration.uri)
86
+ http = Net::HTTP.new(uri.host, uri.port)
87
+ http.use_ssl = true
88
+
89
+ net_response, @response = http.get(uri.path + "?" + self.request)
90
+
91
+ @sent = true
92
+ end
93
+
94
+ def default_parameters
95
+ @timestamp = Time.now.utc
96
+ {
97
+ "Action" => self.action,
98
+ "AWSAccessKeyId" => Agcod::Configuration.access_key,
99
+ "SignatureVersion" => "1",
100
+ "MessageHeader.recipientId" => "AMAZON",
101
+ "MessageHeader.sourceId" => Agcod::Configuration.partner_id,
102
+ "MessageHeader.retryCount" => "0",
103
+ "MessageHeader.contentVersion" => "2008-01-01",
104
+ "MessageHeader.messageType" => self.action + "Request",
105
+ "Timestamp" => @timestamp.strftime("%Y-%m-%dT%H:%M:%S") + ".000Z"
106
+ }
107
+ end
108
+
109
+ def build_sorted_and_signed_request_string
110
+ params_to_submit = default_parameters.merge(self.parameters)
111
+
112
+ unencoded_key_value_strings = []
113
+ encoded_key_value_strings = []
114
+ sort_parameters(params_to_submit).each do |p|
115
+ unencoded_key_value_strings << p[0].to_s + p[1].to_s
116
+
117
+ if p[0] =~ /Timestamp/i
118
+ encoded_value = p[1]
119
+ else
120
+ encoded_value = CGI.escape(p[1].to_s)
121
+ end
122
+ encoded_key_value_strings << p[0].to_s + "=" + encoded_value
123
+ end
124
+
125
+ signature = sign_string(unencoded_key_value_strings.join(""))
126
+ encoded_key_value_strings.insert(encoded_key_value_strings.index("SignatureVersion=1") + 1 , "Signature=" + signature)
127
+ encoded_key_value_strings.join("&")
128
+ end
129
+
130
+
131
+ def sort_parameters(params)
132
+ key_value_strings = []
133
+ params.sort{|a, b| a[0].downcase <=> b[0].downcase }
134
+ end
135
+
136
+ def log
137
+ log_string = "[AGCOD] #{self.action} Request"
138
+ log_string << " \##{self.request_id}" if self.request_id
139
+ log_string << " received response #{self.response_id}" if self.response_id
140
+ if self.respond_to?(:claim_code) && self.claim_code
141
+ log_string << " received claim_code #{self.claim_code}"
142
+ end
143
+ Agcod::Configuration.logger.debug log_string
144
+ end
145
+
146
+ end
147
+ end
@@ -0,0 +1,45 @@
1
+ require "fileutils"
2
+
3
+ namespace :agcod do
4
+ namespace :certification do
5
+ desc "generate a request manifest for certification"
6
+ task :generate_manifest do
7
+ puts "generating manifest"
8
+ i = 1
9
+ prices = [
10
+ 12,
11
+ 999,
12
+ 100,
13
+ 50.02,
14
+ 999.99,
15
+ 600,
16
+ 70,
17
+ 100000,
18
+ 12,
19
+ 12,
20
+ 1
21
+ ]
22
+
23
+ path = File.join(FileUtils.pwd, "features", "support", "certification_requests")
24
+ FileUtils.rm_rf(path)
25
+ FileUtils.mkdir_p(path)
26
+
27
+ requests = []
28
+ prices.each do |p|
29
+ random_string_of_numbers = ""
30
+ 12.times {random_string_of_numbers << rand(9).to_s}
31
+
32
+ request = {"value" => p,
33
+ "request_id" => i.to_s + random_string_of_numbers}
34
+
35
+ File.open(File.join(path, "#{i}.yml"), 'w') do |manifest|
36
+ manifest.puts request.to_yaml
37
+ end
38
+ i += 1
39
+ end
40
+
41
+
42
+ puts "Manifest available at #{path}"
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,3 @@
1
+ Dir[File.join(File.dirname(__FILE__), 'tasks', '*.rake')].each do |f|
2
+ load f
3
+ end
@@ -0,0 +1,14 @@
1
+ module Agcod
2
+ class VoidGiftCardCreation < Agcod::Request
3
+ include Agcod::OptionValidators
4
+
5
+ def initialize(options = {})
6
+ @action = "VoidGiftCardCreation"
7
+ super
8
+
9
+ validate_presence_of("request_id")
10
+
11
+ @parameters["gcCreationRequestId"] = Agcod::Configuration.partner_id.to_s + self.request_id.to_s
12
+ end
13
+ end
14
+ end
data/lib/agcod.rb ADDED
@@ -0,0 +1,24 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+
3
+ require "net/http"
4
+ require "net/https"
5
+ require 'rexml/document'
6
+
7
+ require "uri"
8
+ require "base64"
9
+ require "hmac-sha1"
10
+ require "digest/sha1"
11
+ require "cgi"
12
+ require "logger"
13
+
14
+ require "agcod/error/invalid_parameter"
15
+ require "agcod/error/configuration_error"
16
+ require "agcod/option_validators"
17
+
18
+ require "agcod/configuration"
19
+ require "agcod/request"
20
+
21
+ require "agcod/cancel_gift_card"
22
+ require "agcod/create_gift_card"
23
+ require "agcod/health_check"
24
+ require "agcod/void_gift_card_creation"
data/tasks/agcod.rake ADDED
@@ -0,0 +1 @@
1
+ load File.join(File.dirname(__FILE__), "..", "lib", "agcod", "tasks.rb")
@@ -0,0 +1,106 @@
1
+ require "test_helper"
2
+
3
+ class Agcod::ConfigurationTest < Test::Unit::TestCase
4
+ context "an agcod configuration" do
5
+ setup do
6
+ @valid_app_root = File.join(File.dirname(__FILE__), "..", "app_root")
7
+ @valid_options = {
8
+ "access_key" => "45127185235",
9
+ "secret_key" => "4321542523453454325j",
10
+ "partner_id" => "SomebodySpecial",
11
+ "uri" => "https://agcws-gamma.amazon.com/",
12
+ "discount_percentage" => 0.04
13
+ }
14
+ end
15
+
16
+ should "raise an error if the configuration file isn't specified" do
17
+ assert_raise Agcod::Error::ConfigurationError do
18
+ Agcod::Configuration.load
19
+ end
20
+ end
21
+
22
+ should "raise an error if the configuration file isn't found" do
23
+ assert_raise Agcod::Error::ConfigurationError do
24
+ Agcod::Configuration.load("/foo4258fast43")
25
+ end
26
+ end
27
+
28
+ should "read configuration from a supplied app root" do
29
+ Agcod::Configuration.load(File.join(File.dirname(__FILE__), "..", "app_root"), "test")
30
+ Agcod::Configuration::REQUIRED_OPTIONS.each do |opt|
31
+ assert_not_nil Agcod::Configuration.send(opt)
32
+ end
33
+ end
34
+
35
+ should "allow me to set config options at runtime" do
36
+ Agcod::Configuration.set(@valid_options)
37
+ assert_equal Agcod::Configuration.access_key, @valid_options["access_key"]
38
+ end
39
+
40
+ should_require_config_options [
41
+ "access_key",
42
+ "secret_key",
43
+ "partner_id",
44
+ "uri",
45
+ "discount_percentage"
46
+ ]
47
+ end
48
+
49
+ context "agcod logging" do
50
+ setup do
51
+ configure_with_valid_options
52
+ @log_path = File.join(File.dirname(__FILE__), "..", "log", "test.log")
53
+ FileUtils.touch(@log_path)
54
+ @logger = Logger.new(@log_path)
55
+ @logger.level = Logger::DEBUG
56
+
57
+ Agcod::Configuration.logger = @logger
58
+
59
+ FakeWeb.allow_net_connect = false
60
+
61
+ @request = Agcod::CreateGiftCard.new("request_id" => 34234, "value" => 12)
62
+ @request.stubs(:response_id).returns(4323535)
63
+ @request.stubs(:send_request)
64
+ @request.stubs(:process_response)
65
+ @request.stubs(:claim_code).returns(342145)
66
+ @request.submit
67
+ end
68
+
69
+ teardown do
70
+ FileUtils.rm_f(@log_path)
71
+ end
72
+
73
+ should "allow me to define a logger for logging requests" do
74
+ @logger = Logger.new(STDOUT)
75
+ Agcod::Configuration.logger = @logger
76
+ assert_equal @logger, Agcod::Configuration.logger
77
+ end
78
+
79
+ should "log request operation names" do
80
+ assert_match /CreateGiftCard/, File.read(@log_path)
81
+ end
82
+
83
+ should "log request ids when applicable" do
84
+ assert_match /#{@request.request_id}/, File.read(@log_path)
85
+ end
86
+
87
+ should "log response ids when applicable" do
88
+ assert_match /#{@request.response_id}/, File.read(@log_path)
89
+ end
90
+
91
+ should "og claim code when applicable" do
92
+ assert_match /#{@request.claim_code}/, File.read(@log_path)
93
+ end
94
+ end
95
+
96
+ def configure_with_valid_options
97
+ @valid_options = {
98
+ "access_key" => "45127185235",
99
+ "secret_key" => "4321542523453454325j",
100
+ "partner_id" => "SomebodySpecial",
101
+ "uri" => "https://agcws-gamma.amazon.com/",
102
+ "discount_percentage" => 0.04
103
+ }
104
+ Agcod::Configuration.set(@valid_options)
105
+ end
106
+ end
@@ -0,0 +1,6 @@
1
+ test:
2
+ access_key: fadsfasdgt2434
3
+ secret_key: dfasdf
4
+ partner_id: SomebodyImportant
5
+ uri: https://agcws-gamma.amazon.com/
6
+ discount_percentage: 0.04
@@ -0,0 +1,24 @@
1
+ class Test::Unit::TestCase
2
+ def self.should_require_config_options(options)
3
+ valid_options = {
4
+ "access_key" => "45127185235",
5
+ "secret_key" => "4321542523453454325j",
6
+ "partner_id" => "SomebodySpecial",
7
+ "uri" => "https://agcws-gamma.amazon.com/",
8
+ "discount_percentage" => 0.04
9
+ }
10
+
11
+ options = [options] unless options.is_a?(Array)
12
+
13
+ options.each do |option|
14
+ should "require #{option} as a configuration option" do
15
+ assert_raise Agcod::Error::ConfigurationError do
16
+ Agcod::Configuration.set(valid_options.merge({
17
+ option => ""
18
+ }))
19
+ end
20
+ end
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,25 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'fakeweb'
5
+ require 'mocha'
6
+
7
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
8
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
9
+ require 'agcod'
10
+
11
+ begin require "redgreen" rescue Exception; end
12
+
13
+ FakeWeb.allow_net_connect = false
14
+
15
+ require "macros/configuration"
16
+
17
+ class Test::Unit::TestCase
18
+ def register_response(path, fixture)
19
+
20
+ end
21
+
22
+ def xml_fixture_path(fixture)
23
+ File.join(File.dirname(__FILE__), "fixtures", "#{fixture}.xml")
24
+ end
25
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dpickett-agcod
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Dan Pickett
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-07-02 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: dpickett@enlightsolutions.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.rdoc
25
+ files:
26
+ - .document
27
+ - .gitignore
28
+ - LICENSE
29
+ - README.rdoc
30
+ - Rakefile
31
+ - VERSION
32
+ - agcod.gemspec
33
+ - features/create_a_giftcard.feature
34
+ - features/step_definitions/agcod_steps.rb
35
+ - features/support/app_root/config/agcod.example.yml
36
+ - features/support/env.rb
37
+ - lib/agcod.rb
38
+ - lib/agcod/cancel_gift_card.rb
39
+ - lib/agcod/configuration.rb
40
+ - lib/agcod/create_gift_card.rb
41
+ - lib/agcod/error/configuration_error.rb
42
+ - lib/agcod/error/invalid_parameter.rb
43
+ - lib/agcod/health_check.rb
44
+ - lib/agcod/option_validators.rb
45
+ - lib/agcod/request.rb
46
+ - lib/agcod/tasks.rb
47
+ - lib/agcod/tasks/certification.rake
48
+ - lib/agcod/void_gift_card_creation.rb
49
+ - tasks/agcod.rake
50
+ - test/agcod/configuration_test.rb
51
+ - test/app_root/config/agcod.yml
52
+ - test/macros/configuration.rb
53
+ - test/test_helper.rb
54
+ has_rdoc: true
55
+ homepage: http://github.com/dpickett/agcod
56
+ post_install_message:
57
+ rdoc_options:
58
+ - --charset=UTF-8
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ version:
73
+ requirements: []
74
+
75
+ rubyforge_project:
76
+ rubygems_version: 1.2.0
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: TODO
80
+ test_files:
81
+ - test/agcod/configuration_test.rb
82
+ - test/macros/configuration.rb
83
+ - test/test_helper.rb