quickpos
Version:
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, Heleket, Paydisini sağlayıcısını desteklemektedir ve gelecekte birçok
294 lines (257 loc) • 8.87 kB
JavaScript
const axios = require('axios');
const crypto = require('crypto');
const querystring = require('querystring');
class Paydisini {
constructor(config) {
this.config = config || {};
const requiredFields = ['apiKey'];
for (let field of requiredFields) {
if (!config[field]) throw new Error(`Missing required field: ${field}`);
}
this.apiKey = config.apiKey;
this.baseUrl = config.baseUrl || 'https://api.paydisini.co.id/v1/';
this.debug = config.debug || false;
}
async createPayment(paymentDetails) {
try {
// Zorunlu alanları kontrol et
const requiredData = ['amount', 'uniqueCode', 'note'];
for (let data of requiredData) {
if (!paymentDetails[data]) throw new Error(`Missing required data: ${data}`);
}
// Default değerler ayarla
const service = paymentDetails.service || '11'; // Default QRIS
const validTime = paymentDetails.validTime || '1800';
const typeFee = paymentDetails.typeFee || '1';
const paymentGuide = paymentDetails.paymentGuide !== undefined ? paymentDetails.paymentGuide : true;
const returnUrl = paymentDetails.returnUrl || '';
// İmza oluştur
const signature = this.generateSignature(
this.apiKey,
paymentDetails.uniqueCode,
service,
paymentDetails.amount
);
// Form verilerini hazırla
const formData = {
key: this.apiKey,
request: 'new',
unique_code: paymentDetails.uniqueCode,
service: service,
amount: paymentDetails.amount,
note: paymentDetails.note,
valid_time: validTime,
type_fee: typeFee,
payment_guide: paymentGuide ? 'TRUE' : 'FALSE',
signature: signature,
return_url: returnUrl
};
if (this.debug) {
console.log('Paydisini request data:', formData);
}
// API isteği yap
const response = await axios({
method: 'post',
url: this.baseUrl,
data: querystring.stringify(formData),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36',
'Accept': 'application/json, text/plain, */*',
'Accept-Language': 'en-US,en;q=0.9'
}
});
const responseData = response.data;
if (this.debug) {
console.log('Paydisini response:', responseData);
}
if (responseData.success) {
return {
status: 'success',
data: {
uniqueCode: paymentDetails.uniqueCode,
paymentId: responseData.id,
trxid: responseData.trxid,
amount: responseData.amount,
service: responseData.payment || responseData.service,
serviceName: responseData.service_name,
note: responseData.note,
url: responseData.url || responseData.payment_url,
expired: responseData.expired,
qrCode: responseData.qrcode_url,
qrString: responseData.qrstring,
payNumber: responseData.pay_number,
total: responseData.total
}
};
} else {
return {
status: 'fail',
message: responseData.msg || 'Payment creation failed',
error: responseData
};
}
} catch (error) {
if (error.response) {
if (this.debug) {
console.error('Paydisini API error response:', error.response.data);
}
throw new Error(`Paydisini API error: ${JSON.stringify(error.response.data)}`);
} else if (error.request) {
throw new Error('No response received from Paydisini API');
} else {
throw new Error(`Error in Paydisini payment creation: ${error.message}`);
}
}
}
// İşlem durumu sorgulama
async checkStatus(transactionId) {
try {
const signature = this.generateSignature(
this.apiKey,
transactionId,
'',
''
);
const formData = {
key: this.apiKey,
request: 'status',
trxid: transactionId,
signature: signature
};
if (this.debug) {
console.log('Paydisini status check request:', formData);
}
const response = await axios({
method: 'post',
url: this.baseUrl,
data: querystring.stringify(formData),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
if (this.debug) {
console.log('Paydisini status response:', response.data);
}
return response.data;
} catch (error) {
if (this.debug) {
console.error('Paydisini status check error:', error);
}
throw new Error(`Error checking transaction status: ${error.message}`);
}
}
async handleCallback(callbackData) {
try {
if (this.debug) {
console.log('Processing Paydisini callback data:', callbackData);
}
// Gerekli alanları kontrol et
if (!callbackData.key || !callbackData.unique_code || !callbackData.status || !callbackData.signature) {
throw new Error('Missing required callback parameters');
}
// Gelen anahtarı kontrol et
if (callbackData.key !== this.apiKey) {
throw new Error('Invalid API key in callback');
}
// IP adresini beyaz listeden kontrol etmek için (opsiyonel)
// const whitelistedIPs = ['45.87.242.188']; // Paydisini IP adresi
// if (!whitelistedIPs.includes(ipAddress)) {
// throw new Error('Invalid IP address for callback');
// }
// İmzayı doğrula
const expectedSignature = this.generateCallbackSignature(
this.apiKey,
callbackData.unique_code,
'CallbackStatus'
);
if (callbackData.signature !== expectedSignature) {
throw new Error('Invalid signature in callback');
}
// İşlem durumunu kontrol et
if (callbackData.status === 'Success') {
return {
status: 'success',
orderId: callbackData.unique_code,
trxid: callbackData.trxid || '',
amount: parseFloat(callbackData.amount || '0'),
service: callbackData.payment || callbackData.service || '',
serviceName: callbackData.service_name || '',
date: callbackData.date || new Date().toISOString()
};
} else {
throw new Error(`Payment failed with status: ${callbackData.status}`);
}
} catch (error) {
if (this.debug) {
console.error('Callback handling error:', error);
}
throw new Error(`Error in Paydisini callback handling: ${error.message}`);
}
}
// Ödeme oluşturma için imza
generateSignature(apiKey, uniqueCode, service, amount) {
return crypto
.createHash('md5')
.update(apiKey + uniqueCode + service + amount)
.digest('hex');
}
// Callback için imza
generateCallbackSignature(apiKey, uniqueCode, suffix) {
return crypto
.createHash('md5')
.update(apiKey + uniqueCode + suffix)
.digest('hex');
}
// Servisleri listele
async getServices() {
try {
const signature = crypto
.createHash('md5')
.update(this.apiKey + 'services')
.digest('hex');
const formData = {
key: this.apiKey,
request: 'services',
signature: signature
};
const response = await axios({
method: 'post',
url: this.baseUrl,
data: querystring.stringify(formData),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
return response.data;
} catch (error) {
throw new Error(`Error getting services: ${error.message}`);
}
}
// Bakiye sorgulama
async getBalance() {
try {
const signature = crypto
.createHash('md5')
.update(this.apiKey + 'balance')
.digest('hex');
const formData = {
key: this.apiKey,
request: 'balance',
signature: signature
};
const response = await axios({
method: 'post',
url: this.baseUrl,
data: querystring.stringify(formData),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
return response.data;
} catch (error) {
throw new Error(`Error checking balance: ${error.message}`);
}
}
}
module.exports = Paydisini;