quickpos 1.0.913 → 1.0.915

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/lib/paytr.js +169 -47
  2. package/package.json +1 -1
package/lib/paytr.js CHANGED
@@ -1,26 +1,39 @@
1
1
  const crypto = require('crypto');
2
- const jsSHA = require('jssha');
3
2
  const axios = require('axios');
4
3
 
5
4
  class PayTR {
6
5
  constructor(config) {
7
6
  this.config = config || {};
7
+
8
8
  const requiredFields = ['merchantId', 'merchantKey', 'merchantSalt'];
9
9
  for (let field of requiredFields) {
10
- if (!config[field]) throw new Error(`Missing required field: ${field}`);
10
+ if (!this.config[field]) throw new Error(`Missing required field: ${field}`);
11
11
  }
12
12
 
13
- this.merchantId = config.merchantId;
14
- this.merchantKey = config.merchantKey;
15
- this.merchantSalt = config.merchantSalt;
16
- this.debug_on = String(config?.debug_on) || '0';
13
+ this.merchantId = this.config.merchantId;
14
+ this.merchantKey = this.config.merchantKey;
15
+ this.merchantSalt = this.config.merchantSalt;
16
+ this.testMode = this.config.testMode ? '1' : '0';
17
+ this.debugOn = this.config.debugOn ? '1' : '0';
18
+
19
+ this.iframe = {
20
+ createToken: this.createIframeToken.bind(this)
21
+ };
22
+
23
+ this.direct = {
24
+ createPayment: this.createDirectPayment.bind(this)
25
+ };
26
+
27
+ this.link = {
28
+ createPayment: this.createLinkPayment.bind(this)
29
+ };
17
30
  }
18
31
 
19
- async createPayment(paymentDetails) {
32
+ async createLinkPayment(paymentDetails) {
20
33
  try {
21
- let requiredData = ['name', 'amount', 'currency', 'maxInstallment', 'expiry_date'];
22
- for (let data of requiredData) {
23
- if (!paymentDetails[data]) throw new Error(`Missing required data: ${data}`);
34
+ const requiredFields = ['name', 'amount', 'currency', 'maxInstallment', 'expiry_date'];
35
+ for (let field of requiredFields) {
36
+ if (!paymentDetails[field]) throw new Error(`Missing required data: ${field}`);
24
37
  }
25
38
 
26
39
  const price = Math.round(paymentDetails.amount * 100).toString();
@@ -42,14 +55,16 @@ class PayTR {
42
55
  lang: lang,
43
56
  min_count: minCount,
44
57
  paytr_token: paytrToken,
45
- expiry_date: paymentDetails?.expiry_date,
58
+ expiry_date: paymentDetails.expiry_date,
46
59
  get_qr: '1',
47
- max_count: Number(paymentDetails?.max_count) || '1',
48
- debug_on: this.debug_on
60
+ max_count: Number(paymentDetails.max_count) || '1',
61
+ debug_on: this.debugOn
49
62
  };
50
63
 
51
- let optionalData = ['email', 'callback_link', 'callback_id'];
52
- for (let data of optionalData) { formData[data] = paymentDetails[data]; }
64
+ const optionalData = ['email', 'callback_link', 'callback_id'];
65
+ for (let data of optionalData) {
66
+ if(paymentDetails[data]) formData[data] = paymentDetails[data];
67
+ }
53
68
 
54
69
  const response = await axios({
55
70
  method: 'POST',
@@ -77,42 +92,157 @@ class PayTR {
77
92
  }
78
93
  } catch (error) {
79
94
  if (error.response) {
80
- // The request was made and the server responded with a status code
81
- // that falls out of the range of 2xx
82
95
  throw new Error(`PayTR API error: ${error.response.data.reason || error.response.statusText}`);
83
- } else if (error.request) {
84
- // The request was made but no response was received
85
- throw new Error('No response received from PayTR API');
86
- } else {
87
- // Something happened in setting up the request that triggered an Error
88
- throw new Error(`Error in PayTR payment creation: ${error.message}`);
89
96
  }
97
+ throw error;
90
98
  }
91
99
  }
92
100
 
93
- async handleCallback(callbackData) {
101
+ async createDirectPayment(params) {
94
102
  try {
95
- const token = callbackData.callback_id + callbackData.merchant_oid + this.merchantSalt + callbackData.status + callbackData.total_amount;
103
+ const userBasket = JSON.stringify(params.userBasket);
104
+ const userIp = params.userIp;
105
+ const merchantOid = params.merchantOid;
106
+ const email = params.email;
107
+ const paymentAmount = params.paymentAmount.toString();
108
+ const currency = params.currency || 'TL';
109
+ const installmentCount = params.installmentCount || '0';
110
+ const paymentType = 'card';
111
+ const non3D = params.non3D ? params.non3D : '0';
112
+
113
+ const rawString = `${this.merchantId}${userIp}${merchantOid}${email}${paymentAmount}${paymentType}${installmentCount}${currency}${this.testMode}${non3D}`;
114
+ const paytrToken = this.generateToken(rawString);
115
+
116
+ const formData = new URLSearchParams();
117
+ formData.append('merchant_id', this.merchantId);
118
+ formData.append('user_ip', userIp);
119
+ formData.append('merchant_oid', merchantOid);
120
+ formData.append('email', email);
121
+ formData.append('payment_amount', paymentAmount);
122
+ formData.append('paytr_token', paytrToken);
123
+ formData.append('user_basket', userBasket);
124
+ formData.append('debug_on', this.debugOn);
125
+ formData.append('test_mode', this.testMode);
126
+ formData.append('payment_type', paymentType);
127
+ formData.append('installment_count', installmentCount);
128
+ formData.append('currency', currency);
129
+ formData.append('non_3d', non3D);
130
+ formData.append('cc_owner', params.cardOwner);
131
+ formData.append('card_number', params.cardNumber);
132
+ formData.append('expiry_month', params.cardExpireMonth);
133
+ formData.append('expiry_year', params.cardExpireYear);
134
+ formData.append('cvc', params.cardCvc);
135
+ formData.append('user_name', params.userName);
136
+ formData.append('user_address', params.userAddress);
137
+ formData.append('user_phone', params.userPhone);
138
+ formData.append('merchant_ok_url', params.merchantOkUrl);
139
+ formData.append('merchant_fail_url', params.merchantFailUrl);
140
+
141
+ const response = await axios({
142
+ method: 'POST',
143
+ url: 'https://www.paytr.com/odeme/api/direct',
144
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
145
+ data: formData
146
+ });
147
+
148
+ const result = response.data;
96
149
 
97
- let paytrToken = this.hashCheck(token, callbackData.hash);
98
- if (!paytrToken) {
99
- throw new Error("PAYTR notification failed: bad hash");
150
+ if (result.status === 'success') {
151
+ return result;
152
+ } else {
153
+ throw new Error(result.reason || 'PayTR Direct API Hatası');
100
154
  }
155
+ } catch (error) {
156
+ if (error.response) throw new Error(`PayTR API Error: ${error.response.data.reason || error.response.statusText}`);
157
+ throw error;
158
+ }
159
+ }
101
160
 
102
- if (callbackData.status === 'success') {
103
- return {
104
- status: 'success',
105
- orderId: callbackData.callback_id,
106
- merchant_oid: callbackData.merchant_oid,
107
- amount: parseFloat(callbackData.total_amount) / 100,
108
- currency: callbackData.currency,
109
- paymentType: callbackData.payment_type
110
- };
161
+ async createIframeToken(params) {
162
+ try {
163
+ const userBasket = JSON.stringify(params.userBasket);
164
+ const userIp = params.userIp;
165
+ const merchantOid = params.merchantOid;
166
+ const email = params.email;
167
+ const paymentAmount = params.paymentAmount.toString();
168
+ const currency = params.currency || 'TL';
169
+ const noInstallment = params.noInstallment ? '1' : '0';
170
+ const maxInstallment = params.maxInstallment || '0';
171
+ const paymentType = params.paymentType || 'card';
172
+
173
+ const rawString = `${this.merchantId}${userIp}${merchantOid}${email}${paymentAmount}${userBasket}${noInstallment}${maxInstallment}${currency}${this.testMode}`;
174
+ const paytrToken = this.generateToken(rawString);
175
+
176
+ const formData = new URLSearchParams();
177
+ formData.append('merchant_id', this.merchantId);
178
+ formData.append('user_ip', userIp);
179
+ formData.append('merchant_oid', merchantOid);
180
+ formData.append('email', email);
181
+ formData.append('payment_amount', paymentAmount);
182
+ formData.append('paytr_token', paytrToken);
183
+ formData.append('user_basket', userBasket);
184
+ formData.append('debug_on', this.debugOn);
185
+ formData.append('no_installment', noInstallment);
186
+ formData.append('max_installment', maxInstallment);
187
+ formData.append('user_name', params.userName);
188
+ formData.append('user_address', params.userAddress);
189
+ formData.append('user_phone', params.userPhone);
190
+ formData.append('merchant_ok_url', params.merchantOkUrl);
191
+ formData.append('merchant_fail_url', params.merchantFailUrl);
192
+ formData.append('timeout_limit', params.timeoutLimit || '30');
193
+ formData.append('currency', currency);
194
+ formData.append('test_mode', this.testMode);
195
+ formData.append('payment_type', paymentType);
196
+
197
+ if (params.bank) formData.append('bank', params.bank);
198
+ if (params.lang) formData.append('lang', params.lang);
199
+
200
+ const response = await axios({
201
+ method: 'POST',
202
+ url: 'https://www.paytr.com/odeme/api/get-token',
203
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
204
+ data: formData
205
+ });
206
+
207
+ const result = response.data;
208
+ if (result.status === 'success') {
209
+ return { status: 'success', token: result.token };
111
210
  } else {
112
- throw new Error("Payment failed");
211
+ throw new Error(result.reason || 'PayTR Token alma hatası');
113
212
  }
114
213
  } catch (error) {
115
- throw new Error(`Error in PayTR callback handling: ${error.message}`);
214
+ if (error.response) throw new Error(`PayTR API Error: ${error.response.data.reason || error.response.statusText}`);
215
+ throw error;
216
+ }
217
+ }
218
+
219
+ handleCallback(callbackData) {
220
+ const { merchant_oid, status, total_amount, hash } = callbackData;
221
+
222
+ if (!hash) throw new Error('Hash param missing');
223
+
224
+ const token = `${merchant_oid}${this.merchantSalt}${status}${total_amount}`;
225
+
226
+ const generatedHash = crypto
227
+ .createHmac('sha256', this.merchantKey)
228
+ .update(token)
229
+ .digest('base64');
230
+
231
+ if (generatedHash !== hash) {
232
+ throw new Error("PAYTR notification failed: bad hash");
233
+ }
234
+
235
+ if (status === 'success') {
236
+ return {
237
+ status: 'success',
238
+ orderId: callbackData.callback_id || merchant_oid,
239
+ merchant_oid: merchant_oid,
240
+ amount: parseFloat(total_amount) / 100,
241
+ currency: callbackData.currency,
242
+ paymentType: callbackData.payment_type
243
+ };
244
+ } else {
245
+ throw new Error("Payment failed");
116
246
  }
117
247
  }
118
248
 
@@ -121,14 +251,6 @@ class PayTR {
121
251
  .update(data + this.merchantSalt)
122
252
  .digest('base64');
123
253
  }
124
-
125
- hashCheck(data, key) {
126
- let shaObj = new jsSHA("SHA-256", "TEXT");
127
- shaObj.setHMACKey(this.merchantKey, "TEXT");
128
- shaObj.update(data);
129
- if (shaObj.getHMAC("B64") === key) return true;
130
- else return false;
131
- }
132
254
  }
133
255
 
134
256
  module.exports = PayTR;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quickpos",
3
- "version": "1.0.913",
3
+ "version": "1.0.915",
4
4
  "main": "app.js",
5
5
  "scripts": {
6
6
  "test": "node test.js"