veritrans 2.1.2 → 2.4.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.
- checksums.yaml +5 -5
- data/.gitignore +10 -1
- data/.idea/.gitignore +8 -0
- data/.rubocop.yml +35 -0
- data/.travis.yml +10 -5
- data/CHANGELOG.md +45 -0
- data/Gemfile +6 -7
- data/Gemfile.lock +134 -146
- data/Maintaining.MD +8 -0
- data/README.md +266 -226
- data/api_reference.md +534 -143
- data/example/coreapi/core_api_credit_card_example.rb +66 -0
- data/example/coreapi/readme.md +4 -0
- data/example/sinatra/Gemfile +7 -0
- data/example/sinatra/README.md +6 -0
- data/example/sinatra/index.erb +202 -0
- data/example/sinatra/response.erb +1 -0
- data/example/sinatra/snap.erb +33 -0
- data/example/sinatra/snap_redirect.erb +10 -0
- data/example/sinatra/webapp.rb +113 -0
- data/example/snap/readme.md +4 -0
- data/example/snap/snap_example.rb +39 -0
- data/lib/test/all.rb +1 -0
- data/lib/test/api_test.rb +319 -0
- data/lib/test/config_test.rb +26 -0
- data/lib/test/gopay_tokenization_test.rb +80 -0
- data/lib/test/snap_test.rb +79 -0
- data/lib/test/subscription_test.rb +116 -0
- data/lib/test/transaction_test.rb +160 -0
- data/lib/veritrans/api.rb +146 -22
- data/lib/veritrans/client.rb +48 -12
- data/lib/veritrans/config.rb +31 -6
- data/lib/veritrans/events.rb +46 -35
- data/lib/veritrans/midtrans_error.rb +15 -0
- data/lib/veritrans/result.rb +66 -5
- data/lib/veritrans/version.rb +1 -1
- data/lib/veritrans.rb +121 -12
- data/veritrans.gemspec +2 -9
- metadata +30 -146
- data/.rspec +0 -2
- data/Procfile +0 -1
- data/Rakefile +0 -16
- data/bin/midtrans +0 -3
- data/bin/veritrans +0 -68
- data/example/README.md +0 -8
- data/example/config.ru +0 -6
- data/example/index.erb +0 -213
- data/example/localization.erb +0 -248
- data/example/points.erb +0 -187
- data/example/recurring.erb +0 -201
- data/example/response.erb +0 -37
- data/example/sinatra.rb +0 -188
- data/example/style.css +0 -126
- data/example/veritrans.yml +0 -11
- data/example/widget.erb +0 -51
- data/lib/generators/templates/assets/credit_card_form.js +0 -51
- data/lib/generators/templates/payments_controller.rb +0 -85
- data/lib/generators/templates/veritrans.rb +0 -46
- data/lib/generators/templates/veritrans.yml +0 -18
- data/lib/generators/templates/views/_credit_card_form.erb +0 -42
- data/lib/generators/templates/views/_veritrans_include.erb +0 -10
- data/lib/generators/templates/views/payments/create.erb +0 -15
- data/lib/generators/templates/views/payments/new.erb +0 -6
- data/lib/generators/veritrans/install_generator.rb +0 -32
- data/lib/generators/veritrans/payment_form_generator.rb +0 -45
- data/lib/veritrans/cli.rb +0 -155
- data/lib/veritrans/core_extensions.rb +0 -32
- data/spec/cli_spec.rb +0 -83
- data/spec/configs/real_key.yml +0 -4
- data/spec/configs/veritrans.yml +0 -7
- data/spec/configs/veritrans_flat.yml +0 -2
- data/spec/configs/veritrans_with_erb.yml +0 -2
- data/spec/fixtures/approve_failed.yml +0 -48
- data/spec/fixtures/cancel_failed.yml +0 -48
- data/spec/fixtures/cancel_success.yml +0 -106
- data/spec/fixtures/capture_failed.yml +0 -48
- data/spec/fixtures/charge.yml +0 -50
- data/spec/fixtures/charge_direct.yml +0 -56
- data/spec/fixtures/charge_vtweb.yml +0 -50
- data/spec/fixtures/cli_test_1111-not-exists.yml +0 -45
- data/spec/fixtures/cli_test_not_exists.yml +0 -45
- data/spec/fixtures/cli_test_real_txn.yml +0 -55
- data/spec/fixtures/cli_test_unauthorized.yml +0 -47
- data/spec/fixtures/events_test_real_txn.yml +0 -55
- data/spec/fixtures/expire_failed.yml +0 -50
- data/spec/fixtures/expire_success.yml +0 -56
- data/spec/fixtures/midtrans_status.yml +0 -117
- data/spec/fixtures/status_fail.yml +0 -46
- data/spec/fixtures/status_success.yml +0 -109
- data/spec/midtrans_rename_spec.rb +0 -27
- data/spec/rails_plugin_spec.rb +0 -281
- data/spec/spec_helper.rb +0 -61
- data/spec/veritrans_client_spec.rb +0 -184
- data/spec/veritrans_config_spec.rb +0 -70
- data/spec/veritrans_events_spec.rb +0 -72
- data/spec/veritrans_logger_spec.rb +0 -46
- data/spec/veritrans_snap_spec.rb +0 -39
- data/testing_webhooks.md +0 -78
@@ -0,0 +1,66 @@
|
|
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
|
+
# IMPORTANT NOTE: You should do credit card get token via frontend using `midtrans-new-3ds.min.js`, to avoid card data breach risks on your backend
|
12
|
+
# ( refer to: https://docs.midtrans.com/en/core-api/credit-card?id=_1-getting-the-card-token )
|
13
|
+
# For full example on Credit Card 3DS transaction refer to:
|
14
|
+
# (/example/sinatra) that implement Snap & Core Api
|
15
|
+
|
16
|
+
# prepare CORE API parameter to get credit card token
|
17
|
+
# another sample of card number can refer to https://docs.midtrans.com/en/technical-reference/sandbox-test?id=card-payments
|
18
|
+
begin
|
19
|
+
card = {
|
20
|
+
card_number: 5211111111111117,
|
21
|
+
card_cvv: 123,
|
22
|
+
card_exp_month: 12,
|
23
|
+
card_exp_year: 2025
|
24
|
+
}
|
25
|
+
get_token = Midtrans.create_card_token(card)
|
26
|
+
|
27
|
+
# prepare CORE API parameter to charge credit card ( refer to: https://docs.midtrans.com/en/core-api/credit-card?id=_2-sending-transaction-data-to-charge-api )
|
28
|
+
result = Midtrans.charge(
|
29
|
+
{
|
30
|
+
"payment_type": "credit_card",
|
31
|
+
"transaction_details": {
|
32
|
+
"gross_amount": 10000,
|
33
|
+
"order_id": "ruby-example-coreapi-creditcard-#{Time.now.to_i}"
|
34
|
+
},
|
35
|
+
"credit_card": {
|
36
|
+
"token_id": "#{get_token.token_id}"
|
37
|
+
}
|
38
|
+
}
|
39
|
+
)
|
40
|
+
puts "charge result : #{result.data}"
|
41
|
+
rescue MidtransError => e
|
42
|
+
puts e.message # Basic message error
|
43
|
+
puts e.http_status_code # HTTP status code e.g: 400, 401, etc.
|
44
|
+
puts e.api_response # API response body in String
|
45
|
+
puts e.raw_http_client_data # Raw HTTP client response
|
46
|
+
end
|
47
|
+
|
48
|
+
# result.data this will be Hash representation of the API JSON response, of example:
|
49
|
+
# {
|
50
|
+
# : status_code => "200",
|
51
|
+
# : status_message => "Success, Credit Card transaction is successful",
|
52
|
+
# : channel_response_code => "00",
|
53
|
+
# : channel_response_message => "Approved",
|
54
|
+
# : bank => "bni",
|
55
|
+
# : transaction_id => "21386a6e-6e26-4191-9d05-877aa6063c08",
|
56
|
+
# : order_id => "ruby-example-coreapi-creditcard-1634014338",
|
57
|
+
# : merchant_id => "G686051436",: gross_amount => "10000.00",
|
58
|
+
# : currency => "IDR",
|
59
|
+
# : payment_type => "credit_card",
|
60
|
+
# : transaction_time => "2021-10-12 11:52:18",
|
61
|
+
# : transaction_status => "capture",
|
62
|
+
# : fraud_status => "accept",
|
63
|
+
# : approval_code => "1634014339258",
|
64
|
+
# : masked_card => "521111-1117",
|
65
|
+
# : card_type => "debit"
|
66
|
+
# }
|
@@ -0,0 +1,7 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
gem 'sinatra'
|
3
|
+
gem 'veritrans', path: "./../../" # install from local path, for testing purpose
|
4
|
+
|
5
|
+
# @NOTE: in real usage scenario, for your project dependency you should only require
|
6
|
+
# gem 'veritrans'
|
7
|
+
# so the gem will be installed directly from rubygem repo. No need the `, path: "./../../"`
|
@@ -0,0 +1,202 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Midtrans-Ruby simple demo</title>
|
5
|
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/featherlight/1.7.12/featherlight.min.css">
|
6
|
+
</head>
|
7
|
+
<body>
|
8
|
+
|
9
|
+
<header>
|
10
|
+
<h3>Midtrans sample demo sinatra app</h3>
|
11
|
+
<a href="https://github.com/veritrans/veritrans-ruby" class="github">Source Code</a>
|
12
|
+
</header>
|
13
|
+
|
14
|
+
<section>
|
15
|
+
<h4>Snap Popup</h4>
|
16
|
+
<a href="/snap">Click here</a>
|
17
|
+
</section>
|
18
|
+
|
19
|
+
<section>
|
20
|
+
<h4>Snap Redirect</h4>
|
21
|
+
<a href="/snap_redirect">Click here</a>
|
22
|
+
</section>
|
23
|
+
<br>
|
24
|
+
<h3>Core API Credit Card</h3>
|
25
|
+
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/picomodal/3.0.0/picoModal.js"></script>
|
26
|
+
|
27
|
+
<h1>Checkout</h1>
|
28
|
+
<form action="/coreapi_card_charge_ajax_handler" method="POST" id="payment-form">
|
29
|
+
<fieldset>
|
30
|
+
<legend>Checkout</legend>
|
31
|
+
<small><strong>Field that may be presented to customer:</strong></small>
|
32
|
+
<p>
|
33
|
+
<label>Card Number</label>
|
34
|
+
<input class="card-number" value="4811 1111 1111 1114" size="23" type="text" autocomplete="off" />
|
35
|
+
</p>
|
36
|
+
<p>
|
37
|
+
<label>Expiration (MM/YYYY)</label>
|
38
|
+
<input class="card-expiry-month" value="12" placeholder="MM" size="2" type="text" />
|
39
|
+
<span> / </span>
|
40
|
+
<input class="card-expiry-year" value="2025" placeholder="YYYY" size="4" type="text" />
|
41
|
+
</p>
|
42
|
+
<p>
|
43
|
+
<label>CVV</label>
|
44
|
+
<input class="card-cvv" value="123" size="4" type="password" autocomplete="off" />
|
45
|
+
</p>
|
46
|
+
|
47
|
+
<small><strong>Fields that shouldn't be presented to the customer:</strong></small>
|
48
|
+
<p>
|
49
|
+
<label>3D Secure</label>
|
50
|
+
<input class="authenticate_3ds" type="checkbox" name="authenticate_3ds" value="true" checked>
|
51
|
+
</p>
|
52
|
+
|
53
|
+
<input id="token_id" name="token_id" type="hidden" />
|
54
|
+
<button class="submit-button" type="submit">Submit Payment</button>
|
55
|
+
</fieldset>
|
56
|
+
</form>
|
57
|
+
|
58
|
+
<code>
|
59
|
+
<b>Transaction Result:</b>
|
60
|
+
<pre id="result"> Awaiting transactions... </pre>
|
61
|
+
<b>Transaction verified status result:</b>
|
62
|
+
<pre id="status-result"> Awaiting transactions... </pre>
|
63
|
+
<pre>
|
64
|
+
<b>Testing cards:</b>
|
65
|
+
|
66
|
+
<b>For 3D Secure:</b>
|
67
|
+
Visa success 4811 1111 1111 1114
|
68
|
+
Visa deny by bank 4711 1111 1111 1115
|
69
|
+
Visa deny by FDS 4611 1111 1111 1116
|
70
|
+
|
71
|
+
MasterCard success 5211 1111 1111 1117
|
72
|
+
MasterCard deny by bank 5111 1111 1111 1118
|
73
|
+
MasterCard deny by FDS 5411 1111 1111 1115
|
74
|
+
|
75
|
+
Challenge by FDS 4511 1111 1111 1117
|
76
|
+
</pre>
|
77
|
+
</code>
|
78
|
+
|
79
|
+
<!-- Import MidtransNew3ds library -->
|
80
|
+
<!-- TODO change data-environment to `production` for Production mode -->
|
81
|
+
<!-- TODO change data-client-key to your production client key for Production mode -->
|
82
|
+
<script id= "midtrans-script" src="https://api.midtrans.com/v2/assets/js/midtrans-new-3ds.min.js" data-environment="sandbox" data-client-key=<%= Midtrans.config.client_key %> type="text/javascript"></script>
|
83
|
+
|
84
|
+
<!-- Javascript for token generation -->
|
85
|
+
<script type="text/javascript">
|
86
|
+
// On Submit button clicked
|
87
|
+
document.querySelector(".submit-button").onclick = function (event) {
|
88
|
+
console.log("SUBMIT button clicked");
|
89
|
+
// prepare cardData
|
90
|
+
var cardData = {
|
91
|
+
"card_number": document.querySelector(".card-number").value,
|
92
|
+
"card_exp_month": document.querySelector(".card-expiry-month").value,
|
93
|
+
"card_exp_year": document.querySelector(".card-expiry-year").value,
|
94
|
+
"card_cvv": document.querySelector(".card-cvv").value,
|
95
|
+
};
|
96
|
+
// [1] Use card data to get card token on the callback
|
97
|
+
MidtransNew3ds.getCardToken(cardData, getCardTokenCallback);
|
98
|
+
|
99
|
+
event.preventDefault(); return false;
|
100
|
+
};
|
101
|
+
|
102
|
+
// getCardTokenCallback triggered when `MidtransNew3ds.getCardToken` completed.
|
103
|
+
var getCardTokenCallback = {
|
104
|
+
onSuccess: function(response){
|
105
|
+
// success to get card token
|
106
|
+
// [2] Send AJAX to let backend charge the card using the card token_id
|
107
|
+
fetch("/coreapi_card_charge_ajax_handler", {
|
108
|
+
method : "POST",
|
109
|
+
body: JSON.stringify({
|
110
|
+
"token_id" : response.token_id,
|
111
|
+
"authenticate_3ds" : document.querySelector('.authenticate_3ds').checked
|
112
|
+
}),
|
113
|
+
headers: {'Content-Type': 'application/json'},
|
114
|
+
})
|
115
|
+
.then(function(response) { return response.json(); })
|
116
|
+
.then(function(responseObj) {
|
117
|
+
console.log("Charge response:",responseObj);
|
118
|
+
if (responseObj.status_code == "201"){
|
119
|
+
// [3.1] Transaction need 3DS authentication
|
120
|
+
MidtransNew3ds.authenticate(responseObj.redirect_url, callback3dsAuthentication);
|
121
|
+
} else {
|
122
|
+
// Transaction do not need 3DS Authentication, transaction is complete with result
|
123
|
+
transactionComplete(responseObj);
|
124
|
+
}
|
125
|
+
})
|
126
|
+
},
|
127
|
+
onFailure: function(response){
|
128
|
+
// fail to get card token
|
129
|
+
transactionComplete(response);
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
133
|
+
var callback3dsAuthentication = {
|
134
|
+
performAuthentication: function(redirect_url){
|
135
|
+
// [3.2] 3ds authentication redirect_url received, open iframe to display to customer
|
136
|
+
popupModal.openPopup(redirect_url);
|
137
|
+
},
|
138
|
+
// [3.3] When 3DS authentication result received, which contains transaction result
|
139
|
+
// it will trigger one of function below, according to status: success/failure/pending
|
140
|
+
onSuccess: function(response){
|
141
|
+
transactionComplete(response);
|
142
|
+
},
|
143
|
+
onFailure: function(response){
|
144
|
+
transactionComplete(response);
|
145
|
+
},
|
146
|
+
onPending: function(response){
|
147
|
+
transactionComplete(response);
|
148
|
+
|
149
|
+
}
|
150
|
+
}
|
151
|
+
|
152
|
+
function transactionComplete(responseObj){
|
153
|
+
// Close 3DS popup, then display the result (for example)
|
154
|
+
console.log("transactionComplete with status: ",responseObj);
|
155
|
+
popupModal.closePopup();
|
156
|
+
|
157
|
+
document.querySelector("#result").innerText = JSON.stringify(responseObj, null, 2);
|
158
|
+
document.querySelector("#result").scrollIntoView();
|
159
|
+
|
160
|
+
if (responseObj.transaction_id){
|
161
|
+
// [4] Inform the result to backend update DB status and verify to Midtrans
|
162
|
+
fetch('/check_transaction_status', {
|
163
|
+
method : "POST",
|
164
|
+
body: JSON.stringify({ "transaction_id" : responseObj.transaction_id }),
|
165
|
+
headers: {'Content-Type': 'application/json'},
|
166
|
+
})
|
167
|
+
.then(function(statusResponse) { return statusResponse.json(); } )
|
168
|
+
.then(function(statusResponseObj) {
|
169
|
+
// Transaction status received after being verified
|
170
|
+
console.log("Check transaction response:",statusResponseObj);
|
171
|
+
// transactionComplete(statusResponseObj);
|
172
|
+
document.querySelector("#status-result").innerText =
|
173
|
+
JSON.stringify(statusResponseObj, null, 2);
|
174
|
+
|
175
|
+
})
|
176
|
+
}
|
177
|
+
}
|
178
|
+
|
179
|
+
// helper functions below
|
180
|
+
let popupModal = (function(){
|
181
|
+
let modal = null;
|
182
|
+
return {
|
183
|
+
openPopup(url){
|
184
|
+
modal = picoModal({
|
185
|
+
content:'<iframe frameborder="0" style="height:90vh; width:100%;" src="'+url+'"></iframe>',
|
186
|
+
width: "75%",
|
187
|
+
closeButton: false,
|
188
|
+
overlayClose: false,
|
189
|
+
escCloses: false
|
190
|
+
}).show();
|
191
|
+
},
|
192
|
+
closePopup(){
|
193
|
+
try{
|
194
|
+
modal.close();
|
195
|
+
} catch(e) {}
|
196
|
+
}
|
197
|
+
}
|
198
|
+
}());
|
199
|
+
</script>
|
200
|
+
|
201
|
+
</body>
|
202
|
+
</html>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= @result.response.body %>
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html>
|
3
|
+
|
4
|
+
<body>
|
5
|
+
<p>
|
6
|
+
<label>Snap Token</label>
|
7
|
+
<input type="text" id="token" value="<%= @token %>" readonly size="50">
|
8
|
+
</p>
|
9
|
+
<button id="pay-button">Pay</button>
|
10
|
+
<pre><div id="result-json">JSON result will appear here after payment:<br></div></pre>
|
11
|
+
|
12
|
+
<!-- TODO: Remove ".sandbox" from script src URL for production environment. Also input your client key in "data-client-key" -->
|
13
|
+
<script src="https://app.sandbox.midtrans.com/snap/snap.js" data-client-key=<%= Midtrans.config.client_key %>></script>
|
14
|
+
<script type="text/javascript">
|
15
|
+
document.getElementById('pay-button').onclick = function(){
|
16
|
+
// SnapToken acquired from previous step
|
17
|
+
snap.pay('<%= @token %>', {
|
18
|
+
// Optional
|
19
|
+
onSuccess: function(result){
|
20
|
+
/* You may add your own js here, this is just example */ document.getElementById('result-json').innerHTML += JSON.stringify(result, null, 2);
|
21
|
+
},
|
22
|
+
// Optional
|
23
|
+
onPending: function(result){
|
24
|
+
/* You may add your own js here, this is just example */ document.getElementById('result-json').innerHTML += JSON.stringify(result, null, 2);
|
25
|
+
},
|
26
|
+
// Optional
|
27
|
+
onError: function(result){
|
28
|
+
/* You may add your own js here, this is just example */ document.getElementById('result-json').innerHTML += JSON.stringify(result, null, 2);
|
29
|
+
}
|
30
|
+
});
|
31
|
+
};
|
32
|
+
</script>
|
33
|
+
</body>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html>
|
3
|
+
|
4
|
+
<body>
|
5
|
+
<p>
|
6
|
+
<label>Snap Redirect URL</label>
|
7
|
+
<input type="text" id="Redirect URL" value="<%= @redirecturl %>" readonly size="50"><br><br>
|
8
|
+
<button onclick="location.href='<%= @redirecturl %>'">Open Snap Redirect URL</button></p>
|
9
|
+
</body>
|
10
|
+
</html>
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'veritrans'
|
2
|
+
require 'json'
|
3
|
+
require 'sinatra'
|
4
|
+
|
5
|
+
Midtrans.config.server_key = "SB-Mid-server-uQmMImQMeo0Ky3Svl90QTUj2"
|
6
|
+
Midtrans.config.client_key = "SB-Mid-client-ArNfhrh7st9bQKmz"
|
7
|
+
Midtrans.config.api_host = "https://api.sandbox.midtrans.com"
|
8
|
+
|
9
|
+
set :public_folder, File.dirname(__FILE__)
|
10
|
+
set :views, File.dirname(__FILE__)
|
11
|
+
set :run, $0 == __FILE__
|
12
|
+
|
13
|
+
def generate_order_id
|
14
|
+
"sinatra-example-#{Time.now.to_i}"
|
15
|
+
end
|
16
|
+
|
17
|
+
get "/" do
|
18
|
+
erb :index
|
19
|
+
end
|
20
|
+
|
21
|
+
get "/snap" do
|
22
|
+
result = Midtrans.create_snap_token(
|
23
|
+
transaction_details: {
|
24
|
+
order_id: generate_order_id,
|
25
|
+
gross_amount: 100000,
|
26
|
+
secure: true
|
27
|
+
}
|
28
|
+
)
|
29
|
+
@token = result.token
|
30
|
+
erb :snap
|
31
|
+
end
|
32
|
+
|
33
|
+
get "/snap_redirect" do
|
34
|
+
result = Midtrans.create_snap_redirect_url(
|
35
|
+
transaction_details: {
|
36
|
+
order_id: generate_order_id,
|
37
|
+
gross_amount: 100000,
|
38
|
+
secure: true
|
39
|
+
}
|
40
|
+
)
|
41
|
+
@redirecturl = result.redirect_url
|
42
|
+
erb :snap_redirect
|
43
|
+
end
|
44
|
+
|
45
|
+
post "/coreapi_card_charge_ajax_handler" do
|
46
|
+
@data = JSON.parse(request.body.read)
|
47
|
+
@result = Midtrans.charge(
|
48
|
+
payment_type: "credit_card",
|
49
|
+
credit_card: {
|
50
|
+
token_id: @data['token_id'],
|
51
|
+
authentication: @data['authenticate_3ds']
|
52
|
+
},
|
53
|
+
transaction_details: {
|
54
|
+
order_id: generate_order_id,
|
55
|
+
gross_amount: 20000
|
56
|
+
})
|
57
|
+
|
58
|
+
if params[:format] == "json"
|
59
|
+
content_type :json
|
60
|
+
@result.response.body
|
61
|
+
else
|
62
|
+
erb :response
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
post "/check_transaction_status" do
|
67
|
+
@data = JSON.parse(request.body.read)
|
68
|
+
transaction_id = @data['transaction_id']
|
69
|
+
@result = Midtrans.status(transaction_id)
|
70
|
+
|
71
|
+
if params[:format] == "json"
|
72
|
+
content_type :json
|
73
|
+
@result.response.body
|
74
|
+
else
|
75
|
+
erb :response
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
post "/handle_http_notification" do
|
80
|
+
post_body = JSON.parse(request.body.read)
|
81
|
+
notification = Midtrans.status(post_body['transaction_id'])
|
82
|
+
|
83
|
+
order_id = notification.data[:order_id]
|
84
|
+
payment_type = notification.data[:payment_type]
|
85
|
+
transaction_status = notification.data[:transaction_status]
|
86
|
+
fraud_status = notification.data[:fraud_status]
|
87
|
+
|
88
|
+
puts "Transaction order_id: #{order_id}"
|
89
|
+
puts "Payment type: #{payment_type}"
|
90
|
+
puts "Transaction status: #{transaction_status}"
|
91
|
+
puts "Fraud status: #{fraud_status}"
|
92
|
+
|
93
|
+
return "Transaction notification received. Order ID: #{order_id}. Transaction status: #{transaction_status}. Fraud status: #{fraud_status}"
|
94
|
+
|
95
|
+
# Sample transactionStatus handling logic
|
96
|
+
if transaction_status == "capture" && fraud_status == "challange"
|
97
|
+
# TODO set transaction status on your databaase to 'challenge'
|
98
|
+
elsif transaction_status == "capture" && fraud_status == "success"
|
99
|
+
# TODO set transaction status on your databaase to 'success'
|
100
|
+
elsif transaction_status == "settlement"
|
101
|
+
# TODO set transaction status on your databaase to 'success'
|
102
|
+
elsif transaction_status == "deny"
|
103
|
+
# TODO you can ignore 'deny', because most of the time it allows payment retries
|
104
|
+
elsif transaction_status == "cancel" || transaction_status == "expire"
|
105
|
+
# TODO set transaction status on your databaase to 'failure'
|
106
|
+
elsif transaction_status == "pending"
|
107
|
+
# Todo set transaction status on your databaase to 'pending' / waiting payment
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
|
@@ -0,0 +1,39 @@
|
|
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
|
+
# Please refer to this docs for snap popup:
|
5
|
+
# https://docs.midtrans.com/en/snap/integration-guide?id=integration-steps-overview
|
6
|
+
|
7
|
+
# Please refer to this docs for snap-redirect:
|
8
|
+
# https://docs.midtrans.com/en/snap/integration-guide?id=alternative-way-to-display-snap-payment-page-via-redirect
|
9
|
+
|
10
|
+
# Set Midtrans config
|
11
|
+
# You can find it in Merchant Portal -> Settings -> Access keys
|
12
|
+
Midtrans.config.server_key = "SB-Mid-server-uQmMImQMeo0Ky3Svl90QTUj2"
|
13
|
+
Midtrans.config.client_key = "SB-Mid-client-ArNfhrh7st9bQKmz"
|
14
|
+
Midtrans.config.api_host = "https://api.sandbox.midtrans.com"
|
15
|
+
|
16
|
+
# Create snap transaction
|
17
|
+
begin
|
18
|
+
result = Midtrans.create_snap_token(
|
19
|
+
transaction_details: {
|
20
|
+
order_id: "snap-example-test-#{Time.now.to_i}",
|
21
|
+
gross_amount: 200000
|
22
|
+
},
|
23
|
+
"credit_card": {
|
24
|
+
"secure": true
|
25
|
+
}
|
26
|
+
)
|
27
|
+
puts "Snap result : #{result.data}"
|
28
|
+
rescue MidtransError => e
|
29
|
+
puts e.message # Basic message error
|
30
|
+
puts e.http_status_code # HTTP status code e.g: 400, 401, etc.
|
31
|
+
puts e.api_response # API response body in String
|
32
|
+
puts e.raw_http_client_data # Raw HTTP client response
|
33
|
+
end
|
34
|
+
|
35
|
+
# result.data this will be Hash representation of the API JSON response, of example:
|
36
|
+
# {
|
37
|
+
# : token => "008e586b-17f5-459f-8418-2764f08f1d8c",
|
38
|
+
# : redirect_url => "https://app.sandbox.midtrans.com/snap/v2/vtweb/008e586b-17f5-459f-8418-2764f08f1d8c"
|
39
|
+
# }
|
data/lib/test/all.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Dir[File.dirname(File.absolute_path(__FILE__)) + '/**/*_test.rb'].each {|file| require file }
|