simplepay-js-sdk 0.3.5 → 0.4.0

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.md CHANGED
@@ -4,6 +4,8 @@ A lightweight utility for integrating Hungary's SimplePay payments in Node.js ap
4
4
 
5
5
  ![SimplePay Logo](simplepay_logo.jpg)
6
6
 
7
+ Please read the [SimplePay documentation](https://simplepay.hu/fejlesztoknek) for more information.
8
+
7
9
  ## Installation
8
10
 
9
11
  ```bash
@@ -22,8 +24,8 @@ pnpm add simplepay-js-sdk
22
24
  Set the following environment variables in your `.env` file:
23
25
 
24
26
  - `SIMPLEPAY_LOGGER` If it set to `true`, it will log varibles - useful only for debugging.
25
- - `SIMPLEPAY_MERCHANT_KEY_HUF` Your Simplepay secret merchant key.
26
- - `SIMPLEPAY_MERCHANT_ID_HUF` Your Simplepay merchant id.
27
+ - `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.
28
+ - `SIMPLEPAY_MERCHANT_ID_HUF` Your Simplepay merchant id. Set `SIMPLEPAY_MERCHANT_ID_EUR` and `SIMPLEPAY_MERCHANT_ID_USD` for accepting EUR and USD payments.
27
29
  - `SIMPLEPAY_PRODUCTION` If it set to `true`, it will use production environment, otherwise it will use sandbox environment.
28
30
  - `SIMPLEPAY_REDIRECT_URL` The URL of your site, where the customer will be redirected after the payment.
29
31
 
@@ -40,7 +42,7 @@ try {
40
42
  const response = await startPayment({
41
43
  orderRef: 'order-12',
42
44
  total: 1212,
43
- currency: 'HUF', // optional, defaults to HUF
45
+ currency: 'HUF', // optional, HUF | EUR | USD, defaults to HUF
44
46
  customerEmail: 'rrd@webmania.cc',
45
47
  language: 'HU', // optional, defaults to HU
46
48
  method: 'CARD', // optional, CARD | WIRE, defaults to CARD
package/dist/index.d.ts CHANGED
@@ -1,7 +1,14 @@
1
- import { PaymentData, SimplePayResponse } from './types';
1
+ import { PaymentData, SimplePayResponse, Currency } from './types';
2
2
  declare const generateSignature: (body: string, merchantKey: string) => string;
3
3
  declare const checkSignature: (responseText: string, signature: string, merchantKey: string) => boolean;
4
+ declare const getSimplePayConfig: (currency: Currency) => {
5
+ MERCHANT_KEY: string | undefined;
6
+ MERCHANT_ID: string | undefined;
7
+ API_URL: string;
8
+ SDK_VERSION: string;
9
+ };
4
10
  declare const startPayment: (paymentData: PaymentData) => Promise<SimplePayResponse>;
11
+ declare const getCurrencyFromMerchantId: (merchantId: string) => "HUF" | "EUR" | "USD";
5
12
  declare const getPaymentResponse: (r: string, signature: string) => {
6
13
  responseCode: number;
7
14
  transactionId: string;
@@ -9,4 +16,4 @@ declare const getPaymentResponse: (r: string, signature: string) => {
9
16
  merchantId: string;
10
17
  orderId: string;
11
18
  };
12
- export { startPayment, generateSignature, checkSignature, getPaymentResponse };
19
+ export { startPayment, getPaymentResponse, getSimplePayConfig, generateSignature, checkSignature, getCurrencyFromMerchantId };
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import crypto from 'crypto';
2
+ import { CURRENCIES } from './types';
2
3
  // Existing interfaces remain the same
3
4
  const simplepayLogger = (...args) => {
4
5
  if (process.env.SIMPLEPAY_LOGGER !== 'true') {
@@ -14,12 +15,15 @@ const generateSignature = (body, merchantKey) => {
14
15
  const checkSignature = (responseText, signature, merchantKey) => signature === generateSignature(responseText, merchantKey);
15
16
  // escaping slashes for the request body to prevent strange SimplePay API errors (eg Missing Signature)
16
17
  const prepareRequestBody = (body) => JSON.stringify(body).replace(/\//g, '\\/');
17
- const getSimplePayConfig = () => {
18
+ const getSimplePayConfig = (currency) => {
19
+ if (!CURRENCIES.includes(currency)) {
20
+ throw new Error(`Unsupported currency: ${currency}`);
21
+ }
18
22
  const SIMPLEPAY_API_URL = 'https://secure.simplepay.hu/payment/v2';
19
23
  const SIMPLEPAY_SANDBOX_URL = 'https://sandbox.simplepay.hu/payment/v2/start';
20
- const SDK_VERSION = 'SimplePayV2.1_Rrd_0.3.5';
21
- const MERCHANT_KEY = process.env.SIMPLEPAY_MERCHANT_KEY_HUF;
22
- const MERCHANT_ID = process.env.SIMPLEPAY_MERCHANT_ID_HUF;
24
+ const SDK_VERSION = 'SimplePayV2.1_Rrd_0.4.0';
25
+ const MERCHANT_KEY = process.env[`SIMPLEPAY_MERCHANT_KEY_${currency}`];
26
+ const MERCHANT_ID = process.env[`SIMPLEPAY_MERCHANT_ID_${currency}`];
23
27
  const API_URL = process.env.SIMPLEPAY_PRODUCTION === 'true' ? SIMPLEPAY_API_URL : SIMPLEPAY_SANDBOX_URL;
24
28
  return {
25
29
  MERCHANT_KEY,
@@ -29,7 +33,8 @@ const getSimplePayConfig = () => {
29
33
  };
30
34
  };
31
35
  const startPayment = async (paymentData) => {
32
- const { MERCHANT_KEY, MERCHANT_ID, API_URL, SDK_VERSION } = getSimplePayConfig();
36
+ const currency = paymentData.currency || 'HUF';
37
+ const { MERCHANT_KEY, MERCHANT_ID, API_URL, SDK_VERSION } = getSimplePayConfig(currency);
33
38
  simplepayLogger({ MERCHANT_KEY, MERCHANT_ID, API_URL });
34
39
  if (!MERCHANT_KEY || !MERCHANT_ID) {
35
40
  throw new Error('Missing SimplePay configuration');
@@ -38,7 +43,7 @@ const startPayment = async (paymentData) => {
38
43
  salt: crypto.randomBytes(16).toString('hex'),
39
44
  merchant: MERCHANT_ID,
40
45
  orderRef: paymentData.orderRef,
41
- currency: paymentData.currency || 'HUF',
46
+ currency,
42
47
  customerEmail: paymentData.customerEmail,
43
48
  language: paymentData.language || 'HU',
44
49
  sdkVersion: SDK_VERSION,
@@ -87,10 +92,21 @@ const startPayment = async (paymentData) => {
87
92
  throw error;
88
93
  }
89
94
  };
95
+ const getCurrencyFromMerchantId = (merchantId) => {
96
+ const currency = Object.entries(process.env)
97
+ .find(([key, value]) => key.startsWith('SIMPLEPAY_MERCHANT_ID_') && value === merchantId)?.[0]?.replace('SIMPLEPAY_MERCHANT_ID_', '');
98
+ if (!currency) {
99
+ throw new Error(`Merchant id not found in the environment: ${merchantId}`);
100
+ }
101
+ return currency;
102
+ };
90
103
  const getPaymentResponse = (r, signature) => {
91
- const { MERCHANT_KEY } = getSimplePayConfig();
92
- // Note: Replaced atob with Buffer for ESM
104
+ signature = decodeURIComponent(signature);
105
+ signature = Buffer.from(signature, 'base64').toString('utf-8');
93
106
  const rDecoded = Buffer.from(r, 'base64').toString('utf-8');
107
+ const rDecodedJSON = JSON.parse(rDecoded);
108
+ const currency = getCurrencyFromMerchantId(rDecodedJSON.m);
109
+ const { MERCHANT_KEY } = getSimplePayConfig(currency);
94
110
  if (!checkSignature(rDecoded, signature, MERCHANT_KEY || '')) {
95
111
  simplepayLogger({ rDecoded, signature });
96
112
  throw new Error('Invalid response signature');
@@ -105,5 +121,5 @@ const getPaymentResponse = (r, signature) => {
105
121
  };
106
122
  return response;
107
123
  };
108
- export { startPayment, generateSignature, checkSignature, getPaymentResponse };
124
+ export { startPayment, getPaymentResponse, getSimplePayConfig, generateSignature, checkSignature, getCurrencyFromMerchantId };
109
125
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  type PaymentMethod = 'CARD' | 'WIRE';
2
+ declare const CURRENCIES: readonly ["HUF", "EUR", "USD"];
3
+ type Currency = typeof CURRENCIES[number];
2
4
  interface PaymentData {
3
5
  orderRef: string;
4
6
  total: number | string;
5
7
  customerEmail: string;
6
- currency?: string;
8
+ currency?: Currency;
7
9
  language?: string;
8
10
  method?: PaymentMethod;
9
11
  invoice?: {
@@ -30,7 +32,7 @@ interface SimplePayResponse {
30
32
  salt: string;
31
33
  merchant: string;
32
34
  orderRef: string;
33
- currency: string;
35
+ currency: Currency;
34
36
  transactionId: string;
35
37
  timeout: string;
36
38
  total: string;
@@ -44,4 +46,4 @@ interface SimplepayResult {
44
46
  m: string;
45
47
  o: string;
46
48
  }
47
- export { PaymentData, SimplePayRequestBody, SimplePayResponse, SimplepayResult };
49
+ export { PaymentData, SimplePayRequestBody, SimplePayResponse, SimplepayResult, CURRENCIES, Currency, PaymentMethod };
package/dist/types.js CHANGED
@@ -1 +1,3 @@
1
+ const CURRENCIES = ['HUF', 'EUR', 'USD'];
2
+ export { CURRENCIES };
1
3
  //# sourceMappingURL=types.js.map
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAU,CAAA;AAoDjD,OAAO,EAAyE,UAAU,EAA2B,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "simplepay-js-sdk",
3
- "version": "0.3.5",
3
+ "version": "0.4.0",
4
4
  "description": "A Node.js utility for SimplePay payment integration",
5
5
  "repository": {
6
6
  "type": "git",
@@ -22,7 +22,8 @@
22
22
  "prepare": "npm run build",
23
23
  "test": "vitest --run",
24
24
  "test:watch": "vitest",
25
- "release": "bash ./release.sh"
25
+ "release": "bash ./release.sh",
26
+ "generate-signature": "node tools/generate-signature.js"
26
27
  },
27
28
  "keywords": [
28
29
  "simplepay",
package/src/index.spec.ts CHANGED
@@ -1,10 +1,14 @@
1
- import { describe, it, expect, vi } from 'vitest'
2
- import { checkSignature, generateSignature, getPaymentResponse, startPayment } from './index'
3
- import { PaymentData } from './types'
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest'
2
+ import { checkSignature, generateSignature, getPaymentResponse, getSimplePayConfig, startPayment, getCurrencyFromMerchantId } from './index'
3
+ import { Currency } from './types'
4
4
 
5
5
  const setEnv = () => {
6
- process.env.SIMPLEPAY_MERCHANT_KEY_HUF = 'testKey'
7
6
  process.env.SIMPLEPAY_MERCHANT_ID_HUF = 'testId'
7
+ process.env.SIMPLEPAY_MERCHANT_KEY_HUF = 'testKey'
8
+ // process.env.SIMPLEPAY_MERCHANT_ID_EUR = 'P085402'
9
+ // process.env.SIMPLEPAY_MERCHANT_KEY_EUR = '4?K4&!ZG3|v~6_)p0634'
10
+ process.env.SIMPLEPAY_MERCHANT_ID_EUR = 'merchantEuroId'
11
+ process.env.SIMPLEPAY_MERCHANT_KEY_EUR = 'secretEuroKey'
8
12
  }
9
13
 
10
14
  const paymentData = {
@@ -12,140 +16,165 @@ const paymentData = {
12
16
  customerEmail: 'test@example.com',
13
17
  total: 1212
14
18
  }
15
-
16
- describe('generateSignature', () => {
17
- it('should generate correct signature for sample payload from documentation', () => {
18
- const merchantKey = 'FxDa5w314kLlNseq2sKuVwaqZshZT5d6'
19
- const body = {
20
- salt: 'c1ca1d0e9fc2323b3dda7cf145e36f5e',
21
- merchant: 'PUBLICTESTHUF',
22
- orderRef: '101010516348232058105',
23
- currency: 'HUF',
24
- customerEmail: 'sdk_test@otpmobil.com',
25
- language: 'HU',
26
- sdkVersion: 'SimplePayV2.1_Payment_PHP_SDK_2.0.7_190701:dd236896400d7463677a82a47f53e36e',
27
- methods: ['CARD'],
28
- total: '25',
29
- timeout: '2021-10-30T12:30:11+00:00',
30
- url: 'https://sdk.simplepay.hu/back.php',
31
- }
32
-
33
- let bodyString = JSON.stringify(body)
34
- // after stringify we should insert backslashes for the url
35
- bodyString = bodyString.replace(/\//g, '\\/')
36
-
37
- const result = generateSignature(bodyString, merchantKey)
38
-
39
- const expectedSignature = 'gcDJ8J7TyT1rC/Ygj/8CihXaLwniMWRav09QSEMQUnv5TbYaEDvQAuBE1mW3plvZ'
40
- expect(result).toBe(expectedSignature)
19
+ describe('SimplePay SDK Tests', () => {
20
+ beforeEach(() => {
21
+ // Clear all environment variables before each test
22
+ delete process.env.SIMPLEPAY_MERCHANT_KEY_HUF
23
+ delete process.env.SIMPLEPAY_MERCHANT_ID_HUF
24
+ })
25
+ describe('generateSignature', () => {
26
+ it('should generate correct signature for sample payload from documentation', () => {
27
+ const merchantKey = 'FxDa5w314kLlNseq2sKuVwaqZshZT5d6'
28
+ const body = {
29
+ salt: 'c1ca1d0e9fc2323b3dda7cf145e36f5e',
30
+ merchant: 'PUBLICTESTHUF',
31
+ orderRef: '101010516348232058105',
32
+ currency: 'HUF',
33
+ customerEmail: 'sdk_test@otpmobil.com',
34
+ language: 'HU',
35
+ sdkVersion: 'SimplePayV2.1_Payment_PHP_SDK_2.0.7_190701:dd236896400d7463677a82a47f53e36e',
36
+ methods: ['CARD'],
37
+ total: '25',
38
+ timeout: '2021-10-30T12:30:11+00:00',
39
+ url: 'https://sdk.simplepay.hu/back.php',
40
+ }
41
+
42
+ let bodyString = JSON.stringify(body)
43
+ // after stringify we should insert backslashes for the url
44
+ bodyString = bodyString.replace(/\//g, '\\/')
45
+
46
+ const result = generateSignature(bodyString, merchantKey)
47
+
48
+ const expectedSignature = 'gcDJ8J7TyT1rC/Ygj/8CihXaLwniMWRav09QSEMQUnv5TbYaEDvQAuBE1mW3plvZ'
49
+ expect(result).toBe(expectedSignature)
50
+ })
41
51
  })
42
- })
43
52
 
53
+ describe('checkSignature', () => {
54
+ it('should generate correct signature for the response', () => {
55
+ const merchantKey = 'P085602'
56
+ const response = {
57
+ transactionId: '504226393',
58
+ orderRef: 'ORDER124',
59
+ merchant: merchantKey,
60
+ timeout: '2024-11-29T13:29:17+01:00',
61
+ total: '1000',
62
+ paymentUrl: 'https://sb-checkout.simplepay.hu/trx/cJZs3UUc48FlGu7Mfa1M0tcTWO53oA5RxS0OUMPqA17Fe3HGBr',
63
+ currency: 'HUF',
64
+ salt: 'R0ZBm2gdCXuTmxpOkqB4s0aAhZxZwSWG'
65
+ }
66
+
67
+ const expectedSignature = 'W98O/EdHobsWJTw2U1xUuUWXtCaJnTnzq5Na8ddCKE4gm2IW7vro33tGAW55YPf6'
68
+ const result = checkSignature(JSON.stringify(response).replace(/\//g, '\\/'), expectedSignature, merchantKey)
69
+ expect(result).toBeTruthy()
70
+ })
44
71
 
45
- describe('checkSignature', () => {
46
- it('should generate correct signature for the response', () => {
47
- const merchantKey = 'P085602'
48
- const response = {
49
- transactionId: '504226393',
50
- orderRef: 'ORDER124',
51
- merchant: merchantKey,
52
- timeout: '2024-11-29T13:29:17+01:00',
53
- total: '1000',
54
- paymentUrl: 'https://sb-checkout.simplepay.hu/trx/cJZs3UUc48FlGu7Mfa1M0tcTWO53oA5RxS0OUMPqA17Fe3HGBr',
55
- currency: 'HUF',
56
- salt: 'R0ZBm2gdCXuTmxpOkqB4s0aAhZxZwSWG'
57
- }
58
-
59
- const expectedSignature = 'W98O/EdHobsWJTw2U1xUuUWXtCaJnTnzq5Na8ddCKE4gm2IW7vro33tGAW55YPf6'
60
- const result = checkSignature(JSON.stringify(response).replace(/\//g, '\\/'), expectedSignature, merchantKey)
61
- expect(result).toBeTruthy()
72
+ it('should return false for invalid signature', () => {
73
+ const merchantKey = 'testKey'
74
+ const response = { test: 'data' }
75
+ const invalidSignature = 'invalid-signature'
76
+
77
+ const result = checkSignature(
78
+ JSON.stringify(response),
79
+ invalidSignature,
80
+ merchantKey
81
+ )
82
+ expect(result).toBeFalsy()
83
+ })
62
84
  })
63
85
 
64
- it('should return false for invalid signature', () => {
65
- const merchantKey = 'testKey'
66
- const response = { test: 'data' }
67
- const invalidSignature = 'invalid-signature'
68
-
69
- const result = checkSignature(
70
- JSON.stringify(response),
71
- invalidSignature,
72
- merchantKey
73
- )
74
- expect(result).toBeFalsy()
86
+ describe('getSimplePayConfig', () => {
87
+ it('should return correct config for HUF currency', () => {
88
+ setEnv()
89
+ const config = getSimplePayConfig('HUF')
90
+ expect(config.MERCHANT_ID).toBe('testId')
91
+ expect(config.MERCHANT_KEY).toBe('testKey')
92
+ })
93
+
94
+ it('should throw error for unsupported currency', () => {
95
+ expect(() => getSimplePayConfig('GBP' as Currency)).toThrow('Unsupported currency: GBP')
96
+ })
75
97
  })
76
- })
77
98
 
78
- describe('getPaymentResponse', () => {
79
- it('should correctly decode and parse valid response', () => {
80
- // Create a base64 encoded response similar to what SimplePay returns
81
- const mockResponse = {
82
- r: 'SUCCESS',
83
- t: '123456789',
84
- e: 'PAYMENT',
85
- m: 'MERCHANT123',
86
- o: 'ORDER123'
87
- }
88
- const encodedResponse = Buffer.from(JSON.stringify(mockResponse)).toString('base64')
89
- const validSignature = generateSignature(JSON.stringify(mockResponse), process.env.SIMPLEPAY_MERCHANT_KEY_HUF || '')
90
-
91
- const result = getPaymentResponse(encodedResponse, validSignature)
92
-
93
- expect(result).toEqual({
94
- responseCode: 'SUCCESS',
95
- transactionId: '123456789',
96
- event: 'PAYMENT',
97
- merchantId: 'MERCHANT123',
98
- orderId: 'ORDER123'
99
+ const mockResponse = {
100
+ r: 'SUCCESS',
101
+ t: '123456789',
102
+ e: 'PAYMENT',
103
+ m: 'testId',
104
+ o: 'ORDER123'
105
+ }
106
+ const encodedResponse = Buffer.from(JSON.stringify(mockResponse)).toString('base64')
107
+
108
+ describe('getCurrencyFromMerchantId', () => {
109
+ it('should return correct currency for merchantId', () => {
110
+ setEnv()
111
+ const currency = getCurrencyFromMerchantId('testId')
112
+ expect(currency).toBe('HUF')
99
113
  })
100
114
  })
101
115
 
102
- it('should throw error for invalid signature', () => {
103
- const mockResponse = { test: 'data' }
104
- const encodedResponse = Buffer.from(JSON.stringify(mockResponse)).toString('base64')
116
+ describe('getPaymentResponse', () => {
117
+ it('should correctly decode and parse valid response', () => {
118
+ setEnv()
119
+ const r = 'eyJyIjowLCJ0Ijo1MDQyMzM4ODEsImUiOiJTVUNDRVNTIiwibSI6Im1lcmNoYW50RXVyb0lkIiwibyI6ImMtMS1ldXIifQ=='
120
+ // { r: 0, t: 504233881, e: 'SUCCESS', m: 'merchantEuroId', o: 'c-1-eur' }
121
+ const s = 'WWx4cnBEYThqRi94VkIvck5zRUpvRnhPb0hRK0NpemlCbVdTTUloWVdIU0NKbXZMb2M2a3pBaVpQbVlEVTh6Ng=='
122
+ const result = getPaymentResponse(r, s)
123
+ expect(result).toEqual({
124
+ responseCode: 0,
125
+ transactionId: 504233881,
126
+ event: 'SUCCESS',
127
+ merchantId: 'merchantEuroId',
128
+ orderId: 'c-1-eur'
129
+ })
130
+ })
105
131
 
106
- expect(() =>
107
- getPaymentResponse(encodedResponse, 'invalid-signature')
108
- ).toThrow('Invalid response signature')
132
+ it('should throw error for invalid signature', () => {
133
+ setEnv()
134
+ expect(() =>
135
+ getPaymentResponse(encodedResponse, 'invalid-signature')
136
+ ).toThrow('Invalid response signature')
137
+ })
109
138
  })
110
- })
111
139
 
112
- describe('startPayment', () => {
113
- it('should throw error when merchant configuration is missing', async () => {
114
- await expect(startPayment(paymentData)).rejects.toThrow('Missing SimplePay configuration')
115
- })
140
+ describe('startPayment', () => {
141
+ it('should throw error when merchant configuration is missing', async () => {
142
+ await expect(startPayment(paymentData)).rejects.toThrow('Missing SimplePay configuration')
143
+ })
116
144
 
117
- it('should handle API errors correctly', async () => {
118
- setEnv()
119
-
120
- global.fetch = vi.fn().mockResolvedValue({
121
- ok: true,
122
- headers: {
123
- get: vi.fn().mockReturnValue('mockSignature')
124
- },
125
- text: vi.fn().mockResolvedValue(JSON.stringify({
126
- transactionId: '123456',
127
- total: '1212',
128
- merchant: 'testId'
129
- }))
130
- }) as unknown as typeof fetch
131
- await expect(startPayment(paymentData)).rejects.toThrow('Invalid response signature')
132
- })
145
+ it('should handle API errors correctly', async () => {
146
+ setEnv()
147
+
148
+ global.fetch = vi.fn().mockResolvedValue({
149
+ ok: true,
150
+ headers: {
151
+ get: vi.fn().mockReturnValue('mockSignature')
152
+ },
153
+ text: vi.fn().mockResolvedValue(JSON.stringify({
154
+ transactionId: '123456',
155
+ total: '1212',
156
+ merchant: 'testId'
157
+ }))
158
+ }) as unknown as typeof fetch
159
+ await expect(startPayment(paymentData)).rejects.toThrow('Invalid response signature')
160
+ })
133
161
 
134
- it('should successfully start CARD, HUF, HU payment when API returns valid response', async () => {
135
- setEnv()
136
- global.fetch = vi.fn().mockResolvedValue({
137
- ok: true,
138
- headers: {
139
- get: vi.fn().mockReturnValue('bxSwUc0qn0oABSRcq9uawF6zncFBhRk/AbO4HznYR9Pt5SjocyxAD+9Q4bE44h0J')
140
- },
141
- text: vi.fn().mockResolvedValue(JSON.stringify({
142
- transactionId: '123456',
143
- total: '1212',
144
- merchant: 'testId'
145
- }))
146
- }) as unknown as typeof fetch
147
-
148
- await expect(startPayment(paymentData)).resolves.toBeDefined()
162
+ it('should successfully start CARD, HUF, HU payment when API returns valid response', async () => {
163
+ setEnv()
164
+ global.fetch = vi.fn().mockResolvedValue({
165
+ ok: true,
166
+ headers: {
167
+ get: vi.fn().mockReturnValue('bxSwUc0qn0oABSRcq9uawF6zncFBhRk/AbO4HznYR9Pt5SjocyxAD+9Q4bE44h0J')
168
+ },
169
+ text: vi.fn().mockResolvedValue(JSON.stringify({
170
+ transactionId: '123456',
171
+ total: '1212',
172
+ merchant: 'testId'
173
+ }))
174
+ }) as unknown as typeof fetch
175
+
176
+ await expect(startPayment(paymentData)).resolves.toBeDefined()
177
+ })
149
178
  })
150
- })
151
179
 
180
+ })
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import crypto from 'crypto'
2
- import { PaymentData, SimplePayRequestBody, SimplePayResponse, SimplepayResult } from './types'
2
+ import { PaymentData, SimplePayRequestBody, SimplePayResponse, SimplepayResult, Currency, CURRENCIES } from './types'
3
3
 
4
4
  // Existing interfaces remain the same
5
5
 
@@ -24,12 +24,16 @@ const prepareRequestBody = (body: SimplePayRequestBody) =>
24
24
  JSON.stringify(body).replace(/\//g, '\\/')
25
25
 
26
26
 
27
- const getSimplePayConfig = () => {
27
+ const getSimplePayConfig = (currency: Currency) => {
28
+ if (!CURRENCIES.includes(currency)) {
29
+ throw new Error(`Unsupported currency: ${currency}`)
30
+ }
31
+
28
32
  const SIMPLEPAY_API_URL = 'https://secure.simplepay.hu/payment/v2'
29
33
  const SIMPLEPAY_SANDBOX_URL = 'https://sandbox.simplepay.hu/payment/v2/start'
30
- const SDK_VERSION = 'SimplePayV2.1_Rrd_0.3.5'
31
- const MERCHANT_KEY = process.env.SIMPLEPAY_MERCHANT_KEY_HUF
32
- const MERCHANT_ID = process.env.SIMPLEPAY_MERCHANT_ID_HUF
34
+ const SDK_VERSION = 'SimplePayV2.1_Rrd_0.4.0'
35
+ const MERCHANT_KEY = process.env[`SIMPLEPAY_MERCHANT_KEY_${currency}`]
36
+ const MERCHANT_ID = process.env[`SIMPLEPAY_MERCHANT_ID_${currency}`]
33
37
  const API_URL = process.env.SIMPLEPAY_PRODUCTION === 'true' ? SIMPLEPAY_API_URL : SIMPLEPAY_SANDBOX_URL
34
38
 
35
39
  return {
@@ -41,7 +45,8 @@ const getSimplePayConfig = () => {
41
45
  }
42
46
 
43
47
  const startPayment = async (paymentData: PaymentData) => {
44
- const { MERCHANT_KEY, MERCHANT_ID, API_URL, SDK_VERSION } = getSimplePayConfig()
48
+ const currency = paymentData.currency || 'HUF'
49
+ const { MERCHANT_KEY, MERCHANT_ID, API_URL, SDK_VERSION } = getSimplePayConfig(currency)
45
50
  simplepayLogger({ MERCHANT_KEY, MERCHANT_ID, API_URL })
46
51
 
47
52
  if (!MERCHANT_KEY || !MERCHANT_ID) {
@@ -52,7 +57,7 @@ const startPayment = async (paymentData: PaymentData) => {
52
57
  salt: crypto.randomBytes(16).toString('hex'),
53
58
  merchant: MERCHANT_ID,
54
59
  orderRef: paymentData.orderRef,
55
- currency: paymentData.currency || 'HUF',
60
+ currency,
56
61
  customerEmail: paymentData.customerEmail,
57
62
  language: paymentData.language || 'HU',
58
63
  sdkVersion: SDK_VERSION,
@@ -111,10 +116,24 @@ const startPayment = async (paymentData: PaymentData) => {
111
116
  }
112
117
  }
113
118
 
119
+ const getCurrencyFromMerchantId = (merchantId: string) => {
120
+ const currency = Object.entries(process.env)
121
+ .find(([key, value]) =>
122
+ key.startsWith('SIMPLEPAY_MERCHANT_ID_') && value === merchantId
123
+ )?.[0]?.replace('SIMPLEPAY_MERCHANT_ID_', '') as Currency
124
+ if (!currency) {
125
+ throw new Error(`Merchant id not found in the environment: ${merchantId}`)
126
+ }
127
+ return currency
128
+ }
129
+
114
130
  const getPaymentResponse = (r: string, signature: string) => {
115
- const { MERCHANT_KEY } = getSimplePayConfig()
116
- // Note: Replaced atob with Buffer for ESM
131
+ signature = decodeURIComponent(signature)
132
+ signature = Buffer.from(signature, 'base64').toString('utf-8')
117
133
  const rDecoded = Buffer.from(r, 'base64').toString('utf-8')
134
+ const rDecodedJSON = JSON.parse(rDecoded)
135
+ const currency = getCurrencyFromMerchantId(rDecodedJSON.m)
136
+ const { MERCHANT_KEY } = getSimplePayConfig(currency as Currency)
118
137
 
119
138
  if (!checkSignature(rDecoded, signature, MERCHANT_KEY || '')) {
120
139
  simplepayLogger({ rDecoded, signature })
@@ -133,4 +152,11 @@ const getPaymentResponse = (r: string, signature: string) => {
133
152
  return response
134
153
  }
135
154
 
136
- export { startPayment, generateSignature, checkSignature, getPaymentResponse }
155
+ export {
156
+ startPayment,
157
+ getPaymentResponse,
158
+ getSimplePayConfig,
159
+ generateSignature,
160
+ checkSignature,
161
+ getCurrencyFromMerchantId
162
+ }
package/src/types.ts CHANGED
@@ -1,10 +1,13 @@
1
1
  type PaymentMethod = 'CARD' | 'WIRE'
2
2
 
3
+ const CURRENCIES = ['HUF', 'EUR', 'USD'] as const
4
+ type Currency = typeof CURRENCIES[number]
5
+
3
6
  interface PaymentData {
4
7
  orderRef: string
5
8
  total: number | string
6
9
  customerEmail: string
7
- currency?: string
10
+ currency?: Currency
8
11
  language?: string
9
12
  method?: PaymentMethod
10
13
  invoice?: {
@@ -33,7 +36,7 @@ interface SimplePayResponse {
33
36
  salt: string
34
37
  merchant: string
35
38
  orderRef: string
36
- currency: string
39
+ currency: Currency
37
40
  transactionId: string
38
41
  timeout: string
39
42
  total: string
@@ -49,4 +52,4 @@ interface SimplepayResult {
49
52
  o: string // order id
50
53
  }
51
54
 
52
- export { PaymentData, SimplePayRequestBody, SimplePayResponse, SimplepayResult }
55
+ export { PaymentData, SimplePayRequestBody, SimplePayResponse, SimplepayResult, CURRENCIES, Currency, PaymentMethod }