quickpos 1.0.913 → 1.0.914
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/lib/paytr_eft.js +156 -0
- package/package.json +1 -1
package/lib/paytr_eft.js
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
const crypto = require('crypto');
|
|
2
|
+
const axios = require('axios');
|
|
3
|
+
|
|
4
|
+
class PayTR {
|
|
5
|
+
/**
|
|
6
|
+
* PayTR Kurucu Metodu
|
|
7
|
+
* @param {Object} config - Yapılandırma ayarları
|
|
8
|
+
* @param {string} config.merchantId - Mağaza No
|
|
9
|
+
* @param {string} config.merchantKey - Mağaza Parola
|
|
10
|
+
* @param {string} config.merchantSalt - Mağaza Gizli Anahtar
|
|
11
|
+
* @param {boolean} [config.testMode=false] - Test modu (true/false)
|
|
12
|
+
* @param {boolean} [config.debugOn=false] - Hata ayıklama modu
|
|
13
|
+
*/
|
|
14
|
+
constructor(config) {
|
|
15
|
+
this.config = config || {};
|
|
16
|
+
|
|
17
|
+
// Zorunlu alan kontrolü
|
|
18
|
+
const requiredFields = ['merchantId', 'merchantKey', 'merchantSalt'];
|
|
19
|
+
for (let field of requiredFields) {
|
|
20
|
+
if (!this.config[field]) throw new Error(`Missing required field: ${field}`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
this.merchantId = this.config.merchantId;
|
|
24
|
+
this.merchantKey = this.config.merchantKey;
|
|
25
|
+
this.merchantSalt = this.config.merchantSalt;
|
|
26
|
+
this.testMode = this.config.testMode ? '1' : '0';
|
|
27
|
+
this.debugOn = this.config.debugOn ? '1' : '0';
|
|
28
|
+
|
|
29
|
+
// iframe namespace'i tanımlama (örnekteki kullanıma uygun olması için)
|
|
30
|
+
this.iframe = {
|
|
31
|
+
createToken: this.createIframeToken.bind(this)
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* iFrame Token Oluşturma (EFT ve Kredi Kartı için)
|
|
37
|
+
* @param {Object} params - Ödeme parametreleri
|
|
38
|
+
*/
|
|
39
|
+
async createIframeToken(params) {
|
|
40
|
+
try {
|
|
41
|
+
const userBasket = JSON.stringify(params.userBasket);
|
|
42
|
+
const userIp = params.userIp;
|
|
43
|
+
const merchantOid = params.merchantOid;
|
|
44
|
+
const email = params.email;
|
|
45
|
+
const paymentAmount = params.paymentAmount.toString(); // Kuruş cinsinden (Örn: 10.00 TL -> 1000)
|
|
46
|
+
const currency = params.currency || 'TL';
|
|
47
|
+
const noInstallment = params.noInstallment ? '1' : '0';
|
|
48
|
+
const maxInstallment = params.maxInstallment || '0';
|
|
49
|
+
const paymentType = params.paymentType || 'card'; // 'eft' veya 'card'
|
|
50
|
+
|
|
51
|
+
// PayTR Token Oluşturma Sırası (Dökümantasyona Göre)
|
|
52
|
+
// merchant_id + user_ip + merchant_oid + email + payment_amount + user_basket + no_installment + max_installment + currency + test_mode
|
|
53
|
+
const rawString = `${this.merchantId}${userIp}${merchantOid}${email}${paymentAmount}${userBasket}${noInstallment}${maxInstallment}${currency}${this.testMode}`;
|
|
54
|
+
|
|
55
|
+
const paytrToken = this.generateToken(rawString);
|
|
56
|
+
|
|
57
|
+
// API'ye gönderilecek veri
|
|
58
|
+
const formData = new URLSearchParams();
|
|
59
|
+
formData.append('merchant_id', this.merchantId);
|
|
60
|
+
formData.append('user_ip', userIp);
|
|
61
|
+
formData.append('merchant_oid', merchantOid);
|
|
62
|
+
formData.append('email', email);
|
|
63
|
+
formData.append('payment_amount', paymentAmount);
|
|
64
|
+
formData.append('paytr_token', paytrToken);
|
|
65
|
+
formData.append('user_basket', userBasket);
|
|
66
|
+
formData.append('debug_on', this.debugOn);
|
|
67
|
+
formData.append('no_installment', noInstallment);
|
|
68
|
+
formData.append('max_installment', maxInstallment);
|
|
69
|
+
formData.append('user_name', params.userName);
|
|
70
|
+
formData.append('user_address', params.userAddress);
|
|
71
|
+
formData.append('user_phone', params.userPhone);
|
|
72
|
+
formData.append('merchant_ok_url', params.merchantOkUrl);
|
|
73
|
+
formData.append('merchant_fail_url', params.merchantFailUrl);
|
|
74
|
+
formData.append('timeout_limit', params.timeoutLimit || '30');
|
|
75
|
+
formData.append('currency', currency);
|
|
76
|
+
formData.append('test_mode', this.testMode);
|
|
77
|
+
formData.append('payment_type', paymentType); // 'eft' gönderimi için kritik
|
|
78
|
+
|
|
79
|
+
// Opsiyonel banka seçimi (Sadece payment_type='eft' ise işe yarar)
|
|
80
|
+
if (params.bank) {
|
|
81
|
+
formData.append('bank', params.bank);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Opsiyonel: Lang
|
|
85
|
+
if (params.lang) {
|
|
86
|
+
formData.append('lang', params.lang);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const response = await axios({
|
|
90
|
+
method: 'POST',
|
|
91
|
+
url: 'https://www.paytr.com/odeme/api/get-token',
|
|
92
|
+
headers: {
|
|
93
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
94
|
+
},
|
|
95
|
+
data: formData
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const result = response.data;
|
|
99
|
+
|
|
100
|
+
if (result.status === 'success') {
|
|
101
|
+
return {
|
|
102
|
+
status: 'success',
|
|
103
|
+
token: result.token
|
|
104
|
+
};
|
|
105
|
+
} else {
|
|
106
|
+
throw new Error(result.reason || 'PayTR Token alma hatası');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
} catch (error) {
|
|
110
|
+
if (error.response) {
|
|
111
|
+
throw new Error(`PayTR API Error: ${error.response.data.reason || error.response.statusText}`);
|
|
112
|
+
}
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Callback (Bildirim) Doğrulama
|
|
119
|
+
* PayTR'den gelen POST isteğinin hash'ini doğrular.
|
|
120
|
+
* @param {Object} reqBody - Express/Http request body
|
|
121
|
+
*/
|
|
122
|
+
validateCallback(reqBody) {
|
|
123
|
+
const { merchant_oid, status, total_amount, hash } = reqBody;
|
|
124
|
+
|
|
125
|
+
// Hash Oluşturma Sırası:
|
|
126
|
+
// merchant_oid + merchant_salt + status + total_amount
|
|
127
|
+
const rawString = `${merchant_oid}${this.merchantSalt}${status}${total_amount}`;
|
|
128
|
+
const generatedHash = this.generateToken(rawString);
|
|
129
|
+
|
|
130
|
+
if (hash === generatedHash) {
|
|
131
|
+
return {
|
|
132
|
+
success: true,
|
|
133
|
+
merchantOid: merchant_oid,
|
|
134
|
+
status: status,
|
|
135
|
+
totalAmount: total_amount
|
|
136
|
+
};
|
|
137
|
+
} else {
|
|
138
|
+
return {
|
|
139
|
+
success: false,
|
|
140
|
+
error: 'Hash mismatch'
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Helper: HMAC-SHA256 Token Üretici
|
|
147
|
+
*/
|
|
148
|
+
generateToken(data) {
|
|
149
|
+
return crypto
|
|
150
|
+
.createHmac('sha256', this.merchantKey)
|
|
151
|
+
.update(data + this.merchantSalt)
|
|
152
|
+
.digest('base64');
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
module.exports = PayTR;
|