quickpos 1.0.910 → 1.0.912

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 (131) hide show
  1. package/PROVIDERS-DETAILS.md +1544 -0
  2. package/examples/example-2checkout.js +78 -0
  3. package/examples/example-bitpay.js +83 -0
  4. package/examples/example-cardcom.js +80 -0
  5. package/examples/example-cashfree.js +109 -0
  6. package/examples/example-checkout.js +85 -0
  7. package/examples/example-coingate.js +101 -0
  8. package/examples/example-coinpayments.js +89 -0
  9. package/examples/example-doku.js +27 -0
  10. package/examples/example-epay.js +64 -0
  11. package/examples/example-epoint.js +91 -0
  12. package/examples/example-freekassa.js +26 -0
  13. package/examples/example-heleket.js +139 -0
  14. package/examples/example-konnect.js +227 -0
  15. package/examples/example-midtrans.js +80 -0
  16. package/examples/example-noonpayments.js +297 -0
  17. package/examples/example-nowpayments.js +289 -0
  18. package/examples/example-omise.js +27 -0
  19. package/examples/example-paycom.js +82 -0
  20. package/{example-paydisini.js → examples/example-paydisini.js} +1 -1
  21. package/examples/example-payid19.js +87 -0
  22. package/examples/example-paykun.js +29 -0
  23. package/examples/example-payme.js +202 -0
  24. package/examples/example-paymentwall.js +201 -0
  25. package/examples/example-paynet.js +104 -0
  26. package/examples/example-paynettr.js +18 -0
  27. package/examples/example-payoneer.js +74 -0
  28. package/examples/example-payop.js +351 -0
  29. package/examples/example-paypal.js +200 -0
  30. package/examples/example-payriff.js +89 -0
  31. package/examples/example-paysend.js +81 -0
  32. package/examples/example-payspace.js +103 -0
  33. package/examples/example-payssion.js +27 -0
  34. package/examples/example-paytabs.js +28 -0
  35. package/examples/example-paytm.js +78 -0
  36. package/examples/example-payuindia.js +108 -0
  37. package/examples/example-payulatam.js +75 -0
  38. package/examples/example-phonepe.js +27 -0
  39. package/examples/example-picpay.js +27 -0
  40. package/examples/example-plisio.js +84 -0
  41. package/examples/example-portwallet.js +90 -0
  42. package/examples/example-primepayments.js +250 -0
  43. package/examples/example-razorpay.js +30 -0
  44. package/examples/example-senangpay.js +28 -0
  45. package/examples/example-shurjopay.js +94 -0
  46. package/examples/example-toyyibpay.js +80 -0
  47. package/examples/example-tripay.js +89 -0
  48. package/examples/example-unitpay.js +26 -0
  49. package/examples/example-urway.js +28 -0
  50. package/examples/example-volet.js +80 -0
  51. package/examples/example-xendit.js +28 -0
  52. package/examples/example-yallapay.js +253 -0
  53. package/examples/example-yookassa.js +27 -0
  54. package/examples/example-youcanpay.js +28 -0
  55. package/examples/example-zarinpal.js +98 -0
  56. package/{example.js → examples/example.js} +1 -1
  57. package/lib/2checkout.js +165 -0
  58. package/lib/amazonpay.js +161 -0
  59. package/lib/bitpay.js +122 -0
  60. package/lib/cardcom.js +193 -0
  61. package/lib/cashfree.js +184 -0
  62. package/lib/checkout.js +248 -0
  63. package/lib/coinbase.js +150 -0
  64. package/lib/coingate.js +137 -0
  65. package/lib/coinpayments.js +245 -0
  66. package/lib/doku.js +173 -0
  67. package/lib/epay.js +175 -0
  68. package/lib/epoint.js +162 -0
  69. package/lib/freekassa.js +128 -0
  70. package/lib/heleket.js +67 -1
  71. package/lib/instamojo.js +158 -0
  72. package/lib/konnect.js +211 -0
  73. package/lib/midtrans.js +227 -0
  74. package/lib/noonpayments.js +650 -0
  75. package/lib/nowpayments.js +311 -0
  76. package/lib/omise.js +150 -0
  77. package/lib/paddle.js +180 -0
  78. package/lib/paycom.js +216 -0
  79. package/lib/payid19.js +211 -0
  80. package/lib/paykun.js +144 -0
  81. package/lib/payme.js +302 -0
  82. package/lib/paymentwall.js +205 -0
  83. package/lib/paynet.js +186 -0
  84. package/lib/paynettr.js +165 -0
  85. package/lib/payoneer.js +128 -0
  86. package/lib/payop.js +256 -0
  87. package/lib/paypal.js +542 -0
  88. package/lib/payriff.js +148 -0
  89. package/lib/paysend.js +189 -0
  90. package/lib/payspace.js +168 -0
  91. package/lib/payssion.js +177 -0
  92. package/lib/paytabs.js +145 -0
  93. package/lib/paytm.js +253 -0
  94. package/lib/payuindia.js +162 -0
  95. package/lib/payulatam.js +179 -0
  96. package/lib/perfectmoney.js +143 -0
  97. package/lib/phonepe.js +174 -0
  98. package/lib/picpay.js +119 -0
  99. package/lib/plisio.js +234 -0
  100. package/lib/portwallet.js +152 -0
  101. package/lib/primepayments.js +256 -0
  102. package/lib/razorpay.js +205 -0
  103. package/lib/senangpay.js +130 -0
  104. package/lib/shurjopay.js +159 -0
  105. package/lib/toyyibpay.js +151 -0
  106. package/lib/tripay.js +220 -0
  107. package/lib/unitpay.js +223 -0
  108. package/lib/urway.js +182 -0
  109. package/lib/volet.js +147 -0
  110. package/lib/xendit.js +206 -0
  111. package/lib/yallapay.js +279 -0
  112. package/lib/yookassa.js +193 -0
  113. package/lib/youcanpay.js +124 -0
  114. package/lib/zarinpal.js +157 -0
  115. package/package.json +138 -64
  116. package/readme.md +348 -105
  117. package/test.js +492 -0
  118. package/example-heleket.js +0 -83
  119. package/lib/vallet.js +0 -22
  120. /package/{example-anypay.js → examples/example-anypay.js} +0 -0
  121. /package/{example-bufpay.js → examples/example-bufpay.js} +0 -0
  122. /package/{example-cryptomus.js → examples/example-cryptomus.js} +0 -0
  123. /package/{example-esnekpos.js → examples/example-esnekpos.js} +0 -0
  124. /package/{example-fedapay.js → examples/example-fedapay.js} +0 -0
  125. /package/{example-iyzico.js → examples/example-iyzico.js} +0 -0
  126. /package/{example-papara.js → examples/example-papara.js} +0 -0
  127. /package/{example-payeer.js → examples/example-payeer.js} +0 -0
  128. /package/{example-paymaya.js → examples/example-paymaya.js} +0 -0
  129. /package/{example-shopier.js → examples/example-shopier.js} +0 -0
  130. /package/{ipaymu.js → examples/ipaymu.js} +0 -0
  131. /package/{oderopay.js → examples/oderopay.js} +0 -0
package/lib/payme.js ADDED
@@ -0,0 +1,302 @@
1
+ const axios = require('axios');
2
+
3
+ /**
4
+ * PayMe Ödeme Entegrasyonu
5
+ *
6
+ * Başlamadan önce:
7
+ * 1. PayMe hesabı oluşturun
8
+ * 2. API anahtarınızı alın (seller_payme_id)
9
+ * 3. Gerekli webhook URL'lerini ayarlayın
10
+ */
11
+ class PayMeService {
12
+ constructor(config) {
13
+ this.config = config || {};
14
+ const requiredFields = ['sellerPaymeId'];
15
+ for (let field of requiredFields) {
16
+ if (!config[field]) throw new Error(`Missing required field: ${field}`);
17
+ }
18
+
19
+ this.sellerPaymeId = config.sellerPaymeId;
20
+
21
+ // Sandbox veya Production modu seçimi
22
+ this.sandbox = config.sandbox || false;
23
+
24
+ // API URL'ini ortama göre ayarla
25
+ if (this.sandbox) {
26
+ this.baseUrl = 'https://sandbox.payme.io/api';
27
+ } else {
28
+ this.baseUrl = 'https://live.payme.io/api';
29
+ }
30
+
31
+ // Debug modu
32
+ this.debug = config.debug || false;
33
+ console.log(`PayMe API URL: ${this.baseUrl}`);
34
+ }
35
+
36
+ /**
37
+ * Yeni bir ödeme linki oluşturur
38
+ *
39
+ * @param {Object} paymentDetails - Ödeme detayları
40
+ * @returns {Promise<Object>} Ödeme sonucu
41
+ */
42
+ async createPayment(paymentDetails) {
43
+ try {
44
+ // Zorunlu alanları kontrol et
45
+ let requiredData = ['name', 'amount', 'currency'];
46
+ for (let data of requiredData) {
47
+ if (!paymentDetails[data]) throw new Error(`Missing required data: ${data}`);
48
+ }
49
+
50
+ // PayMe için fiyat formatını ayarla (kuruş/cents cinsinden)
51
+ const salePrice = Math.round(paymentDetails.amount * 100);
52
+
53
+ // Temel ödeme verilerini hazırla
54
+ const paymentData = {
55
+ seller_payme_id: this.sellerPaymeId,
56
+ sale_price: salePrice,
57
+ currency: paymentDetails.currency || 'ILS',
58
+ product_name: paymentDetails.name,
59
+ transaction_id: paymentDetails.orderId || `order-${Date.now()}`,
60
+ installments: paymentDetails.installments || '1',
61
+ market_fee: paymentDetails.marketFee || 0,
62
+ sale_send_notification: paymentDetails.sendNotification || false,
63
+ sale_type: paymentDetails.saleType || 'sale',
64
+ sale_payment_method: paymentDetails.paymentMethod || 'credit-card',
65
+ language: paymentDetails.language || 'he' // Varsayılan dil: İbranice (he)
66
+ };
67
+
68
+ // İsteğe bağlı alanları ekle
69
+ if (paymentDetails.callbackUrl) paymentData.sale_callback_url = paymentDetails.callbackUrl;
70
+ if (paymentDetails.returnUrl) paymentData.sale_return_url = paymentDetails.returnUrl;
71
+ if (paymentDetails.email) paymentData.sale_email = paymentDetails.email;
72
+ if (paymentDetails.phone) paymentData.sale_mobile = paymentDetails.phone;
73
+ if (paymentDetails.buyerName) paymentData.sale_name = paymentDetails.buyerName;
74
+ if (paymentDetails.layout) paymentData.layout = paymentDetails.layout;
75
+
76
+ // Buyer token kaydetme
77
+ if (paymentDetails.captureBuyer === true) {
78
+ paymentData.capture_buyer = '1';
79
+ }
80
+
81
+ // Debug modunda istek detaylarını göster
82
+ if (this.debug) {
83
+ console.log('PayMe ödeme isteği hazırlanıyor:', JSON.stringify(paymentData, null, 2));
84
+ }
85
+
86
+ // API isteği gönder
87
+ const response = await axios({
88
+ method: 'POST',
89
+ url: `${this.baseUrl}/generate-sale`,
90
+ headers: {
91
+ 'Content-Type': 'application/json',
92
+ 'Accept': 'application/json'
93
+ },
94
+ data: paymentData
95
+ });
96
+
97
+ const responseData = response.data;
98
+
99
+ // Debug modunda yanıt detaylarını göster
100
+ if (this.debug) {
101
+ console.log('PayMe API yanıtı:', JSON.stringify(responseData, null, 2));
102
+ }
103
+
104
+ // Hata kontrolü
105
+ if (responseData.status_code !== 0) {
106
+ throw new Error(`PayMe API error: ${responseData.status_error_details || 'Unknown error'}`);
107
+ }
108
+
109
+ // QR kod oluştur (isteğe bağlı)
110
+ let qrCode = null;
111
+ if (paymentDetails.generateQr) {
112
+ qrCode = await this.generateQrCode(responseData.sale_url);
113
+ }
114
+
115
+ return {
116
+ status: 'success',
117
+ data: {
118
+ transactionId: responseData.transaction_id,
119
+ paymeId: responseData.payme_sale_id,
120
+ paymeCode: responseData.payme_sale_code,
121
+ url: responseData.sale_url,
122
+ id: responseData.payme_sale_id,
123
+ qr: qrCode
124
+ }
125
+ };
126
+ } catch (error) {
127
+ if (this.debug) {
128
+ console.error('PayMe API hatası:', error);
129
+ }
130
+
131
+ if (error.response) {
132
+ console.error('Hata detayları:', {
133
+ statusCode: error.response.status,
134
+ statusText: error.response.statusText,
135
+ data: error.response.data
136
+ });
137
+ throw new Error(`PayMe API error (${error.response.status}): ${JSON.stringify(error.response.data)}`);
138
+ } else if (error.request) {
139
+ console.error('Yanıt alınamadı:', error.request);
140
+ throw new Error('No response received from PayMe API');
141
+ } else {
142
+ throw new Error(`Error in PayMe payment creation: ${error.message}`);
143
+ }
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Webhook callback'ini işler
149
+ *
150
+ * @param {Object} callbackData - Callback verileri
151
+ * @returns {Promise<Object>} İşlem sonucu
152
+ */
153
+ async handleCallback(callbackData) {
154
+ try {
155
+ // Debug modunda callback verilerini göster
156
+ if (this.debug) {
157
+ console.log('PayMe callback verileri:', JSON.stringify(callbackData, null, 2));
158
+ }
159
+
160
+ // PayMe'den gelen önemli alanları kontrol et
161
+ if (!callbackData.payme_sale_id || !callbackData.status_code) {
162
+ throw new Error("Missing required fields in callback data");
163
+ }
164
+
165
+ // Signature doğrulaması (tam implementasyon için PayMe ile kontrol gerekebilir)
166
+ if (callbackData.payme_signature) {
167
+ // İleri düzey implementasyon: Signature doğrulaması
168
+ console.log('PayMe signature:', callbackData.payme_signature);
169
+ }
170
+
171
+ // Bildirim türü
172
+ const notifyType = callbackData.notify_type || '';
173
+ const saleStatus = callbackData.sale_status || '';
174
+
175
+ // Ödeme durumunu notifyType ve saleStatus'a göre belirle
176
+ if (notifyType === 'sale-complete' || saleStatus === 'completed') {
177
+ // Başarılı ödeme
178
+ return {
179
+ status: 'success',
180
+ orderId: callbackData.transaction_id || '',
181
+ merchant_oid: callbackData.payme_sale_id,
182
+ amount: parseFloat(callbackData.price) / 100, // Kuruş/cents'ten ana birime çevirme
183
+ currency: callbackData.currency || '',
184
+ paymentType: 'payme',
185
+ card: {
186
+ cardMask: callbackData.buyer_card_mask || '',
187
+ cardExp: callbackData.buyer_card_exp || '',
188
+ cardBrand: callbackData.payme_transaction_card_brand || ''
189
+ },
190
+ buyer: {
191
+ name: callbackData.buyer_name || '',
192
+ email: callbackData.buyer_email || '',
193
+ phone: callbackData.buyer_phone || '',
194
+ socialId: callbackData.buyer_social_id || '',
195
+ buyerKey: callbackData.buyer_key || '' // Token için kullanılabilir
196
+ },
197
+ sale: {
198
+ id: callbackData.payme_sale_id,
199
+ code: callbackData.payme_sale_code || '',
200
+ transactionId: callbackData.payme_transaction_id || '',
201
+ authNumber: callbackData.payme_transaction_auth_number || '',
202
+ installments: callbackData.installments || '1',
203
+ createDate: callbackData.sale_created || '',
204
+ paidDate: callbackData.sale_paid_date || '',
205
+ releaseDate: callbackData.sale_release_date || '',
206
+ isTokenSale: callbackData.is_token_sale === '1',
207
+ invoiceUrl: callbackData.sale_invoice_url || ''
208
+ }
209
+ };
210
+ } else if (notifyType === 'sale-authorized') {
211
+ // Yetkilendirilmiş ödeme (para henüz çekilmemiş)
212
+ return {
213
+ status: 'authorized',
214
+ orderId: callbackData.transaction_id || '',
215
+ merchant_oid: callbackData.payme_sale_id,
216
+ amount: parseFloat(callbackData.price) / 100,
217
+ currency: callbackData.currency || '',
218
+ paymentType: 'payme',
219
+ authNumber: callbackData.payme_transaction_auth_number || ''
220
+ };
221
+ } else if (notifyType === 'refund' || saleStatus === 'refunded' || saleStatus === 'partial-refund') {
222
+ // İade edilen ödeme
223
+ return {
224
+ status: 'refunded',
225
+ orderId: callbackData.transaction_id || '',
226
+ merchant_oid: callbackData.payme_sale_id,
227
+ amount: parseFloat(callbackData.price) / 100,
228
+ currency: callbackData.currency || '',
229
+ isPartial: saleStatus === 'partial-refund'
230
+ };
231
+ } else if (notifyType === 'sale-chargeback' || saleStatus === 'chargeback' || saleStatus === 'partial-chargeback') {
232
+ // Chargeback - müşteri bankasından geri ödeme talebi
233
+ return {
234
+ status: 'chargeback',
235
+ orderId: callbackData.transaction_id || '',
236
+ merchant_oid: callbackData.payme_sale_id,
237
+ amount: parseFloat(callbackData.price) / 100,
238
+ currency: callbackData.currency || '',
239
+ isPartial: saleStatus === 'partial-chargeback'
240
+ };
241
+ } else if (notifyType === 'sale-chargeback-refund') {
242
+ // Chargeback geri alındı
243
+ return {
244
+ status: 'chargeback-refund',
245
+ orderId: callbackData.transaction_id || '',
246
+ merchant_oid: callbackData.payme_sale_id,
247
+ amount: parseFloat(callbackData.price) / 100,
248
+ currency: callbackData.currency || ''
249
+ };
250
+ } else if (notifyType === 'sale-failure' || saleStatus === 'failed' || saleStatus === 'canceled') {
251
+ // Başarısız ödeme
252
+ return {
253
+ status: 'failed',
254
+ orderId: callbackData.transaction_id || '',
255
+ merchant_oid: callbackData.payme_sale_id,
256
+ reason: callbackData.status_error_details || 'Payment failed or canceled'
257
+ };
258
+ } else {
259
+ // Diğer durumlar
260
+ return {
261
+ status: 'other',
262
+ type: notifyType,
263
+ saleStatus: saleStatus,
264
+ orderId: callbackData.transaction_id || '',
265
+ merchant_oid: callbackData.payme_sale_id,
266
+ rawData: callbackData
267
+ };
268
+ }
269
+ } catch (error) {
270
+ if (this.debug) {
271
+ console.error('PayMe callback işleme hatası:', error);
272
+ }
273
+ throw new Error(`Error in PayMe callback handling: ${error.message}`);
274
+ }
275
+ }
276
+
277
+ /**
278
+ * Ödeme bağlantısı için QR kod oluşturur
279
+ *
280
+ * @param {string} paymentUrl - Ödeme URL'i
281
+ * @returns {Promise<string|null>} Base64 formatında QR kod
282
+ */
283
+ async generateQrCode(paymentUrl) {
284
+ try {
285
+ const response = await axios.get('https://api.qrserver.com/v1/create-qr-code/', {
286
+ params: {
287
+ size: '300x300',
288
+ data: paymentUrl
289
+ },
290
+ responseType: 'arraybuffer'
291
+ });
292
+
293
+ const base64Image = Buffer.from(response.data, 'binary').toString('base64');
294
+ return `data:image/png;base64,${base64Image}`;
295
+ } catch (error) {
296
+ console.error('QR kod oluşturma hatası:', error);
297
+ return null;
298
+ }
299
+ }
300
+ }
301
+
302
+ module.exports = PayMeService;
@@ -0,0 +1,205 @@
1
+ const Paymentwall = require('paymentwall');
2
+ const axios = require('axios');
3
+
4
+ class PaymentwallService {
5
+ constructor(config) {
6
+ this.config = config || {};
7
+ const requiredFields = ['appKey', 'secretKey'];
8
+ for (let field of requiredFields) {
9
+ if (!config[field]) throw new Error(`Missing required field: ${field}`);
10
+ }
11
+
12
+ // Paymentwall SDK'sını yapılandır
13
+ Paymentwall.Configure(
14
+ Paymentwall.Base.API_GOODS,
15
+ config.appKey,
16
+ config.secretKey
17
+ );
18
+
19
+ this.testMode = config.testMode || false;
20
+ }
21
+
22
+ async createPayment(paymentDetails) {
23
+ try {
24
+ let requiredData = ['name', 'amount', 'currency', 'email'];
25
+ for (let data of requiredData) {
26
+ if (!paymentDetails[data]) throw new Error(`Missing required data: ${data}`);
27
+ }
28
+
29
+ // Benzersiz bir ürün ve işlem ID'si oluştur
30
+ const productId = paymentDetails.productId || 'product_' + Date.now();
31
+ const orderId = paymentDetails.orderId || 'order_' + Date.now();
32
+
33
+ // Ürünü tek seferlik (one-time) ödeme olarak yapılandır
34
+ const product = new Paymentwall.Product(
35
+ productId,
36
+ paymentDetails.amount,
37
+ paymentDetails.currency,
38
+ paymentDetails.name,
39
+ Paymentwall.Product.TYPE_FIXED // Tek seferlik ödeme tipi
40
+ );
41
+
42
+ // Kullanıcı bilgilerini oluştur
43
+ const userId = paymentDetails.userId || 'user_' + Date.now();
44
+ const userInfo = {
45
+ 'email': paymentDetails.email,
46
+ 'order_id': orderId
47
+ };
48
+
49
+ if (paymentDetails.userName) userInfo.name = paymentDetails.userName;
50
+
51
+ // Tüm extra parametreleri toplayalım
52
+ const extraParams = {};
53
+
54
+ // Custom parametreleri ekle (varsa)
55
+ if (paymentDetails.customParams) {
56
+ Object.entries(paymentDetails.customParams).forEach(([key, value]) => {
57
+ extraParams[key] = value;
58
+ });
59
+ }
60
+
61
+ // Webhook URL'ini ayarla (varsa)
62
+ if (paymentDetails.pingback_url) {
63
+ extraParams['pingback_url'] = paymentDetails.pingback_url;
64
+ }
65
+
66
+ // Dönüş URL'ini ayarla (varsa)
67
+ if (paymentDetails.successUrl) {
68
+ extraParams['success_url'] = paymentDetails.successUrl;
69
+ }
70
+
71
+ // Ödeme Widget'ını oluştur
72
+ const widgetCode = paymentDetails.widgetCode || 'p1_1';
73
+ const widget = new Paymentwall.Widget(
74
+ userId,
75
+ widgetCode,
76
+ [product],
77
+ {...userInfo, ...extraParams}
78
+ );
79
+
80
+ // Widget URL'sini al
81
+ const widgetUrl = widget.getUrl();
82
+
83
+ // QR kod oluştur (isteğe bağlı)
84
+ let qrCode = null;
85
+ if (paymentDetails.generateQr) {
86
+ qrCode = await this.generateQrCode(widgetUrl);
87
+ }
88
+
89
+ return {
90
+ status: 'success',
91
+ data: {
92
+ transactionId: orderId,
93
+ url: widgetUrl,
94
+ id: orderId,
95
+ qr: qrCode
96
+ }
97
+ };
98
+ } catch (error) {
99
+ throw new Error(`Error in Paymentwall payment creation: ${error.message}`);
100
+ }
101
+ }
102
+
103
+ async handleCallback(callbackData, ipAddress) {
104
+ try {
105
+ console.log('🔍 Paymentwall callback işleniyor:', callbackData);
106
+
107
+ // Test modu kontrolü
108
+ if (callbackData.is_test === 1 || callbackData.is_test === '1' || callbackData.test_mode === 1) {
109
+ console.log('🧪 Test modu callback algılandı');
110
+
111
+ // Test callback işleme - gerçek data doğrulama yapmadan test için
112
+ return {
113
+ status: 'success',
114
+ orderId: callbackData.order_id || callbackData.uid || 'test-order',
115
+ merchant_oid: callbackData.ref || 'test-ref',
116
+ amount: callbackData.amount || '199.99',
117
+ currency: callbackData.currency || 'TRY',
118
+ paymentType: 'paymentwall-test'
119
+ };
120
+ }
121
+
122
+ // Paymentwall pingback nesnesi oluştur
123
+ const pingback = new Paymentwall.Pingback(
124
+ callbackData,
125
+ ipAddress,
126
+ this.testMode
127
+ );
128
+
129
+ console.log('🔍 Pingback oluşturuldu, doğrulanıyor...');
130
+
131
+ // Pingback'in geçerli olup olmadığını kontrol et
132
+ if (pingback.validate()) {
133
+ console.log('✅ Pingback doğrulandı. Tip:', pingback.getType());
134
+
135
+ // Callback verileri direkt olarak kullanılacak
136
+ let amount = callbackData.amount || '0';
137
+ let currency = callbackData.currency || 'TRY';
138
+
139
+ // Callback veri yapısına göre doğru alan isimlerini kullan
140
+ if (callbackData.goodsid) {
141
+ console.log('✅ Ürün ID tespit edildi:', callbackData.goodsid);
142
+ }
143
+
144
+ // Ödeme başarılı mı kontrolü
145
+ if (pingback.isDeliverable()) {
146
+ console.log('✅ Ödeme başarılı (deliverable)');
147
+ // Tek seferlik ödeme başarılı
148
+ return {
149
+ status: 'success',
150
+ orderId: callbackData.order_id || callbackData.uid || '',
151
+ merchant_oid: callbackData.ref || '',
152
+ amount: amount,
153
+ currency: currency,
154
+ paymentType: 'paymentwall',
155
+ raw: callbackData // Tüm veriyi de ekleyelim
156
+ };
157
+ } else if (pingback.isCancelable()) {
158
+ console.log('❌ Ödeme iptal edildi (cancelable)');
159
+ return {
160
+ status: 'failed',
161
+ orderId: callbackData.order_id || callbackData.uid || '',
162
+ reason: 'Payment was cancelled',
163
+ raw: callbackData
164
+ };
165
+ } else {
166
+ console.log('ℹ️ Diğer pingback tipi:', pingback.getType());
167
+ return {
168
+ status: 'other',
169
+ type: pingback.getType(),
170
+ orderId: callbackData.order_id || callbackData.uid || '',
171
+ raw: callbackData
172
+ };
173
+ }
174
+ } else {
175
+ const errorCode = pingback.getErrorCode();
176
+ console.error('❌ Geçersiz pingback:', errorCode);
177
+ throw new Error('Invalid pingback: ' + errorCode);
178
+ }
179
+ } catch (error) {
180
+ console.error('❌ Callback işleme hatası:', error);
181
+ throw new Error(`Error in Paymentwall callback handling: ${error.message}`);
182
+ }
183
+ }
184
+
185
+ // QR code oluşturmak için yardımcı fonksiyon
186
+ async generateQrCode(paymentUrl) {
187
+ try {
188
+ const response = await axios.get('https://api.qrserver.com/v1/create-qr-code/', {
189
+ params: {
190
+ size: '300x300',
191
+ data: paymentUrl
192
+ },
193
+ responseType: 'arraybuffer'
194
+ });
195
+
196
+ const base64Image = Buffer.from(response.data, 'binary').toString('base64');
197
+ return `data:image/png;base64,${base64Image}`;
198
+ } catch (error) {
199
+ console.error('QR code generation failed:', error);
200
+ return null;
201
+ }
202
+ }
203
+ }
204
+
205
+ module.exports = PaymentwallService;
package/lib/paynet.js ADDED
@@ -0,0 +1,186 @@
1
+ const axios = require('axios');
2
+ const crypto = require('crypto');
3
+
4
+ class PayNetClient {
5
+ constructor(config) {
6
+ const requiredFields = ['merchantId', 'secretKey'];
7
+ for (let field of requiredFields) {
8
+ if (!config[field]) throw new Error(`Missing required field: ${field}`);
9
+ }
10
+
11
+ this.merchantId = config.merchantId;
12
+ this.secretKey = config.secretKey;
13
+ this.baseURL = 'https://paynet.md/acquiring';
14
+
15
+ this.client = axios.create({
16
+ baseURL: this.baseURL,
17
+ headers: {
18
+ 'Content-Type': 'application/json'
19
+ }
20
+ });
21
+ }
22
+
23
+ generateSignature(data) {
24
+ const signatureString = Object.keys(data)
25
+ .filter(key => key !== 'signature')
26
+ .sort()
27
+ .map(key => `${key}=${data[key]}`)
28
+ .join('&');
29
+
30
+ return crypto
31
+ .createHmac('sha256', this.secretKey)
32
+ .update(signatureString)
33
+ .digest('hex')
34
+ .toUpperCase();
35
+ }
36
+
37
+ async createPayment(options) {
38
+ try {
39
+ const orderId = options.orderId || `ORDER-${Date.now()}`;
40
+ const amount = parseFloat(options.amount) * 100; // Convert to cents
41
+
42
+ const paymentData = {
43
+ merchant_id: this.merchantId,
44
+ order_id: orderId,
45
+ amount: amount,
46
+ currency: options.currency || 'MDL',
47
+ description: options.description || options.name || 'Payment',
48
+ success_url: options.successUrl || options.callback_link,
49
+ fail_url: options.failUrl || options.callback_link,
50
+ callback_url: options.callbackUrl || options.callback_link,
51
+ language: options.language || 'ro',
52
+ customer_email: options.email || '',
53
+ customer_name: options.name || '',
54
+ customer_phone: options.phone || ''
55
+ };
56
+
57
+ paymentData.signature = this.generateSignature(paymentData);
58
+
59
+ const response = await this.client.post('/api/v1/payment', paymentData);
60
+
61
+ if (response.data.success) {
62
+ return {
63
+ status: 'success',
64
+ data: {
65
+ url: response.data.payment_url,
66
+ orderId: orderId,
67
+ paymentId: response.data.payment_id,
68
+ amount: amount / 100,
69
+ currency: paymentData.currency
70
+ }
71
+ };
72
+ } else {
73
+ throw new Error(response.data.message || 'Payment creation failed');
74
+ }
75
+ } catch (error) {
76
+ throw new Error(`Payment creation error: ${error.response?.data?.message || error.message}`);
77
+ }
78
+ }
79
+
80
+ async handleCallback(callbackData) {
81
+ try {
82
+ const verification = await this.verifyCallback(callbackData);
83
+
84
+ if (!verification.status) {
85
+ throw new Error(verification.error.message);
86
+ }
87
+
88
+ const data = verification.data;
89
+
90
+ // Status mapping
91
+ const statusMapping = {
92
+ 'success': 'success',
93
+ 'completed': 'success',
94
+ 'approved': 'success',
95
+ 'failed': 'failed',
96
+ 'declined': 'failed',
97
+ 'cancelled': 'failed',
98
+ 'pending': 'pending',
99
+ 'processing': 'pending'
100
+ };
101
+
102
+ return {
103
+ status: statusMapping[data.status] || 'unknown',
104
+ orderId: data.order_id,
105
+ transactionId: data.payment_id || data.transaction_id,
106
+ amount: parseFloat(data.amount) / 100,
107
+ currency: data.currency,
108
+ paymentStatus: data.status,
109
+ paymentMethod: data.payment_method,
110
+ rrn: data.rrn,
111
+ approvalCode: data.approval_code
112
+ };
113
+ } catch (error) {
114
+ throw new Error(`Error in PayNet callback handling: ${error.message}`);
115
+ }
116
+ }
117
+
118
+ async verifyCallback(data) {
119
+ try {
120
+ const receivedSign = data.signature;
121
+ const dataToVerify = { ...data };
122
+ delete dataToVerify.signature;
123
+
124
+ const expectedSign = this.generateSignature(dataToVerify);
125
+
126
+ if (receivedSign !== expectedSign) {
127
+ return {
128
+ status: false,
129
+ error: {
130
+ code: 401,
131
+ message: 'Invalid signature'
132
+ }
133
+ };
134
+ }
135
+
136
+ return {
137
+ status: true,
138
+ data: data
139
+ };
140
+ } catch (error) {
141
+ return {
142
+ status: false,
143
+ error: {
144
+ code: 500,
145
+ message: error.message
146
+ }
147
+ };
148
+ }
149
+ }
150
+
151
+ async getPaymentStatus(paymentId) {
152
+ try {
153
+ const data = {
154
+ merchant_id: this.merchantId,
155
+ payment_id: paymentId
156
+ };
157
+
158
+ data.signature = this.generateSignature(data);
159
+
160
+ const response = await this.client.post('/api/v1/payment/status', data);
161
+ return response.data;
162
+ } catch (error) {
163
+ throw new Error(`Error getting payment status: ${error.response?.data?.message || error.message}`);
164
+ }
165
+ }
166
+
167
+ async refundPayment(paymentId, options = {}) {
168
+ try {
169
+ const data = {
170
+ merchant_id: this.merchantId,
171
+ payment_id: paymentId,
172
+ amount: options.amount ? parseFloat(options.amount) * 100 : undefined,
173
+ reason: options.reason || 'Customer request'
174
+ };
175
+
176
+ data.signature = this.generateSignature(data);
177
+
178
+ const response = await this.client.post('/api/v1/payment/refund', data);
179
+ return response.data;
180
+ } catch (error) {
181
+ throw new Error(`Error creating refund: ${error.response?.data?.message || error.message}`);
182
+ }
183
+ }
184
+ }
185
+
186
+ module.exports = PayNetClient;