Skip to content

Commit 94ec783

Browse files
authored
Merge pull request #7 from paynl/feature/uuid
Feature/UUID
2 parents fc5ff78 + 36c2958 commit 94ec783

File tree

7 files changed

+221
-3
lines changed

7 files changed

+221
-3
lines changed

src/datatypes/transaction-start.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ export class TransactionStartClass extends TransactionStart {
147147
return dateFormat(date, 'dd-mm-yyyy hh:MM:ss');
148148
}
149149
private calculateVatCode(priceIncl, vatAmount) {
150-
var vatCodes = { 0: 'N', 6: 'L', 21: 'H' };
150+
var vatCodes = { 0: 'N', 9: 'L', 21: 'H' };
151151
var priceExcl = priceIncl - vatAmount;
152152
if (!vatAmount || vatAmount == 0 || !priceIncl || priceIncl == 0) {
153153
return vatCodes[0];

src/dynamicuuid.ts

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
import {Observable} from 'rxjs/Observable';
2+
3+
const REFERENCE_TYPE_STRING = 1;
4+
const REFERENCE_TYPE_HEX = 0;
5+
const HASH_METHOD = 'sha256';
6+
7+
export class DynamicUUID {
8+
/**
9+
* Generate a UUID
10+
*
11+
* @param serviceId The PAY. service-id from one of your sales locations
12+
* @param secret Your custom secret
13+
* @param reference Your reference to the transaction
14+
* @param padChar The reference will be padded with this character, default pad '0'
15+
* @param referenceType Define if you are using a string (8 chars) of hex (16 chars)
16+
*/
17+
static encode(serviceId: string, secret: string, reference: string, padChar = '0', referenceType = REFERENCE_TYPE_STRING): Observable<string> {
18+
return Observable.create(observable => {
19+
if (referenceType == REFERENCE_TYPE_STRING) {
20+
if (!this.isValidReferenceString(reference)) {
21+
observable.error('Secret invalid: ' + secret);
22+
observable.complete();
23+
return;
24+
}
25+
reference = this.asciiToHex(reference);
26+
} else {
27+
if (!this.isValidHexString(reference)) {
28+
observable.error('Reference is not a valid hex: ' + reference);
29+
observable.complete();
30+
return;
31+
}
32+
}
33+
reference = reference.toLowerCase();
34+
35+
if (!this.isValidSecret(secret)) {
36+
observable.error('Secret invalid: ' + secret);
37+
observable.complete();
38+
return;
39+
}
40+
if (!this.isValidServiceId(serviceId)) {
41+
observable.error('serviceId invalid: ' + serviceId);
42+
observable.complete();
43+
return;
44+
}
45+
if (!this.isValidPadChar(padChar)) {
46+
observable.error('padChar invalid: ' + padChar);
47+
observable.complete();
48+
return;
49+
}
50+
51+
var uuid = serviceId.replace(/[^0-9]/g, '') + reference.padStart(16, padChar);
52+
var crypto = require('crypto');
53+
var hash = crypto.createHmac(HASH_METHOD, secret).update(uuid).digest('hex');
54+
55+
uuid = 'b' + hash.substring(0, 7) + uuid;
56+
57+
uuid =
58+
uuid.substring(0, 8) + '-' +
59+
uuid.substring(8, 12) + '-' +
60+
uuid.substring(12, 16) + '-' +
61+
uuid.substring(16, 20) + '-' +
62+
uuid.substring(20, 32);
63+
64+
observable.next(uuid);
65+
observable.complete();
66+
});
67+
}
68+
69+
/**
70+
* Decode a UUID
71+
*
72+
* @param uuid The UUID to decode
73+
* @param secret If supplied the uuid will be validated before decoding.
74+
* @param padChar The reference will be padded with this character, default '0'
75+
* @param referenceType
76+
*/
77+
static decode(uuid: string, secret = '', padChar = '0', referenceType = REFERENCE_TYPE_STRING): Observable<any> {
78+
79+
return Observable.create(observable => {
80+
81+
if (secret != '') {
82+
if (!this.isValidSecret(secret)) {
83+
observable.error('Secret is invalid: ' + secret);
84+
observable.complete();
85+
return
86+
}
87+
}
88+
89+
uuid = uuid.replace(/[^0-9a-z]/ig, '');
90+
uuid = uuid.substr(8, uuid.length);
91+
92+
var serviceid = 'SL-' + uuid.substring(0, 4) + '-' + uuid.substring(4, 8);
93+
var referenceCode = uuid.substring(8, uuid.length);
94+
95+
referenceCode = this.ltrim(referenceCode, padChar);
96+
97+
var referenc_hex = referenceCode;
98+
var reference_string = Buffer.from(referenceCode, "hex");
99+
100+
var obj = {
101+
'serviceId': serviceid,
102+
'reference': referenceType == REFERENCE_TYPE_HEX ? referenc_hex : reference_string
103+
};
104+
105+
observable.next(obj);
106+
observable.complete();
107+
});
108+
}
109+
110+
/**
111+
* Validate UUID
112+
*
113+
* @param uuid Your UUID code
114+
* @param secret Your secret
115+
*/
116+
static validate(uuid: string, secret = ''): Observable<string> {
117+
return Observable.create(observable => {
118+
119+
if (secret != '') {
120+
if (!this.isValidSecret(secret)) {
121+
observable.error('Secret is invalid: ' + secret);
122+
observable.complete();
123+
return
124+
}
125+
}
126+
127+
var uuidData = uuid.replace(/[^0-9a-z]/ig, '');
128+
uuidData = uuidData.substring(8, uuidData.length);
129+
130+
var crypto = require('crypto');
131+
var hash = crypto.createHmac(HASH_METHOD, secret).update(uuidData).digest('hex');
132+
133+
var checksum = 'b' + hash.substring(0, 7);
134+
135+
observable.next(checksum == uuid.substring(0, 8));
136+
observable.complete();
137+
});
138+
}
139+
140+
private static ltrim(str, charlist) {
141+
charlist = !charlist ? ' \\s\u00A0' : (charlist + '')
142+
.replace(/([[\]().?/*{}+$^:])/g, '$1')
143+
var re = new RegExp('^[' + charlist + ']+', 'g')
144+
return (str + '')
145+
.replace(re, '')
146+
}
147+
148+
private static asciiToHex(str) {
149+
var arr1 = [];
150+
for (var n = 0, l = str.length; n < l; n++) {
151+
var hex = Number(str.charCodeAt(n)).toString(16).toUpperCase();
152+
arr1.push(hex);
153+
}
154+
return arr1.join('');
155+
}
156+
157+
private static isValidReferenceString(reference) {
158+
return /^[0-9a-zA-Z]{0,8}$/i.test(reference)
159+
}
160+
161+
private static isValidHexString(hexString) {
162+
return /^[0-9a-f]{0,16}$/i.test(hexString)
163+
}
164+
165+
private static isValidSecret(secret) {
166+
return /^[0-9a-f]{40}$/i.test(secret);
167+
}
168+
169+
private static isValidServiceId(serviceId) {
170+
return /^SL-[0-9]{4}-[0-9]{4}$/.test(serviceId);
171+
}
172+
173+
private static isValidPadChar(padChar) {
174+
return /^[a-z0-9]{1}$/i.test(padChar);
175+
}
176+
177+
}

src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ export { Config } from './config';
33
export { Transaction } from './transaction';
44
export { Paymentmethods } from './paymentmethods';
55
export { Instore } from './instore';
6-
export { GiftCard } from './giftcard'
6+
export { GiftCard } from './giftcard'
7+
export { DynamicUUID } from './dynamicuuid'

src/result/transaction.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ export class TransactionResult {
4040
isBeingVerified(){
4141
return this.paymentDetails.stateName == 'VERIFY';
4242
}
43-
43+
isAuthorized(){
44+
return this.paymentDetails.state == 95;
45+
}
4446
approve():Observable<boolean> {
4547
return Transaction.approve(this.transactionId);
4648
}

src/samples/dynamicUUID/decode.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import * as Paynl from '../../index'
2+
3+
Paynl.DynamicUUID.decode('#your UUID#')
4+
.subscribe(
5+
function (result) {
6+
console.log('Decoded serviceId: ' + result.serviceId);
7+
console.log('Decoded reference: ' + result.reference);
8+
},
9+
function (error) {
10+
console.log('Decode failed: ' + error);
11+
}
12+
);

src/samples/dynamicUUID/encode.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import * as Paynl from '../../index'
2+
3+
var secret = 'abcdef1234567890abcdef1234567890abcdef12';
4+
var slcode = 'SL-5261-6001';
5+
var reference = 'INV001';
6+
7+
Paynl.DynamicUUID.encode(slcode, secret, reference)
8+
.subscribe(
9+
function (result) {
10+
console.log('UUID: ' + result);
11+
},
12+
function (error) {
13+
console.log('Encoding failed: ' + error);
14+
}
15+
);
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import * as Paynl from '../../index'
2+
3+
Paynl.DynamicUUID.validate('#your UUID#', '#your secret#')
4+
.subscribe(
5+
function (result) {
6+
console.log('Validation result: ' + result);
7+
},
8+
function (error) {
9+
console.log('Validation failed: ' + error);
10+
}
11+
);

0 commit comments

Comments
 (0)