quickpos 1.0.906 → 1.0.908
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/app.js +2 -1
- package/example-anypay.js +334 -0
- package/example-esnekpos.js +254 -0
- package/example-fedapay.js +217 -0
- package/example-iyzico.js +103 -0
- package/example-paymaya.js +112 -0
- package/lib/anypay.js +246 -0
- package/lib/esnekpos.js +352 -0
- package/lib/fedapay.js +194 -0
- package/lib/iyzico.js +180 -0
- package/lib/paymaya.js +126 -0
- package/package.json +16 -4
- package/readme.md +10 -12
package/lib/iyzico.js
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
const Iyzipay = require('iyzipay');
|
|
2
|
+
const uuid = require('uuid');
|
|
3
|
+
const dayjs = require('dayjs');
|
|
4
|
+
|
|
5
|
+
class Iyzico {
|
|
6
|
+
constructor(config) {
|
|
7
|
+
this.config = config || {};
|
|
8
|
+
const requiredFields = ['apiKey', 'secretKey', 'uri'];
|
|
9
|
+
for (let field of requiredFields) {
|
|
10
|
+
if (!config[field]) throw new Error(`Missing required field: ${field}`);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
this.iyzipay = new Iyzipay({
|
|
14
|
+
apiKey: config.apiKey,
|
|
15
|
+
secretKey: config.secretKey,
|
|
16
|
+
uri: config.uri || 'https://sandbox-api.iyzipay.com'
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async createPayment(paymentDetails) {
|
|
21
|
+
try {
|
|
22
|
+
// Zorunlu alanları kontrol et
|
|
23
|
+
const requiredData = ['name', 'amount', 'currency', 'callbackUrl', 'email'];
|
|
24
|
+
for (let data of requiredData) {
|
|
25
|
+
if (!paymentDetails[data]) throw new Error(`Missing required data: ${data}`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const price = parseFloat(paymentDetails.amount).toFixed(2);
|
|
29
|
+
const paidPrice = price; // Fiyatı ayarla, vergi/komisyon eklenecekse burada değiştirebilirsin
|
|
30
|
+
const currency = this.getCurrencyCode(paymentDetails.currency);
|
|
31
|
+
|
|
32
|
+
// Benzersiz sipariş ID oluştur
|
|
33
|
+
const conversationId = paymentDetails.conversationId || `conv_${Date.now()}_${Math.floor(Math.random() * 1000)}`;
|
|
34
|
+
const basketId = paymentDetails.orderId || `order_${Date.now()}`;
|
|
35
|
+
|
|
36
|
+
// Ödeme formu oluşturma isteği
|
|
37
|
+
const request = {
|
|
38
|
+
locale: paymentDetails.locale || Iyzipay.LOCALE.TR,
|
|
39
|
+
conversationId: conversationId,
|
|
40
|
+
price: price,
|
|
41
|
+
paidPrice: paidPrice,
|
|
42
|
+
currency: currency,
|
|
43
|
+
basketId: basketId,
|
|
44
|
+
paymentGroup: Iyzipay.PAYMENT_GROUP.PRODUCT,
|
|
45
|
+
callbackUrl: paymentDetails.callbackUrl,
|
|
46
|
+
enabledInstallments: paymentDetails.enabledInstallments || [1, 2, 3, 6, 9],
|
|
47
|
+
buyer: {
|
|
48
|
+
id: paymentDetails.buyerId || 'BY789',
|
|
49
|
+
name: paymentDetails.buyerName || 'John',
|
|
50
|
+
surname: paymentDetails.buyerSurname || 'Doe',
|
|
51
|
+
gsmNumber: paymentDetails.buyerPhone || '+905350000000',
|
|
52
|
+
email: paymentDetails.email,
|
|
53
|
+
identityNumber: paymentDetails.identityNumber || '74300864791',
|
|
54
|
+
lastLoginDate: paymentDetails.lastLoginDate || dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
|
55
|
+
registrationDate: paymentDetails.registrationDate || dayjs().format('YYYY-MM-DD HH:mm:ss'),
|
|
56
|
+
registrationAddress: paymentDetails.address || 'Nidakule Göztepe, Merdivenköy Mah. Bora Sok. No:1',
|
|
57
|
+
ip: paymentDetails.ip || '85.34.78.112',
|
|
58
|
+
city: paymentDetails.city || 'Istanbul',
|
|
59
|
+
country: paymentDetails.country || 'Turkey',
|
|
60
|
+
zipCode: paymentDetails.zipCode || '34732'
|
|
61
|
+
},
|
|
62
|
+
shippingAddress: {
|
|
63
|
+
contactName: paymentDetails.buyerName ? `${paymentDetails.buyerName} ${paymentDetails.buyerSurname}` : 'John Doe',
|
|
64
|
+
city: paymentDetails.city || 'Istanbul',
|
|
65
|
+
country: paymentDetails.country || 'Turkey',
|
|
66
|
+
address: paymentDetails.address || 'Nidakule Göztepe, Merdivenköy Mah. Bora Sok. No:1',
|
|
67
|
+
zipCode: paymentDetails.zipCode || '34732'
|
|
68
|
+
},
|
|
69
|
+
billingAddress: {
|
|
70
|
+
contactName: paymentDetails.buyerName ? `${paymentDetails.buyerName} ${paymentDetails.buyerSurname}` : 'John Doe',
|
|
71
|
+
city: paymentDetails.city || 'Istanbul',
|
|
72
|
+
country: paymentDetails.country || 'Turkey',
|
|
73
|
+
address: paymentDetails.address || 'Nidakule Göztepe, Merdivenköy Mah. Bora Sok. No:1',
|
|
74
|
+
zipCode: paymentDetails.zipCode || '34732'
|
|
75
|
+
},
|
|
76
|
+
basketItems: [
|
|
77
|
+
{
|
|
78
|
+
id: paymentDetails.itemId || `ITEM${Date.now()}`,
|
|
79
|
+
name: paymentDetails.name,
|
|
80
|
+
category1: paymentDetails.category || 'Digital',
|
|
81
|
+
category2: paymentDetails.subCategory || 'Service',
|
|
82
|
+
itemType: Iyzipay.BASKET_ITEM_TYPE.VIRTUAL,
|
|
83
|
+
price: price
|
|
84
|
+
}
|
|
85
|
+
]
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// Önce checkoutFormInitialize ile ödeme formu oluşturalım
|
|
89
|
+
return new Promise((resolve, reject) => {
|
|
90
|
+
this.iyzipay.checkoutFormInitialize.create(request, (err, result) => {
|
|
91
|
+
if (err) {
|
|
92
|
+
return reject(new Error(`Iyzico error: ${err.message}`));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (result.status === 'success') {
|
|
96
|
+
resolve({
|
|
97
|
+
status: 'success',
|
|
98
|
+
data: {
|
|
99
|
+
token: result.token,
|
|
100
|
+
url: result.paymentPageUrl, // Ödeme sayfası linki
|
|
101
|
+
status: result.status
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
} else {
|
|
105
|
+
reject(new Error(`Iyzico payment creation failed: ${result.errorMessage}`));
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
} catch (error) {
|
|
110
|
+
throw new Error(`Error in Iyzico payment creation: ${error.message}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async handleCallback(callbackData) {
|
|
115
|
+
try {
|
|
116
|
+
if (!callbackData || !callbackData.token) {
|
|
117
|
+
throw new Error('Invalid callback data: token is missing');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const request = {
|
|
121
|
+
locale: Iyzipay.LOCALE.TR,
|
|
122
|
+
conversationId: `retrieve_${Date.now()}`,
|
|
123
|
+
token: callbackData.token
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
return new Promise((resolve, reject) => {
|
|
127
|
+
// checkout form ile ödeme sonucunu kontrol et
|
|
128
|
+
this.iyzipay.checkoutForm.retrieve(request, (err, result) => {
|
|
129
|
+
if (err) {
|
|
130
|
+
return reject(new Error(`Iyzico retrieval error: ${err.message}`));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
console.log(result)
|
|
134
|
+
|
|
135
|
+
if (result.status === 'success' && result.paymentStatus === 'SUCCESS') {
|
|
136
|
+
resolve({
|
|
137
|
+
status: 'success',
|
|
138
|
+
orderId: result.basketId,
|
|
139
|
+
amount: parseFloat(result.price),
|
|
140
|
+
currency: this.getCurrencyName(result.currency),
|
|
141
|
+
paymentId: result.paymentId,
|
|
142
|
+
paymentType: result.cardType || 'Unknown',
|
|
143
|
+
paymentTransactionId: result.token,
|
|
144
|
+
installment: result.installment
|
|
145
|
+
});
|
|
146
|
+
} else {
|
|
147
|
+
reject(new Error(`Payment failed: ${result.errorMessage || 'Unknown error'}`));
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
} catch (error) {
|
|
152
|
+
throw new Error(`Error in Iyzico callback handling: ${error.message}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
getCurrencyCode(currency) {
|
|
157
|
+
const currencyMap = {
|
|
158
|
+
'TRY': Iyzipay.CURRENCY.TRY,
|
|
159
|
+
'TL': Iyzipay.CURRENCY.TRY,
|
|
160
|
+
'USD': Iyzipay.CURRENCY.USD,
|
|
161
|
+
'EUR': Iyzipay.CURRENCY.EUR,
|
|
162
|
+
'GBP': Iyzipay.CURRENCY.GBP
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
return currencyMap[currency.toUpperCase()] || Iyzipay.CURRENCY.TRY;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
getCurrencyName(currencyCode) {
|
|
169
|
+
const currencyMap = {
|
|
170
|
+
[Iyzipay.CURRENCY.TRY]: 'TRY',
|
|
171
|
+
[Iyzipay.CURRENCY.USD]: 'USD',
|
|
172
|
+
[Iyzipay.CURRENCY.EUR]: 'EUR',
|
|
173
|
+
[Iyzipay.CURRENCY.GBP]: 'GBP'
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
return currencyMap[currencyCode] || 'TRY';
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
module.exports = Iyzico;
|
package/lib/paymaya.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
const paymayasdk = require('paymaya-integration');
|
|
2
|
+
|
|
3
|
+
class PayMaya {
|
|
4
|
+
constructor(config) {
|
|
5
|
+
this.config = config || {};
|
|
6
|
+
const requiredFields = ['publicKey', 'secretKey'];
|
|
7
|
+
for (let field of requiredFields) {
|
|
8
|
+
if (!config[field]) throw new Error(`Missing required field: ${field}`);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
this.publicKey = config.publicKey;
|
|
12
|
+
this.secretKey = config.secretKey;
|
|
13
|
+
this.isProduction = config.isProduction || false;
|
|
14
|
+
|
|
15
|
+
this.paymaya = new paymayasdk({
|
|
16
|
+
publicKey: this.publicKey,
|
|
17
|
+
secretKey: this.secretKey,
|
|
18
|
+
environment: this.isProduction ? 'PRODUCTION' : 'SANDBOX'
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async createPayment(paymentDetails) {
|
|
23
|
+
try {
|
|
24
|
+
// Zorunlu alanları kontrol et
|
|
25
|
+
const requiredData = ['name', 'amount', 'currency', 'successUrl'];
|
|
26
|
+
for (let data of requiredData) {
|
|
27
|
+
if (!paymentDetails[data]) throw new Error(`Missing required data: ${data}`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Ödeme verileri hazırlanıyor
|
|
31
|
+
const paymentData = {
|
|
32
|
+
totalAmount: {
|
|
33
|
+
value: parseFloat(paymentDetails.amount).toFixed(2),
|
|
34
|
+
currency: paymentDetails.currency
|
|
35
|
+
},
|
|
36
|
+
requestReferenceNumber: paymentDetails.orderId || `REF-${Date.now()}`,
|
|
37
|
+
redirectUrl: {
|
|
38
|
+
success: paymentDetails.successUrl,
|
|
39
|
+
failure: paymentDetails.failureUrl || paymentDetails.successUrl,
|
|
40
|
+
cancel: paymentDetails.cancelUrl || paymentDetails.successUrl
|
|
41
|
+
},
|
|
42
|
+
items: [
|
|
43
|
+
{
|
|
44
|
+
name: paymentDetails.name,
|
|
45
|
+
description: paymentDetails.description || paymentDetails.name,
|
|
46
|
+
quantity: paymentDetails.quantity || 1,
|
|
47
|
+
code: paymentDetails.code || `ITEM-${Date.now()}`,
|
|
48
|
+
amount: {
|
|
49
|
+
value: parseFloat(paymentDetails.amount).toFixed(2),
|
|
50
|
+
currency: paymentDetails.currency
|
|
51
|
+
},
|
|
52
|
+
totalAmount: {
|
|
53
|
+
value: parseFloat(paymentDetails.amount).toFixed(2),
|
|
54
|
+
currency: paymentDetails.currency
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
],
|
|
58
|
+
metadata: paymentDetails.metadata || {}
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const checkout = await this.paymaya.checkout.create(paymentData);
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
status: 'success',
|
|
65
|
+
data: {
|
|
66
|
+
transactionId: checkout.checkoutId,
|
|
67
|
+
url: checkout.redirectUrl,
|
|
68
|
+
id: checkout.checkoutId,
|
|
69
|
+
expiresAt: checkout.expiresAt
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
} catch (error) {
|
|
73
|
+
if (error.response) {
|
|
74
|
+
throw new Error(`PayMaya API error: ${JSON.stringify(error.response.data)}`);
|
|
75
|
+
} else if (error.request) {
|
|
76
|
+
throw new Error('No response received from PayMaya API');
|
|
77
|
+
} else {
|
|
78
|
+
throw new Error(`Error in PayMaya payment creation: ${error.message}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async handleCallback(callbackData) {
|
|
84
|
+
try {
|
|
85
|
+
if (!callbackData.checkoutId) {
|
|
86
|
+
throw new Error('Invalid callback data: missing required fields');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
let checkoutId = callbackData.checkoutId;
|
|
90
|
+
|
|
91
|
+
let checkoutStatus = await this.paymaya.checkout.retrieve(checkoutId);
|
|
92
|
+
checkoutStatus = checkoutStatus?.length ? checkoutStatus[0] : checkoutStatus;
|
|
93
|
+
if (checkoutStatus.status === 'PAYMENT_SUCCESS') {
|
|
94
|
+
return {
|
|
95
|
+
status: 'success',
|
|
96
|
+
id: checkoutStatus.id,
|
|
97
|
+
orderId: checkoutStatus.requestReferenceNumber,
|
|
98
|
+
amount: checkoutStatus.amount,
|
|
99
|
+
currency: checkoutStatus.currency
|
|
100
|
+
};
|
|
101
|
+
} else {
|
|
102
|
+
throw new Error(`Payment failed with status: ${checkoutStatus.status}. Please wait a few minutes and refresh the page.`);
|
|
103
|
+
}
|
|
104
|
+
} catch (error) {
|
|
105
|
+
throw new Error(`Error in PayMaya callback handling: ${error.message}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async getCheckoutStatus(checkoutId) {
|
|
110
|
+
return await this.paymaya.checkout.retrieve(checkoutId);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async voidPayment(paymentId, reason) {
|
|
114
|
+
return await this.paymaya.checkout.voidPayment(paymentId, reason);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async refundPayment(paymentId, data) {
|
|
118
|
+
return await this.paymaya.checkout.refundPayment(paymentId, data);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
verifyWebhookSignature(payload, signature) {
|
|
122
|
+
return this.paymaya.webhooks.verifySignature(payload, signature);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
module.exports = PayMaya;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quickpos",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.908",
|
|
4
4
|
"main": "app.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
@@ -26,7 +26,11 @@
|
|
|
26
26
|
"shopier",
|
|
27
27
|
"cryptomus",
|
|
28
28
|
"payeer",
|
|
29
|
-
"papara"
|
|
29
|
+
"papara",
|
|
30
|
+
"paymaya",
|
|
31
|
+
"anypay",
|
|
32
|
+
"esnekpos",
|
|
33
|
+
"fedapay"
|
|
30
34
|
],
|
|
31
35
|
"repository": {
|
|
32
36
|
"type": "git",
|
|
@@ -40,11 +44,19 @@
|
|
|
40
44
|
"license": "ISC",
|
|
41
45
|
"description": "",
|
|
42
46
|
"dependencies": {
|
|
47
|
+
"anypay-node": "^1.0.0",
|
|
43
48
|
"axios": "^1.7.2",
|
|
49
|
+
"body-parser": "^1.20.3",
|
|
44
50
|
"crypto": "^1.0.1",
|
|
45
|
-
"
|
|
51
|
+
"dayjs": "^1.11.13",
|
|
52
|
+
"esnekpos": "^1.0.0",
|
|
53
|
+
"express": "^4.21.2",
|
|
54
|
+
"fedapay": "^1.2.4",
|
|
55
|
+
"iyzipay": "^2.0.48",
|
|
46
56
|
"jssha": "^3.3.1",
|
|
47
57
|
"multer": "^1.4.5-lts.1",
|
|
48
|
-
"
|
|
58
|
+
"paymaya-integration": "^1.0.4",
|
|
59
|
+
"payu-websdk": "^1.2.0",
|
|
60
|
+
"uuid": "^9.0.1"
|
|
49
61
|
}
|
|
50
62
|
}
|
package/readme.md
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# 💳 QuickPos 🚀
|
|
2
2
|
|
|
3
|
-
QuickPos, farklı ödeme sağlayıcılarını destekleyen güçlü bir ödeme entegrasyon modülüdür. Şu anda PayTR, Shopier, Cryptomus, Payeer, Papara sağlayıcısını desteklemektedir ve gelecekte birçok yeni sağlayıcı ile özellik eklemeyi planlamaktadır. Yol haritamıza göz atarak gelecek özellikleri keşfedebilirsiniz.
|
|
3
|
+
QuickPos, farklı ödeme sağlayıcılarını destekleyen güçlü bir ödeme entegrasyon modülüdür. Şu anda PayTR, Shopier, Cryptomus, Payeer, Papara, Anypay, EsnekPos, İyzico, PayMaya, FedaPay sağlayıcısını desteklemektedir ve gelecekte birçok yeni sağlayıcı ile özellik eklemeyi planlamaktadır. Yol haritamıza göz atarak gelecek özellikleri keşfedebilirsiniz.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
- SpeedSMM.COM Tarafın'dan Geliştirilmektedir.
|
|
4
7
|
|
|
5
8
|
---
|
|
6
9
|
|
|
@@ -144,7 +147,7 @@ const quickPos = new QuickPos({
|
|
|
144
147
|
|
|
145
148
|
### Gelecek Özellikler
|
|
146
149
|
|
|
147
|
-
- 🏦 Yeni ödeme sağlayıcıları:
|
|
150
|
+
- 🏦 Yeni ödeme sağlayıcıları: Öneri'de Bulunun
|
|
148
151
|
- 🌐 Çoklu dil desteği
|
|
149
152
|
- 💸 Çoklu para birimi desteği
|
|
150
153
|
- 📝 Gelişmiş dökümantasyon
|
|
@@ -156,16 +159,11 @@ const quickPos = new QuickPos({
|
|
|
156
159
|
- [x] Cryptomus entegrasyonu
|
|
157
160
|
- [x] Payeer entegrasyonu
|
|
158
161
|
- [x] Papara entegrasyonu
|
|
159
|
-
- [
|
|
160
|
-
- [
|
|
161
|
-
- [
|
|
162
|
-
- [
|
|
163
|
-
- [
|
|
164
|
-
- [ ] Payizone entegrasyonu
|
|
165
|
-
- [ ] Weepay entegrasyonu
|
|
166
|
-
- [ ] Paynet entegrasyonu
|
|
167
|
-
- [ ] Stripe entegrasyonu
|
|
168
|
-
- [ ] PayPal entegrasyonu
|
|
162
|
+
- [x] İyzico entegrasyonu
|
|
163
|
+
- [x] Anypay entegrasyonu
|
|
164
|
+
- [x] EsnekPos entegrasyonu
|
|
165
|
+
- [x] PayMaya entegrasyonu
|
|
166
|
+
- [x] FedaPay entegrasyonu
|
|
169
167
|
|
|
170
168
|
---
|
|
171
169
|
|