Recharge 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/happymapper/attribute.rb +3 -0
- data/lib/happymapper/element.rb +3 -0
- data/lib/happymapper/item.rb +179 -0
- data/lib/happymapper/version.rb +3 -0
- data/lib/happymapper.rb +315 -0
- data/lib/recharge/base.rb +45 -0
- data/lib/recharge/charge.rb +45 -0
- data/lib/recharge/client.rb +58 -0
- data/lib/recharge/customer.rb +53 -0
- data/lib/recharge/paymethod.rb +23 -0
- data/lib/recharge/product.rb +37 -0
- data/lib/recharge/response.rb +34 -0
- data/lib/recharge/transaction.rb +31 -0
- data/lib/recharge.rb +59 -0
- data/lib/test.rb +520 -0
- metadata +76 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
module Recharge
|
2
|
+
class PayMethod
|
3
|
+
include HappyMapper
|
4
|
+
|
5
|
+
tag 'payMethod'
|
6
|
+
|
7
|
+
element :id, String
|
8
|
+
element :alias, String
|
9
|
+
element :cardType, String
|
10
|
+
element :last4, String
|
11
|
+
element :expDate, String
|
12
|
+
element :nameOnCard, String
|
13
|
+
element :error, String
|
14
|
+
|
15
|
+
def self.create (attributes = {})
|
16
|
+
responseXML = Recharge::Base.post('paymethods', attributes)
|
17
|
+
parse(responseXML.to_s)
|
18
|
+
end
|
19
|
+
def self.destroy (id)
|
20
|
+
responseXML = Recharge::Base.delete('paymethods/'+id)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Recharge
|
2
|
+
class Product
|
3
|
+
include HappyMapper
|
4
|
+
|
5
|
+
tag 'product'
|
6
|
+
|
7
|
+
element :id, String
|
8
|
+
element :name, String
|
9
|
+
element :setupFee, String
|
10
|
+
element :price, String
|
11
|
+
element :intervalValue, String
|
12
|
+
element :intervalUnit, String
|
13
|
+
|
14
|
+
def initialize(id='')
|
15
|
+
@id = id
|
16
|
+
end
|
17
|
+
def self.find_all
|
18
|
+
responseXML = Recharge::Base.get('products')
|
19
|
+
parse(responseXML.to_s)
|
20
|
+
end
|
21
|
+
def self.find (id)
|
22
|
+
responseXML = Recharge::Base.get('products/'+id)
|
23
|
+
parse(responseXML.to_s)
|
24
|
+
end
|
25
|
+
def self.create (attributes = {})
|
26
|
+
responseXML = Recharge::Base.post('products', attributes)
|
27
|
+
parse(responseXML.to_s)
|
28
|
+
end
|
29
|
+
def update (attributes = {})
|
30
|
+
responseXML = Recharge::Base.post('products/'+self.id, attributes)
|
31
|
+
Product.parse(responseXML.to_s)
|
32
|
+
end
|
33
|
+
def destroy (attributes = {})
|
34
|
+
responseXML = Recharge::Base.delete('products/'+self.id)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Response
|
2
|
+
def initialize(code, body)
|
3
|
+
@code = code
|
4
|
+
@body = body
|
5
|
+
end
|
6
|
+
def code
|
7
|
+
@code
|
8
|
+
end
|
9
|
+
def body
|
10
|
+
@body
|
11
|
+
end
|
12
|
+
|
13
|
+
class NotFound < StandardError
|
14
|
+
end
|
15
|
+
|
16
|
+
class BadRequest < StandardError
|
17
|
+
end
|
18
|
+
|
19
|
+
class NotAuthorized < StandardError
|
20
|
+
end
|
21
|
+
|
22
|
+
def assertValidResponse
|
23
|
+
case @code.to_i
|
24
|
+
when 200
|
25
|
+
return
|
26
|
+
when 400
|
27
|
+
raise BadRequest, Recharge::Base.returnErrorXML(@body)
|
28
|
+
when 401
|
29
|
+
raise NotAuthorized, Recharge::Base.returnErrorXML(@body)
|
30
|
+
when 404
|
31
|
+
raise NotFound, Recharge::Base.returnErrorXML(@body)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Recharge
|
2
|
+
class Transaction
|
3
|
+
include HappyMapper
|
4
|
+
|
5
|
+
tag 'transaction'
|
6
|
+
|
7
|
+
element :responseDescription, String
|
8
|
+
element :transactionID, String
|
9
|
+
element :amount, String
|
10
|
+
element :cardType, String
|
11
|
+
element :maskedAcctNum, String
|
12
|
+
element :expDate, String
|
13
|
+
element :processorResponse, String
|
14
|
+
element :batchNum, String
|
15
|
+
element :batchAmount, String
|
16
|
+
element :approvalCode, String
|
17
|
+
|
18
|
+
def self.purchase (attributes = {})
|
19
|
+
responseXML = Recharge::Base.post('purchase', attributes)
|
20
|
+
parse(responseXML.to_s)
|
21
|
+
end
|
22
|
+
def self.refund (attributes = {})
|
23
|
+
responseXML = Recharge::Base.post('return', attributes)
|
24
|
+
parse(responseXML.to_s)
|
25
|
+
end
|
26
|
+
def self.void (attributes = {})
|
27
|
+
responseXML = Recharge::Base.post('void', attributes)
|
28
|
+
parse(responseXML.to_s)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/recharge.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
module Recharge
|
2
|
+
require File.dirname(__FILE__) + '/happymapper'
|
3
|
+
|
4
|
+
require File.dirname(__FILE__) + '/recharge/base'
|
5
|
+
require File.dirname(__FILE__) + '/recharge/paymethod'
|
6
|
+
require File.dirname(__FILE__) + '/recharge/charge'
|
7
|
+
require File.dirname(__FILE__) + '/recharge/customer'
|
8
|
+
require File.dirname(__FILE__) + '/recharge/product'
|
9
|
+
require File.dirname(__FILE__) + '/recharge/transaction'
|
10
|
+
require File.dirname(__FILE__) + '/recharge/client'
|
11
|
+
require File.dirname(__FILE__) + '/recharge/response'
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def api_key
|
15
|
+
defined? @api_key and @api_key
|
16
|
+
end
|
17
|
+
attr_writer :api_key
|
18
|
+
end
|
19
|
+
|
20
|
+
def get(uri)
|
21
|
+
client = Client.new()
|
22
|
+
return client.request('GET', uri)
|
23
|
+
end
|
24
|
+
|
25
|
+
def post(uri, data=nil)
|
26
|
+
client = Client.new()
|
27
|
+
return client.request('POST', uri, data)
|
28
|
+
end
|
29
|
+
|
30
|
+
def delete(uri)
|
31
|
+
client = Client.new()
|
32
|
+
return client.request('DELETE', uri)
|
33
|
+
end
|
34
|
+
|
35
|
+
def returnImportantXML(data)
|
36
|
+
require "rexml/document"
|
37
|
+
doc = REXML::Document.new(data)
|
38
|
+
|
39
|
+
if doc.elements[1].elements[3].length == 1
|
40
|
+
return doc.elements[1].elements[3].elements[1]
|
41
|
+
else
|
42
|
+
return doc.elements[1].elements[3]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def returnErrorXML(data)
|
47
|
+
require "rexml/document"
|
48
|
+
doc = REXML::Document.new(data)
|
49
|
+
|
50
|
+
doc.elements["/response/result/resultDescription"].text
|
51
|
+
end
|
52
|
+
|
53
|
+
def returnStatusXML(data)
|
54
|
+
require "rexml/document"
|
55
|
+
doc = REXML::Document.new(data)
|
56
|
+
|
57
|
+
doc.elements["/response/result/resultDescription"]
|
58
|
+
end
|
59
|
+
end
|
data/lib/test.rb
ADDED
@@ -0,0 +1,520 @@
|
|
1
|
+
module Recharge
|
2
|
+
require 'happymapper'
|
3
|
+
|
4
|
+
class << self
|
5
|
+
def api_key
|
6
|
+
defined? @api_key and @api_key
|
7
|
+
end
|
8
|
+
attr_writer :api_key
|
9
|
+
end
|
10
|
+
|
11
|
+
class PayMethod
|
12
|
+
include HappyMapper
|
13
|
+
|
14
|
+
tag 'payMethod'
|
15
|
+
|
16
|
+
element :id, String
|
17
|
+
element :alias, String
|
18
|
+
element :cardType, String
|
19
|
+
element :last4, String
|
20
|
+
element :expDate, String
|
21
|
+
element :nameOnCard, String
|
22
|
+
end
|
23
|
+
|
24
|
+
class Customer
|
25
|
+
include HappyMapper
|
26
|
+
|
27
|
+
tag 'customer'
|
28
|
+
|
29
|
+
element :id, String
|
30
|
+
element :refID, String
|
31
|
+
element :firstName, String
|
32
|
+
element :lastName, String
|
33
|
+
element :email, String
|
34
|
+
element :company, String
|
35
|
+
element :phone, String
|
36
|
+
element :billingAddress1, String
|
37
|
+
element :billingAddress2, String
|
38
|
+
element :billingCity, String
|
39
|
+
element :billingState, String
|
40
|
+
element :billingZIP, String
|
41
|
+
element :shippingAddress1, String
|
42
|
+
element :shippingAddress2, String
|
43
|
+
element :shippingCity, String
|
44
|
+
element :shippingState, String
|
45
|
+
element :shippingZIP, String
|
46
|
+
element :emailOption, String
|
47
|
+
element :signupDate, String
|
48
|
+
|
49
|
+
has_many :payMethods, PayMethod
|
50
|
+
|
51
|
+
def initialize(id='')
|
52
|
+
@id = id
|
53
|
+
end
|
54
|
+
def self.find_all
|
55
|
+
responseXML = get('customers')
|
56
|
+
parse(responseXML.to_s)
|
57
|
+
end
|
58
|
+
def self.find (id)
|
59
|
+
responseXML = get('customers/'+id)
|
60
|
+
parse(responseXML.to_s)
|
61
|
+
end
|
62
|
+
def self.create (attributes = {})
|
63
|
+
responseXML = post('customers', attributes)
|
64
|
+
parse(responseXML.to_s)
|
65
|
+
end
|
66
|
+
def update (attributes = {})
|
67
|
+
responseXML = post('customers/'+self.id, attributes)
|
68
|
+
Customer.parse(responseXML.to_s)
|
69
|
+
end
|
70
|
+
def destroy (attributes = {})
|
71
|
+
responseXML = delete('customers/'+self.id)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class Product
|
76
|
+
include HappyMapper
|
77
|
+
|
78
|
+
tag 'product'
|
79
|
+
|
80
|
+
element :id, String
|
81
|
+
element :name, String
|
82
|
+
element :setupFee, String
|
83
|
+
element :price, String
|
84
|
+
element :intervalValue, String
|
85
|
+
element :intervalUnit, String
|
86
|
+
|
87
|
+
def initialize(id='')
|
88
|
+
@id = id
|
89
|
+
end
|
90
|
+
def self.find_all
|
91
|
+
responseXML = get('products')
|
92
|
+
parse(responseXML.to_s)
|
93
|
+
end
|
94
|
+
def self.find (id)
|
95
|
+
responseXML = get('products/'+id)
|
96
|
+
parse(responseXML.to_s)
|
97
|
+
end
|
98
|
+
def self.create (attributes = {})
|
99
|
+
responseXML = post('products', attributes)
|
100
|
+
parse(responseXML.to_s)
|
101
|
+
end
|
102
|
+
def update (attributes = {})
|
103
|
+
responseXML = post('products/'+self.id, attributes)
|
104
|
+
Product.parse(responseXML.to_s)
|
105
|
+
end
|
106
|
+
def destroy (attributes = {})
|
107
|
+
responseXML = delete('products/'+self.id)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
|
128
|
+
|
129
|
+
|
130
|
+
|
131
|
+
|
132
|
+
|
133
|
+
|
134
|
+
|
135
|
+
|
136
|
+
|
137
|
+
|
138
|
+
|
139
|
+
|
140
|
+
|
141
|
+
|
142
|
+
|
143
|
+
|
144
|
+
|
145
|
+
|
146
|
+
|
147
|
+
|
148
|
+
|
149
|
+
|
150
|
+
|
151
|
+
|
152
|
+
def get(uri)
|
153
|
+
client = Client.new()
|
154
|
+
return client.request('GET', uri)
|
155
|
+
end
|
156
|
+
|
157
|
+
def post(uri, data=nil)
|
158
|
+
client = Client.new()
|
159
|
+
return client.request('POST', uri, data)
|
160
|
+
end
|
161
|
+
|
162
|
+
def delete(uri)
|
163
|
+
client = Client.new()
|
164
|
+
return client.request('DELETE', uri)
|
165
|
+
end
|
166
|
+
|
167
|
+
def returnImportantXML(data)
|
168
|
+
require "rexml/document"
|
169
|
+
doc = REXML::Document.new(data)
|
170
|
+
|
171
|
+
if doc.elements[1].elements[3].length == 1
|
172
|
+
return doc.elements[1].elements[3].elements[1]
|
173
|
+
else
|
174
|
+
return doc.elements[1].elements[3]
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def returnErrorXML(data)
|
179
|
+
require "rexml/document"
|
180
|
+
doc = REXML::Document.new(data)
|
181
|
+
|
182
|
+
doc.elements["/response/result/resultDescription"].text
|
183
|
+
end
|
184
|
+
|
185
|
+
def returnStatusXML(data)
|
186
|
+
require "rexml/document"
|
187
|
+
doc = REXML::Document.new(data)
|
188
|
+
|
189
|
+
doc.elements["/response/result/resultDescription"]
|
190
|
+
end
|
191
|
+
|
192
|
+
|
193
|
+
|
194
|
+
|
195
|
+
|
196
|
+
|
197
|
+
|
198
|
+
|
199
|
+
|
200
|
+
|
201
|
+
|
202
|
+
|
203
|
+
|
204
|
+
|
205
|
+
|
206
|
+
|
207
|
+
|
208
|
+
|
209
|
+
|
210
|
+
|
211
|
+
|
212
|
+
|
213
|
+
|
214
|
+
|
215
|
+
|
216
|
+
|
217
|
+
|
218
|
+
|
219
|
+
|
220
|
+
|
221
|
+
|
222
|
+
|
223
|
+
|
224
|
+
|
225
|
+
|
226
|
+
|
227
|
+
|
228
|
+
|
229
|
+
|
230
|
+
class Client
|
231
|
+
|
232
|
+
def baseURL
|
233
|
+
"https://www.rechargebilling.com/API/v2/"
|
234
|
+
end
|
235
|
+
|
236
|
+
def request(method, uri, data=nil)
|
237
|
+
response = sendRequest(method, uri, data)
|
238
|
+
response.assertValidResponse
|
239
|
+
if response.code.to_i == 200
|
240
|
+
if method != "DELETE"
|
241
|
+
returnImportantXML(response.body)
|
242
|
+
else
|
243
|
+
returnStatusXML(response.body)
|
244
|
+
end
|
245
|
+
else
|
246
|
+
returnErrorXML(response.body)
|
247
|
+
end
|
248
|
+
|
249
|
+
end
|
250
|
+
|
251
|
+
def sendRequest(method, uri, data=nil)
|
252
|
+
require "net/https"
|
253
|
+
require "uri"
|
254
|
+
|
255
|
+
if !Recharge.api_key
|
256
|
+
puts "no api key"
|
257
|
+
return
|
258
|
+
end
|
259
|
+
|
260
|
+
uri = baseURL+uri
|
261
|
+
uri = URI.parse(uri)
|
262
|
+
|
263
|
+
if method == "GET"
|
264
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
265
|
+
end
|
266
|
+
|
267
|
+
if method == "POST"
|
268
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
269
|
+
request.set_form_data(data)
|
270
|
+
end
|
271
|
+
|
272
|
+
if method == "DELETE"
|
273
|
+
request = Net::HTTP::Delete.new(uri.request_uri)
|
274
|
+
end
|
275
|
+
|
276
|
+
request.basic_auth(Recharge.api_key, "")
|
277
|
+
|
278
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
279
|
+
http.use_ssl = true
|
280
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
281
|
+
|
282
|
+
response = http.request(request)
|
283
|
+
|
284
|
+
return Response.new(response.code, response.body)
|
285
|
+
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
|
290
|
+
|
291
|
+
|
292
|
+
|
293
|
+
|
294
|
+
|
295
|
+
|
296
|
+
|
297
|
+
|
298
|
+
|
299
|
+
|
300
|
+
|
301
|
+
|
302
|
+
|
303
|
+
|
304
|
+
|
305
|
+
|
306
|
+
|
307
|
+
|
308
|
+
|
309
|
+
|
310
|
+
|
311
|
+
|
312
|
+
|
313
|
+
|
314
|
+
|
315
|
+
|
316
|
+
|
317
|
+
|
318
|
+
|
319
|
+
|
320
|
+
|
321
|
+
|
322
|
+
|
323
|
+
|
324
|
+
|
325
|
+
|
326
|
+
|
327
|
+
|
328
|
+
class Response
|
329
|
+
def initialize(code, body)
|
330
|
+
@code = code
|
331
|
+
@body = body
|
332
|
+
end
|
333
|
+
def code
|
334
|
+
@code
|
335
|
+
end
|
336
|
+
def body
|
337
|
+
@body
|
338
|
+
end
|
339
|
+
|
340
|
+
class NotFound < StandardError
|
341
|
+
end
|
342
|
+
|
343
|
+
class BadRequest < StandardError
|
344
|
+
end
|
345
|
+
|
346
|
+
def assertValidResponse
|
347
|
+
case @code.to_i
|
348
|
+
when 200
|
349
|
+
return
|
350
|
+
when 400
|
351
|
+
raise NotFound, returnErrorXML(@body)
|
352
|
+
when 404
|
353
|
+
raise NotFound, returnErrorXML(@body)
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
|
359
|
+
|
360
|
+
|
361
|
+
|
362
|
+
|
363
|
+
|
364
|
+
|
365
|
+
|
366
|
+
|
367
|
+
|
368
|
+
|
369
|
+
|
370
|
+
|
371
|
+
|
372
|
+
|
373
|
+
|
374
|
+
|
375
|
+
|
376
|
+
|
377
|
+
|
378
|
+
|
379
|
+
|
380
|
+
|
381
|
+
|
382
|
+
|
383
|
+
|
384
|
+
|
385
|
+
|
386
|
+
|
387
|
+
|
388
|
+
|
389
|
+
|
390
|
+
|
391
|
+
|
392
|
+
|
393
|
+
|
394
|
+
|
395
|
+
|
396
|
+
|
397
|
+
|
398
|
+
|
399
|
+
|
400
|
+
|
401
|
+
|
402
|
+
|
403
|
+
|
404
|
+
|
405
|
+
|
406
|
+
|
407
|
+
|
408
|
+
|
409
|
+
|
410
|
+
|
411
|
+
|
412
|
+
|
413
|
+
|
414
|
+
|
415
|
+
|
416
|
+
|
417
|
+
|
418
|
+
|
419
|
+
|
420
|
+
|
421
|
+
|
422
|
+
|
423
|
+
|
424
|
+
|
425
|
+
|
426
|
+
|
427
|
+
|
428
|
+
|
429
|
+
|
430
|
+
|
431
|
+
|
432
|
+
|
433
|
+
|
434
|
+
|
435
|
+
|
436
|
+
|
437
|
+
|
438
|
+
Recharge.api_key = "92ec3e4d8b623dd9baaaf1575b7c557cd113e3e8"
|
439
|
+
|
440
|
+
customerID = ""
|
441
|
+
|
442
|
+
puts "Find All Customers"
|
443
|
+
|
444
|
+
begin
|
445
|
+
Recharge::Customer.find_all.each do |customer|
|
446
|
+
puts "id: #{customer.id}"
|
447
|
+
puts "name: #{customer.firstName} #{customer.lastName}"
|
448
|
+
puts "email: #{customer.email}"
|
449
|
+
|
450
|
+
customerID = customer.id
|
451
|
+
|
452
|
+
customer.payMethods.each do |paymethod|
|
453
|
+
puts ">> paymethod id: #{paymethod.id}"
|
454
|
+
puts ">> card number: #{paymethod.cardType} ****#{paymethod.last4}"
|
455
|
+
end
|
456
|
+
end
|
457
|
+
rescue Exception => e
|
458
|
+
puts ">> error #{e.message}"
|
459
|
+
end
|
460
|
+
|
461
|
+
|
462
|
+
|
463
|
+
puts "", "Find Individual Customers"
|
464
|
+
|
465
|
+
begin
|
466
|
+
customer = Recharge::Customer.find(customerID)
|
467
|
+
|
468
|
+
puts "id: #{customer.id}"
|
469
|
+
puts "name: #{customer.firstName} #{customer.lastName}"
|
470
|
+
puts "email: #{customer.email}"
|
471
|
+
|
472
|
+
customer.payMethods.each do |paymethod|
|
473
|
+
puts ">> paymethod id: #{paymethod.id}"
|
474
|
+
puts ">> card number: #{paymethod.cardType} ****#{paymethod.last4}"
|
475
|
+
end
|
476
|
+
rescue Exception => e
|
477
|
+
puts ">> error #{e.message}"
|
478
|
+
end
|
479
|
+
|
480
|
+
|
481
|
+
|
482
|
+
puts "", "Create New Customer"
|
483
|
+
|
484
|
+
begin
|
485
|
+
customer = Recharge::Customer.create(
|
486
|
+
:firstName => "Eric",
|
487
|
+
:lastName=> "Cardin",
|
488
|
+
:email=> "email@rechargebilling.com",
|
489
|
+
:bad=> "bad"
|
490
|
+
)
|
491
|
+
customerID = customer.id
|
492
|
+
p customer
|
493
|
+
rescue Exception => e
|
494
|
+
puts ">> error #{e.message}"
|
495
|
+
end
|
496
|
+
|
497
|
+
|
498
|
+
|
499
|
+
puts "", "Update Customer"
|
500
|
+
|
501
|
+
begin
|
502
|
+
customer = Recharge::Customer.find(customerID)
|
503
|
+
customer.update(
|
504
|
+
:refID=> Time.now.to_i
|
505
|
+
)
|
506
|
+
p customer
|
507
|
+
rescue Exception => e
|
508
|
+
puts ">> error #{e.message}"
|
509
|
+
end
|
510
|
+
|
511
|
+
|
512
|
+
|
513
|
+
puts "", "Delete Customer"
|
514
|
+
|
515
|
+
begin
|
516
|
+
customer = Recharge::Customer.find(customerID)
|
517
|
+
customer.destroy
|
518
|
+
rescue Exception => e
|
519
|
+
puts ">> error #{e.message}"
|
520
|
+
end
|