hps 2.2.2 → 2.2.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/examples/sinatra-verify-only/Gemfile +4 -0
- data/examples/sinatra-verify-only/app.rb +32 -0
- data/examples/sinatra-verify-only/public/images/cvv.png +0 -0
- data/examples/sinatra-verify-only/public/images/cvv1.png +0 -0
- data/examples/sinatra-verify-only/public/images/cvv2.png +0 -0
- data/examples/sinatra-verify-only/public/images/ss-cvv@2x.png +0 -0
- data/examples/sinatra-verify-only/public/images/ss-inputcard-blank@2x.png +0 -0
- data/examples/sinatra-verify-only/public/images/ss-saved-amex@2x.png +0 -0
- data/examples/sinatra-verify-only/public/images/ss-saved-discover@2x.png +0 -0
- data/examples/sinatra-verify-only/public/images/ss-saved-jcb@2x.png +0 -0
- data/examples/sinatra-verify-only/public/images/ss-saved-mastercard.png +0 -0
- data/examples/sinatra-verify-only/public/images/ss-saved-mastercard@2x.png +0 -0
- data/examples/sinatra-verify-only/public/images/ss-saved-visa@2x.png +0 -0
- data/examples/sinatra-verify-only/public/images/ss-savedcards-amex@2x.png +0 -0
- data/examples/sinatra-verify-only/public/images/ss-shield-ie.png +0 -0
- data/examples/sinatra-verify-only/public/images/ss-shield@1x.png +0 -0
- data/examples/sinatra-verify-only/public/images/ss-shield@2x.png +0 -0
- data/examples/sinatra-verify-only/views/index.erb +478 -0
- data/examples/sinatra-verify-only/views/result.erb +39 -0
- data/lib/hps.rb +1 -0
- data/lib/hps/entities/hps_manage_tokens.rb +9 -0
- data/lib/hps/services/hps_charge_service.rb +38 -0
- data/lib/hps/version.rb +1 -1
- data/tests/general_tests.rb +94 -19
- metadata +23 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76db4e4f82ebe0a3399a498fc68055353cf82a7f
|
4
|
+
data.tar.gz: e61ba75e59c12b39e293faf121c4852895f38895
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59b397a58ee800edac5b043b0f6208120e45a4f539674b816a21b5b46cc8bbfd495ee86e146b32e502b09dae6c27ca3affd4a50c022901cf86a2b07997a100b7
|
7
|
+
data.tar.gz: 789fdfd04c540a00cb620749419c2632527f25b4f8d89216ebee189209c4daf2a90269370da5efa9d9b40d9094b74d8bba69a57ecf725fe8b0a8ceff6267f23f
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'sinatra'
|
2
|
+
require 'hps'
|
3
|
+
|
4
|
+
Hps.configure do |config|
|
5
|
+
config.secret_api_key = 'skapi_cert_MTyMAQBiHVEAewvIzXVFcmUd2UcyBge_eCpaASUp0A'
|
6
|
+
end
|
7
|
+
|
8
|
+
service = Hps::HpsChargeService.new
|
9
|
+
|
10
|
+
get '/' do
|
11
|
+
erb :index
|
12
|
+
end
|
13
|
+
|
14
|
+
post '/charge' do
|
15
|
+
card_holder = Hps::HpsCardHolder.new
|
16
|
+
card_holder.first_name = request['FirstName']
|
17
|
+
card_holder.last_name = request['LastName']
|
18
|
+
card_holder.address = Hps::HpsAddress.new
|
19
|
+
card_holder.address.address = request['Address']
|
20
|
+
card_holder.address.city = request['City']
|
21
|
+
card_holder.address.state = request['State']
|
22
|
+
card_holder.address.zip = request['Zip']
|
23
|
+
|
24
|
+
token = request['token_value']
|
25
|
+
|
26
|
+
logger.info card_holder
|
27
|
+
logger.info token
|
28
|
+
|
29
|
+
verification = service.verify(token, card_holder, true)
|
30
|
+
|
31
|
+
erb :result, :locals => { :verification => verification }
|
32
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,478 @@
|
|
1
|
+
<!--[if IE]><![endif]-->
|
2
|
+
<!--[if lt IE 7 ]> <html lang="en" class="ie6"> <![endif]-->
|
3
|
+
<!--[if IE 7 ]> <html lang="en" class="ie7"> <![endif]-->
|
4
|
+
<!--[if IE 8 ]> <html lang="en" class="ie8"> <![endif]-->
|
5
|
+
<!--[if IE 9 ]> <html lang="en" class="ie9"> <![endif]-->
|
6
|
+
<!--[if (gt IE 9)|!(IE)]><!-->
|
7
|
+
<html lang="en"><!--<![endif]-->
|
8
|
+
<head>
|
9
|
+
<meta charset="utf-8">
|
10
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
11
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
12
|
+
<meta name="description" content="SecureSubmit Ruby end-to-end payment example using tokenization.">
|
13
|
+
<meta name="author" content="Mark Hagan">
|
14
|
+
<title>Simple Payment Form Demo</title>
|
15
|
+
|
16
|
+
<link src="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.css">
|
17
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script>
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<div class="container">
|
21
|
+
<div class="row col-xs-12">
|
22
|
+
<h1>Ruby SecureSubmit Example</h1>
|
23
|
+
</div>
|
24
|
+
|
25
|
+
<form class="payment_form form-horizontal" id="payment_form" action="/charge" method="POST">
|
26
|
+
<div class="form-group row">
|
27
|
+
<label for="FirstName" class="col-sm-2 control-label">First Name</label>
|
28
|
+
<div class="col-sm-10">
|
29
|
+
<input type="text" name="FirstName" />
|
30
|
+
</div>
|
31
|
+
</div>
|
32
|
+
<div class="form-group row">
|
33
|
+
<label for="LastName" class="col-sm-2 control-label">Last Name</label>
|
34
|
+
<div class="col-sm-10">
|
35
|
+
<input type="text" name="LastName" />
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
<div class="form-group row">
|
39
|
+
<label for="Address" class="col-sm-2 control-label">Address</label>
|
40
|
+
<div class="col-sm-10">
|
41
|
+
<input type="text" name="Address" />
|
42
|
+
</div>
|
43
|
+
</div>
|
44
|
+
<div class="form-group row">
|
45
|
+
<label for="City" class="col-sm-2 control-label">City</label>
|
46
|
+
<div class="col-sm-10">
|
47
|
+
<input type="text" name="City" />
|
48
|
+
</div>
|
49
|
+
</div>
|
50
|
+
<div class="form-group row">
|
51
|
+
<label for="State" class="col-sm-2 control-label">State</label>
|
52
|
+
<div class="col-sm-10">
|
53
|
+
<select Name="State">
|
54
|
+
<option value="AL">Alabama</option>
|
55
|
+
<option value="AK">Alaska</option>
|
56
|
+
<option value="AZ">Arizona</option>
|
57
|
+
<option value="AR">Arkansas</option>
|
58
|
+
<option value="CA">California</option>
|
59
|
+
<option value="CO">Colorado</option>
|
60
|
+
<option value="CT">Connecticut</option>
|
61
|
+
<option value="DE">Delaware</option>
|
62
|
+
<option value="DC">District Of Columbia</option>
|
63
|
+
<option value="FL">Florida</option>
|
64
|
+
<option value="GA">Georgia</option>
|
65
|
+
<option value="HI">Hawaii</option>
|
66
|
+
<option value="ID">Idaho</option>
|
67
|
+
<option value="IL">Illinois</option>
|
68
|
+
<option value="IN">Indiana</option>
|
69
|
+
<option value="IA">Iowa</option>
|
70
|
+
<option value="KS">Kansas</option>
|
71
|
+
<option value="KY">Kentucky</option>
|
72
|
+
<option value="LA">Louisiana</option>
|
73
|
+
<option value="ME">Maine</option>
|
74
|
+
<option value="MD">Maryland</option>
|
75
|
+
<option value="MA">Massachusetts</option>
|
76
|
+
<option value="MI">Michigan</option>
|
77
|
+
<option value="MN">Minnesota</option>
|
78
|
+
<option value="MS">Mississippi</option>
|
79
|
+
<option value="MO">Missouri</option>
|
80
|
+
<option value="MT">Montana</option>
|
81
|
+
<option value="NE">Nebraska</option>
|
82
|
+
<option value="NV">Nevada</option>
|
83
|
+
<option value="NH">New Hampshire</option>
|
84
|
+
<option value="NJ">New Jersey</option>
|
85
|
+
<option value="NM">New Mexico</option>
|
86
|
+
<option value="NY">New York</option>
|
87
|
+
<option value="NC">North Carolina</option>
|
88
|
+
<option value="ND">North Dakota</option>
|
89
|
+
<option value="OH">Ohio</option>
|
90
|
+
<option value="OK">Oklahoma</option>
|
91
|
+
<option value="OR">Oregon</option>
|
92
|
+
<option value="PA">Pennsylvania</option>
|
93
|
+
<option value="RI">Rhode Island</option>
|
94
|
+
<option value="SC">South Carolina</option>
|
95
|
+
<option value="SD">South Dakota</option>
|
96
|
+
<option value="TN">Tennessee</option>
|
97
|
+
<option value="TX">Texas</option>
|
98
|
+
<option value="UT">Utah</option>
|
99
|
+
<option value="VT">Vermont</option>
|
100
|
+
<option value="VA">Virginia</option>
|
101
|
+
<option value="WA">Washington</option>
|
102
|
+
<option value="WV">West Virginia</option>
|
103
|
+
<option value="WI">Wisconsin</option>
|
104
|
+
<option value="WY">Wyoming</option>
|
105
|
+
</select>
|
106
|
+
</div>
|
107
|
+
</div>
|
108
|
+
<div class="form-group row">
|
109
|
+
<label for="Zip" class="col-sm-2 control-label">Zip</label>
|
110
|
+
<div class="col-sm-10">
|
111
|
+
<input type="text" name="Zip" />
|
112
|
+
</div>
|
113
|
+
</div>
|
114
|
+
|
115
|
+
<div class="container">
|
116
|
+
<div class="row col-xs-12">
|
117
|
+
<h2>Card Information</h2>
|
118
|
+
<div id="ss-banner">
|
119
|
+
</div>
|
120
|
+
</div>
|
121
|
+
<!-- make iframes styled like other form -->
|
122
|
+
<style type="text/css">
|
123
|
+
body {
|
124
|
+
font-family:sans-serif;
|
125
|
+
}
|
126
|
+
#iframes iframe{
|
127
|
+
float:left;
|
128
|
+
width:100%;
|
129
|
+
}
|
130
|
+
.form-group {
|
131
|
+
height:40px;
|
132
|
+
}
|
133
|
+
h2 {
|
134
|
+
margin:7px 0;
|
135
|
+
}
|
136
|
+
#ss-card,
|
137
|
+
#ss-date,
|
138
|
+
#ss-cvv {
|
139
|
+
height:85px;
|
140
|
+
}
|
141
|
+
#ss-card {
|
142
|
+
margin-bottom:55px;
|
143
|
+
display:block;
|
144
|
+
}
|
145
|
+
#ss-date {
|
146
|
+
float:left;
|
147
|
+
display:block;
|
148
|
+
}
|
149
|
+
#ss-cvv.form-group {
|
150
|
+
float:right;
|
151
|
+
}
|
152
|
+
.ie8 form .iframeholder {
|
153
|
+
padding:10px;
|
154
|
+
}
|
155
|
+
.iframeholder::after{
|
156
|
+
content:'';
|
157
|
+
display:block;
|
158
|
+
width:100%;
|
159
|
+
height:0px;
|
160
|
+
clear:both;
|
161
|
+
position:relative;
|
162
|
+
}
|
163
|
+
.ie8 form .form-group {
|
164
|
+
margin-bottom:5px;
|
165
|
+
}
|
166
|
+
textarea {
|
167
|
+
padding:10px;
|
168
|
+
font-family:sans-serif;
|
169
|
+
}
|
170
|
+
label[for=iframesCardNumber],
|
171
|
+
label[for=iframesCardExpiration],
|
172
|
+
label[for=iframesCardCvv]{
|
173
|
+
text-transform:uppercase;
|
174
|
+
font-weight:500;
|
175
|
+
font-size:13px;
|
176
|
+
color:#555;
|
177
|
+
line-height:1.5;
|
178
|
+
}
|
179
|
+
.ie8 form label {
|
180
|
+
padding-left:10px;
|
181
|
+
margin:0px;
|
182
|
+
}
|
183
|
+
#heartland-frame-cardExpiration,
|
184
|
+
#heartland-frame-cardCvv,
|
185
|
+
#heartland-frame-cardNumber,
|
186
|
+
.ie8 #heartland-frame-cardExpiration,
|
187
|
+
.ie8 #heartland-frame-cardCvv,
|
188
|
+
.ie8 #heartland-frame-cardNumber {
|
189
|
+
width:100%;
|
190
|
+
}
|
191
|
+
iframe {
|
192
|
+
margin:0;
|
193
|
+
padding:0;
|
194
|
+
border:none;
|
195
|
+
width:value;
|
196
|
+
height:value;
|
197
|
+
}
|
198
|
+
#ss-banner {
|
199
|
+
background:transparent url(/images/ss-shield@2x.png) no-repeat left center;
|
200
|
+
height:40px;
|
201
|
+
background-size:280px 34px;
|
202
|
+
margin-bottom:7px;
|
203
|
+
}
|
204
|
+
.ie8 #ss-banner {
|
205
|
+
background:transparent url(/images/ss-shield-ie.png) no-repeat left center;
|
206
|
+
}
|
207
|
+
.btn-primary{
|
208
|
+
display:block;
|
209
|
+
border-radius:0px;
|
210
|
+
font-size:18px;
|
211
|
+
float:right;
|
212
|
+
background-color:#36b46e;
|
213
|
+
border:1px solid #2a8d56;
|
214
|
+
margin-bottom:10px;
|
215
|
+
height:50px;
|
216
|
+
color:#ffffff;
|
217
|
+
width:100%;
|
218
|
+
}
|
219
|
+
.btn-primary:hover,
|
220
|
+
.btn-primary:focus{
|
221
|
+
color: #fff;
|
222
|
+
background-color: #2a8d56;
|
223
|
+
}
|
224
|
+
.ie8 .btn-primary {
|
225
|
+
width:15%;
|
226
|
+
}
|
227
|
+
.red {
|
228
|
+
color:#ce2027;
|
229
|
+
margin-left:2px;
|
230
|
+
font-size:17px;
|
231
|
+
}
|
232
|
+
.container {
|
233
|
+
margin:5px;
|
234
|
+
}
|
235
|
+
#ss-date.form-group,
|
236
|
+
#ss-cvv.form-group{
|
237
|
+
width:100%;
|
238
|
+
}
|
239
|
+
|
240
|
+
|
241
|
+
@media screen and (min-width:767px) {
|
242
|
+
|
243
|
+
#heartland-frame-cardNumber {
|
244
|
+
width : 100%;
|
245
|
+
}
|
246
|
+
}
|
247
|
+
@media screen and (min-width:696px) {
|
248
|
+
#ss-date.form-group,
|
249
|
+
#ss-cvv.form-group{
|
250
|
+
width:48%;
|
251
|
+
}
|
252
|
+
}
|
253
|
+
@media screen and (min-width:636px) {
|
254
|
+
#ss-card {
|
255
|
+
margin-bottom:40px;
|
256
|
+
}
|
257
|
+
}
|
258
|
+
@media screen and (min-width:450px) {
|
259
|
+
.btn-primary,
|
260
|
+
.ie8 .btn-primary {
|
261
|
+
width:10em;
|
262
|
+
}
|
263
|
+
.container {
|
264
|
+
margin:20px;
|
265
|
+
}
|
266
|
+
}
|
267
|
+
|
268
|
+
</style>
|
269
|
+
|
270
|
+
<!-- The Payment Form -->
|
271
|
+
<form id="iframes" action="" method="GET">
|
272
|
+
<!-- <div class="row col-xs-12">-->
|
273
|
+
<div id="ss-card" class="form-group">
|
274
|
+
<label for="iframesCardNumber">Card Number<span class="red">*</span><label>
|
275
|
+
<div class="iframeholder" id="iframesCardNumber" style="height:50px; width:100%;"></div>
|
276
|
+
</div>
|
277
|
+
<div id="ss-date" class="form-group">
|
278
|
+
<label for="iframesCardExpiration">Card Expiration<span class="red">*</span></label>
|
279
|
+
<div class="iframeholder" id="iframesCardExpiration" style="height:50px; width:100%;"></div>
|
280
|
+
</div>
|
281
|
+
<div id="ss-cvv" class="form-group">
|
282
|
+
<label for="iframesCardCvv">Card CVV<span class="red">*</span></label>
|
283
|
+
<div class="iframeholder" id="iframesCardCvv" style="height:50px; width:100%;" /></div>
|
284
|
+
</div>
|
285
|
+
<div style="clear:both"></div>
|
286
|
+
<input id="iframesSubmit" type="submit" class="btn btn-lg btn-primary" value="Submit" />
|
287
|
+
</form>
|
288
|
+
|
289
|
+
<!-- The SecureSubmit Javascript Library -->
|
290
|
+
<script type="text/javascript" src="https://api2.heartlandportico.com/SecureSubmit.v1/token/2.1/securesubmit.js" href="assets/securesubmit.js"></script>
|
291
|
+
|
292
|
+
<input type="hidden" name="token_value">
|
293
|
+
</form>
|
294
|
+
|
295
|
+
</div>
|
296
|
+
<!-- The Integration Code -->
|
297
|
+
<script type="text/javascript">
|
298
|
+
(function (document, Heartland) {
|
299
|
+
// Create a new `HPS` object with the necessary configuration
|
300
|
+
var hps = new Heartland.HPS({
|
301
|
+
publicKey: 'pkapi_cert_jKc1FtuyAydZhZfbB3',
|
302
|
+
type: 'iframe',
|
303
|
+
// Configure the iframe fields to tell the library where
|
304
|
+
// the iframe should be inserted into the DOM and some
|
305
|
+
// basic options
|
306
|
+
fields: {
|
307
|
+
cardNumber: {
|
308
|
+
target: 'iframesCardNumber',
|
309
|
+
placeholder: '•••• •••• •••• ••••'
|
310
|
+
},
|
311
|
+
cardExpiration: {
|
312
|
+
target: 'iframesCardExpiration',
|
313
|
+
placeholder: 'MM / YYYY'
|
314
|
+
},
|
315
|
+
cardCvv: {
|
316
|
+
target: 'iframesCardCvv',
|
317
|
+
placeholder: 'CVV'
|
318
|
+
}
|
319
|
+
},
|
320
|
+
// Collection of CSS to inject into the iframes.
|
321
|
+
// These properties can match the site's styles
|
322
|
+
// to create a seamless experience.
|
323
|
+
style: {
|
324
|
+
'input': {
|
325
|
+
'background': '#fff',
|
326
|
+
'border': '1px solid',
|
327
|
+
'border-color': '#bbb3b9 #c7c1c6 #c7c1c6',
|
328
|
+
'box-sizing': 'border-box',
|
329
|
+
'font-family': 'serif',
|
330
|
+
'font-size': '16px',
|
331
|
+
'line-height': '1',
|
332
|
+
'margin': '0 .5em 0 0',
|
333
|
+
'max-width': '100%',
|
334
|
+
'outline': '0',
|
335
|
+
'padding': '0.5278em',
|
336
|
+
'vertical-align': 'baseline',
|
337
|
+
},
|
338
|
+
'#heartland-field': {
|
339
|
+
'font-family':'sans-serif',
|
340
|
+
'box-sizing':'border-box',
|
341
|
+
'display': 'block',
|
342
|
+
'height': '50px',
|
343
|
+
'padding': '6px 12px',
|
344
|
+
'font-size': '14px',
|
345
|
+
'line-height': '1.42857143',
|
346
|
+
'color': '#555',
|
347
|
+
'background-color': '#fff',
|
348
|
+
'border': '1px solid #ccc',
|
349
|
+
'border-radius': '0px',
|
350
|
+
'-webkit-box-shadow': 'inset 0 1px 1px rgba(0,0,0,.075)',
|
351
|
+
'box-shadow': 'inset 0 1px 1px rgba(0,0,0,.075)',
|
352
|
+
'-webkit-transition': 'border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s',
|
353
|
+
'-o-transition': 'border-color ease-in-out .15s,box-shadow ease-in-out .15s',
|
354
|
+
'transition': 'border-color ease-in-out .15s,box-shadow ease-in-out .15s',
|
355
|
+
'width':'100%'
|
356
|
+
},
|
357
|
+
'input#heartland-field:focus' : {
|
358
|
+
'border':'1px solid #3989e3',
|
359
|
+
'outline':'none',
|
360
|
+
'box-shadow':'none'
|
361
|
+
},
|
362
|
+
'input[type=submit]' : {
|
363
|
+
'box-sizing':'border-box',
|
364
|
+
'display': 'inline-block',
|
365
|
+
'padding': '6px 12px',
|
366
|
+
'margin-bottom': '0',
|
367
|
+
'font-size': '14px',
|
368
|
+
'font-weight': '400',
|
369
|
+
'line-height': '1.42857143',
|
370
|
+
'text-align': 'center',
|
371
|
+
'white-space': 'nowrap',
|
372
|
+
'vertical-align': 'middle',
|
373
|
+
'-ms-touch-action': 'manipulation',
|
374
|
+
'touch-action': 'manipulation',
|
375
|
+
'cursor': 'pointer',
|
376
|
+
'-webkit-user-select': 'none',
|
377
|
+
'-moz-user-select': 'none',
|
378
|
+
'-ms-user-select': 'none',
|
379
|
+
'user-select': 'none',
|
380
|
+
'background-image': 'none',
|
381
|
+
'border': '1px solid transparent',
|
382
|
+
'border-radius': '4px',
|
383
|
+
'color': '#fff',
|
384
|
+
'background-color': '#337ab7',
|
385
|
+
'border-color': '#2e6da4'
|
386
|
+
},
|
387
|
+
'#heartland-field[placeholder]' :{
|
388
|
+
'letter-spacing':'3px'
|
389
|
+
},
|
390
|
+
'#heartland-field[name=cardCvv]' :{
|
391
|
+
'background':'transparent url('+location.href+ 'images/cvv1.png) no-repeat right',
|
392
|
+
'background-size' :'63px 40px',
|
393
|
+
},
|
394
|
+
'input#heartland-field[name=cardNumber]' : {
|
395
|
+
'background':'transparent url('+location.href+ 'images/ss-inputcard-blank@2x.png) no-repeat right',
|
396
|
+
'background-size' :'55px 35px'},
|
397
|
+
'#heartland-field.invalid.card-type-visa' :{
|
398
|
+
'background':'transparent url('+location.href+ 'images/ss-saved-visa@2x.png) no-repeat right',
|
399
|
+
'background-size' :'83px 88px',
|
400
|
+
'background-position-y':'-44px'
|
401
|
+
},
|
402
|
+
'#heartland-field.valid.card-type-visa' :{
|
403
|
+
'background':'transparent url('+location.href+ 'images/ss-saved-visa@2x.png) no-repeat right top',
|
404
|
+
'background-size' :'82px 86px'
|
405
|
+
},
|
406
|
+
'#heartland-field.invalid.card-type-discover' :{
|
407
|
+
'background':'transparent url('+location.href+ 'images/ss-saved-discover@2x.png) no-repeat right',
|
408
|
+
'background-size' :'85px 90px',
|
409
|
+
'background-position-y' : '-44px'
|
410
|
+
},
|
411
|
+
'#heartland-field.valid.card-type-discover' :{
|
412
|
+
'background':'transparent url('+location.href+ 'images/ss-saved-discover@2x.png) no-repeat right',
|
413
|
+
'background-size' :'85px 90px',
|
414
|
+
'background-position-y' : '1px'
|
415
|
+
},
|
416
|
+
'#heartland-field.invalid.card-type-amex' :{
|
417
|
+
'background':'transparent url('+location.href+ 'images/ss-savedcards-amex@2x.png) no-repeat right',
|
418
|
+
'background-size' :'50px 90px',
|
419
|
+
'background-position-y':'-44px'
|
420
|
+
},
|
421
|
+
'#heartland-field.valid.card-type-amex' :{
|
422
|
+
'background':'transparent url('+location.href+ 'images/ss-savedcards-amex@2x.png) no-repeat right top',
|
423
|
+
'background-size' :'50px 90px'
|
424
|
+
},
|
425
|
+
'#heartland-field.invalid.card-type-mastercard' :{
|
426
|
+
'background':'transparent url('+location.href+ 'images/ss-saved-mastercard.png) no-repeat right',
|
427
|
+
'background-size' :'62px 105px',
|
428
|
+
'background-position-y':'-52px'
|
429
|
+
},
|
430
|
+
'#heartland-field.valid.card-type-mastercard' :{
|
431
|
+
'background':'transparent url('+location.href+ 'images/ss-saved-mastercard.png) no-repeat right',
|
432
|
+
'background-size' :'62px 105px',
|
433
|
+
'background-position-y':'-1px'
|
434
|
+
},
|
435
|
+
'#heartland-field.invalid.card-type-jcb' :{
|
436
|
+
'background':'transparent url('+location.href+ 'images/ss-saved-jcb@2x.png) no-repeat right',
|
437
|
+
'background-size' :'55px 94px',
|
438
|
+
'background-position-y':'-44px'
|
439
|
+
},
|
440
|
+
'#heartland-field.valid.card-type-jcb' :{
|
441
|
+
'background':'transparent url('+location.href+ 'images/ss-saved-jcb@2x.png) no-repeat right top',
|
442
|
+
'background-size' :'55px 94px',
|
443
|
+
'background-position-y':'2px'
|
444
|
+
},
|
445
|
+
'input#heartland-field[name=cardNumber]::-ms-clear' : {
|
446
|
+
'display':'none'
|
447
|
+
}
|
448
|
+
},
|
449
|
+
// Callback when a token is received from the service
|
450
|
+
onTokenSuccess: function (resp) {
|
451
|
+
document.querySelector("input[name=token_value]").value=resp.token_value;
|
452
|
+
Heartland.Events.removeHandler(document.getElementById('payment_form'), 'submit');
|
453
|
+
document.getElementById('payment_form').submit()
|
454
|
+
},
|
455
|
+
// Callback when an error is received from the service
|
456
|
+
onTokenError: function (resp) {
|
457
|
+
alert('There was an error: ' + resp.error.message);
|
458
|
+
}
|
459
|
+
});
|
460
|
+
|
461
|
+
// Attach a handler to interrupt the form submission
|
462
|
+
Heartland.Events.addHandler(document.getElementById('payment_form'), 'submit', function (e) {
|
463
|
+
// Prevent the form from continuing to the `action` address
|
464
|
+
e.preventDefault();
|
465
|
+
// Tell the iframes to tokenize the data
|
466
|
+
hps.Messages.post(
|
467
|
+
{
|
468
|
+
accumulateData: true,
|
469
|
+
action: 'tokenize',
|
470
|
+
message: 'pkapi_cert_jKc1FtuyAydZhZfbB3'
|
471
|
+
},
|
472
|
+
'cardNumber'
|
473
|
+
);
|
474
|
+
});
|
475
|
+
}(document, Heartland));
|
476
|
+
</script>
|
477
|
+
</body>
|
478
|
+
</html>
|
@@ -0,0 +1,39 @@
|
|
1
|
+
<!--[if IE]><![endif]-->
|
2
|
+
<!--[if lt IE 7 ]> <html lang="en" class="ie6"> <![endif]-->
|
3
|
+
<!--[if IE 7 ]> <html lang="en" class="ie7"> <![endif]-->
|
4
|
+
<!--[if IE 8 ]> <html lang="en" class="ie8"> <![endif]-->
|
5
|
+
<!--[if IE 9 ]> <html lang="en" class="ie9"> <![endif]-->
|
6
|
+
<!--[if (gt IE 9)|!(IE)]><!-->
|
7
|
+
<html lang="en"><!--<![endif]-->
|
8
|
+
<head>
|
9
|
+
<meta charset="utf-8">
|
10
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
11
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
12
|
+
<meta name="description" content="SecureSubmit Ruby end-to-end payment example using tokenization.">
|
13
|
+
<meta name="author" content="Mark Hagan">
|
14
|
+
<title>Simple Payment Form Demo</title>
|
15
|
+
|
16
|
+
<link src="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.css">
|
17
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script>
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<div class="container">
|
21
|
+
<div class="row col-xs-12">
|
22
|
+
<h1>Ruby SecureSubmit Example</h1>
|
23
|
+
</div>
|
24
|
+
|
25
|
+
<h2>Results</h2>
|
26
|
+
|
27
|
+
<table>
|
28
|
+
<tr>
|
29
|
+
<td>Response Code</td>
|
30
|
+
<td><%= verification.response_code %>
|
31
|
+
</tr>
|
32
|
+
<tr>
|
33
|
+
<td>Multi-use Token</td>
|
34
|
+
<td><%= verification.token_data.token_value unless verification.token_data.nil? %>
|
35
|
+
</tr>
|
36
|
+
</table>
|
37
|
+
</div>
|
38
|
+
</body>
|
39
|
+
</html>
|
data/lib/hps.rb
CHANGED
@@ -29,6 +29,7 @@ require "hps/entities/hps_check"
|
|
29
29
|
require "hps/entities/hps_check_holder"
|
30
30
|
require "hps/entities/hps_check_response"
|
31
31
|
require "hps/entities/hps_check_response_details"
|
32
|
+
require "hps/entities/hps_manage_tokens"
|
32
33
|
|
33
34
|
# Infrastructure
|
34
35
|
require "hps/infrastructure/hps_sdk_codes"
|
@@ -435,6 +435,30 @@ module Hps
|
|
435
435
|
|
436
436
|
submit_void(xml.target!)
|
437
437
|
end
|
438
|
+
|
439
|
+
def update_token_expiration(token_value, exp_month, exp_year)
|
440
|
+
xml = Builder::XmlMarkup.new
|
441
|
+
xml.hps :Transaction do
|
442
|
+
xml.hps :ManageTokens do
|
443
|
+
xml.hps :TokenValue, token_value
|
444
|
+
xml.hps :TokenActions do
|
445
|
+
xml.hps :Set do
|
446
|
+
xml.hps :Attribute do
|
447
|
+
xml.hps :Name, "ExpMonth"
|
448
|
+
xml.hps :Value, format('%02d', exp_month)
|
449
|
+
end
|
450
|
+
xml.hps :Attribute do
|
451
|
+
xml.hps :Name, "ExpYear"
|
452
|
+
xml.hps :Value, exp_year
|
453
|
+
end
|
454
|
+
end
|
455
|
+
end
|
456
|
+
end
|
457
|
+
end
|
458
|
+
|
459
|
+
submit_manage_tokens(xml.target!)
|
460
|
+
end
|
461
|
+
|
438
462
|
private
|
439
463
|
|
440
464
|
def check_amount(amount)
|
@@ -671,6 +695,20 @@ module Hps
|
|
671
695
|
result
|
672
696
|
end
|
673
697
|
|
698
|
+
def submit_manage_tokens(transaction)
|
699
|
+
response = doTransaction(transaction)
|
700
|
+
header = response["Header"]
|
701
|
+
unless header["GatewayRspCode"].eql? "0"
|
702
|
+
raise @exception_mapper.map_gateway_exception(header["GatewayTxnId"], header["GatewayRspCode"], header["GatewayRspMsg"])
|
703
|
+
end
|
704
|
+
|
705
|
+
result = HpsManageTokens.new(hydrate_transaction_header(header))
|
706
|
+
result.transaction_id = header["GatewayTxnId"]
|
707
|
+
result.response_code = "00"
|
708
|
+
result.response_text = ""
|
709
|
+
result
|
710
|
+
end
|
711
|
+
|
674
712
|
def process_charge_gateway_response(response_code, response_text, transaction_id, amount, currency)
|
675
713
|
|
676
714
|
if !response_code.eql? "0"
|
data/lib/hps/version.rb
CHANGED
data/tests/general_tests.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
require File.join( File.dirname(__FILE__), "test_helper.rb" )
|
2
2
|
|
3
3
|
describe "General Tests" do
|
4
|
-
|
4
|
+
|
5
5
|
before(:each) do
|
6
6
|
Hps::TestHelper.configure_hps_module()
|
7
7
|
@service = Hps::HpsChargeService.new()
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
it "SecretAPIKey with spaces on Visa charge should return OK" do
|
11
11
|
Hps::TestHelper.configure_hps_module_secret_key_with_spaces
|
12
12
|
@service = Hps::HpsChargeService.new()
|
@@ -14,53 +14,128 @@ describe "General Tests" do
|
|
14
14
|
expect(result.response_code).to eql("00")
|
15
15
|
end
|
16
16
|
|
17
|
-
|
17
|
+
|
18
18
|
it "charge when amount is less than zero should throw invalid request exception" do
|
19
19
|
expect {
|
20
|
-
@service.charge(-5, "usd", Hps::TestData::valid_visa, Hps::TestData::valid_cardholder)
|
20
|
+
@service.charge(-5, "usd", Hps::TestData::valid_visa, Hps::TestData::valid_cardholder)
|
21
21
|
}.to raise_error(Hps::InvalidRequestException)
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
it "charge when currency is empty should throw invalid request exception" do
|
25
25
|
expect {
|
26
|
-
@service.charge(50, "", Hps::TestData::valid_visa, Hps::TestData::valid_cardholder)
|
26
|
+
@service.charge(50, "", Hps::TestData::valid_visa, Hps::TestData::valid_cardholder)
|
27
27
|
}.to raise_error(Hps::InvalidRequestException)
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
it "charge when currency is not usd should throw invalid request exception" do
|
31
31
|
expect {
|
32
|
-
@service.charge(50, "eur", Hps::TestData::valid_visa, Hps::TestData::valid_cardholder)
|
32
|
+
@service.charge(50, "eur", Hps::TestData::valid_visa, Hps::TestData::valid_cardholder)
|
33
33
|
}.to raise_error(Hps::InvalidRequestException)
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
it "charge when configuration is invalid should throw hps exception" do
|
37
37
|
expect {
|
38
38
|
@service = Hps::HpsChargeService.new :service_uri => nil
|
39
|
-
@service.charge(50, "usd", Hps::TestData::valid_visa, Hps::TestData::valid_cardholder)
|
39
|
+
@service.charge(50, "usd", Hps::TestData::valid_visa, Hps::TestData::valid_cardholder)
|
40
40
|
}.to raise_error(Hps::HpsException)
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
it "charge when license_id is invalid should throw authentication exception" do
|
44
44
|
expect {
|
45
45
|
@service = Hps::HpsChargeService.new :license_id => 11111
|
46
|
-
@service.charge(50, "usd", Hps::TestData::valid_visa, Hps::TestData::valid_cardholder)
|
46
|
+
@service.charge(50, "usd", Hps::TestData::valid_visa, Hps::TestData::valid_cardholder)
|
47
47
|
}.to raise_error(Hps::AuthenticationException)
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
it "charge when card number is invalid should throw hps exception" do
|
51
51
|
expect {
|
52
|
-
@service.charge(50, "usd", Hps::TestData::invalid_card, Hps::TestData::valid_cardholder)
|
52
|
+
@service.charge(50, "usd", Hps::TestData::invalid_card, Hps::TestData::valid_cardholder)
|
53
53
|
}.to raise_error(Hps::HpsException)
|
54
54
|
end
|
55
|
-
|
56
|
-
it "list when charge is in filter range should show in list" do
|
55
|
+
|
56
|
+
it "list when charge is in filter range should show in list" do
|
57
57
|
start_date = DateTime.now - 12.hours
|
58
|
-
charge = @service.charge(50, "usd", Hps::TestData::valid_visa, Hps::TestData::valid_cardholder)
|
58
|
+
charge = @service.charge(50, "usd", Hps::TestData::valid_visa, Hps::TestData::valid_cardholder)
|
59
59
|
end_date = DateTime.now
|
60
60
|
|
61
61
|
charges = @service.list(start_date, end_date)
|
62
|
-
expect(charges).to have_at_least(1).items
|
62
|
+
expect(charges).to have_at_least(1).items
|
63
63
|
expect(charges.any? { |c| c.transaction_id = charge.transaction_id }).to be_true
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
|
+
it "updates multi-use token" do
|
67
|
+
Hps::TestHelper.valid_multi_use_config
|
68
|
+
service = Hps::HpsChargeService.new()
|
69
|
+
verify = service.verify(Hps::TestData::valid_visa, Hps::TestData.valid_cardholder, true)
|
70
|
+
expect(verify).not_to be_nil
|
71
|
+
expect(verify.response_code).to eql("85")
|
72
|
+
expect(verify.token_data).not_to be_nil
|
73
|
+
expect(verify.token_data.token_value).not_to be_nil
|
74
|
+
expect(verify.token_data.token_value).not_to be_empty
|
75
|
+
|
76
|
+
month = Time.now.strftime('%m')
|
77
|
+
year = (Time.now + 2.years).strftime('%Y')
|
78
|
+
result = service.update_token_expiration(verify.token_data.token_value, month, year)
|
79
|
+
expect(result).not_to be_nil
|
80
|
+
expect(result.response_code).to eql("00")
|
81
|
+
end
|
82
|
+
|
83
|
+
it "fails to update multi-use token with bad year" do
|
84
|
+
Hps::TestHelper.valid_multi_use_config
|
85
|
+
service = Hps::HpsChargeService.new()
|
86
|
+
verify = service.verify(Hps::TestData::valid_visa, Hps::TestData.valid_cardholder, true)
|
87
|
+
expect(verify).not_to be_nil
|
88
|
+
expect(verify.response_code).to eql("85")
|
89
|
+
expect(verify.token_data).not_to be_nil
|
90
|
+
expect(verify.token_data.token_value).not_to be_nil
|
91
|
+
expect(verify.token_data.token_value).not_to be_empty
|
92
|
+
|
93
|
+
month = nil
|
94
|
+
year = 19
|
95
|
+
|
96
|
+
expect {
|
97
|
+
service.update_token_expiration(verify.token_data.token_value, month, year)
|
98
|
+
}.to raise_error(TypeError)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "fails to update multi-use token with nil date" do
|
102
|
+
Hps::TestHelper.valid_multi_use_config
|
103
|
+
service = Hps::HpsChargeService.new()
|
104
|
+
verify = service.verify(Hps::TestData::valid_visa, Hps::TestData.valid_cardholder, true)
|
105
|
+
expect(verify).not_to be_nil
|
106
|
+
expect(verify.response_code).to eql("85")
|
107
|
+
expect(verify.token_data).not_to be_nil
|
108
|
+
expect(verify.token_data.token_value).not_to be_nil
|
109
|
+
expect(verify.token_data.token_value).not_to be_empty
|
110
|
+
|
111
|
+
month = nil
|
112
|
+
year = nil
|
113
|
+
|
114
|
+
expect {
|
115
|
+
service.update_token_expiration(verify.token_data.token_value, month, year)
|
116
|
+
}.to raise_error(TypeError)
|
117
|
+
end
|
118
|
+
|
119
|
+
it "fails to update multi-use token with invalid token" do
|
120
|
+
Hps::TestHelper.valid_multi_use_config
|
121
|
+
service = Hps::HpsChargeService.new()
|
122
|
+
month = Time.now.strftime('%m')
|
123
|
+
year = (Time.now + 2.years).strftime('%Y')
|
124
|
+
|
125
|
+
expect {
|
126
|
+
service.update_token_expiration("abcdefg", month, year)
|
127
|
+
}.to raise_error(Hps::HpsException)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "fails to update multi-use token with nil token" do
|
131
|
+
Hps::TestHelper.valid_multi_use_config
|
132
|
+
service = Hps::HpsChargeService.new()
|
133
|
+
month = Time.now.strftime('%m')
|
134
|
+
year = (Time.now + 2.years).strftime('%Y')
|
135
|
+
|
136
|
+
expect {
|
137
|
+
service.update_token_expiration(nil, month, year)
|
138
|
+
}.to raise_error(Hps::HpsException)
|
139
|
+
end
|
140
|
+
|
66
141
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hps
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Heartland Payment Systems
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -118,6 +118,25 @@ files:
|
|
118
118
|
- PRIVACY.txt
|
119
119
|
- README.md
|
120
120
|
- Rakefile
|
121
|
+
- examples/sinatra-verify-only/Gemfile
|
122
|
+
- examples/sinatra-verify-only/app.rb
|
123
|
+
- examples/sinatra-verify-only/public/images/cvv.png
|
124
|
+
- examples/sinatra-verify-only/public/images/cvv1.png
|
125
|
+
- examples/sinatra-verify-only/public/images/cvv2.png
|
126
|
+
- examples/sinatra-verify-only/public/images/ss-cvv@2x.png
|
127
|
+
- examples/sinatra-verify-only/public/images/ss-inputcard-blank@2x.png
|
128
|
+
- examples/sinatra-verify-only/public/images/ss-saved-amex@2x.png
|
129
|
+
- examples/sinatra-verify-only/public/images/ss-saved-discover@2x.png
|
130
|
+
- examples/sinatra-verify-only/public/images/ss-saved-jcb@2x.png
|
131
|
+
- examples/sinatra-verify-only/public/images/ss-saved-mastercard.png
|
132
|
+
- examples/sinatra-verify-only/public/images/ss-saved-mastercard@2x.png
|
133
|
+
- examples/sinatra-verify-only/public/images/ss-saved-visa@2x.png
|
134
|
+
- examples/sinatra-verify-only/public/images/ss-savedcards-amex@2x.png
|
135
|
+
- examples/sinatra-verify-only/public/images/ss-shield-ie.png
|
136
|
+
- examples/sinatra-verify-only/public/images/ss-shield@1x.png
|
137
|
+
- examples/sinatra-verify-only/public/images/ss-shield@2x.png
|
138
|
+
- examples/sinatra-verify-only/views/index.erb
|
139
|
+
- examples/sinatra-verify-only/views/result.erb
|
121
140
|
- hps.gemspec
|
122
141
|
- lib/.DS_Store
|
123
142
|
- lib/hps.rb
|
@@ -136,6 +155,7 @@ files:
|
|
136
155
|
- lib/hps/entities/hps_credit_card.rb
|
137
156
|
- lib/hps/entities/hps_direct_market_data.rb
|
138
157
|
- lib/hps/entities/hps_encryption_data.rb
|
158
|
+
- lib/hps/entities/hps_manage_tokens.rb
|
139
159
|
- lib/hps/entities/hps_refund.rb
|
140
160
|
- lib/hps/entities/hps_report_transaction_details.rb
|
141
161
|
- lib/hps/entities/hps_report_transaction_summary.rb
|
@@ -203,7 +223,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
203
223
|
version: '0'
|
204
224
|
requirements: []
|
205
225
|
rubyforge_project:
|
206
|
-
rubygems_version: 2.6.
|
226
|
+
rubygems_version: 2.6.13
|
207
227
|
signing_key:
|
208
228
|
specification_version: 4
|
209
229
|
summary: Heartland Payment Systems - Portico Gateway SDK
|