lipstick 1.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ODY3NmJjZmI3ODJkODBmMzVmNmMzYjZiYzUxODg2YTg0YjAyYTA2Nw==
5
+ data.tar.gz: !binary |-
6
+ MDYzZTM4ZWY1ODBkZmI4YjFiODQ2MmMyZmUzYTVjNTAyYzcwYTRjOA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ ZWY5ZmU4ODM5NGYyMjlhMWQzNDU4ZTg2MTYwZWFhZGI2M2NmZjljMTBkNzZj
10
+ YmUzNmY2ZDkwODQwY2I3YWMzNmQ5Zjc3OWM4OTE1Y2U0MDM4MmE1N2YyOGVi
11
+ ZDY5MzA3MmJlMWYyY2VhZjk2ZWZjZTA2ZGQ3NzFjNzY1MDIwMGQ=
12
+ data.tar.gz: !binary |-
13
+ NDNjMTlhYWJhOGYzYmE5NDkxOWY3MWZiYjkyNjZlNjAzMDZiZTIzMmRjOGE2
14
+ ODg3MmRmMTcxZWY2ODA5ODEyYTQ5Y2U5M2Q5NjQyNTMwMWQwYmUxNTdlNGJi
15
+ M2E4MGZiZDc5YjQzYjIzZTIxYWQ5NTY1MDk0ZGExNzZjYzdkNTU=
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "minitest", ">= 0"
10
+ gem "yard", "~> 0.7"
11
+ gem "rdoc", "~> 3.12"
12
+ gem "bundler", "~> 1.0"
13
+ gem "jeweler", "~> 2.0.1"
14
+ gem "simplecov", ">= 0"
15
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,67 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ addressable (2.3.6)
5
+ builder (3.2.2)
6
+ descendants_tracker (0.0.4)
7
+ thread_safe (~> 0.3, >= 0.3.1)
8
+ docile (1.1.5)
9
+ faraday (0.9.0)
10
+ multipart-post (>= 1.2, < 3)
11
+ git (1.2.8)
12
+ github_api (0.12.2)
13
+ addressable (~> 2.3)
14
+ descendants_tracker (~> 0.0.4)
15
+ faraday (~> 0.8, < 0.10)
16
+ hashie (>= 3.3)
17
+ multi_json (>= 1.7.5, < 2.0)
18
+ nokogiri (~> 1.6.3)
19
+ oauth2
20
+ hashie (3.3.1)
21
+ highline (1.6.21)
22
+ jeweler (2.0.1)
23
+ builder
24
+ bundler (>= 1.0)
25
+ git (>= 1.2.5)
26
+ github_api
27
+ highline (>= 1.6.15)
28
+ nokogiri (>= 1.5.10)
29
+ rake
30
+ rdoc
31
+ json (1.8.1)
32
+ jwt (1.0.0)
33
+ mini_portile (0.6.1)
34
+ minitest (5.4.2)
35
+ multi_json (1.10.1)
36
+ multi_xml (0.5.5)
37
+ multipart-post (2.0.0)
38
+ nokogiri (1.6.4.1)
39
+ mini_portile (~> 0.6.0)
40
+ oauth2 (1.0.0)
41
+ faraday (>= 0.8, < 0.10)
42
+ jwt (~> 1.0)
43
+ multi_json (~> 1.3)
44
+ multi_xml (~> 0.5)
45
+ rack (~> 1.2)
46
+ rack (1.5.2)
47
+ rake (10.3.2)
48
+ rdoc (3.12.2)
49
+ json (~> 1.4)
50
+ simplecov (0.9.1)
51
+ docile (~> 1.1.0)
52
+ multi_json (~> 1.0)
53
+ simplecov-html (~> 0.8.0)
54
+ simplecov-html (0.8.0)
55
+ thread_safe (0.3.4)
56
+ yard (0.8.7.6)
57
+
58
+ PLATFORMS
59
+ ruby
60
+
61
+ DEPENDENCIES
62
+ bundler (~> 1.0)
63
+ jeweler (~> 2.0.1)
64
+ minitest
65
+ rdoc (~> 3.12)
66
+ simplecov
67
+ yard (~> 0.7)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2014 Piers Chambers and South Beach Skin Care, LLC
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,24 @@
1
+ = Lipstick
2
+
3
+ Unofficial ruby wrapper for the following Lime Light CRM APIs:
4
+
5
+ * {Membership API}[http://help.limelightcrm.com/entries/317874-Membership-API-Documentation]
6
+ * {Transaction API}[http://help.limelightcrm.com/entries/22934241-Transaction-API-Documentation]
7
+
8
+ Note this wrapper attempts to fix some of the inconsistencies in the underlying APIs.
9
+
10
+ To run the tests you will need your own Lime Light CRM account with a valid campaign and test payment method.
11
+
12
+ == Contributing to lipstick
13
+
14
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
15
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
16
+ * Fork the project.
17
+ * Start a feature/bugfix branch.
18
+ * Commit and push until you are happy with your contribution.
19
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
20
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
21
+
22
+ Copyright (c) 2014 Piers Chambers and South Beach Skin Care, LLC. See LICENSE.txt for
23
+ further details.
24
+
data/Rakefile ADDED
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://guides.rubygems.org/specification-reference/ for more options
17
+ gem.name = "lipstick"
18
+ gem.homepage = "http://github.com/varyonic/lipstick"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Unofficial ruby wrapper for the Lime Light CRM APIs.}
21
+ gem.description = %Q{Unofficial ruby wrapper for the Lime Light CRM membership and transaction APIs}
22
+ gem.email = "piers@varyonic.com"
23
+ gem.authors = ["Piers Chambers"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ desc "Code coverage detail"
36
+ task :simplecov do
37
+ ENV['COVERAGE'] = "true"
38
+ Rake::Task['test'].execute
39
+ end
40
+
41
+ task :default => :test
42
+
43
+ require 'yard'
44
+ YARD::Rake::YardocTask.new
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0.pre
data/lib/lipstick.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'logger'
2
+ require 'lipstick/api/session.rb'
3
+ require 'lipstick/api/response.rb'
4
+ require 'lipstick/api/campaign_view_response.rb'
5
+ require 'lipstick/api/campaign_find_active_response.rb'
6
+ require 'lipstick/api/customer_find_active_product_response.rb'
7
+ require 'lipstick/api/new_order_response.rb'
8
+ require 'lipstick/api/order_find_response.rb'
9
+ require 'lipstick/api/order_find_updated_response.rb'
10
+ require 'lipstick/api/order_view_response.rb'
@@ -0,0 +1,12 @@
1
+ module Lipstick
2
+ module Api
3
+ class CampaignFindActiveResponse < Response
4
+ int_csv_field :campaign_id
5
+ csv_field :campaign_name
6
+ def initialize(fields)
7
+ fields[:response_code] = fields.delete(:response)
8
+ super fields
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ module Lipstick
2
+ module Api
3
+ class CampaignViewResponse < Response
4
+ csv_field :product_id, :product_name, :is_upsell
5
+ csv_field :shipping_id, :shipping_name, :shipping_description
6
+ csv_field :shipping_recurring_price, :shipping_initial_price
7
+ csv_field :countries, :payment_name
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,7 @@
1
+ module Lipstick
2
+ module Api
3
+ class CustomerFindActiveProductResponse < Response
4
+ int_csv_field :product_ids
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ module Lipstick
2
+ module Api
3
+ class NewOrderResponse < Response
4
+ def initialize(fields)
5
+ fields.keys.each do |key|
6
+ fields[underscore(key.to_s).to_sym] = fields.delete(key)
7
+ end
8
+ if fields[:response_code] == '100'
9
+ fields[:test] = (fields[:test] == '1')
10
+ fields[:customer_id] = fields.delete(:customer_id).to_i
11
+ fields[:order_id] = fields.delete(:order_id).to_i
12
+ end
13
+ super(fields)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,7 @@
1
+ module Lipstick
2
+ module Api
3
+ class OrderFindResponse < Response
4
+ int_csv_field :order_ids
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Lipstick
2
+ module Api
3
+ class OrderFindUpdatedResponse < Response
4
+ int_csv_field :order_ids
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,65 @@
1
+ require 'pp'
2
+ require 'bigdecimal'
3
+ require 'ostruct'
4
+
5
+ module Lipstick
6
+ module Api
7
+ class OrderViewResponse < Response
8
+ def initialize(fields)
9
+ fields.keys.each do |key|
10
+ fields[underscore(key.to_s).to_sym] = fields.delete(key)
11
+ end
12
+ fields[:customer] = OpenStruct.new(
13
+ id: fields.delete(:customer_id).to_i,
14
+ first_name: fields.delete(:first_name),
15
+ last_name: fields.delete(:last_name),
16
+ telephone: fields.delete(:customers_telephone),
17
+ email_address: fields.delete(:email_address)
18
+ )
19
+ fields[:shipping] = OpenStruct.new(
20
+ first_name: fields.delete(:shipping_first_name),
21
+ last_name: fields.delete(:shipping_last_name),
22
+ street_address: fields.delete(:shipping_street_address),
23
+ street_address2: fields.delete(:shipping_street_address2),
24
+ city: fields.delete(:shipping_city),
25
+ state: fields.delete(:shipping_state),
26
+ state_id: fields.delete(:shipping_state_id),
27
+ postcode: fields.delete(:shipping_postcode),
28
+ country: fields.delete(:shipping_country),
29
+ )
30
+ fields[:billing] = OpenStruct.new(
31
+ first_name: fields.delete(:billing_first_name),
32
+ last_name: fields.delete(:billing_last_name),
33
+ street_address: fields.delete(:billing_street_address),
34
+ street_address2: fields.delete(:billing_street_address2),
35
+ city: fields.delete(:billing_city),
36
+ state: fields.delete(:billing_state),
37
+ state_id: fields.delete(:billing_state_id),
38
+ postcode: fields.delete(:billing_postcode),
39
+ country: fields.delete(:billing_country),
40
+ )
41
+ fields[:order] = OpenStruct.new(
42
+ customer: fields[:customer],
43
+ ancestor_id: fields.delete(:ancestor_id).to_i,
44
+ child_id: fields.delete(:child_id).to_i,
45
+ status: fields.delete(:order_status).to_i,
46
+ is_recurring: fields.delete(:is_recurring)=='1',
47
+ shipping: fields[:shipping],
48
+ shipping_method_name: fields.delete(:shipping_method_name),
49
+ billing: fields[:billing],
50
+ created_at: DateTime.strptime(fields.delete(:time_stamp),'%Y-%m-%d %H:%M:%S'),
51
+ cc_number: fields.delete(:cc_number),
52
+ cc_expires: fields.delete(:cc_expires),
53
+ campaign_id: fields.delete(:campaign_id).to_i,
54
+
55
+ order_total: BigDecimal.new(fields.delete(:order_total)),
56
+ parent_id: fields.delete(:parent_id).to_i,
57
+ transaction_id: fields.delete(:transaction_id),
58
+ auth_id: fields.delete(:auth_id),
59
+ )
60
+ # PP.pp fields # TODO: parse remaining fields
61
+ super
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,155 @@
1
+ module Lipstick
2
+ module Api
3
+ class Response
4
+ CODES = {
5
+ 100 => 'Success',
6
+ 200 => 'Invalid login credentials',
7
+ 320 => 'Invalid Product Id',
8
+ 321 => 'Existing Product Category Id Not Found',
9
+ 322 => 'Invalid Category Id',
10
+ 323 => 'Digital Delivery and Digital URL must be paired together and digital URL must be a valid URL',
11
+ 324 => 'Invalid rebill_product or rebill_days value',
12
+ 325 => 'Length Does Not Meet Minimum',
13
+ 326 => 'URL is invalid',
14
+ 327 => 'Payment Type Invalid',
15
+ 328 => 'Expiration Date Invalid (Must be in the format of MMYY with no special characters)',
16
+ 329 => 'Credit card must be either 15 or 16 digits numeric only',
17
+ 330 => 'No Status Passed',
18
+ 331 => 'Invalid Criteria',
19
+ 332 => 'Start and end date are required',
20
+ 333 => 'No Orders Found',
21
+ 334 => 'Invalid Start Date format',
22
+ 335 => 'Invalid End Date format',
23
+ 336 => 'Wild Card Unsupported for this search criteria',
24
+ 337 => 'Last 4 or First 4 must be 4 characters exactly',
25
+ 338 => 'Timestamp invalid',
26
+ 339 => 'Total Amount must be numeric and non-negative',
27
+ 340 => 'Invalid country code',
28
+ 341 => 'Invalid state code',
29
+ 342 => 'Invalid Email Address',
30
+ 343 => 'Data Element Has Same Value As Value Passed No Update done (Information ONLY, but still a success)',
31
+ 344 => 'Invalid Number Format',
32
+ 345 => 'Must be a 1 or 0. "1" being "On" or true. "0" being "Off" or false.',
33
+ 346 => 'Invalid date format. Use mm/dd/yyyy',
34
+ 347 => 'Invalid RMA reason',
35
+ 348 => 'Order is already flagged as RMA',
36
+ 349 => 'Order is not flagged as RMA',
37
+ 350 => 'Invalid order Id supplied',
38
+ 351 => 'Invalid status or action supplied',
39
+ 352 => 'Uneven Order/Status/Action Pairing',
40
+ 353 => 'Cannot stop recurring',
41
+ 354 => 'Cannot reset recurring',
42
+ 355 => 'Cannot start recurring',
43
+ 356 => 'Credit card has expired',
44
+ 360 => 'Cannot stop upsell recurring',
45
+ 370 => 'Invalid amount supplied',
46
+ 371 => 'Invalid keep recurring flag supplied',
47
+ 372 => 'Refund amount exceeds current order total',
48
+ 373 => 'Cannot void a fully refunded order',
49
+ 374 => 'Cannot reprocess non-declined orders',
50
+ 375 => 'Cannot blacklist test payment method',
51
+ 376 => 'Invalid tracking number',
52
+ 377 => 'Cannot ship pending orders',
53
+ 378 => 'Order already shipped',
54
+ 379 => 'Order is fully refunded/voided',
55
+ 380 => 'Order is not valid for force bill',
56
+ 381 => 'Customer is blacklisted',
57
+ 382 => 'Invalid US state',
58
+ 383 => 'All military states must have a city of either "APO", "FPO". or "DPO"',
59
+ 384 => 'Invalid date mode',
60
+ 385 => 'Invalid billing cycle filter',
61
+ 386 => 'Order has already been returned',
62
+ 387 => 'Invalid return reason',
63
+ 388 => 'Rebill discount exceeds maximum for product',
64
+ 389 => 'Refund amount must be greater than 0',
65
+ 390 => 'Invalid number of days supplied',
66
+ 400 => 'Invalid campaign Id supplied',
67
+ 401 => 'Invalid subscription type',
68
+ 402 => 'Subscription type 3 requires subscription week and subscription day values',
69
+ 403 => 'Invalid subscription week value',
70
+ 404 => 'Invalid subscription day value',
71
+ 405 => 'Subscription type 3 required for subscription week and subscription day values',
72
+ 406 => 'Rebill days must be a value between 1 and 31 for subscription type 2',
73
+ 407 => 'Rebill days must be greater than 0 if subscription type is 1 or 2',
74
+ 408 => 'Rebill days is invalid unless type is 1 or 2',
75
+ 409 => 'Subscription type 0, other subscription fields invalid',
76
+ 410 => 'API user: (api_username) has reached the limit of requests per minute: (limit) for method: (method_name)',
77
+ 411 => 'Invalid subscription field',
78
+ 412 => 'Missing subscription field',
79
+ 413 => 'Product is not subscription based',
80
+ 415 => 'Invalid subscription value',
81
+ 420 => 'Campaign does not have fulfillment provider attached',
82
+ 421 => 'This order was placed on hold',
83
+ 422 => 'This order has not been sent to fulfillment yet',
84
+ 423 => 'Invalid SKU',
85
+ 424 => 'Fulfillment Error, provider did not specify',
86
+ 425 => 'This order has been sent to fulfillment but has not been shipped',
87
+ 500 => 'Invalid customer Id supplied',
88
+ 600 => 'Invalid product Id supplied',
89
+ 601 => 'Invalid prospect Id supplied',
90
+ 602 => 'No prospects found',
91
+ 603 => 'Invalid customer Id supplied',
92
+ 604 => 'No customers found',
93
+ 700 => 'Invalid method supplied',
94
+ 701 => 'Action not permitted by gateway',
95
+ 702 => 'Invalid gateway Id',
96
+ 800 => 'Transaction was declined',
97
+ 901 => 'Invalid return URL',
98
+ 902 => 'Invalid cancel URL',
99
+ 903 => 'Error retrieving alternative provider data',
100
+ 904 => 'Campaign does not support an alternative payment provider',
101
+ 905 => 'Product quantity/dynamic price does not match',
102
+ 906 => 'Invalid quantity',
103
+ 907 => 'Invalid shipping Id',
104
+ 908 => 'Payment was already approved',
105
+ 1000 => 'SSL is required'
106
+ }
107
+ attr_reader :code, :message
108
+
109
+ class << self
110
+ def csv_field(*args)
111
+ @csv_fields ||= []
112
+ @csv_fields = @csv_fields + args
113
+ end
114
+ def int_csv_field(*args)
115
+ @int_csv_fields ||= []
116
+ @int_csv_fields = @int_csv_fields + args
117
+ end
118
+ end
119
+
120
+ def initialize(resp)
121
+ @code = resp.delete(:response_code).to_i
122
+ @message = CODES[@code]
123
+
124
+ if @code == 100
125
+ self.class.csv_field.each do |key|
126
+ resp[key] = CSV.parse_line(resp[key])
127
+ end
128
+ self.class.int_csv_field.each do |key|
129
+ resp[key] = CSV.parse_line(resp[key]).map(&:to_i)
130
+ end
131
+ end
132
+
133
+ if !resp.empty?
134
+ resp.each do |att, val|
135
+ self.class.__send__(:attr_accessor, att)
136
+ self.__send__("#{att}=", val)
137
+ end
138
+ end
139
+ end
140
+
141
+ # partly copied from activesupport/inflector
142
+ def underscore(camel_cased_word)
143
+ word = camel_cased_word.to_s.dup
144
+ word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
145
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
146
+ word.tr!("-", "_")
147
+ word.tr!("[", "_")
148
+ word.tr!("]", "")
149
+ word.downcase!
150
+ word
151
+ end
152
+
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,193 @@
1
+ require 'csv'
2
+
3
+ module Lipstick
4
+ module Api
5
+ class Session
6
+ # API endpoint, eg. {https://example.com/admin}[https://example.com/admin]
7
+ attr_reader :base_url
8
+
9
+ # Hash containing :username, :password
10
+ attr_reader :credentials
11
+
12
+ # Used for logging request and response info.
13
+ attr_reader :logger
14
+
15
+ # Public: Initialize session.
16
+ #
17
+ # params - Hash
18
+ # * +:url+ - API endpoint, eg. {https://example.com/admin}[https://example.com/admin]
19
+ # * +:username+
20
+ # * +:password+
21
+ # * +:logger+ - Used for logging request and response info.
22
+ def initialize(params)
23
+ @base_url = params[:url] || raise("url not defined.")
24
+ raise("username missing") unless params[:username]
25
+ raise("password missing") unless params[:password]
26
+ @credentials = { username: params[:username], password: params[:password] }
27
+ @logger = params[:logger] || Logger.new('/dev/null')
28
+ end
29
+
30
+ # Find all active campaigns.
31
+ def campaign_find_active
32
+ call_api(:campaign_find_active)
33
+ end
34
+
35
+ # Fetch details for a given campaign.
36
+ def campaign_view(campaign_id)
37
+ call_api(:campaign_view, campaign_id: campaign_id)
38
+ end
39
+
40
+ def customer_find_active_product(customer_id, campaign_id = nil)
41
+ params = { customer_id: customer_id }
42
+ params.merge!(campaign_id: campaign_id) if campaign_id
43
+ call_api(:customer_find_active_product, params)
44
+ end
45
+
46
+ # Create order for new customer
47
+ def new_order(params)
48
+ camelcase_params!(params)
49
+ call_api('NewOrder', params)
50
+ end
51
+
52
+ def order_find(start_time, end_time, params = {})
53
+ params.merge!(
54
+ start_date: start_time.strftime('%m/%d/%Y'),
55
+ start_time: start_time.strftime('%H:%M:%S'),
56
+ end_date: end_time.strftime('%m/%d/%Y'),
57
+ end_time: end_time.strftime('%H:%M:%S'))
58
+ params[:campaign_id] ||= 'all'
59
+ params[:product_id] ||= 'all'
60
+ params[:criteria] ||= 'all'
61
+ call_api(:order_find, params)
62
+ end
63
+
64
+ def order_find_updated(start_time, end_time, params = {})
65
+ params.merge!(
66
+ start_date: start_time.strftime('%m/%d/%Y'),
67
+ start_time: start_time.strftime('%H:%M:%S'),
68
+ end_date: end_time.strftime('%m/%d/%Y'),
69
+ end_time: end_time.strftime('%H:%M:%S'))
70
+ params[:campaign_id] ||= 'all'
71
+ call_api(:order_find_updated, params)
72
+ end
73
+
74
+ def order_refund(order_id, amount, keep_recurring = true)
75
+ call_api(:order_refund,
76
+ order_id: order_id,
77
+ amount: amount.to_s,
78
+ keep_recurring: keep_recurring ? '1' : '0')
79
+ end
80
+
81
+ def order_update(order_id, action, value)
82
+ call_api(:order_update, order_ids: order_id, actions: action, values: value)
83
+ end
84
+
85
+ def order_update_recurring(order_id, status)
86
+ call_api(:order_update_recurring, order_id: order_id, status: status)
87
+ end
88
+
89
+ def order_view(order_id)
90
+ call_api(:order_view, order_id: order_id)
91
+ end
92
+
93
+ def order_void(order_id)
94
+ call_api(:order_void, order_id: order_id)
95
+ end
96
+
97
+ def shipping_method_find(campaign_id = 'all')
98
+ call_api(:shipping_method_find, campaign_id: campaign_id) do |fields|
99
+ if fields[:response_code] == '100'
100
+ [:shipping_ids].each do |key|
101
+ fields[key] = CSV.parse_line(fields[key]).map(&:to_i)
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ def validate_credentials
108
+ call_api(:validate_credentials)
109
+ end
110
+
111
+ # partly copied from activesupport/inflector
112
+ def underscore(camel_cased_word)
113
+ word = camel_cased_word.to_s.dup
114
+ word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
115
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
116
+ word.tr!("-", "_")
117
+ word.tr!("[", "_")
118
+ word.tr!("]", "")
119
+ word.downcase!
120
+ word
121
+ end
122
+
123
+ def camelize(str)
124
+ return str.to_s unless str.to_s.include?(?_)
125
+ str.to_s.split("_").each {|s| s.capitalize! }.join
126
+ end
127
+
128
+ protected
129
+ # Munge params into style accepted by transaction API.
130
+ def camelcase_params!(params)
131
+ params.keys.select {|key| key.is_a?(Symbol) && key.to_s.include?(?_) }.each do |key|
132
+ camelcase_key = camelize(key)
133
+ camelcase_key[0] = camelcase_key[0].chr.downcase
134
+ params[camelcase_key] = params.delete(key)
135
+ end
136
+ end
137
+
138
+ def call_api(method, params = {}, &block)
139
+ params = params.merge(method: method)
140
+ logger.info "request = #{params.inspect}"
141
+ response = post_form(uri_for(method), params.merge(credentials))
142
+ logger.info "response = #{response.inspect}"
143
+ logger.debug "response.body = #{response.body}"
144
+ if block_given?
145
+ api_response = parse_response(response, &block)
146
+ else
147
+ fields = response_fields(response)
148
+ klassname = "#{camelize(method)}Response".to_sym
149
+ klass = Lipstick::Api.constants.include?(klassname) ? Lipstick::Api.const_get(klassname) : Lipstick::Api::Response
150
+ api_response = klass.new(fields)
151
+ end
152
+ logger.info "API response = #{api_response.inspect}"
153
+ api_response
154
+ end
155
+
156
+ def uri_for(method)
157
+ api = ['NewOrder'].include?(method) ? 'transact' : 'membership'
158
+ URI.parse("#{base_url}/#{api}.php")
159
+ end
160
+
161
+ def post_form(uri, params)
162
+ post = Net::HTTP::Post.new(uri.request_uri)
163
+ post.set_form_data(params)
164
+ request(uri, post)
165
+ end
166
+
167
+ def request(uri, request)
168
+ http = Net::HTTP.new(uri.host, uri.port)
169
+ http.use_ssl = true
170
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
171
+ http.request(request)
172
+ end
173
+
174
+ def response_fields(response)
175
+ if response.body.include?(?=)
176
+ CGI::unescape(response.body).split('&').inject({}) do |h,kv|
177
+ k,v = kv.split('=')
178
+ k = k.to_sym if k.match(/\w/)
179
+ h.merge( k => v )
180
+ end
181
+ else
182
+ { response_code: response.body }
183
+ end
184
+ end
185
+
186
+ def parse_response(response, &block)
187
+ fields = response_fields(response)
188
+ yield fields if block_given?
189
+ Lipstick::Api::Response.new(fields)
190
+ end
191
+ end
192
+ end
193
+ end
data/lipstick.gemspec ADDED
@@ -0,0 +1,76 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: lipstick 1.0.0.pre ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "lipstick"
9
+ s.version = "1.0.0.pre"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
13
+ s.authors = ["Piers Chambers"]
14
+ s.date = "2014-11-28"
15
+ s.description = "Unofficial ruby wrapper for the Lime Light CRM membership and transaction APIs"
16
+ s.email = "piers@varyonic.com"
17
+ s.extra_rdoc_files = [
18
+ "LICENSE.txt",
19
+ "README.rdoc"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ "Gemfile",
24
+ "Gemfile.lock",
25
+ "LICENSE.txt",
26
+ "README.rdoc",
27
+ "Rakefile",
28
+ "VERSION",
29
+ "lib/lipstick.rb",
30
+ "lib/lipstick/api/campaign_find_active_response.rb",
31
+ "lib/lipstick/api/campaign_view_response.rb",
32
+ "lib/lipstick/api/customer_find_active_product_response.rb",
33
+ "lib/lipstick/api/new_order_response.rb",
34
+ "lib/lipstick/api/order_find_response.rb",
35
+ "lib/lipstick/api/order_find_updated_response.rb",
36
+ "lib/lipstick/api/order_view_response.rb",
37
+ "lib/lipstick/api/response.rb",
38
+ "lib/lipstick/api/session.rb",
39
+ "lipstick.gemspec",
40
+ "test/helper.rb",
41
+ "test/test_lipstick.rb",
42
+ "test/test_order_view_response.rb"
43
+ ]
44
+ s.homepage = "http://github.com/varyonic/lipstick"
45
+ s.licenses = ["MIT"]
46
+ s.rubygems_version = "2.2.2"
47
+ s.summary = "Unofficial ruby wrapper for the Lime Light CRM APIs."
48
+
49
+ if s.respond_to? :specification_version then
50
+ s.specification_version = 4
51
+
52
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
53
+ s.add_development_dependency(%q<minitest>, [">= 0"])
54
+ s.add_development_dependency(%q<yard>, ["~> 0.7"])
55
+ s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
56
+ s.add_development_dependency(%q<bundler>, ["~> 1.0"])
57
+ s.add_development_dependency(%q<jeweler>, ["~> 2.0.1"])
58
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
59
+ else
60
+ s.add_dependency(%q<minitest>, [">= 0"])
61
+ s.add_dependency(%q<yard>, ["~> 0.7"])
62
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
63
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
64
+ s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
65
+ s.add_dependency(%q<simplecov>, [">= 0"])
66
+ end
67
+ else
68
+ s.add_dependency(%q<minitest>, [">= 0"])
69
+ s.add_dependency(%q<yard>, ["~> 0.7"])
70
+ s.add_dependency(%q<rdoc>, ["~> 3.12"])
71
+ s.add_dependency(%q<bundler>, ["~> 1.0"])
72
+ s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
73
+ s.add_dependency(%q<simplecov>, [">= 0"])
74
+ end
75
+ end
76
+
data/test/helper.rb ADDED
@@ -0,0 +1,81 @@
1
+ require 'simplecov'
2
+
3
+ module SimpleCov::Configuration
4
+ def clean_filters
5
+ @filters = []
6
+ end
7
+ end
8
+
9
+ SimpleCov.configure do
10
+ clean_filters
11
+ load_adapter 'test_frameworks'
12
+ end
13
+
14
+ ENV["COVERAGE"] && SimpleCov.start do
15
+ add_filter "/.rvm/"
16
+ end
17
+ require 'rubygems'
18
+ require 'bundler'
19
+ begin
20
+ Bundler.setup(:default, :development)
21
+ rescue Bundler::BundlerError => e
22
+ $stderr.puts e.message
23
+ $stderr.puts "Run `bundle install` to install missing gems"
24
+ exit e.status_code
25
+ end
26
+ require 'minitest/autorun'
27
+ require 'minitest/unit'
28
+
29
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
30
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
31
+ require 'lipstick'
32
+
33
+ require 'yaml'
34
+
35
+ module Lipstick
36
+ module Fixtures
37
+ HOME_DIR = RUBY_PLATFORM =~ /mswin32/ ? ENV['HOMEPATH'] : ENV['HOME'] unless defined?(HOME_DIR)
38
+ LOCAL_CREDENTIALS = File.join(HOME_DIR.to_s, '.lipstick/fixtures.yml') unless defined?(LOCAL_CREDENTIALS)
39
+
40
+ def address(prefix, options = {})
41
+ {
42
+ "#{prefix}Address1" => '1234 My Street',
43
+ "#{prefix}Address2" => 'Apt 1',
44
+ "#{prefix}City" => 'Ottawa',
45
+ "#{prefix}State" => 'ON',
46
+ "#{prefix}Zip" => 'K1C2N6',
47
+ "#{prefix}Country" => 'CA',
48
+ }.update(options)
49
+ end
50
+
51
+ def all_fixtures
52
+ @@fixtures ||= load_fixtures
53
+ end
54
+
55
+ def fixtures(key)
56
+ data = all_fixtures[key] || raise(StandardError, "No fixture data was found for '#{key}'")
57
+ data.dup
58
+ end
59
+
60
+ def load_fixtures
61
+ [LOCAL_CREDENTIALS].inject({}) do |credentials, file_name|
62
+ if File.exist?(file_name)
63
+ yaml_data = YAML.load(File.read(file_name))
64
+ credentials.merge!(symbolize_keys(yaml_data))
65
+ end
66
+ credentials
67
+ end
68
+ end
69
+
70
+ def symbolize_keys(hash)
71
+ return hash unless hash.is_a?(Hash)
72
+ hash.each_with_object({}){|(k,v), h| h[k.to_sym] = symbolize_keys(v)}
73
+ end
74
+ end
75
+ end
76
+
77
+ def context(*args, &block)
78
+ describe(*args, &block)
79
+ end
80
+
81
+ Minitest.autorun
@@ -0,0 +1,186 @@
1
+ require 'helper'
2
+
3
+ include Lipstick::Fixtures
4
+
5
+ describe 'Lipstick::Api::Session' do
6
+ before(:each) do
7
+ params = fixtures(:credentials)
8
+ params[:logger] = Logger.new(STDOUT) if ENV['DEBUG_LIPSTICK'] == 'true'
9
+ @session = Lipstick::Api::Session.new(params)
10
+ end
11
+
12
+ describe '#campaign_find_active' do
13
+ it "finds all active campaigns" do
14
+ api_response = @session.campaign_find_active
15
+ assert api_response.code == 100, "unexpected response: #{api_response.inspect}"
16
+ assert api_response.campaign_id.is_a?(Array)
17
+ assert api_response.campaign_id[0].is_a?(Integer)
18
+ assert api_response.campaign_name.is_a?(Array)
19
+ end
20
+ end
21
+
22
+ describe '#campaign_view' do
23
+ it "fetches attributes of a campaign" do
24
+ api_response = @session.campaign_find_active
25
+ campaign_id = api_response.campaign_id.sample
26
+ api_response = @session.campaign_view(campaign_id)
27
+ assert api_response.code == 100
28
+ assert api_response.product_id.is_a?(Array)
29
+ assert api_response.shipping_id.is_a?(Array)
30
+ end
31
+ end
32
+
33
+ context "sample campaign" do
34
+ let (:order_params) {
35
+ {
36
+ campaign_id: @campaign_id,
37
+ product_id: @product_id,
38
+ first_name: 'Jim',
39
+ last_name: 'Smith',
40
+ phone: '(555)555-5555',
41
+ email: 'test@test.com', # jim.smith@example.com'
42
+ credit_card_type: @credit_card_type,
43
+ credit_card_number: fixtures(:test_card_number),
44
+ expiration_date: '1219',
45
+ "CVV" => '123',
46
+ tran_type: 'NewOrder',
47
+ shipping_id: @shipping_method_id,
48
+ ip_address: '127.0.0.1',
49
+ upsell_count: 0,
50
+ }.update(address('shipping')).update(address('billing'))
51
+ }
52
+ before (:all) do
53
+ api_response = @session.campaign_find_active
54
+ @campaign_id = api_response.campaign_id.sample
55
+ @campaign = @session.campaign_view(@campaign_id)
56
+ @product_id = @campaign.product_id.sample
57
+ @credit_card_type = @campaign.payment_name.sample
58
+ @shipping_method_id = @campaign.shipping_id.sample
59
+ end
60
+
61
+ describe '#new_order' do
62
+ it "creates order" do
63
+ api_response = @session.new_order(order_params)
64
+ assert api_response.code == 100
65
+ assert api_response.test, "Expected #{api_response.test.inspect} to be true"
66
+ assert api_response.customer_id.is_a?(Integer), "Expected #{api_response.customer_id.inspect} to be an integer"
67
+ assert api_response.order_id.is_a?(Integer)
68
+ assert api_response.transaction_id == 'Not Available'
69
+ assert api_response.auth_id == 'Not Available'
70
+ end
71
+ end
72
+
73
+ context "existing order" do
74
+ before (:all) do
75
+ api_response = @session.new_order(order_params)
76
+ @order_id = api_response.order_id
77
+ @customer_id = api_response.customer_id
78
+ end
79
+
80
+ describe '#customer_find_active_product' do
81
+ it "fetches product ids" do
82
+ api_response = @session.customer_find_active_product(@customer_id)
83
+ assert api_response.code == 100
84
+ assert api_response.product_ids.is_a?(Array)
85
+ assert api_response.product_ids[0].is_a?(Integer)
86
+ end
87
+ end
88
+
89
+ describe '#order_find' do
90
+ it "returns orders matching criteria" do
91
+ api_response = @session.order_find(Time.now - 120, Time.now)
92
+ assert api_response.code == 100, "unexpected response: #{api_response.inspect}"
93
+ assert api_response.order_ids.is_a?(Array)
94
+ assert api_response.order_ids[0].is_a?(Integer)
95
+ end
96
+ end
97
+
98
+ describe '#order_refund' do
99
+ it "refunds the customer" do
100
+ api_response = @session.order_refund(@order_id, 0.01)
101
+ assert api_response.code == 100
102
+ end
103
+ end
104
+
105
+ describe '#order_view' do
106
+ it "returns details of an order" do
107
+ api_response = @session.order_view(@order_id)
108
+ assert api_response.code == 100, "unexpected response: #{api_response.inspect}"
109
+ end
110
+ end
111
+
112
+ describe '#order_update1' do
113
+ it 'posts chages to an order' do
114
+ api_response = @session.order_update(@order_id, :tracking_number, 'LC123456789012345678US')
115
+ assert api_response.code == 100
116
+ end
117
+ end
118
+
119
+ context "updated order" do
120
+ before (:each) do
121
+ api_response = @session.order_update(@order_id, :tracking_number, 'LC123456789012345678US')
122
+ end
123
+
124
+ describe '#order_find_updated' do
125
+ it "finds updated orders" do
126
+ api_response = @session.order_find_updated(Time.now - 128, Time.now)
127
+ assert api_response.code == 100, "unexpected response: #{api_response.inspect}"
128
+ assert api_response.order_ids.is_a?(Array)
129
+ assert api_response.order_ids[0].is_a?(Integer)
130
+ end
131
+ end
132
+ end
133
+ end # existing order
134
+
135
+ context "new order" do
136
+ before (:each) do
137
+ api_response = @session.new_order(order_params)
138
+ @new_order_id = api_response.order_id
139
+ end
140
+
141
+ describe '#order_update_recurring' do
142
+ it "cancels a new order" do
143
+ api_response = @session.order_update_recurring(@new_order_id,'stop')
144
+ assert api_response.code == 100, "unexpected response: #{api_response.inspect}"
145
+ end
146
+ end
147
+
148
+ describe '#order_void' do
149
+ it "cancels a new order" do
150
+ api_response = @session.order_void(@new_order_id)
151
+ assert api_response.code == 100, "unexpected response: #{api_response.inspect}"
152
+ end
153
+ end
154
+ end
155
+ end # sample campaign
156
+
157
+ describe '#shipping_method_find' do
158
+ it "finds shipping methods" do
159
+ api_response = @session.shipping_method_find
160
+ assert api_response.code == 100
161
+ assert api_response.shipping_ids.is_a?(Array)
162
+ assert api_response.shipping_ids[0].is_a?(Integer)
163
+ end
164
+ end
165
+
166
+ describe "validate_credentials" do
167
+ it "returns true if credentials valid" do
168
+ api_response = @session.validate_credentials
169
+ assert api_response.code == 100, "Credentials not valid."
170
+ end
171
+
172
+ it "returns false if credentials invalid" do
173
+ invalid_credentials = fixtures(:credentials).merge!(password: 'invalid')
174
+ @invalid_session = Lipstick::Api::Session.new(invalid_credentials)
175
+ api_response = @invalid_session.validate_credentials
176
+ assert api_response.code == 200, "Invalid credentials not detected."
177
+ end
178
+ end
179
+
180
+ describe '#underscore' do
181
+ it 'munges whatsit' do
182
+ foobar = @session.underscore('FooBar')
183
+ assert foobar == 'foo_bar', ">> #{foobar} <<"
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,127 @@
1
+ require 'helper'
2
+
3
+ describe 'Lipstick::Api::OrderViewResponse' do
4
+ describe 'initialize' do
5
+ it 'parses the fields' do
6
+ fields = {
7
+ :response_code=>"100",
8
+ :ancestor_id=>"581006",
9
+ :customer_id=>"30346",
10
+ :parent_id=>"2081410",
11
+ :child_id=>nil,
12
+ :order_status=>"11",
13
+ :is_recurring=>"0",
14
+ :first_name=>"Jim",
15
+ :last_name=>"Smith",
16
+ :shipping_first_name=>"Jim",
17
+ :shipping_last_name=>"Smith",
18
+ :shipping_street_address=>"1234 My Street",
19
+ :shipping_street_address2=>"Apt 1",
20
+ :shipping_city=>"Ottawa",
21
+ :shipping_state=>"ON",
22
+ :shipping_state_id=>"ON",
23
+ :shipping_postcode=>"K1C2N6",
24
+ :shipping_country=>"CA",
25
+ :billing_first_name=>"Jim",
26
+ :billing_last_name=>"Smith",
27
+ :billing_street_address=>"1234 My Street",
28
+ :billing_street_address2=>"Apt 1",
29
+ :billing_city=>"Ottawa",
30
+ :billing_state=>"ON",
31
+ :billing_state_id=>"ON",
32
+ :billing_postcode=>"K1C2N6",
33
+ :billing_country=>"CA",
34
+ :customers_telephone=>"(555)555-5555",
35
+ :time_stamp=>"2014-11-26 16:34:33",
36
+ :recurring_date=>"0000-00-00",
37
+ :retry_date=>"N/A",
38
+ :cc_type=>"offline",
39
+ :cc_number=>"2822", # "N/A",
40
+ :check_account_last_4=>"N/A",
41
+ :check_routing_last_4=>"N/A",
42
+ :check_ssn_last_4=>"N/A",
43
+ :cc_expires=>"1219",
44
+ :prepaid_match=>"N/A",
45
+ :main_product_id=>"17",
46
+ :main_product_quantity=>"1",
47
+ :upsell_product_quantity=>nil,
48
+ :upsell_product_id=>nil,
49
+ :shipping_id=>"1",
50
+ :shipping_method_name=>"USPS",
51
+ :order_total=>"4.25",
52
+ :transaction_id=>"5804215901", # "Not Available",
53
+ :auth_id=>"02553Z", # "Not Available",
54
+ :tracking_number=>nil,
55
+ :on_hold=>"0",
56
+ :on_hold_by=>nil,
57
+ :hold_date=>nil,
58
+ :shipping_date=>"Not Shipped",
59
+ :email_address=>"test@test.com",
60
+ :gateway_id=>"1",
61
+ :preserve_gateway=>"0",
62
+ :amount_refunded_to_date=>"0.00",
63
+ :order_confirmed=>"NO_STATUS",
64
+ :order_confirmed_date=>nil,
65
+ :is_chargeback=>"0",
66
+ :is_fraud=>"0",
67
+ :is_rma=>"0",
68
+ :rma_number=>nil,
69
+ :rma_reason=>nil,
70
+ :ip_address=>"127.0.0.1",
71
+ :affiliate=>nil,
72
+ :sub_affiliate=>nil,
73
+ :decline_reason=>"N/A",
74
+ :campaign_id=>"23",
75
+ :order_sales_tax=>"0.00",
76
+ :order_sales_tax_amount=>"0.00",
77
+ :processor_id=>nil,
78
+ :created_by_user_name=>nil,
79
+ :created_by_employee_name=>nil,
80
+ :billing_cycle=>"0",
81
+ :click_id=>nil,
82
+ :product_qty_17=>"1",
83
+ :"products[0][product_id]"=>"1",
84
+ :"products[0][sku]"=>"094922807700",
85
+ :"products[0][price]"=>"0.00",
86
+ :"products[0][name]"=>"Lipstick",
87
+ :"products[0][on_hold]"=>"0",
88
+ :"products[0][is_recurring]"=>"1",
89
+ :"products[0][recurring_date]"=>"2014-12-26",
90
+ :"products[0][product_qty]"=>"1",
91
+ :"products[0][subscription_id]"=>"653cfc05e89438543a943731bbe6dbce",
92
+ :"products[0][subscription_type]"=>"Bill by cycle",
93
+ :"products[0][subscription_desc]"=>"Bills every 30 days"
94
+ }
95
+ response = Lipstick::Api::OrderViewResponse.new(fields)
96
+ customer = response.customer
97
+ assert_equal customer.id, 30346
98
+ assert_equal customer.first_name, "Jim"
99
+ assert_equal customer.last_name, "Smith"
100
+ assert_equal customer.telephone, "(555)555-5555"
101
+ assert_equal customer.email_address, "test@test.com"
102
+
103
+ order = response.order
104
+ assert_equal order.ancestor_id, 581006
105
+ # assert_equal order.customer.id, 30346
106
+ assert_equal order.parent_id, 2081410
107
+ assert_equal order.status, 11
108
+
109
+ assert_equal order.shipping.first_name, "Jim"
110
+ assert_equal order.shipping.last_name, "Smith"
111
+ assert_equal order.shipping.street_address, "1234 My Street"
112
+ assert_equal order.shipping.street_address2, "Apt 1"
113
+ assert_equal order.shipping.postcode, "K1C2N6"
114
+ assert_equal order.shipping.country, "CA"
115
+ assert_equal order.billing.marshal_dump, order.shipping.marshal_dump
116
+ assert_equal order.created_at, DateTime.new(2014,11,26,16,34,33)
117
+ assert_equal order.cc_number, "2822"
118
+
119
+ assert_equal order.cc_expires, "1219"
120
+ assert_equal order.shipping_method_name, "USPS"
121
+ assert_equal order.order_total, BigDecimal.new('4.25')
122
+ assert_equal order.transaction_id, '5804215901'
123
+ assert_equal order.auth_id, '02553Z'
124
+ assert_equal order.campaign_id, 23
125
+ end
126
+ end
127
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lipstick
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0.pre
5
+ platform: ruby
6
+ authors:
7
+ - Piers Chambers
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: yard
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '0.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '0.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rdoc
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '3.12'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '3.12'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: jeweler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: 2.0.1
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 2.0.1
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Unofficial ruby wrapper for the Lime Light CRM membership and transaction
98
+ APIs
99
+ email: piers@varyonic.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files:
103
+ - LICENSE.txt
104
+ - README.rdoc
105
+ files:
106
+ - .document
107
+ - Gemfile
108
+ - Gemfile.lock
109
+ - LICENSE.txt
110
+ - README.rdoc
111
+ - Rakefile
112
+ - VERSION
113
+ - lib/lipstick.rb
114
+ - lib/lipstick/api/campaign_find_active_response.rb
115
+ - lib/lipstick/api/campaign_view_response.rb
116
+ - lib/lipstick/api/customer_find_active_product_response.rb
117
+ - lib/lipstick/api/new_order_response.rb
118
+ - lib/lipstick/api/order_find_response.rb
119
+ - lib/lipstick/api/order_find_updated_response.rb
120
+ - lib/lipstick/api/order_view_response.rb
121
+ - lib/lipstick/api/response.rb
122
+ - lib/lipstick/api/session.rb
123
+ - lipstick.gemspec
124
+ - test/helper.rb
125
+ - test/test_lipstick.rb
126
+ - test/test_order_view_response.rb
127
+ homepage: http://github.com/varyonic/lipstick
128
+ licenses:
129
+ - MIT
130
+ metadata: {}
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ! '>='
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ! '>'
143
+ - !ruby/object:Gem::Version
144
+ version: 1.3.1
145
+ requirements: []
146
+ rubyforge_project:
147
+ rubygems_version: 2.2.2
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: Unofficial ruby wrapper for the Lime Light CRM APIs.
151
+ test_files: []