jirafe 0.3.0 → 0.5.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/fixtures/responses/callback_event_post_event.yml +3 -3
- data/fixtures/responses/callback_event_post_event_fetch_token.yml +1412 -12
- data/fixtures/responses/sync_reset_with_app_token.yml +38 -0
- data/lib/jirafe.rb +3 -0
- data/lib/jirafe/callback/event.rb +4 -5
- data/lib/jirafe/callback/events/data_helper.rb +25 -0
- data/lib/jirafe/callback/events/item.rb +21 -0
- data/lib/jirafe/callback/events/order.rb +7 -6
- data/lib/jirafe/callback/events/refund.rb +7 -6
- data/lib/jirafe/callback/jirafe_callback.rb +2 -23
- data/lib/jirafe/resource/jirafe_resource.rb +2 -21
- data/lib/jirafe/response_parser.rb +30 -0
- data/lib/jirafe/version.rb +1 -1
- data/spec/jirafe/callback/event_spec.rb +56 -24
- data/spec/jirafe/callback/events/data_helper_spec.rb +49 -0
- data/spec/jirafe/resource/resources_spec.rb +7 -0
- data/spec/spec_helper.rb +15 -5
- metadata +8 -2
@@ -0,0 +1,38 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: post
|
5
|
+
uri: http://api.jirafe.dev/v1/applications/1/resources?token=secret_token
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: sites[0][description]=Test%20Site&sites[0][url]=http%3A%2F%2Fjirafe.com&sites[0][currency]=EUR&sites[0][timezone]=Europe%2FParis&sites[0][external_id]=1&sites[0][site_id]=1&users[0][email]=user%40example.com&users[0][first_name]=Test&users[0][last_name]=User
|
9
|
+
headers: {}
|
10
|
+
response:
|
11
|
+
status:
|
12
|
+
code: 200
|
13
|
+
message: OK
|
14
|
+
headers:
|
15
|
+
Server:
|
16
|
+
- nginx/1.2.2
|
17
|
+
Content-Type:
|
18
|
+
- application/json
|
19
|
+
Transfer-Encoding:
|
20
|
+
- chunked
|
21
|
+
Connection:
|
22
|
+
- keep-alive
|
23
|
+
Keep-Alive:
|
24
|
+
- timeout=10
|
25
|
+
X-Powered-By:
|
26
|
+
- PHP/5.3.15
|
27
|
+
Cache-Control:
|
28
|
+
- no-cache
|
29
|
+
Date:
|
30
|
+
- Wed, 12 Sep 2012 20:41:37 GMT
|
31
|
+
X-Debug-Token:
|
32
|
+
- 5050f3815203d
|
33
|
+
body:
|
34
|
+
encoding: US-ASCII
|
35
|
+
string: ! '{"sites":[{"site_id":1,"app_id":1,"description":"Test Site","url":"http:\/\/jirafe.com","timezone":"Europe\/Paris","currency":"EUR","external_id":"1","store_api_url":null,"store_cart_url":null}],"users":[{"email":"user@example.com","username":null,"first_name":"Test","last_name":"User","mobile_phone":null,"token":"c2785280dffad7835195b7a44829a103"}]}'
|
36
|
+
http_version:
|
37
|
+
recorded_at: Wed, 12 Sep 2012 20:41:37 GMT
|
38
|
+
recorded_with: VCR 2.2.4
|
data/lib/jirafe.rb
CHANGED
@@ -16,6 +16,7 @@ module Jirafe
|
|
16
16
|
autoload :VERSION, "jirafe/version.rb"
|
17
17
|
autoload :Configuration, "jirafe/configuration.rb"
|
18
18
|
autoload :Error, "jirafe/error.rb"
|
19
|
+
autoload :ResponseParser, "jirafe/response_parser.rb"
|
19
20
|
autoload :Asset, "jirafe/asset.rb"
|
20
21
|
autoload :Tracker, "jirafe/tracker.rb"
|
21
22
|
module Resource
|
@@ -58,6 +59,8 @@ module Jirafe
|
|
58
59
|
autoload :JirafeCallback, "jirafe/callback/jirafe_callback.rb"
|
59
60
|
autoload :Event, "jirafe/callback/event.rb"
|
60
61
|
module Events
|
62
|
+
autoload :DataHelper, "jirafe/callback/events/data_helper.rb"
|
63
|
+
autoload :Item, "jirafe/callback/events/item.rb"
|
61
64
|
autoload :Order, "jirafe/callback/events/order.rb"
|
62
65
|
autoload :Refund, "jirafe/callback/events/refund.rb"
|
63
66
|
end
|
@@ -23,6 +23,10 @@ module Jirafe
|
|
23
23
|
check_response_for_exception(response)
|
24
24
|
true
|
25
25
|
end
|
26
|
+
|
27
|
+
def trust_callback?(token, confirmation_token, confirmation_hash)
|
28
|
+
Digest::SHA1.hexdigest(confirmation_token.to_s + token.to_s) == confirmation_hash
|
29
|
+
end
|
26
30
|
end
|
27
31
|
|
28
32
|
def action_map
|
@@ -45,11 +49,6 @@ module Jirafe
|
|
45
49
|
}.to_json(*args)
|
46
50
|
end
|
47
51
|
|
48
|
-
def initialize(attributes = {})
|
49
|
-
attributes.each do |attr, value|
|
50
|
-
self.send("#{attr}=", value) if self.respond_to?("#{attr}=")
|
51
|
-
end
|
52
|
-
end
|
53
52
|
end
|
54
53
|
end
|
55
54
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Jirafe
|
2
|
+
module Callback
|
3
|
+
module Events
|
4
|
+
module DataHelper
|
5
|
+
def initialize(attributes = {})
|
6
|
+
attributes.each do |attr, value|
|
7
|
+
self.send("#{attr}=", value) if self.respond_to?("#{attr}=")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def format_amount(amount)
|
12
|
+
return nil if amount.nil?
|
13
|
+
"%01.4f" % amount
|
14
|
+
end
|
15
|
+
|
16
|
+
def format_discount_amount(amount)
|
17
|
+
return nil if amount.nil?
|
18
|
+
format_amount(amount.abs)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Jirafe
|
2
|
+
module Callback
|
3
|
+
module Events
|
4
|
+
class Item
|
5
|
+
include DataHelper
|
6
|
+
attr_accessor :sku, :name, :price, :quantity, :category
|
7
|
+
|
8
|
+
def data
|
9
|
+
{
|
10
|
+
"sku" => sku,
|
11
|
+
"name" => name,
|
12
|
+
"price" => format_amount(price),
|
13
|
+
"quantity" => quantity,
|
14
|
+
"category" => category
|
15
|
+
}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -2,6 +2,7 @@ module Jirafe
|
|
2
2
|
module Callback
|
3
3
|
module Events
|
4
4
|
class Order < Jirafe::Callback::Event
|
5
|
+
include DataHelper
|
5
6
|
attr_accessor :identifier, :status, :customer, :visitor_identifier, :created_at,
|
6
7
|
:grand_total, :sub_total, :tax_amount, :shipping_amount, :discount_amount, :items
|
7
8
|
|
@@ -34,12 +35,12 @@ module Jirafe
|
|
34
35
|
"customerHash" => customer,
|
35
36
|
"vistorId" => visitor_identifier,
|
36
37
|
"time" => created_at || Time.now.to_i,
|
37
|
-
"grandTotal" => grand_total,
|
38
|
-
"subTotal" => sub_total,
|
39
|
-
"taxAmount" => tax_amount,
|
40
|
-
"shippingAmount" => shipping_amount,
|
41
|
-
"discountAmount" => discount_amount,
|
42
|
-
"items" => items
|
38
|
+
"grandTotal" => format_amount(grand_total),
|
39
|
+
"subTotal" => format_amount(sub_total),
|
40
|
+
"taxAmount" => format_amount(tax_amount),
|
41
|
+
"shippingAmount" => format_amount(shipping_amount),
|
42
|
+
"discountAmount" => format_discount_amount(discount_amount),
|
43
|
+
"items" => items.map { |item| item.data }
|
43
44
|
}
|
44
45
|
end
|
45
46
|
end
|
@@ -2,6 +2,7 @@ module Jirafe
|
|
2
2
|
module Callback
|
3
3
|
module Events
|
4
4
|
class Refund < Jirafe::Callback::Event
|
5
|
+
include DataHelper
|
5
6
|
attr_accessor :identifier, :order_identifier, :created_at,
|
6
7
|
:grand_total, :sub_total, :tax_amount, :shipping_amount,
|
7
8
|
:discount_amount, :items
|
@@ -18,12 +19,12 @@ module Jirafe
|
|
18
19
|
"refundId" => identifier,
|
19
20
|
"orderId" => order_identifier,
|
20
21
|
"time" => created_at || Time.now.to_i,
|
21
|
-
"grandTotal" => grand_total,
|
22
|
-
"subTotal" => sub_total,
|
23
|
-
"taxAmount" => tax_amount
|
24
|
-
"shippingAmount" => shipping_amount,
|
25
|
-
"discountAmount" => discount_amount,
|
26
|
-
"items" => items
|
22
|
+
"grandTotal" => format_amount(grand_total),
|
23
|
+
"subTotal" => format_amount(sub_total),
|
24
|
+
"taxAmount" => format_amount(tax_amount),
|
25
|
+
"shippingAmount" => format_amount(shipping_amount),
|
26
|
+
"discountAmount" => format_discount_amount(discount_amount),
|
27
|
+
"items" => items.map { |item| item.data }
|
27
28
|
}
|
28
29
|
end
|
29
30
|
end
|
@@ -2,6 +2,8 @@ module Jirafe
|
|
2
2
|
module Callback
|
3
3
|
class JirafeCallback
|
4
4
|
include HTTParty
|
5
|
+
include Jirafe::ResponseParser
|
6
|
+
|
5
7
|
base_uri Jirafe.config.callback_url
|
6
8
|
format :html
|
7
9
|
debug_output Jirafe.config.logger if ENV["DEBUG_JIRAFE"]
|
@@ -21,29 +23,6 @@ module Jirafe
|
|
21
23
|
check_response_for_exception(response)
|
22
24
|
true
|
23
25
|
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
def check_response_for_exception(response)
|
28
|
-
return if (200..399).include?(response.code) # Allow any 2xx or 3xx
|
29
|
-
exception = case response.code.to_i
|
30
|
-
when 400 # NOTE: Being thrown for what should be 422's
|
31
|
-
Jirafe::Error::BadRequest
|
32
|
-
when 401
|
33
|
-
Jirafe::Error::Unauthorized
|
34
|
-
when 403
|
35
|
-
Jirafe::Error::Forbidden
|
36
|
-
when 404
|
37
|
-
Jirafe::Error::ResourceNotFound
|
38
|
-
when 405
|
39
|
-
Jirafe::Error::NotAllowed
|
40
|
-
when 500
|
41
|
-
Jirafe::Error::ServerError
|
42
|
-
else
|
43
|
-
Jirafe::Error::UnknownError
|
44
|
-
end
|
45
|
-
raise exception.new(response)
|
46
|
-
end
|
47
26
|
end
|
48
27
|
end
|
49
28
|
end
|
@@ -2,6 +2,8 @@ module Jirafe
|
|
2
2
|
module Resource
|
3
3
|
class JirafeResource
|
4
4
|
include HTTParty
|
5
|
+
include Jirafe::ResponseParser
|
6
|
+
|
5
7
|
base_uri Jirafe.config.url
|
6
8
|
format :json
|
7
9
|
default_params :token => Jirafe.config.token
|
@@ -95,27 +97,6 @@ module Jirafe
|
|
95
97
|
query_options = options.delete(:query) || {}
|
96
98
|
{:query => { :token => Jirafe.config.token }.merge(query_options) }.merge(options)
|
97
99
|
end
|
98
|
-
|
99
|
-
def check_response_for_exception(response)
|
100
|
-
return if (200..399).include?(response.code) # Allow any 2xx or 3xx
|
101
|
-
exception = case response.code.to_i
|
102
|
-
when 400 # NOTE: Being thrown for what should be 422's
|
103
|
-
Jirafe::Error::BadRequest
|
104
|
-
when 401
|
105
|
-
Jirafe::Error::Unauthorized
|
106
|
-
when 403
|
107
|
-
Jirafe::Error::Forbidden
|
108
|
-
when 404
|
109
|
-
Jirafe::Error::ResourceNotFound
|
110
|
-
when 405
|
111
|
-
Jirafe::Error::NotAllowed
|
112
|
-
when 500
|
113
|
-
Jirafe::Error::ServerError
|
114
|
-
else
|
115
|
-
Jirafe::Error::UnknownError
|
116
|
-
end
|
117
|
-
raise exception.new(response)
|
118
|
-
end
|
119
100
|
end
|
120
101
|
|
121
102
|
def initialize(attributes = {})
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Jirafe
|
2
|
+
module ResponseParser
|
3
|
+
def self.included(base)
|
4
|
+
base.extend(ClassMethods)
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def check_response_for_exception(response)
|
9
|
+
return if (200..399).include?(response.code) # Allow any 2xx or 3xx
|
10
|
+
exception = case response.code.to_i
|
11
|
+
when 400 # NOTE: Being thrown for what should be 422's
|
12
|
+
Jirafe::Error::BadRequest
|
13
|
+
when 401
|
14
|
+
Jirafe::Error::Unauthorized
|
15
|
+
when 403
|
16
|
+
Jirafe::Error::Forbidden
|
17
|
+
when 404
|
18
|
+
Jirafe::Error::ResourceNotFound
|
19
|
+
when 405
|
20
|
+
Jirafe::Error::NotAllowed
|
21
|
+
when 500
|
22
|
+
Jirafe::Error::ServerError
|
23
|
+
else
|
24
|
+
Jirafe::Error::UnknownError
|
25
|
+
end
|
26
|
+
raise exception.new(response)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/jirafe/version.rb
CHANGED
@@ -7,9 +7,8 @@ describe Jirafe::Callback::Event do
|
|
7
7
|
|
8
8
|
let(:cassette) { "#{resource_prefix}_post_event" }
|
9
9
|
|
10
|
-
before do
|
10
|
+
before :all do
|
11
11
|
use_master_token
|
12
|
-
@query_capture = ENV['CALLTHROUGH'] ? [] : ["confirmToken=#{'a' * 16}"]
|
13
12
|
@server = CallbackServer.run(@query_capture, 3333)
|
14
13
|
end
|
15
14
|
|
@@ -17,29 +16,60 @@ describe Jirafe::Callback::Event do
|
|
17
16
|
@server.shutdown
|
18
17
|
end
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
19
|
+
before do
|
20
|
+
static_hash = "af5f436b948804627dc5641e309f54dc87a0f1c7"
|
21
|
+
@query_capture = ENV['CALLTHROUGH'] ? [] : ["confirmToken=#{'a' * 16}&hash=#{static_hash}"]
|
22
|
+
make_request("#{cassette}_fetch_token") do
|
23
|
+
use_master_token
|
24
|
+
app = Jirafe::Resource::Application.new(:name => "test app cmb")
|
25
|
+
created_app = app.create
|
26
|
+
@app_token = created_app.token
|
27
|
+
@site = Jirafe::Resource::Site.new(:app_id => app.identifier,
|
28
|
+
:description => "test site cmb",
|
29
|
+
:url => "http://testsitecmb.example.com",
|
30
|
+
:store_api_url =>"http://127.0.0.1:3333") # SF2 validator doesn't like 'localhost'
|
31
|
+
@site.parent = app
|
32
|
+
|
33
|
+
use_app_token(app)
|
34
|
+
@site.create
|
35
|
+
Jirafe::Callback::Event.notify(@site.identifier)
|
36
|
+
while @query_capture.empty?
|
37
|
+
sleep 0.1
|
39
38
|
end
|
39
|
+
@confirm_token = @query_capture.last.split("&").detect {|param| param.match(/confirmToken/) }.split("=").last
|
40
|
+
@hash = @query_capture.last.split("&").detect {|param| param.match(/hash/) }.split("=").last
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe ".trust_callback?" do
|
45
|
+
subject { Jirafe::Callback::Event.trust_callback?(app_token, confirm_token, hash) }
|
46
|
+
let(:app_token) { @app_token }
|
47
|
+
let(:confirm_token) { @confirm_token }
|
48
|
+
let(:hash) { @hash }
|
49
|
+
|
50
|
+
context "given valid values" do
|
51
|
+
|
52
|
+
it { should be_true }
|
40
53
|
end
|
54
|
+
|
55
|
+
context "given something that doesn't match" do
|
56
|
+
let(:app_token) { tokens[:invalid_token] }
|
57
|
+
|
58
|
+
it { should be_false }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe ".send" do
|
41
63
|
let(:version) { 1 }
|
42
64
|
|
65
|
+
let(:item) do
|
66
|
+
Jirafe::Callback::Events::Item.new(:sku => "1234",
|
67
|
+
:name => "Widget",
|
68
|
+
:price => 40,
|
69
|
+
:quantity => 2,
|
70
|
+
:category => "Things")
|
71
|
+
end
|
72
|
+
|
43
73
|
let(:newly_created_order) do
|
44
74
|
Jirafe::Callback::Events::Order.new(:version => version,
|
45
75
|
:action => :create,
|
@@ -48,7 +78,8 @@ describe Jirafe::Callback::Event do
|
|
48
78
|
:sub_total => 80.00,
|
49
79
|
:tax_amount => 20.00,
|
50
80
|
:discount_amount => 0.00,
|
51
|
-
:status => :pending
|
81
|
+
:status => :pending,
|
82
|
+
:items => [item])
|
52
83
|
end
|
53
84
|
|
54
85
|
let(:completed_order) do
|
@@ -59,7 +90,8 @@ describe Jirafe::Callback::Event do
|
|
59
90
|
:sub_total => 80.00,
|
60
91
|
:tax_amount => 20.00,
|
61
92
|
:discount_amount => 10.00,
|
62
|
-
:status => :complete
|
93
|
+
:status => :complete,
|
94
|
+
:items => [item])
|
63
95
|
end
|
64
96
|
|
65
97
|
let(:refund) do
|
@@ -76,7 +108,7 @@ describe Jirafe::Callback::Event do
|
|
76
108
|
it "sends events for processing" do
|
77
109
|
events = [newly_created_order, completed_order]
|
78
110
|
make_request(cassette) do
|
79
|
-
Jirafe::Callback::Event.send(@site.identifier, @
|
111
|
+
Jirafe::Callback::Event.send(@site.identifier, @confirm_token, events)
|
80
112
|
end
|
81
113
|
end
|
82
114
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Jirafe::Callback::Events::DataHelper do
|
4
|
+
before do
|
5
|
+
class DataHelperTestClass
|
6
|
+
include Jirafe::Callback::Events::DataHelper
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:instance) { DataHelperTestClass.new }
|
11
|
+
|
12
|
+
describe "#format_amount" do
|
13
|
+
subject { instance.format_amount(amount) }
|
14
|
+
|
15
|
+
context "given nil" do
|
16
|
+
let(:amount) { nil }
|
17
|
+
|
18
|
+
it { should be_nil }
|
19
|
+
end
|
20
|
+
|
21
|
+
context "given a whole number" do
|
22
|
+
let(:amount) { 23 }
|
23
|
+
|
24
|
+
it { should == "23.0000" }
|
25
|
+
end
|
26
|
+
|
27
|
+
context "given a float" do
|
28
|
+
let(:amount) { 12.34 }
|
29
|
+
|
30
|
+
it { should == "12.3400" }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#format_discount_amount" do
|
35
|
+
subject { instance.format_discount_amount(amount) }
|
36
|
+
|
37
|
+
context "given nil" do
|
38
|
+
let(:amount) { nil }
|
39
|
+
|
40
|
+
it { should be_nil }
|
41
|
+
end
|
42
|
+
|
43
|
+
context "given a negative number" do
|
44
|
+
let(:amount) { -12.34 }
|
45
|
+
|
46
|
+
it { should == "12.3400" }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|