hps 2.2.2 → 2.2.5

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.
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