twocheckout 0.1.0 → 0.1.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.
- data/.gitignore +5 -0
- data/LICENSE +21 -0
- data/README.md +176 -0
- data/lib/twocheckout/api.rb +49 -0
- data/lib/twocheckout/checkout.rb +26 -0
- data/lib/twocheckout/company.rb +33 -0
- data/lib/twocheckout/coupon.rb +41 -0
- data/lib/twocheckout/hash_object.rb +44 -0
- data/lib/twocheckout/invoice.rb +58 -0
- data/lib/twocheckout/lineitem.rb +57 -0
- data/lib/twocheckout/option.rb +57 -0
- data/lib/twocheckout/product.rb +57 -0
- data/lib/twocheckout/sale.rb +100 -0
- data/lib/twocheckout/twocheckout_error.rb +18 -0
- data/lib/twocheckout/validate_response.rb +28 -0
- data/lib/twocheckout/version.rb +3 -0
- data/lib/twocheckout.rb +13 -0
- data/test/test_twocheckout.rb +252 -0
- data/twocheckout.gemspec +21 -0
- metadata +31 -12
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2012 - Craig Christenson
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
2Checkout Ruby Library
|
2
|
+
=====================
|
3
|
+
|
4
|
+
This library provides developers with a simple set of bindings to the 2Checkout purchase routine, Instant Notification Service and Back Office API.
|
5
|
+
|
6
|
+
To use, install the `twocheckout` gem.
|
7
|
+
|
8
|
+
```shell
|
9
|
+
gem install twocheckout
|
10
|
+
```
|
11
|
+
|
12
|
+
Or import into your Gemfile.
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
gem "twocheckout", "~> 0.1.0"
|
16
|
+
```
|
17
|
+
|
18
|
+
Full documentation for each binding is provided in the **[Wiki](https://github.com/craigchristenson/2checkout-ruby/wiki)**.
|
19
|
+
|
20
|
+
|
21
|
+
Example API Usage
|
22
|
+
-----------------
|
23
|
+
|
24
|
+
*Example Usage:*
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
Twocheckout::API.credentials = { :username => 'APIuser1817037', :password => 'APIpass1817037' }
|
28
|
+
|
29
|
+
sale = Twocheckout::Sale.find(:sale_id => 4838212958)
|
30
|
+
sale.stop_recurring!
|
31
|
+
```
|
32
|
+
|
33
|
+
*Example Response:*
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
[
|
37
|
+
#<Twocheckout: : LineItem: 4838213015>{
|
38
|
+
"affiliate_vendor_id"=>nil,
|
39
|
+
"billing"=>#<Twocheckout: : HashObject: 70259731127120>{
|
40
|
+
"amount"=>"0.01",
|
41
|
+
"bill_method"=>"paypal_int",
|
42
|
+
"billing_id"=>"4838213024",
|
43
|
+
"customer_amount"=>"0.01",
|
44
|
+
"customer_id"=>"4838212964",
|
45
|
+
"date_deposited"=>nil,
|
46
|
+
"date_end"=>nil,
|
47
|
+
"date_fail"=>"2012-10-30",
|
48
|
+
"date_next"=>"2012-10-30",
|
49
|
+
"date_pending"=>"2012-10-23",
|
50
|
+
"date_start"=>"2012-10-25",
|
51
|
+
"lineitem_id"=>"4838213015",
|
52
|
+
"recurring_status"=>"active",
|
53
|
+
"status"=>"bill",
|
54
|
+
"usd_amount"=>"0.01",
|
55
|
+
"vendor_amount"=>"0.01"
|
56
|
+
},
|
57
|
+
"commission"=>nil,
|
58
|
+
"commission_affiliate_vendor_id"=>nil,
|
59
|
+
"commission_flat_rate"=>nil,
|
60
|
+
"commission_percentage"=>nil,
|
61
|
+
"commission_type"=>nil,
|
62
|
+
"commission_usd_amount"=>nil,
|
63
|
+
"customer_amount"=>"0.01",
|
64
|
+
"flat_rate"=>nil,
|
65
|
+
"installment"=>"1",
|
66
|
+
"invoice_id"=>"4838212967",
|
67
|
+
"lc_affiliate_vendor_id"=>nil,
|
68
|
+
"lc_usd_amount"=>nil,
|
69
|
+
"lineitem_id"=>"4838213015",
|
70
|
+
"linked_id"=>nil,
|
71
|
+
"options"=>[
|
72
|
+
{
|
73
|
+
"customer_surcharge"=>"0.01",
|
74
|
+
"lineitem_id"=>"4838213015",
|
75
|
+
"lineitem_option_id"=>"4838213021",
|
76
|
+
"option_name"=>"0.5",
|
77
|
+
"option_value"=>"test1",
|
78
|
+
"usd_surcharge"=>"0.01",
|
79
|
+
"vendor_surcharge"=>"0.01"
|
80
|
+
}
|
81
|
+
],
|
82
|
+
"percentage"=>nil,
|
83
|
+
"product_description"=>"This is a test product!",
|
84
|
+
"product_duration"=>"Forever",
|
85
|
+
"product_handling"=>"0.00",
|
86
|
+
"product_id"=>"4774388564",
|
87
|
+
"product_is_cart"=>"0",
|
88
|
+
"product_name"=>"Example Product",
|
89
|
+
"product_price"=>"0.01",
|
90
|
+
"product_recurrence"=>"1 Week",
|
91
|
+
"product_startup_fee"=>nil,
|
92
|
+
"product_tangible"=>"0",
|
93
|
+
"sale_id"=>"4838212958",
|
94
|
+
"status"=>"bill",
|
95
|
+
"type"=>nil,
|
96
|
+
"usd_amount"=>"0.01",
|
97
|
+
"usd_commission"=>nil,
|
98
|
+
"vendor_amount"=>"0.01",
|
99
|
+
"vendor_product_id"=>"example123"
|
100
|
+
}
|
101
|
+
]
|
102
|
+
```
|
103
|
+
|
104
|
+
Example Checkout Usage:
|
105
|
+
-----------------------
|
106
|
+
|
107
|
+
*Example Usage:*
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
require "sinatra"
|
111
|
+
|
112
|
+
get '/' do
|
113
|
+
@@form = Twocheckout::Checkout.submit({ 'sid' => '1817037', 'mode' => '2CO','li_0_name' => 'Example Product', 'li_0_price' => '1.00'})
|
114
|
+
@@form
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
118
|
+
*Example Response:*
|
119
|
+
|
120
|
+
```html
|
121
|
+
<form id="2checkout" action="https://www.2checkout.com/checkout/spurchase" method="post">
|
122
|
+
<input type="hidden" name="sid" value="1817037" />
|
123
|
+
<input type="hidden" name="mode" value="2CO" />
|
124
|
+
<input type="hidden" name="li_0_name" value="Example Product" />
|
125
|
+
<input type="hidden" name="li_0_price" value="1.00" />
|
126
|
+
</form>
|
127
|
+
<script type="text/javascript">document.getElementById('2checkout').submit();</script>
|
128
|
+
```
|
129
|
+
|
130
|
+
Example Return Usage:
|
131
|
+
---------------------
|
132
|
+
|
133
|
+
*Example Usage:*
|
134
|
+
|
135
|
+
```ruby
|
136
|
+
require "sinatra"
|
137
|
+
|
138
|
+
post '/' do
|
139
|
+
@@response = Twocheckout::ValidateResponse.purchase({:sid => 1817037, :secret => "tango", :order_number => params[:order_number], :total => params[:total], :key => params[:key]})
|
140
|
+
@@response.inspect
|
141
|
+
end
|
142
|
+
```
|
143
|
+
|
144
|
+
*Example Response:*
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
{
|
148
|
+
:code => "PASS",
|
149
|
+
:message => "Hash Matched"
|
150
|
+
}
|
151
|
+
```
|
152
|
+
|
153
|
+
Example INS Usage:
|
154
|
+
------------------
|
155
|
+
|
156
|
+
*Example Usage:*
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
require "sinatra"
|
160
|
+
|
161
|
+
post '/' do
|
162
|
+
@@response = Twocheckout::ValidateResponse.notification({:sale_id => params[:sale_id], :vendor_id => 1817037, :invoice_id => params[:invoice_id], :secret => "tango", :md5_hash => params[:md5_hash]})
|
163
|
+
@@response.inspect
|
164
|
+
end
|
165
|
+
```
|
166
|
+
|
167
|
+
*Example Response:*
|
168
|
+
|
169
|
+
```ruby
|
170
|
+
{
|
171
|
+
:code => "PASS",
|
172
|
+
:message => "Hash Matched"
|
173
|
+
}
|
174
|
+
```
|
175
|
+
|
176
|
+
Full documentation for each binding is provided in the **[Wiki](https://github.com/craigchristenson/2checkout-ruby/wiki)**.
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rest_client'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Twocheckout
|
5
|
+
class API
|
6
|
+
API_BASE = 'https://www.2checkout.com/api/'
|
7
|
+
|
8
|
+
def self.credentials=(opts)
|
9
|
+
@@username = opts[:username]
|
10
|
+
@@password = opts[:password]
|
11
|
+
opts
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.request(http_method, api_call, params = nil)
|
15
|
+
url = API_BASE + api_call
|
16
|
+
if http_method == :get
|
17
|
+
url += hash_to_querystring(params)
|
18
|
+
params = nil
|
19
|
+
end
|
20
|
+
opts = {
|
21
|
+
:method => http_method,
|
22
|
+
:url => url,
|
23
|
+
:headers => {
|
24
|
+
:accept => :json,
|
25
|
+
:content_type => :json,
|
26
|
+
:user_agent => "2Checkout/Ruby/," + Twocheckout::VERSION
|
27
|
+
},
|
28
|
+
:user => @@username,
|
29
|
+
:password => @@password,
|
30
|
+
:payload => params,
|
31
|
+
}
|
32
|
+
begin
|
33
|
+
response = RestClient::Request.execute(opts)
|
34
|
+
JSON.parse(response)
|
35
|
+
rescue => e
|
36
|
+
error_hash = JSON.parse(e.response)
|
37
|
+
raise TwocheckoutError.new(error_hash['errors'][0]['message']).retrieve
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def self.hash_to_querystring(hash)
|
44
|
+
return '' if hash.nil? || hash.empty?
|
45
|
+
'?' + hash.map { |k,v| "#{URI.encode(k.to_s)}=#{URI.encode(v.to_s)}" }.join('&')
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Twocheckout
|
2
|
+
class Checkout
|
3
|
+
|
4
|
+
def self.form(params={})
|
5
|
+
@form = "<form id=\"2checkout\" action=\"https://www.2checkout.com/checkout/spurchase\" method=\"post\">\n";
|
6
|
+
params.each do |k,v|
|
7
|
+
@form = @form + "<input type=\"hidden\" name=\"" + k + "\" value=\"" + v.to_s + "\" />\n"
|
8
|
+
end
|
9
|
+
@form + "<input type=\"submit\" value=\"Proceed to Checkout\" />\n</form>"
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.submit(params={})
|
13
|
+
@form = "<form id=\"2checkout\" action=\"https://www.2checkout.com/checkout/spurchase\" method=\"post\">\n";
|
14
|
+
params.each do |k,v|
|
15
|
+
@form = @form + "<input type=\"hidden\" name=\"" + k + "\" value=\"" + v.to_s + "\" />\n"
|
16
|
+
end
|
17
|
+
@form = @form + "</form>\n"
|
18
|
+
@form = @form + "<script type=\"text/javascript\">document.getElementById('2checkout').submit();</script>"
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.link(params={}, url="https://www.2checkout.com/checkout/spurchase?")
|
22
|
+
@querystring = params.map{|k,v| "#{CGI.escape(k)}=#{CGI.escape(v)}"}.join("&")
|
23
|
+
@purchase_url = url + @querystring
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
module Twocheckout
|
4
|
+
class Company < HashObject
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
#
|
8
|
+
# Returns company info
|
9
|
+
#
|
10
|
+
def initialize
|
11
|
+
response = Twocheckout::API.request(:get, 'acct/detail_company_info')
|
12
|
+
super(response['vendor_company_info'])
|
13
|
+
end
|
14
|
+
|
15
|
+
#
|
16
|
+
# Returns contact info
|
17
|
+
#
|
18
|
+
def contact_info
|
19
|
+
if @contact_info.nil?
|
20
|
+
response = Twocheckout::API.request(:get, 'acct/detail_contact_info')
|
21
|
+
@contact_info = HashObject.new(response['vendor_contact_info'])
|
22
|
+
end
|
23
|
+
@contact_info
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def _key
|
29
|
+
self.vendor_id
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Twocheckout
|
2
|
+
class Coupon < HashObject
|
3
|
+
|
4
|
+
def self.find(options)
|
5
|
+
response = Twocheckout::API.request(:get, 'products/detail_coupon', options)
|
6
|
+
Coupon.new(response['coupon'])
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.with_coupon_code(coupon_code)
|
10
|
+
find(:coupon_code => coupon_code)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.create(opts)
|
14
|
+
response = Twocheckout::API.request(:post, 'products/create_coupon', opts)
|
15
|
+
find(:coupon_code => response['coupon_code'])
|
16
|
+
end
|
17
|
+
|
18
|
+
def update(opts)
|
19
|
+
opts = opts.merge(:coupon_code => self.coupon_code)
|
20
|
+
Twocheckout::API.request(:post, 'products/update_coupon', opts)
|
21
|
+
response = Twocheckout::API.request(:get, 'products/detail_coupon', opts)
|
22
|
+
Coupon.new(response['coupon'])
|
23
|
+
end
|
24
|
+
|
25
|
+
def delete!
|
26
|
+
opts = {:coupon_code => self.coupon_code}
|
27
|
+
Twocheckout::API.request(:post, 'products/delete_coupon', opts)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.list(opts=nil)
|
31
|
+
Twocheckout::API.request(:get, 'products/list_coupons', opts)
|
32
|
+
end
|
33
|
+
|
34
|
+
protected
|
35
|
+
|
36
|
+
def _key
|
37
|
+
self.coupon_code
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "pp"
|
2
|
+
|
3
|
+
module Twocheckout
|
4
|
+
class HashObject
|
5
|
+
|
6
|
+
def initialize(hash)
|
7
|
+
@hash = hash
|
8
|
+
end
|
9
|
+
|
10
|
+
def method_missing(name)
|
11
|
+
name = name.to_s
|
12
|
+
if @hash.key? name
|
13
|
+
result = @hash[name]
|
14
|
+
if result.is_a?(Hash)
|
15
|
+
result = HashObject.new(result)
|
16
|
+
@hash[name] = result
|
17
|
+
end
|
18
|
+
if result.is_a?(Array)
|
19
|
+
new_array = []
|
20
|
+
result.each do |item|
|
21
|
+
new_item = item.is_a?(Hash) ? HashObject.new(item) : item
|
22
|
+
new_array << new_item
|
23
|
+
end
|
24
|
+
new_array.freeze
|
25
|
+
result = new_array
|
26
|
+
@hash[name] = result
|
27
|
+
end
|
28
|
+
return result
|
29
|
+
end
|
30
|
+
super.method_missing name
|
31
|
+
end
|
32
|
+
|
33
|
+
def inspect
|
34
|
+
"#<#{self.class.name}:#{self._key}> #{pp @hash}"
|
35
|
+
end
|
36
|
+
|
37
|
+
protected
|
38
|
+
|
39
|
+
def _key
|
40
|
+
self.object_id.to_s
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Twocheckout
|
2
|
+
class Invoice < HashObject
|
3
|
+
|
4
|
+
def self.find(options)
|
5
|
+
response = Twocheckout::API.request(:get, 'sales/detail_sale', options)
|
6
|
+
Sale.new(response['sale']).invoice[options[:invoice_id]]
|
7
|
+
end
|
8
|
+
|
9
|
+
#
|
10
|
+
# An array of all line-items in this invoice
|
11
|
+
#
|
12
|
+
def lineitems
|
13
|
+
if @lineitems.nil?
|
14
|
+
@lineitems = @hash['lineitems'].map { |li| Twocheckout::LineItem.new(li) }
|
15
|
+
@lineitems.freeze
|
16
|
+
end
|
17
|
+
@lineitems
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# A hash to index line-items by id
|
22
|
+
#
|
23
|
+
def lineitem
|
24
|
+
if @lineitem.nil?
|
25
|
+
@lineitem = {}
|
26
|
+
lineitems.each { |li| @lineitem[li.lineitem_id] = li }
|
27
|
+
@lineitem.freeze
|
28
|
+
end
|
29
|
+
return @lineitem
|
30
|
+
end
|
31
|
+
|
32
|
+
#
|
33
|
+
# Refund invoice
|
34
|
+
#
|
35
|
+
def refund!(opts)
|
36
|
+
opts = opts.merge(:invoice_id => self.invoice_id)
|
37
|
+
Twocheckout::API.request(:post, 'sales/refund_invoice', opts)
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Get active recurring lineitems
|
42
|
+
#
|
43
|
+
def active_lineitems
|
44
|
+
@active_lineitems ||= lineitems.select(&:active?).freeze
|
45
|
+
end
|
46
|
+
|
47
|
+
def stop_recurring!
|
48
|
+
active_lineitems.each { |li| li.stop_recurring! }
|
49
|
+
end
|
50
|
+
|
51
|
+
protected
|
52
|
+
|
53
|
+
def _key
|
54
|
+
self.invoice_id
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Twocheckout
|
2
|
+
class LineItem < HashObject
|
3
|
+
|
4
|
+
def refund!(opts)
|
5
|
+
opts = opts.merge(:lineitem_id => self.lineitem_id)
|
6
|
+
Twocheckout::API.request(:post, 'sales/refund_lineitem', opts)
|
7
|
+
end
|
8
|
+
|
9
|
+
def active?
|
10
|
+
self.billing.recurring_status == 'active'
|
11
|
+
end
|
12
|
+
|
13
|
+
def stop_recurring!
|
14
|
+
Twocheckout::API.request(:post, 'sales/stop_lineitem_recurring', lineitem_id: self.lineitem_id)
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# Provide access to update existing recurring lineitems by allowing to lower the lineitem price
|
19
|
+
# and push the recurring billing date forward. This call is not currently documented in the
|
20
|
+
# 2Checkout API documentation.
|
21
|
+
#
|
22
|
+
# POST https://www.2checkout.com/api/sales/update_lineitem_recurring
|
23
|
+
#
|
24
|
+
# Parameters:
|
25
|
+
# * (required) lineitem_id: lineitem_id
|
26
|
+
# * (optional) comment: Optional comment added to sale
|
27
|
+
# * (optional) shift: days to shift next recurring payment forward
|
28
|
+
# * (optional) price: new recurring price (must be lower than previous price or else call will fail)
|
29
|
+
#
|
30
|
+
# The shift and price parameters are optional, but at least one of them must be provided for the
|
31
|
+
# call to be valid.
|
32
|
+
#
|
33
|
+
# Example Shift Date Next
|
34
|
+
# curl -X POST https://www.2checkout.com/api/sales/update_lineitem_recurring -u \
|
35
|
+
# 'username:password' -d 'lineitem_id=1234567890' -d 'shift=7' -H 'Accept: application/json'
|
36
|
+
#
|
37
|
+
# Example Update Price
|
38
|
+
# curl -X POST https://www.2checkout.com/api/sales/update_lineitem_recurring -u \
|
39
|
+
# 'username:password' -d 'lineitem_id=1234567890' -d 'price=1.00' -H 'Accept: application/json'
|
40
|
+
#
|
41
|
+
# Please note that this method cannot be used on PayPal sales as 2Checkout cannot alter the
|
42
|
+
# customer's billing agreement so this call can only update a recurring lineitem on credit card
|
43
|
+
# sales.
|
44
|
+
#
|
45
|
+
def update_recurring!(opts)
|
46
|
+
opts = opts.merge(:lineitem_id => self.lineitem_id)
|
47
|
+
Twocheckout::API.request(:post, 'sales/update_lineitem_recurring', opts)
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
def _key
|
53
|
+
self.lineitem_id
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Twocheckout
|
2
|
+
class Option < HashObject
|
3
|
+
|
4
|
+
#
|
5
|
+
# Finds option by ID and returns a Option object
|
6
|
+
#
|
7
|
+
def self.find(options)
|
8
|
+
response = Twocheckout::API.request(:get, 'products/detail_option', options)
|
9
|
+
Option.new(response['option'][0])
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.with_option_id(option_id)
|
13
|
+
find(:option_id => option_id)
|
14
|
+
end
|
15
|
+
|
16
|
+
#
|
17
|
+
# Creates a new product option
|
18
|
+
#
|
19
|
+
def self.create(opts)
|
20
|
+
response = Twocheckout::API.request(:post, 'products/create_option', opts)
|
21
|
+
find(:option_id => response['option_id'])
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# Updates option and returns a new object
|
26
|
+
#
|
27
|
+
def update(opts)
|
28
|
+
opts = opts.merge(:option_id => self.option_id)
|
29
|
+
Twocheckout::API.request(:post, 'products/update_option', opts)
|
30
|
+
response = Twocheckout::API.request(:get, 'products/detail_option', opts)
|
31
|
+
Option.new(response['option'][0])
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Deletes the option and returns the response
|
36
|
+
#
|
37
|
+
def delete!
|
38
|
+
opts = {:option_id => self.option_id}
|
39
|
+
Twocheckout::API.request(:post, 'products/delete_option', opts)
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# An array to index options list
|
44
|
+
#
|
45
|
+
def self.list(opts=nil)
|
46
|
+
response = Twocheckout::API.request(:get, 'products/list_options', opts)
|
47
|
+
response['options']
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
def _key
|
53
|
+
self.option_id
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Twocheckout
|
2
|
+
class Product < HashObject
|
3
|
+
|
4
|
+
#
|
5
|
+
# Finds product by ID and returns a Product object
|
6
|
+
#
|
7
|
+
def self.find(opts)
|
8
|
+
response = Twocheckout::API.request(:get, 'products/detail_product', opts)
|
9
|
+
Product.new(response['product'])
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.with_product_id(product_id)
|
13
|
+
find(:product_id => product_id)
|
14
|
+
end
|
15
|
+
|
16
|
+
#
|
17
|
+
# Creates a new product and returns the Product object
|
18
|
+
#
|
19
|
+
def self.create(opts)
|
20
|
+
response = Twocheckout::API.request(:post, 'products/create_product', opts)
|
21
|
+
find(:product_id => response['product_id'])
|
22
|
+
end
|
23
|
+
|
24
|
+
#
|
25
|
+
# Updates product and returns a new Product object
|
26
|
+
#
|
27
|
+
def update(opts)
|
28
|
+
opts = opts.merge(:product_id => self.product_id)
|
29
|
+
Twocheckout::API.request(:post, 'products/update_product', opts)
|
30
|
+
response = Twocheckout::API.request(:get, 'products/detail_product', opts)
|
31
|
+
Product.new(response['product'])
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Deletes the product and returns the response
|
36
|
+
#
|
37
|
+
def delete!
|
38
|
+
opts = {:product_id => self.product_id}
|
39
|
+
Twocheckout::API.request(:post, 'products/delete_product', opts)
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# Get product list in an array
|
44
|
+
#
|
45
|
+
def self.list(opts)
|
46
|
+
response = Twocheckout::API.request(:get, 'products/list_products', opts)
|
47
|
+
response['products']
|
48
|
+
end
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
def _key
|
53
|
+
self.product_id
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
module Twocheckout
|
2
|
+
class Sale < HashObject
|
3
|
+
|
4
|
+
def self.find(options)
|
5
|
+
response = Twocheckout::API.request(:get, 'sales/detail_sale', options)
|
6
|
+
Sale.new(response['sale'])
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.with_sale_id(sale_id)
|
10
|
+
find(:sale_id => sale_id)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.with_invoice_id(invoice_id)
|
14
|
+
find(:invoice_id => invoice_id)
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# An array of all invoices in this sale
|
19
|
+
#
|
20
|
+
def invoices
|
21
|
+
if @invoices.nil?
|
22
|
+
@invoices = @hash['invoices'].map { |i| Twocheckout::Invoice.new(i) }
|
23
|
+
@invoices.freeze
|
24
|
+
end
|
25
|
+
@invoices
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# A hash to index invoices by id
|
30
|
+
#
|
31
|
+
def invoice
|
32
|
+
if @invoice.nil?
|
33
|
+
@invoice = {}
|
34
|
+
invoices.each { |inv| @invoice[inv.invoice_id] = inv }
|
35
|
+
@invoice.freeze
|
36
|
+
end
|
37
|
+
return @invoice
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Refund sale
|
42
|
+
#
|
43
|
+
def refund!(opts)
|
44
|
+
opts = opts.merge(:sale_id => self.sale_id)
|
45
|
+
Twocheckout::API.request(:post, 'sales/refund_invoice', opts)
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
# Get active recurring lineitems from the most recent invoice
|
50
|
+
#
|
51
|
+
def active_lineitems
|
52
|
+
invoices.last.active_lineitems
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# Stop all active recurring lineitems
|
57
|
+
#
|
58
|
+
def stop_recurring!
|
59
|
+
active_lineitems.each { |li| li.stop_recurring! }
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
# Add a sale comment
|
64
|
+
#
|
65
|
+
def comment(opts)
|
66
|
+
opts = opts.merge(:sale_id => self.sale_id)
|
67
|
+
Twocheckout::API.request(:post, 'sales/create_comment', opts)
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Mark tangible sale as shipped
|
72
|
+
#
|
73
|
+
def ship(opts)
|
74
|
+
opts = opts.merge(:sale_id => self.sale_id)
|
75
|
+
Twocheckout::API.request(:post, 'sales/mark_shipped', opts)
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# Reauthorize sale
|
80
|
+
#
|
81
|
+
def reauth
|
82
|
+
Twocheckout::API.request(:post, 'sales/reauth', sale_id: self.sale_id)
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
# Get sale list in an array
|
87
|
+
#
|
88
|
+
def self.list(opts)
|
89
|
+
response = Twocheckout::API.request(:get, 'sales/list_sales', opts)
|
90
|
+
response['sale_summary']
|
91
|
+
end
|
92
|
+
|
93
|
+
protected
|
94
|
+
|
95
|
+
def _key
|
96
|
+
self.sale_id
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Twocheckout
|
2
|
+
class TwocheckoutError < StandardError
|
3
|
+
attr_reader :message
|
4
|
+
|
5
|
+
def initialize(message)
|
6
|
+
@message = message
|
7
|
+
end
|
8
|
+
|
9
|
+
def retrieve
|
10
|
+
if @message.is_a?(Hash)
|
11
|
+
@message = JSON.generate(@message)
|
12
|
+
"#{@message}"
|
13
|
+
else
|
14
|
+
"#{@message}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'digest/md5'
|
2
|
+
|
3
|
+
module Twocheckout
|
4
|
+
class ValidateResponse
|
5
|
+
|
6
|
+
# Checks against MD5 Hash
|
7
|
+
def self.valid?(arg1, arg2, arg3, arg4, key)
|
8
|
+
Digest::MD5.hexdigest("#{arg1}#{arg2}#{arg3}#{arg4}").upcase == key
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.purchase(options)
|
12
|
+
options[:demo] == 'Y' ? 1 : options[:order_number]
|
13
|
+
if valid?(options[:secret], options[:sid], options[:order_number], options[:total], options[:key])
|
14
|
+
{:code => "PASS", :message => "Hash Matched"}
|
15
|
+
else
|
16
|
+
{:code => "FAIL", :message => "Hash Mismatch"}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.notification(options)
|
21
|
+
if valid?(options[:sale_id], options[:vendor_id], options[:invoice_id], options[:secret], options[:md5_hash])
|
22
|
+
{:code => "PASS", :message => "Hash Matched"}
|
23
|
+
else
|
24
|
+
{:code => "FAIL", :message => "Hash Mismatch"}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/twocheckout.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "twocheckout/version"
|
2
|
+
require "twocheckout/api"
|
3
|
+
require "twocheckout/hash_object"
|
4
|
+
require "twocheckout/validate_response"
|
5
|
+
require "twocheckout/company"
|
6
|
+
require "twocheckout/lineitem"
|
7
|
+
require "twocheckout/invoice"
|
8
|
+
require "twocheckout/sale"
|
9
|
+
require "twocheckout/coupon"
|
10
|
+
require "twocheckout/product"
|
11
|
+
require "twocheckout/option"
|
12
|
+
require "twocheckout/checkout"
|
13
|
+
require "twocheckout/twocheckout_error"
|
@@ -0,0 +1,252 @@
|
|
1
|
+
require "minitest/spec"
|
2
|
+
require "minitest/autorun"
|
3
|
+
require "twocheckout"
|
4
|
+
|
5
|
+
#
|
6
|
+
# Sales
|
7
|
+
#
|
8
|
+
describe Twocheckout::Sale do
|
9
|
+
before do
|
10
|
+
Twocheckout::API.credentials = { :username => 'APIuser1817037', :password => 'APIpass1817037' }
|
11
|
+
end
|
12
|
+
|
13
|
+
#retrieve sale
|
14
|
+
it "Sale retrieve returns sale" do
|
15
|
+
sale = Twocheckout::Sale.find(:sale_id => 4786293822)
|
16
|
+
assert_equal('4786293822', sale.sale_id)
|
17
|
+
end
|
18
|
+
|
19
|
+
#retrieve invoice
|
20
|
+
it "Sale retrieve returns invoice" do
|
21
|
+
invoice = Twocheckout::Sale.find({:invoice_id => 4786293831})
|
22
|
+
assert_equal('4786293831', invoice.invoice_id)
|
23
|
+
end
|
24
|
+
|
25
|
+
#retrieve sale list
|
26
|
+
it "Sale list returns list" do
|
27
|
+
sale_list = Twocheckout::Sale.list({:pagesize => 5})
|
28
|
+
assert_equal(5, sale_list.size)
|
29
|
+
end
|
30
|
+
|
31
|
+
#refund sale
|
32
|
+
it "Refunding a refunded sale returns exception" do
|
33
|
+
begin
|
34
|
+
sale = Twocheckout::Sale.find(:sale_id => 4786293822)
|
35
|
+
sale.refund!({:comment => "test refund", :category => 1})
|
36
|
+
rescue Exception => e
|
37
|
+
assert_equal("Invoice was already refunded.", e.message)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
#refund invoice
|
42
|
+
it "Refunding a refunded invoice returns exception" do
|
43
|
+
begin
|
44
|
+
sale = Twocheckout::Sale.find(:sale_id => 4786293822)
|
45
|
+
invoice = sale.invoices.first
|
46
|
+
invoice.refund!({:comment => "test refund", :category => 1})
|
47
|
+
rescue Exception => e
|
48
|
+
assert_equal("Invoice was already refunded.", e.message)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
#refund lineitem
|
53
|
+
it "Refunding a refunded lineitem returns exception" do
|
54
|
+
begin
|
55
|
+
sale = Twocheckout::Sale.find(:sale_id => 4786293822)
|
56
|
+
first_invoice = sale.invoices.first
|
57
|
+
last_lineitem = first_invoice.lineitems.last
|
58
|
+
last_lineitem.refund!({:comment => "test refund", :category => 1})
|
59
|
+
rescue Exception => e
|
60
|
+
assert_equal("This lineitem cannot be refunded.", e.message)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
#stop recurring lineitem
|
65
|
+
it "Stopping a stopped recurring lineitem returns exception" do
|
66
|
+
begin
|
67
|
+
sale = Twocheckout::Sale.find(:sale_id => 4786293822)
|
68
|
+
result = sale.stop_recurring!
|
69
|
+
assert_equal(result, [])
|
70
|
+
rescue Exception => e
|
71
|
+
assert_equal("Lineitem is not scheduled to recur.", e.message)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
#stop recurring sale
|
76
|
+
it "Stopping a stopped recurring sale returns exception" do
|
77
|
+
begin
|
78
|
+
sale = Twocheckout::Sale.find(:sale_id => 4786293822)
|
79
|
+
last_invoice = sale.invoices.last
|
80
|
+
last_lineitem = last_invoice.lineitems.last
|
81
|
+
last_lineitem.stop_recurring!
|
82
|
+
rescue Exception => e
|
83
|
+
assert_equal("Lineitem is not scheduled to recur.", e.message)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
#create comment
|
88
|
+
it "Creates a sale comment" do
|
89
|
+
sale = Twocheckout::Sale.find(:sale_id => 4786293822)
|
90
|
+
result = sale.comment({:sale_comment => "test"})
|
91
|
+
assert_equal('Created comment successfully.', result['response_message'])
|
92
|
+
end
|
93
|
+
|
94
|
+
#mark shipped
|
95
|
+
it "Shipping an intangible sale returns exception" do
|
96
|
+
begin
|
97
|
+
sale = Twocheckout::Sale.find(:sale_id => 4786293822)
|
98
|
+
sale.ship({:tracking_number => "123"})
|
99
|
+
rescue Exception => e
|
100
|
+
assert_equal("Item not shippable.", e.message)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
#reauth
|
105
|
+
it "Reauthorizing a pending sale returns exception" do
|
106
|
+
begin
|
107
|
+
sale = Twocheckout::Sale.find(:sale_id => 4786293822)
|
108
|
+
sale.reauth
|
109
|
+
rescue Exception => e
|
110
|
+
assert_equal("Payment is already pending or deposited and cannot be reauthorized.", e.message)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
#
|
116
|
+
# Products
|
117
|
+
#
|
118
|
+
|
119
|
+
describe Twocheckout::Product do
|
120
|
+
before do
|
121
|
+
Twocheckout::API.credentials = { :username => 'APIuser1817037', :password => 'APIpass1817037' }
|
122
|
+
end
|
123
|
+
|
124
|
+
# Product list
|
125
|
+
it "Product list returns array of products" do
|
126
|
+
product_list = Twocheckout::Product.list({ :pagesize => 5 })
|
127
|
+
assert_equal(product_list.size, 5)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Product CRUD
|
131
|
+
it "Product create, find, update, delete is successful" do
|
132
|
+
# create
|
133
|
+
new_product = Twocheckout::Product.create({:name => "test product", :price => 1.00})
|
134
|
+
assert_equal("test product", new_product.name)
|
135
|
+
# find
|
136
|
+
product = Twocheckout::Product.find({:product_id => new_product.product_id})
|
137
|
+
assert_equal(new_product.product_id, product.product_id)
|
138
|
+
# update
|
139
|
+
product = product.update({:name => "new name"})
|
140
|
+
assert_equal("new name", product.name)
|
141
|
+
# delete
|
142
|
+
result = product.delete!
|
143
|
+
assert_equal("Product successfully deleted.", result['response_message'])
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe Twocheckout::Option do
|
148
|
+
before do
|
149
|
+
Twocheckout::API.credentials = { :username => 'APIuser1817037', :password => 'APIpass1817037' }
|
150
|
+
end
|
151
|
+
|
152
|
+
# Option list
|
153
|
+
it "Option list returns array of options" do
|
154
|
+
option_list = Twocheckout::Option.list({ :pagesize => 5 })
|
155
|
+
assert_equal(5, option_list.size)
|
156
|
+
end
|
157
|
+
|
158
|
+
# Option CRUD
|
159
|
+
it "Option create, find, update, delete is successful" do
|
160
|
+
# create
|
161
|
+
new_option = Twocheckout::Option.create({:option_name => "test option",
|
162
|
+
:option_value_name => "test option value", :option_value_surcharge => 1.00})
|
163
|
+
assert_equal("test option", new_option.option_name)
|
164
|
+
# find
|
165
|
+
option = Twocheckout::Option.find({:option_id => new_option.option_id})
|
166
|
+
assert_equal(new_option.option_id, option.option_id)
|
167
|
+
# update
|
168
|
+
option = option.update({:option_name => "new name"})
|
169
|
+
assert_equal("new name", option.option_name)
|
170
|
+
# delete
|
171
|
+
result = option.delete!
|
172
|
+
assert_equal("Option deleted successfully", result['response_message'])
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe Twocheckout::Coupon do
|
177
|
+
before do
|
178
|
+
Twocheckout::API.credentials = { :username => 'APIuser1817037', :password => 'APIpass1817037' }
|
179
|
+
end
|
180
|
+
|
181
|
+
# Coupon list
|
182
|
+
it "Coupon list returns array of coupons" do
|
183
|
+
coupon_list = Twocheckout::Coupon.list({ :pagesize => 4 })
|
184
|
+
assert_equal(4, coupon_list.size)
|
185
|
+
end
|
186
|
+
|
187
|
+
# Coupon CRUD
|
188
|
+
it "Coupon create, find, update, delete is successful" do
|
189
|
+
# create
|
190
|
+
new_coupon = Twocheckout::Coupon.create({:date_expire => "2020-01-01",
|
191
|
+
:type => "shipping", :minimum_purchase => 1.00})
|
192
|
+
assert_equal("2020-01-01", new_coupon.date_expire)
|
193
|
+
# find
|
194
|
+
coupon = Twocheckout::Coupon.find({:coupon_code => new_coupon.coupon_code})
|
195
|
+
assert_equal(new_coupon.coupon_code, coupon.coupon_code)
|
196
|
+
# update
|
197
|
+
coupon = coupon.update({:date_expire => "2020-01-02"})
|
198
|
+
assert_equal("2020-01-02", coupon.date_expire)
|
199
|
+
# delete
|
200
|
+
result = coupon.delete!
|
201
|
+
assert_equal("Coupon successfully deleted.", result['response_message'])
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe Twocheckout::ValidateResponse do
|
206
|
+
#purchase
|
207
|
+
it "Validates Purchase MD5 Hash" do
|
208
|
+
result = Twocheckout::ValidateResponse.purchase({:sid => 1817037, :secret => "tango", :order_number => 4789848870, :total => 0.01,
|
209
|
+
:key => 'CDF3E502AA1597DD4401760783432337'})
|
210
|
+
assert_equal('PASS', result[:code])
|
211
|
+
end
|
212
|
+
|
213
|
+
#notification
|
214
|
+
it "Validates Notification MD5 Hash" do
|
215
|
+
result = Twocheckout::ValidateResponse.notification({:sale_id => 4789848870, :vendor_id => 1817037, :invoice_id => 4789848879, :secret => "tango",
|
216
|
+
:md5_hash => '827220324C722873694758F38D8D3624'})
|
217
|
+
assert_equal('PASS', result[:code])
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
describe Twocheckout::Checkout do
|
222
|
+
#submit
|
223
|
+
it "Submit return a form + JS to submit" do
|
224
|
+
form = Twocheckout::Checkout.submit({ 'sid' => '1817037', 'cart_order_id' => 'Example Sale', 'total' => '1.00'})
|
225
|
+
@form = "<form id=\"2checkout\" action=\"https://www.2checkout.com/checkout/spurchase\" method=\"post\">\n" +
|
226
|
+
"<input type=\"hidden\" name=\"sid\" value=\"1817037\" />\n" +
|
227
|
+
"<input type=\"hidden\" name=\"cart_order_id\" value=\"Example Sale\" />\n" +
|
228
|
+
"<input type=\"hidden\" name=\"total\" value=\"1.00\" />\n" +
|
229
|
+
"</form>\n" +
|
230
|
+
"<script type=\"text/javascript\">document.getElementById('2checkout').submit();</script>"
|
231
|
+
assert_equal(form, @form)
|
232
|
+
end
|
233
|
+
|
234
|
+
#form
|
235
|
+
it "Form returns a form" do
|
236
|
+
form = Twocheckout::Checkout.form({ 'sid' => '1817037', 'cart_order_id' => 'Example Sale', 'total' => '1.00'})
|
237
|
+
@form = "<form id=\"2checkout\" action=\"https://www.2checkout.com/checkout/spurchase\" method=\"post\">\n" +
|
238
|
+
"<input type=\"hidden\" name=\"sid\" value=\"1817037\" />\n" +
|
239
|
+
"<input type=\"hidden\" name=\"cart_order_id\" value=\"Example Sale\" />\n" +
|
240
|
+
"<input type=\"hidden\" name=\"total\" value=\"1.00\" />\n" +
|
241
|
+
"<input type=\"submit\" value=\"Proceed to Checkout\" />\n" +
|
242
|
+
"</form>"
|
243
|
+
assert_equal(form, @form)
|
244
|
+
end
|
245
|
+
|
246
|
+
#link
|
247
|
+
it "Link returns a link" do
|
248
|
+
link = Twocheckout::Checkout.link({ 'sid' => '1817037', 'cart_order_id' => 'Example Sale', 'total' => '1.00'})
|
249
|
+
@link = "https://www.2checkout.com/checkout/spurchase?sid=1817037&cart_order_id=Example+Sale&total=1.00"
|
250
|
+
assert_equal(link, @link)
|
251
|
+
end
|
252
|
+
end
|
data/twocheckout.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
$:.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.platform = Gem::Platform::RUBY
|
6
|
+
s.name = 'twocheckout'
|
7
|
+
s.version = '0.1.1'
|
8
|
+
s.summary = '2Checkout Ruby Library'
|
9
|
+
s.description = '0.1.1'
|
10
|
+
s.summary = '2Checkout Ruby Library'
|
11
|
+
s.author = "Craig Christenson", "Ernesto Garcia"
|
12
|
+
s.email = 'christensoncraig@gmail.com'
|
13
|
+
s.homepage = 'https://github.com/craigchristenson'
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.add_dependency('rest-client', '~> 1.4')
|
18
|
+
s.require_paths = %w{lib}
|
19
|
+
s.requirements << 'none'
|
20
|
+
|
21
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: twocheckout
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -19,7 +19,7 @@ dependencies:
|
|
19
19
|
requirements:
|
20
20
|
- - ~>
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 1.
|
22
|
+
version: '1.4'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -27,16 +27,33 @@ dependencies:
|
|
27
27
|
requirements:
|
28
28
|
- - ~>
|
29
29
|
- !ruby/object:Gem::Version
|
30
|
-
version: 1.
|
31
|
-
description: 0.1.
|
32
|
-
email:
|
33
|
-
- christensoncraig@gmail.com
|
34
|
-
- ernesto+git@gnapse.com
|
30
|
+
version: '1.4'
|
31
|
+
description: 0.1.1
|
32
|
+
email: christensoncraig@gmail.com
|
35
33
|
executables: []
|
36
34
|
extensions: []
|
37
35
|
extra_rdoc_files: []
|
38
|
-
files:
|
39
|
-
|
36
|
+
files:
|
37
|
+
- .gitignore
|
38
|
+
- LICENSE
|
39
|
+
- README.md
|
40
|
+
- lib/twocheckout.rb
|
41
|
+
- lib/twocheckout/api.rb
|
42
|
+
- lib/twocheckout/checkout.rb
|
43
|
+
- lib/twocheckout/company.rb
|
44
|
+
- lib/twocheckout/coupon.rb
|
45
|
+
- lib/twocheckout/hash_object.rb
|
46
|
+
- lib/twocheckout/invoice.rb
|
47
|
+
- lib/twocheckout/lineitem.rb
|
48
|
+
- lib/twocheckout/option.rb
|
49
|
+
- lib/twocheckout/product.rb
|
50
|
+
- lib/twocheckout/sale.rb
|
51
|
+
- lib/twocheckout/twocheckout_error.rb
|
52
|
+
- lib/twocheckout/validate_response.rb
|
53
|
+
- lib/twocheckout/version.rb
|
54
|
+
- test/test_twocheckout.rb
|
55
|
+
- twocheckout.gemspec
|
56
|
+
homepage: https://github.com/craigchristenson
|
40
57
|
licenses: []
|
41
58
|
post_install_message:
|
42
59
|
rdoc_options: []
|
@@ -54,10 +71,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
54
71
|
- - ! '>='
|
55
72
|
- !ruby/object:Gem::Version
|
56
73
|
version: '0'
|
57
|
-
requirements:
|
74
|
+
requirements:
|
75
|
+
- none
|
58
76
|
rubyforge_project:
|
59
77
|
rubygems_version: 1.8.24
|
60
78
|
signing_key:
|
61
79
|
specification_version: 3
|
62
|
-
summary: Ruby
|
63
|
-
test_files:
|
80
|
+
summary: 2Checkout Ruby Library
|
81
|
+
test_files:
|
82
|
+
- test/test_twocheckout.rb
|