hps 2.2.2 → 2.2.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (26) hide show
  1. checksums.yaml +4 -4
  2. data/examples/sinatra-verify-only/Gemfile +4 -0
  3. data/examples/sinatra-verify-only/app.rb +32 -0
  4. data/examples/sinatra-verify-only/public/images/cvv.png +0 -0
  5. data/examples/sinatra-verify-only/public/images/cvv1.png +0 -0
  6. data/examples/sinatra-verify-only/public/images/cvv2.png +0 -0
  7. data/examples/sinatra-verify-only/public/images/ss-cvv@2x.png +0 -0
  8. data/examples/sinatra-verify-only/public/images/ss-inputcard-blank@2x.png +0 -0
  9. data/examples/sinatra-verify-only/public/images/ss-saved-amex@2x.png +0 -0
  10. data/examples/sinatra-verify-only/public/images/ss-saved-discover@2x.png +0 -0
  11. data/examples/sinatra-verify-only/public/images/ss-saved-jcb@2x.png +0 -0
  12. data/examples/sinatra-verify-only/public/images/ss-saved-mastercard.png +0 -0
  13. data/examples/sinatra-verify-only/public/images/ss-saved-mastercard@2x.png +0 -0
  14. data/examples/sinatra-verify-only/public/images/ss-saved-visa@2x.png +0 -0
  15. data/examples/sinatra-verify-only/public/images/ss-savedcards-amex@2x.png +0 -0
  16. data/examples/sinatra-verify-only/public/images/ss-shield-ie.png +0 -0
  17. data/examples/sinatra-verify-only/public/images/ss-shield@1x.png +0 -0
  18. data/examples/sinatra-verify-only/public/images/ss-shield@2x.png +0 -0
  19. data/examples/sinatra-verify-only/views/index.erb +478 -0
  20. data/examples/sinatra-verify-only/views/result.erb +39 -0
  21. data/lib/hps.rb +1 -0
  22. data/lib/hps/entities/hps_manage_tokens.rb +9 -0
  23. data/lib/hps/services/hps_charge_service.rb +38 -0
  24. data/lib/hps/version.rb +1 -1
  25. data/tests/general_tests.rb +94 -19
  26. metadata +23 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5a0dfdbe99a74b2d018080484c953a1fca62fdb0
4
- data.tar.gz: ce9a6bfc80ffc2e105540ea4a73f9ea1fedf4a51
3
+ metadata.gz: 76db4e4f82ebe0a3399a498fc68055353cf82a7f
4
+ data.tar.gz: e61ba75e59c12b39e293faf121c4852895f38895
5
5
  SHA512:
6
- metadata.gz: ecb4fa1dafcf31ffe95a0d83faefd7b85d4e7a16768cd833615b481e86f29902c3cf45b8290c4ccfc8aea49f405fff3e1cb28ce1157bc9bb8facf0cbaeb734f2
7
- data.tar.gz: cbe344a3167ef15fd5a2a64add266bc92646a61465c19fb8b2135af657ad24c02c6895efa4c8294ec55b2b763bff460b23b6a6facf9ffbb66fcde2a16753fe4b
6
+ metadata.gz: 59b397a58ee800edac5b043b0f6208120e45a4f539674b816a21b5b46cc8bbfd495ee86e146b32e502b09dae6c27ca3affd4a50c022901cf86a2b07997a100b7
7
+ data.tar.gz: 789fdfd04c540a00cb620749419c2632527f25b4f8d89216ebee189209c4daf2a90269370da5efa9d9b40d9094b74d8bba69a57ecf725fe8b0a8ceff6267f23f
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'sinatra'
4
+ gem 'hps'
@@ -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
@@ -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"
@@ -0,0 +1,9 @@
1
+ module Hps
2
+ class HpsManageTokens < HpsTransaction
3
+
4
+ def initialize(header)
5
+ super(header)
6
+ end
7
+
8
+ end
9
+ end
@@ -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"
@@ -1,3 +1,3 @@
1
1
  module Hps
2
- VERSION = "2.2.2"
2
+ VERSION = "2.2.5"
3
3
  end
@@ -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.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-08-10 00:00:00.000000000 Z
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.11
226
+ rubygems_version: 2.6.13
207
227
  signing_key:
208
228
  specification_version: 4
209
229
  summary: Heartland Payment Systems - Portico Gateway SDK