appdirect 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1c6a0ac2a415fe05554d0afd962ad67aa26de0d7
4
+ data.tar.gz: 8693ff887bccd8d4513b3da2cb58c26aac3224d7
5
+ SHA512:
6
+ metadata.gz: b2c999cff3cf4658c0316bb5cbc543418b3f30b4d58cd1be8c8eb68c9fd7af8350ffa281d6ab5e4e3de98cbb0fff25c0a720e6da03d269fcb43b011afcbeb133
7
+ data.tar.gz: 25f764ff894a03c03a13e233181cb889ee9ac720af6ddf7b72f7009ff78b5004a2807bf2bf7f27eb96b7ab28c601d845095e9d92eab7148e77422d8b67475f66
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in appdirect.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Tim Williams
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # AppDirect
2
+
3
+ Ruby bindings for the AppDirect Vendor API. Provides oauth signed retrieval of AppDirect events. Intended for use with the [AppDirect Subscription API](http://info.appdirect.com/developers/docs/api_integration/subscription_management)
4
+
5
+ Please note this is NOT an offical library and is not endorsed or supported by AppDirect.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'appdirect'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install appdirect
20
+
21
+ ## Usage
22
+
23
+ ### Configuration
24
+ The AppDirect API requires your own OAuth 1.0 Consumer Key and Secret. This is used to sign all get requests to the AppDirect REST API.
25
+
26
+ #config/initializers/appdirect.rb
27
+ AppDirect.consumer_key = "Dummy"
28
+ AppDirect.secret = "secret"
29
+
30
+ ### Retrieving an event
31
+ Subscription Management is intiated by a call from AppDirect to your defined callback urls. Part of this callback will include a URL parameter storing the URL for the event that you need to respond to.
32
+
33
+ For example you may have defined a callback URL as follows in your AppDirect integration settings
34
+
35
+ ``https://example.com/create?url={eventUrl}``
36
+
37
+ Once you have retrieved the URL you can retrieve the Event:
38
+
39
+ url = "https://www.appdirect.com/rest/api/events/dummyOrder" # <-- this should be the url from the callback
40
+ event = AppDirect::Event.retrieve(url)
41
+
42
+ #Inspect the event
43
+ if event.type == "SUBSCRIPTION_CANCEL"
44
+ puts "Bad news, somebody just cancelled!"
45
+ end
46
+
47
+ ### Event data structure
48
+ As part of the retrieval the XML representation of the event is converted to a Ruby object, exposing the child elements of the ``<event>`` tag as methods on the event object.
49
+
50
+ In this SUBSCRIPTION_NOTICE XML example:
51
+
52
+ <event>
53
+ <flag>STATELESS</flag>
54
+ <marketplace>
55
+ <baseUrl>https://acme.appdirect.com</baseUrl>
56
+ <partner>ACME</partner>
57
+ </marketplace>
58
+ <payload>
59
+ <account>
60
+ <accountIdentifier>dummy-account</accountIdentifier>
61
+ <status>SUSPENDED</status>
62
+ </account>
63
+ <configuration/>
64
+ <notice>
65
+ <type>DEACTIVATED</type>
66
+ </notice>
67
+ </payload>
68
+ <type>SUBSCRIPTION_NOTICE</type>
69
+ </event>
70
+
71
+ You can access the information as follows:
72
+
73
+ event = AppDirect::Event.retrieve(url)
74
+ event.flag # STATELESS
75
+ event.payload.account.status # SUSPENDED
76
+ event.type # SUBSCRIPTION_NOTICE
77
+
78
+ ## Contributing
79
+
80
+ 1. Fork it ( https://github.com/timrwilliams/appdirect/fork )
81
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
82
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
83
+ 4. Push to the branch (`git push origin my-new-feature`)
84
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/appdirect.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'appdirect/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "appdirect"
8
+ spec.version = AppDirect::VERSION
9
+ spec.authors = ["Tim Williams"]
10
+ spec.email = ["tim@teachmatic.com"]
11
+ spec.summary = %q{Ruby wrapper for AppDirect API}
12
+ spec.description = %q{Basic ruby wrapper for the AppDirect Vendor API. Handles event retrieval and parsing XML in to Ruby object.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.6"
22
+ spec.add_development_dependency "minitest", "~> 5.4"
23
+ spec.add_development_dependency "vcr", '~> 2.9'
24
+ spec.add_development_dependency "webmock",'~> 1.20'
25
+ spec.add_development_dependency "rake"
26
+
27
+ spec.add_dependency 'oauth', '~> 0.4'
28
+ spec.add_dependency 'nori', '~> 2.4'
29
+ end
@@ -0,0 +1,193 @@
1
+ module AppDirect
2
+ class AppDirectObject
3
+ include Enumerable
4
+
5
+ attr_accessor :consumer_key, :secret
6
+ @@permanent_attributes = Set.new([:consumer_key, :secret, :id])
7
+
8
+ # The default :id method is deprecated and isn't useful to us
9
+ if method_defined?(:id)
10
+ undef :id
11
+ end
12
+
13
+ def initialize(id=nil, consumer_key=nil, secret=nil)
14
+
15
+ # parameter overloading!
16
+ if id.kind_of?(Hash)
17
+ @retrieve_options = id.dup
18
+ @retrieve_options.delete(:id)
19
+ id = id[:id]
20
+ else
21
+ @retrieve_options = {}
22
+ end
23
+
24
+ @consumer_key = consumer_key
25
+ @secret = secret
26
+ @values = {}
27
+ # This really belongs in APIResource, but not putting it there allows us
28
+ # to have a unified inspect method
29
+ @unsaved_values = Set.new
30
+ @transient_values = Set.new
31
+ @values[:id] = id if id
32
+ end
33
+
34
+ def self.construct_from(values, consumer_key=nil, secret=nil)
35
+ obj = self.new(values[:id], consumer_key, secret)
36
+ obj.refresh_from(values, consumer_key, secret)
37
+ obj
38
+ end
39
+
40
+ def to_s(*args)
41
+ JSON.pretty_generate(@values)
42
+ end
43
+
44
+ def inspect()
45
+ id_string = (self.respond_to?(:id) && !self.id.nil?) ? " id=#{self.id}" : ""
46
+ "#<#{self.class}:0x#{self.object_id.to_s(16)}#{id_string}> JSON: " + JSON.pretty_generate(@values)
47
+ end
48
+
49
+ def refresh_from(values, consumer_key, secret, partial=false)
50
+ @consumer_key = consumer_key
51
+ @secret = secret
52
+
53
+ @previous_metadata = values[:metadata]
54
+ removed = partial ? Set.new : Set.new(@values.keys - values.keys)
55
+ added = Set.new(values.keys - @values.keys)
56
+ # Wipe old state before setting new. This is useful for e.g. updating a
57
+ # customer, where there is no persistent card parameter. Mark those values
58
+ # which don't persist as transient
59
+
60
+ instance_eval do
61
+ remove_accessors(removed)
62
+ add_accessors(added)
63
+ end
64
+ removed.each do |k|
65
+ @values.delete(k)
66
+ @transient_values.add(k)
67
+ @unsaved_values.delete(k)
68
+ end
69
+ values.each do |k, v|
70
+ @values[k] = Util.convert_to_appdirect_object(v, consumer_key, secret)
71
+ @transient_values.delete(k)
72
+ @unsaved_values.delete(k)
73
+ end
74
+ end
75
+
76
+ def [](k)
77
+ @values[k.to_sym]
78
+ end
79
+
80
+ def []=(k, v)
81
+ send(:"#{k}=", v)
82
+ end
83
+
84
+ def keys
85
+ @values.keys
86
+ end
87
+
88
+ def values
89
+ @values.values
90
+ end
91
+
92
+ def to_json(*a)
93
+ JSON.generate(@values)
94
+ end
95
+
96
+ def as_json(*a)
97
+ @values.as_json(*a)
98
+ end
99
+
100
+ def to_hash
101
+ @values.inject({}) do |acc, (key, value)|
102
+ acc[key] = value.respond_to?(:to_hash) ? value.to_hash : value
103
+ acc
104
+ end
105
+ end
106
+
107
+ def each(&blk)
108
+ @values.each(&blk)
109
+ end
110
+
111
+ def _dump(level)
112
+ Marshal.dump([@values, @consumer_key, @secret])
113
+ end
114
+
115
+ def self._load(args)
116
+ values, api_key = Marshal.load(args)
117
+ construct_from(values, consumer_key, secret)
118
+ end
119
+
120
+ if RUBY_VERSION < '1.9.2'
121
+ def respond_to?(symbol)
122
+ @values.has_key?(symbol) || super
123
+ end
124
+ end
125
+
126
+ protected
127
+
128
+ def metaclass
129
+ class << self; self; end
130
+ end
131
+
132
+ def remove_accessors(keys)
133
+ metaclass.instance_eval do
134
+ keys.each do |k|
135
+ next if @@permanent_attributes.include?(k)
136
+ k_eq = :"#{k}="
137
+ remove_method(k) if method_defined?(k)
138
+ remove_method(k_eq) if method_defined?(k_eq)
139
+ end
140
+ end
141
+ end
142
+
143
+ def add_accessors(keys)
144
+ metaclass.instance_eval do
145
+ keys.each do |k|
146
+ next if @@permanent_attributes.include?(k)
147
+ k_eq = :"#{k}="
148
+ define_method(k) { @values[k] }
149
+ define_method(k_eq) do |v|
150
+ if v == ""
151
+ raise ArgumentError.new(
152
+ "You cannot set #{k} to an empty string." +
153
+ "We interpret empty strings as nil in requests." +
154
+ "You may set #{self}.#{k} = nil to delete the property.")
155
+ end
156
+ @values[k] = v
157
+ @unsaved_values.add(k)
158
+ end
159
+ end
160
+ end
161
+ end
162
+
163
+ def method_missing(name, *args)
164
+ # TODO: only allow setting in updateable classes.
165
+ if name.to_s.end_with?('=')
166
+ attr = name.to_s[0...-1].to_sym
167
+ add_accessors([attr])
168
+ begin
169
+ mth = method(name)
170
+ rescue NameError
171
+ raise NoMethodError.new("Cannot set #{attr} on this object. HINT: you can't set: #{@@permanent_attributes.to_a.join(', ')}")
172
+ end
173
+ return mth.call(args[0])
174
+ else
175
+ return @values[name] if @values.has_key?(name)
176
+ end
177
+
178
+ begin
179
+ super
180
+ rescue NoMethodError => e
181
+ if @transient_values.include?(name)
182
+ raise NoMethodError.new(e.message + ". HINT: The '#{name}' attribute was set in the past, however. It was then wiped when refreshing the object with the result returned by AppDirect's API, probably as a result of a save(). The attributes currently available on this object are: #{@values.keys.join(', ')}")
183
+ else
184
+ raise
185
+ end
186
+ end
187
+ end
188
+
189
+ def respond_to_missing?(symbol, include_private = false)
190
+ @values && @values.has_key?(symbol) || super
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,20 @@
1
+ module AppDirect
2
+ class AppDirectError < StandardError
3
+ attr_reader :message
4
+ attr_reader :http_status
5
+ attr_reader :http_body
6
+ attr_reader :json_body
7
+
8
+ def initialize(message=nil, http_status=nil, http_body=nil, json_body=nil)
9
+ @message = message
10
+ @http_status = http_status
11
+ @http_body = http_body
12
+ @json_body = json_body
13
+ end
14
+
15
+ def to_s
16
+ status_string = @http_status.nil? ? "" : "(Status #{@http_status}) "
17
+ "#{status_string}#{@message}"
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,4 @@
1
+ module AppDirect
2
+ class AuthenticationError < AppDirectError
3
+ end
4
+ end
@@ -0,0 +1,15 @@
1
+ module AppDirect
2
+ class Event < AppDirectObject
3
+
4
+ def refresh
5
+ response, consumer_key, secret = AppDirect.signed_get(@values[:id], @consumer_key, @secret, @retrieve_options)
6
+ refresh_from(response[:event], consumer_key, secret)
7
+ end
8
+
9
+ def self.retrieve(url, consumer_key=nil, secret=nil)
10
+ instance = self.new(url, consumer_key, secret)
11
+ instance.refresh
12
+ instance
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,38 @@
1
+ module AppDirect
2
+ module Util
3
+
4
+ def self.object_classes
5
+ @object_classes ||= {
6
+ :event => Event
7
+ }
8
+ end
9
+
10
+ def self.symbolize_names(object)
11
+ case object
12
+ when Hash
13
+ new = {}
14
+ object.each do |key, value|
15
+ key = (key.to_sym rescue key) || key
16
+ new[key] = symbolize_names(value)
17
+ end
18
+ new
19
+ when Array
20
+ object.map { |value| symbolize_names(value) }
21
+ else
22
+ object
23
+ end
24
+ end
25
+
26
+ def self.convert_to_appdirect_object(resp, consumer_key, secret)
27
+ case resp
28
+ when Array
29
+ resp.map { |i| convert_to_appdirect_object(i, consumer_key, secret) }
30
+ when Hash
31
+ # Try converting to a known object class. If none available, fall back to generic BoffinIOObject
32
+ object_classes.fetch(resp.keys.first, AppDirectObject).construct_from(resp, consumer_key, secret)
33
+ else
34
+ resp
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,3 @@
1
+ module AppDirect
2
+ VERSION = "0.0.1"
3
+ end
data/lib/appdirect.rb ADDED
@@ -0,0 +1,48 @@
1
+ require "set"
2
+
3
+ require_relative "appdirect/version"
4
+ require_relative "appdirect/util"
5
+ require_relative "appdirect/appdirect_object"
6
+ require_relative "appdirect/event"
7
+
8
+ #Error declarations
9
+ require_relative "appdirect/errors/appdirect_error"
10
+ require_relative "appdirect/errors/authentication_error"
11
+
12
+ require 'oauth'
13
+ require 'nori'
14
+
15
+
16
+ module AppDirect
17
+ class << self
18
+ attr_accessor :consumer_key, :secret
19
+ end
20
+
21
+ def self.signed_get(event_url, consumer_key, secret, params={})
22
+ unless consumer_key ||= @consumer_key
23
+ raise AuthenticationError.new('No Consumer key provided. ' +
24
+ 'Set your Consumer key using "AppDirect.consumer_key = <CONSUMER-KEY>". ' +
25
+ 'You can view your consumer key via the AppDirect Edit Integration page. ')
26
+ end
27
+
28
+ if consumer_key =~ /\s/
29
+ raise AuthenticationError.new('Your Consumer key is invalid, as it contains whitespace')
30
+ end
31
+
32
+ unless secret ||= @secret
33
+ raise AuthenticationError.new('No API Secret provided. ' +
34
+ 'Set your Secret using "AppDirect.secret = <SECRET>". ' +
35
+ 'You can view your secret key via the AppDirect Edit Integration page. ')
36
+ end
37
+
38
+ if secret =~ /\s/
39
+ raise AuthenticationError.new('Your API Secret is invalid, as it contains whitespace')
40
+ end
41
+ consumer = OAuth::Consumer.new(consumer_key, secret)
42
+ access_token = OAuth::AccessToken.new(consumer)
43
+ response = access_token.get(event_url)
44
+ parser = Nori.new
45
+ hash = parser.parse(response.body)
46
+ [Util.symbolize_names(hash),consumer_key, secret]
47
+ end
48
+ end
@@ -0,0 +1,47 @@
1
+ require './test/test_helper'
2
+
3
+ class EventTest < Minitest::Test
4
+ def test_exists
5
+ assert AppDirect::Event
6
+ end
7
+
8
+ def test_it_retrieves_an_order_event
9
+ VCR.use_cassette('dummy_order') do
10
+ event = AppDirect::Event.retrieve("https://www.appdirect.com/rest/api/events/dummyOrder")
11
+ assert_equal "STATELESS",event.flag
12
+ assert_equal "SUBSCRIPTION_ORDER",event.type
13
+ assert_equal "test-email+creator@appdirect.com", event.creator.email
14
+ assert_equal "BASIC", event.payload.order.editionCode
15
+ end
16
+ end
17
+
18
+ def test_it_retrieves_a_change_event
19
+ VCR.use_cassette('dummy_change') do
20
+ event = AppDirect::Event.retrieve("https://www.appdirect.com/rest/api/events/dummyChange")
21
+ assert_equal "STATELESS",event.flag
22
+ assert_equal "SUBSCRIPTION_CHANGE",event.type
23
+ assert_equal "test-email+creator@appdirect.com", event.creator.email
24
+ assert_equal "PREMIUM", event.payload.order.editionCode
25
+ assert_equal "dummy-account", event.payload.account.accountIdentifier
26
+ end
27
+ end
28
+
29
+ def test_it_retrieves_a_cancel_event
30
+ VCR.use_cassette('dummy_cancel') do
31
+ event = AppDirect::Event.retrieve("https://www.appdirect.com/rest/api/events/dummyCancel")
32
+ assert_equal "STATELESS",event.flag
33
+ assert_equal "SUBSCRIPTION_CANCEL",event.type
34
+ assert_equal "test-email+creator@appdirect.com", event.creator.email
35
+ assert_equal "dummy-account", event.payload.account.accountIdentifier
36
+ end
37
+ end
38
+
39
+ def test_it_retrieves_a_notice_event
40
+ VCR.use_cassette('dummy_notice') do
41
+ event = AppDirect::Event.retrieve("https://www.appdirect.com/rest/api/events/dummyNotice")
42
+ assert_equal "STATELESS",event.flag
43
+ assert_equal "SUBSCRIPTION_NOTICE",event.type
44
+ assert_equal "DEACTIVATED", event.payload.notice.type
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,60 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://www.appdirect.com/rest/api/events/dummyCancel
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - "*/*"
14
+ User-Agent:
15
+ - OAuth gem v0.4.7
16
+ Authorization:
17
+ - OAuth oauth_consumer_key="statica-16287", oauth_nonce="YEm8lGN4ZmMRLCsjViZxg8b3SjiUTHiCBUYUrAxbFRE",
18
+ oauth_signature="LpMD%2BZI8adU2ysTHe4gVWYr4gEc%3D", oauth_signature_method="HMAC-SHA1",
19
+ oauth_timestamp="1414773354", oauth_version="1.0"
20
+ response:
21
+ status:
22
+ code: 200
23
+ message: OK
24
+ headers:
25
+ Cache-Control:
26
+ - no-cache, no-store, max-age=0, must-revalidate
27
+ - no-cache="set-cookie"
28
+ - private
29
+ Content-Type:
30
+ - application/xml;charset=UTF-8
31
+ Date:
32
+ - Fri, 31 Oct 2014 16:35:41 GMT
33
+ Expires:
34
+ - '0'
35
+ - Wed, 31 Dec 1969 19:00:00 EST
36
+ Pragma:
37
+ - no-cache
38
+ Server:
39
+ - APPSERVER
40
+ Set-Cookie:
41
+ - AWSELB=9DF3DFDB06E99836F49B4DBC3EB5DEE1BC2F4E2A51DC93894B5743680C134F214C9ED5CD7830863BD5B9D917450CCAC074115D10BF13AB9026347C3B6098744FCE8AD5B33F;PATH=/;MAX-AGE=3600
42
+ - JSESSIONID=5BA1D0BFED13E8D5DFB562BF0C34E620-n1; Path=/; Secure; HttpOnly
43
+ Strict-Transport-Security:
44
+ - max-age=0 ; includeSubDomains
45
+ X-Content-Type-Options:
46
+ - nosniff
47
+ X-Frame-Options:
48
+ - SAMEORIGIN
49
+ X-Xss-Protection:
50
+ - 1; mode=block
51
+ Content-Length:
52
+ - '731'
53
+ Connection:
54
+ - keep-alive
55
+ body:
56
+ encoding: UTF-8
57
+ string: <?xml version="1.0" encoding="UTF-8" standalone="yes"?><event><creator><email>test-email+creator@appdirect.com</email><firstName>DummyCreatorFirst</firstName><language>fr</language><lastName>DummyCreatorLast</lastName><openId>https://www.appdirect.com/openid/id/ec5d8eda-5cec-444d-9e30-125b6e4b67e2</openId><uuid>ec5d8eda-5cec-444d-9e30-125b6e4b67e2</uuid></creator><flag>STATELESS</flag><marketplace><baseUrl>https://acme.appdirect.com</baseUrl><partner>ACME</partner></marketplace><payload><account><accountIdentifier>dummy-account</accountIdentifier><status>ACTIVE</status></account><configuration/></payload><returnUrl>https://www.appdirect.com/finishcancel?token=dummyCancel</returnUrl><type>SUBSCRIPTION_CANCEL</type></event>
58
+ http_version:
59
+ recorded_at: Fri, 31 Oct 2014 16:35:55 GMT
60
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,60 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://www.appdirect.com/rest/api/events/dummyChange
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - "*/*"
14
+ User-Agent:
15
+ - OAuth gem v0.4.7
16
+ Authorization:
17
+ - OAuth oauth_consumer_key="statica-16287", oauth_nonce="r2kLZO3UiSYDNDZXgvfodt5GGz6i3zoaSgiwmt148tU",
18
+ oauth_signature="ZnSGKiCauwR0h%2Bu%2F9wbpwH4veDs%3D", oauth_signature_method="HMAC-SHA1",
19
+ oauth_timestamp="1414773354", oauth_version="1.0"
20
+ response:
21
+ status:
22
+ code: 200
23
+ message: OK
24
+ headers:
25
+ Cache-Control:
26
+ - no-cache, no-store, max-age=0, must-revalidate
27
+ - no-cache="set-cookie"
28
+ - private
29
+ Content-Type:
30
+ - application/xml;charset=UTF-8
31
+ Date:
32
+ - Fri, 31 Oct 2014 16:35:40 GMT
33
+ Expires:
34
+ - '0'
35
+ - Wed, 31 Dec 1969 19:00:00 EST
36
+ Pragma:
37
+ - no-cache
38
+ Server:
39
+ - APPSERVER
40
+ Set-Cookie:
41
+ - AWSELB=9DF3DFDB06E99836F49B4DBC3EB5DEE1BC2F4E2A51DC93894B5743680C134F214C9ED5CD7830863BD5B9D917450CCAC074115D10BF13AB9026347C3B6098744FCE8AD5B33F;PATH=/;MAX-AGE=3600
42
+ - JSESSIONID=B1A5F585AFDF31D1E124B5DAF76018D0-n1; Path=/; Secure; HttpOnly
43
+ Strict-Transport-Security:
44
+ - max-age=0 ; includeSubDomains
45
+ X-Content-Type-Options:
46
+ - nosniff
47
+ X-Frame-Options:
48
+ - SAMEORIGIN
49
+ X-Xss-Protection:
50
+ - 1; mode=block
51
+ Content-Length:
52
+ - '933'
53
+ Connection:
54
+ - keep-alive
55
+ body:
56
+ encoding: UTF-8
57
+ string: <?xml version="1.0" encoding="UTF-8" standalone="yes"?><event><creator><email>test-email+creator@appdirect.com</email><firstName>DummyCreatorFirst</firstName><language>fr</language><lastName>DummyCreatorLast</lastName><openId>https://www.appdirect.com/openid/id/ec5d8eda-5cec-444d-9e30-125b6e4b67e2</openId><uuid>ec5d8eda-5cec-444d-9e30-125b6e4b67e2</uuid></creator><flag>STATELESS</flag><marketplace><baseUrl>https://acme.appdirect.com</baseUrl><partner>ACME</partner></marketplace><payload><account><accountIdentifier>dummy-account</accountIdentifier><status>ACTIVE</status></account><configuration/><order><editionCode>PREMIUM</editionCode><item><quantity>20</quantity><unit>USER</unit></item><item><quantity>15</quantity><unit>MEGABYTE</unit></item><pricingDuration>MONTHLY</pricingDuration></order></payload><returnUrl>https://www.appdirect.com/finishprocure?token=dummyChange</returnUrl><type>SUBSCRIPTION_CHANGE</type></event>
58
+ http_version:
59
+ recorded_at: Fri, 31 Oct 2014 16:35:54 GMT
60
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,60 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://www.appdirect.com/rest/api/events/dummyNotice
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - "*/*"
14
+ User-Agent:
15
+ - OAuth gem v0.4.7
16
+ Authorization:
17
+ - OAuth oauth_consumer_key="statica-16287", oauth_nonce="WsOv09nHw5TqcnMLSnwGffhIlEN7KXoOX14zp334ho",
18
+ oauth_signature="2HoWoJn1Va0wrH%2Bqytqb%2FHNZ5dA%3D", oauth_signature_method="HMAC-SHA1",
19
+ oauth_timestamp="1414773355", oauth_version="1.0"
20
+ response:
21
+ status:
22
+ code: 200
23
+ message: OK
24
+ headers:
25
+ Cache-Control:
26
+ - no-cache, no-store, max-age=0, must-revalidate
27
+ - no-cache="set-cookie"
28
+ - private
29
+ Content-Type:
30
+ - application/xml;charset=UTF-8
31
+ Date:
32
+ - Fri, 31 Oct 2014 16:35:41 GMT
33
+ Expires:
34
+ - '0'
35
+ - Wed, 31 Dec 1969 19:00:00 EST
36
+ Pragma:
37
+ - no-cache
38
+ Server:
39
+ - APPSERVER
40
+ Set-Cookie:
41
+ - AWSELB=9DF3DFDB06E99836F49B4DBC3EB5DEE1BC2F4E2A51DC93894B5743680C134F214C9ED5CD7830863BD5B9D917450CCAC074115D10BF13AB9026347C3B6098744FCE8AD5B33F;PATH=/;MAX-AGE=3600
42
+ - JSESSIONID=D73433A6327A1412ED887D792D28FA87-n1; Path=/; Secure; HttpOnly
43
+ Strict-Transport-Security:
44
+ - max-age=0 ; includeSubDomains
45
+ X-Content-Type-Options:
46
+ - nosniff
47
+ X-Frame-Options:
48
+ - SAMEORIGIN
49
+ X-Xss-Protection:
50
+ - 1; mode=block
51
+ Content-Length:
52
+ - '392'
53
+ Connection:
54
+ - keep-alive
55
+ body:
56
+ encoding: UTF-8
57
+ string: <?xml version="1.0" encoding="UTF-8" standalone="yes"?><event><flag>STATELESS</flag><marketplace><baseUrl>https://acme.appdirect.com</baseUrl><partner>ACME</partner></marketplace><payload><account><accountIdentifier>dummy-account</accountIdentifier><status>SUSPENDED</status></account><configuration/><notice><type>DEACTIVATED</type></notice></payload><type>SUBSCRIPTION_NOTICE</type></event>
58
+ http_version:
59
+ recorded_at: Fri, 31 Oct 2014 16:35:55 GMT
60
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,63 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://www.appdirect.com/rest/api/events/dummyOrder
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ Accept-Encoding:
11
+ - gzip;q=1.0,deflate;q=0.6,identity;q=0.3
12
+ Accept:
13
+ - "*/*"
14
+ User-Agent:
15
+ - OAuth gem v0.4.7
16
+ Authorization:
17
+ - OAuth oauth_consumer_key="statica-16287", oauth_nonce="WpcvHpByfAlbD8Z7SFwFn2yg7WDknEzm4libw8jDeuI",
18
+ oauth_signature="NG4YV5tyrVt6IAifvq2bt%2BwXvHY%3D", oauth_signature_method="HMAC-SHA1",
19
+ oauth_timestamp="1414774026", oauth_version="1.0"
20
+ response:
21
+ status:
22
+ code: 200
23
+ message: OK
24
+ headers:
25
+ Cache-Control:
26
+ - no-cache, no-store, max-age=0, must-revalidate
27
+ - no-cache="set-cookie"
28
+ - private
29
+ Content-Type:
30
+ - application/xml;charset=UTF-8
31
+ Date:
32
+ - Fri, 31 Oct 2014 16:47:06 GMT
33
+ Expires:
34
+ - '0'
35
+ - Wed, 31 Dec 1969 19:00:00 EST
36
+ Pragma:
37
+ - no-cache
38
+ Server:
39
+ - APPSERVER
40
+ Set-Cookie:
41
+ - AWSELB=9DF3DFDB06E99836F49B4DBC3EB5DEE1BC2F4E2A51185BCBF9FE9B1556FC26BE90C967D51C7D29762B45076D59BE46F256800BBA3472C60D6240760072A996081A81F83201;PATH=/;MAX-AGE=3600
42
+ - JSESSIONID=17CB0F4248F7ADD1420ACC30AFF69677-n1; Path=/; Secure; HttpOnly
43
+ Strict-Transport-Security:
44
+ - max-age=0 ; includeSubDomains
45
+ Vary:
46
+ - Accept-Encoding
47
+ X-Content-Type-Options:
48
+ - nosniff
49
+ X-Frame-Options:
50
+ - SAMEORIGIN
51
+ X-Xss-Protection:
52
+ - 1; mode=block
53
+ Content-Length:
54
+ - '603'
55
+ Connection:
56
+ - keep-alive
57
+ body:
58
+ encoding: UTF-8
59
+ string: <?xml version="1.0" encoding="UTF-8" standalone="yes"?><event><creator><email>test-email+creator@appdirect.com</email><firstName>DummyCreatorFirst</firstName><language>fr</language><lastName>DummyCreatorLast</lastName><openId>https://www.appdirect.com/openid/id/ec5d8eda-5cec-444d-9e30-125b6e4b67e2</openId><uuid>ec5d8eda-5cec-444d-9e30-125b6e4b67e2</uuid></creator><flag>STATELESS</flag><marketplace><baseUrl>https://acme.appdirect.com</baseUrl><partner>ACME</partner></marketplace><payload><company><country>CA</country><email>company-email@example.com</email><name>Example
60
+ Company Name</name><phoneNumber>415-555-1212</phoneNumber><uuid>d15bb36e-5fb5-11e0-8c3c-00262d2cda03</uuid><website>http://www.example.com</website></company><configuration><entry><key>domain</key><value>mydomain</value></entry></configuration><order><editionCode>BASIC</editionCode><item><quantity>10</quantity><unit>USER</unit></item><item><quantity>15</quantity><unit>MEGABYTE</unit></item><pricingDuration>MONTHLY</pricingDuration></order></payload><returnUrl>https://www.appdirect.com/finishprocure?token=dummyOrder</returnUrl><type>SUBSCRIPTION_ORDER</type></event>
61
+ http_version:
62
+ recorded_at: Fri, 31 Oct 2014 16:47:07 GMT
63
+ recorded_with: VCR 2.9.3
@@ -0,0 +1,15 @@
1
+ #test/test_helper.rb
2
+ require './lib/appdirect'
3
+ require 'minitest/autorun'
4
+ require 'webmock/minitest'
5
+ require 'vcr'
6
+
7
+ VCR.configure do |c|
8
+ c.cassette_library_dir = "test/fixtures"
9
+ c.hook_into :webmock
10
+ end
11
+
12
+ # If you need to record more test responses using VCR you need genuine AppDirect keys
13
+ # You can find them on the Edit Integration page of your AppDirect Product's dashboard.
14
+ AppDirect.consumer_key=ENV["APPDIRECT_KEY"] || "Dummy"
15
+ AppDirect.secret=ENV["APPDIRECT_SECRET"] || "secret"
metadata ADDED
@@ -0,0 +1,168 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: appdirect
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Tim Williams
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.4'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: vcr
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.9'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.9'
55
+ - !ruby/object:Gem::Dependency
56
+ name: webmock
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.20'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.20'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: oauth
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.4'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.4'
97
+ - !ruby/object:Gem::Dependency
98
+ name: nori
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '2.4'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '2.4'
111
+ description: Basic ruby wrapper for the AppDirect Vendor API. Handles event retrieval
112
+ and parsing XML in to Ruby object.
113
+ email:
114
+ - tim@teachmatic.com
115
+ executables: []
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".gitignore"
120
+ - Gemfile
121
+ - LICENSE.txt
122
+ - README.md
123
+ - Rakefile
124
+ - appdirect.gemspec
125
+ - lib/appdirect.rb
126
+ - lib/appdirect/appdirect_object.rb
127
+ - lib/appdirect/errors/appdirect_error.rb
128
+ - lib/appdirect/errors/authentication_error.rb
129
+ - lib/appdirect/event.rb
130
+ - lib/appdirect/util.rb
131
+ - lib/appdirect/version.rb
132
+ - test/event/event_test.rb
133
+ - test/fixtures/dummy_cancel.yml
134
+ - test/fixtures/dummy_change.yml
135
+ - test/fixtures/dummy_notice.yml
136
+ - test/fixtures/dummy_order.yml
137
+ - test/test_helper.rb
138
+ homepage: ''
139
+ licenses:
140
+ - MIT
141
+ metadata: {}
142
+ post_install_message:
143
+ rdoc_options: []
144
+ require_paths:
145
+ - lib
146
+ required_ruby_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ required_rubygems_version: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - ">="
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
156
+ requirements: []
157
+ rubyforge_project:
158
+ rubygems_version: 2.2.2
159
+ signing_key:
160
+ specification_version: 4
161
+ summary: Ruby wrapper for AppDirect API
162
+ test_files:
163
+ - test/event/event_test.rb
164
+ - test/fixtures/dummy_cancel.yml
165
+ - test/fixtures/dummy_change.yml
166
+ - test/fixtures/dummy_notice.yml
167
+ - test/fixtures/dummy_order.yml
168
+ - test/test_helper.rb