/** * PayKash JavaScript SDK v1.0 * للربط مع مواقع الميرشنتس */ (function(window) { 'use strict'; // ============================================ // التكوين الرئيسي // ============================================ const PAYKASH_CONFIG = { apiUrl: 'https://paykash.com/api/v1', modalZIndex: 9999, pollInterval: 3000, // 3 ثواني maxPollAttempts: 300, // 15 دقيقة (300 * 3 = 900 ثانية) theme: { primary: '#1E3A8A', primaryLight: '#2563EB', primaryBright: '#3B82F6', accent: '#0EA5E9', success: '#10B981', warning: '#F59E0B', danger: '#EF4444', white: '#FFFFFF', gray50: '#F8FAFC', gray100: '#F1F5F9', gray200: '#E2E8F0', gray400: '#94A3B8', gray600: '#475569', gray900: '#0F172A' } }; // ============================================ // فئة PayKash الرئيسية // ============================================ class PayKash { constructor(options = {}) { this.storeId = options.storeId || this.getDataAttribute('store-id'); this.storeKey = options.storeKey || this.getDataAttribute('store-key'); this.lang = options.lang || this.getDataAttribute('lang') || 'ar'; this.theme = options.theme || this.getDataAttribute('theme') || 'light'; this.gateway = options.gateway || this.getDataAttribute('gateway') || 'vodafone_cash'; if (!this.storeId || !this.storeKey) { console.error('PayKash: store-id and store-key are required'); return; } this.apiUrl = PAYKASH_CONFIG.apiUrl; this.modal = null; this.pollInterval = null; this.pollAttempts = 0; // تهيئة الزر التلقائي إذا وجد this.initAutoButton(); } // جلب البيانات من data attributes getDataAttribute(name) { const script = document.querySelector(`script[data-${name}]`); return script ? script.getAttribute(`data-${name}`) : null; } // تهيئة الزر التلقائي initAutoButton() { const container = document.getElementById('paykash-payment-container'); if (container) { this.renderButton(container); } } // رسم الزر renderButton(container) { const button = document.createElement('button'); button.className = 'paykash-pay-button'; button.innerHTML = ` ادفع عبر ${this.getGatewayName(this.gateway)} `; button.addEventListener('click', () => { this.checkout({ amount: 100, // القيمة الافتراضية gateway: this.gateway, customer_ref: 'user_' + Date.now() }); }); container.appendChild(button); this.injectStyles(); } // اسم البوابة getGatewayName(gateway) { const names = { 'vodafone_cash': 'فودافون كاش', 'instapay': 'انستاباي', 'fawry': 'فوري', 'paymob': 'فيزا/ماستركارد' }; return names[gateway] || gateway; } // ============================================ // إنشاء طلب دفع // ============================================ async createOrder(params) { try { const response = await fetch(`${this.apiUrl}/orders/create.php`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Store-Key': this.storeKey, 'X-Api-Token': params.apiToken || '' }, body: JSON.stringify({ amount: params.amount, gateway: params.gateway || this.gateway, customer_ref: params.customer_ref, currency: params.currency || 'EGP', customer_phone: params.customer_phone || '', success_url: params.success_url || '', fail_url: params.fail_url || '' }) }); const data = await response.json(); if (!response.ok) { throw new Error(data.message || 'Failed to create order'); } return data; } catch (error) { console.error('PayKash Create Order Error:', error); throw error; } } // ============================================ // الاستعلام عن حالة الطلب // ============================================ async getOrderStatus(orderUuid) { try { const response = await fetch(`${this.apiUrl}/orders/status.php?uuid=${orderUuid}`, { headers: { 'X-Store-Key': this.storeKey } }); const data = await response.json(); if (!response.ok) { throw new Error(data.message || 'Failed to get status'); } return data; } catch (error) { console.error('PayKash Status Error:', error); throw error; } } // ============================================ // فتح نافذة الدفع // ============================================ openPaymentModal(order, callbacks = {}) { this.order = order; this.callbacks = callbacks; this.pollAttempts = 0; this.createModal(); this.startPolling(); } // إنشاء النافذة المنبثقة createModal() { // إزالة أي نافذة سابقة if (this.modal) { this.modal.remove(); } this.modal = document.createElement('div'); this.modal.className = 'paykash-modal'; this.modal.setAttribute('dir', this.lang === 'ar' ? 'rtl' : 'ltr'); const expiresIn = Math.max(0, Math.floor((new Date(this.order.expires_at) - new Date()) / 1000)); const minutes = Math.floor(expiresIn / 60); const seconds = expiresIn % 60; this.modal.innerHTML = `

${this.lang === 'ar' ? 'الدفع عبر' : 'Pay via'} ${this.getGatewayName(this.order.gateway)}

${this.lang === 'ar' ? 'المبلغ' : 'Amount'}
${this.order.amount_egp} EGP
${this.lang === 'ar' ? 'رقم المحفظة' : 'Wallet Number'}
${this.order.wallet_number}
${this.order.qr_code ? `
QR Code
` : ''}
${this.lang === 'ar' ? 'الوقت المتبقي' : 'Time Remaining'}
${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}
${this.lang === 'ar' ? 'في انتظار الدفع...' : 'Waiting for payment...'}
${this.order.instructions ? this.order.instructions.ar : `

1. افتح محفظة فودافون كاش

2. اختر "الدفع والتحويل"

3. أدخل الرقم أعلاه والمبلغ

4. أكد العملية

`}
`; document.body.appendChild(this.modal); // إضافة المستمعين this.modal.querySelector('.paykash-modal-close').addEventListener('click', () => this.closeModal()); this.modal.querySelector('.paykash-cancel-btn').addEventListener('click', () => this.cancelOrder()); // بدء المؤقت this.startTimer(expiresIn); } // بدء المؤقت startTimer(seconds) { const timerEl = document.getElementById('paykashTimer'); let remaining = seconds; this.timerInterval = setInterval(() => { remaining--; if (remaining <= 0) { clearInterval(this.timerInterval); timerEl.textContent = '00:00'; this.handleExpired(); return; } const minutes = Math.floor(remaining / 60); const secs = remaining % 60; timerEl.textContent = `${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`; }, 1000); } // بدء الاستعلام الدوري startPolling() { this.pollInterval = setInterval(async () => { this.pollAttempts++; if (this.pollAttempts > PAYKASH_CONFIG.maxPollAttempts) { this.stopPolling(); return; } try { const status = await this.getOrderStatus(this.order.order_uuid); if (status.status === 'confirmed') { this.stopPolling(); clearInterval(this.timerInterval); this.showSuccess(status); if (this.callbacks.onSuccess) { this.callbacks.onSuccess(status); } } else if (status.status === 'expired') { this.stopPolling(); clearInterval(this.timerInterval); this.handleExpired(); } } catch (error) { console.error('Polling error:', error); } }, PAYKASH_CONFIG.pollInterval); } // إيقاف الاستعلام stopPolling() { if (this.pollInterval) { clearInterval(this.pollInterval); this.pollInterval = null; } } // معالجة انتهاء الوقت handleExpired() { const statusEl = document.getElementById('paykashStatus'); statusEl.innerHTML = `
${this.lang === 'ar' ? 'انتهت مهلة الدفع' : 'Payment expired'}
`; if (this.callbacks.onExpire) { this.callbacks.onExpire(); } } // عرض نجاح showSuccess(order) { const statusEl = document.getElementById('paykashStatus'); statusEl.innerHTML = `
${this.lang === 'ar' ? 'تم تأكيد الدفع بنجاح' : 'Payment confirmed'}
`; setTimeout(() => this.closeModal(), 3000); } // إغلاق النافذة closeModal() { this.stopPolling(); clearInterval(this.timerInterval); if (this.modal) { this.modal.remove(); this.modal = null; } } // إلغاء الطلب async cancelOrder() { try { await fetch(`${this.apiUrl}/orders/cancel.php`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Store-Key': this.storeKey }, body: JSON.stringify({ uuid: this.order.order_uuid }) }); this.closeModal(); if (this.callbacks.onCancel) { this.callbacks.onCancel(); } } catch (error) { console.error('Cancel error:', error); this.closeModal(); } } // ============================================ // نسخ رقم المحفظة // ============================================ static copyWalletNumber() { const walletNumber = document.getElementById('paykashWalletNumber'); const text = walletNumber.innerText; navigator.clipboard.writeText(text).then(() => { const btn = document.querySelector('.paykash-copy-btn'); const originalText = btn.innerHTML; btn.innerHTML = ' تم النسخ!'; setTimeout(() => { btn.innerHTML = originalText; }, 2000); }); } // ============================================ // الدفع السريع // ============================================ async checkout(params) { try { const order = await this.createOrder(params); this.openPaymentModal(order, params); } catch (error) { console.error('Checkout error:', error); alert(error.message); } } // ============================================ // إضافة الأنماط // ============================================ injectStyles() { if (document.getElementById('paykash-styles')) { return; } const style = document.createElement('style'); style.id = 'paykash-styles'; style.textContent = ` .paykash-pay-button { background: linear-gradient(135deg, ${PAYKASH_CONFIG.theme.primary}, ${PAYKASH_CONFIG.theme.primaryLight}); color: ${PAYKASH_CONFIG.theme.white}; border: none; padding: 12px 30px; border-radius: 50px; font-size: 16px; font-weight: 600; cursor: pointer; transition: all 0.3s ease; box-shadow: 0 5px 15px rgba(30, 58, 138, 0.3); font-family: 'Tajawal', sans-serif; display: inline-flex; align-items: center; justify-content: center; } .paykash-pay-button:hover { transform: translateY(-2px); box-shadow: 0 8px 25px rgba(30, 58, 138, 0.4); } .paykash-modal { position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: ${PAYKASH_CONFIG.modalZIndex}; display: flex; align-items: center; justify-content: center; font-family: 'Tajawal', sans-serif; } .paykash-modal-overlay { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); backdrop-filter: blur(5px); } .paykash-modal-content { position: relative; background: ${PAYKASH_CONFIG.theme.white}; border-radius: 30px; width: 90%; max-width: 450px; max-height: 90vh; overflow-y: auto; box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); animation: paykash-modal-slide 0.3s ease; } @keyframes paykash-modal-slide { from { opacity: 0; transform: translateY(-30px); } to { opacity: 1; transform: translateY(0); } } .paykash-modal-header { background: ${PAYKASH_CONFIG.theme.primary}; color: ${PAYKASH_CONFIG.theme.white}; padding: 20px 30px; border-radius: 30px 30px 0 0; display: flex; align-items: center; justify-content: space-between; } .paykash-modal-header h2 { margin: 0; font-size: 20px; font-weight: 700; } .paykash-modal-close { background: none; border: none; color: ${PAYKASH_CONFIG.theme.white}; font-size: 28px; cursor: pointer; opacity: 0.8; transition: opacity 0.2s ease; } .paykash-modal-close:hover { opacity: 1; } .paykash-modal-body { padding: 30px; } .paykash-amount { text-align: center; margin-bottom: 25px; } .paykash-amount-label { color: ${PAYKASH_CONFIG.theme.gray400}; font-size: 14px; margin-bottom: 5px; } .paykash-amount-value { font-size: 48px; font-weight: 700; color: ${PAYKASH_CONFIG.theme.gray900}; } .paykash-amount-value span { font-size: 18px; color: ${PAYKASH_CONFIG.theme.gray400}; } .paykash-wallet { background: ${PAYKASH_CONFIG.theme.gray50}; border: 2px dashed ${PAYKASH_CONFIG.theme.primary}; border-radius: 16px; padding: 20px; text-align: center; margin-bottom: 20px; } .paykash-wallet-label { color: ${PAYKASH_CONFIG.theme.gray600}; margin-bottom: 10px; } .paykash-wallet-number { font-size: 24px; font-weight: 700; color: ${PAYKASH_CONFIG.theme.primary}; margin-bottom: 10px; direction: ltr; } .paykash-copy-btn { background: ${PAYKASH_CONFIG.theme.white}; border: 2px solid ${PAYKASH_CONFIG.theme.primary}; color: ${PAYKASH_CONFIG.theme.primary}; padding: 8px 20px; border-radius: 50px; font-size: 14px; cursor: pointer; transition: all 0.2s ease; } .paykash-copy-btn:hover { background: ${PAYKASH_CONFIG.theme.primary}; color: ${PAYKASH_CONFIG.theme.white}; } .paykash-qr { text-align: center; margin: 20px 0; } .paykash-qr img { width: 150px; height: 150px; border-radius: 15px; } .paykash-timer { text-align: center; margin: 20px 0; } .paykash-timer-label { color: ${PAYKASH_CONFIG.theme.gray400}; font-size: 14px; margin-bottom: 5px; } .paykash-timer-value { font-size: 32px; font-weight: 700; color: ${PAYKASH_CONFIG.theme.danger}; } .paykash-status { margin: 20px 0; padding: 15px; border-radius: 12px; text-align: center; } .paykash-status-pending { color: ${PAYKASH_CONFIG.theme.warning}; } .paykash-status-success { background: ${PAYKASH_CONFIG.theme.success}; color: white; padding: 15px; border-radius: 12px; } .paykash-status-expired { background: ${PAYKASH_CONFIG.theme.danger}; color: white; padding: 15px; border-radius: 12px; } .paykash-instructions { background: ${PAYKASH_CONFIG.theme.gray50}; border-radius: 12px; padding: 15px; margin-top: 20px; } .paykash-instructions p { margin: 5px 0; color: ${PAYKASH_CONFIG.theme.gray600}; } .paykash-modal-footer { padding: 20px 30px; border-top: 1px solid ${PAYKASH_CONFIG.theme.gray200}; text-align: center; } .paykash-cancel-btn { background: ${PAYKASH_CONFIG.theme.gray200}; border: none; color: ${PAYKASH_CONFIG.theme.gray600}; padding: 10px 25px; border-radius: 50px; font-size: 14px; cursor: pointer; transition: all 0.2s ease; } .paykash-cancel-btn:hover { background: ${PAYKASH_CONFIG.theme.gray400}; color: white; } `; document.head.appendChild(style); } } // ============================================ // تصدير للاستخدام العام // ============================================ window.PayKash = PayKash; // تهيئة تلقائية إذا وجدت العناصر document.addEventListener('DOMContentLoaded', function() { const script = document.querySelector('script[data-store-id]'); if (script) { window.paykash = new PayKash(); } }); })(window);