simplepay-js-sdk 0.6.1 → 0.8.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/dist/index.js CHANGED
@@ -1,89 +1,161 @@
1
- import P from "crypto";
2
- const h = ["HUF", "EUR", "USD"], a = (...e) => {
3
- process.env.SIMPLEPAY_LOGGER === "true" && console.log(...e);
4
- }, R = (e, t) => {
5
- const r = P.createHmac("sha384", t.trim());
6
- return r.update(e, "utf8"), r.digest("base64");
7
- }, _ = (e, t, r) => t === R(e, r), I = (e) => JSON.stringify(e).replace(/\//g, "\\/"), g = (e) => {
8
- if (!h.includes(e))
1
+ import S from "crypto";
2
+ const g = ["HUF", "EUR", "USD"], i = (...e) => {
3
+ process.env.SIMPLEPAY_LOGGER === "true" && console.log("👉 ", ...e);
4
+ }, E = (e) => {
5
+ if (!g.includes(e))
9
6
  throw new Error(`Unsupported currency: ${e}`);
10
- const t = "https://secure.simplepay.hu/payment/v2", r = "https://sandbox.simplepay.hu/payment/v2/start", o = "SimplePayV2.1_Rrd_0.6.0", s = process.env[`SIMPLEPAY_MERCHANT_KEY_${e}`], c = process.env[`SIMPLEPAY_MERCHANT_ID_${e}`], n = process.env.SIMPLEPAY_PRODUCTION === "true" ? t : r;
7
+ const n = "https://secure.simplepay.hu/payment/v2", r = "https://sandbox.simplepay.hu/payment/v2", t = "SimplePayV2.1_Rrd_0.6.1", 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";
11
8
  return {
12
9
  MERCHANT_KEY: s,
13
10
  MERCHANT_ID: c,
14
- API_URL: n,
15
- SDK_VERSION: o
11
+ API_URL_PAYMENT: u,
12
+ API_URL_RECURRING: R,
13
+ API_URL_CARD_CANCEL: a,
14
+ SDK_VERSION: t
16
15
  };
17
- }, A = async (e) => {
18
- const t = e.currency || "HUF", { MERCHANT_KEY: r, MERCHANT_ID: o, API_URL: s, SDK_VERSION: c } = g(t);
19
- if (a({ MERCHANT_KEY: r, MERCHANT_ID: o, API_URL: s }), !r || !o)
20
- throw new Error("Missing SimplePay configuration");
21
- const n = {
22
- salt: P.randomBytes(16).toString("hex"),
23
- merchant: o,
24
- orderRef: e.orderRef,
25
- currency: t,
26
- customerEmail: e.customerEmail,
27
- language: e.language || "HU",
28
- sdkVersion: c,
29
- methods: [e.method || "CARD"],
30
- total: String(e.total),
31
- timeout: new Date(Date.now() + 30 * 60 * 1e3).toISOString().replace(/\.\d{3}Z$/, "+00:00"),
32
- url: process.env.SIMPLEPAY_REDIRECT_URL || "http://url.to.redirect",
33
- invoice: e.invoice
34
- }, p = I(n), u = R(p, r);
35
- a({ bodyString: p, signature: u });
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(
22
+ ([s, c]) => s.startsWith("SIMPLEPAY_MERCHANT_ID_") && c === e
23
+ )) == null ? void 0 : r[0]) == null ? void 0 : t.replace("SIMPLEPAY_MERCHANT_ID_", "");
24
+ if (!n)
25
+ throw new Error(`Merchant id not found in the environment: ${e}`);
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 });
36
30
  try {
37
- const i = await fetch(s, {
31
+ const o = await fetch(e, {
38
32
  method: "POST",
39
33
  headers: {
40
34
  "Content-Type": "application/json",
41
- Signature: u
35
+ Signature: c
42
36
  },
43
- body: p
37
+ body: s
44
38
  });
45
- if (a({ response: i }), !i.ok)
46
- throw new Error(`SimplePay API error: ${i.status}`);
47
- const S = i.headers.get("Signature");
48
- if (a({ responseSignature: S }), !S)
39
+ if (i({ function: `SimplePay/makeRequest/${t}`, response: o }), !o.ok)
40
+ throw new Error(`SimplePay API error: ${o.status}`);
41
+ const u = o.headers.get("Signature");
42
+ if (i({ function: `SimplePay/makeRequest/${t}`, responseSignature: u }), !u)
49
43
  throw new Error("Missing response signature");
50
- const d = await i.text(), E = JSON.parse(d);
51
- if (a({ responseText: d, responseJSON: E }), E.errorCodes)
52
- throw new Error(`SimplePay API error: ${E.errorCodes}`);
53
- if (!_(d, S, r))
44
+ const R = await o.text(), a = JSON.parse(R);
45
+ if (i({ function: `SimplePay/makeRequest/${t}`, responseText: R, responseJSON: a }), a.errorCodes)
46
+ throw new Error(`SimplePay API error: ${a.errorCodes}`);
47
+ if (!_(R, u, r))
54
48
  throw new Error("Invalid response signature");
55
- return E;
56
- } catch (i) {
57
- throw i;
49
+ return a;
50
+ } catch (o) {
51
+ throw o;
58
52
  }
59
- }, m = (e) => {
60
- var r, o;
61
- const t = (o = (r = Object.entries(process.env).find(
62
- ([s, c]) => s.startsWith("SIMPLEPAY_MERCHANT_ID_") && c === e
63
- )) == null ? void 0 : r[0]) == null ? void 0 : o.replace("SIMPLEPAY_MERCHANT_ID_", "");
64
- if (!t)
65
- throw new Error(`Merchant id not found in the environment: ${e}`);
66
- return t;
67
- }, f = (e, t) => {
68
- t = decodeURIComponent(t);
69
- const r = Buffer.from(e, "base64").toString("utf-8"), o = JSON.parse(r), s = m(o.m), { MERCHANT_KEY: c } = g(s);
70
- if (!_(r, t, c || ""))
71
- throw a({ rDecoded: r, signature: t }), new Error("Invalid response signature");
72
- const n = JSON.parse(r);
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);
73
59
  return {
74
- responseCode: n.r,
75
- transactionId: n.t,
76
- event: n.e,
77
- merchantId: n.m,
78
- orderRef: n.o
60
+ responseCode: o.r,
61
+ transactionId: o.t,
62
+ event: o.e,
63
+ merchantId: o.m,
64
+ orderRef: o.o,
65
+ tokens: o.tokens
66
+ };
67
+ }, w = async (e) => {
68
+ i({ function: "SimplePay/startPayment", paymentData: e });
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}`);
72
+ const o = {
73
+ salt: S.randomBytes(16).toString("hex"),
74
+ merchant: t,
75
+ orderRef: e.orderRef,
76
+ currency: n,
77
+ customerEmail: e.customerEmail,
78
+ language: e.language || "HU",
79
+ sdkVersion: c,
80
+ methods: [e.method || "CARD"],
81
+ total: String(e.total),
82
+ timeout: m(new Date(Date.now() + 30 * 60 * 1e3)),
83
+ url: process.env.SIMPLEPAY_REDIRECT_URL || "http://url.to.redirect",
84
+ invoice: e.invoice
85
+ };
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) => {
88
+ i({ function: "SimplePay/startRecurringPayment", paymentData: e });
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}`);
92
+ const o = {
93
+ salt: S.randomBytes(16).toString("hex"),
94
+ merchant: t,
95
+ orderRef: e.orderRef,
96
+ currency: n,
97
+ customer: e.customer,
98
+ customerEmail: e.customerEmail,
99
+ language: e.language || "HU",
100
+ sdkVersion: c,
101
+ methods: ["CARD"],
102
+ recurring: {
103
+ times: e.recurring.times || N,
104
+ until: e.recurring.until || m(C),
105
+ maxAmount: e.recurring.maxAmount || M
106
+ },
107
+ threeDSReqAuthMethod: "02",
108
+ total: String(e.total),
109
+ timeout: m(new Date(Date.now() + 30 * 60 * 1e3)),
110
+ url: process.env.SIMPLEPAY_REDIRECT_URL || "http://url.to.redirect",
111
+ invoice: e.invoice
112
+ };
113
+ return f(s, o, r);
114
+ }, H = async (e) => {
115
+ i({ function: "SimplePay/startTokenPayment", paymentData: e });
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}`);
119
+ const o = {
120
+ salt: S.randomBytes(16).toString("hex"),
121
+ merchant: t,
122
+ orderRef: e.orderRef,
123
+ currency: n,
124
+ customer: e.customer,
125
+ customerEmail: e.customerEmail,
126
+ language: e.language || "HU",
127
+ sdkVersion: c,
128
+ methods: ["CARD"],
129
+ token: e.token,
130
+ type: "MIT",
131
+ threeDSReqAuthMethod: "02",
132
+ total: String(e.total),
133
+ timeout: m(new Date(Date.now() + 30 * 60 * 1e3)),
134
+ url: process.env.SIMPLEPAY_REDIRECT_URL || "http://recurring.url.to.redirect",
135
+ invoice: e.invoice
136
+ };
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
79
148
  };
149
+ return h(n, c, r);
80
150
  };
81
151
  export {
152
+ k as cardCancel,
82
153
  _ as checkSignature,
83
- R as generateSignature,
84
- m as getCurrencyFromMerchantId,
85
- f as getPaymentResponse,
86
- g as getSimplePayConfig,
87
- A as startPayment
154
+ l as generateSignature,
155
+ U as getPaymentResponse,
156
+ w as startPayment,
157
+ L as startRecurringPayment,
158
+ H as startTokenPayment,
159
+ m as toISO8601DateString
88
160
  };
89
161
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/types.ts","../src/index.ts"],"sourcesContent":["type PaymentMethod = 'CARD' | 'WIRE'\n\nconst CURRENCIES = ['HUF', 'EUR', 'USD'] as const\ntype Currency = typeof CURRENCIES[number]\n\nconst 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\ntype Language = typeof LANGUAGES[number]\n\ninterface 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\ninterface 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\ninterface SimplePayResponse {\n salt: string\n merchant: string\n orderRef: string\n currency: Currency\n transactionId: string\n timeout: string\n total: string\n paymentUrl: string\n errorCodes?: string[]\n}\n\ninterface SimplepayResult {\n r: number // response code\n t: string // transaction id\n e: 'success' | 'fail' | 'timeout' | 'cancel' // event\n m: string // merchant id\n o: string // order id\n}\n\nexport { PaymentData, SimplePayRequestBody, SimplePayResponse, SimplepayResult, CURRENCIES, Currency, PaymentMethod, LANGUAGES, Language }","import crypto from 'crypto'\nimport { PaymentData, SimplePayRequestBody, SimplePayResponse, SimplepayResult, Currency, CURRENCIES } from './types'\n\n// Existing interfaces remain the same\n\nconst simplepayLogger = (...args: any[]) => {\n if (process.env.SIMPLEPAY_LOGGER !== 'true') {\n return\n }\n console.log(...args)\n}\n\nconst 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\nconst checkSignature = (responseText: string, signature: string, merchantKey: string) =>\n signature === generateSignature(responseText, merchantKey)\n\n// escaping slashes for the request body to prevent strange SimplePay API errors (eg Missing Signature)\nconst prepareRequestBody = (body: SimplePayRequestBody) =>\n JSON.stringify(body).replace(/\\//g, '\\\\/')\n\n\nconst 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.0'\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\n return {\n MERCHANT_KEY,\n MERCHANT_ID,\n API_URL,\n SDK_VERSION\n }\n}\n\nconst startPayment = async (paymentData: PaymentData) => {\n const currency = paymentData.currency || 'HUF'\n const { MERCHANT_KEY, MERCHANT_ID, API_URL, SDK_VERSION } = getSimplePayConfig(currency)\n simplepayLogger({ MERCHANT_KEY, MERCHANT_ID, API_URL })\n\n if (!MERCHANT_KEY || !MERCHANT_ID) {\n throw new Error('Missing SimplePay configuration')\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: new Date(Date.now() + 30 * 60 * 1000)\n .toISOString()\n .replace(/\\.\\d{3}Z$/, '+00:00'),\n url: process.env.SIMPLEPAY_REDIRECT_URL || 'http://url.to.redirect',\n invoice: paymentData.invoice,\n }\n\n const bodyString = prepareRequestBody(requestBody)\n const signature = generateSignature(bodyString, MERCHANT_KEY)\n simplepayLogger({ bodyString, signature })\n\n try {\n const response = await fetch(API_URL, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Signature': signature,\n },\n body: bodyString,\n })\n\n simplepayLogger({ 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({ 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 SimplePayResponse\n simplepayLogger({ responseText, responseJSON })\n\n if (responseJSON.errorCodes) {\n throw new Error(`SimplePay API error: ${responseJSON.errorCodes}`)\n }\n\n if (!checkSignature(responseText, responseSignature, MERCHANT_KEY)) {\n throw new Error('Invalid response signature')\n }\n\n return responseJSON\n\n } catch (error) {\n throw error\n }\n}\n\nconst 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\nconst getPaymentResponse = (r: string, signature: string) => {\n signature = decodeURIComponent(signature)\n const rDecoded = Buffer.from(r, 'base64').toString('utf-8')\n const rDecodedJSON = JSON.parse(rDecoded)\n const currency = getCurrencyFromMerchantId(rDecodedJSON.m)\n const { MERCHANT_KEY } = getSimplePayConfig(currency as Currency)\n\n if (!checkSignature(rDecoded, signature, MERCHANT_KEY || '')) {\n simplepayLogger({ rDecoded, signature })\n throw new Error('Invalid response signature')\n }\n\n const responseJson: SimplepayResult = JSON.parse(rDecoded)\n const response = {\n responseCode: responseJson.r,\n transactionId: responseJson.t,\n event: responseJson.e,\n merchantId: responseJson.m,\n orderRef: responseJson.o,\n }\n\n return response\n}\n\nexport {\n startPayment,\n getPaymentResponse,\n getSimplePayConfig,\n generateSignature,\n checkSignature,\n getCurrencyFromMerchantId\n}"],"names":["CURRENCIES","simplepayLogger","args","generateSignature","body","merchantKey","hmac","crypto","checkSignature","responseText","signature","prepareRequestBody","getSimplePayConfig","currency","SIMPLEPAY_API_URL","SIMPLEPAY_SANDBOX_URL","SDK_VERSION","MERCHANT_KEY","MERCHANT_ID","API_URL","startPayment","paymentData","requestBody","bodyString","response","responseSignature","responseJSON","error","getCurrencyFromMerchantId","merchantId","_b","_a","key","value","getPaymentResponse","r","rDecoded","rDecodedJSON","responseJson"],"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.6.1'\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":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "simplepay-js-sdk",
3
- "version": "0.6.1",
3
+ "version": "0.8.0",
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.4.2",
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,160 +1,11 @@
1
- import crypto from 'crypto'
2
- import { PaymentData, SimplePayRequestBody, SimplePayResponse, SimplepayResult, Currency, CURRENCIES } from './types'
3
-
4
- // Existing interfaces remain the same
5
-
6
- const simplepayLogger = (...args: any[]) => {
7
- if (process.env.SIMPLEPAY_LOGGER !== 'true') {
8
- return
9
- }
10
- console.log(...args)
11
- }
12
-
13
- const generateSignature = (body: string, merchantKey: string) => {
14
- const hmac = crypto.createHmac('sha384', merchantKey.trim())
15
- hmac.update(body, 'utf8')
16
- return hmac.digest('base64')
17
- }
18
-
19
- const checkSignature = (responseText: string, signature: string, merchantKey: string) =>
20
- signature === generateSignature(responseText, merchantKey)
21
-
22
- // escaping slashes for the request body to prevent strange SimplePay API errors (eg Missing Signature)
23
- const prepareRequestBody = (body: SimplePayRequestBody) =>
24
- JSON.stringify(body).replace(/\//g, '\\/')
25
-
26
-
27
- const getSimplePayConfig = (currency: Currency) => {
28
- if (!CURRENCIES.includes(currency)) {
29
- throw new Error(`Unsupported currency: ${currency}`)
30
- }
31
-
32
- const SIMPLEPAY_API_URL = 'https://secure.simplepay.hu/payment/v2'
33
- const SIMPLEPAY_SANDBOX_URL = 'https://sandbox.simplepay.hu/payment/v2/start'
34
- const SDK_VERSION = 'SimplePayV2.1_Rrd_0.6.1'
35
- const MERCHANT_KEY = process.env[`SIMPLEPAY_MERCHANT_KEY_${currency}`]
36
- const MERCHANT_ID = process.env[`SIMPLEPAY_MERCHANT_ID_${currency}`]
37
- const API_URL = process.env.SIMPLEPAY_PRODUCTION === 'true' ? SIMPLEPAY_API_URL : SIMPLEPAY_SANDBOX_URL
38
-
39
- return {
40
- MERCHANT_KEY,
41
- MERCHANT_ID,
42
- API_URL,
43
- SDK_VERSION
44
- }
45
- }
46
-
47
- const startPayment = async (paymentData: PaymentData) => {
48
- const currency = paymentData.currency || 'HUF'
49
- const { MERCHANT_KEY, MERCHANT_ID, API_URL, SDK_VERSION } = getSimplePayConfig(currency)
50
- simplepayLogger({ MERCHANT_KEY, MERCHANT_ID, API_URL })
51
-
52
- if (!MERCHANT_KEY || !MERCHANT_ID) {
53
- throw new Error('Missing SimplePay configuration')
54
- }
55
-
56
- const requestBody: SimplePayRequestBody = {
57
- salt: crypto.randomBytes(16).toString('hex'),
58
- merchant: MERCHANT_ID,
59
- orderRef: paymentData.orderRef,
60
- currency,
61
- customerEmail: paymentData.customerEmail,
62
- language: paymentData.language || 'HU',
63
- sdkVersion: SDK_VERSION,
64
- methods: [paymentData.method || 'CARD'],
65
- total: String(paymentData.total),
66
- timeout: new Date(Date.now() + 30 * 60 * 1000)
67
- .toISOString()
68
- .replace(/\.\d{3}Z$/, '+00:00'),
69
- url: process.env.SIMPLEPAY_REDIRECT_URL || 'http://url.to.redirect',
70
- invoice: paymentData.invoice,
71
- }
72
-
73
- const bodyString = prepareRequestBody(requestBody)
74
- const signature = generateSignature(bodyString, MERCHANT_KEY)
75
- simplepayLogger({ bodyString, signature })
76
-
77
- try {
78
- const response = await fetch(API_URL, {
79
- method: 'POST',
80
- headers: {
81
- 'Content-Type': 'application/json',
82
- 'Signature': signature,
83
- },
84
- body: bodyString,
85
- })
86
-
87
- simplepayLogger({ response })
88
-
89
- if (!response.ok) {
90
- throw new Error(`SimplePay API error: ${response.status}`)
91
- }
92
-
93
- const responseSignature = response.headers.get('Signature')
94
- simplepayLogger({ responseSignature })
95
- if (!responseSignature) {
96
- throw new Error('Missing response signature')
97
- }
98
-
99
- const responseText = await response.text()
100
- const responseJSON = JSON.parse(responseText) as SimplePayResponse
101
- simplepayLogger({ responseText, responseJSON })
102
-
103
- if (responseJSON.errorCodes) {
104
- throw new Error(`SimplePay API error: ${responseJSON.errorCodes}`)
105
- }
106
-
107
- if (!checkSignature(responseText, responseSignature, MERCHANT_KEY)) {
108
- throw new Error('Invalid response signature')
109
- }
110
-
111
- return responseJSON
112
-
113
- } catch (error) {
114
- throw error
115
- }
116
- }
117
-
118
- const getCurrencyFromMerchantId = (merchantId: string) => {
119
- const currency = Object.entries(process.env)
120
- .find(([key, value]) =>
121
- key.startsWith('SIMPLEPAY_MERCHANT_ID_') && value === merchantId
122
- )?.[0]?.replace('SIMPLEPAY_MERCHANT_ID_', '') as Currency
123
- if (!currency) {
124
- throw new Error(`Merchant id not found in the environment: ${merchantId}`)
125
- }
126
- return currency
127
- }
128
-
129
- const getPaymentResponse = (r: string, signature: string) => {
130
- signature = decodeURIComponent(signature)
131
- const rDecoded = Buffer.from(r, 'base64').toString('utf-8')
132
- const rDecodedJSON = JSON.parse(rDecoded)
133
- const currency = getCurrencyFromMerchantId(rDecodedJSON.m)
134
- const { MERCHANT_KEY } = getSimplePayConfig(currency as Currency)
135
-
136
- if (!checkSignature(rDecoded, signature, MERCHANT_KEY || '')) {
137
- simplepayLogger({ rDecoded, signature })
138
- throw new Error('Invalid response signature')
139
- }
140
-
141
- const responseJson: SimplepayResult = JSON.parse(rDecoded)
142
- const response = {
143
- responseCode: responseJson.r,
144
- transactionId: responseJson.t,
145
- event: responseJson.e,
146
- merchantId: responseJson.m,
147
- orderRef: responseJson.o,
148
- }
149
-
150
- return response
151
- }
1
+ import { startPayment } from './oneTime'
2
+ import { startRecurringPayment, startTokenPayment, cardCancel} from './recurring'
3
+ import type { Currency, Language, PaymentMethod } from './types'
4
+ import { checkSignature, generateSignature, getPaymentResponse, toISO8601DateString } from './utils'
152
5
 
153
6
  export {
154
- startPayment,
155
- getPaymentResponse,
156
- getSimplePayConfig,
157
- generateSignature,
158
- checkSignature,
159
- getCurrencyFromMerchantId
7
+ Currency, Language, PaymentMethod,
8
+ checkSignature, generateSignature, toISO8601DateString, getPaymentResponse,
9
+ startPayment,
10
+ startRecurringPayment, startTokenPayment, cardCancel
160
11
  }
@@ -0,0 +1,97 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest'
2
+ import { getPaymentResponse, startPayment } from './index'
3
+
4
+ const setEnv = () => {
5
+ process.env.SIMPLEPAY_MERCHANT_ID_HUF = 'testId'
6
+ process.env.SIMPLEPAY_MERCHANT_KEY_HUF = 'testKey'
7
+ process.env.SIMPLEPAY_MERCHANT_ID_EUR = 'merchantEuroId'
8
+ process.env.SIMPLEPAY_MERCHANT_KEY_EUR = 'secretEuroKey'
9
+ }
10
+
11
+ const paymentData = {
12
+ orderRef: 'TEST123',
13
+ customerEmail: 'test@example.com',
14
+ total: 1212
15
+ }
16
+ describe('SimplePay SDK Tests', () => {
17
+ beforeEach(() => {
18
+ // Clear all environment variables before each test
19
+ delete process.env.SIMPLEPAY_MERCHANT_ID_HUF
20
+ delete process.env.SIMPLEPAY_MERCHANT_KEY_HUF
21
+ delete process.env.SIMPLEPAY_MERCHANT_ID_EUR
22
+ delete process.env.SIMPLEPAY_MERCHANT_KEY_EUR
23
+ })
24
+
25
+ describe('startPayment', () => {
26
+ it('should throw error when merchant configuration is missing', async () => {
27
+ await expect(startPayment(paymentData)).rejects.toThrow('Missing SimplePay configuration')
28
+ })
29
+
30
+ it('should handle API errors correctly', async () => {
31
+ setEnv()
32
+
33
+ global.fetch = vi.fn().mockResolvedValue({
34
+ ok: true,
35
+ headers: {
36
+ get: vi.fn().mockReturnValue('mockSignature')
37
+ },
38
+ text: vi.fn().mockResolvedValue(JSON.stringify({
39
+ transactionId: '123456',
40
+ total: '1212',
41
+ merchant: 'testId'
42
+ }))
43
+ }) as unknown as typeof fetch
44
+ await expect(startPayment(paymentData)).rejects.toThrow('Invalid response signature')
45
+ })
46
+
47
+ it('should successfully start CARD, HUF, HU payment when API returns valid response', async () => {
48
+ setEnv()
49
+ global.fetch = vi.fn().mockResolvedValue({
50
+ ok: true,
51
+ headers: {
52
+ get: vi.fn().mockReturnValue('bxSwUc0qn0oABSRcq9uawF6zncFBhRk/AbO4HznYR9Pt5SjocyxAD+9Q4bE44h0J')
53
+ },
54
+ text: vi.fn().mockResolvedValue(JSON.stringify({
55
+ transactionId: '123456',
56
+ total: '1212',
57
+ merchant: 'testId'
58
+ }))
59
+ }) as unknown as typeof fetch
60
+
61
+ await expect(startPayment(paymentData)).resolves.toBeDefined()
62
+ })
63
+ })
64
+
65
+ describe('getPaymentResponse', () => {
66
+ it('should correctly decode and parse valid response', () => {
67
+ setEnv()
68
+ const r = 'eyJyIjowLCJ0Ijo1MDQyMzM4ODEsImUiOiJTVUNDRVNTIiwibSI6Im1lcmNoYW50RXVyb0lkIiwibyI6ImMtMS1ldXIifQ=='
69
+ // { r: 0, t: 504233881, e: 'SUCCESS', m: 'merchantEuroId', o: 'c-1-eur' }
70
+ const s = 'YlxrpDa8jF/xVB/rNsEJoFxOoHQ+CiziBmWSMIhYWHSCJmvLoc6kzAiZPmYDU8z6'
71
+ const result = getPaymentResponse(r, s)
72
+ expect(result).toEqual({
73
+ responseCode: 0,
74
+ transactionId: 504233881,
75
+ event: 'SUCCESS',
76
+ merchantId: 'merchantEuroId',
77
+ orderRef: 'c-1-eur'
78
+ })
79
+ })
80
+
81
+ it('should throw error for invalid signature', () => {
82
+ setEnv()
83
+ const mockResponse = {
84
+ r: 'SUCCESS',
85
+ t: '123456789',
86
+ e: 'PAYMENT',
87
+ m: 'testId',
88
+ o: 'ORDER123'
89
+ }
90
+ const encodedResponse = Buffer.from(JSON.stringify(mockResponse)).toString('base64')
91
+
92
+ expect(() =>
93
+ getPaymentResponse(encodedResponse, 'invalid-signature')
94
+ ).toThrow('Invalid response signature')
95
+ })
96
+ })
97
+ })
package/src/oneTime.ts ADDED
@@ -0,0 +1,33 @@
1
+ import crypto from 'crypto'
2
+ import { PaymentData, SimplePayRequestBody } from './types'
3
+ import { simplepayLogger, getSimplePayConfig, toISO8601DateString, makeSimplePayRequest } from './utils'
4
+
5
+ const startPayment = async (paymentData: PaymentData) => {
6
+ simplepayLogger({ function: 'SimplePay/startPayment', paymentData })
7
+ const currency = paymentData.currency || 'HUF'
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
+
11
+ if (!MERCHANT_KEY || !MERCHANT_ID) {
12
+ throw new Error(`Missing SimplePay configuration for ${currency}`)
13
+ }
14
+
15
+ const requestBody: SimplePayRequestBody = {
16
+ salt: crypto.randomBytes(16).toString('hex'),
17
+ merchant: MERCHANT_ID,
18
+ orderRef: paymentData.orderRef,
19
+ currency,
20
+ customerEmail: paymentData.customerEmail,
21
+ language: paymentData.language || 'HU',
22
+ sdkVersion: SDK_VERSION,
23
+ methods: [paymentData.method || 'CARD'],
24
+ total: String(paymentData.total),
25
+ timeout: toISO8601DateString(new Date(Date.now() + 30 * 60 * 1000)),
26
+ url: process.env.SIMPLEPAY_REDIRECT_URL || 'http://url.to.redirect',
27
+ invoice: paymentData.invoice,
28
+ }
29
+
30
+ return makeSimplePayRequest(API_URL_PAYMENT, requestBody, MERCHANT_KEY)
31
+ }
32
+
33
+ export { startPayment }