voucherify 0.8.0 → 0.8.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ac6bfd1ead5ca241b7d5d62d1e0a18b2b34f6269
4
- data.tar.gz: 334f47cdd657274805b1506b794f7d515df6f982
3
+ metadata.gz: 6fe764e120a047b704074d28bb3557e97412e421
4
+ data.tar.gz: e79ac6e9a61e40746d9fcd39ca7a51af40b88a00
5
5
  SHA512:
6
- metadata.gz: 588e0ab94075bebf6cf57feb95528f9ef8d7cc048d0e7a61f8c2864e319498d63b44dc1ec8908da60f01678d21e146c69f633e315c6d74e46c7a1d9bcd7c54fe
7
- data.tar.gz: 7e2ca93824f47367b5cdeeece4dabe3d1681e58d3364324ea611c172ac476c33952315114a367a6604fd6352f5c5136e01a7d2a9605fade26b9d88dcddee6034
6
+ metadata.gz: d6ded6e46fcf6e24e021fac76c04e13e2ddd6b3264556b57a05f5d87d1604116daa1207e7d4e66d8ac1139103fb9bc67974136f7e7b6d391a13e002a3d74c98d
7
+ data.tar.gz: 92b7bcb922ba68e442d62b285fc16710a689491e6ac11fb0c08b4f91a18a6c2a5982a1aac4c5dfd9727f09f498cc8eef14eb8771af2834240049f93e8d2c7e1f
data/README.md CHANGED
@@ -1,12 +1,10 @@
1
1
  ## Voucherify Ruby SDK
2
2
 
3
- [Voucherify](http://voucherify.io?utm_source=github&utm_medium=sdk&utm_campaign=acq) has a new platform that will help your team automate voucher campaigns. It does this by providing composable API and the marketer-friendly interface that increases teams' productivity:
3
+ [Voucherify](http://voucherify.io?utm_source=github&utm_medium=sdk&utm_campaign=acq) is an API-first platform for software developers who are dissatisfied with high-maintenance custom coupon software. Our product is a coupon infrastructure through API that provides a quicker way to build coupon generation, distribution and tracking. Unlike legacy coupon software we have:
4
4
 
5
- - **roll-out thousands** of vouchers **in minutes** instead of weeks,
6
- - **check status** or disable **every single** promo code in real time,
7
- - **track redemption** history and build reports on the fly.
8
-
9
- Here you can find a library that makes it easier to integrate Voucherify with your Ruby server.
5
+ * an API-first SaaS platform that enables customisation of every aspect of coupon campaigns
6
+ * a management console that helps cut down maintenance and reporting overhead
7
+ * an infrastructure to scale up coupon activity in no time
10
8
 
11
9
  Full documentation is located at [voucherify.readme.io](https://voucherify.readme.io).
12
10
 
@@ -85,47 +83,77 @@ voucherify.list({ limit: 10, skip: 20, category: "API Test" })
85
83
  Result:
86
84
  ```json
87
85
  [{
88
- "code": "9mYBpIk",
89
- "campaign": null,
90
- "category": "API Test",
91
- "type": "DISCOUNT_VOUCHER",
92
- "discount": {
93
- "type": "AMOUNT",
94
- "amount_off": 400
95
- },
96
- "start_date": "2016-03-01T12:00:00Z",
97
- "expiration_date": null,
98
- "redemption": {
99
- "quantity": 1,
100
- "redeemed_quantity": 0,
101
- "redemption_entries": []
102
- },
103
- "active": true,
104
- "additional_info": null,
105
- "metadata": null
106
- },
107
- {
108
- "code": "AzTsIH",
109
- "campaign": null,
110
- "category": "API Test",
111
- "type": "GIFT_VOUCHER",
112
- "gift": {
113
- "amount": 5000
114
- },
115
- "start_date": "2016-03-01T10:00:00Z",
116
- "expiration_date": null,
117
- "redemption": {
118
- "quantity": 1,
86
+ "code": "9mYBpIk",
87
+ "campaign": null,
88
+ "category": "API Test",
89
+ "type": "DISCOUNT_VOUCHER",
90
+ "discount": {
91
+ "type": "AMOUNT",
92
+ "amount_off": 400
93
+ },
94
+ "start_date": "2016-03-01T12:00:00Z",
95
+ "expiration_date": null,
96
+ "publish": {
97
+ "object": "list",
98
+ "count": 1,
99
+ "data_ref": "entries",
100
+ "entries": [{
101
+ "channel": "Email",
102
+ "customer": "alice.morgan@email.com",
103
+ "customer_id": "cust_1fnSUBno3iimKTPNDCkjg4xV",
104
+ "published_at": "2016-01-22T09:25:07Z"
105
+ }]
106
+ },
107
+ "redemption": {
108
+ "object": "list",
109
+ "quantity": 3,
110
+ "data_ref": "redemption_entries",
111
+ "redeemed_quantity": 1,
112
+ "redemption_entries": [{
113
+ "id": "r_gQzOnTwmhn2nTLwW4sZslNKY",
114
+ "object": "redemption",
115
+ "date": "2016-04-24T06:03:35Z",
116
+ "customer_id": null,
117
+ "tracking_id": "(tracking_id not set)"
118
+ }]
119
+ },
120
+ "active": true,
121
+ "additional_info": null,
122
+ "metadata": null
123
+ }, {
124
+ "code": "AzTsIH",
125
+ "campaign": null,
126
+ "category": "API Test",
127
+ "type": "GIFT_VOUCHER",
128
+ "gift": {
129
+ "amount": 10000,
130
+ "balance": 5000
131
+ },
132
+ "start_date": "2016-03-01T10:00:00Z",
133
+ "expiration_date": null,
134
+ "publish": {
135
+ "object": "list",
136
+ "count": 1,
137
+ "data_ref": "entries",
138
+ "entries": [{
139
+ "channel": "Email",
140
+ "customer": "alice.morgan@email.com",
141
+ "customer_id": "cust_1fnSUBno3iimKTPNDCkjg4xV",
142
+ "published_at": "2016-01-22T09:25:07Z"
143
+ }]
144
+ },
145
+ "redemption": {
146
+ "object": "list",
147
+ "quantity": 0,
148
+ "data_ref": "redemption_entries",
119
149
  "redeemed_quantity": 0,
120
150
  "redeemed_amount": 0,
121
151
  "redemption_entries": []
122
- },
123
- "active": true,
124
- "additional_info": null,
125
- "metadata": null
126
- },
127
- ...
128
- ]
152
+ },
153
+ "active": true,
154
+ "additional_info": null,
155
+ "metadata": null
156
+ }]
129
157
  ```
130
158
 
131
159
  #### Getting voucher details
@@ -145,8 +173,21 @@ Result:
145
173
  "type": "PERCENT"
146
174
  },
147
175
  "expiration_date": "2016-12-31T23:59:59Z",
176
+ "publish": {
177
+ "object": "list",
178
+ "count": 1,
179
+ "data_ref": "entries",
180
+ "entries": [{
181
+ "channel": "Email",
182
+ "customer": "alice.morgan@email.com",
183
+ "customer_id": "cust_1fnSUBno3iimKTPNDCkjg4xV",
184
+ "published_at": "2016-01-22T09:25:07Z"
185
+ }]
186
+ },
148
187
  "redemption": {
188
+ "object": "list",
149
189
  "quantity": 3,
190
+ "data_ref": "redemption_entries",
150
191
  "redeemed_quantity": 1,
151
192
  "redemption_entries": [
152
193
  {
@@ -195,11 +236,19 @@ Example:
195
236
  ```ruby
196
237
  voucherify.publish("First Ride")
197
238
  ```
239
+
198
240
  or
241
+
199
242
  ```ruby
200
243
  voucherify.publish({campaign: "First Ride", channel: "Email", customer: "donny.roll@mail.com"})
201
244
  ```
202
245
 
246
+ or
247
+
248
+ ```ruby
249
+ voucherify.publish({voucher: "FR-zT-u9I7zG", channel: "Email", customer: "donny.roll@mail.com"})
250
+ ```
251
+
203
252
  Positive result:
204
253
 
205
254
  ```json
@@ -214,15 +263,20 @@ Positive result:
214
263
  "start_date": "2015-01-01T00:00:00Z",
215
264
  "expiration_date": "2016-12-31T23:59:59Z",
216
265
  "publish": {
266
+ "object": "list",
217
267
  "count": 1,
268
+ "data_ref": "entries",
218
269
  "entries": [{
219
270
  "channel": "Email",
220
271
  "customer": "donny.roll@mail.com",
272
+ "customer_id": "cust_1fnSUBno3iimKTPNDCkjg4xV",
221
273
  "published_at": "2016-01-22T09:25:07Z"
222
274
  }]
223
275
  },
224
276
  "redemption": {
225
- "quantity": 1,
277
+ "object": "list",
278
+ "quantity": 0,
279
+ "data_ref": "redemption_entries",
226
280
  "redeemed_quantity": 0,
227
281
  "redemption_entries": []
228
282
  },
@@ -246,33 +300,38 @@ Validation lets you check if given voucher code can be successfuly redeemed.
246
300
 
247
301
  `voucherify.validate(code, context)`
248
302
 
249
- The `context` param is generaly optional unless you are validating a gift voucher.
303
+ The `context` param is generally optional unless you are validating a gift voucher or a voucher with order validation rules.
250
304
  Then you have to pass `order.amount` expressed in cents (e.g. $10 is 1000).
305
+ Validation rules also require to pass `order.items` as a list of objects including `product_id`, `sku_id` and `quantity`.
251
306
 
252
307
  Example:
253
308
 
254
309
  ```
255
310
  validation_result = voucherify.validate("91Ft4U", {
256
- tracking_id: "john@lemon.com",
311
+ tracking_id: "john@lemon.com",
257
312
  customer: {
258
313
  id: "cust_07sVjVsr71Ewot9lVZSrIVLH",
259
314
  source_id: "john@lemon.com",
260
315
  name: "John Lemon"
261
- },
262
- order: {
263
- amount: 1000
316
+ },
317
+ order: {
318
+ amount: 1250
319
+ items: [
320
+ { product_id: "prod_ELvEXqF4qzB7Rs", sku_id: "sku_GoXSOI4FwJZafb", quantity: 1 },
321
+ { product_id: "prod_wye1naw5JO5dh3", sku_id: "sku_U3rHSlfOCGUnbo", quantity: 2 }
322
+ ]
264
323
  }
265
324
  })
266
325
  ```
267
326
 
268
327
  Successful validation result:
269
328
  ```
270
- {"code"=>"91Ft4U", "valid"=>true, "gift"=>{"amount"=>10000}, "tracking_id"=>"john@lemon.com"}
329
+ {"code"=>"91Ft4U", "valid"=>true, "gift"=>{"amount"=>10000, "balance"=>5000}, "tracking_id"=>"john@lemon.com"}
271
330
  ```
272
331
 
273
332
  Failed validation result:
274
333
  ```
275
- {"code"=>"91Ft4U", "valid"=>true, "reason"=>"gift amount exceeded", "tracking_id"=>"john@lemon.com"}
334
+ {"code"=>"91Ft4U", "valid"=>false, "reason"=>"gift amount exceeded", "tracking_id"=>"john@lemon.com"}
276
335
  ```
277
336
 
278
337
  There are several reasons why validation may fail (`valid: false` response). You can find the actual cause in the `reason` field:
@@ -283,6 +342,8 @@ There are several reasons why validation may fail (`valid: false` response). You
283
342
  - `voucher expired`
284
343
  - `quantity exceeded`
285
344
  - `gift amount exceeded`
345
+ - `customer does not match segment rules`
346
+ - `order does not match validation rules`
286
347
 
287
348
  #### Redeeming voucher
288
349
 
@@ -311,7 +372,9 @@ Result (voucher details after redemption):
311
372
  },
312
373
  "expiration_date": "2016-12-31T23:59:59Z",
313
374
  "redemption": {
375
+ "object": "list",
314
376
  "quantity": 3,
377
+ "data_ref": "redemption_entries",
315
378
  "redeemed_quantity": 2,
316
379
  "redemption_entries": [
317
380
  {
@@ -437,8 +500,9 @@ voucherify.redeem({
437
500
 
438
501
  ##### 5. With order amount
439
502
 
440
- Redeeming a gift voucher requires to pass an amount that you wish to withdraw from the voucher.
441
- Order amount have to be expressed in cents, as an integer. For example $22.50 should be provided as 2250:
503
+ Redeeming a gift voucher requires passing order amount. The same applies to vouchers with validation rules on order's total amount.
504
+ Order amount have to be expressed in cents, as an integer. For example $22.50 should be provided as 2250.
505
+ Gift voucher balance will be used to cover the order amount entirely or partially.
442
506
 
443
507
  ```ruby
444
508
  voucherify.redeem({
@@ -448,6 +512,21 @@ voucherify.redeem({
448
512
  })
449
513
  ```
450
514
 
515
+ ##### 6. With order items
516
+
517
+ Vouchers with validation rules regarding products or SKUs require to pass `order.items`.
518
+ Items are a list of objects consisting of `product_id`, `sku_id` and `quantity`.
519
+
520
+ ```javascript
521
+ voucherify.redeem({
522
+ voucher: "91Ft4U",
523
+ order: {
524
+ items: [
525
+ { product_id: "prod_ELvEXqF4qzB7Rs", sku_id: "sku_GoXSOI4FwJZafb", quantity: 1 },
526
+ { product_id: "prod_wye1naw5JO5dh3", sku_id: "sku_U3rHSlfOCGUnbo", quantity: 2 }
527
+ ]
528
+ })
529
+ ```
451
530
 
452
531
  #### Listing redemptions
453
532
 
@@ -528,8 +607,16 @@ Result (voucher details):
528
607
  },
529
608
  "start_date": "2016-01-01T00:00:00Z",
530
609
  "expiration_date": "2016-12-31T23:59:59Z",
610
+ "publish": {
611
+ "object": "list",
612
+ "count": 0,
613
+ "data_ref": "entries",
614
+ "entries": []
615
+ },
531
616
  "redemption": {
617
+ "object": "list",
532
618
  "quantity": 1,
619
+ "data_ref": "redemption_entries",
533
620
  "redeemed_quantity": 0,
534
621
  "redemption_entries": []
535
622
  },
@@ -607,8 +694,16 @@ Result:
607
694
  "type": "PERCENT"
608
695
  },
609
696
  "expiration_date": "2016-12-31T23:59:59Z",
697
+ "publish": {
698
+ "object": "list",
699
+ "count": 0,
700
+ "data_ref": "entries",
701
+ "entries": []
702
+ },
610
703
  "redemption": {
704
+ "object": "list",
611
705
  "quantity": 3,
706
+ "data_ref": "redemption_entries",
612
707
  "redeemed_quantity": 2,
613
708
  "redemption_entries": [
614
709
  {
@@ -807,6 +902,8 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
807
902
  Bug reports and pull requests are welcome on GitHub at https://github.com/rspective/voucherify-ruby-sdk.
808
903
 
809
904
  ## Changelog
905
+ - **2016-12-02** - `0.8.2` - support gift vouchers in utils, fix price and discount calculations for amount discounts
906
+ - **2016-10-03** - `0.8.1` - publish update
810
907
  - **2016-08-02** - `0.8.0` - validate voucher
811
908
  - **2016-07-18** - `0.7.0` - voucher udpate
812
909
  - **2016-07-05** - `0.6.0` - new utils module
data/examples/utils.rb CHANGED
@@ -1,21 +1,73 @@
1
- require 'voucherify/utils'
1
+ require '../lib/voucherify/utils'
2
2
 
3
3
  include Utils
4
4
 
5
- discount = Utils.calculate_discount(20, {
5
+ base_price = 20.00
6
+
7
+ puts "base price: " + base_price.to_s
8
+
9
+ puts "===== amount discount ====="
10
+ amount_voucher = {
6
11
  discount: {
7
- unit_off: 2.0,
8
- type: 'UNIT'
12
+ amount_off: 1000, # 10.0
13
+ type: 'AMOUNT'
9
14
  }
10
- }, 5)
15
+ }
16
+ puts "discount: " + Utils.calculate_discount(base_price, amount_voucher).to_s
17
+ puts "price after discount: " + Utils.calculate_price(base_price, amount_voucher).to_s
18
+ puts
19
+
11
20
 
12
- print(discount)
21
+ puts "===== percent discount ===="
13
22
 
14
- discount = Utils.calculate_price(20, amount_voucher_object = {
23
+ percent_discount_voucher = {
15
24
  discount: {
16
- amount_off: 7.0,
17
- type: 'AMOUNT'
25
+ percent_off: 20,
26
+ type: 'PERCENT'
27
+ }
28
+ }
29
+
30
+ puts "discount: " + Utils.calculate_discount(base_price, percent_discount_voucher).to_s
31
+ puts "price after discount: " + Utils.calculate_price(base_price, percent_discount_voucher).to_s
32
+ puts
33
+
34
+
35
+ puts "===== unit discount ======="
36
+
37
+ unit_discount_voucher = {
38
+ discount: {
39
+ unit_off: 2,
40
+ type: 'UNIT'
41
+ }
42
+ }
43
+
44
+ puts "discount: " + Utils.calculate_discount(base_price, unit_discount_voucher, 5).to_s
45
+ puts "price after discount: " + Utils.calculate_price(base_price, unit_discount_voucher, 5).to_s
46
+ puts
47
+
48
+
49
+ puts "===== gift voucher ========"
50
+
51
+ gift_voucher = {
52
+ gift: {
53
+ amount: 1000,
54
+ balance: 500
55
+ }
56
+ }
57
+
58
+ puts "discount: " + Utils.calculate_discount(base_price, gift_voucher).to_s
59
+ puts "price after discount: " + Utils.calculate_price(base_price, gift_voucher).to_s
60
+ puts
61
+
62
+ puts "===== gift voucher 2 ======"
63
+
64
+ gift_voucher2 = {
65
+ gift: {
66
+ amount: 10000,
67
+ balance: 5000
18
68
  }
19
- })
69
+ }
20
70
 
21
- print(discount)
71
+ puts "discount: " + Utils.calculate_discount(base_price, gift_voucher2).to_s
72
+ puts "price after discount: " + Utils.calculate_price(base_price, gift_voucher2).to_s
73
+ puts
@@ -22,6 +22,13 @@ module Utils
22
22
  end
23
23
 
24
24
  def calculate_price(base_price, voucher, unit_price = nil)
25
+ e = 100.0
26
+
27
+ if voucher[:gift]
28
+ discount = [voucher[:gift][:balance] / e, base_price].min
29
+ return round_money(base_price - discount)
30
+ end
31
+
25
32
  if !voucher[:discount]
26
33
  raise "Unsupported voucher type."
27
34
  end
@@ -29,11 +36,11 @@ module Utils
29
36
  if voucher[:discount][:type] === 'PERCENT'
30
37
  discount = voucher[:discount][:percent_off]
31
38
  validate_percent_discount(discount);
32
- price_discount = base_price * (discount / 100)
39
+ price_discount = base_price * (discount / 100.0)
33
40
  return round_money(base_price - price_discount)
34
41
 
35
42
  elsif voucher[:discount][:type] === 'AMOUNT'
36
- discount = voucher[:discount][:amount_off]
43
+ discount = voucher[:discount][:amount_off] / e
37
44
  validate_amount_discount(discount)
38
45
  new_price = base_price - discount
39
46
  return round_money(new_price > 0 ? (new_price) : 0)
@@ -53,6 +60,13 @@ module Utils
53
60
  end
54
61
 
55
62
  def calculate_discount(base_price, voucher, unit_price = nil)
63
+ e = 100.0
64
+
65
+ if voucher[:gift]
66
+ discount = [voucher[:gift][:balance] / e, base_price].min
67
+ return round_money(discount)
68
+ end
69
+
56
70
  if !voucher[:discount]
57
71
  raise "Unsupported voucher type."
58
72
  end
@@ -60,11 +74,11 @@ module Utils
60
74
  if voucher[:discount][:type] === 'PERCENT'
61
75
  discount = voucher[:discount][:percent_off]
62
76
  validate_percent_discount(discount);
63
- price_discount = base_price * (discount / 100)
77
+ price_discount = base_price * (discount / 100.0)
64
78
  return round_money(price_discount)
65
79
 
66
80
  elsif voucher[:discount][:type] === 'AMOUNT'
67
- discount = voucher[:discount][:amount_off]
81
+ discount = voucher[:discount][:amount_off] / e
68
82
  validate_amount_discount(discount)
69
83
  new_price = base_price - discount
70
84
  return round_money(new_price > 0 ? (discount) : (base_price))
@@ -1,3 +1,3 @@
1
1
  class Voucherify
2
- VERSION = "0.8.0"
2
+ VERSION = "0.8.2"
3
3
  end
metadata CHANGED
@@ -1,69 +1,69 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: voucherify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - pawelrychlik
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-08-02 00:00:00.000000000 Z
11
+ date: 2016-12-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ~>
18
18
  - !ruby/object:Gem::Version
19
19
  version: '1.11'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.11'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
33
  version: '10.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ~>
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ~>
46
46
  - !ruby/object:Gem::Version
47
47
  version: '3.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rest-client
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
61
  version: '1.8'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ~>
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1.8'
69
69
  description:
@@ -73,7 +73,7 @@ executables: []
73
73
  extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
- - ".gitignore"
76
+ - .gitignore
77
77
  - Gemfile
78
78
  - LICENSE
79
79
  - README.md
@@ -97,17 +97,17 @@ require_paths:
97
97
  - lib
98
98
  required_ruby_version: !ruby/object:Gem::Requirement
99
99
  requirements:
100
- - - ">="
100
+ - - '>='
101
101
  - !ruby/object:Gem::Version
102
102
  version: 1.9.3
103
103
  required_rubygems_version: !ruby/object:Gem::Requirement
104
104
  requirements:
105
- - - ">="
105
+ - - '>='
106
106
  - !ruby/object:Gem::Version
107
107
  version: '0'
108
108
  requirements: []
109
109
  rubyforge_project:
110
- rubygems_version: 2.2.2
110
+ rubygems_version: 2.0.14.1
111
111
  signing_key:
112
112
  specification_version: 4
113
113
  summary: Ruby SDK for Voucherify. More info on http://www.voucherify.io