affiliate-window 0.2.0.pre1 → 0.2.1.pre1
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 +4 -4
- data/.gitignore +48 -0
- data/Gemfile.lock +70 -0
- data/VERSION +1 -0
- data/affiliate-window-0.2.0.pre1.gem +0 -0
- data/affiliate-window.gemspec +68 -0
- data/lib/affiliate-window/account.rb +48 -0
- data/lib/affiliate-window/clients/affiliate_service.rb +45 -0
- data/lib/affiliate-window/clients/category.rb +19 -0
- data/lib/affiliate-window/clients/merchant.rb +32 -0
- data/lib/affiliate-window/clients/shop_window.rb +45 -0
- data/lib/affiliate-window/helpers/account.rb +25 -0
- data/lib/affiliate-window/helpers/client.rb +23 -0
- data/lib/affiliate-window/helpers/csv.rb +24 -0
- data/lib/affiliate-window/models/transaction.rb +92 -0
- data/lib/affiliate-window/version.rb +10 -0
- data/spec/affiliate_window/account_spec.rb +33 -0
- data/spec/affiliate_window/clients/affiliate_service_spec.rb +51 -0
- data/spec/affiliate_window/clients/category_spec.rb +39 -0
- data/spec/affiliate_window/clients/merchant_spec.rb +48 -0
- data/spec/affiliate_window/clients/shop_window_spec.rb +41 -0
- data/spec/affiliate_window/helpers/account_spec.rb +0 -0
- data/spec/affiliate_window/helpers/csv_spec.rb +43 -0
- data/spec/affiliate_window/models/transaction_spec.rb +44 -0
- data/spec/affiliate_window_spec.rb +28 -0
- data/spec/fixtures/csv/merchants.csv +3 -0
- data/spec/fixtures/responses/affiliate_service_v3.wsdl +1039 -0
- data/spec/fixtures/responses/get_transaction_list.xml +310 -0
- data/spec/fixtures/responses/gtl.xml +300 -0
- data/spec/fixtures/responses/merchants.csv +32 -0
- data/spec/helper.rb +62 -0
- data/wsdl/affiliate_service_v3.wsdl +1029 -0
- metadata +32 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9111b0e915d1b9ad173bb31f8eb7b75754d5cc39
|
4
|
+
data.tar.gz: 94b8e9859831f34d6b5b3384fa936a416a9f9fbb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5cb0c3655d7049a0850f436b9a546bd71ca2dcf93c6c4131a77c0cea812504a5f2dea360a6870632157a9fadfb16da88ab6ccee145669fbcd166672bbac9dd53
|
7
|
+
data.tar.gz: 42b1d02a62e570d392baaffe3f9839f5b03f8a7f36aec4b96252a0e5c1ca32614581dbdea530cc72754d1f89f1d488c9aa2bad5a5ec9bab6e94f7ab2e316118d
|
data/.gitignore
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# rcov generated
|
2
|
+
coverage
|
3
|
+
|
4
|
+
# rdoc generated
|
5
|
+
rdoc
|
6
|
+
|
7
|
+
# yard generated
|
8
|
+
doc
|
9
|
+
.yardoc
|
10
|
+
|
11
|
+
# bundler
|
12
|
+
.bundle
|
13
|
+
|
14
|
+
# jeweler generated
|
15
|
+
pkg
|
16
|
+
|
17
|
+
# Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
|
18
|
+
#
|
19
|
+
# * Create a file at ~/.gitignore
|
20
|
+
# * Include files you want ignored
|
21
|
+
# * Run: git config --global core.excludesfile ~/.gitignore
|
22
|
+
#
|
23
|
+
# After doing this, these files will be ignored in all your git projects,
|
24
|
+
# saving you from having to 'pollute' every project you touch with them
|
25
|
+
#
|
26
|
+
# Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
|
27
|
+
#
|
28
|
+
# For MacOS:
|
29
|
+
#
|
30
|
+
#.DS_Store
|
31
|
+
|
32
|
+
# For TextMate
|
33
|
+
#*.tmproj
|
34
|
+
#tmtags
|
35
|
+
|
36
|
+
# For emacs:
|
37
|
+
#*~
|
38
|
+
#\#*
|
39
|
+
#.\#*
|
40
|
+
|
41
|
+
# For vim:
|
42
|
+
#*.swp
|
43
|
+
|
44
|
+
# For redcar:
|
45
|
+
#.redcar
|
46
|
+
|
47
|
+
# For rubinius:
|
48
|
+
#*.rbc
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
akami (1.0.0)
|
5
|
+
gyoku (>= 0.4.0)
|
6
|
+
ansi (1.4.1)
|
7
|
+
builder (3.0.0)
|
8
|
+
fakeweb (1.3.0)
|
9
|
+
git (1.2.5)
|
10
|
+
gyoku (0.4.4)
|
11
|
+
builder (>= 2.1.2)
|
12
|
+
hashie (1.2.0)
|
13
|
+
httpi (0.9.5)
|
14
|
+
rack
|
15
|
+
jeweler (1.6.4)
|
16
|
+
bundler (~> 1.0)
|
17
|
+
git (>= 1.2.5)
|
18
|
+
rake
|
19
|
+
json (1.6.1)
|
20
|
+
metaclass (0.0.1)
|
21
|
+
minitest (2.8.1)
|
22
|
+
minitest-reporters (0.4.0)
|
23
|
+
ansi
|
24
|
+
minitest (~> 2.0)
|
25
|
+
ruby-progressbar
|
26
|
+
mocha (0.10.0)
|
27
|
+
metaclass (~> 0.0.1)
|
28
|
+
multi_json (1.0.3)
|
29
|
+
nokogiri (1.5.0)
|
30
|
+
nori (1.0.2)
|
31
|
+
rack (1.3.5)
|
32
|
+
rake (0.9.2.2)
|
33
|
+
rcov (0.9.11)
|
34
|
+
rdoc (3.11)
|
35
|
+
json (~> 1.4)
|
36
|
+
ruby-progressbar (0.0.10)
|
37
|
+
savon (0.9.7)
|
38
|
+
akami (~> 1.0)
|
39
|
+
builder (>= 2.1.2)
|
40
|
+
gyoku (>= 0.4.0)
|
41
|
+
httpi (~> 0.9)
|
42
|
+
nokogiri (>= 1.4.0)
|
43
|
+
nori (~> 1.0)
|
44
|
+
wasabi (~> 2.0)
|
45
|
+
savon_model (1.1.0)
|
46
|
+
httpi (>= 0.7.8)
|
47
|
+
savon (>= 0.8.2)
|
48
|
+
simplecov (0.5.4)
|
49
|
+
multi_json (~> 1.0.3)
|
50
|
+
simplecov-html (~> 0.5.3)
|
51
|
+
simplecov-html (0.5.3)
|
52
|
+
wasabi (2.0.0)
|
53
|
+
nokogiri (>= 1.4.0)
|
54
|
+
|
55
|
+
PLATFORMS
|
56
|
+
ruby
|
57
|
+
|
58
|
+
DEPENDENCIES
|
59
|
+
bundler (~> 1.0.0)
|
60
|
+
fakeweb
|
61
|
+
hashie (>= 0.0.0)
|
62
|
+
jeweler (~> 1.6.4)
|
63
|
+
minitest
|
64
|
+
minitest-reporters
|
65
|
+
mocha
|
66
|
+
rcov
|
67
|
+
rdoc
|
68
|
+
savon (>= 0.9.7)
|
69
|
+
savon_model (>= 0.0.0)
|
70
|
+
simplecov
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.2.1
|
Binary file
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require File.expand_path('../lib/affiliate-window/version', __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "affiliate-window"
|
5
|
+
s.version = AffiliateWindow::Version::STRING
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["andy.triggs@gmail.com"]
|
9
|
+
s.date = "2011-11-30"
|
10
|
+
s.description = "Affiliate Window provide APIs for interacting with their merchant, product and transaction data via your publisher account. This gem provides clients for those APIs."
|
11
|
+
s.email = "andy.triggs@gmail.com"
|
12
|
+
s.extra_rdoc_files = [
|
13
|
+
"LICENSE.txt",
|
14
|
+
"README.rdoc"
|
15
|
+
]
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.homepage = "http://github.com/andyt/affiliate-window"
|
18
|
+
s.licenses = ["MIT"]
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
s.rubygems_version = "1.8.10"
|
21
|
+
s.summary = "Clients and other publisher tools for using Affiliate Window APIs"
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
s.specification_version = 3
|
25
|
+
|
26
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
27
|
+
s.add_runtime_dependency(%q<savon>, [">= 0.9.7"])
|
28
|
+
s.add_runtime_dependency(%q<savon_model>, [">= 0.0.0"])
|
29
|
+
s.add_runtime_dependency(%q<hashie>, [">= 0.0.0"])
|
30
|
+
s.add_development_dependency(%q<minitest>, [">= 0"])
|
31
|
+
s.add_development_dependency(%q<minitest-reporters>, [">= 0"])
|
32
|
+
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
33
|
+
s.add_development_dependency(%q<fakeweb>, [">= 0"])
|
34
|
+
s.add_development_dependency(%q<mocha>, [">= 0"])
|
35
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
36
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
37
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
38
|
+
s.add_development_dependency(%q<rdoc>, [">= 0"])
|
39
|
+
else
|
40
|
+
s.add_dependency(%q<savon>, [">= 0.9.7"])
|
41
|
+
s.add_dependency(%q<savon_model>, [">= 0.0.0"])
|
42
|
+
s.add_dependency(%q<hashie>, [">= 0.0.0"])
|
43
|
+
s.add_dependency(%q<minitest>, [">= 0"])
|
44
|
+
s.add_dependency(%q<minitest-reporters>, [">= 0"])
|
45
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
46
|
+
s.add_dependency(%q<fakeweb>, [">= 0"])
|
47
|
+
s.add_dependency(%q<mocha>, [">= 0"])
|
48
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
49
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
50
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
51
|
+
s.add_dependency(%q<rdoc>, [">= 0"])
|
52
|
+
end
|
53
|
+
else
|
54
|
+
s.add_dependency(%q<savon>, [">= 0.9.7"])
|
55
|
+
s.add_dependency(%q<savon_model>, [">= 0.0.0"])
|
56
|
+
s.add_dependency(%q<hashie>, [">= 0.0.0"])
|
57
|
+
s.add_dependency(%q<minitest>, [">= 0"])
|
58
|
+
s.add_dependency(%q<minitest-reporters>, [">= 0"])
|
59
|
+
s.add_dependency(%q<simplecov>, [">= 0"])
|
60
|
+
s.add_dependency(%q<fakeweb>, [">= 0"])
|
61
|
+
s.add_dependency(%q<mocha>, [">= 0"])
|
62
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
63
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
64
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
65
|
+
s.add_dependency(%q<rdoc>, [">= 0"])
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module AffiliateWindow
|
2
|
+
class Account
|
3
|
+
attr_reader :user, :api_password, :api_key, :datafeed_password, :format, :compression
|
4
|
+
|
5
|
+
VALID_FORMATS = %w{CSV} # XML not yet supported.
|
6
|
+
|
7
|
+
# Unzipping is not supported for portability, but you can specify it to download a zipped file.
|
8
|
+
# CSV helper methods won't work with zipped downloads.
|
9
|
+
VALID_COMPRESSIONS = %w{none zip}
|
10
|
+
|
11
|
+
def initialize(options)
|
12
|
+
@user ||= options[:user] || raise(ArgumentError, ":user option is required.")
|
13
|
+
@api_password ||= options[:api_password] || raise(ArgumentError, ":api_password option is required.")
|
14
|
+
@api_key ||= options[:api_key] || raise(ArgumentError, ":api_key option is required.")
|
15
|
+
@datafeed_password ||= options[:datafeed_password] || raise(ArgumentError, ":datafeed_password option is required.")
|
16
|
+
self.format = options[:format] || VALID_FORMATS.first
|
17
|
+
self.compression = options[:compression] || VALID_COMPRESSIONS.first
|
18
|
+
end
|
19
|
+
|
20
|
+
def format=(value)
|
21
|
+
value = value.upcase.to_s
|
22
|
+
raise ArgumentError, "Invalid format #{value} - use #{VALID_FORMATS.join(', ')}." unless VALID_FORMATS.include?(value)
|
23
|
+
@format = value
|
24
|
+
end
|
25
|
+
|
26
|
+
def compression=(value)
|
27
|
+
value = value.downcase.to_s
|
28
|
+
raise ArgumentError, "Invalid compression #{value} - use #{VALID_COMPRESSIONS.join(', ')}." unless VALID_COMPRESSIONS.include?(value)
|
29
|
+
@compression = value
|
30
|
+
end
|
31
|
+
|
32
|
+
def compression_parameter
|
33
|
+
@compression == 'none' ? '' : @compression
|
34
|
+
end
|
35
|
+
|
36
|
+
def attributes
|
37
|
+
{
|
38
|
+
:user => user,
|
39
|
+
:api_password => api_password,
|
40
|
+
:api_key => api_key,
|
41
|
+
:datafeed_password => datafeed_password,
|
42
|
+
:format => format,
|
43
|
+
:compression => compression
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module AffiliateWindow::Clients
|
2
|
+
|
3
|
+
# SOAP client for the AffiliateWindow AffiliateService API.
|
4
|
+
#
|
5
|
+
# Instantiate carefully! This parses the WSDL document every time.
|
6
|
+
class AffiliateService < Savon::Client
|
7
|
+
|
8
|
+
include AffiliateWindow::Helpers::Account
|
9
|
+
|
10
|
+
ENDPOINT_URL = 'http://api.affiliatewindow.com/v3/AffiliateService'
|
11
|
+
|
12
|
+
WSDL_URL = ENDPOINT_URL + '?wsdl'
|
13
|
+
|
14
|
+
CACHED_WSDL_PATH = File.join(File.dirname(__FILE__), '..', '..', '..', 'wsdl', 'affiliate_service_v3.wsdl')
|
15
|
+
|
16
|
+
ACTIONS = [:get_transaction_list, :get_transaction_product, :get_transaction, :get_merchant_list, :get_merchant, :get_transaction_querys, :set_transaction_query, :get_impression_stats, :get_click_stats, :get_commission_group, :get_commission_group_list]
|
17
|
+
|
18
|
+
def initialize(account = nil)
|
19
|
+
set_account(account)
|
20
|
+
super(CACHED_WSDL_PATH)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Override the request method so that we can inject the authentication header.
|
24
|
+
def request(*args, &block)
|
25
|
+
super(*args) do
|
26
|
+
soap.header = header
|
27
|
+
process &block if block
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
# We need 'UserAuthenication' as a string due to the odd capitalisation.
|
34
|
+
def header
|
35
|
+
{
|
36
|
+
'UserAuthentication' => {
|
37
|
+
:i_id => user,
|
38
|
+
:s_password => api_password,
|
39
|
+
:s_type => 'affiliate'
|
40
|
+
}
|
41
|
+
}
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module AffiliateWindow::Clients
|
2
|
+
|
3
|
+
class Category
|
4
|
+
|
5
|
+
include AffiliateWindow::Helpers::Account
|
6
|
+
include AffiliateWindow::Helpers::Csv
|
7
|
+
|
8
|
+
URL_TEMPLATE = 'http://datafeeds.productserve.com/datafeed_category.php?user=#{user}&password=#{datafeed_password}&format=#{format}&compression=#{compression_parameter}'
|
9
|
+
|
10
|
+
def initialize(account = nil)
|
11
|
+
set_account(account)
|
12
|
+
end
|
13
|
+
|
14
|
+
def url
|
15
|
+
@url ||= eval(%Q|"#{URL_TEMPLATE}"|)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module AffiliateWindow::Clients
|
2
|
+
|
3
|
+
class Merchant
|
4
|
+
|
5
|
+
include AffiliateWindow::Helpers::Account
|
6
|
+
include AffiliateWindow::Helpers::Csv
|
7
|
+
|
8
|
+
attr :filter
|
9
|
+
|
10
|
+
URL_TEMPLATE = 'https://www.affiliatewindow.com/affiliates/shopwindow/datafeed_metadata.php?user=#{user}&password=#{datafeed_password}&format=#{format}&filter=#{filter}&compression='
|
11
|
+
|
12
|
+
VALID_FILTERS = %w{SUBSCRIBED_ALL SUBSCRIBED_ENABLED ALL_ALL ALL_ENABLED}
|
13
|
+
|
14
|
+
def initialize(filter = nil, account = nil)
|
15
|
+
set_account(account)
|
16
|
+
self.filter = filter || VALID_FILTERS.first
|
17
|
+
end
|
18
|
+
|
19
|
+
def url
|
20
|
+
@url ||= eval(%Q|"#{URL_TEMPLATE}"|)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def filter=(value)
|
26
|
+
value = value.to_s.upcase
|
27
|
+
raise ArgumentError unless VALID_FILTERS.include?(value)
|
28
|
+
@filter = value
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module AffiliateWindow
|
2
|
+
module Clients
|
3
|
+
|
4
|
+
class ShopWindow
|
5
|
+
|
6
|
+
include AffiliateWindow::Helpers::Client
|
7
|
+
include AffiliateWindow::Helpers::Account
|
8
|
+
include AffiliateWindow::Helpers::Csv
|
9
|
+
|
10
|
+
attr :merchant_ids
|
11
|
+
|
12
|
+
# This URL template only works for a selection of merchants by ID.
|
13
|
+
# It ignores the compression setting in account. Valid options are zip or gzip. We use zip.
|
14
|
+
URL_TEMPLATE = 'http://datafeed.api.productserve.com/datafeed/download/apikey/#{api_key}/mid/#{merchant_id_list}/columns/#{column_list}/format/#{format.downcase}/compression/zip/'
|
15
|
+
|
16
|
+
DEFAULT_COLUMNS = %w{ merchant_id merchant_name aw_product_id merchant_product_id product_name description
|
17
|
+
category_id category_name merchant_category aw_deep_link aw_image_url search_price
|
18
|
+
delivery_cost merchant_deep_link merchant_image_url mpn rrp_price stock_quantity
|
19
|
+
brand_id ean merchant_thumb_url brand_name in_stock model_number specifications upc }
|
20
|
+
|
21
|
+
def initialize(options = {})
|
22
|
+
parse_options(options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def url
|
26
|
+
@url ||= eval(%Q|"#{URL_TEMPLATE}"|)
|
27
|
+
end
|
28
|
+
|
29
|
+
def columns
|
30
|
+
@columns || DEFAULT_COLUMNS
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def column_list
|
36
|
+
columns.join(',')
|
37
|
+
end
|
38
|
+
|
39
|
+
def merchant_id_list
|
40
|
+
merchant_ids.join(',')
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module AffiliateWindow::Helpers
|
2
|
+
|
3
|
+
# Helper methods for account delegation and using a default account.
|
4
|
+
module Account
|
5
|
+
|
6
|
+
attr_accessor :account
|
7
|
+
|
8
|
+
# Some delegation methods (avoids having a delegation dependency).
|
9
|
+
def user; account.user; end
|
10
|
+
def datafeed_password; account.datafeed_password; end
|
11
|
+
def api_password; account.api_password; end
|
12
|
+
def api_key; account.api_key; end
|
13
|
+
|
14
|
+
def format; account.format; end
|
15
|
+
def compression_parameter; account.compression_parameter; end
|
16
|
+
|
17
|
+
# Sets @account to the passed account, or a defined default.
|
18
|
+
def set_account(account)
|
19
|
+
@account = account || AffiliateWindow.account
|
20
|
+
raise ArgumentError, "Pass the account parameter, or set AffiliateWindow.account." unless @account
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module AffiliateWindow::Helpers
|
2
|
+
|
3
|
+
# Helper methods for client classes.
|
4
|
+
module Client
|
5
|
+
|
6
|
+
def parse_options(options)
|
7
|
+
set_account(options.delete(:account))
|
8
|
+
options.each do |k, v|
|
9
|
+
if respond_to?(k)
|
10
|
+
instance_variable_set("@#{k}", v)
|
11
|
+
else
|
12
|
+
raise ArgumentError, "Unknown option #{k}."
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def fetch(target = Tempfile.new('awin').path)
|
18
|
+
AffiliateWindow.fetch(url, target)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|