foxy_sync 0.1.1 → 0.2.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/lib/foxy_sync/api/base.rb +9 -8
- data/lib/foxy_sync/api/customer.rb +4 -3
- data/lib/foxy_sync/api/messenger.rb +2 -2
- data/lib/foxy_sync/datafeed.rb +3 -3
- data/lib/foxy_sync/xml/base.rb +48 -0
- data/lib/foxy_sync/xml/document.rb +22 -0
- data/lib/foxy_sync/xml/transaction_detail.rb +39 -0
- data/lib/foxy_sync.rb +8 -2
- metadata +23 -11
- data/lib/foxy_sync/api/response.rb +0 -47
data/lib/foxy_sync/api/base.rb
CHANGED
@@ -1,22 +1,23 @@
|
|
1
1
|
module FoxySync::Api
|
2
2
|
#
|
3
3
|
# Intended for subclassing, +Base+ forms the foundation
|
4
|
-
# for ::Api:: classes that wrap
|
5
|
-
#
|
4
|
+
# for ::Api:: classes that wrap a +FoxySync::Xml::Document+
|
5
|
+
# composed of API reply XML to provide behavior around
|
6
|
+
# specific elements
|
6
7
|
class Base
|
7
|
-
|
8
|
+
attr_reader :api_response
|
8
9
|
|
9
10
|
#
|
10
11
|
# [_api_response_]
|
11
|
-
# A +FoxySync::
|
12
|
+
# A +FoxySync::Xml::Document+ that holds API reply XML
|
12
13
|
def initialize(api_response)
|
13
|
-
|
14
|
+
@api_response = api_response
|
14
15
|
end
|
15
16
|
|
16
17
|
#
|
17
18
|
# Delegates to #api_response
|
18
19
|
def respond_to?(method_name, include_private = false)
|
19
|
-
api_response.respond_to?
|
20
|
+
super || api_response.respond_to?(method_name, include_private)
|
20
21
|
end
|
21
22
|
|
22
23
|
|
@@ -27,8 +28,8 @@ module FoxySync::Api
|
|
27
28
|
end
|
28
29
|
|
29
30
|
|
30
|
-
def
|
31
|
-
@
|
31
|
+
def messenger
|
32
|
+
@_messenger ||= FoxySync::Api::Messenger.new
|
32
33
|
end
|
33
34
|
end
|
34
35
|
end
|
@@ -20,21 +20,22 @@ module FoxySync::Api
|
|
20
20
|
# that work with authentication systems like +Devise+
|
21
21
|
def initialize(user)
|
22
22
|
self.user = user
|
23
|
-
super
|
23
|
+
super messenger.customer_get :customer_email => user.email
|
24
24
|
end
|
25
25
|
|
26
26
|
|
27
27
|
#
|
28
28
|
# Sends the customer_save command to the FoxyCart API.
|
29
|
-
# Returns a FoxySync::
|
29
|
+
# Returns a FoxySync::Xml::Document
|
30
30
|
def save
|
31
31
|
salt = user.password_salt
|
32
32
|
hash = OpenSSL::HMAC.hexdigest 'sha256', salt, user.encrypted_password + salt
|
33
|
-
|
33
|
+
messenger.customer_save(
|
34
34
|
:customer_email => user.email,
|
35
35
|
:customer_password_hash => hash,
|
36
36
|
:customer_password_salt => salt
|
37
37
|
)
|
38
38
|
end
|
39
39
|
end
|
40
|
+
|
40
41
|
end
|
@@ -7,7 +7,7 @@ module FoxySync::Api
|
|
7
7
|
# the FoxyCart API (http://wiki.foxycart.com/v/1.0/api).
|
8
8
|
# To use it create a new instance and then send it a message
|
9
9
|
# that corresponds to the FoxyCart API. All messages
|
10
|
-
# return an instance of +FoxySync::
|
10
|
+
# return an instance of +FoxySync::Xml::Document+. For Example:
|
11
11
|
#
|
12
12
|
# api = FoxySync::Api::Messenger.new
|
13
13
|
# reply = api.customer_get :customer_email => 'foo@bar.com'
|
@@ -49,7 +49,7 @@ module FoxySync::Api
|
|
49
49
|
def method_missing(method_name, *args, &block)
|
50
50
|
return super unless respond_to? method_name
|
51
51
|
xml = api_request method_name, args.first || {}
|
52
|
-
FoxySync::
|
52
|
+
FoxySync::Xml::Document.new xml
|
53
53
|
end
|
54
54
|
|
55
55
|
|
data/lib/foxy_sync/datafeed.rb
CHANGED
@@ -9,8 +9,8 @@ module FoxySync
|
|
9
9
|
module Datafeed
|
10
10
|
|
11
11
|
#
|
12
|
-
# Handles the decoding and decrypting of a datafeed
|
13
|
-
# Returns a +FoxySync::
|
12
|
+
# Handles the decoding and decrypting of a datafeed.
|
13
|
+
# Returns a +FoxySync::Xml::Document+ whose #xml is the datafeed XML
|
14
14
|
#[_params_]
|
15
15
|
# Something that responds_to? [] and has a key 'FoxyData'. In Rails
|
16
16
|
# that would be the +params+ object
|
@@ -18,7 +18,7 @@ module FoxySync
|
|
18
18
|
encrypted = params['FoxyData']
|
19
19
|
rc4 = RC4.new FoxySync.api_key
|
20
20
|
xml = rc4.decrypt CGI::unescape(encrypted)
|
21
|
-
FoxySync::
|
21
|
+
FoxySync::Xml::Document.new xml
|
22
22
|
end
|
23
23
|
|
24
24
|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module FoxySync::Xml
|
2
|
+
#
|
3
|
+
# Allows querying of the given +Nokogiri::XML::Node+.
|
4
|
+
# Every message returns:
|
5
|
+
#
|
6
|
+
# * nil if no matching element is found in the XML or
|
7
|
+
# if the matched element(s) do not contain text or cdata.
|
8
|
+
# * A +String+ if there is one matching element in the reply.
|
9
|
+
# * An +Array+ with all element values if there is more than one
|
10
|
+
# matching element in the XML.
|
11
|
+
class Base
|
12
|
+
|
13
|
+
attr_reader :node
|
14
|
+
|
15
|
+
|
16
|
+
#
|
17
|
+
# [_node_]
|
18
|
+
# A +Nokogiri::XML::Node+
|
19
|
+
def initialize(node)
|
20
|
+
@node = node
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
def respond_to?(method_name, include_private = false)
|
25
|
+
true # respond to everything; we don't know what will be in the response doc
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def method_missing(method_name, *args, &block)
|
32
|
+
node_set = node.xpath "//#{method_name}"
|
33
|
+
return nil if node_set.nil? || node_set.empty?
|
34
|
+
|
35
|
+
contents = []
|
36
|
+
|
37
|
+
node_set.children.each do |child|
|
38
|
+
next if child.element?
|
39
|
+
content = child.content.strip
|
40
|
+
contents << content unless content.empty?
|
41
|
+
end
|
42
|
+
|
43
|
+
contents.empty? ? nil : contents.size == 1 ? contents.first : contents
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module FoxySync::Xml
|
4
|
+
#
|
5
|
+
# Encapsulates a FoxyCart XML doc. To use it simply send a
|
6
|
+
# message that corresponds to an element in the XML. For example,
|
7
|
+
#
|
8
|
+
# api = FoxySync::Api::Messenger.new
|
9
|
+
# reply = api.customer_get :customer_email => 'foo@bar.com'
|
10
|
+
# reply.customer_id # is the customer's FoxyCart id
|
11
|
+
class Document < Base
|
12
|
+
#
|
13
|
+
# The raw XML used to create this +Document+
|
14
|
+
attr_reader :xml
|
15
|
+
|
16
|
+
|
17
|
+
def initialize(xml)
|
18
|
+
@xml = xml
|
19
|
+
super Nokogiri::XML(xml) {|config| config.strict.nonet }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module FoxySync::Xml
|
2
|
+
#
|
3
|
+
# Provides methods to easily query the transaction_detail
|
4
|
+
# elements found in a FoxyCart transaction XML datafeed
|
5
|
+
class TransactionDetail < Base
|
6
|
+
|
7
|
+
#
|
8
|
+
# Returns an +Array+ of the +TransactionDetail+s in +xml_base+
|
9
|
+
# [_xml_base_]
|
10
|
+
# A +FoxySync::Xml::Base+ that has a transaction_details element
|
11
|
+
def self.all(xml_base)
|
12
|
+
transactions = []
|
13
|
+
|
14
|
+
xml_base.node.xpath('//transaction_details').each do |detail|
|
15
|
+
transactions << new(detail)
|
16
|
+
end
|
17
|
+
|
18
|
+
transactions
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
#
|
23
|
+
# Returns custom product options in a 'name' => 'value' +Hash+
|
24
|
+
def custom_product_options
|
25
|
+
options = {}
|
26
|
+
options_xml = node.xpath '//transaction_detail_option'
|
27
|
+
|
28
|
+
options_xml.each do |node|
|
29
|
+
name = node.at_css('product_option_name').content.strip
|
30
|
+
value = node.at_css('product_option_value').content.strip
|
31
|
+
options[name] = value
|
32
|
+
end
|
33
|
+
|
34
|
+
options
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
data/lib/foxy_sync.rb
CHANGED
@@ -4,10 +4,16 @@ module FoxySync
|
|
4
4
|
autoload :CartValidation, 'foxy_sync/cart_validation'
|
5
5
|
|
6
6
|
module Api
|
7
|
-
autoload :Messenger, 'foxy_sync/api/messenger'
|
8
|
-
autoload :Response, 'foxy_sync/api/response'
|
9
7
|
autoload :Base, 'foxy_sync/api/base'
|
10
8
|
autoload :Customer, 'foxy_sync/api/customer'
|
9
|
+
autoload :Messenger, 'foxy_sync/api/messenger'
|
10
|
+
end
|
11
|
+
|
12
|
+
module Xml
|
13
|
+
autoload :Base, 'foxy_sync/xml/base'
|
14
|
+
autoload :Document, 'foxy_sync/xml/document'
|
15
|
+
autoload :Transaction, 'foxy_sync/xml/transaction'
|
16
|
+
autoload :TransactionDetail, 'foxy_sync/xml/transaction_detail'
|
11
17
|
end
|
12
18
|
|
13
19
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: foxy_sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-03-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nokogiri
|
@@ -65,14 +65,26 @@ executables: []
|
|
65
65
|
extensions: []
|
66
66
|
extra_rdoc_files: []
|
67
67
|
files:
|
68
|
-
-
|
69
|
-
|
70
|
-
-
|
71
|
-
|
72
|
-
-
|
73
|
-
|
74
|
-
-
|
75
|
-
|
68
|
+
- !binary |-
|
69
|
+
Li9saWIvZm94eV9zeW5jL2FwaS9iYXNlLnJi
|
70
|
+
- !binary |-
|
71
|
+
Li9saWIvZm94eV9zeW5jL2FwaS9jdXN0b21lci5yYg==
|
72
|
+
- !binary |-
|
73
|
+
Li9saWIvZm94eV9zeW5jL2FwaS9tZXNzZW5nZXIucmI=
|
74
|
+
- !binary |-
|
75
|
+
Li9saWIvZm94eV9zeW5jL2NhcnRfdmFsaWRhdGlvbi5yYg==
|
76
|
+
- !binary |-
|
77
|
+
Li9saWIvZm94eV9zeW5jL2RhdGFmZWVkLnJi
|
78
|
+
- !binary |-
|
79
|
+
Li9saWIvZm94eV9zeW5jL3Nzby5yYg==
|
80
|
+
- !binary |-
|
81
|
+
Li9saWIvZm94eV9zeW5jL3htbC9iYXNlLnJi
|
82
|
+
- !binary |-
|
83
|
+
Li9saWIvZm94eV9zeW5jL3htbC9kb2N1bWVudC5yYg==
|
84
|
+
- !binary |-
|
85
|
+
Li9saWIvZm94eV9zeW5jL3htbC90cmFuc2FjdGlvbl9kZXRhaWwucmI=
|
86
|
+
- !binary |-
|
87
|
+
Li9saWIvZm94eV9zeW5jLnJi
|
76
88
|
homepage: https://github.com/tablexi/foxy_sync
|
77
89
|
licenses: []
|
78
90
|
post_install_message:
|
@@ -93,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
93
105
|
version: '0'
|
94
106
|
requirements: []
|
95
107
|
rubyforge_project:
|
96
|
-
rubygems_version: 1.8.
|
108
|
+
rubygems_version: 1.8.24
|
97
109
|
signing_key:
|
98
110
|
specification_version: 3
|
99
111
|
summary: Synchronizes your Ruby application with FoxyCart
|
@@ -1,47 +0,0 @@
|
|
1
|
-
require 'nokogiri'
|
2
|
-
|
3
|
-
module FoxySync::Api
|
4
|
-
#
|
5
|
-
# A +Response+ represents an XML reply
|
6
|
-
# sent by the FoxyCart API. To use it simply
|
7
|
-
# send an instance a message that corresponds
|
8
|
-
# to an element in the XML. For example,
|
9
|
-
#
|
10
|
-
# api = FoxySync::Api::Messenger.new
|
11
|
-
# reply = api.customer_get :customer_email => 'foo@bar.com'
|
12
|
-
# reply.customer_id # is the customer's FoxyCart id
|
13
|
-
#
|
14
|
-
# Every message will return +nil+ if no matching
|
15
|
-
# element is found in the XML reply, a +String+ if
|
16
|
-
# there is one matching element in the reply, or an
|
17
|
-
# +Array+ with all element values if there is more than one
|
18
|
-
# element in the XML reply.
|
19
|
-
class Response
|
20
|
-
#
|
21
|
-
# A +Nokogiri::XML::Document+ of the API reply
|
22
|
-
attr_reader :document
|
23
|
-
|
24
|
-
|
25
|
-
def initialize(xml)
|
26
|
-
@document = Nokogiri::XML(xml) {|config| config.strict.nonet }
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
def respond_to?(method_name, include_private = false)
|
31
|
-
true # respond to everything; we don't know what will be in the response doc
|
32
|
-
end
|
33
|
-
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def method_missing(method_name, *args, &block)
|
38
|
-
node_set = document.xpath "//#{method_name}"
|
39
|
-
return nil if node_set.nil? || node_set.empty?
|
40
|
-
|
41
|
-
contents = node_set.to_a
|
42
|
-
contents.map!{|node| node.content }
|
43
|
-
contents.delete_if{|content| content.empty? }
|
44
|
-
contents.size == 1 ? contents.first : contents
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|