Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions PROVIDERS-DETAILS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,27 @@ Bu dokümantasyon, QuickPos tarafından desteklenen tüm 48 ödeme sağlayıcıs

---

### 🌐 Stripe (Global)
- **Website**: https://stripe.com
- **Desteklenen Ülkeler**: 46+ ülke
- **Para Birimleri**: 135+ para birimi
- **Client Oluşturma**:
```javascript
{
secretKey: 'YOUR_SECRET_KEY',
webhookSecret: 'YOUR_WEBHOOK_SECRET' // Opsiyonel, webhook doğrulaması için
}
```
- **createPayment Gereken Alanlar**:
- `amount`: Ödeme tutarı
- `currency`: Para birimi
- `orderId`: Benzersiz sipariş ID
- `callback_link`: Başarılı URL yönlendirmesi
- `email`: Müşteri email
- `name`: Ürün açıklaması

---

### 🌐 Amazon Pay (Global)
- **Website**: https://pay.amazon.com
- **Desteklenen Ülkeler**: ABD, AB, Japonya, Hindistan
Expand Down Expand Up @@ -1465,15 +1486,15 @@ Bu dokümantasyon, QuickPos tarafından desteklenen tüm 48 ödeme sağlayıcıs
- **Orta Doğu & Afrika**: 17 provider
- **Avrupa**: 5 provider
- **Latin Amerika**: 2 provider
- **Global**: 13 provider
- **Global**: 14 provider
- **Kripto Para**: 12 provider

### Para Birimi Çeşitliliği
- **Toplam Desteklenen Para Birimi**: 100+
- **En Çok Kullanılan**: USD, EUR, INR, IDR, TRY

### Toplam İstatistikler
- **Toplam Provider**: 48
- **Toplam Provider**: 49
- **Desteklenen Ülke**: 200+
- **Kripto Para Desteği**: 2000+ coin
- **Yerel Ödeme Yöntemi**: 500+
Expand Down Expand Up @@ -1541,4 +1562,4 @@ Bu dokümantasyon QuickPos v1.3.0 için hazırlanmıştır.

**Son Güncelleme**: 2024
**Versiyon**: 1.3.0
**Toplam Provider**: 48
**Toplam Provider**: 49
149 changes: 149 additions & 0 deletions examples/example-stripe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
const Stripe = require('../lib/stripe');
const QuickPos = require('../app');
const express = require('express');
const bodyParser = require('body-parser');

// QuickPos yapılandırması
const quickPos = new QuickPos({
providers: {
stripe: {
secretKey: 'sk_test_YOUR_TEST_SECRET_KEY'
}
}
});

// Stripe sağlayıcısını al
let stripe = quickPos.providers['stripe'];

// Express uygulaması oluştur
const app = express();
// Webhook doğrulaması için raw body kaydetmek gerekebilir (Stripe özel durumu)
app.use(express.json({
verify: (req, res, buf) => {
req.rawBody = buf;
}
}));
app.use(express.urlencoded({ extended: true }));
app.use(express.static('public'));

// Ana sayfa - Basit form
app.get('/', (req, res) => {
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>Stripe Ödeme</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body { font-family: Arial; margin: 0; padding: 20px; background: #f5f5f5; }
.container { max-width: 500px; margin: 0 auto; background: white; padding: 20px; border-radius: 5px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
h1 { margin-top: 0; }
label { display: block; margin-bottom: 5px; }
input, select { width: 100%; padding: 8px; margin-bottom: 15px; border: 1px solid #ddd; border-radius: 3px; }
button { background: #635bff; color: white; border: none; padding: 10px 15px; border-radius: 3px; cursor: pointer; width: 100%; }
</style>
</head>
<body>
<div class="container">
<h1>Stripe ile Ödeme Oluştur</h1>
<form action="/checkout" method="POST">
<label for="amount">Tutar:</label>
<input type="text" id="amount" name="amount" value="99.99" required>

<label for="currency">Para Birimi:</label>
<select id="currency" name="currency">
<option value="USD">USD - Amerikan Doları</option>
<option value="EUR">EUR - Euro</option>
<option value="TRY">TRY - Türk Lirası</option>
</select>

<label for="description">Açıklama:</label>
<input type="text" id="description" name="description" value="Premium Üyelik" required>

<button type="submit">Ödeme Sayfasına Git</button>
</form>
</div>
</body>
</html>
`);
});

// Ödeme sayfası - Stripe Checkout Session oluşturur
app.post('/checkout', async (req, res) => {
try {
const { amount, currency, description } = req.body;

const payment = await stripe.createPayment({
amount: amount || '99.99',
currency: currency || 'USD',
description: description || 'Premium Üyelik',
orderId: 'order-' + Date.now(),
successUrl: \`http://\${req.headers.host}/success\`,
cancelUrl: \`http://\${req.headers.host}/cancel\`
});

// Stripe ödeme sayfasına yönlendir
res.redirect(payment.paymentUrl);
} catch (error) {
res.status(500).send(`
<div style="text-align:center; padding:20px;">
<h1>Hata</h1>
<p>\${error.message}</p>
<a href="/">Geri Dön</a>
</div>
`);
}
});

// İptal sayfası - basit HTML
app.get('/cancel', (req, res) => {
res.send(`
<div style="text-align:center; padding:20px;">
<h1>Ödeme İptal Edildi</h1>
<p>İşlem iptal edildi, herhangi bir ücret tahsil edilmedi.</p>
<a href="/">Geri Dön</a>
</div>
`);
});

// Başarılı ödeme sayfası
app.get('/success', (req, res) => {
const { session_id, order_id } = req.query;

res.send(`
<div style="text-align:center; padding:20px;">
<h1>Ödeme Başarılı</h1>
<p>Sipariş ID: \${order_id || 'N/A'}</p>
<p>Stripe Session ID: \${session_id || 'N/A'}</p>
<p style="color:green; font-weight:bold;">Ödeme durumu: Başarılı</p>
<p>İşlem tarihi: \${new Date().toLocaleString('tr-TR')}</p>
<a href="/">Yeni Ödeme</a>
</div>
`);
});

// Stripe webhook handler
app.post('/stripe-webhook', async (req, res) => {
try {
// We pass req to handleCallback to allow signature verification
const result = await stripe.handleCallback(req.body, req);

if (result.success && result.status === 'completed') {
console.log('Ödeme başarıyla tamamlandı:', result.orderId, result.amount, result.currency);
// Veritabanını güncelleyebilir veya email gönderebilirsiniz
}

res.status(200).send('OK');
} catch (error) {
console.error('Webhook işleme hatası:', error.message);
res.status(400).send(\`Webhook Error: \${error.message}\`);
}
});

// Sunucuyu başlat
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(\`Sunucu çalışıyor: http://localhost:\${PORT}\`);
console.log(\`Örnek ödeme sayfası: http://localhost:\${PORT}\`);
});
118 changes: 118 additions & 0 deletions lib/stripe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
const StripeSDK = require('stripe');

class Stripe {
constructor(config) {
this.config = config || {};
if (!config.secretKey) {
throw new Error('Missing required field: secretKey');
}

this.stripe = StripeSDK(config.secretKey);
this.endpointSecret = config.webhookSecret || null;
}

/**
* Create a new payment (Checkout Session)
* @param {Object} paymentData - Payment data
* @returns {Promise<Object>} - Payment result containing payment URL
*/
async createPayment(paymentData) {
try {
if (!paymentData.amount || !paymentData.currency) {
throw new Error('Tutar (amount) ve para birimi (currency) gerekli');
}

const orderId = paymentData.orderId || `order-${Date.now()}`;
const successUrl = paymentData.successUrl || paymentData.callback_link || 'http://localhost:3000/success';
const cancelUrl = paymentData.cancelUrl || 'http://localhost:3000/cancel';

// Ensure amount is properly formatted to cents for Stripe
const unitAmount = Math.round(parseFloat(paymentData.amount) * 100);

const sessionConfig = {
payment_method_types: ['card'],
line_items: [
{
price_data: {
currency: paymentData.currency.toLowerCase(),
product_data: {
name: paymentData.name || paymentData.description || 'QuickPos Payment',
},
unit_amount: unitAmount,
},
quantity: 1,
},
],
mode: 'payment',
success_url: `${successUrl}?session_id={CHECKOUT_SESSION_ID}&order_id=${orderId}`,
cancel_url: cancelUrl,
client_reference_id: orderId,
};

if (paymentData.email) {
sessionConfig.customer_email = paymentData.email;
}

const session = await this.stripe.checkout.sessions.create(sessionConfig);

return {
success: true,
paymentUrl: session.url,
transactionId: session.id,
orderId: orderId,
amount: paymentData.amount,
currency: paymentData.currency
};
} catch (error) {
throw new Error(`Stripe payment creation failed: ${error.message}`);
}
}

/**
* Handle callback/webhook from Stripe
* @param {Object} callbackData - Webhook data (req.body)
* @param {Object} req - Request object (used to verify signature if endpointSecret exists)
* @returns {Promise<Object>} - Callback result
*/
async handleCallback(callbackData, req) {
try {
let event = callbackData;

// Verify webhook signature if endpointSecret is provided
if (this.endpointSecret && req && req.headers && req.headers['stripe-signature']) {
const sig = req.headers['stripe-signature'];
try {
// req.rawBody is needed for stripe webhook verification, assume it's available or we fallback to event
event = this.stripe.webhooks.constructEvent(req.rawBody || JSON.stringify(callbackData), sig, this.endpointSecret);
} catch (err) {
throw new Error(`Webhook Error: ${err.message}`);
}
}

if (event.type === 'checkout.session.completed') {
const session = event.data.object;

return {
success: true,
status: 'completed',
transactionId: session.payment_intent || session.id,
orderId: session.client_reference_id,
amount: session.amount_total / 100,
currency: (session.currency || '').toUpperCase(),
rawData: event
};
}

return {
success: false,
status: 'pending_or_other',
event: event.type,
rawData: event
};
} catch (error) {
throw new Error(`Stripe callback handling failed: ${error.message}`);
}
}
}

module.exports = Stripe;
22 changes: 20 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "quickpos",
"version": "1.0.924",
"version": "1.3.1",
"main": "app.js",
"scripts": {
"test": "node test.js"
Expand Down Expand Up @@ -133,6 +133,7 @@
"paymaya-integration": "^1.0.4",
"paymentwall": "^2.1.1",
"payu-websdk": "^1.2.0",
"stripe": "^22.3.0",
"uuid": "^9.0.1"
}
}
Loading