veritrans 2.4.0 → 2.4.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 +4 -4
- data/Gemfile +0 -2
- data/Gemfile.lock +2 -129
- data/Maintaining.md +17 -0
- data/README.md +91 -0
- data/example/subscription/credit_card_subscription_example.rb +138 -0
- data/example/subscription/gopay_subscription_example.rb +153 -0
- data/example/subscription/readme.md +4 -0
- data/example/tokenization/gopay_tokenization_example.rb +144 -0
- data/example/tokenization/readme.md +4 -0
- data/lib/veritrans/client.rb +1 -1
- data/lib/veritrans/version.rb +1 -1
- metadata +8 -3
- data/Maintaining.MD +0 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b8f40c46b892c2f87d0803387f08aeb565e7b5ecea9e26d4962fb5e852d5cbbb
|
|
4
|
+
data.tar.gz: 79ce221c6297fbc3558e60881704a0b6c72bce9353ce85c500f7145d1928a30d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6ec9419b6388b39665415dcfccb10acde81266d4ac338259bed4e033cca4c6240f4e6e7f7cf631f541ed831cefd033bb11b49b4eafda0781468a84f381924cfb
|
|
7
|
+
data.tar.gz: 8906403f8cc21a0963697b1e6b3283f8f8c8f30cc22305348cc7e96fadccd9817594b5d330dfea4b5001904fee71295b3b60c6751f81da771bf9fb20f7310482
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,155 +1,30 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
veritrans (2.4.
|
|
4
|
+
veritrans (2.4.1)
|
|
5
5
|
excon (~> 0.20)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
8
8
|
remote: https://rubygems.org/
|
|
9
9
|
specs:
|
|
10
|
-
|
|
11
|
-
actionpack (= 6.1.4.1)
|
|
12
|
-
activesupport (= 6.1.4.1)
|
|
13
|
-
nio4r (~> 2.0)
|
|
14
|
-
websocket-driver (>= 0.6.1)
|
|
15
|
-
actionmailbox (6.1.4.1)
|
|
16
|
-
actionpack (= 6.1.4.1)
|
|
17
|
-
activejob (= 6.1.4.1)
|
|
18
|
-
activerecord (= 6.1.4.1)
|
|
19
|
-
activestorage (= 6.1.4.1)
|
|
20
|
-
activesupport (= 6.1.4.1)
|
|
21
|
-
mail (>= 2.7.1)
|
|
22
|
-
actionmailer (6.1.4.1)
|
|
23
|
-
actionpack (= 6.1.4.1)
|
|
24
|
-
actionview (= 6.1.4.1)
|
|
25
|
-
activejob (= 6.1.4.1)
|
|
26
|
-
activesupport (= 6.1.4.1)
|
|
27
|
-
mail (~> 2.5, >= 2.5.4)
|
|
28
|
-
rails-dom-testing (~> 2.0)
|
|
29
|
-
actionpack (6.1.4.1)
|
|
30
|
-
actionview (= 6.1.4.1)
|
|
31
|
-
activesupport (= 6.1.4.1)
|
|
32
|
-
rack (~> 2.0, >= 2.0.9)
|
|
33
|
-
rack-test (>= 0.6.3)
|
|
34
|
-
rails-dom-testing (~> 2.0)
|
|
35
|
-
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
|
36
|
-
actiontext (6.1.4.1)
|
|
37
|
-
actionpack (= 6.1.4.1)
|
|
38
|
-
activerecord (= 6.1.4.1)
|
|
39
|
-
activestorage (= 6.1.4.1)
|
|
40
|
-
activesupport (= 6.1.4.1)
|
|
41
|
-
nokogiri (>= 1.12.5)
|
|
42
|
-
actionview (6.1.4.1)
|
|
43
|
-
activesupport (= 6.1.4.1)
|
|
44
|
-
builder (~> 3.1)
|
|
45
|
-
erubi (~> 1.4)
|
|
46
|
-
rails-dom-testing (~> 2.0)
|
|
47
|
-
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
|
48
|
-
activejob (6.1.4.1)
|
|
49
|
-
activesupport (= 6.1.4.1)
|
|
50
|
-
globalid (>= 0.3.6)
|
|
51
|
-
activemodel (6.1.4.1)
|
|
52
|
-
activesupport (= 6.1.4.1)
|
|
53
|
-
activerecord (6.1.4.1)
|
|
54
|
-
activemodel (= 6.1.4.1)
|
|
55
|
-
activesupport (= 6.1.4.1)
|
|
56
|
-
activestorage (6.1.4.1)
|
|
57
|
-
actionpack (= 6.1.4.1)
|
|
58
|
-
activejob (= 6.1.4.1)
|
|
59
|
-
activerecord (= 6.1.4.1)
|
|
60
|
-
activesupport (= 6.1.4.1)
|
|
61
|
-
marcel (~> 1.0.0)
|
|
62
|
-
mini_mime (>= 1.1.0)
|
|
63
|
-
activesupport (6.1.4.1)
|
|
64
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
65
|
-
i18n (>= 1.6, < 2)
|
|
66
|
-
minitest (>= 5.1)
|
|
67
|
-
tzinfo (~> 2.0)
|
|
68
|
-
zeitwerk (~> 2.3)
|
|
69
|
-
builder (3.2.4)
|
|
70
|
-
concurrent-ruby (1.1.9)
|
|
71
|
-
crass (1.0.6)
|
|
72
|
-
erubi (1.10.0)
|
|
73
|
-
excon (0.85.0)
|
|
74
|
-
globalid (0.5.2)
|
|
75
|
-
activesupport (>= 5.0)
|
|
76
|
-
i18n (1.8.10)
|
|
77
|
-
concurrent-ruby (~> 1.0)
|
|
78
|
-
loofah (2.12.0)
|
|
79
|
-
crass (~> 1.0.2)
|
|
80
|
-
nokogiri (>= 1.5.9)
|
|
81
|
-
mail (2.7.1)
|
|
82
|
-
mini_mime (>= 0.1.1)
|
|
83
|
-
marcel (1.0.2)
|
|
84
|
-
method_source (1.0.0)
|
|
85
|
-
mini_mime (1.1.1)
|
|
86
|
-
mini_portile2 (2.6.1)
|
|
10
|
+
excon (0.88.0)
|
|
87
11
|
minitest (5.14.4)
|
|
88
12
|
mustermann (1.1.1)
|
|
89
13
|
ruby2_keywords (~> 0.0.1)
|
|
90
14
|
nio4r (2.5.8)
|
|
91
|
-
nokogiri (1.12.5)
|
|
92
|
-
mini_portile2 (~> 2.6.1)
|
|
93
|
-
racc (~> 1.4)
|
|
94
|
-
nokogiri (1.12.5-x86_64-darwin)
|
|
95
|
-
racc (~> 1.4)
|
|
96
15
|
puma (5.5.0)
|
|
97
16
|
nio4r (~> 2.0)
|
|
98
|
-
racc (1.5.2)
|
|
99
17
|
rack (2.2.3)
|
|
100
18
|
rack-protection (2.1.0)
|
|
101
19
|
rack
|
|
102
|
-
rack-test (1.1.0)
|
|
103
|
-
rack (>= 1.0, < 3)
|
|
104
|
-
rails (6.1.4.1)
|
|
105
|
-
actioncable (= 6.1.4.1)
|
|
106
|
-
actionmailbox (= 6.1.4.1)
|
|
107
|
-
actionmailer (= 6.1.4.1)
|
|
108
|
-
actionpack (= 6.1.4.1)
|
|
109
|
-
actiontext (= 6.1.4.1)
|
|
110
|
-
actionview (= 6.1.4.1)
|
|
111
|
-
activejob (= 6.1.4.1)
|
|
112
|
-
activemodel (= 6.1.4.1)
|
|
113
|
-
activerecord (= 6.1.4.1)
|
|
114
|
-
activestorage (= 6.1.4.1)
|
|
115
|
-
activesupport (= 6.1.4.1)
|
|
116
|
-
bundler (>= 1.15.0)
|
|
117
|
-
railties (= 6.1.4.1)
|
|
118
|
-
sprockets-rails (>= 2.0.0)
|
|
119
|
-
rails-dom-testing (2.0.3)
|
|
120
|
-
activesupport (>= 4.2.0)
|
|
121
|
-
nokogiri (>= 1.6)
|
|
122
|
-
rails-html-sanitizer (1.4.2)
|
|
123
|
-
loofah (~> 2.3)
|
|
124
|
-
railties (6.1.4.1)
|
|
125
|
-
actionpack (= 6.1.4.1)
|
|
126
|
-
activesupport (= 6.1.4.1)
|
|
127
|
-
method_source
|
|
128
|
-
rake (>= 0.13)
|
|
129
|
-
thor (~> 1.0)
|
|
130
|
-
rake (13.0.6)
|
|
131
20
|
ruby2_keywords (0.0.5)
|
|
132
21
|
sinatra (2.1.0)
|
|
133
22
|
mustermann (~> 1.0)
|
|
134
23
|
rack (~> 2.2)
|
|
135
24
|
rack-protection (= 2.1.0)
|
|
136
25
|
tilt (~> 2.0)
|
|
137
|
-
sprockets (4.0.2)
|
|
138
|
-
concurrent-ruby (~> 1.0)
|
|
139
|
-
rack (> 1, < 3)
|
|
140
|
-
sprockets-rails (3.2.2)
|
|
141
|
-
actionpack (>= 4.0)
|
|
142
|
-
activesupport (>= 4.0)
|
|
143
|
-
sprockets (>= 3.0.0)
|
|
144
26
|
sqlite3 (1.4.2)
|
|
145
|
-
thor (1.1.0)
|
|
146
27
|
tilt (2.0.10)
|
|
147
|
-
tzinfo (2.0.4)
|
|
148
|
-
concurrent-ruby (~> 1.0)
|
|
149
|
-
websocket-driver (0.7.5)
|
|
150
|
-
websocket-extensions (>= 0.1.0)
|
|
151
|
-
websocket-extensions (0.1.5)
|
|
152
|
-
zeitwerk (2.4.2)
|
|
153
28
|
|
|
154
29
|
PLATFORMS
|
|
155
30
|
ruby
|
|
@@ -158,8 +33,6 @@ PLATFORMS
|
|
|
158
33
|
DEPENDENCIES
|
|
159
34
|
minitest (~> 5.14, >= 5.14.4)
|
|
160
35
|
puma
|
|
161
|
-
rails (< 7)
|
|
162
|
-
rake
|
|
163
36
|
sinatra
|
|
164
37
|
sqlite3
|
|
165
38
|
tilt
|
data/Maintaining.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
> Warning: This note is for developer/maintainer of this package only
|
|
2
|
+
|
|
3
|
+
## Updating Package
|
|
4
|
+
|
|
5
|
+
- Make your changes
|
|
6
|
+
- Update `version` value on `version.rb` file
|
|
7
|
+
- To install the package from local codes, you should build a gem `gem build veritrans.gemspec` after that `gem install veritrans-x.y.z.gem` (replace `x.y.z` with the version number e.g. `gem install veritrans-2.4.0.gem`)
|
|
8
|
+
- Note: In case you want to test another new code changes, you will need to re-build & re-install, so that your latest code will be used by the locally installed gem
|
|
9
|
+
- To run all test `cd /lib/test` and after that `ruby -Itest all.rb`
|
|
10
|
+
- To run specific test `ruby snap_test.rb`
|
|
11
|
+
- If you are using Rubymine, you can right click folder test and choose `run all tests in test`
|
|
12
|
+
|
|
13
|
+
## Update Rubygems.org
|
|
14
|
+
- Run this command `gem build veritrans.gemspec`
|
|
15
|
+
- Run this command `gem push veritrans-x.y.z.gem` (replace `x.y.z` with the version number e.g. `gem push veritrans-2.4.0.gem`), after that you are required to enter email and password account in Rubygems.org
|
|
16
|
+
- You can get account Rubygems.org in `Account Access & Resources`
|
|
17
|
+
- If you are using Rubymine, you can use `Tools -> Gem -> Build Gem` and `Push Gem`
|
data/README.md
CHANGED
|
@@ -60,6 +60,9 @@ Midtrans.config.server_key = "your server key"
|
|
|
60
60
|
Midtrans.config.client_key = "your client key"
|
|
61
61
|
Midtrans.config.api_host = "https://api.sandbox.midtrans.com"
|
|
62
62
|
```
|
|
63
|
+
Follow the steps given below to switch to Midtrans Production environment and to accept real payments from real customers.
|
|
64
|
+
1. Change api_host URL from `https://api.sandbox.midtrans.com` to `https://api.midtrans.com`.
|
|
65
|
+
2. Use Client Key and Server Key for Production environment. For more details, refer to [Retrieving API Access Keys](https://docs.midtrans.com/en/midtrans-account/overview?id=retrieving-api-access-keys).
|
|
63
66
|
|
|
64
67
|
### 2.2.A Snap
|
|
65
68
|
You can see Snap example [with Sinatra](example/sinatra) and [without framework](example/snap).
|
|
@@ -230,6 +233,94 @@ The credit card charge result may contains `redirect_url` for 3DS authentication
|
|
|
230
233
|
For full example on Credit Card 3DS transaction refer to:
|
|
231
234
|
- [Sinatra example](/example/sinatra) that implement Snap & Core Api
|
|
232
235
|
|
|
236
|
+
### 2.2.D Subscription API
|
|
237
|
+
|
|
238
|
+
You can see some Subscription API examples [here](example/subscription), [Subscription API Docs](https://api-docs.midtrans.com/#subscription-api).
|
|
239
|
+
|
|
240
|
+
#### Subscription API for Credit Card
|
|
241
|
+
|
|
242
|
+
To use subscription API for credit card, you should first obtain the 1-click saved token, [refer to this docs.](https://docs.midtrans.com/en/core-api/advanced-features?id=recurring-transaction-with-subscriptions-api)
|
|
243
|
+
You will receive `saved_token_id` as part of the response when the initial card payment is accepted (will also available in the HTTP notification's JSON), [refer to this docs.](https://docs.midtrans.com/en/core-api/advanced-features?id=sample-3ds-authenticate-json-response-for-the-first-transaction)
|
|
244
|
+
```ruby
|
|
245
|
+
require 'veritrans'
|
|
246
|
+
# Set Midtrans config
|
|
247
|
+
Midtrans.config.server_key = "your server key"
|
|
248
|
+
Midtrans.config.client_key = "your client key"
|
|
249
|
+
Midtrans.config.api_host = "https://api.sandbox.midtrans.com"
|
|
250
|
+
# Prepare parameter
|
|
251
|
+
parameter = {
|
|
252
|
+
"name": "monthly_subscription",
|
|
253
|
+
"amount": "14000",
|
|
254
|
+
"currency": "IDR",
|
|
255
|
+
"payment_type": "credit_card",
|
|
256
|
+
"token": saved_token_id,
|
|
257
|
+
"schedule": {
|
|
258
|
+
"interval": 1,
|
|
259
|
+
"interval_unit": "month",
|
|
260
|
+
"max_interval": 12,
|
|
261
|
+
#start_time value is just a sample time & should be replaced with a valid future time.
|
|
262
|
+
"start_time": "2022-12-20 07:00:00 +0700"
|
|
263
|
+
},
|
|
264
|
+
"metadata": {
|
|
265
|
+
"description": "Recurring payment for A"
|
|
266
|
+
},
|
|
267
|
+
"customer_details": {
|
|
268
|
+
"first_name": "John",
|
|
269
|
+
"last_name": "Doe",
|
|
270
|
+
"email": "johndoe@email.com",
|
|
271
|
+
"phone": "+62812345678"
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
result = Midtrans.create_subscription(parameter)
|
|
276
|
+
puts "Create subscription response : #{result.data}"
|
|
277
|
+
|
|
278
|
+
result_get_subs = Midtrans.get_subscription(subscription_id)
|
|
279
|
+
puts "get subscription response : #{result_get_subs.data}"
|
|
280
|
+
|
|
281
|
+
result_enable_subs = Midtrans.enable_subscription(subscription_id)
|
|
282
|
+
puts "enable subscription response : #{result_enable_subs.data}"
|
|
283
|
+
|
|
284
|
+
# update subscription by subscription_id and update_subscription_param
|
|
285
|
+
result_update_subs = Midtrans.update_subscription(subscription_id, update_subscription_param)
|
|
286
|
+
puts "update subscription response : #{result_update_subs.data}"
|
|
287
|
+
|
|
288
|
+
# disable subscription by subscription_id
|
|
289
|
+
result_disable_subs = Midtrans.disable_subscription(subscription_id)
|
|
290
|
+
puts "disable subscription response : #{result_disable_subs.data}"
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
#### Subscription API for Gopay
|
|
294
|
+
|
|
295
|
+
To use subscription API for gopay, you should first link your customer gopay account with gopay tokenization API, [refer to this section.](#22e-tokenization-api) You will receive gopay payment token using `getPaymentAccount` API call. You can see some Subscription API examples [here](example/subscription)
|
|
296
|
+
|
|
297
|
+
### 2.2.E Tokenization API
|
|
298
|
+
You can see some Tokenization API examples [here](examples/tokenization), [Tokenization API Docs.](https://api-docs.midtrans.com/#gopay-tokenization)
|
|
299
|
+
```ruby
|
|
300
|
+
require 'veritrans'
|
|
301
|
+
# Set Midtrans config
|
|
302
|
+
Midtrans.config.server_key = "your server key"
|
|
303
|
+
Midtrans.config.client_key = "your client key"
|
|
304
|
+
Midtrans.config.api_host = "https://api.sandbox.midtrans.com"
|
|
305
|
+
# Prepare parameter
|
|
306
|
+
parameter = {
|
|
307
|
+
"payment_type": "gopay",
|
|
308
|
+
"gopay_partner": {
|
|
309
|
+
"phone_number": "81987654321",
|
|
310
|
+
"country_code": "62",
|
|
311
|
+
"redirect_url": "https://www.gojek.com"
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
result = Midtrans.link_payment_account(parameter)
|
|
316
|
+
puts "Create pay account response : #{result.data}"
|
|
317
|
+
|
|
318
|
+
result_get_account = Midtrans.get_payment_account(active_account_id)
|
|
319
|
+
puts "Get pay account response : #{result_get_account.data}"
|
|
320
|
+
|
|
321
|
+
result_unlink = Midtrans.unlink_payment_account(active_account_id)
|
|
322
|
+
puts "Unlink response : #{result_unlink.data}"
|
|
323
|
+
```
|
|
233
324
|
|
|
234
325
|
### 2.3 Handle HTTP Notification
|
|
235
326
|
> **IMPORTANT NOTE**: To update transaction status on your backend/database, **DO NOT** solely rely on frontend callbacks! For security reason to make sure the status is authentically coming from Midtrans, only update transaction status based on HTTP Notification or API Get Status.
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
require 'veritrans'
|
|
2
|
+
|
|
3
|
+
# This is just for very basic implementation reference, in production, you should validate the incoming requests and implement your backend more securely.
|
|
4
|
+
|
|
5
|
+
# Set Midtrans config
|
|
6
|
+
# You can find it in Merchant Portal -> Settings -> Access keys
|
|
7
|
+
Midtrans.config.server_key = "SB-Mid-server-uQmMImQMeo0Ky3Svl90QTUj2"
|
|
8
|
+
Midtrans.config.client_key = "SB-Mid-client-ArNfhrh7st9bQKmz"
|
|
9
|
+
Midtrans.config.api_host = "https://api.sandbox.midtrans.com"
|
|
10
|
+
|
|
11
|
+
# To use API subscription for credit card, you should first obtain the 1 click token
|
|
12
|
+
# Refer to this docs: https://docs.midtrans.com/en/core-api/advanced-features?id=recurring-transaction-with-subscriptions-api
|
|
13
|
+
|
|
14
|
+
# You will receive saved_token_id as part of the response when the initial card payment is accepted (will also available in the HTTP notification's JSON)
|
|
15
|
+
# Refer to this docs: https://docs.midtrans.com/en/core-api/advanced-features?id=sample-3ds-authenticate-json-response-for-the-first-transaction
|
|
16
|
+
# {
|
|
17
|
+
# .
|
|
18
|
+
# "status_code": "200",
|
|
19
|
+
# "signature_key": "02d88dbe3ea009934daae63f0ec10b3078f92bbd75139cc9834689b92e707d305fb04b079020e877703c5ddbfbd779d5e2f62dc6edd63b0e68edeb57a985cf38",
|
|
20
|
+
# "saved_token_id_expired_at": "2025-12-31 07:00:00",
|
|
21
|
+
# "saved_token_id": "521111eLfszZpPoDAxJEjmoYCuaR1117",
|
|
22
|
+
# .
|
|
23
|
+
# }
|
|
24
|
+
# Sample saved token id for testing purpose
|
|
25
|
+
saved_token_id = "521111eLfszZpPoDAxJEjmoYCuaR1117"
|
|
26
|
+
|
|
27
|
+
# prepare parameter ( refer to: https://api-docs.midtrans.com/#create-subscription ) create subscription parameter example
|
|
28
|
+
begin
|
|
29
|
+
parameter = {
|
|
30
|
+
"name": "monthly_subscription",
|
|
31
|
+
"amount": "14000",
|
|
32
|
+
"currency": "IDR",
|
|
33
|
+
"payment_type": "credit_card",
|
|
34
|
+
"token": saved_token_id,
|
|
35
|
+
"schedule": {
|
|
36
|
+
"interval": 1,
|
|
37
|
+
"interval_unit": "month",
|
|
38
|
+
"max_interval": 12,
|
|
39
|
+
# start_time value is just a sample time & should be replaced with a valid future time.
|
|
40
|
+
"start_time": "2022-12-20 07:00:00 +0700"
|
|
41
|
+
},
|
|
42
|
+
"metadata": {
|
|
43
|
+
"description": "Recurring payment for A"
|
|
44
|
+
},
|
|
45
|
+
"customer_details": {
|
|
46
|
+
"first_name": "John",
|
|
47
|
+
"last_name": "Doe",
|
|
48
|
+
"email": "johndoe@email.com",
|
|
49
|
+
"phone": "+62812345678"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
result = Midtrans.create_subscription(parameter)
|
|
54
|
+
puts "Create subscription response : #{result.data}"
|
|
55
|
+
rescue MidtransError => e
|
|
56
|
+
puts e.message # Basic message error
|
|
57
|
+
puts e.http_status_code # HTTP status code e.g: 400, 401, etc.
|
|
58
|
+
puts e.api_response # API response body in String
|
|
59
|
+
puts e.raw_http_client_data # Raw HTTP client response
|
|
60
|
+
end
|
|
61
|
+
# result.data this will be Hash representation of the API JSON response
|
|
62
|
+
# {
|
|
63
|
+
# : id => "1d9c15ea-13e2-43f3-a87b-90aad6a9ad95",
|
|
64
|
+
# : name => "MONTHLY_2021",
|
|
65
|
+
# : amount => "14000",
|
|
66
|
+
# : currency => "IDR",
|
|
67
|
+
# : created_at => "2021-12-16 13:19:25",
|
|
68
|
+
# : schedule => {
|
|
69
|
+
# "interval" => 1, "current_interval" => 0, "max_interval" => 12, "interval_unit" => "month", "start_time" => "2021-12-20 07:00:00", "next_execution_at" => "2021-12-20 07:00:00"
|
|
70
|
+
# },
|
|
71
|
+
# : status => "active",
|
|
72
|
+
# : token => "521111eLfszZpPoDAxJEjmoYCuaR1117",
|
|
73
|
+
# : payment_type => "credit_card",
|
|
74
|
+
# : transaction_ids => [],
|
|
75
|
+
# : metadata => {
|
|
76
|
+
# "description" => "Recurring payment for A"
|
|
77
|
+
# },
|
|
78
|
+
# : customer_details => {
|
|
79
|
+
# "email" => "johndoe@email.com", "first_name" => "John", "last_name" => "Doe", "phone" => "+62812345678"
|
|
80
|
+
# }
|
|
81
|
+
# }
|
|
82
|
+
|
|
83
|
+
# Sample active subscription id for testing purpose
|
|
84
|
+
subscription_id = "1d9c15ea-13e2-43f3-a87b-90aad6a9ad95"
|
|
85
|
+
|
|
86
|
+
# get subscription by subscription_id
|
|
87
|
+
begin
|
|
88
|
+
result_get_subs = Midtrans.get_subscription(subscription_id)
|
|
89
|
+
puts "get subscription response : #{result_get_subs.data}"
|
|
90
|
+
rescue MidtransError => e
|
|
91
|
+
puts e.message # Basic message error
|
|
92
|
+
puts e.http_status_code # HTTP status code e.g: 400, 401, etc.
|
|
93
|
+
puts e.api_response # API response body in String
|
|
94
|
+
puts e.raw_http_client_data # Raw HTTP client response
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# enable subscription by subscription_id
|
|
98
|
+
begin
|
|
99
|
+
result_enable_subs = Midtrans.enable_subscription(subscription_id)
|
|
100
|
+
puts "enable subscription response : #{result_enable_subs.data}"
|
|
101
|
+
rescue MidtransError => e
|
|
102
|
+
puts e.message # Basic message error
|
|
103
|
+
puts e.http_status_code # HTTP status code e.g: 400, 401, etc.
|
|
104
|
+
puts e.api_response # API response body in String
|
|
105
|
+
puts e.raw_http_client_data # Raw HTTP client response
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# update subscription by subscription_id and update_subscription_param
|
|
109
|
+
begin
|
|
110
|
+
update_subscription_param = {
|
|
111
|
+
"name": "monthly_subscription",
|
|
112
|
+
"amount": "300000",
|
|
113
|
+
"currency": "IDR",
|
|
114
|
+
"token": saved_token_id,
|
|
115
|
+
"schedule": {
|
|
116
|
+
"interval": 1
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
result_update_subs = Midtrans.update_subscription(subscription_id, update_subscription_param)
|
|
121
|
+
puts "update subscription response : #{result_update_subs.data}"
|
|
122
|
+
rescue MidtransError => e
|
|
123
|
+
puts e.message # Basic message error
|
|
124
|
+
puts e.http_status_code # HTTP status code e.g: 400, 401, etc.
|
|
125
|
+
puts e.api_response # API response body in String
|
|
126
|
+
puts e.raw_http_client_data # Raw HTTP client response
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# disable subscription by subscription_id
|
|
130
|
+
begin
|
|
131
|
+
result_disable_subs = Midtrans.disable_subscription(subscription_id)
|
|
132
|
+
puts "disable subscription response : #{result_disable_subs.data}"
|
|
133
|
+
rescue MidtransError => e
|
|
134
|
+
puts e.message # Basic message error
|
|
135
|
+
puts e.http_status_code # HTTP status code e.g: 400, 401, etc.
|
|
136
|
+
puts e.api_response # API response body in String
|
|
137
|
+
puts e.raw_http_client_data # Raw HTTP client response
|
|
138
|
+
end
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
require 'veritrans'
|
|
2
|
+
|
|
3
|
+
# This is just for very basic implementation reference, in production, you should validate the incoming requests and implement your backend more securely.
|
|
4
|
+
|
|
5
|
+
# Set Midtrans config
|
|
6
|
+
# You can find it in Merchant Portal -> Settings -> Access keys
|
|
7
|
+
Midtrans.config.server_key = "SB-Mid-server-uQmMImQMeo0Ky3Svl90QTUj2"
|
|
8
|
+
Midtrans.config.client_key = "SB-Mid-client-ArNfhrh7st9bQKmz"
|
|
9
|
+
Midtrans.config.api_host = "https://api.sandbox.midtrans.com"
|
|
10
|
+
|
|
11
|
+
# To use API subscription for gopay, you should first link your customer gopay account with gopay tokenization
|
|
12
|
+
# Refer to this docs: https://api-docs.midtrans.com/#gopay-tokenization
|
|
13
|
+
|
|
14
|
+
# You will receive gopay payment token using `get_payment_account` API call.
|
|
15
|
+
# You can see some Tokenization API examples here (examples/tokenization)
|
|
16
|
+
# {
|
|
17
|
+
# : status_code => "200",: payment_type => "gopay",: account_id => "7501d1f5-697c-4b4b-b095-69e60003759f",: account_status => "ENABLED",: metadata => {
|
|
18
|
+
# "payment_options" => [{
|
|
19
|
+
# "name" => "GOPAY_WALLET",
|
|
20
|
+
# "active" => true,
|
|
21
|
+
# "balance" => {
|
|
22
|
+
# "value" => "8000000.00", "currency" => "IDR"
|
|
23
|
+
# },
|
|
24
|
+
# "metadata" => {},
|
|
25
|
+
# "token" => "de60838a-4fb7-48af-89b8-4741ba8e5404"
|
|
26
|
+
# }, {
|
|
27
|
+
# "name" => "PAY_LATER",
|
|
28
|
+
# "active" => true,
|
|
29
|
+
# "balance" => {
|
|
30
|
+
# "value" => "8000000.00", "currency" => "IDR"
|
|
31
|
+
# },
|
|
32
|
+
# "metadata" => {},
|
|
33
|
+
# "token" => "5b141678-7dc3-4f36-a5ec-c74ce62d2c46"
|
|
34
|
+
# }]
|
|
35
|
+
# }
|
|
36
|
+
# }
|
|
37
|
+
# Sample gopay payment option token and gopay account id for testing purpose that has been already activated before
|
|
38
|
+
gopay_payment_option_token = "de60838a-4fb7-48af-89b8-4741ba8e5404"
|
|
39
|
+
gopay_account_id = "7501d1f5-697c-4b4b-b095-69e60003759f"
|
|
40
|
+
|
|
41
|
+
# prepare CORE API parameter ( refer to: https://api-docs.midtrans.com/#create-subscription ) create subscription parameter example
|
|
42
|
+
begin
|
|
43
|
+
parameter = {
|
|
44
|
+
"name": "gopay_monthly_subscription",
|
|
45
|
+
"amount": "10000",
|
|
46
|
+
"currency": "IDR",
|
|
47
|
+
"payment_type": "gopay",
|
|
48
|
+
"token": gopay_payment_option_token,
|
|
49
|
+
"schedule": {
|
|
50
|
+
"interval": 1,
|
|
51
|
+
"interval_unit": "day",
|
|
52
|
+
"max_interval": 7
|
|
53
|
+
},
|
|
54
|
+
"metadata": {
|
|
55
|
+
"description": "Recurring payment for A"
|
|
56
|
+
},
|
|
57
|
+
"customer_details": {
|
|
58
|
+
"first_name": "John A",
|
|
59
|
+
"last_name": "Doe A",
|
|
60
|
+
"email": "johndoe@email.com",
|
|
61
|
+
"phone": "+62812345678"
|
|
62
|
+
},
|
|
63
|
+
"gopay": {
|
|
64
|
+
"account_id": gopay_account_id
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
result = Midtrans.create_subscription(parameter)
|
|
69
|
+
puts "Create subscription response : #{result.data}"
|
|
70
|
+
rescue MidtransError => e
|
|
71
|
+
puts e.message # Basic message error
|
|
72
|
+
puts e.http_status_code # HTTP status code e.g: 400, 401, etc.
|
|
73
|
+
puts e.api_response # API response body in String
|
|
74
|
+
puts e.raw_http_client_data # Raw HTTP client response
|
|
75
|
+
end
|
|
76
|
+
# result.data this will be Hash representation of the API JSON response
|
|
77
|
+
# {
|
|
78
|
+
# : id => "c04d89cb-ece6-4419-a87a-f773b243760d",
|
|
79
|
+
# : name => "SUBS-Gopay-2021",
|
|
80
|
+
# : amount => "10000",
|
|
81
|
+
# : currency => "IDR",
|
|
82
|
+
# : created_at => "2021-12-17 11:05:16",
|
|
83
|
+
# : schedule => {
|
|
84
|
+
# "interval" => 1, "current_interval" => 0, "max_interval" => 7, "interval_unit" => "day", "start_time" => "2021-12-17 11:05:16", "previous_execution_at" => "2021-12-17 11:05:16", "next_execution_at" => "2021-12-18 11:05:16"
|
|
85
|
+
# },
|
|
86
|
+
# : status => "active",
|
|
87
|
+
# : token => "de60838a-4fb7-48af-89b8-4741ba8e5404",
|
|
88
|
+
# : payment_type => "gopay",
|
|
89
|
+
# : transaction_ids => [],
|
|
90
|
+
# : metadata => {
|
|
91
|
+
# "description" => "Recurring payment for A"
|
|
92
|
+
# },
|
|
93
|
+
# : customer_details => {
|
|
94
|
+
# "email" => "johndoe@email.com", "first_name" => "John A", "last_name" => "Doe A", "phone" => "+62812345678"
|
|
95
|
+
# }
|
|
96
|
+
# }
|
|
97
|
+
|
|
98
|
+
# sample active subscription id for testing purpose
|
|
99
|
+
subscription_id = "c04d89cb-ece6-4419-a87a-f773b243760d"
|
|
100
|
+
|
|
101
|
+
# get subscription by subscription_id
|
|
102
|
+
begin
|
|
103
|
+
result_get_subs = Midtrans.get_subscription(subscription_id)
|
|
104
|
+
puts "get subscription response : #{result_get_subs.data}"
|
|
105
|
+
rescue MidtransError => e
|
|
106
|
+
puts e.message # Basic message error
|
|
107
|
+
puts e.http_status_code # HTTP status code e.g: 400, 401, etc.
|
|
108
|
+
puts e.api_response # API response body in String
|
|
109
|
+
puts e.raw_http_client_data # Raw HTTP client response
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# enable subscription by subscription_id
|
|
113
|
+
begin
|
|
114
|
+
result_enable_subs = Midtrans.enable_subscription(subscription_id)
|
|
115
|
+
puts "enable subscription response : #{result_enable_subs.data}"
|
|
116
|
+
rescue MidtransError => e
|
|
117
|
+
puts e.message # Basic message error
|
|
118
|
+
puts e.http_status_code # HTTP status code e.g: 400, 401, etc.
|
|
119
|
+
puts e.api_response # API response body in String
|
|
120
|
+
puts e.raw_http_client_data # Raw HTTP client response
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# update subscription by subscription_id and update_subscription_param
|
|
124
|
+
begin
|
|
125
|
+
update_subscription_param = {
|
|
126
|
+
"name": "gopay_monthly_subscription",
|
|
127
|
+
"amount": "300000",
|
|
128
|
+
"currency": "IDR",
|
|
129
|
+
"token": gopay_payment_option_token,
|
|
130
|
+
"schedule": {
|
|
131
|
+
"interval": 1
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
result_update_subs = Midtrans.update_subscription(subscription_id, update_subscription_param)
|
|
136
|
+
puts "update subscription response : #{result_update_subs.data}"
|
|
137
|
+
rescue MidtransError => e
|
|
138
|
+
puts e.message # Basic message error
|
|
139
|
+
puts e.http_status_code # HTTP status code e.g: 400, 401, etc.
|
|
140
|
+
puts e.api_response # API response body in String
|
|
141
|
+
puts e.raw_http_client_data # Raw HTTP client response
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# disable subscription by subscription_id
|
|
145
|
+
begin
|
|
146
|
+
result_disable_subs = Midtrans.disable_subscription(subscription_id)
|
|
147
|
+
puts "disable subscription response : #{result_disable_subs.data}"
|
|
148
|
+
rescue MidtransError => e
|
|
149
|
+
puts e.message # Basic message error
|
|
150
|
+
puts e.http_status_code # HTTP status code e.g: 400, 401, etc.
|
|
151
|
+
puts e.api_response # API response body in String
|
|
152
|
+
puts e.raw_http_client_data # Raw HTTP client response
|
|
153
|
+
end
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
require 'veritrans'
|
|
2
|
+
|
|
3
|
+
# This is just for very basic implementation reference, in production, you should validate the incoming requests and implement your backend more securely.
|
|
4
|
+
|
|
5
|
+
# Set Midtrans config
|
|
6
|
+
# You can find it in Merchant Portal -> Settings -> Access keys
|
|
7
|
+
Midtrans.config.server_key = "SB-Mid-server-uQmMImQMeo0Ky3Svl90QTUj2"
|
|
8
|
+
Midtrans.config.client_key = "SB-Mid-client-ArNfhrh7st9bQKmz"
|
|
9
|
+
Midtrans.config.api_host = "https://api.sandbox.midtrans.com"
|
|
10
|
+
|
|
11
|
+
# prepare CORE API parameter ( refer to: https://api-docs.midtrans.com/#create-pay-account ) create pay account parameter example
|
|
12
|
+
begin
|
|
13
|
+
parameter = {
|
|
14
|
+
"payment_type": "gopay",
|
|
15
|
+
"gopay_partner": {
|
|
16
|
+
"phone_number": "81987654321",
|
|
17
|
+
"country_code": "62",
|
|
18
|
+
"redirect_url": "https://www.gojek.com"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
# link payment account
|
|
23
|
+
result = Midtrans.link_payment_account(parameter)
|
|
24
|
+
puts "Create pay account response : #{result.data}"
|
|
25
|
+
rescue MidtransError => e
|
|
26
|
+
puts e.message # Basic message error
|
|
27
|
+
puts e.http_status_code # HTTP status code e.g: 400, 401, etc.
|
|
28
|
+
puts e.api_response # API response body in String
|
|
29
|
+
puts e.raw_http_client_data # Raw HTTP client response
|
|
30
|
+
end
|
|
31
|
+
# sample response :
|
|
32
|
+
# {
|
|
33
|
+
# : status_code => "201",: payment_type => "gopay",: account_id => "7501d1f5-697c-4b4b-b095-69e60003759f",: account_status => "PENDING",: actions => [{
|
|
34
|
+
# "name" => "activation-deeplink",
|
|
35
|
+
# "method" => "GET",
|
|
36
|
+
# "url" => "https://api.sandbox.midtrans.com/v2/pay/account/gpar_a5f424d0-c215-4633-b72d-6cac3bbc4328/link"
|
|
37
|
+
# }, {
|
|
38
|
+
# "name" => "activation-link-url",
|
|
39
|
+
# "method" => "GET",
|
|
40
|
+
# "url" => "https://api.sandbox.midtrans.com/v2/pay/account/gpar_a5f424d0-c215-4633-b72d-6cac3bbc4328/link"
|
|
41
|
+
# }, {
|
|
42
|
+
# "name" => "activation-link-app",
|
|
43
|
+
# "method" => "GET",
|
|
44
|
+
# "url" => "https://simulator.sandbox.midtrans.com/gopay/partner/web/otp?id=1cf353e9-d2ba-44e3-b6dc-00b2eb706ca9"
|
|
45
|
+
# }],: metadata => {
|
|
46
|
+
# "reference_id" => "d7e7cabe-a516-442f-b97a-230249cd62d0"
|
|
47
|
+
# }
|
|
48
|
+
# }
|
|
49
|
+
# for the first link, the account status is PENDING, you must activate it by accessing one of the URLs on the actions object
|
|
50
|
+
|
|
51
|
+
# Sample active account id for testing purpose
|
|
52
|
+
active_account_id = "bf45fd32-c379-4ef1-8ef6-b51c81da0204"
|
|
53
|
+
active_account_id_2 = "7501d1f5-697c-4b4b-b095-69e60003759f"
|
|
54
|
+
|
|
55
|
+
# Get payment account by account id
|
|
56
|
+
begin
|
|
57
|
+
result_get_account = Midtrans.get_payment_account(active_account_id)
|
|
58
|
+
puts "Get pay account response : #{result_get_account.data}"
|
|
59
|
+
rescue MidtransError => e
|
|
60
|
+
puts e.message # Basic message error
|
|
61
|
+
puts e.http_status_code # HTTP status code e.g: 400, 401, etc.
|
|
62
|
+
puts e.api_response # API response body in String
|
|
63
|
+
puts e.raw_http_client_data # Raw HTTP client response
|
|
64
|
+
end
|
|
65
|
+
# sample response :
|
|
66
|
+
# {
|
|
67
|
+
# : status_code => "200",: payment_type => "gopay",: account_id => "bf45fd32-c379-4ef1-8ef6-b51c81da0204",: account_status => "ENABLED",: metadata => {
|
|
68
|
+
# "payment_options" => [{
|
|
69
|
+
# "name" => "GOPAY_WALLET",
|
|
70
|
+
# "active" => true,
|
|
71
|
+
# "balance" => {
|
|
72
|
+
# "value" => "8000000.00", "currency" => "IDR"
|
|
73
|
+
# },
|
|
74
|
+
# "metadata" => {},
|
|
75
|
+
# "token" => "ebce5a0a-69d0-4961-bb23-390a9df9f4f9"
|
|
76
|
+
# }, {
|
|
77
|
+
# "name" => "PAY_LATER",
|
|
78
|
+
# "active" => true,
|
|
79
|
+
# "balance" => {
|
|
80
|
+
# "value" => "8000000.00", "currency" => "IDR"
|
|
81
|
+
# },
|
|
82
|
+
# "metadata" => {},
|
|
83
|
+
# "token" => "0272b39c-13bb-4aba-be68-74074f85aa86"
|
|
84
|
+
# }]
|
|
85
|
+
# }
|
|
86
|
+
# }
|
|
87
|
+
|
|
88
|
+
# sample param request charge
|
|
89
|
+
begin
|
|
90
|
+
params = {
|
|
91
|
+
"payment_type": "gopay",
|
|
92
|
+
"gopay": {
|
|
93
|
+
"account_id": active_account_id,
|
|
94
|
+
"payment_option_token": "0272b39c-13bb-4aba-be68-74074f85aa86",
|
|
95
|
+
"callback_url": "https://mywebstore.com/gopay-linking-finish"
|
|
96
|
+
},
|
|
97
|
+
"transaction_details": {
|
|
98
|
+
"gross_amount": 1000,
|
|
99
|
+
"order_id": "Gopaylink-sample-#{Time.now.to_i}"
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
# sample request charge
|
|
103
|
+
result_charge = Midtrans.charge(params)
|
|
104
|
+
puts "charge response : #{result_charge.data}"
|
|
105
|
+
rescue MidtransError => e
|
|
106
|
+
puts e.message # Basic message error
|
|
107
|
+
puts e.http_status_code # HTTP status code e.g: 400, 401, etc.
|
|
108
|
+
puts e.api_response # API response body in String
|
|
109
|
+
puts e.raw_http_client_data # Raw HTTP client response
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# sample charge response
|
|
113
|
+
# {
|
|
114
|
+
# : status_code => "200",
|
|
115
|
+
# : status_message => "Success, GoPay transaction is successful",
|
|
116
|
+
# : transaction_id => "55de5840-99f1-4b1d-a5fb-1b48d4ab321c",
|
|
117
|
+
# : order_id => "Gopaylink-sample-1641270143",
|
|
118
|
+
# : merchant_id => "G686051436",
|
|
119
|
+
# : gross_amount => "10000.00",
|
|
120
|
+
# : currency => "IDR",
|
|
121
|
+
# : payment_type => "gopay",
|
|
122
|
+
# : transaction_time => "2022-01-04 11:22:24",
|
|
123
|
+
# : transaction_status => "settlement",
|
|
124
|
+
# : fraud_status => "accept",
|
|
125
|
+
# : settlement_time => "2022-01-04 11:22:24"
|
|
126
|
+
# }
|
|
127
|
+
|
|
128
|
+
# unlink payment account by accountId
|
|
129
|
+
# when account status still PENDING, you will get status code 412
|
|
130
|
+
# sample response :
|
|
131
|
+
# {
|
|
132
|
+
# "status_code": "412",
|
|
133
|
+
# "status_message": "Account status cannot be updated.",
|
|
134
|
+
# "id": "358fdb22-1be2-4e6d-888d-b6703d60af6e"
|
|
135
|
+
# }
|
|
136
|
+
begin
|
|
137
|
+
result_unlink = Midtrans.unlink_payment_account(active_account_id_2)
|
|
138
|
+
puts "Unlink response : #{result_unlink.data}"
|
|
139
|
+
rescue MidtransError => e
|
|
140
|
+
puts e.message # Basic message error
|
|
141
|
+
puts e.http_status_code # HTTP status code e.g: 400, 401, etc.
|
|
142
|
+
puts e.api_response # API response body in String
|
|
143
|
+
puts e.raw_http_client_data # Raw HTTP client response
|
|
144
|
+
end
|
data/lib/veritrans/client.rb
CHANGED
|
@@ -126,7 +126,7 @@ class Veritrans
|
|
|
126
126
|
status_code = Integer(response_body["status_code"])
|
|
127
127
|
if status_code >= 400 && status_code != 407
|
|
128
128
|
raise MidtransError.new(
|
|
129
|
-
"Midtrans API is returning API error. HTTP status code: #{status_code}",
|
|
129
|
+
"Midtrans API is returning API error. HTTP status code: #{status_code} API response: #{response_body}",
|
|
130
130
|
"#{status_code}",
|
|
131
131
|
"#{response_body}",
|
|
132
132
|
"#{response}")
|
data/lib/veritrans/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: veritrans
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.4.
|
|
4
|
+
version: 2.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Veritrans Dev Team
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2022-01-12 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: excon
|
|
@@ -38,7 +38,7 @@ files:
|
|
|
38
38
|
- CHANGELOG.md
|
|
39
39
|
- Gemfile
|
|
40
40
|
- Gemfile.lock
|
|
41
|
-
- Maintaining.
|
|
41
|
+
- Maintaining.md
|
|
42
42
|
- README.md
|
|
43
43
|
- api_reference.md
|
|
44
44
|
- example/coreapi/core_api_credit_card_example.rb
|
|
@@ -52,6 +52,11 @@ files:
|
|
|
52
52
|
- example/sinatra/webapp.rb
|
|
53
53
|
- example/snap/readme.md
|
|
54
54
|
- example/snap/snap_example.rb
|
|
55
|
+
- example/subscription/credit_card_subscription_example.rb
|
|
56
|
+
- example/subscription/gopay_subscription_example.rb
|
|
57
|
+
- example/subscription/readme.md
|
|
58
|
+
- example/tokenization/gopay_tokenization_example.rb
|
|
59
|
+
- example/tokenization/readme.md
|
|
55
60
|
- lib/test/all.rb
|
|
56
61
|
- lib/test/api_test.rb
|
|
57
62
|
- lib/test/config_test.rb
|
data/Maintaining.MD
DELETED