recharge-api 0.0.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.
- checksums.yaml +7 -0
- data/.gitignore +122 -0
- data/.travis.yml +12 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +83 -0
- data/Rakefile +6 -0
- data/lib/recharge-api.rb +1 -0
- data/lib/recharge.rb +36 -0
- data/lib/recharge/classes.rb +462 -0
- data/lib/recharge/http_request.rb +223 -0
- data/lib/recharge/tasks.rb +65 -0
- data/lib/recharge/version.rb +3 -0
- data/recharge-api.gemspec +27 -0
- metadata +127 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 38da2ffc86ba27bea660a00c153e74ffe72fc054
|
4
|
+
data.tar.gz: eed4ac714a4c95f27791c196fbe8c74a2e458b63
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3b0e967d97687f1df95f7c981bae8846fd62736e246ff186087c40fb005f4711321652450475ccaff461b7ff915c3e7d4479c74e8021fe5794b67c7b1902a171
|
7
|
+
data.tar.gz: fab06c67606cd8052deb664ebaea1d1adc1b7615cd6777080c737ccfb05ea53bf0fc56e4ab02a4cab480c3c05c333b5297410d5fbb2702f1c27c3e6c3d44ec3a
|
data/.gitignore
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
|
2
|
+
# Created by https://www.gitignore.io/api/emacs,ruby
|
3
|
+
|
4
|
+
### Emacs ###
|
5
|
+
# -*- mode: gitignore; -*-
|
6
|
+
*~
|
7
|
+
\#*\#
|
8
|
+
/.emacs.desktop
|
9
|
+
/.emacs.desktop.lock
|
10
|
+
*.elc
|
11
|
+
auto-save-list
|
12
|
+
tramp
|
13
|
+
.\#*
|
14
|
+
|
15
|
+
# Org-mode
|
16
|
+
.org-id-locations
|
17
|
+
*_archive
|
18
|
+
|
19
|
+
# flymake-mode
|
20
|
+
*_flymake.*
|
21
|
+
|
22
|
+
# eshell files
|
23
|
+
/eshell/history
|
24
|
+
/eshell/lastdir
|
25
|
+
|
26
|
+
# elpa packages
|
27
|
+
/elpa/
|
28
|
+
|
29
|
+
# reftex files
|
30
|
+
*.rel
|
31
|
+
|
32
|
+
# AUCTeX auto folder
|
33
|
+
/auto/
|
34
|
+
|
35
|
+
# cask packages
|
36
|
+
.cask/
|
37
|
+
dist/
|
38
|
+
|
39
|
+
# Flycheck
|
40
|
+
flycheck_*.el
|
41
|
+
|
42
|
+
# server auth directory
|
43
|
+
/server/
|
44
|
+
|
45
|
+
# projectiles files
|
46
|
+
.projectile
|
47
|
+
projectile-bookmarks.eld
|
48
|
+
|
49
|
+
# directory configuration
|
50
|
+
.dir-locals.el
|
51
|
+
|
52
|
+
# saveplace
|
53
|
+
places
|
54
|
+
|
55
|
+
# url cache
|
56
|
+
url/cache/
|
57
|
+
|
58
|
+
# cedet
|
59
|
+
ede-projects.el
|
60
|
+
|
61
|
+
# smex
|
62
|
+
smex-items
|
63
|
+
|
64
|
+
# company-statistics
|
65
|
+
company-statistics-cache.el
|
66
|
+
|
67
|
+
# anaconda-mode
|
68
|
+
anaconda-mode/
|
69
|
+
|
70
|
+
### Ruby ###
|
71
|
+
*.gem
|
72
|
+
*.rbc
|
73
|
+
/.config
|
74
|
+
/coverage/
|
75
|
+
/InstalledFiles
|
76
|
+
/pkg/
|
77
|
+
/spec/reports/
|
78
|
+
/spec/examples.txt
|
79
|
+
/test/tmp/
|
80
|
+
/test/version_tmp/
|
81
|
+
/tmp/
|
82
|
+
|
83
|
+
# Used by dotenv library to load environment variables.
|
84
|
+
# .env
|
85
|
+
|
86
|
+
## Specific to RubyMotion:
|
87
|
+
.dat*
|
88
|
+
.repl_history
|
89
|
+
build/
|
90
|
+
*.bridgesupport
|
91
|
+
build-iPhoneOS/
|
92
|
+
build-iPhoneSimulator/
|
93
|
+
|
94
|
+
## Specific to RubyMotion (use of CocoaPods):
|
95
|
+
#
|
96
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
97
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
98
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
99
|
+
#
|
100
|
+
# vendor/Pods/
|
101
|
+
|
102
|
+
## Documentation cache and generated files:
|
103
|
+
/.yardoc/
|
104
|
+
/_yardoc/
|
105
|
+
/doc/
|
106
|
+
/rdoc/
|
107
|
+
|
108
|
+
## Environment normalization:
|
109
|
+
/.bundle/
|
110
|
+
/vendor/bundle
|
111
|
+
/lib/bundler/man/
|
112
|
+
|
113
|
+
# for a library or gem, you might want to ignore these files since the code is
|
114
|
+
# intended to run in multiple environments; otherwise, check them in:
|
115
|
+
# Gemfile.lock
|
116
|
+
# .ruby-version
|
117
|
+
# .ruby-gemset
|
118
|
+
|
119
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
120
|
+
.rvmrc
|
121
|
+
|
122
|
+
# End of https://www.gitignore.io/api/emacs,ruby
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 ScreenStaring
|
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
|
13
|
+
all 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
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# ReCharge API Client
|
2
|
+
|
3
|
+
[](https://travis-ci.org/ScreenStaring/recharge-api)
|
4
|
+
|
5
|
+
Ruby client for [ReCharge Payments'](https://rechargepayments.com/developers)
|
6
|
+
recurring payments API for Shopify.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Ruby gems:
|
11
|
+
|
12
|
+
gem install recharge-api
|
13
|
+
|
14
|
+
Bundler:
|
15
|
+
|
16
|
+
gem "recharge-api", :require => "recharge"
|
17
|
+
|
18
|
+
## Usage
|
19
|
+
|
20
|
+
```rb
|
21
|
+
require "recharge"
|
22
|
+
|
23
|
+
ReCharge.api_key = "YOUR_KEY" # Can also use Recharge
|
24
|
+
data = {
|
25
|
+
:address_id => 123234321,
|
26
|
+
:customer_id => 565728,
|
27
|
+
# ... more stuff
|
28
|
+
:next_charge_scheduled_at => Time.new,
|
29
|
+
:properties => {
|
30
|
+
:name => "size",
|
31
|
+
:value => "medium"
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
subscription = ReCharge::Subscription.create(data)
|
36
|
+
subscription.address_id = 454343
|
37
|
+
subscription.save
|
38
|
+
|
39
|
+
# Or
|
40
|
+
ReCharge::Subscription.update(id, data)
|
41
|
+
|
42
|
+
subscription = ReCharge::Subscription.new(data)
|
43
|
+
subscription.save
|
44
|
+
|
45
|
+
order1 = ReCharge::Order.get(123123)
|
46
|
+
order1.line_items.each do |li|
|
47
|
+
p li.title
|
48
|
+
p li.quantity
|
49
|
+
end
|
50
|
+
|
51
|
+
order2 = ReCharge::Order.get(453321)
|
52
|
+
p "Different" if order1 != order2
|
53
|
+
|
54
|
+
JSON.dump(order2.to_h)
|
55
|
+
|
56
|
+
customers = ReCharge::Customer.list(:page => 10, :limit => 50)
|
57
|
+
customers.each do |customer|
|
58
|
+
addresses = ReCharge::Customer.addresses(customer.id)
|
59
|
+
# ...
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
For complete documentation refer to the API docs: http://rdoc.info/gems/recharge-api
|
64
|
+
|
65
|
+
## Rake Tasks for Webhook Management
|
66
|
+
|
67
|
+
Requiring `recharge/tasks` will include several Rake tasks for webhook management.
|
68
|
+
All tasks require `RECHARGE_API_KEY` be set.
|
69
|
+
|
70
|
+
The hooks are:
|
71
|
+
|
72
|
+
* `recharge:hook:create` - create webhook `HOOK` to be sent to `CALLBACK`
|
73
|
+
* `recharge:hooks:delete` - delete the webhook(s) given by `ID`
|
74
|
+
* `recharge:hooks:delete_all` - delete all webhooks
|
75
|
+
* `recharge:hooks:list` - list webhooks
|
76
|
+
|
77
|
+
## License
|
78
|
+
|
79
|
+
Released under the MIT License: www.opensource.org/licenses/MIT
|
80
|
+
|
81
|
+
---
|
82
|
+
|
83
|
+
Made by [ScreenStaring](http://screenstaring.com)
|
data/Rakefile
ADDED
data/lib/recharge-api.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "recharge"
|
data/lib/recharge.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require "recharge/classes"
|
2
|
+
require "recharge/version"
|
3
|
+
|
4
|
+
module Recharge
|
5
|
+
ENDPOINT = "api.rechargeapps.com".freeze
|
6
|
+
PORT = 443
|
7
|
+
TOKEN_HEADER = "X-Recharge-Access-Token".freeze
|
8
|
+
USER_AGENT = "ReCharge API Client v#{VERSION} (Ruby v#{RUBY_VERSION})"
|
9
|
+
|
10
|
+
Error = Class.new(StandardError)
|
11
|
+
ConnectionError = Class.new(Error)
|
12
|
+
|
13
|
+
#
|
14
|
+
# Raised when a non-2XX HTTP response is returned
|
15
|
+
#
|
16
|
+
class RequestError < Error
|
17
|
+
attr_accessor :errors
|
18
|
+
attr_accessor :status
|
19
|
+
attr_accessor :meta
|
20
|
+
|
21
|
+
def initialize(message, status, meta = nil, errors = nil)
|
22
|
+
super message
|
23
|
+
@status = status
|
24
|
+
@meta = meta || {}
|
25
|
+
@errors = errors || {}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class << self
|
30
|
+
attr_accessor :api_key
|
31
|
+
# If +true+ output HTTP request/response to stderr. Can also be an +IO+ instance to output to.
|
32
|
+
attr_accessor :debug
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
ReCharge = Recharge
|
@@ -0,0 +1,462 @@
|
|
1
|
+
require "json"
|
2
|
+
require "class2"
|
3
|
+
require "recharge/http_request"
|
4
|
+
|
5
|
+
class2 "Recharge", JSON.parse(<<-END) do
|
6
|
+
{
|
7
|
+
"subscription":
|
8
|
+
{
|
9
|
+
"id":10101,
|
10
|
+
"address_id":178918,
|
11
|
+
"customer_id":1438,
|
12
|
+
"created_at":"2017-02-28T20:31:29",
|
13
|
+
"updated_at":"2017-02-28 20:31:29",
|
14
|
+
"next_charge_scheduled_at":"2017-04-01T00:00:00",
|
15
|
+
"cancelled_at":null,
|
16
|
+
"product_title":"Sumatra Coffee",
|
17
|
+
"price":12,
|
18
|
+
"quantity":1,
|
19
|
+
"status":"ACTIVE",
|
20
|
+
"shopify_product_id":1255183683,
|
21
|
+
"shopify_variant_id":3844924611,
|
22
|
+
"sku":null,
|
23
|
+
"order_interval_unit":"day",
|
24
|
+
"order_interval_frequency":"30",
|
25
|
+
"charge_interval_frequency":"30",
|
26
|
+
"order_day_of_month":null,
|
27
|
+
"order_day_of_week":null,
|
28
|
+
"properties": []
|
29
|
+
},
|
30
|
+
"charge":
|
31
|
+
{
|
32
|
+
"address_id":178918,
|
33
|
+
"billing_address":{
|
34
|
+
"address1":"3030 Nebraska Avenue",
|
35
|
+
"address2":"",
|
36
|
+
"city":"Los Angeles",
|
37
|
+
"company":"",
|
38
|
+
"country":"United States",
|
39
|
+
"first_name":"Mike",
|
40
|
+
"last_name":"Flynn",
|
41
|
+
"phone":"",
|
42
|
+
"province":"California",
|
43
|
+
"zip":"90404"
|
44
|
+
},
|
45
|
+
"client_details": {
|
46
|
+
"browser_ip": null,
|
47
|
+
"user_agent": null
|
48
|
+
},
|
49
|
+
"created_at":"2017-03-01T19:52:11",
|
50
|
+
"customer_hash":null,
|
51
|
+
"customer_id":10101,
|
52
|
+
"first_name":"Mike",
|
53
|
+
"id":1843,
|
54
|
+
"last_name":"Flynn",
|
55
|
+
"line_items":[
|
56
|
+
{
|
57
|
+
"grams":0,
|
58
|
+
"price":100.0,
|
59
|
+
"properties":[],
|
60
|
+
"quantity":1,
|
61
|
+
"shopify_product_id": "1255183683",
|
62
|
+
"shopify_variant_id":"3844924611",
|
63
|
+
"sku":"",
|
64
|
+
"title": "Milk 10% Off Auto renew",
|
65
|
+
"variant_title": "a / b",
|
66
|
+
"vendor": "Example Storeeeeeee",
|
67
|
+
"subscription_id":14562
|
68
|
+
}
|
69
|
+
],
|
70
|
+
"processed_at":"2014-11-20T00:00:00",
|
71
|
+
"scheduled_at":"2014-11-20T00:00:01",
|
72
|
+
"shipments_count":null,
|
73
|
+
"shipping_address":{
|
74
|
+
"address1":"3030 Nebraska Avenue",
|
75
|
+
"address2":"",
|
76
|
+
"city":"Los Angeles",
|
77
|
+
"company":"",
|
78
|
+
"country":"United States",
|
79
|
+
"first_name":"Mike",
|
80
|
+
"last_name":"Flynn",
|
81
|
+
"phone":"3103843698",
|
82
|
+
"province":"California",
|
83
|
+
"zip":"90404"
|
84
|
+
},
|
85
|
+
"shopify_order_id":"281223307",
|
86
|
+
"status":"SUCCESS",
|
87
|
+
"total_price":446.00,
|
88
|
+
"updated_at":"2016-09-05T09:19:29"
|
89
|
+
},
|
90
|
+
"customer":
|
91
|
+
{
|
92
|
+
"id": 1438,
|
93
|
+
"hash": "143806234a9ff87a8d9e",
|
94
|
+
"shopify_customer_id": null,
|
95
|
+
"email": "mike@gmail.com",
|
96
|
+
"created_at": "2018-01-10T11:00:00",
|
97
|
+
"updated_at": "2017-01-11T13:16:19",
|
98
|
+
"first_name": "Mike",
|
99
|
+
"last_name": "Flynn",
|
100
|
+
"billing_first_name": "Mike",
|
101
|
+
"billing_last_name": "Flynn",
|
102
|
+
"billing_company": null,
|
103
|
+
"billing_address1": "3030 Nebraska Avenue",
|
104
|
+
"billing_address2": null,
|
105
|
+
"billing_zip": "90404",
|
106
|
+
"billing_city": "Los Angeles",
|
107
|
+
"billing_province": "California",
|
108
|
+
"billing_country": "United States",
|
109
|
+
"billing_phone": "3103843698",
|
110
|
+
"processor_type": null,
|
111
|
+
"status": "FOO"
|
112
|
+
},
|
113
|
+
"order": {
|
114
|
+
"id":7271806,
|
115
|
+
"customer_id":10101,
|
116
|
+
"address_id":178918,
|
117
|
+
"charge_id":9519316,
|
118
|
+
"transaction_id":"ch_19sdP2J2zqHvZRd1hqkeGANO",
|
119
|
+
"shopify_order_id":"5180645510",
|
120
|
+
"shopify_order_number":5913,
|
121
|
+
"created_at":"2017-03-01T14:46:26",
|
122
|
+
"updated_at":"2017-03-01T14:46:26",
|
123
|
+
"scheduled_at":"2017-03-01T00:00:00",
|
124
|
+
"processed_at":"2017-03-01T14:46:26",
|
125
|
+
"status":"SUCCESS",
|
126
|
+
"charge_status":"SUCCESS",
|
127
|
+
"type":"CHECKOUT",
|
128
|
+
"first_name":"Mike",
|
129
|
+
"last_name":"Flynn",
|
130
|
+
"email":"mike@gmail.com",
|
131
|
+
"payment_processor":"stripe",
|
132
|
+
"address_is_active":1,
|
133
|
+
"is_prepaid":0,
|
134
|
+
"line_items":[
|
135
|
+
{
|
136
|
+
"subscription_id":10101,
|
137
|
+
"shopify_product_id":"1255183683",
|
138
|
+
"shopify_variant_id":"3844924611",
|
139
|
+
"variant_title":"Sumatra",
|
140
|
+
"title":"Sumatra Latte",
|
141
|
+
"quantity":1,
|
142
|
+
"properties":[]
|
143
|
+
}
|
144
|
+
],
|
145
|
+
"total_price":18.00,
|
146
|
+
"shipping_address":{
|
147
|
+
"address1":"1933 Manning",
|
148
|
+
"address2":"204",
|
149
|
+
"city":"los angeles",
|
150
|
+
"province":"California",
|
151
|
+
"first_name":"mike",
|
152
|
+
"last_name":"flynn",
|
153
|
+
"zip":"90025",
|
154
|
+
"company":"bootstrap",
|
155
|
+
"phone":"3103103101",
|
156
|
+
"country":"United States"
|
157
|
+
},
|
158
|
+
"billing_address":{
|
159
|
+
"address1":"1933 Manning",
|
160
|
+
"address2":"204",
|
161
|
+
"city":"los angeles",
|
162
|
+
"province":"California",
|
163
|
+
"first_name":"mike",
|
164
|
+
"last_name":"flynn",
|
165
|
+
"zip":"90025",
|
166
|
+
"company":"bootstrap",
|
167
|
+
"phone":"3103103101",
|
168
|
+
"country":"United States"
|
169
|
+
}
|
170
|
+
},
|
171
|
+
"webhook":
|
172
|
+
{
|
173
|
+
"id":6,
|
174
|
+
"address":"https://request.in/foo",
|
175
|
+
"topic":"order/create"
|
176
|
+
},
|
177
|
+
"address":{
|
178
|
+
"id":3411137,
|
179
|
+
"address1":"1933 Manning",
|
180
|
+
"address2":"204",
|
181
|
+
"city":"los angeles",
|
182
|
+
"province":"California",
|
183
|
+
"first_name":"mike",
|
184
|
+
"last_name":"flynn",
|
185
|
+
"zip":"90025",
|
186
|
+
"company":"bootstrap",
|
187
|
+
"phone":"3103103101",
|
188
|
+
"country":"United States"
|
189
|
+
}
|
190
|
+
}
|
191
|
+
END
|
192
|
+
def meta=(meta)
|
193
|
+
@meta = meta
|
194
|
+
end
|
195
|
+
|
196
|
+
def meta
|
197
|
+
@meta ||= {}
|
198
|
+
end
|
199
|
+
|
200
|
+
private
|
201
|
+
|
202
|
+
def self.instance(response)
|
203
|
+
args = response[self::SINGLE]
|
204
|
+
args["meta"] = response["meta"]
|
205
|
+
new(args)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
module Recharge
|
210
|
+
module Persistable # :nodoc:
|
211
|
+
def save
|
212
|
+
data = to_h
|
213
|
+
data.delete("id")
|
214
|
+
|
215
|
+
if id
|
216
|
+
self.class.update(id, data)
|
217
|
+
else
|
218
|
+
self.id = self.class.create(data).id
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
class Address
|
224
|
+
PATH = "/addresses".freeze
|
225
|
+
SINGLE = "address".freeze
|
226
|
+
COLLECTION = "addresses".freeze
|
227
|
+
|
228
|
+
extend HTTPRequest::Get
|
229
|
+
extend HTTPRequest::Update
|
230
|
+
|
231
|
+
#
|
232
|
+
# Persist the updated address
|
233
|
+
#
|
234
|
+
# === Errors
|
235
|
+
#
|
236
|
+
# Recharge::ConnectionError, Recharge::RequestError
|
237
|
+
#
|
238
|
+
def save
|
239
|
+
data = to_h
|
240
|
+
data.delete("id")
|
241
|
+
self.class.update(id, data)
|
242
|
+
end
|
243
|
+
|
244
|
+
# Validate an address
|
245
|
+
#
|
246
|
+
# === Arguments
|
247
|
+
#
|
248
|
+
# [data (Hash)] Address to validate, see: https://developer.rechargepayments.com/?shell#validate-address
|
249
|
+
#
|
250
|
+
# === Returns
|
251
|
+
#
|
252
|
+
# [Hash] Validated and sometimes updated address
|
253
|
+
#
|
254
|
+
# === Errors
|
255
|
+
#
|
256
|
+
# Recharge::ConnectionError, Recharge::RequestError
|
257
|
+
#
|
258
|
+
# If the address is invalid a Recharge::RequestError is raised. The validation
|
259
|
+
# errors can be retrieved via Recharge::RequestError#errors
|
260
|
+
#
|
261
|
+
def self.validate(data)
|
262
|
+
POST(join("validate"), data)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
class Customer
|
267
|
+
PATH = "/customers".freeze
|
268
|
+
SINGLE = "customer".freeze
|
269
|
+
COLLECTION = "customers".freeze
|
270
|
+
|
271
|
+
extend HTTPRequest::Create
|
272
|
+
extend HTTPRequest::Get
|
273
|
+
extend HTTPRequest::Update
|
274
|
+
extend HTTPRequest::List
|
275
|
+
extend HTTPRequest::Count
|
276
|
+
|
277
|
+
include Persistable
|
278
|
+
|
279
|
+
# Retrieve all of a customer's addresses
|
280
|
+
#
|
281
|
+
# === Arguments
|
282
|
+
#
|
283
|
+
# [id (Fixnum)] Customer ID
|
284
|
+
#
|
285
|
+
# === Errors
|
286
|
+
#
|
287
|
+
# ConnectionError, RequestError
|
288
|
+
#
|
289
|
+
# === Returns
|
290
|
+
#
|
291
|
+
# [Array[Recharge::Address]] The customer's addresses
|
292
|
+
#
|
293
|
+
def self.addresses(id)
|
294
|
+
id_required!(id)
|
295
|
+
data = GET(join(id, Address::COLLECTION))
|
296
|
+
(data[Address::COLLECTION] || []).map do |d|
|
297
|
+
address = Address.new(d)
|
298
|
+
address.meta = data["meta"]
|
299
|
+
address
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
# Create a new address
|
304
|
+
#
|
305
|
+
# === Arguments
|
306
|
+
#
|
307
|
+
# [id (Fixnum)] Customer ID
|
308
|
+
# [address (Hash)] Address attributes, see: https://developer.rechargepayments.com/?shell#create-address
|
309
|
+
#
|
310
|
+
# === Returns
|
311
|
+
#
|
312
|
+
# [Recharge::Address] The created address
|
313
|
+
#
|
314
|
+
# === Errors
|
315
|
+
#
|
316
|
+
# Recharge::ConnectionError, Recharge::RequestError
|
317
|
+
#
|
318
|
+
def self.create_address(id, address)
|
319
|
+
id_required!(id)
|
320
|
+
data = POST(join(id, Address::COLLECTION), address)
|
321
|
+
address = Address.new(data[Address::SINGLE])
|
322
|
+
address.meta = data["meta"]
|
323
|
+
address
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
class Charge
|
328
|
+
PATH = "/charges".freeze
|
329
|
+
SINGLE = "charge".freeze
|
330
|
+
COLLECTION = "charges".freeze
|
331
|
+
|
332
|
+
extend HTTPRequest::Count
|
333
|
+
extend HTTPRequest::Get
|
334
|
+
extend HTTPRequest::List
|
335
|
+
|
336
|
+
def self.list(options = nil)
|
337
|
+
super(convert_date_params(options, :date_min, :date_max))
|
338
|
+
end
|
339
|
+
|
340
|
+
def self.change_next_charge_date(id, date)
|
341
|
+
path = join(id, "change_next_charge_date")
|
342
|
+
instance(POST(path, :next_charge_date => date_param(date)))
|
343
|
+
end
|
344
|
+
|
345
|
+
def self.skip(id, subscription_id)
|
346
|
+
path = join(id, "skip")
|
347
|
+
instance(POST(path, :subscription_id => subscription_id))
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
class Order
|
352
|
+
PATH = "/orders".freeze
|
353
|
+
SINGLE = "order".freeze
|
354
|
+
COLLECTION = "orders".freeze
|
355
|
+
|
356
|
+
extend HTTPRequest::Count
|
357
|
+
extend HTTPRequest::Get
|
358
|
+
extend HTTPRequest::List
|
359
|
+
|
360
|
+
def self.count(options = nil)
|
361
|
+
super(convert_date_params(options, :created_at_max, :created_at_min, :date_min, :date_max))
|
362
|
+
end
|
363
|
+
|
364
|
+
def self.change_date(id, date)
|
365
|
+
id_required!(id)
|
366
|
+
instance(POST(join(id, "change_date"), :shipping_date => date_param(date)))
|
367
|
+
end
|
368
|
+
|
369
|
+
def self.update_shopify_variant(id, old_variant_id, new_varient_id)
|
370
|
+
id_required!(id)
|
371
|
+
path = join(id, "update_shopify_variant", old_variant_id)
|
372
|
+
instance(POST(path, :new_shopify_variant_id => new_varient_id))
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
class Subscription
|
377
|
+
PATH = "/subscriptions".freeze
|
378
|
+
SINGLE = "subscription".freeze
|
379
|
+
COLLECTION = "subscriptions".freeze
|
380
|
+
|
381
|
+
extend HTTPRequest::Create
|
382
|
+
extend HTTPRequest::Get
|
383
|
+
extend HTTPRequest::Update
|
384
|
+
extend HTTPRequest::List
|
385
|
+
|
386
|
+
include Persistable
|
387
|
+
|
388
|
+
#
|
389
|
+
# Activate a subscription
|
390
|
+
#
|
391
|
+
# === Arguments
|
392
|
+
#
|
393
|
+
# [id (Integer)] ID of subscription to cancel
|
394
|
+
#
|
395
|
+
# === Returns
|
396
|
+
#
|
397
|
+
# [Recharge::Subscription] The activated subscription
|
398
|
+
#
|
399
|
+
# === Errors
|
400
|
+
#
|
401
|
+
# Recharge::ConnectionError, Recharge::RequestError
|
402
|
+
#
|
403
|
+
# If the subscription was already activated a Recharge::RequestError will be raised
|
404
|
+
#
|
405
|
+
def self.activate(id)
|
406
|
+
id_required!(id)
|
407
|
+
instance(POST(join(id, "activate"), :status => "active"))
|
408
|
+
end
|
409
|
+
|
410
|
+
#
|
411
|
+
# Cancel a subscription
|
412
|
+
#
|
413
|
+
# === Arguments
|
414
|
+
#
|
415
|
+
# [id (Integer)] ID of subscription to cancel
|
416
|
+
# [reason (String)] Reason for the cancellation
|
417
|
+
#
|
418
|
+
# === Returns
|
419
|
+
#
|
420
|
+
# [Recharge::Subscription] The canceled subscription
|
421
|
+
#
|
422
|
+
# === Errors
|
423
|
+
#
|
424
|
+
# Recharge::ConnectionError, Recharge::RequestError
|
425
|
+
#
|
426
|
+
# If the subscription was already canceled a Recharge::RequestError will be raised
|
427
|
+
#
|
428
|
+
def self.cancel(id, reason)
|
429
|
+
id_required!(id)
|
430
|
+
instance(POST(join(id, "cancel"), :cancellation_reason => reason))
|
431
|
+
end
|
432
|
+
|
433
|
+
def self.set_next_charge_date(id, date)
|
434
|
+
id_required!(id)
|
435
|
+
instance(POST(join(id, "set_next_charge_date"), :date => date_param(date)))
|
436
|
+
end
|
437
|
+
|
438
|
+
def self.list(options = nil)
|
439
|
+
#options[:status] = options[:status].upcase if options[:status]
|
440
|
+
super(convert_date_params(options, :created_at, :created_at_max, :updated_at, :updated_at_max))
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
class Webhook
|
445
|
+
PATH = "/webhooks".freeze
|
446
|
+
COLLECTION = "webhooks".freeze
|
447
|
+
SINGLE = "webhook".freeze
|
448
|
+
|
449
|
+
extend HTTPRequest::Create
|
450
|
+
extend HTTPRequest::Delete
|
451
|
+
extend HTTPRequest::Get
|
452
|
+
extend HTTPRequest::List
|
453
|
+
extend HTTPRequest::Update
|
454
|
+
|
455
|
+
include Persistable
|
456
|
+
|
457
|
+
def delete
|
458
|
+
self.class.delete(id)
|
459
|
+
true
|
460
|
+
end
|
461
|
+
end
|
462
|
+
end
|
@@ -0,0 +1,223 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "uri"
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
# For iso8601
|
6
|
+
require "date"
|
7
|
+
require "time"
|
8
|
+
|
9
|
+
module Recharge
|
10
|
+
module HTTPRequest # :nodoc:
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
def DELETE(path, data = {})
|
15
|
+
request(Net::HTTP::Delete.new(path), data)
|
16
|
+
end
|
17
|
+
|
18
|
+
def GET(path, data = {})
|
19
|
+
path += sprintf("?%s", URI.encode_www_form(data)) if data && data.any?
|
20
|
+
request(Net::HTTP::Get.new(path))
|
21
|
+
end
|
22
|
+
|
23
|
+
def POST(path, data = {})
|
24
|
+
request(Net::HTTP::Post.new(path), data)
|
25
|
+
end
|
26
|
+
|
27
|
+
def PUT(path, data = {})
|
28
|
+
request(Net::HTTP::Put.new(path), data)
|
29
|
+
end
|
30
|
+
|
31
|
+
def id_required!(id)
|
32
|
+
raise ArgumentError, "id required" if id.nil? || id.to_s.strip.empty?
|
33
|
+
end
|
34
|
+
|
35
|
+
def join(*parts)
|
36
|
+
parts.unshift(self::PATH).join("/")
|
37
|
+
end
|
38
|
+
|
39
|
+
def convert_date_params(options, *keys)
|
40
|
+
return unless options
|
41
|
+
|
42
|
+
options = options.dup
|
43
|
+
keys.each do |key|
|
44
|
+
options[key] = date_param(options[key]) if options.include?(key)
|
45
|
+
end
|
46
|
+
|
47
|
+
options
|
48
|
+
end
|
49
|
+
|
50
|
+
def date_param(date)
|
51
|
+
# ReCharge doesn't accept 8601, 500s on zone specifier
|
52
|
+
# date.respond_to?(:iso8601) ? date.iso8601 : date
|
53
|
+
date.respond_to?(:strftime) ? date.strftime("%Y-%m-%dT%H:%M:%S") : date
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def request(req, data = {})
|
59
|
+
req[TOKEN_HEADER] = ReCharge.api_key || ""
|
60
|
+
req["User-Agent"] = USER_AGENT
|
61
|
+
|
62
|
+
if req.request_body_permitted? && data && data.any?
|
63
|
+
req.body = data.to_json
|
64
|
+
req["Content-Type"] = "application/json"
|
65
|
+
end
|
66
|
+
|
67
|
+
connection.start do |http|
|
68
|
+
res = http.request(req)
|
69
|
+
data = res["Content-Type"] == "application/json" ? parse_json(res.body) : {}
|
70
|
+
data["meta"] = { "id" => res["X-Request-Id"], "limit" => res["X-Recharge-Limit"] }
|
71
|
+
|
72
|
+
return data if res.code[0] == "2" && !data["warning"] && !data["error"]
|
73
|
+
|
74
|
+
message = data["warning"] || data["error"] || "#{res.code} - #{res.message}"
|
75
|
+
raise RequestError.new(message, res.code, data["meta"], data["errors"])
|
76
|
+
end
|
77
|
+
rescue Net::ReadTimeout, IOError, SocketError, SystemCallError => e
|
78
|
+
raise ConnectionError, "connection failure: #{e}"
|
79
|
+
end
|
80
|
+
|
81
|
+
def connection
|
82
|
+
unless defined? @request
|
83
|
+
@request = Net::HTTP.new(ENDPOINT, PORT)
|
84
|
+
@request.use_ssl = true
|
85
|
+
end
|
86
|
+
|
87
|
+
if !Recharge.debug
|
88
|
+
@request.set_debug_output(nil)
|
89
|
+
else
|
90
|
+
@request.set_debug_output(
|
91
|
+
Recharge.debug.is_a?(IO) ? Recharge.debug : $stderr
|
92
|
+
)
|
93
|
+
end
|
94
|
+
|
95
|
+
@request
|
96
|
+
end
|
97
|
+
|
98
|
+
def parse_json(s)
|
99
|
+
JSON.parse(s)
|
100
|
+
rescue JSON::ParserError => e
|
101
|
+
raise Error, "failed to parse JSON response: #{e}"
|
102
|
+
end
|
103
|
+
|
104
|
+
#
|
105
|
+
# Make a count request to the included/extended class' endpoint
|
106
|
+
#
|
107
|
+
# === Arguments
|
108
|
+
#
|
109
|
+
# [options (Hash)] Optional arguments to filter the count on.
|
110
|
+
#
|
111
|
+
# See the appropriate count call in {ReCharge's documentation}[https://developer.rechargepayments.com/] for valid options.
|
112
|
+
#
|
113
|
+
# === Returns
|
114
|
+
#
|
115
|
+
# +Fixnum+ of the resulting count
|
116
|
+
#
|
117
|
+
# === Errors
|
118
|
+
#
|
119
|
+
# Recharge::ConnectionError, Recharge::RequestError
|
120
|
+
#
|
121
|
+
module Count
|
122
|
+
include HTTPRequest
|
123
|
+
|
124
|
+
def count(options = nil)
|
125
|
+
GET(join("count"), options)["count"]
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
#
|
130
|
+
# Create an new record for the included/extended entity
|
131
|
+
#
|
132
|
+
# === Arguments
|
133
|
+
#
|
134
|
+
# [data (Hash)] New record's attributes
|
135
|
+
#
|
136
|
+
# See the appropriate create call in {ReCharge's documentation}[https://developer.rechargepayments.com/] for valid attributes
|
137
|
+
#
|
138
|
+
# === Returns
|
139
|
+
#
|
140
|
+
# An instance of the created entity
|
141
|
+
#
|
142
|
+
# === Errors
|
143
|
+
#
|
144
|
+
# Recharge::ConnectionError, Recharge::RequestError
|
145
|
+
#
|
146
|
+
module Create
|
147
|
+
include HTTPRequest
|
148
|
+
|
149
|
+
def create(data)
|
150
|
+
new(POST(self::PATH, data)[self::SINGLE])
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
#
|
155
|
+
# Delete a record for included/extended entity
|
156
|
+
#
|
157
|
+
# === Arguments
|
158
|
+
#
|
159
|
+
# [id (Fixnum)] ID of the record to delete
|
160
|
+
#
|
161
|
+
# === Returns
|
162
|
+
#
|
163
|
+
# An instance of the deleted entity
|
164
|
+
#
|
165
|
+
# === Errors
|
166
|
+
#
|
167
|
+
# Recharge::ConnectionError, Recharge::RequestError
|
168
|
+
#
|
169
|
+
module Delete
|
170
|
+
include HTTPRequest
|
171
|
+
|
172
|
+
def delete(id)
|
173
|
+
id_required!(id)
|
174
|
+
DELETE(join(id))
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
module Get
|
179
|
+
include HTTPRequest
|
180
|
+
|
181
|
+
def get(id)
|
182
|
+
id_required!(id)
|
183
|
+
new(GET(join(id))[self::SINGLE])
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
#
|
188
|
+
# Retrieve a page of records for the included/extended class'
|
189
|
+
#
|
190
|
+
# === Arguments
|
191
|
+
#
|
192
|
+
# [options (Hash)] Optional arguments to filter the result set on.
|
193
|
+
#
|
194
|
+
# In most cases +:page+ and +:limit+ are accepted but see
|
195
|
+
# the appropriate call in {ReCharge's documentation}[https://developer.rechargepayments.com/] for valid options.
|
196
|
+
#
|
197
|
+
# === Returns
|
198
|
+
#
|
199
|
+
# +Array+ of record instances
|
200
|
+
#
|
201
|
+
# === Errors
|
202
|
+
#
|
203
|
+
# Recharge::ConnectionError, Recharge::RequestError
|
204
|
+
#
|
205
|
+
module List
|
206
|
+
include HTTPRequest
|
207
|
+
|
208
|
+
def list(options = nil)
|
209
|
+
data = GET(self::PATH, options)
|
210
|
+
(data[self::COLLECTION] || []).map { |d| new(d.merge("meta" => data["meta"])) }
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
module Update
|
215
|
+
include HTTPRequest
|
216
|
+
|
217
|
+
def update(id, data)
|
218
|
+
id_required!(id)
|
219
|
+
new(PUT(join(id), data)[self::SINGLE])
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require "rake"
|
2
|
+
require "recharge"
|
3
|
+
|
4
|
+
namespace :recharge do
|
5
|
+
namespace :hooks do
|
6
|
+
task :_setup_recharge do
|
7
|
+
abort "RECHARGE_API_KEY required" unless ENV["RECHARGE_API_KEY"]
|
8
|
+
ReCharge.api_key = ENV["RECHARGE_API_KEY"]
|
9
|
+
end
|
10
|
+
|
11
|
+
desc "List webhooks for RECHARGE_API_KEY"
|
12
|
+
task :list => :_setup_recharge do
|
13
|
+
format = "%-5s %-25s %-80s\n"
|
14
|
+
printf format, "ID", "Hook", "URL"
|
15
|
+
|
16
|
+
Recharge::Webhook.list.each do |hook|
|
17
|
+
printf format, hook.id, hook.topic, hook.address
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "Delete webhooks for RECHARGE_API_KEY"
|
22
|
+
task :delete_all => :_setup_recharge do
|
23
|
+
Recharge::Webhook.list.each { |hook| hook.class.delete(hook.id) }
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "Delete the webhooks given by the ID(s) in ID for RECHARGE_API_KEY"
|
27
|
+
task :delete => :_setup_recharge do
|
28
|
+
ids = ENV["ID"].to_s.strip.split(",")
|
29
|
+
abort "ID required" unless ids.any?
|
30
|
+
|
31
|
+
ids.each do |id|
|
32
|
+
puts "Deleting webhook #{id}"
|
33
|
+
Recharge::Webhook.delete(id)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
desc "Create webhook HOOK to be sent to CALLBACK for RECHARGE_API_KEY"
|
38
|
+
task :create => :_setup_recharge do
|
39
|
+
known_hooks = %w[
|
40
|
+
subscription/created
|
41
|
+
subscription/updated
|
42
|
+
subscription/activated
|
43
|
+
subscription/cancelled
|
44
|
+
customer/created
|
45
|
+
customer/updated
|
46
|
+
order/created
|
47
|
+
charge/created
|
48
|
+
charge/paid
|
49
|
+
]
|
50
|
+
|
51
|
+
abort "CALLBACK required" unless ENV["CALLBACK"]
|
52
|
+
abort "HOOK required" unless ENV["HOOK"]
|
53
|
+
abort "unknown hook #{ENV["HOOK"]}" unless known_hooks.include?(ENV["HOOK"])
|
54
|
+
|
55
|
+
puts "Creating webhook #{ENV["HOOK"]} for #{ENV["CALLBACK"]}"
|
56
|
+
|
57
|
+
hook = Recharge::Webhook.create(
|
58
|
+
:topic => ENV["HOOK"],
|
59
|
+
:address => ENV["CALLBACK"]
|
60
|
+
)
|
61
|
+
|
62
|
+
puts "Created hook ##{hook.id}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "recharge/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "recharge-api"
|
8
|
+
spec.version = Recharge::VERSION
|
9
|
+
spec.authors = ["Skye Shaw"]
|
10
|
+
spec.email = ["skye.shaw@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Client for ReCharge Payments API}
|
13
|
+
spec.description = %q{Client for ReCharge Payments recurring payments API for Shopify}
|
14
|
+
spec.homepage = "https://github.com/ScreenStaring/recharge-api"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_dependency "class2", "~> 0.3.0"
|
23
|
+
spec.add_development_dependency "webmock", "~> 3.0"
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.12"
|
25
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
26
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: recharge-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Skye Shaw
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-12-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: class2
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.3.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.3.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: webmock
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.12'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.12'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.0'
|
83
|
+
description: Client for ReCharge Payments recurring payments API for Shopify
|
84
|
+
email:
|
85
|
+
- skye.shaw@gmail.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- ".travis.yml"
|
92
|
+
- Gemfile
|
93
|
+
- LICENSE.txt
|
94
|
+
- README.md
|
95
|
+
- Rakefile
|
96
|
+
- lib/recharge-api.rb
|
97
|
+
- lib/recharge.rb
|
98
|
+
- lib/recharge/classes.rb
|
99
|
+
- lib/recharge/http_request.rb
|
100
|
+
- lib/recharge/tasks.rb
|
101
|
+
- lib/recharge/version.rb
|
102
|
+
- recharge-api.gemspec
|
103
|
+
homepage: https://github.com/ScreenStaring/recharge-api
|
104
|
+
licenses:
|
105
|
+
- MIT
|
106
|
+
metadata: {}
|
107
|
+
post_install_message:
|
108
|
+
rdoc_options: []
|
109
|
+
require_paths:
|
110
|
+
- lib
|
111
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
121
|
+
requirements: []
|
122
|
+
rubyforge_project:
|
123
|
+
rubygems_version: 2.6.14
|
124
|
+
signing_key:
|
125
|
+
specification_version: 4
|
126
|
+
summary: Client for ReCharge Payments API
|
127
|
+
test_files: []
|