simplepay-js-sdk 0.7.0 → 0.8.1
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.
- package/README-ENG.md +203 -0
- package/README.md +84 -60
- package/dist/index.d.ts +10 -0
- package/dist/index.js +74 -60
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +2 -2
- package/src/oneTime.ts +3 -3
- package/src/recurring.ts +23 -6
- package/src/types.ts +15 -0
- package/src/utils.ts +14 -7
package/README-ENG.md
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# SimplePay JS SDK
|
|
2
|
+
|
|
3
|
+
[Magyar README](README.md)
|
|
4
|
+
|
|
5
|
+
A lightweight utility for integrating Hungary's SimplePay payments in Node.js applications.
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
Please read the [SimplePay documentation](https://simplepay.hu/fejlesztoknek) for more information.
|
|
10
|
+
|
|
11
|
+
> 🫵 If this package is useful to you, please star it on GitHub.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# npm
|
|
17
|
+
npm install simplepay-js-sdk
|
|
18
|
+
|
|
19
|
+
# yarn
|
|
20
|
+
yarn add simplepay-js-sdk
|
|
21
|
+
|
|
22
|
+
# pnpm
|
|
23
|
+
pnpm add simplepay-js-sdk
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Configuration
|
|
27
|
+
|
|
28
|
+
Set the following environment variables in your `.env` file:
|
|
29
|
+
|
|
30
|
+
- `SIMPLEPAY_LOGGER` If it set to `true`, it will log varibles - useful only for debugging.
|
|
31
|
+
- `SIMPLEPAY_MERCHANT_KEY_HUF` Your Simplepay secret merchant key. Set `SIMPLEPAY_MERCHANT_KEY_EUR` and `SIMPLEPAY_MERCHANT_KEY_USD` for accepting EUR and USD payments.
|
|
32
|
+
- `SIMPLEPAY_MERCHANT_ID_HUF` Your Simplepay merchant id. Set `SIMPLEPAY_MERCHANT_ID_EUR` and `SIMPLEPAY_MERCHANT_ID_USD` for accepting EUR and USD payments.
|
|
33
|
+
- `SIMPLEPAY_PRODUCTION` If it set to `true`, it will use production environment, otherwise it will use sandbox environment.
|
|
34
|
+
- `SIMPLEPAY_REDIRECT_URL` The URL of your site, where the customer will be redirected after the payment.
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
You should create 3 endpoints, to start the payment, get the payment response and handle the IPN.
|
|
39
|
+
|
|
40
|
+
### One Time Payment
|
|
41
|
+
|
|
42
|
+
#### Start Payment Endpoint
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { startPayment } from 'simplepay-js-sdk'
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
const response = await startPayment({
|
|
49
|
+
orderRef: 'order-12',
|
|
50
|
+
total: 1212,
|
|
51
|
+
currency: 'HUF', // optional, HUF | EUR | USD, defaults to HUF
|
|
52
|
+
customerEmail: 'rrd@webmania.cc',
|
|
53
|
+
language: 'HU', // optional, AR | BG | CS | DE | EN | ES | FR | IT | HR | HU | PL | RO | RU | SK | TR | ZH, defaults to HU
|
|
54
|
+
method: 'CARD', // optional, CARD | WIRE, defaults to CARD
|
|
55
|
+
invoice: {
|
|
56
|
+
name: 'Radharadhya Dasa',
|
|
57
|
+
country: 'HU',
|
|
58
|
+
state: 'Budapest',
|
|
59
|
+
city: 'Budapest',
|
|
60
|
+
zip: '1234',
|
|
61
|
+
address: 'Sehol u. 0',
|
|
62
|
+
},
|
|
63
|
+
})
|
|
64
|
+
return response
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error('Payment initiation failed:', error)
|
|
67
|
+
return error
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`response.paymentUrl` will contain the Simplepay payment URL, which you can redirect the customer to.
|
|
72
|
+
|
|
73
|
+
#### Get Payment Response Endpoint
|
|
74
|
+
|
|
75
|
+
When the customer returns from the Simplepay payment page, you need to get the payment response at your `SIMPLEPAY_REDIRECT_URL`. The url will contain 2 parameters: `r` and `s`.
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
import { getPaymentResponse } from 'simplepay-js-sdk'
|
|
79
|
+
|
|
80
|
+
// get "r" and "s" from the url the way you do it on your app and framework
|
|
81
|
+
|
|
82
|
+
const response = getPaymentResponse(r, s)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`response` will have the following properties:
|
|
86
|
+
|
|
87
|
+
- `responseCode`: `0` on success, or an error code
|
|
88
|
+
- `transactionId`: the transaction id
|
|
89
|
+
- `event`: the event type: `success` | `fail` | `timeout` | `cancel`
|
|
90
|
+
- `merchantId`: the merchant id
|
|
91
|
+
- `orderRef`: the order id
|
|
92
|
+
|
|
93
|
+
#### IPN Endpoint
|
|
94
|
+
|
|
95
|
+
Simplepay will send a `POST` request to the IPN url and you should send a response back.
|
|
96
|
+
At this endpoint you should
|
|
97
|
+
|
|
98
|
+
- check if the signature is valid - use `checkSignature(ipnBody, signatureHeader, SIMPLEPAY_MERCHANT_KEY_HUF)`
|
|
99
|
+
- add a `receiveDate` property to the received JSON
|
|
100
|
+
- calculate the new signature - use `generateSignature(responseText, SIMPLEPAY_MERCHANT_KEY_HUF)`
|
|
101
|
+
- send the `response` with the new `signature`
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
### Recurring Payment
|
|
105
|
+
|
|
106
|
+
#### Start Recurring Payment Endpoint
|
|
107
|
+
|
|
108
|
+
Here you have to use the `startRecurringPayment()` function what works the same way as the `startPayment()` function. The only difference is that you have to pass 2 additional properties: `customer` and `recurring`.
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
try {
|
|
112
|
+
const response = await startRecurringPayment({
|
|
113
|
+
// ... other preoperties
|
|
114
|
+
customer: 'Radharadhya Dasa',
|
|
115
|
+
recurring: {
|
|
116
|
+
times: 3, // how many times the payment will be made, number of tokens
|
|
117
|
+
until: '2025-12-31T18:00:00+02:00', // the end date of the recurring payment - use the toISO8601DateString() helper function
|
|
118
|
+
maxAmount: 100000 // the maximum amount of the recurring payment
|
|
119
|
+
}
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
The response will have an additional `tokens` property, what will contain the tokens of the registered cards.
|
|
125
|
+
You are responsible to save the tokens to your database, so you can use them later to make a payment.
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
#### Get Recurring Payment Response Endpoint
|
|
129
|
+
|
|
130
|
+
Use the same enpoint as the one time payment.
|
|
131
|
+
|
|
132
|
+
#### IPN Endpoint on card registration
|
|
133
|
+
|
|
134
|
+
It works the same as the `IPN` endpoint of the one time payment.
|
|
135
|
+
The response will have the same properties, and 2 additional properties:
|
|
136
|
+
|
|
137
|
+
- `cardMask`: xxxx-xxxx-xxxx-1234 - the masked card number what is registered
|
|
138
|
+
- `expiry`: 2025-01-31T00:00:00+02:00 - the expiry date of the registered card
|
|
139
|
+
|
|
140
|
+
#### Token Payment Endpoint
|
|
141
|
+
|
|
142
|
+
After a card is registered you can use the tokens to make a payment without any user intercation for example by a daily `cron`
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import { startTokenPayment } from 'simplepay-js-sdk'
|
|
146
|
+
|
|
147
|
+
// TODO: get payment data from your database, where you saved the tokens
|
|
148
|
+
|
|
149
|
+
const payment = {
|
|
150
|
+
token: '1234567890123456',
|
|
151
|
+
total: 1212,
|
|
152
|
+
currency: 'HUF' as Currency,
|
|
153
|
+
customer: 'Radharadhya Dasa',
|
|
154
|
+
customerEmail: 'rrd@webmania.cc',
|
|
155
|
+
invoice: {
|
|
156
|
+
name: 'Radharadhya Dasa',
|
|
157
|
+
country: 'HU',
|
|
158
|
+
state: 'Budapest',
|
|
159
|
+
city: 'Budapest',
|
|
160
|
+
zip: '1234',
|
|
161
|
+
address: 'Sehol u. 0',
|
|
162
|
+
},
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
try {
|
|
166
|
+
const response = await startTokenPayment({
|
|
167
|
+
orderRef: Date.now().toString(),
|
|
168
|
+
language: 'HU',
|
|
169
|
+
method: 'CARD', // must be CARD
|
|
170
|
+
...payment,
|
|
171
|
+
})
|
|
172
|
+
return response
|
|
173
|
+
} catch (error) {
|
|
174
|
+
console.error('Token payment initiation failed:', error)
|
|
175
|
+
return error
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
#### Card Cancelation
|
|
180
|
+
|
|
181
|
+
Paying customers should be able to delete their registered card on the website.
|
|
182
|
+
To do this, use the `cancelCard` function. Use SimplePay transaction id of the card registration transaction as `cardId`.
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
import { cancelCard } from 'simplepay-js-sdk'
|
|
186
|
+
|
|
187
|
+
try {
|
|
188
|
+
const response = await cancelCard(cardId)
|
|
189
|
+
|
|
190
|
+
if (response.status == 'DISABLED') {
|
|
191
|
+
// The card has been successfully deleted
|
|
192
|
+
// TODO: delete the unused tokens and the card from the database
|
|
193
|
+
}
|
|
194
|
+
return response
|
|
195
|
+
} catch (error) {
|
|
196
|
+
console.error('Card deletion failed:', error)
|
|
197
|
+
return error
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## License
|
|
202
|
+
|
|
203
|
+
MIT
|
package/README.md
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
# SimplePay JS SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[English README](README-ENG.md)
|
|
4
|
+
|
|
5
|
+
Egy pehelysúlyú segédprogram a magyarországi SimplePay fizetések integrálásához Node.js alkalmazásokban.
|
|
4
6
|
|
|
5
7
|

|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
További információkért kérlek, olvasd el a [SimplePay dokumentációt](https://simplepay.hu/fejlesztoknek).
|
|
10
|
+
|
|
11
|
+
> 🫵 Ha a csomag hasznos a számodra, akkor ne feletjs el rányomni a star-ra GitHub-on.
|
|
8
12
|
|
|
9
|
-
##
|
|
13
|
+
## Telepítés
|
|
10
14
|
|
|
11
15
|
```bash
|
|
12
16
|
# npm
|
|
@@ -19,23 +23,23 @@ yarn add simplepay-js-sdk
|
|
|
19
23
|
pnpm add simplepay-js-sdk
|
|
20
24
|
```
|
|
21
25
|
|
|
22
|
-
##
|
|
26
|
+
## Konfiguráció
|
|
23
27
|
|
|
24
|
-
|
|
28
|
+
Állítsd be a következő környezeti változókat a `.env` fájlban:
|
|
25
29
|
|
|
26
|
-
- `SIMPLEPAY_LOGGER`
|
|
27
|
-
- `SIMPLEPAY_MERCHANT_KEY_HUF`
|
|
28
|
-
- `SIMPLEPAY_MERCHANT_ID_HUF`
|
|
29
|
-
- `SIMPLEPAY_PRODUCTION`
|
|
30
|
-
- `SIMPLEPAY_REDIRECT_URL`
|
|
30
|
+
- `SIMPLEPAY_LOGGER` Ha `true`-ra van állítva, naplózza a változókat - csak hibakereséshez hasznos.
|
|
31
|
+
- `SIMPLEPAY_MERCHANT_KEY_HUF` A te SimplePay titkos kereskedői kulcsod. Állítsd be a `SIMPLEPAY_MERCHANT_KEY_EUR` és `SIMPLEPAY_MERCHANT_KEY_USD` értékeket EUR és USD fizetések elfogadásához.
|
|
32
|
+
- `SIMPLEPAY_MERCHANT_ID_HUF` A te SimplePay kereskedői azonosítód. Állítsd be a `SIMPLEPAY_MERCHANT_ID_EUR` és `SIMPLEPAY_MERCHANT_ID_USD` értékeket EUR és USD fizetések elfogadásához.
|
|
33
|
+
- `SIMPLEPAY_PRODUCTION` Ha `true`-ra van állítva, éles környezetet használ, egyébként teszt környezetet.
|
|
34
|
+
- `SIMPLEPAY_REDIRECT_URL` A te weboldalad URL-je, ahova a vásárló átirányításra kerül a fizetés után.
|
|
31
35
|
|
|
32
|
-
##
|
|
36
|
+
## Használat
|
|
33
37
|
|
|
34
|
-
|
|
38
|
+
Három végpontot kell létrehoznia: egyet a fizetés indításához, egyet a fizetési válasz fogadásához és egyet az IPN kezeléséhez.
|
|
35
39
|
|
|
36
|
-
###
|
|
40
|
+
### Egyszeri fizetés
|
|
37
41
|
|
|
38
|
-
####
|
|
42
|
+
#### Fizetés indítása végpont
|
|
39
43
|
|
|
40
44
|
```typescript
|
|
41
45
|
import { startPayment } from 'simplepay-js-sdk'
|
|
@@ -44,10 +48,10 @@ try {
|
|
|
44
48
|
const response = await startPayment({
|
|
45
49
|
orderRef: 'order-12',
|
|
46
50
|
total: 1212,
|
|
47
|
-
currency: 'HUF', //
|
|
51
|
+
currency: 'HUF', // opcionális, HUF | EUR | USD, alapértelmezett: HUF
|
|
48
52
|
customerEmail: 'rrd@webmania.cc',
|
|
49
|
-
language: 'HU', //
|
|
50
|
-
method: 'CARD', //
|
|
53
|
+
language: 'HU', // opcionális, AR | BG | CS | DE | EN | ES | FR | IT | HR | HU | PL | RO | RU | SK | TR | ZH, alapértelmezett: HU
|
|
54
|
+
method: 'CARD', // opcionális, CARD | WIRE, alapértelmezett: CARD
|
|
51
55
|
invoice: {
|
|
52
56
|
name: 'Radharadhya Dasa',
|
|
53
57
|
country: 'HU',
|
|
@@ -59,88 +63,86 @@ try {
|
|
|
59
63
|
})
|
|
60
64
|
return response
|
|
61
65
|
} catch (error) {
|
|
62
|
-
console.error('
|
|
66
|
+
console.error('Fizetés indítása sikertelen:', error)
|
|
63
67
|
return error
|
|
64
68
|
}
|
|
65
69
|
```
|
|
66
70
|
|
|
67
|
-
`response.paymentUrl`
|
|
71
|
+
A `response.paymentUrl` tartalmazza a SimplePay fizetési URL-t, ahova a vásárlót átirányíthatja.
|
|
68
72
|
|
|
69
|
-
####
|
|
73
|
+
#### Fizetési válasz fogadása végpont
|
|
70
74
|
|
|
71
|
-
|
|
75
|
+
Amikor a vásárló visszatér a SimplePay fizetési oldalról, a fizetési választ a `SIMPLEPAY_REDIRECT_URL` címen kell fogadni. Az URL két paramétert tartalmaz: `r` és `s`.
|
|
72
76
|
|
|
73
77
|
```typescript
|
|
74
78
|
import { getPaymentResponse } from 'simplepay-js-sdk'
|
|
75
79
|
|
|
76
|
-
//
|
|
80
|
+
// az "r" és "s" paraméterek kinyerése az URL-ből az alkalmazásod és keretrendszerének megfelelően
|
|
77
81
|
|
|
78
82
|
const response = getPaymentResponse(r, s)
|
|
79
83
|
```
|
|
80
84
|
|
|
81
|
-
`response`
|
|
85
|
+
A `response` a következő tulajdonságokkal rendelkezik:
|
|
82
86
|
|
|
83
|
-
- `responseCode`: `0`
|
|
84
|
-
- `transactionId`:
|
|
85
|
-
- `event`:
|
|
86
|
-
- `merchantId`:
|
|
87
|
-
- `orderRef`:
|
|
87
|
+
- `responseCode`: `0` siker esetén, vagy hibakód
|
|
88
|
+
- `transactionId`: a tranzakció azonosítója
|
|
89
|
+
- `event`: az esemény típusa: `success` | `fail` | `timeout` | `cancel`
|
|
90
|
+
- `merchantId`: a kereskedő azonosítója
|
|
91
|
+
- `orderRef`: a rendelés azonosítója
|
|
88
92
|
|
|
89
|
-
#### IPN
|
|
93
|
+
#### IPN végpont
|
|
90
94
|
|
|
91
|
-
|
|
92
|
-
|
|
95
|
+
A SimplePay `POST` kérést küld az IPN URL-re, és válaszolnunk kell rá.
|
|
96
|
+
Ennél a végpontnál a következőket kell tenned:
|
|
93
97
|
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
-
|
|
97
|
-
-
|
|
98
|
+
- ellenőrizd az aláírás érvényességét - használd a `checkSignature(ipnBody, signatureHeader, SIMPLEPAY_MERCHANT_KEY_HUF)` függvényt
|
|
99
|
+
- adj hozzá egy `receiveDate` tulajdonságot a kapott JSON-hoz
|
|
100
|
+
- számítsa ki az új aláírást - használd a `generateSignature(responseText, SIMPLEPAY_MERCHANT_KEY_HUF)` függvényt
|
|
101
|
+
- küldd el a `response`-t az új `signature`-rel
|
|
98
102
|
|
|
103
|
+
### Ismétlődő fizetés
|
|
99
104
|
|
|
100
|
-
|
|
105
|
+
#### Ismétlődő fizetés indítása végpont
|
|
101
106
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
Here you have to use the `startRecurringPayment()` function what works the same way as the `startPayment()` function. The only difference is that you have to pass 2 additional properties: `customer` and `recurring`.
|
|
107
|
+
Itt a `startRecurringPayment()` függvényt kell használnod, ami ugyanúgy működik, mint a `startPayment()`. Az egyetlen különbség, hogy két további tulajdonságot kell megadni: `customer` és `recurring`.
|
|
105
108
|
|
|
106
109
|
```typescript
|
|
107
110
|
try {
|
|
108
111
|
const response = await startRecurringPayment({
|
|
109
|
-
// ...
|
|
112
|
+
// ... egyéb tulajdonságok
|
|
110
113
|
customer: 'Radharadhya Dasa',
|
|
111
114
|
recurring: {
|
|
112
|
-
times: 3, //
|
|
113
|
-
until: '2025-12-31T18:00:00+02:00', //
|
|
114
|
-
maxAmount: 100000 //
|
|
115
|
+
times: 3, // hányszor történik meg a fizetés, tokenek száma
|
|
116
|
+
until: '2025-12-31T18:00:00+02:00', // az ismétlődő fizetés végdátuma - használd a toISO8601DateString() segédfüggvényt
|
|
117
|
+
maxAmount: 100000 // az ismétlődő fizetés maximális összege
|
|
115
118
|
}
|
|
116
119
|
})
|
|
117
120
|
}
|
|
118
121
|
```
|
|
119
122
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
+
A válasz egy további `tokens` tulajdonsággal rendelkezik, ami tartalmazza a regisztrált kártyák tokenjeit.
|
|
124
|
+
A te dolgod a tokenek mentése az adatbázisba, hogy később használhasd őket fizetéshez.
|
|
123
125
|
|
|
124
|
-
####
|
|
126
|
+
#### Ismétlődő fizetési válasz fogadása végpont
|
|
125
127
|
|
|
126
|
-
|
|
128
|
+
Használd ugyanazt a végpontot, mint az egyszeri fizetésnél.
|
|
127
129
|
|
|
128
|
-
#### IPN
|
|
130
|
+
#### IPN végpont kártyaregisztrációnál
|
|
129
131
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
+
Ugyanúgy működik, mint az egyszeri fizetés `IPN` végpontja.
|
|
133
|
+
A válasz ugyanazokkal a tulajdonságokkal rendelkezik, és 2 további tulajdonsággal:
|
|
132
134
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
+
- `cardMask`: xxxx-xxxx-xxxx-1234 - a regisztrált kártya maszkolt száma
|
|
136
|
+
- `expiry`: 2025-01-31T00:00:00+02:00 - a regisztrált kártya lejárati dátuma
|
|
135
137
|
|
|
136
|
-
|
|
138
|
+
#### Tokenes fizetés
|
|
137
139
|
|
|
138
|
-
|
|
140
|
+
Miután egy kártya regisztrálva van, használhatod a tokeneket fizetéshez felhasználói interakció nélkül, például napi `cron` feladattal
|
|
139
141
|
|
|
140
142
|
```typescript
|
|
141
143
|
import { startTokenPayment } from 'simplepay-js-sdk'
|
|
142
144
|
|
|
143
|
-
// TODO:
|
|
145
|
+
// TODO: fizetési adatok lekérése az adatbázisból, ahol a tokeneket tárolod
|
|
144
146
|
|
|
145
147
|
const payment = {
|
|
146
148
|
token: '1234567890123456',
|
|
@@ -162,16 +164,38 @@ try {
|
|
|
162
164
|
const response = await startTokenPayment({
|
|
163
165
|
orderRef: Date.now().toString(),
|
|
164
166
|
language: 'HU',
|
|
165
|
-
method: 'CARD', //
|
|
167
|
+
method: 'CARD', // kötelezően CARD
|
|
166
168
|
...payment,
|
|
167
169
|
})
|
|
168
170
|
return response
|
|
169
171
|
} catch (error) {
|
|
170
|
-
console.error('Token
|
|
172
|
+
console.error('Token fizetés indítása sikertelen:', error)
|
|
173
|
+
return error
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
#### Kártya törlése
|
|
178
|
+
|
|
179
|
+
A fizető ügyfelek számára lehetővé kell tenni, hogy a honlapodon belépve törölni tudja a regisztrált kártyáját.
|
|
180
|
+
Ehhez használd a `cancelCard` függvényt. `cardId`-ként a kártya regisztrációs tranzakció SimplePay azonosítóját kell megadnod.
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
import { cancelCard } from 'simplepay-js-sdk'
|
|
184
|
+
|
|
185
|
+
try {
|
|
186
|
+
const response = await cancelCard(cardId)
|
|
187
|
+
|
|
188
|
+
if (response.status == 'DISABLED') {
|
|
189
|
+
// A kártya sikeresen törölve
|
|
190
|
+
// TODO: a fel nem használt tokenek és a kártya törlése az adatbázisból
|
|
191
|
+
}
|
|
192
|
+
return response
|
|
193
|
+
} catch (error) {
|
|
194
|
+
console.error('Kártya törlése sikertelen:', error)
|
|
171
195
|
return error
|
|
172
196
|
}
|
|
173
197
|
```
|
|
174
198
|
|
|
175
|
-
##
|
|
199
|
+
## Licenc
|
|
176
200
|
|
|
177
|
-
MIT
|
|
201
|
+
MIT
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
export declare const cardCancel: (cardId: string) => Promise<SimplePayCardCancelResponse>;
|
|
2
|
+
|
|
1
3
|
export declare const checkSignature: (responseText: string, signature: string, merchantKey: string) => boolean;
|
|
2
4
|
|
|
3
5
|
declare const CURRENCIES: readonly ["HUF", "EUR", "USD"];
|
|
@@ -46,6 +48,14 @@ declare interface RecurringPaymentData extends PaymentData {
|
|
|
46
48
|
recurring: Recurring;
|
|
47
49
|
}
|
|
48
50
|
|
|
51
|
+
declare interface SimplePayCardCancelResponse {
|
|
52
|
+
salt: string;
|
|
53
|
+
merchant: string;
|
|
54
|
+
cardId: string;
|
|
55
|
+
status: 'DISABLED';
|
|
56
|
+
expiry: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
49
59
|
declare type SimplePayEvents = 'SUCCESS' | 'FAIL' | 'TIMEOUT' | 'CANCEL';
|
|
50
60
|
|
|
51
61
|
declare interface SimplePayRecurringResponse extends SimplePayResponse {
|
package/dist/index.js
CHANGED
|
@@ -1,31 +1,32 @@
|
|
|
1
1
|
import S from "crypto";
|
|
2
|
-
const
|
|
2
|
+
const g = ["HUF", "EUR", "USD"], i = (...e) => {
|
|
3
3
|
process.env.SIMPLEPAY_LOGGER === "true" && console.log("👉 ", ...e);
|
|
4
|
-
},
|
|
5
|
-
if (!
|
|
4
|
+
}, E = (e) => {
|
|
5
|
+
if (!g.includes(e))
|
|
6
6
|
throw new Error(`Unsupported currency: ${e}`);
|
|
7
|
-
const
|
|
7
|
+
const n = "https://secure.simplepay.hu/payment/v2", r = "https://sandbox.simplepay.hu/payment/v2", t = "SimplePayV2.1_Rrd_0.8.0", s = process.env[`SIMPLEPAY_MERCHANT_KEY_${e}`], c = process.env[`SIMPLEPAY_MERCHANT_ID_${e}`], o = process.env.SIMPLEPAY_PRODUCTION === "true" ? n : r, u = o + "/start", R = o + "/dorecurring", a = o + "/cancelcard";
|
|
8
8
|
return {
|
|
9
9
|
MERCHANT_KEY: s,
|
|
10
10
|
MERCHANT_ID: c,
|
|
11
|
-
|
|
12
|
-
API_URL_RECURRING:
|
|
13
|
-
|
|
11
|
+
API_URL_PAYMENT: u,
|
|
12
|
+
API_URL_RECURRING: R,
|
|
13
|
+
API_URL_CARD_CANCEL: a,
|
|
14
|
+
SDK_VERSION: t
|
|
14
15
|
};
|
|
15
|
-
},
|
|
16
|
-
const
|
|
17
|
-
return
|
|
18
|
-
},
|
|
19
|
-
var
|
|
20
|
-
const
|
|
16
|
+
}, d = (e) => JSON.stringify(e).replace(/\//g, "\\/"), l = (e, n) => {
|
|
17
|
+
const r = S.createHmac("sha384", n.trim());
|
|
18
|
+
return r.update(e, "utf8"), r.digest("base64");
|
|
19
|
+
}, _ = (e, n, r) => n === l(e, r), m = (e) => e.toISOString().replace(/\.\d{3}Z$/, "+00:00"), A = (e) => {
|
|
20
|
+
var r, t;
|
|
21
|
+
const n = (t = (r = Object.entries(process.env).find(
|
|
21
22
|
([s, c]) => s.startsWith("SIMPLEPAY_MERCHANT_ID_") && c === e
|
|
22
|
-
)) == null ? void 0 :
|
|
23
|
-
if (!
|
|
23
|
+
)) == null ? void 0 : r[0]) == null ? void 0 : t.replace("SIMPLEPAY_MERCHANT_ID_", "");
|
|
24
|
+
if (!n)
|
|
24
25
|
throw new Error(`Merchant id not found in the environment: ${e}`);
|
|
25
|
-
return
|
|
26
|
-
}, I = async (e,
|
|
27
|
-
const s =
|
|
28
|
-
i({ function: `SimplePay/makeRequest/${
|
|
26
|
+
return n;
|
|
27
|
+
}, I = async (e, n, r) => P(e, n, r, "oneTime"), f = async (e, n, r) => P(e, n, r, "recurring"), p = async (e, n, r) => P(e, n, r, "token"), h = async (e, n, r) => P(e, n, r, "cardCancel"), P = async (e, n, r, t) => {
|
|
28
|
+
const s = d(n), c = l(s, r);
|
|
29
|
+
i({ function: `SimplePay/makeRequest/${t}`, bodyString: s, signature: c });
|
|
29
30
|
try {
|
|
30
31
|
const o = await fetch(e, {
|
|
31
32
|
method: "POST",
|
|
@@ -35,26 +36,26 @@ const d = ["HUF", "EUR", "USD"], i = (...e) => {
|
|
|
35
36
|
},
|
|
36
37
|
body: s
|
|
37
38
|
});
|
|
38
|
-
if (i({ function: `SimplePay/makeRequest/${
|
|
39
|
+
if (i({ function: `SimplePay/makeRequest/${t}`, response: o }), !o.ok)
|
|
39
40
|
throw new Error(`SimplePay API error: ${o.status}`);
|
|
40
41
|
const u = o.headers.get("Signature");
|
|
41
|
-
if (i({ function: `SimplePay/makeRequest/${
|
|
42
|
+
if (i({ function: `SimplePay/makeRequest/${t}`, responseSignature: u }), !u)
|
|
42
43
|
throw new Error("Missing response signature");
|
|
43
|
-
const
|
|
44
|
-
if (i({ function: `SimplePay/makeRequest/${
|
|
44
|
+
const R = await o.text(), a = JSON.parse(R);
|
|
45
|
+
if (i({ function: `SimplePay/makeRequest/${t}`, responseText: R, responseJSON: a }), a.errorCodes)
|
|
45
46
|
throw new Error(`SimplePay API error: ${a.errorCodes}`);
|
|
46
|
-
if (!
|
|
47
|
+
if (!_(R, u, r))
|
|
47
48
|
throw new Error("Invalid response signature");
|
|
48
49
|
return a;
|
|
49
50
|
} catch (o) {
|
|
50
51
|
throw o;
|
|
51
52
|
}
|
|
52
|
-
},
|
|
53
|
-
i({ function: "SimplePay/getPaymentResponse", r: e, signature:
|
|
54
|
-
const
|
|
55
|
-
if (!
|
|
56
|
-
throw i({ function: "SimplePay/getPaymentResponse", rDecoded:
|
|
57
|
-
const o = JSON.parse(
|
|
53
|
+
}, U = (e, n) => {
|
|
54
|
+
i({ function: "SimplePay/getPaymentResponse", r: e, signature: n }), n = decodeURIComponent(n);
|
|
55
|
+
const r = Buffer.from(e, "base64").toString("utf-8"), t = JSON.parse(r), s = A(t.m), { MERCHANT_KEY: c } = E(s);
|
|
56
|
+
if (!_(r, n, c || ""))
|
|
57
|
+
throw i({ function: "SimplePay/getPaymentResponse", rDecoded: r, signature: n }), new Error("Invalid response signature");
|
|
58
|
+
const o = JSON.parse(r);
|
|
58
59
|
return {
|
|
59
60
|
responseCode: o.r,
|
|
60
61
|
transactionId: o.t,
|
|
@@ -65,61 +66,61 @@ const d = ["HUF", "EUR", "USD"], i = (...e) => {
|
|
|
65
66
|
};
|
|
66
67
|
}, w = async (e) => {
|
|
67
68
|
i({ function: "SimplePay/startPayment", paymentData: e });
|
|
68
|
-
const
|
|
69
|
-
if (i({ function: "SimplePay/startPayment", MERCHANT_KEY:
|
|
70
|
-
throw new Error(`Missing SimplePay configuration for ${
|
|
69
|
+
const n = e.currency || "HUF", { MERCHANT_KEY: r, MERCHANT_ID: t, API_URL_PAYMENT: s, SDK_VERSION: c } = E(n);
|
|
70
|
+
if (i({ function: "SimplePay/startPayment", MERCHANT_KEY: r, MERCHANT_ID: t, API_URL_PAYMENT: s }), !r || !t)
|
|
71
|
+
throw new Error(`Missing SimplePay configuration for ${n}`);
|
|
71
72
|
const o = {
|
|
72
73
|
salt: S.randomBytes(16).toString("hex"),
|
|
73
|
-
merchant:
|
|
74
|
+
merchant: t,
|
|
74
75
|
orderRef: e.orderRef,
|
|
75
|
-
currency:
|
|
76
|
+
currency: n,
|
|
76
77
|
customerEmail: e.customerEmail,
|
|
77
78
|
language: e.language || "HU",
|
|
78
79
|
sdkVersion: c,
|
|
79
80
|
methods: [e.method || "CARD"],
|
|
80
81
|
total: String(e.total),
|
|
81
|
-
timeout:
|
|
82
|
+
timeout: m(new Date(Date.now() + 30 * 60 * 1e3)),
|
|
82
83
|
url: process.env.SIMPLEPAY_REDIRECT_URL || "http://url.to.redirect",
|
|
83
84
|
invoice: e.invoice
|
|
84
85
|
};
|
|
85
|
-
return I(s, o,
|
|
86
|
-
},
|
|
86
|
+
return I(s, o, r);
|
|
87
|
+
}, y = 6, C = new Date(Date.now() + y * 30 * 24 * 60 * 60 * 1e3), M = 12e3, N = 3, L = async (e) => {
|
|
87
88
|
i({ function: "SimplePay/startRecurringPayment", paymentData: e });
|
|
88
|
-
const
|
|
89
|
-
if (i({ function: "SimplePay/startRecurringPayment", MERCHANT_KEY:
|
|
90
|
-
throw new Error(`Missing SimplePay configuration for ${
|
|
89
|
+
const n = e.currency || "HUF", { MERCHANT_KEY: r, MERCHANT_ID: t, API_URL_PAYMENT: s, SDK_VERSION: c } = E(n);
|
|
90
|
+
if (i({ function: "SimplePay/startRecurringPayment", MERCHANT_KEY: r, MERCHANT_ID: t, API_URL_PAYMENT: s }), !r || !t)
|
|
91
|
+
throw new Error(`Missing SimplePay configuration for ${n}`);
|
|
91
92
|
const o = {
|
|
92
93
|
salt: S.randomBytes(16).toString("hex"),
|
|
93
|
-
merchant:
|
|
94
|
+
merchant: t,
|
|
94
95
|
orderRef: e.orderRef,
|
|
95
|
-
currency:
|
|
96
|
+
currency: n,
|
|
96
97
|
customer: e.customer,
|
|
97
98
|
customerEmail: e.customerEmail,
|
|
98
99
|
language: e.language || "HU",
|
|
99
100
|
sdkVersion: c,
|
|
100
101
|
methods: ["CARD"],
|
|
101
102
|
recurring: {
|
|
102
|
-
times: e.recurring.times ||
|
|
103
|
-
until: e.recurring.until ||
|
|
103
|
+
times: e.recurring.times || N,
|
|
104
|
+
until: e.recurring.until || m(C),
|
|
104
105
|
maxAmount: e.recurring.maxAmount || M
|
|
105
106
|
},
|
|
106
107
|
threeDSReqAuthMethod: "02",
|
|
107
108
|
total: String(e.total),
|
|
108
|
-
timeout:
|
|
109
|
+
timeout: m(new Date(Date.now() + 30 * 60 * 1e3)),
|
|
109
110
|
url: process.env.SIMPLEPAY_REDIRECT_URL || "http://url.to.redirect",
|
|
110
111
|
invoice: e.invoice
|
|
111
112
|
};
|
|
112
|
-
return f(s, o,
|
|
113
|
-
},
|
|
113
|
+
return f(s, o, r);
|
|
114
|
+
}, H = async (e) => {
|
|
114
115
|
i({ function: "SimplePay/startTokenPayment", paymentData: e });
|
|
115
|
-
const
|
|
116
|
-
if (i({ function: "SimplePay/startTokenPayment", MERCHANT_KEY:
|
|
117
|
-
throw new Error(`Missing SimplePay configuration for ${
|
|
116
|
+
const n = e.currency || "HUF", { MERCHANT_KEY: r, MERCHANT_ID: t, API_URL_RECURRING: s, SDK_VERSION: c } = E(n);
|
|
117
|
+
if (i({ function: "SimplePay/startTokenPayment", MERCHANT_KEY: r, MERCHANT_ID: t, API_URL_RECURRING: s }), !r || !t)
|
|
118
|
+
throw new Error(`Missing SimplePay configuration for ${n}`);
|
|
118
119
|
const o = {
|
|
119
120
|
salt: S.randomBytes(16).toString("hex"),
|
|
120
|
-
merchant:
|
|
121
|
+
merchant: t,
|
|
121
122
|
orderRef: e.orderRef,
|
|
122
|
-
currency:
|
|
123
|
+
currency: n,
|
|
123
124
|
customer: e.customer,
|
|
124
125
|
customerEmail: e.customerEmail,
|
|
125
126
|
language: e.language || "HU",
|
|
@@ -129,19 +130,32 @@ const d = ["HUF", "EUR", "USD"], i = (...e) => {
|
|
|
129
130
|
type: "MIT",
|
|
130
131
|
threeDSReqAuthMethod: "02",
|
|
131
132
|
total: String(e.total),
|
|
132
|
-
timeout:
|
|
133
|
+
timeout: m(new Date(Date.now() + 30 * 60 * 1e3)),
|
|
133
134
|
url: process.env.SIMPLEPAY_REDIRECT_URL || "http://recurring.url.to.redirect",
|
|
134
135
|
invoice: e.invoice
|
|
135
136
|
};
|
|
136
|
-
return
|
|
137
|
+
return p(s, o, r);
|
|
138
|
+
}, k = async (e) => {
|
|
139
|
+
i({ function: "SimplePay/cardCancel", cardId: e });
|
|
140
|
+
const { API_URL_CARD_CANCEL: n, MERCHANT_KEY: r, MERCHANT_ID: t, SDK_VERSION: s } = E("HUF");
|
|
141
|
+
if (!r || !t)
|
|
142
|
+
throw new Error("Missing SimplePay configuration for HUF");
|
|
143
|
+
const c = {
|
|
144
|
+
salt: S.randomBytes(16).toString("hex"),
|
|
145
|
+
cardId: e,
|
|
146
|
+
merchant: t,
|
|
147
|
+
sdkVersion: s
|
|
148
|
+
};
|
|
149
|
+
return h(n, c, r);
|
|
137
150
|
};
|
|
138
151
|
export {
|
|
139
|
-
|
|
152
|
+
k as cardCancel,
|
|
153
|
+
_ as checkSignature,
|
|
140
154
|
l as generateSignature,
|
|
141
|
-
|
|
155
|
+
U as getPaymentResponse,
|
|
142
156
|
w as startPayment,
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
157
|
+
L as startRecurringPayment,
|
|
158
|
+
H as startTokenPayment,
|
|
159
|
+
m as toISO8601DateString
|
|
146
160
|
};
|
|
147
161
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/types.ts","../src/utils.ts","../src/oneTime.ts","../src/recurring.ts"],"sourcesContent":["export type PaymentMethod = 'CARD' | 'WIRE'\n\nexport const CURRENCIES = ['HUF', 'EUR', 'USD'] as const\nexport type Currency = typeof CURRENCIES[number]\n\nexport const LANGUAGES = [\n 'AR', // Arabic\n 'BG', // Bulgarian\n 'CS', // Czech\n 'DE', // German\n 'EN', // English\n 'ES', // Spanish\n 'FR', // French\n 'IT', // Italian\n 'HR', // Croatian\n 'HU', // Hungarian\n 'PL', // Polish\n 'RO', // Romanian\n 'RU', // Russian\n 'SK', // Slovak\n 'TR', // Turkish\n 'ZH', // Chinese\n] as const\nexport type Language = typeof LANGUAGES[number]\n\nexport interface PaymentData {\n orderRef: string\n total: number | string\n customerEmail: string\n currency?: Currency\n language?: Language\n method?: PaymentMethod\n invoice?: {\n name: string\n country: string\n state: string\n city: string\n zip: string\n address: string\n address2?: string\n phone?: string\n }\n}\n\nexport type ISO8601DateString = string\nexport interface Recurring {\n times: number,\n until: ISO8601DateString,\n maxAmount: number\n}\nexport interface RecurringPaymentData extends PaymentData {\n customer: string,\n recurring: Recurring\n}\n\nexport interface TokenPaymentData extends Omit<PaymentData, 'method'> {\n method: 'CARD',\n customer: string,\n token: string\n}\n\nexport interface SimplePayRequestBody extends Omit<PaymentData, 'total'> {\n total: string\n salt: string\n merchant: string\n sdkVersion: string\n methods: PaymentMethod[]\n timeout: string\n url: string\n}\n\nexport interface SimplePayRecurringRequestBody extends SimplePayRequestBody {\n customer: string\n recurring: Recurring\n threeDSReqAuthMethod: '02' // only registered users can use this\n}\n\nexport interface SimplePayTokenRequestBody extends SimplePayRequestBody {\n customer: string\n token: string\n threeDSReqAuthMethod: '02' // only registered users can use this\n type: 'MIT' // Merchant Initiated Transaction\n}\n\nexport interface SimplePayResponse {\n salt: string\n merchant: string\n orderRef: string\n currency: Currency\n transactionId: string\n timeout: ISO8601DateString\n total: string\n paymentUrl: string\n errorCodes?: string[]\n}\n\nexport interface SimplePayRecurringResponse extends SimplePayResponse {\n tokens: string[]\n}\n\nexport interface SimplePayTokenResponse extends Omit<SimplePayResponse, 'paymentUrl' | 'timeout'> { }\n\nexport type SimplePayEvents = 'SUCCESS' | 'FAIL' | 'TIMEOUT' | 'CANCEL'\n\nexport interface SimplePayAPIResult {\n r: number // response code\n t: string // transaction id\n e: SimplePayEvents // event\n m: string // merchant id\n o: string // order id\n}\n\nexport interface SimplePayResult {\n responseCode: number,\n transactionId: string,\n event: SimplePayEvents,\n merchantId: string,\n orderRef: string,\n tokens?: string[],\n}\n","import crypto from 'crypto'\nimport { CURRENCIES, Currency, ISO8601DateString, SimplePayAPIResult, SimplePayRecurringRequestBody, SimplePayRecurringResponse, SimplePayRequestBody, SimplePayResponse, SimplePayResult, SimplePayTokenRequestBody, SimplePayTokenResponse } from \"./types\"\n\nexport const simplepayLogger = (...args: any[]) => {\n if (process.env.SIMPLEPAY_LOGGER !== 'true') {\n return\n }\n\n console.log('👉 ', ...args)\n}\n\nexport const getSimplePayConfig = (currency: Currency) => {\n if (!CURRENCIES.includes(currency)) {\n throw new Error(`Unsupported currency: ${currency}`)\n }\n\n const SIMPLEPAY_API_URL = 'https://secure.simplepay.hu/payment/v2'\n const SIMPLEPAY_SANDBOX_URL = 'https://sandbox.simplepay.hu/payment/v2/start'\n const SDK_VERSION = 'SimplePayV2.1_Rrd_0.6.1'\n const MERCHANT_KEY = process.env[`SIMPLEPAY_MERCHANT_KEY_${currency}`]\n const MERCHANT_ID = process.env[`SIMPLEPAY_MERCHANT_ID_${currency}`]\n const API_URL = process.env.SIMPLEPAY_PRODUCTION === 'true' ? SIMPLEPAY_API_URL : SIMPLEPAY_SANDBOX_URL\n const API_URL_RECURRING = process.env.SIMPLEPAY_PRODUCTION === 'true' ? SIMPLEPAY_API_URL : 'https://sandbox.simplepay.hu/payment/v2/dorecurring'\n\n return {\n MERCHANT_KEY,\n MERCHANT_ID,\n API_URL,\n API_URL_RECURRING,\n SDK_VERSION\n }\n}\n\n// escaping slashes for the request body to prevent strange SimplePay API errors (eg Missing Signature)\nexport const prepareRequestBody = (body: any) =>\n JSON.stringify(body).replace(/\\//g, '\\\\/')\n\nexport const generateSignature = (body: string, merchantKey: string) => {\n const hmac = crypto.createHmac('sha384', merchantKey.trim())\n hmac.update(body, 'utf8')\n return hmac.digest('base64')\n}\n\nexport const checkSignature = (responseText: string, signature: string, merchantKey: string) =>\n signature === generateSignature(responseText, merchantKey)\n\nexport const toISO8601DateString = (date: Date): ISO8601DateString => date.toISOString().replace(/\\.\\d{3}Z$/, '+00:00')\n\nexport const getCurrencyFromMerchantId = (merchantId: string) => {\n const currency = Object.entries(process.env)\n .find(([key, value]) =>\n key.startsWith('SIMPLEPAY_MERCHANT_ID_') && value === merchantId\n )?.[0]?.replace('SIMPLEPAY_MERCHANT_ID_', '') as Currency\n if (!currency) {\n throw new Error(`Merchant id not found in the environment: ${merchantId}`)\n }\n return currency\n}\n\nexport const makeSimplePayRequest = async (apiUrl: string, requestBody: SimplePayRequestBody, merchantKey: string) => {\n return makeRequest(apiUrl, requestBody, merchantKey, 'oneTime') as Promise<SimplePayResponse>\n}\n\nexport const makeSimplePayRecurringRequest = async (apiUrl: string, requestBody: SimplePayRecurringRequestBody, merchantKey: string) => {\n return makeRequest(apiUrl, requestBody, merchantKey, 'recurring') as Promise<SimplePayRecurringResponse>\n}\n\nexport const makeSimplePayTokenRequest = async (apiUrl: string, requestBody: SimplePayTokenRequestBody, merchantKey: string) => {\n return makeRequest(apiUrl, requestBody, merchantKey, 'token') as Promise<SimplePayTokenResponse>\n}\n\nconst makeRequest = async (apiUrl: string, requestBody: SimplePayRequestBody | SimplePayRecurringRequestBody | SimplePayTokenRequestBody, merchantKey: string, type: 'oneTime' | 'recurring' | 'token') => {\n const bodyString = prepareRequestBody(requestBody)\n const signature = generateSignature(bodyString, merchantKey)\n simplepayLogger({ function: `SimplePay/makeRequest/${type}`, bodyString, signature })\n\n try {\n const response = await fetch(apiUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Signature': signature,\n },\n body: bodyString,\n })\n\n simplepayLogger({ function: `SimplePay/makeRequest/${type}`, response })\n\n if (!response.ok) {\n throw new Error(`SimplePay API error: ${response.status}`)\n }\n\n const responseSignature = response.headers.get('Signature')\n simplepayLogger({ function: `SimplePay/makeRequest/${type}`, responseSignature })\n if (!responseSignature) {\n throw new Error('Missing response signature')\n }\n\n const responseText = await response.text()\n const responseJSON = JSON.parse(responseText) as { errorCodes?: string[] }\n simplepayLogger({ function: `SimplePay/makeRequest/${type}`, responseText, responseJSON })\n\n if (responseJSON.errorCodes) {\n throw new Error(`SimplePay API error: ${responseJSON.errorCodes}`)\n }\n\n if (!checkSignature(responseText, responseSignature, merchantKey)) {\n throw new Error('Invalid response signature')\n }\n\n return responseJSON\n\n } catch (error) {\n throw error\n }\n}\n\nexport const getPaymentResponse = (r: string, signature: string) => {\n simplepayLogger({ function: 'SimplePay/getPaymentResponse', r, signature })\n signature = decodeURIComponent(signature)\n const rDecoded = Buffer.from(r, 'base64').toString('utf-8')\n const rDecodedJSON = JSON.parse(rDecoded) as SimplePayAPIResult\n const currency = getCurrencyFromMerchantId(rDecodedJSON.m)\n const { MERCHANT_KEY } = getSimplePayConfig(currency as Currency)\n\n if (!checkSignature(rDecoded, signature, MERCHANT_KEY || '')) {\n simplepayLogger({ function: 'SimplePay/getPaymentResponse', rDecoded, signature })\n throw new Error('Invalid response signature')\n }\n\n const responseJson = JSON.parse(rDecoded)\n const response: SimplePayResult = {\n responseCode: responseJson.r,\n transactionId: responseJson.t,\n event: responseJson.e,\n merchantId: responseJson.m,\n orderRef: responseJson.o,\n tokens: responseJson.tokens,\n }\n\n return response\n}\n","import crypto from 'crypto'\nimport { PaymentData, SimplePayRequestBody } from './types'\nimport { simplepayLogger, getSimplePayConfig, toISO8601DateString, makeSimplePayRequest } from './utils'\n\nconst startPayment = async (paymentData: PaymentData) => {\n simplepayLogger({ function: 'SimplePay/startPayment', paymentData })\n const currency = paymentData.currency || 'HUF'\n const { MERCHANT_KEY, MERCHANT_ID, API_URL, SDK_VERSION } = getSimplePayConfig(currency)\n simplepayLogger({ function: 'SimplePay/startPayment', MERCHANT_KEY, MERCHANT_ID, API_URL })\n\n if (!MERCHANT_KEY || !MERCHANT_ID) {\n throw new Error(`Missing SimplePay configuration for ${currency}`)\n }\n\n const requestBody: SimplePayRequestBody = {\n salt: crypto.randomBytes(16).toString('hex'),\n merchant: MERCHANT_ID,\n orderRef: paymentData.orderRef,\n currency,\n customerEmail: paymentData.customerEmail,\n language: paymentData.language || 'HU',\n sdkVersion: SDK_VERSION,\n methods: [paymentData.method || 'CARD'],\n total: String(paymentData.total),\n timeout: toISO8601DateString(new Date(Date.now() + 30 * 60 * 1000)),\n url: process.env.SIMPLEPAY_REDIRECT_URL || 'http://url.to.redirect',\n invoice: paymentData.invoice,\n }\n\n return makeSimplePayRequest(API_URL, requestBody, MERCHANT_KEY)\n}\n\nexport { startPayment }\n","import crypto from 'crypto'\nimport { SimplePayRecurringRequestBody, RecurringPaymentData, TokenPaymentData, SimplePayTokenRequestBody} from './types'\nimport { getSimplePayConfig, simplepayLogger, toISO8601DateString, makeSimplePayTokenRequest, makeSimplePayRecurringRequest} from './utils'\n\nconst INTERVAL_IN_MONTHS = 6\nconst DEFAULT_UNTIL = new Date(Date.now() + INTERVAL_IN_MONTHS * 30 * 24 * 60 * 60 * 1000)\nconst DEFAULT_MAX_AMOUNT = 12000\nconst DEFAULT_TIMES = 3\n\nconst startRecurringPayment = async (paymentData: RecurringPaymentData) => {\n simplepayLogger({ function: 'SimplePay/startRecurringPayment', paymentData })\n const currency = paymentData.currency || 'HUF'\n const { MERCHANT_KEY, MERCHANT_ID, API_URL, SDK_VERSION } = getSimplePayConfig(currency)\n simplepayLogger({ function: 'SimplePay/startRecurringPayment', MERCHANT_KEY, MERCHANT_ID, API_URL })\n\n if (!MERCHANT_KEY || !MERCHANT_ID) {\n throw new Error(`Missing SimplePay configuration for ${currency}`)\n }\n\n const requestBody: SimplePayRecurringRequestBody = {\n salt: crypto.randomBytes(16).toString('hex'),\n merchant: MERCHANT_ID,\n orderRef: paymentData.orderRef,\n currency,\n customer: paymentData.customer,\n customerEmail: paymentData.customerEmail,\n language: paymentData.language || 'HU',\n sdkVersion: SDK_VERSION,\n methods: ['CARD'],\n recurring: {\n times: paymentData.recurring.times || DEFAULT_TIMES,\n until: paymentData.recurring.until || toISO8601DateString(DEFAULT_UNTIL),\n maxAmount: paymentData.recurring.maxAmount || DEFAULT_MAX_AMOUNT\n },\n threeDSReqAuthMethod: '02', \n total: String(paymentData.total),\n timeout: toISO8601DateString(new Date(Date.now() + 30 * 60 * 1000)),\n url: process.env.SIMPLEPAY_REDIRECT_URL || 'http://url.to.redirect',\n invoice: paymentData.invoice,\n }\n\n return makeSimplePayRecurringRequest(API_URL, requestBody, MERCHANT_KEY)\n}\n\nconst startTokenPayment = async (paymentData: TokenPaymentData) => {\n simplepayLogger({ function: 'SimplePay/startTokenPayment', paymentData })\n const currency = paymentData.currency || 'HUF'\n const { MERCHANT_KEY, MERCHANT_ID, API_URL_RECURRING, SDK_VERSION } = getSimplePayConfig(currency)\n simplepayLogger({ function: 'SimplePay/startTokenPayment', MERCHANT_KEY, MERCHANT_ID, API_URL_RECURRING })\n\n if (!MERCHANT_KEY || !MERCHANT_ID) {\n throw new Error(`Missing SimplePay configuration for ${currency}`)\n }\n\n const requestBody: SimplePayTokenRequestBody = {\n salt: crypto.randomBytes(16).toString('hex'),\n merchant: MERCHANT_ID,\n orderRef: paymentData.orderRef,\n currency,\n customer: paymentData.customer,\n customerEmail: paymentData.customerEmail,\n language: paymentData.language || 'HU',\n sdkVersion: SDK_VERSION,\n methods: ['CARD'],\n token: paymentData.token,\n type: 'MIT',\n threeDSReqAuthMethod: '02',\n total: String(paymentData.total),\n timeout: toISO8601DateString(new Date(Date.now() + 30 * 60 * 1000)),\n url: process.env.SIMPLEPAY_REDIRECT_URL || 'http://recurring.url.to.redirect',\n invoice: paymentData.invoice,\n }\n\n return makeSimplePayTokenRequest(API_URL_RECURRING, requestBody, MERCHANT_KEY)\n}\n\nexport { startRecurringPayment, startTokenPayment }"],"names":["CURRENCIES","simplepayLogger","args","getSimplePayConfig","currency","SIMPLEPAY_API_URL","SIMPLEPAY_SANDBOX_URL","SDK_VERSION","MERCHANT_KEY","MERCHANT_ID","API_URL","API_URL_RECURRING","prepareRequestBody","body","generateSignature","merchantKey","hmac","crypto","checkSignature","responseText","signature","toISO8601DateString","date","getCurrencyFromMerchantId","merchantId","_b","_a","key","value","makeSimplePayRequest","apiUrl","requestBody","makeRequest","makeSimplePayRecurringRequest","makeSimplePayTokenRequest","type","bodyString","response","responseSignature","responseJSON","error","getPaymentResponse","r","rDecoded","rDecodedJSON","responseJson","startPayment","paymentData","INTERVAL_IN_MONTHS","DEFAULT_UNTIL","DEFAULT_MAX_AMOUNT","DEFAULT_TIMES","startRecurringPayment","startTokenPayment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/types.ts","../src/utils.ts","../src/oneTime.ts","../src/recurring.ts"],"sourcesContent":["export type PaymentMethod = 'CARD' | 'WIRE'\n\nexport const CURRENCIES = ['HUF', 'EUR', 'USD'] as const\nexport type Currency = typeof CURRENCIES[number]\n\nexport const LANGUAGES = [\n 'AR', // Arabic\n 'BG', // Bulgarian\n 'CS', // Czech\n 'DE', // German\n 'EN', // English\n 'ES', // Spanish\n 'FR', // French\n 'IT', // Italian\n 'HR', // Croatian\n 'HU', // Hungarian\n 'PL', // Polish\n 'RO', // Romanian\n 'RU', // Russian\n 'SK', // Slovak\n 'TR', // Turkish\n 'ZH', // Chinese\n] as const\nexport type Language = typeof LANGUAGES[number]\n\nexport interface PaymentData {\n orderRef: string\n total: number | string\n customerEmail: string\n currency?: Currency\n language?: Language\n method?: PaymentMethod\n invoice?: {\n name: string\n country: string\n state: string\n city: string\n zip: string\n address: string\n address2?: string\n phone?: string\n }\n}\n\nexport type ISO8601DateString = string\nexport interface Recurring {\n times: number,\n until: ISO8601DateString,\n maxAmount: number\n}\nexport interface RecurringPaymentData extends PaymentData {\n customer: string,\n recurring: Recurring\n}\n\nexport interface TokenPaymentData extends Omit<PaymentData, 'method'> {\n method: 'CARD',\n customer: string,\n token: string\n}\n\nexport interface SimplePayRequestBody extends Omit<PaymentData, 'total'> {\n total: string\n salt: string\n merchant: string\n sdkVersion: string\n methods: PaymentMethod[]\n timeout: string\n url: string\n}\n\nexport interface SimplePayRecurringRequestBody extends SimplePayRequestBody {\n customer: string\n recurring: Recurring\n threeDSReqAuthMethod: '02' // only registered users can use this\n}\n\nexport interface SimplePayTokenRequestBody extends SimplePayRequestBody {\n customer: string\n token: string\n threeDSReqAuthMethod: '02' // only registered users can use this\n type: 'MIT' // Merchant Initiated Transaction\n}\n\nexport interface SimplePayCardCancelRequestBody {\n salt: string\n cardId: string\n merchant: string\n sdkVersion: string\n}\n\nexport interface SimplePayResponse {\n salt: string\n merchant: string\n orderRef: string\n currency: Currency\n transactionId: string\n timeout: ISO8601DateString\n total: string\n paymentUrl: string\n errorCodes?: string[]\n}\n\nexport interface SimplePayRecurringResponse extends SimplePayResponse {\n tokens: string[]\n}\n\nexport interface SimplePayTokenResponse extends Omit<SimplePayResponse, 'paymentUrl' | 'timeout'> { }\n\nexport interface SimplePayCardCancelResponse {\n salt: string\n merchant: string\n cardId: string\n status: 'DISABLED'\n expiry: string\n}\n\nexport type SimplePayEvents = 'SUCCESS' | 'FAIL' | 'TIMEOUT' | 'CANCEL'\n\nexport interface SimplePayAPIResult {\n r: number // response code\n t: string // transaction id\n e: SimplePayEvents // event\n m: string // merchant id\n o: string // order id\n}\n\nexport interface SimplePayResult {\n responseCode: number,\n transactionId: string,\n event: SimplePayEvents,\n merchantId: string,\n orderRef: string,\n tokens?: string[],\n}\n","import crypto from 'crypto'\nimport { CURRENCIES, Currency, ISO8601DateString, SimplePayAPIResult, SimplePayCardCancelRequestBody, SimplePayCardCancelResponse, SimplePayRecurringRequestBody, SimplePayRecurringResponse, SimplePayRequestBody, SimplePayResponse, SimplePayResult, SimplePayTokenRequestBody, SimplePayTokenResponse } from \"./types\"\n\nexport const simplepayLogger = (...args: any[]) => {\n if (process.env.SIMPLEPAY_LOGGER !== 'true') {\n return\n }\n\n console.log('👉 ', ...args)\n}\n\nexport const getSimplePayConfig = (currency: Currency) => {\n if (!CURRENCIES.includes(currency)) {\n throw new Error(`Unsupported currency: ${currency}`)\n }\n\n const SIMPLEPAY_API_URL = 'https://secure.simplepay.hu/payment/v2'\n const SIMPLEPAY_SANDBOX_URL = 'https://sandbox.simplepay.hu/payment/v2'\n const SDK_VERSION = 'SimplePayV2.1_Rrd_0.8.0'\n const MERCHANT_KEY = process.env[`SIMPLEPAY_MERCHANT_KEY_${currency}`]\n const MERCHANT_ID = process.env[`SIMPLEPAY_MERCHANT_ID_${currency}`]\n\n const API_URL = process.env.SIMPLEPAY_PRODUCTION === 'true' ? SIMPLEPAY_API_URL : SIMPLEPAY_SANDBOX_URL\n const API_URL_PAYMENT = API_URL + '/start'\n const API_URL_RECURRING = API_URL + '/dorecurring'\n const API_URL_CARD_CANCEL = API_URL + '/cancelcard'\n return {\n MERCHANT_KEY,\n MERCHANT_ID,\n API_URL_PAYMENT,\n API_URL_RECURRING,\n API_URL_CARD_CANCEL,\n SDK_VERSION\n }\n}\n\n// escaping slashes for the request body to prevent strange SimplePay API errors (eg Missing Signature)\nexport const prepareRequestBody = (body: any) =>\n JSON.stringify(body).replace(/\\//g, '\\\\/')\n\nexport const generateSignature = (body: string, merchantKey: string) => {\n const hmac = crypto.createHmac('sha384', merchantKey.trim())\n hmac.update(body, 'utf8')\n return hmac.digest('base64')\n}\n\nexport const checkSignature = (responseText: string, signature: string, merchantKey: string) =>\n signature === generateSignature(responseText, merchantKey)\n\nexport const toISO8601DateString = (date: Date): ISO8601DateString => date.toISOString().replace(/\\.\\d{3}Z$/, '+00:00')\n\nexport const getCurrencyFromMerchantId = (merchantId: string) => {\n const currency = Object.entries(process.env)\n .find(([key, value]) =>\n key.startsWith('SIMPLEPAY_MERCHANT_ID_') && value === merchantId\n )?.[0]?.replace('SIMPLEPAY_MERCHANT_ID_', '') as Currency\n if (!currency) {\n throw new Error(`Merchant id not found in the environment: ${merchantId}`)\n }\n return currency\n}\n\nexport const makeSimplePayRequest = async (apiUrl: string, requestBody: SimplePayRequestBody, merchantKey: string) => {\n return makeRequest(apiUrl, requestBody, merchantKey, 'oneTime') as Promise<SimplePayResponse>\n}\n\nexport const makeSimplePayRecurringRequest = async (apiUrl: string, requestBody: SimplePayRecurringRequestBody, merchantKey: string) => {\n return makeRequest(apiUrl, requestBody, merchantKey, 'recurring') as Promise<SimplePayRecurringResponse>\n}\n\nexport const makeSimplePayTokenRequest = async (apiUrl: string, requestBody: SimplePayTokenRequestBody, merchantKey: string) => {\n return makeRequest(apiUrl, requestBody, merchantKey, 'token') as Promise<SimplePayTokenResponse>\n}\n\nexport const makeSimplePayCardCancelRequest = async (apiUrl: string, requestBody: SimplePayCardCancelRequestBody, merchantKey: string) => {\n return makeRequest(apiUrl, requestBody, merchantKey, 'cardCancel') as Promise<SimplePayCardCancelResponse>\n}\n\nconst makeRequest = async (apiUrl: string, requestBody: SimplePayRequestBody | SimplePayRecurringRequestBody | SimplePayTokenRequestBody | SimplePayCardCancelRequestBody, merchantKey: string, type: 'oneTime' | 'recurring' | 'token' | 'cardCancel') => {\n const bodyString = prepareRequestBody(requestBody)\n const signature = generateSignature(bodyString, merchantKey)\n simplepayLogger({ function: `SimplePay/makeRequest/${type}`, bodyString, signature })\n\n try {\n const response = await fetch(apiUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Signature': signature,\n },\n body: bodyString,\n })\n\n simplepayLogger({ function: `SimplePay/makeRequest/${type}`, response })\n\n if (!response.ok) {\n throw new Error(`SimplePay API error: ${response.status}`)\n }\n\n const responseSignature = response.headers.get('Signature')\n simplepayLogger({ function: `SimplePay/makeRequest/${type}`, responseSignature })\n if (!responseSignature) {\n throw new Error('Missing response signature')\n }\n\n const responseText = await response.text()\n const responseJSON = JSON.parse(responseText) as { errorCodes?: string[] }\n simplepayLogger({ function: `SimplePay/makeRequest/${type}`, responseText, responseJSON })\n\n if (responseJSON.errorCodes) {\n throw new Error(`SimplePay API error: ${responseJSON.errorCodes}`)\n }\n\n if (!checkSignature(responseText, responseSignature, merchantKey)) {\n throw new Error('Invalid response signature')\n }\n\n return responseJSON\n\n } catch (error) {\n throw error\n }\n}\n\nexport const getPaymentResponse = (r: string, signature: string) => {\n simplepayLogger({ function: 'SimplePay/getPaymentResponse', r, signature })\n signature = decodeURIComponent(signature)\n const rDecoded = Buffer.from(r, 'base64').toString('utf-8')\n const rDecodedJSON = JSON.parse(rDecoded) as SimplePayAPIResult\n const currency = getCurrencyFromMerchantId(rDecodedJSON.m)\n const { MERCHANT_KEY } = getSimplePayConfig(currency as Currency)\n\n if (!checkSignature(rDecoded, signature, MERCHANT_KEY || '')) {\n simplepayLogger({ function: 'SimplePay/getPaymentResponse', rDecoded, signature })\n throw new Error('Invalid response signature')\n }\n\n const responseJson = JSON.parse(rDecoded)\n const response: SimplePayResult = {\n responseCode: responseJson.r,\n transactionId: responseJson.t,\n event: responseJson.e,\n merchantId: responseJson.m,\n orderRef: responseJson.o,\n tokens: responseJson.tokens,\n }\n\n return response\n}\n","import crypto from 'crypto'\nimport { PaymentData, SimplePayRequestBody } from './types'\nimport { simplepayLogger, getSimplePayConfig, toISO8601DateString, makeSimplePayRequest } from './utils'\n\nconst startPayment = async (paymentData: PaymentData) => {\n simplepayLogger({ function: 'SimplePay/startPayment', paymentData })\n const currency = paymentData.currency || 'HUF'\n const { MERCHANT_KEY, MERCHANT_ID, API_URL_PAYMENT, SDK_VERSION } = getSimplePayConfig(currency)\n simplepayLogger({ function: 'SimplePay/startPayment', MERCHANT_KEY, MERCHANT_ID, API_URL_PAYMENT })\n\n if (!MERCHANT_KEY || !MERCHANT_ID) {\n throw new Error(`Missing SimplePay configuration for ${currency}`)\n }\n\n const requestBody: SimplePayRequestBody = {\n salt: crypto.randomBytes(16).toString('hex'),\n merchant: MERCHANT_ID,\n orderRef: paymentData.orderRef,\n currency,\n customerEmail: paymentData.customerEmail,\n language: paymentData.language || 'HU',\n sdkVersion: SDK_VERSION,\n methods: [paymentData.method || 'CARD'],\n total: String(paymentData.total),\n timeout: toISO8601DateString(new Date(Date.now() + 30 * 60 * 1000)),\n url: process.env.SIMPLEPAY_REDIRECT_URL || 'http://url.to.redirect',\n invoice: paymentData.invoice,\n }\n\n return makeSimplePayRequest(API_URL_PAYMENT, requestBody, MERCHANT_KEY)\n}\n\nexport { startPayment }\n","import crypto from 'crypto'\nimport { SimplePayRecurringRequestBody, RecurringPaymentData, TokenPaymentData, SimplePayTokenRequestBody, SimplePayCardCancelRequestBody} from './types'\nimport { getSimplePayConfig, simplepayLogger, toISO8601DateString, makeSimplePayTokenRequest, makeSimplePayRecurringRequest, makeSimplePayRequest, makeSimplePayCardCancelRequest} from './utils'\n\nconst INTERVAL_IN_MONTHS = 6\nconst DEFAULT_UNTIL = new Date(Date.now() + INTERVAL_IN_MONTHS * 30 * 24 * 60 * 60 * 1000)\nconst DEFAULT_MAX_AMOUNT = 12000\nconst DEFAULT_TIMES = 3\n\nconst startRecurringPayment = async (paymentData: RecurringPaymentData) => {\n simplepayLogger({ function: 'SimplePay/startRecurringPayment', paymentData })\n const currency = paymentData.currency || 'HUF'\n const { MERCHANT_KEY, MERCHANT_ID, API_URL_PAYMENT, SDK_VERSION } = getSimplePayConfig(currency)\n simplepayLogger({ function: 'SimplePay/startRecurringPayment', MERCHANT_KEY, MERCHANT_ID, API_URL_PAYMENT })\n\n if (!MERCHANT_KEY || !MERCHANT_ID) {\n throw new Error(`Missing SimplePay configuration for ${currency}`)\n }\n\n const requestBody: SimplePayRecurringRequestBody = {\n salt: crypto.randomBytes(16).toString('hex'),\n merchant: MERCHANT_ID,\n orderRef: paymentData.orderRef,\n currency,\n customer: paymentData.customer,\n customerEmail: paymentData.customerEmail,\n language: paymentData.language || 'HU',\n sdkVersion: SDK_VERSION,\n methods: ['CARD'],\n recurring: {\n times: paymentData.recurring.times || DEFAULT_TIMES,\n until: paymentData.recurring.until || toISO8601DateString(DEFAULT_UNTIL),\n maxAmount: paymentData.recurring.maxAmount || DEFAULT_MAX_AMOUNT\n },\n threeDSReqAuthMethod: '02', \n total: String(paymentData.total),\n timeout: toISO8601DateString(new Date(Date.now() + 30 * 60 * 1000)),\n url: process.env.SIMPLEPAY_REDIRECT_URL || 'http://url.to.redirect',\n invoice: paymentData.invoice,\n }\n\n return makeSimplePayRecurringRequest(API_URL_PAYMENT, requestBody, MERCHANT_KEY)\n}\n\nconst startTokenPayment = async (paymentData: TokenPaymentData) => {\n simplepayLogger({ function: 'SimplePay/startTokenPayment', paymentData })\n const currency = paymentData.currency || 'HUF'\n const { MERCHANT_KEY, MERCHANT_ID, API_URL_RECURRING, SDK_VERSION } = getSimplePayConfig(currency)\n simplepayLogger({ function: 'SimplePay/startTokenPayment', MERCHANT_KEY, MERCHANT_ID, API_URL_RECURRING })\n\n if (!MERCHANT_KEY || !MERCHANT_ID) {\n throw new Error(`Missing SimplePay configuration for ${currency}`)\n }\n\n const requestBody: SimplePayTokenRequestBody = {\n salt: crypto.randomBytes(16).toString('hex'),\n merchant: MERCHANT_ID,\n orderRef: paymentData.orderRef,\n currency,\n customer: paymentData.customer,\n customerEmail: paymentData.customerEmail,\n language: paymentData.language || 'HU',\n sdkVersion: SDK_VERSION,\n methods: ['CARD'],\n token: paymentData.token,\n type: 'MIT',\n threeDSReqAuthMethod: '02',\n total: String(paymentData.total),\n timeout: toISO8601DateString(new Date(Date.now() + 30 * 60 * 1000)),\n url: process.env.SIMPLEPAY_REDIRECT_URL || 'http://recurring.url.to.redirect',\n invoice: paymentData.invoice,\n }\n\n return makeSimplePayTokenRequest(API_URL_RECURRING, requestBody, MERCHANT_KEY)\n}\n\nconst cardCancel = async (cardId: string) => {\n simplepayLogger({ function: 'SimplePay/cardCancel', cardId })\n const {API_URL_CARD_CANCEL, MERCHANT_KEY, MERCHANT_ID, SDK_VERSION} = getSimplePayConfig('HUF')\n\n if (!MERCHANT_KEY || !MERCHANT_ID) {\n throw new Error(`Missing SimplePay configuration for HUF`)\n }\n\n const requestBody: SimplePayCardCancelRequestBody = {\n salt: crypto.randomBytes(16).toString('hex'),\n cardId,\n merchant: MERCHANT_ID,\n sdkVersion: SDK_VERSION,\n }\n return makeSimplePayCardCancelRequest(API_URL_CARD_CANCEL, requestBody, MERCHANT_KEY)\n}\n\nexport { startRecurringPayment, startTokenPayment , cardCancel}\n"],"names":["CURRENCIES","simplepayLogger","args","getSimplePayConfig","currency","SIMPLEPAY_API_URL","SIMPLEPAY_SANDBOX_URL","SDK_VERSION","MERCHANT_KEY","MERCHANT_ID","API_URL","API_URL_PAYMENT","API_URL_RECURRING","API_URL_CARD_CANCEL","prepareRequestBody","body","generateSignature","merchantKey","hmac","crypto","checkSignature","responseText","signature","toISO8601DateString","date","getCurrencyFromMerchantId","merchantId","_b","_a","key","value","makeSimplePayRequest","apiUrl","requestBody","makeRequest","makeSimplePayRecurringRequest","makeSimplePayTokenRequest","makeSimplePayCardCancelRequest","type","bodyString","response","responseSignature","responseJSON","error","getPaymentResponse","r","rDecoded","rDecodedJSON","responseJson","startPayment","paymentData","INTERVAL_IN_MONTHS","DEFAULT_UNTIL","DEFAULT_MAX_AMOUNT","DEFAULT_TIMES","startRecurringPayment","startTokenPayment","cardCancel","cardId"],"mappings":";AAEO,MAAMA,IAAa,CAAC,OAAO,OAAO,KAAK,GCCjCC,IAAkB,IAAIC,MAAgB;AAC3C,EAAA,QAAQ,IAAI,qBAAqB,UAI7B,QAAA,IAAI,OAAO,GAAGA,CAAI;AAC9B,GAEaC,IAAqB,CAACC,MAAuB;AACtD,MAAI,CAACJ,EAAW,SAASI,CAAQ;AAC7B,UAAM,IAAI,MAAM,yBAAyBA,CAAQ,EAAE;AAGvD,QAAMC,IAAoB,0CACpBC,IAAwB,2CACxBC,IAAc,2BACdC,IAAe,QAAQ,IAAI,0BAA0BJ,CAAQ,EAAE,GAC/DK,IAAc,QAAQ,IAAI,yBAAyBL,CAAQ,EAAE,GAE7DM,IAAU,QAAQ,IAAI,yBAAyB,SAASL,IAAoBC,GAC5EK,IAAkBD,IAAU,UAC5BE,IAAoBF,IAAU,gBAC9BG,IAAsBH,IAAU;AAC/B,SAAA;AAAA,IACH,cAAAF;AAAA,IACA,aAAAC;AAAA,IACA,iBAAAE;AAAA,IACA,mBAAAC;AAAA,IACA,qBAAAC;AAAA,IACA,aAAAN;AAAA,EACJ;AACJ,GAGaO,IAAqB,CAACC,MAC/B,KAAK,UAAUA,CAAI,EAAE,QAAQ,OAAO,KAAK,GAEhCC,IAAoB,CAACD,GAAcE,MAAwB;AACpE,QAAMC,IAAOC,EAAO,WAAW,UAAUF,EAAY,MAAM;AACtD,SAAAC,EAAA,OAAOH,GAAM,MAAM,GACjBG,EAAK,OAAO,QAAQ;AAC/B,GAEaE,IAAiB,CAACC,GAAsBC,GAAmBL,MACpEK,MAAcN,EAAkBK,GAAcJ,CAAW,GAEhDM,IAAsB,CAACC,MAAkCA,EAAK,cAAc,QAAQ,aAAa,QAAQ,GAEzGC,IAA4B,CAACC,MAAuB;;AAC7D,QAAMtB,KAAWuB,KAAAC,IAAA,OAAO,QAAQ,QAAQ,GAAG,EACtC;AAAA,IAAK,CAAC,CAACC,GAAKC,CAAK,MACdD,EAAI,WAAW,wBAAwB,KAAKC,MAAUJ;AAAA,EACtD,MAHS,gBAAAE,EAGT,OAHS,gBAAAD,EAGL,QAAQ,0BAA0B;AAC9C,MAAI,CAACvB;AACD,UAAM,IAAI,MAAM,6CAA6CsB,CAAU,EAAE;AAEtE,SAAAtB;AACX,GAEa2B,IAAuB,OAAOC,GAAgBC,GAAmChB,MACnFiB,EAAYF,GAAQC,GAAahB,GAAa,SAAS,GAGrDkB,IAAgC,OAAOH,GAAgBC,GAA4ChB,MACrGiB,EAAYF,GAAQC,GAAahB,GAAa,WAAW,GAGvDmB,IAA4B,OAAOJ,GAAgBC,GAAwChB,MAC7FiB,EAAYF,GAAQC,GAAahB,GAAa,OAAO,GAGnDoB,IAAiC,OAAOL,GAAgBC,GAA6ChB,MACvGiB,EAAYF,GAAQC,GAAahB,GAAa,YAAY,GAG/DiB,IAAc,OAAOF,GAAgBC,GAAgIhB,GAAqBqB,MAA2D;AACjP,QAAAC,IAAazB,EAAmBmB,CAAW,GAC3CX,IAAYN,EAAkBuB,GAAYtB,CAAW;AAC3D,EAAAhB,EAAgB,EAAE,UAAU,yBAAyBqC,CAAI,IAAI,YAAAC,GAAY,WAAAjB,GAAW;AAEhF,MAAA;AACM,UAAAkB,IAAW,MAAM,MAAMR,GAAQ;AAAA,MACjC,QAAQ;AAAA,MACR,SAAS;AAAA,QACL,gBAAgB;AAAA,QAChB,WAAaV;AAAA,MACjB;AAAA,MACA,MAAMiB;AAAA,IAAA,CACT;AAIG,QAFJtC,EAAgB,EAAE,UAAU,yBAAyBqC,CAAI,IAAI,UAAAE,GAAU,GAEnE,CAACA,EAAS;AACV,YAAM,IAAI,MAAM,wBAAwBA,EAAS,MAAM,EAAE;AAG7D,UAAMC,IAAoBD,EAAS,QAAQ,IAAI,WAAW;AAE1D,QADAvC,EAAgB,EAAE,UAAU,yBAAyBqC,CAAI,IAAI,mBAAAG,GAAmB,GAC5E,CAACA;AACK,YAAA,IAAI,MAAM,4BAA4B;AAG1C,UAAApB,IAAe,MAAMmB,EAAS,KAAK,GACnCE,IAAe,KAAK,MAAMrB,CAAY;AAG5C,QAFApB,EAAgB,EAAE,UAAU,yBAAyBqC,CAAI,IAAI,cAAAjB,GAAc,cAAAqB,GAAc,GAErFA,EAAa;AACb,YAAM,IAAI,MAAM,wBAAwBA,EAAa,UAAU,EAAE;AAGrE,QAAI,CAACtB,EAAeC,GAAcoB,GAAmBxB,CAAW;AACtD,YAAA,IAAI,MAAM,4BAA4B;AAGzC,WAAAyB;AAAA,WAEFC,GAAO;AACN,UAAAA;AAAA,EAAA;AAEd,GAEaC,IAAqB,CAACC,GAAWvB,MAAsB;AAChE,EAAArB,EAAgB,EAAE,UAAU,gCAAgC,GAAA4C,GAAG,WAAAvB,GAAW,GAC1EA,IAAY,mBAAmBA,CAAS;AACxC,QAAMwB,IAAW,OAAO,KAAKD,GAAG,QAAQ,EAAE,SAAS,OAAO,GACpDE,IAAe,KAAK,MAAMD,CAAQ,GAClC1C,IAAWqB,EAA0BsB,EAAa,CAAC,GACnD,EAAE,cAAAvC,EAAA,IAAiBL,EAAmBC,CAAoB;AAEhE,MAAI,CAACgB,EAAe0B,GAAUxB,GAAWd,KAAgB,EAAE;AACvD,UAAAP,EAAgB,EAAE,UAAU,gCAAgC,UAAA6C,GAAU,WAAAxB,GAAW,GAC3E,IAAI,MAAM,4BAA4B;AAG1C,QAAA0B,IAAe,KAAK,MAAMF,CAAQ;AAUjC,SAT2B;AAAA,IAC9B,cAAcE,EAAa;AAAA,IAC3B,eAAeA,EAAa;AAAA,IAC5B,OAAOA,EAAa;AAAA,IACpB,YAAYA,EAAa;AAAA,IACzB,UAAUA,EAAa;AAAA,IACvB,QAAQA,EAAa;AAAA,EACzB;AAGJ,GChJMC,IAAe,OAAOC,MAA6B;AACrD,EAAAjD,EAAgB,EAAE,UAAU,0BAA0B,aAAAiD,EAAA,CAAa;AAC7D,QAAA9C,IAAW8C,EAAY,YAAY,OACnC,EAAE,cAAA1C,GAAc,aAAAC,GAAa,iBAAAE,GAAiB,aAAAJ,EAAY,IAAIJ,EAAmBC,CAAQ;AAG3F,MAFJH,EAAgB,EAAE,UAAU,0BAA0B,cAAAO,GAAc,aAAAC,GAAa,iBAAAE,GAAiB,GAE9F,CAACH,KAAgB,CAACC;AAClB,UAAM,IAAI,MAAM,uCAAuCL,CAAQ,EAAE;AAGrE,QAAM6B,IAAoC;AAAA,IACtC,MAAMd,EAAO,YAAY,EAAE,EAAE,SAAS,KAAK;AAAA,IAC3C,UAAUV;AAAA,IACV,UAAUyC,EAAY;AAAA,IACtB,UAAA9C;AAAA,IACA,eAAe8C,EAAY;AAAA,IAC3B,UAAUA,EAAY,YAAY;AAAA,IAClC,YAAY3C;AAAA,IACZ,SAAS,CAAC2C,EAAY,UAAU,MAAM;AAAA,IACtC,OAAO,OAAOA,EAAY,KAAK;AAAA,IAC/B,SAAS3B,EAAoB,IAAI,KAAK,KAAK,QAAQ,KAAK,KAAK,GAAI,CAAC;AAAA,IAClE,KAAK,QAAQ,IAAI,0BAA0B;AAAA,IAC3C,SAAS2B,EAAY;AAAA,EACzB;AAEO,SAAAnB,EAAqBpB,GAAiBsB,GAAazB,CAAY;AAC1E,GC1BM2C,IAAqB,GACrBC,IAAgB,IAAI,KAAK,KAAK,IAAQ,IAAAD,IAAqB,KAAK,KAAK,KAAK,KAAK,GAAI,GACnFE,IAAqB,MACrBC,IAAgB,GAEhBC,IAAwB,OAAOL,MAAsC;AACvE,EAAAjD,EAAgB,EAAE,UAAU,mCAAmC,aAAAiD,EAAA,CAAa;AACtE,QAAA9C,IAAW8C,EAAY,YAAY,OACnC,EAAE,cAAA1C,GAAc,aAAAC,GAAa,iBAAAE,GAAiB,aAAAJ,EAAY,IAAIJ,EAAmBC,CAAQ;AAG3F,MAFJH,EAAgB,EAAE,UAAU,mCAAmC,cAAAO,GAAc,aAAAC,GAAa,iBAAAE,GAAiB,GAEvG,CAACH,KAAgB,CAACC;AAClB,UAAM,IAAI,MAAM,uCAAuCL,CAAQ,EAAE;AAGrE,QAAM6B,IAA6C;AAAA,IAC/C,MAAMd,EAAO,YAAY,EAAE,EAAE,SAAS,KAAK;AAAA,IAC3C,UAAUV;AAAA,IACV,UAAUyC,EAAY;AAAA,IACtB,UAAA9C;AAAA,IACA,UAAU8C,EAAY;AAAA,IACtB,eAAeA,EAAY;AAAA,IAC3B,UAAUA,EAAY,YAAY;AAAA,IAClC,YAAY3C;AAAA,IACZ,SAAS,CAAC,MAAM;AAAA,IAChB,WAAW;AAAA,MACP,OAAO2C,EAAY,UAAU,SAASI;AAAA,MACtC,OAAOJ,EAAY,UAAU,SAAS3B,EAAoB6B,CAAa;AAAA,MACvE,WAAWF,EAAY,UAAU,aAAaG;AAAA,IAClD;AAAA,IACA,sBAAsB;AAAA,IACtB,OAAO,OAAOH,EAAY,KAAK;AAAA,IAC/B,SAAS3B,EAAoB,IAAI,KAAK,KAAK,QAAQ,KAAK,KAAK,GAAI,CAAC;AAAA,IAClE,KAAK,QAAQ,IAAI,0BAA0B;AAAA,IAC3C,SAAS2B,EAAY;AAAA,EACzB;AAEM,SAAAf,EAA8BxB,GAAiBsB,GAAazB,CAAY;AAClF,GAEMgD,IAAoB,OAAON,MAAkC;AAC/D,EAAAjD,EAAgB,EAAE,UAAU,+BAA+B,aAAAiD,EAAA,CAAa;AAClE,QAAA9C,IAAW8C,EAAY,YAAY,OACnC,EAAE,cAAA1C,GAAc,aAAAC,GAAa,mBAAAG,GAAmB,aAAAL,EAAY,IAAIJ,EAAmBC,CAAQ;AAG7F,MAFJH,EAAgB,EAAE,UAAU,+BAA+B,cAAAO,GAAc,aAAAC,GAAa,mBAAAG,GAAmB,GAErG,CAACJ,KAAgB,CAACC;AAClB,UAAM,IAAI,MAAM,uCAAuCL,CAAQ,EAAE;AAGrE,QAAM6B,IAAyC;AAAA,IAC3C,MAAMd,EAAO,YAAY,EAAE,EAAE,SAAS,KAAK;AAAA,IAC3C,UAAUV;AAAA,IACV,UAAUyC,EAAY;AAAA,IACtB,UAAA9C;AAAA,IACA,UAAU8C,EAAY;AAAA,IACtB,eAAeA,EAAY;AAAA,IAC3B,UAAUA,EAAY,YAAY;AAAA,IAClC,YAAY3C;AAAA,IACZ,SAAS,CAAC,MAAM;AAAA,IAChB,OAAO2C,EAAY;AAAA,IACnB,MAAM;AAAA,IACN,sBAAsB;AAAA,IACtB,OAAO,OAAOA,EAAY,KAAK;AAAA,IAC/B,SAAS3B,EAAoB,IAAI,KAAK,KAAK,QAAQ,KAAK,KAAK,GAAI,CAAC;AAAA,IAClE,KAAK,QAAQ,IAAI,0BAA0B;AAAA,IAC3C,SAAS2B,EAAY;AAAA,EACzB;AAEK,SAAAd,EAA0BxB,GAAmBqB,GAAazB,CAAY;AAC/E,GAEMiD,IAAa,OAAOC,MAAmB;AACzC,EAAAzD,EAAgB,EAAE,UAAU,wBAAwB,QAAAyD,EAAA,CAAQ;AAC5D,QAAM,EAAC,qBAAA7C,GAAqB,cAAAL,GAAc,aAAAC,GAAa,aAAAF,EAAW,IAAIJ,EAAmB,KAAK;AAE1F,MAAA,CAACK,KAAgB,CAACC;AACZ,UAAA,IAAI,MAAM,yCAAyC;AAG7D,QAAMwB,IAA8C;AAAA,IAChD,MAAMd,EAAO,YAAY,EAAE,EAAE,SAAS,KAAK;AAAA,IAC3C,QAAAuC;AAAA,IACA,UAAUjD;AAAA,IACV,YAAYF;AAAA,EAChB;AACO,SAAA8B,EAA+BxB,GAAqBoB,GAAazB,CAAY;AACxF;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "simplepay-js-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "A Node.js utility for SimplePay payment integration",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"license": "MIT",
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@types/node": "^22.0.0",
|
|
41
|
-
"typescript": "~5.
|
|
41
|
+
"typescript": "~5.7.0",
|
|
42
42
|
"vite": "^6.0.3",
|
|
43
43
|
"vite-plugin-dts": "^4.3.0",
|
|
44
44
|
"vitest": "^2.1.6"
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { startPayment } from './oneTime'
|
|
2
|
-
import { startRecurringPayment, startTokenPayment} from './recurring'
|
|
2
|
+
import { startRecurringPayment, startTokenPayment, cardCancel} from './recurring'
|
|
3
3
|
import type { Currency, Language, PaymentMethod } from './types'
|
|
4
4
|
import { checkSignature, generateSignature, getPaymentResponse, toISO8601DateString } from './utils'
|
|
5
5
|
|
|
@@ -7,5 +7,5 @@ export {
|
|
|
7
7
|
Currency, Language, PaymentMethod,
|
|
8
8
|
checkSignature, generateSignature, toISO8601DateString, getPaymentResponse,
|
|
9
9
|
startPayment,
|
|
10
|
-
startRecurringPayment, startTokenPayment,
|
|
10
|
+
startRecurringPayment, startTokenPayment, cardCancel
|
|
11
11
|
}
|
package/src/oneTime.ts
CHANGED
|
@@ -5,8 +5,8 @@ import { simplepayLogger, getSimplePayConfig, toISO8601DateString, makeSimplePay
|
|
|
5
5
|
const startPayment = async (paymentData: PaymentData) => {
|
|
6
6
|
simplepayLogger({ function: 'SimplePay/startPayment', paymentData })
|
|
7
7
|
const currency = paymentData.currency || 'HUF'
|
|
8
|
-
const { MERCHANT_KEY, MERCHANT_ID,
|
|
9
|
-
simplepayLogger({ function: 'SimplePay/startPayment', MERCHANT_KEY, MERCHANT_ID,
|
|
8
|
+
const { MERCHANT_KEY, MERCHANT_ID, API_URL_PAYMENT, SDK_VERSION } = getSimplePayConfig(currency)
|
|
9
|
+
simplepayLogger({ function: 'SimplePay/startPayment', MERCHANT_KEY, MERCHANT_ID, API_URL_PAYMENT })
|
|
10
10
|
|
|
11
11
|
if (!MERCHANT_KEY || !MERCHANT_ID) {
|
|
12
12
|
throw new Error(`Missing SimplePay configuration for ${currency}`)
|
|
@@ -27,7 +27,7 @@ const startPayment = async (paymentData: PaymentData) => {
|
|
|
27
27
|
invoice: paymentData.invoice,
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
return makeSimplePayRequest(
|
|
30
|
+
return makeSimplePayRequest(API_URL_PAYMENT, requestBody, MERCHANT_KEY)
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
export { startPayment }
|
package/src/recurring.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import crypto from 'crypto'
|
|
2
|
-
import { SimplePayRecurringRequestBody, RecurringPaymentData, TokenPaymentData, SimplePayTokenRequestBody} from './types'
|
|
3
|
-
import { getSimplePayConfig, simplepayLogger, toISO8601DateString, makeSimplePayTokenRequest, makeSimplePayRecurringRequest} from './utils'
|
|
2
|
+
import { SimplePayRecurringRequestBody, RecurringPaymentData, TokenPaymentData, SimplePayTokenRequestBody, SimplePayCardCancelRequestBody} from './types'
|
|
3
|
+
import { getSimplePayConfig, simplepayLogger, toISO8601DateString, makeSimplePayTokenRequest, makeSimplePayRecurringRequest, makeSimplePayRequest, makeSimplePayCardCancelRequest} from './utils'
|
|
4
4
|
|
|
5
5
|
const INTERVAL_IN_MONTHS = 6
|
|
6
6
|
const DEFAULT_UNTIL = new Date(Date.now() + INTERVAL_IN_MONTHS * 30 * 24 * 60 * 60 * 1000)
|
|
@@ -10,8 +10,8 @@ const DEFAULT_TIMES = 3
|
|
|
10
10
|
const startRecurringPayment = async (paymentData: RecurringPaymentData) => {
|
|
11
11
|
simplepayLogger({ function: 'SimplePay/startRecurringPayment', paymentData })
|
|
12
12
|
const currency = paymentData.currency || 'HUF'
|
|
13
|
-
const { MERCHANT_KEY, MERCHANT_ID,
|
|
14
|
-
simplepayLogger({ function: 'SimplePay/startRecurringPayment', MERCHANT_KEY, MERCHANT_ID,
|
|
13
|
+
const { MERCHANT_KEY, MERCHANT_ID, API_URL_PAYMENT, SDK_VERSION } = getSimplePayConfig(currency)
|
|
14
|
+
simplepayLogger({ function: 'SimplePay/startRecurringPayment', MERCHANT_KEY, MERCHANT_ID, API_URL_PAYMENT })
|
|
15
15
|
|
|
16
16
|
if (!MERCHANT_KEY || !MERCHANT_ID) {
|
|
17
17
|
throw new Error(`Missing SimplePay configuration for ${currency}`)
|
|
@@ -39,7 +39,7 @@ const startRecurringPayment = async (paymentData: RecurringPaymentData) => {
|
|
|
39
39
|
invoice: paymentData.invoice,
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
return makeSimplePayRecurringRequest(
|
|
42
|
+
return makeSimplePayRecurringRequest(API_URL_PAYMENT, requestBody, MERCHANT_KEY)
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
const startTokenPayment = async (paymentData: TokenPaymentData) => {
|
|
@@ -74,4 +74,21 @@ const startTokenPayment = async (paymentData: TokenPaymentData) => {
|
|
|
74
74
|
return makeSimplePayTokenRequest(API_URL_RECURRING, requestBody, MERCHANT_KEY)
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
const cardCancel = async (cardId: string) => {
|
|
78
|
+
simplepayLogger({ function: 'SimplePay/cardCancel', cardId })
|
|
79
|
+
const {API_URL_CARD_CANCEL, MERCHANT_KEY, MERCHANT_ID, SDK_VERSION} = getSimplePayConfig('HUF')
|
|
80
|
+
|
|
81
|
+
if (!MERCHANT_KEY || !MERCHANT_ID) {
|
|
82
|
+
throw new Error(`Missing SimplePay configuration for HUF`)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const requestBody: SimplePayCardCancelRequestBody = {
|
|
86
|
+
salt: crypto.randomBytes(16).toString('hex'),
|
|
87
|
+
cardId,
|
|
88
|
+
merchant: MERCHANT_ID,
|
|
89
|
+
sdkVersion: SDK_VERSION,
|
|
90
|
+
}
|
|
91
|
+
return makeSimplePayCardCancelRequest(API_URL_CARD_CANCEL, requestBody, MERCHANT_KEY)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export { startRecurringPayment, startTokenPayment , cardCancel}
|
package/src/types.ts
CHANGED
|
@@ -82,6 +82,13 @@ export interface SimplePayTokenRequestBody extends SimplePayRequestBody {
|
|
|
82
82
|
type: 'MIT' // Merchant Initiated Transaction
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
+
export interface SimplePayCardCancelRequestBody {
|
|
86
|
+
salt: string
|
|
87
|
+
cardId: string
|
|
88
|
+
merchant: string
|
|
89
|
+
sdkVersion: string
|
|
90
|
+
}
|
|
91
|
+
|
|
85
92
|
export interface SimplePayResponse {
|
|
86
93
|
salt: string
|
|
87
94
|
merchant: string
|
|
@@ -100,6 +107,14 @@ export interface SimplePayRecurringResponse extends SimplePayResponse {
|
|
|
100
107
|
|
|
101
108
|
export interface SimplePayTokenResponse extends Omit<SimplePayResponse, 'paymentUrl' | 'timeout'> { }
|
|
102
109
|
|
|
110
|
+
export interface SimplePayCardCancelResponse {
|
|
111
|
+
salt: string
|
|
112
|
+
merchant: string
|
|
113
|
+
cardId: string
|
|
114
|
+
status: 'DISABLED'
|
|
115
|
+
expiry: string
|
|
116
|
+
}
|
|
117
|
+
|
|
103
118
|
export type SimplePayEvents = 'SUCCESS' | 'FAIL' | 'TIMEOUT' | 'CANCEL'
|
|
104
119
|
|
|
105
120
|
export interface SimplePayAPIResult {
|
package/src/utils.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import crypto from 'crypto'
|
|
2
|
-
import { CURRENCIES, Currency, ISO8601DateString, SimplePayAPIResult, SimplePayRecurringRequestBody, SimplePayRecurringResponse, SimplePayRequestBody, SimplePayResponse, SimplePayResult, SimplePayTokenRequestBody, SimplePayTokenResponse } from "./types"
|
|
2
|
+
import { CURRENCIES, Currency, ISO8601DateString, SimplePayAPIResult, SimplePayCardCancelRequestBody, SimplePayCardCancelResponse, SimplePayRecurringRequestBody, SimplePayRecurringResponse, SimplePayRequestBody, SimplePayResponse, SimplePayResult, SimplePayTokenRequestBody, SimplePayTokenResponse } from "./types"
|
|
3
3
|
|
|
4
4
|
export const simplepayLogger = (...args: any[]) => {
|
|
5
5
|
if (process.env.SIMPLEPAY_LOGGER !== 'true') {
|
|
@@ -15,18 +15,21 @@ export const getSimplePayConfig = (currency: Currency) => {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
const SIMPLEPAY_API_URL = 'https://secure.simplepay.hu/payment/v2'
|
|
18
|
-
const SIMPLEPAY_SANDBOX_URL = 'https://sandbox.simplepay.hu/payment/v2
|
|
19
|
-
const SDK_VERSION = 'SimplePayV2.1_Rrd_0.
|
|
18
|
+
const SIMPLEPAY_SANDBOX_URL = 'https://sandbox.simplepay.hu/payment/v2'
|
|
19
|
+
const SDK_VERSION = 'SimplePayV2.1_Rrd_0.8.0'
|
|
20
20
|
const MERCHANT_KEY = process.env[`SIMPLEPAY_MERCHANT_KEY_${currency}`]
|
|
21
21
|
const MERCHANT_ID = process.env[`SIMPLEPAY_MERCHANT_ID_${currency}`]
|
|
22
|
-
const API_URL = process.env.SIMPLEPAY_PRODUCTION === 'true' ? SIMPLEPAY_API_URL : SIMPLEPAY_SANDBOX_URL
|
|
23
|
-
const API_URL_RECURRING = process.env.SIMPLEPAY_PRODUCTION === 'true' ? SIMPLEPAY_API_URL : 'https://sandbox.simplepay.hu/payment/v2/dorecurring'
|
|
24
22
|
|
|
23
|
+
const API_URL = process.env.SIMPLEPAY_PRODUCTION === 'true' ? SIMPLEPAY_API_URL : SIMPLEPAY_SANDBOX_URL
|
|
24
|
+
const API_URL_PAYMENT = API_URL + '/start'
|
|
25
|
+
const API_URL_RECURRING = API_URL + '/dorecurring'
|
|
26
|
+
const API_URL_CARD_CANCEL = API_URL + '/cancelcard'
|
|
25
27
|
return {
|
|
26
28
|
MERCHANT_KEY,
|
|
27
29
|
MERCHANT_ID,
|
|
28
|
-
|
|
30
|
+
API_URL_PAYMENT,
|
|
29
31
|
API_URL_RECURRING,
|
|
32
|
+
API_URL_CARD_CANCEL,
|
|
30
33
|
SDK_VERSION
|
|
31
34
|
}
|
|
32
35
|
}
|
|
@@ -69,7 +72,11 @@ export const makeSimplePayTokenRequest = async (apiUrl: string, requestBody: Sim
|
|
|
69
72
|
return makeRequest(apiUrl, requestBody, merchantKey, 'token') as Promise<SimplePayTokenResponse>
|
|
70
73
|
}
|
|
71
74
|
|
|
72
|
-
const
|
|
75
|
+
export const makeSimplePayCardCancelRequest = async (apiUrl: string, requestBody: SimplePayCardCancelRequestBody, merchantKey: string) => {
|
|
76
|
+
return makeRequest(apiUrl, requestBody, merchantKey, 'cardCancel') as Promise<SimplePayCardCancelResponse>
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const makeRequest = async (apiUrl: string, requestBody: SimplePayRequestBody | SimplePayRecurringRequestBody | SimplePayTokenRequestBody | SimplePayCardCancelRequestBody, merchantKey: string, type: 'oneTime' | 'recurring' | 'token' | 'cardCancel') => {
|
|
73
80
|
const bodyString = prepareRequestBody(requestBody)
|
|
74
81
|
const signature = generateSignature(bodyString, merchantKey)
|
|
75
82
|
simplepayLogger({ function: `SimplePay/makeRequest/${type}`, bodyString, signature })
|