/**
* 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' ? 'المبلغ' : 'Amount'}
${this.order.amount_egp} EGP
${this.lang === 'ar' ? 'رقم المحفظة' : 'Wallet Number'}
${this.order.wallet_number}
${this.order.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);