officeguy / laravel-sumit-gateway
Laravel package for SUMIT payment gateway with Filament integration - 1:1 port from WooCommerce (Laravel 12 Compatible)
Installs: 53
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 3
pkg:composer/officeguy/laravel-sumit-gateway
Requires
- php: ^8.2
- filament/filament: ^4.0
- guzzlehttp/guzzle: ^7.0
- laravel/framework: ^12.0
Requires (Dev)
- orchestra/testbench: ^10.0
- phpunit/phpunit: ^11.0|^12.0
- dev-main
- v1.9.0
- v1.8.11
- v1.8.10
- v1.8.9
- v1.8.8
- v1.8.7
- v1.8.6
- v1.8.5
- v1.8.4
- v1.8.3
- v1.8.2
- v1.8.1
- v1.8.0
- v1.7.2
- v1.7.1
- v1.7.0
- v1.6.2
- v1.6.1
- v1.6.0
- v1.5.0
- v1.4.2
- v1.4.1
- v1.4.0
- v1.3.2
- v1.3.1
- v1.3.0
- v1.2.4
- v1.2.3
- v1.2.2
- v1.2.1
- v1.2.0
- v1.1.7
- v1.1.6
- v1.1.5
- v1.1.4
- v1.1.3
- v1.1.2
- v1.1.1
- v1.1.0
- v1.0.6
- v1.0.5
- v1.0.4
- V1.0.3
- V1.0.2
- V1.0.1
- v1.0.0
- V1.0b
- dev-docs/add-claude-guide
- dev-copilot/complete-missing-definitions
- dev-copilot/fix-code-for-filament-v4
- dev-copilot/document-api-endpoints
- dev-copilot/add-product-purchase-page-view
- dev-copilot/update-readme-documentation
- dev-copilot/fill-gaps-woocommerce-laravel
- dev-copilot/remove-unused-files-and-unzip
- dev-copilot/remove-all-files-and-folders
- dev-copilot/fix-navigation-icon-type-error-again
- dev-copilot/fix-navigation-icon-type-error
- dev-copilot/fix-navigation-group-type-error
- dev-copilot/upgrade-sumit-payment-gateway
- dev-copilot/move-package-files-to-main
This package is auto-updated.
Last update: 2025-12-01 13:45:46 UTC
README
Clone 1:1 של התוסף WooCommerce woo-payment-gateway-officeguy עבור Laravel.
- תשלומים בכרטיס אשראי (PCI modes: no/redirect/yes)
- תשלומי Bit
- תמיכה ב‑Tokens (J2/J5), Authorize Only, תשלומים (עד 36), recurring
- מסמכים (חשבונית/קבלה/תרומה), שילוב PayPal/BlueSnap receipts
- Multivendor & CartFlows מקבילים (לפי מפרט המקור)
- סנכרון מלאי (12/24 שעות/Checkout), ווידג'ט דשבורד (למימוש עתידי)
- ממשק ניהול Filament v4
- דפי לקוח Filament להצגת טרנזקציות/מסמכים/אמצעי תשלום
תוכן עניינים
- התקנה
- הגדרות
- עמוד תשלום
- שדות ת"ז ו-CVV
- מסמכים
- סוגי תשלומים
- תשלומים מחולקים
- תפיסת מסגרת (Authorize Only)
- מצב טסט
- שמירת פרטי אשראי
- הוראות קבע ומנויים
- מלאי
- Bit ו-Redirect
- מיזוג לקוחות
- Multi-Vendor
- תרומות
- Upsell / CartFlows
- אירועים
- Custom Event Webhooks
- Webhook Events Resource
- קבלת Webhooks מ-SUMIT
- מיגרציות נתונים
- בדיקות
- קבצים לפרסום
התקנה
composer require officeguy/laravel-sumit-gateway
php artisan migrate # יריץ את כל מיגרציות החבילה
אם תרצה להעתיק גם קונפיג/מיגרציות/תצוגות:
--tag=officeguy-config,--tag=officeguy-migrations,--tag=officeguy-views. ראה קבצים לפרסום לפרטים נוספים.
הגדרות
כל ההגדרות נשמרות במסד הנתונים (טבלת officeguy_settings) עם fallback לקובץ config. ניתן לערוך דרך Filament (עמוד Gateway Settings) או בקוד באמצעות SettingsService.
גישה לעמוד ההגדרות
נווטו ל-SUMIT Gateway > Gateway Settings ב-Admin Panel.
שדות עיקריים
- מפתחות חברה: company_id, private_key, public_key
- PCI mode:
no(PaymentsJS),redirect,yes(PCI server) - תשלומים: max_payments, min_amount_for_payments, min_amount_per_payment
- Authorize Only: דגל + אחוז תוספת + מינימום תוספת
- מסמכים: draft_document, email_document, create_order_document, merge_customers, automatic_languages
- Tokens: support_tokens, token_param (J2/J5)
- Bit: bit_enabled
- מלאי: stock_sync_freq (none/12/24), checkout_stock_sync
- לוגים: logging, log_channel, ssl_verify
- מסלולי Redirect: routes.success, routes.failed
- Order binding: order.model או order.resolver (callable)
התאמת נתיבים (Route Configuration)
ניתן להתאים את כל נתיבי החבילה ישירות מה-Admin Panel:
ב-Admin Panel: נווטו ל-SUMIT Gateway > Gateway Settings > Route Configuration
נתיבים ניתנים להתאמה:
| הגדרה | ברירת מחדל | תיאור |
|---|---|---|
| Route Prefix | officeguy |
קידומת לכל הנתיבים |
| Card Callback | callback/card |
חזרה מתשלום בכרטיס |
| Bit Webhook | webhook/bit |
קבלת IPN מ-Bit |
| SUMIT Webhook | webhook/sumit |
קבלת webhooks מ-SUMIT |
| Document Download | documents/{document} |
הורדת מסמכים |
| Checkout Charge | checkout/charge |
חיוב ישיר |
| Public Checkout | checkout/{id} |
עמוד תשלום ציבורי |
| Success Route | checkout.success |
נתיב הצלחה |
| Failed Route | checkout.failed |
נתיב כישלון |
דוגמה - שינוי נתיבים:
- גשו ל-Admin Panel > Gateway Settings > Route Configuration
- שנו את Route Prefix ל-
payments - שנו את Card Callback ל-
return/card - שמרו את ההגדרות
- נקו cache:
php artisan route:clear
תוצאה:
POST /payments/return/cardבמקוםPOST /officeguy/callback/cardPOST /payments/webhook/bitבמקוםPOST /officeguy/webhook/bit
או ב-.env:
OFFICEGUY_ROUTE_PREFIX=payments OFFICEGUY_CARD_CALLBACK_PATH=return/card OFFICEGUY_BIT_WEBHOOK_PATH=ipn/bit OFFICEGUY_SUMIT_WEBHOOK_PATH=triggers/sumit
שימוש בקוד:
use OfficeGuy\LaravelSumitGateway\Support\RouteConfig; // קבלת כל הנתיבים המוגדרים $paths = RouteConfig::getAllPaths(); // [ // 'prefix' => 'officeguy', // 'card_callback' => 'officeguy/callback/card', // 'bit_webhook' => 'officeguy/webhook/bit', // 'sumit_webhook' => 'officeguy/webhook/sumit', // ... // ] // קבלת נתיב ספציפי $cardCallbackPath = RouteConfig::getPrefix() . '/' . RouteConfig::getCardCallbackPath();
עמוד תשלום
תצוגה, ממשק ותוכן
עמוד התשלום מספק ממשק מלא ומותאם לגביית תשלומים מלקוחות. ניתן להתאים את התוכן, העיצוב והשדות.
הפעלה:
// ב-Admin Panel // נווטו ל-SUMIT Gateway > Gateway Settings > Public Checkout Page // הפעילו את "Enable Public Checkout"
או ב-.env:
OFFICEGUY_ENABLE_PUBLIC_CHECKOUT=true
גישה לעמוד:
GET /officeguy/checkout/{id}
יצירת קישור תשלום:
$checkoutUrl = route('officeguy.public.checkout', ['id' => $order->id]); // שליחה ללקוח Mail::to($customer->email)->send(new PaymentLinkEmail($checkoutUrl));
התאמת עיצוב עמוד התשלום
php artisan vendor:publish --tag=officeguy-views
לאחר מכן ערכו את הקובץ:
resources/views/vendor/officeguy/pages/checkout.blade.php
תכונות עמוד התשלום:
- תמיכה מלאה ב-RTL (עברית/ערבית)
- עיצוב רספונסיבי עם Tailwind CSS
- בחירת אמצעי תשלום (כרטיס אשראי / Bit)
- תמיכה בכרטיסים שמורים (טוקנים)
- בחירת מספר תשלומים
- סיכום הזמנה
שדות ת"ז ו-CVV
הגדרת שדות חובה
ניתן להגדיר אם שדות ת.ז ו-CVV יהיו חובה, אופציונליים, או מוסתרים.
ב-Admin Panel: נווטו ל-SUMIT Gateway > Gateway Settings > Payment Settings
אפשרויות לכל שדה:
required- חובה (ברירת מחדל)yes- אופציונלי (מוצג אך לא חובה)no- מוסתר
ב-.env:
OFFICEGUY_CITIZEN_ID=required # required/yes/no OFFICEGUY_CVV=required # required/yes/no
בקוד:
// קריאה להגדרות $settings = app(SettingsService::class); $citizenIdMode = $settings->get('citizen_id', 'required'); $cvvMode = $settings->get('cvv', 'required');
⚠️ חשוב: חברות האשראי מחייבות הזנת נתונים אלה. כדי להסתיר את השדות, יש לקבל מהן פטור מהזנת מס' ת.ז ו-CVV.
מסמכים
בחירת שפה אוטומטית
בברירת המחדל יופקו המסמכים בעברית. הפעלת "בחירת שפה אוטומטית" תאפשר להפיק את המסמכים בהתאם לשפת הלקוח/ה.
ב-Admin Panel:
- נווטו ל-Gateway Settings > Document Settings
- סמנו את "Automatic Languages"
ב-.env:
OFFICEGUY_AUTOMATIC_LANGUAGES=true
הפקת מסמך הזמנה
הפקת מסמך הזמנה נוסף ושליחתו ללקוח לאחר חיוב מוצלח, בנוסף למסמך חשבונית/קבלה.
ב-Admin Panel:
- סמנו את "Create Order Document"
ב-.env:
OFFICEGUY_CREATE_ORDER_DOCUMENT=true
הגדרות מסמכים נוספות
# שליחת מסמך במייל ללקוח OFFICEGUY_EMAIL_DOCUMENT=true # יצירת מסמך כטיוטא (לא סופי) OFFICEGUY_DRAFT_DOCUMENT=false
שיעור מע"מ מותאם
// במודל Payable שלכם public function getVatRate(): ?float { return 17.0; // 17% מע"מ } public function isTaxEnabled(): bool { return true; }
סוגי תשלומים
אינטגרציות עם PayPal ו-BlueSnap
הפקת מסמך (חשבונית/קבלה) אוטומטית בתשלום ב-PayPal, BlueSnap, או שערי תשלום אחרים.
ב-Admin Panel: נווטו ל-Gateway Settings > Additional Features
ב-.env:
# PayPal - אפשרויות: no, yes, async OFFICEGUY_PAYPAL_RECEIPTS=yes # BlueSnap OFFICEGUY_BLUESNAP_RECEIPTS=true # שערים אחרים OFFICEGUY_OTHER_RECEIPTS=stripe,paddle
בקוד:
// הפקת קבלה ידנית לתשלום PayPal DocumentService::createReceiptForExternalPayment($order, 'paypal', $transactionId);
תשלומים מחולקים (Installments)
הגדרת עסקאות תשלומים
הגדרת מספר תשלומים (עד 36) אפשרי לעסקה.
ב-Admin Panel: נווטו ל-Gateway Settings > Payment Settings
הגדרות:
- Max Payments - מספר תשלומים מקסימלי (עד 36)
- Min Amount for Payments - סכום מינימלי לאפשר תשלומים
- Min Amount per Payment - סכום מינימלי לתשלום בודד
ב-.env:
OFFICEGUY_MAX_PAYMENTS=12 OFFICEGUY_MIN_AMOUNT_FOR_PAYMENTS=100 OFFICEGUY_MIN_AMOUNT_PER_PAYMENT=50
בקוד:
// קבלת מספר תשלומים מקסימלי לסכום מסוים $maxPayments = PaymentService::getMaximumPayments($amount); // חיוב עם תשלומים $result = PaymentService::processCharge($order, $paymentsCount = 6);
תפיסת מסגרת (Authorize Only)
קביעת מסגרת אשראי לחיוב מושהה
תפיסת מסגרת מאפשרת לבצע את חיוב האשראי בשלב מאוחר יותר - מתאימה לעסקאות עם סכום חיוב משתנה.
ב-Admin Panel: נווטו ל-Gateway Settings > Payment Settings
הגדרות:
- Authorize Only - הפעלת מצב תפיסת מסגרת
- Authorize Added Percent - אחוז תוספת למסגרת (למשל: 20%)
- Authorize Minimum Addition - סכום תוספת מינימלי
ב-.env:
OFFICEGUY_AUTHORIZE_ONLY=true OFFICEGUY_AUTHORIZE_ADDED_PERCENT=20 OFFICEGUY_AUTHORIZE_MINIMUM_ADDITION=50
בקוד:
// תפיסת מסגרת $result = PaymentService::authorizePayment($order, $amount); // חיוב מאוחר יותר $result = PaymentService::capturePayment($transactionId, $finalAmount);
💡 שימוש נפוץ: בתי מלון, השכרת רכב, או כל עסקה שבה הסכום הסופי עשוי להשתנות.
מצב טסט
בדיקות ללא חיוב אמיתי
מצב טסט מאפשר לבצע בדיקות כדי לוודא שהכל עובד בלי לסלוק ולבצע חיובים אמיתיים. מסמכים יופקו כטיוטות.
ב-Admin Panel: נווטו ל-Gateway Settings > Environment Settings > סמנו "Testing Mode"
ב-.env:
OFFICEGUY_TESTING=true
מספרי כרטיסים לבדיקות:
| כרטיס | מספר | תוקף | CVV |
|---|---|---|---|
| ויזה (הצלחה) | 4580 0000 0000 0000 | כל תאריך עתידי | 123 |
| ויזה (כישלון) | 4580 0000 0000 0001 | כל תאריך עתידי | 123 |
| מאסטרקארד | 5326 1000 0000 0000 | כל תאריך עתידי | 123 |
בקוד:
// בדיקה אם במצב טסט $isTest = app(SettingsService::class)->get('testing', false);
⚠️ חשוב: לפני שהאתר עולה לאוויר, ודאו שביטלתם את מצב הטסט כדי לא לפספס מכירות אמיתיות!
שמירת פרטי אשראי (Tokens)
שמירת כרטיסי אשראי לרכישות חוזרות
מאפשר ללקוחות לשמור את פרטי כרטיס האשראי לרכישות עתידיות מהירות יותר.
ב-Admin Panel: נווטו ל-Gateway Settings > Tokenization > סמנו "Support Tokens"
ב-.env:
OFFICEGUY_SUPPORT_TOKENS=true OFFICEGUY_TOKEN_PARAM=5 # 5=J5 (מומלץ), 2=J2
בקוד:
// שמירת טוקן לאחר חיוב $token = OfficeGuyToken::createFromApiResponse($customer, $response); // חיוב עם טוקן שמור $result = PaymentService::processCharge($order, $payments, false, false, $token); // קבלת טוקנים של לקוח $tokens = OfficeGuyToken::where('owner_type', get_class($user)) ->where('owner_id', $user->id) ->get();
תכונות:
- שמירת פרטי כרטיס מאובטחת (PCI DSS)
- מילוי אוטומטי ברכישות הבאות
- תמיכה בחיובים חוזרים (Subscriptions)
- ניהול כרטיסים בפאנל לקוח
הוראות קבע ומנויים (Subscriptions)
גביית תשלומים קבועים באשראי
לגביית תשלומים קבועים מלקוחות או תורמים, החבילה מספקת פתרון יעיל ואוטומטי לניהול מנויים.
ב-Admin Panel: נווטו ל-Gateway Settings > Subscriptions
הגדרות:
- Enable Subscriptions - הפעלת מנויים
- Default Interval (Months) - מרווח ברירת מחדל בחודשים
- Default Cycles - מספר חיובים (ריק = ללא הגבלה)
- Allow Pause - אפשרות להשהות מנוי
- Retry Failed Charges - ניסיון חוזר בכישלון
- Max Retry Attempts - מספר ניסיונות מקסימלי
ב-.env:
OFFICEGUY_SUBSCRIPTIONS_ENABLED=true OFFICEGUY_SUBSCRIPTIONS_DEFAULT_INTERVAL=1 OFFICEGUY_SUBSCRIPTIONS_DEFAULT_CYCLES=12 OFFICEGUY_SUBSCRIPTIONS_ALLOW_PAUSE=true OFFICEGUY_SUBSCRIPTIONS_RETRY_FAILED=true OFFICEGUY_SUBSCRIPTIONS_MAX_RETRIES=3
יצירת מנוי:
use OfficeGuy\LaravelSumitGateway\Services\SubscriptionService; // יצירת מנוי חדש $subscription = SubscriptionService::create( $user, // הלקוח 'תוכנית חודשית', // שם המנוי 99.00, // סכום 'ILS', // מטבע 1, // אינטרוול בחודשים 12, // מספר חיובים (null = ללא הגבלה) $tokenId // טוקן לתשלום ); // חיוב ראשוני $result = SubscriptionService::processInitialCharge($subscription); // חיוב ידני $result = SubscriptionService::processRecurringCharge($subscription); // השהיית מנוי SubscriptionService::pause($subscription); // חידוש מנוי SubscriptionService::resume($subscription); // ביטול מנוי SubscriptionService::cancel($subscription);
תזמון חיובים חוזרים אוטומטיים:
הוסיפו ל-routes/console.php:
use Illuminate\Support\Facades\Schedule; // חיוב יומי בשעה 8:00 Schedule::command('sumit:process-recurring-payments')->dailyAt('08:00'); // או חיוב כל שעה Schedule::command('sumit:process-recurring-payments')->hourly(); // עם דיווח על כשלונות Schedule::command('sumit:process-recurring-payments') ->daily() ->emailOutputOnFailure('admin@example.com');
הרצה ידנית:
# הרצה אסינכרונית (כ-job) php artisan sumit:process-recurring-payments # הרצה סינכרונית php artisan sumit:process-recurring-payments --sync # עיבוד מנוי ספציפי php artisan sumit:process-recurring-payments --subscription=123
מלאי (Stock Management)
סנכרון מלאי עם מערכת החשבונות
📦 לניהול המלאי, יש להתקין את מודול מלאי בחשבון SUMIT.
ב-Admin Panel: נווטו ל-Gateway Settings > Additional Features
הגדרות:
- Stock Sync Frequency - תדירות סנכרון:
none,12(שעות),24(שעות) - Checkout Stock Sync - סנכרון בזמן Checkout
ב-.env:
OFFICEGUY_STOCK_SYNC_FREQ=12 # none/12/24 OFFICEGUY_CHECKOUT_STOCK_SYNC=true
Callback לעדכון מלאי:
// config/officeguy.php 'stock' => [ 'update_callback' => function(array $stockItem) { // עדכון מלאי במוצר $product = Product::where('sku', $stockItem['sku'])->first(); if ($product) { $product->update(['stock_quantity' => $stockItem['quantity']]); } }, ],
הרצת סנכרון ידנית:
php artisan sumit:stock-sync
סנכרון בקוד:
use OfficeGuy\LaravelSumitGateway\Services\Stock\StockSyncService; // סנכרון כל המלאי StockSyncService::syncAll(); // סנכרון מוצר ספציפי StockSyncService::syncProduct($sku);
תזמון סנכרון אוטומטי:
// routes/console.php Schedule::command('sumit:stock-sync')->everyTwelveHours();
Bit ו-Redirect
דף סליקה מסוג Redirect
גביה באמצעות Bit, Google Pay, Apple Pay, 3DS אפשרית באמצעות הגדרת דף סליקה בשיטת Redirect.
ב-Admin Panel: נווטו ל-Gateway Settings > Environment Settings > PCI Mode > בחרו "Redirect"
ב-.env:
OFFICEGUY_PCI_MODE=redirect OFFICEGUY_BIT_ENABLED=true
בקוד:
// חיוב עם Bit $result = BitPaymentService::processOrder( $order, route('checkout.success'), route('checkout.failed'), route('officeguy.webhook.bit') ); if ($result['success']) { return redirect($result['redirect_url']); }
Webhook ל-Bit:
POST /officeguy/webhook/bit
החבילה מטפלת אוטומטית ב-webhook ומעדכנת את סטטוס ההזמנה.
⚠️ שימו לב: מצב Redirect לא תומך בהוראות קבע, שמירת פרטי תשלום, ותפיסת מסגרת.
מיזוג לקוחות אוטומטי
מניעת כפילות כרטיסי לקוח ב-SUMIT
מיזוג כרטיס לקוח קיים במערכת SUMIT בסיום הרכישה באתר כדי למנוע כפילות. המיזוג מתבצע בהתאם למזהה הלקוח או המייל.
ב-Admin Panel: נווטו ל-Gateway Settings > Customer Merging > סמנו "Enable Customer Merging"
ב-.env:
OFFICEGUY_MERGE_CUSTOMERS=true
איך זה עובד:
- בעת יצירת מסמך, המערכת מחפשת לקוח קיים לפי מייל או מזהה
- אם נמצא - המסמך מקושר ללקוח הקיים
- אם לא נמצא - נוצר לקוח חדש
סנכרון לקוחות עם מודל מקומי (ללא שינוי קוד)
ניתן לסנכרן לקוחות מ-SUMIT עם מודל הלקוחות המקומי שלכם ללא לגעת בקוד המודל.
ב-Admin Panel: נווטו ל-Gateway Settings > Customer Merging
הגדרות:
| הגדרה | תיאור | דוגמה |
|---|---|---|
| Enable Customer Merging | הפעלת מיזוג ב-SUMIT | true |
| Enable Local Customer Sync | הפעלת סנכרון מקומי | true |
| Customer Model Class | שם מלא של מודל הלקוח | App\Models\User |
מיפוי שדות לקוח:
| שדה | ברירת מחדל | תיאור |
|---|---|---|
| Email Field | email |
שדה אימייל (מזהה ייחודי) |
| Name Field | name |
שדה שם מלא |
| Phone Field | phone |
שדה טלפון |
| First Name Field | - | שדה שם פרטי (אם נפרד) |
| Last Name Field | - | שדה שם משפחה (אם נפרד) |
| Company Field | - | שדה שם חברה |
| Address Field | - | שדה כתובת |
| City Field | - | שדה עיר |
| SUMIT ID Field | sumit_customer_id |
שדה לשמירת מזהה SUMIT |
דוגמה - חיבור למודל User:
- הוסיפו עמודה לטבלת users:
php artisan make:migration add_sumit_customer_id_to_users_table
Schema::table('users', function (Blueprint $table) { $table->string('sumit_customer_id')->nullable()->index(); });
-
ב-Admin Panel הגדירו:
- Customer Model Class:
App\Models\User - Email Field:
email - Name Field:
name - SUMIT ID Field:
sumit_customer_id
- Customer Model Class:
-
הפעילו סנכרון אוטומטי ב-Listener:
// app/Providers/EventServiceProvider.php use OfficeGuy\LaravelSumitGateway\Events\SumitWebhookReceived; use OfficeGuy\LaravelSumitGateway\Listeners\CustomerSyncListener; protected $listen = [ SumitWebhookReceived::class => [ CustomerSyncListener::class, ], ];
שימוש ב-CustomerMergeService:
use OfficeGuy\LaravelSumitGateway\Services\CustomerMergeService; // סנכרון ידני של לקוח מ-SUMIT $mergeService = app(CustomerMergeService::class); // מציאת לקוח לפי SUMIT ID $customer = $mergeService->findBySumitId('12345'); // מציאת לקוח לפי אימייל $customer = $mergeService->findByEmail('customer@example.com'); // סנכרון לקוח מנתוני SUMIT $sumitData = [ 'ID' => '12345', 'Email' => 'customer@example.com', 'FirstName' => 'John', 'LastName' => 'Doe', 'Phone' => '0501234567', ]; $localCustomer = $mergeService->syncFromSumit($sumitData);
יתרונות:
- ✅ אין צורך לשנות את קוד המודל
- ✅ הגדרה מלאה דרך Admin Panel
- ✅ סנכרון אוטומטי כשמתקבל webhook מ-SUMIT
- ✅ מניעת כפילויות לקוחות
- ✅ שיפור חוויית לקוח - זיהוי לקוחות חוזרים
מודל Order (Payable)
החבילה דורשת שמודל ההזמנה יממש OfficeGuy\LaravelSumitGateway\Contracts\Payable.
אפשרות 1: מיפוי שדות מ-Admin Panel (ללא שינוי קוד)
ניתן לחבר כל מודל קיים מבלי לשנות את הקוד שלו. ראו סעיף עמוד תשלום ציבורי.
אפשרות 2: שימוש ב-Trait
class Order extends Model implements Payable { use \OfficeGuy\LaravelSumitGateway\Support\Traits\PayableAdapter; }
כדאי להעמיס (eager load) יחסי items/fees.
קונפיגורציה
'order' => [ 'model' => App\Models\Order::class, // או 'resolver' => fn($id) => App\Models\Order::with('items','fees')->find($id), ],
מסלולים (Routes)
תחת prefix (ברירת מחדל officeguy):
| מסלול | סוג | תיאור |
|---|---|---|
callback/card |
GET | חזרת Redirect מכרטיס |
webhook/bit |
POST | IPN ל-Bit |
checkout/charge |
POST | מסלול סליקה מובנה (אופציונלי) |
checkout/{id} |
GET/POST | עמוד תשלום ציבורי (אופציונלי) |
מסלולי הצלחה/כישלון: מוגדרים ב-config routes.success / routes.failed.
Filament Admin Panel
עמודים וניהול
- Gateway Settings - הגדרות שער התשלום (ניווט: SUMIT Gateway)
- משאבי לקוח - טרנזקציות, מסמכים, אמצעי תשלום (Client Panel)
גישה להגדרות
Admin Panel > SUMIT Gateway > Gateway Settings
SSL
ה-HTTP client משתמש ב-ssl_verify (ברירת מחדל true). לשימוש dev בלבד ניתן לכבות:
OFFICEGUY_SSL_VERIFY=false
לוגים
הפעלת לוגים לניטור ודיבוג:
OFFICEGUY_LOGGING=true OFFICEGUY_LOG_CHANNEL=stack
🔒 נתונים רגישים (מספר כרטיס/CVV) מנוקים אוטומטית מהלוגים.
Multi-Vendor
תמיכה בריבוי מוכרים
תמיכה בשוק (marketplace) עם credentials נפרדים לכל ספק.
ב-Admin Panel: נווטו ל-Gateway Settings > Multi-Vendor
הגדרות:
- Enable Multi-Vendor - הפעלת מצב ריבוי מוכרים
- Validate Vendor Credentials - אימות פרטי ספק
- Allow Authorize Only - אפשרות תפיסת מסגרת לספקים
ב-.env:
OFFICEGUY_MULTIVENDOR_ENABLED=true OFFICEGUY_MULTIVENDOR_VALIDATE_CREDENTIALS=true OFFICEGUY_MULTIVENDOR_ALLOW_AUTHORIZE=false
בקוד:
use OfficeGuy\LaravelSumitGateway\Models\VendorCredential; use OfficeGuy\LaravelSumitGateway\Services\MultiVendorPaymentService; // שמירת credentials לספק VendorCredential::create([ 'vendor_type' => get_class($vendor), 'vendor_id' => $vendor->id, 'company_id' => '12345', 'api_key' => 'your-api-key', ]); // חיוב הזמנה מרובת ספקים $result = MultiVendorPaymentService::processMultiVendorCharge($order, $paymentsCount);
Resolver לזיהוי ספק:
// config/officeguy.php 'multivendor' => [ 'vendor_resolver' => fn(array $item) => \App\Models\Vendor::find($item['vendor_id']), ],
תרומות (Donations)
תמיכה במוצרי תרומה
הפקת קבלת תרומה אוטומטית במקום חשבונית רגילה.
ב-Admin Panel: נווטו ל-Gateway Settings > Donations
הגדרות:
- Enable Donations - הפעלת תמיכה בתרומות
- Allow Mixed Cart - אפשרות לשלב תרומות עם מוצרים רגילים
- Document Type - סוג מסמך (Donation Receipt / Invoice)
ב-.env:
OFFICEGUY_DONATIONS_ENABLED=true OFFICEGUY_DONATIONS_ALLOW_MIXED=false OFFICEGUY_DONATIONS_DOCUMENT_TYPE=320 # 320=קבלת תרומה
בקוד:
use OfficeGuy\LaravelSumitGateway\Services\DonationService; // בדיקה אם עגלה מכילה תרומות ומוצרים רגילים $validation = DonationService::validateCart($order); if (!$validation['valid']) { return redirect()->back()->with('error', $validation['message']); } // קבלת סוג המסמך המתאים $docType = DonationService::getDocumentType($order);
Upsell / CartFlows
חיוב מוצרי upsell
חיוב מוצרים נוספים באמצעות טוקן מהחיוב הראשי - ללא צורך להזין שוב פרטי כרטיס.
ב-Admin Panel: נווטו ל-Gateway Settings > Upsell / CartFlows
הגדרות:
- Enable Upsell - הפעלת upsell
- Require Saved Token - דרישת טוקן שמור
- Max Upsells Per Order - מקסימום upsells להזמנה
ב-.env:
OFFICEGUY_UPSELL_ENABLED=true OFFICEGUY_UPSELL_REQUIRE_TOKEN=true OFFICEGUY_UPSELL_MAX_PER_ORDER=5
בקוד:
use OfficeGuy\LaravelSumitGateway\Services\UpsellService; // חיוב עם טוקן ידוע $result = UpsellService::processUpsellCharge($upsellOrder, $token, $parentOrderId); // חיוב עם זיהוי אוטומטי של הטוקן $result = UpsellService::processUpsellWithAutoToken($upsellOrder, $parentOrderId, $customer);
אירועים (Events)
החבילה משדרת את האירועים הבאים:
| אירוע | תיאור |
|---|---|
PaymentCompleted |
תשלום הצליח |
PaymentFailed |
תשלום נכשל |
DocumentCreated |
מסמך נוצר |
StockSynced |
מלאי סונכרן |
BitPaymentCompleted |
תשלום Bit הושלם |
SubscriptionCreated |
מנוי נוצר |
SubscriptionCharged |
מנוי חויב |
SubscriptionChargesFailed |
חיוב מנוי נכשל |
SubscriptionCancelled |
מנוי בוטל |
MultiVendorPaymentCompleted |
תשלום מרובה-ספקים הצליח |
MultiVendorPaymentFailed |
תשלום מרובה-ספקים נכשל |
UpsellPaymentCompleted |
תשלום upsell הצליח |
UpsellPaymentFailed |
תשלום upsell נכשל |
האזנה לאירועים:
// app/Providers/EventServiceProvider.php use OfficeGuy\LaravelSumitGateway\Events\PaymentCompleted; protected $listen = [ PaymentCompleted::class => [ \App\Listeners\SendPaymentConfirmation::class, \App\Listeners\UpdateOrderStatus::class, ], ];
דוגמת Listener:
namespace App\Listeners; use OfficeGuy\LaravelSumitGateway\Events\PaymentCompleted; class SendPaymentConfirmation { public function handle(PaymentCompleted $event): void { $orderId = $event->orderId; $transactionId = $event->transactionId; // שליחת אימייל אישור Mail::to($event->customerEmail)->send(new PaymentConfirmed($orderId)); } }
Custom Event Webhooks
הגדרת Webhooks מה-Admin Panel
במקום ליצור Listeners בקוד, ניתן להגדיר Webhooks מותאמים אישית ישירות מה-Admin Panel. המערכת תשלח התראות HTTP לכל URL שתגדירו כאשר מתרחשים אירועים.
ב-Admin Panel: נווטו ל-SUMIT Gateway > Gateway Settings > Custom Event Webhooks
אירועים נתמכים:
| אירוע | שדה בהגדרות | תיאור |
|---|---|---|
| Payment Completed | webhook_payment_completed |
תשלום הושלם בהצלחה |
| Payment Failed | webhook_payment_failed |
תשלום נכשל |
| Document Created | webhook_document_created |
מסמך (חשבונית/קבלה) נוצר |
| Subscription Created | webhook_subscription_created |
מנוי חדש נוצר |
| Subscription Charged | webhook_subscription_charged |
מנוי חויב |
| Bit Payment Completed | webhook_bit_payment_completed |
תשלום Bit הושלם |
| Stock Synced | webhook_stock_synced |
מלאי סונכרן |
הגדרת סוד לאימות:
הגדירו Webhook Secret ב-Admin Panel. המערכת תשלח חתימה בכותרת X-Webhook-Signature לאימות מקור הבקשה.
דוגמת Payload:
{
"event": "payment_completed",
"timestamp": "2024-01-15T10:30:00+02:00",
"order_id": 123,
"transaction_id": "TXN_12345",
"amount": 99.00,
"currency": "ILS",
"customer_email": "customer@example.com"
}
כותרות HTTP:
Content-Type: application/json
X-Webhook-Event: payment_completed
X-Webhook-Signature: sha256=abc123...
X-Webhook-Timestamp: 2024-01-15T10:30:00+02:00
אימות חתימה בשרת שלכם:
function verifyWebhook(Request $request): bool { $signature = $request->header('X-Webhook-Signature'); $payload = $request->getContent(); $secret = config('your-webhook-secret'); $expectedSignature = hash_hmac('sha256', $payload, $secret); return hash_equals($expectedSignature, $signature); }
שימוש ב-WebhookService ישירות (אופציונלי):
use OfficeGuy\LaravelSumitGateway\Services\WebhookService; // שליחת webhook ידנית $webhookService = app(WebhookService::class); $webhookService->send('payment_completed', [ 'order_id' => 123, 'amount' => 99.00, ]);
Webhook Events Resource (Admin Panel)
צפייה ב-Webhook Events
משאב מלא לצפייה וניהול כל אירועי ה-Webhook, כולל חיבור למשאבים קיימים לבניית אוטומציות.
ב-Admin Panel: נווטו ל-SUMIT Gateway > Webhook Events
תכונות הממשק
רשימת אירועים:
- צפייה בכל האירועים שנשלחו
- סינון לפי סוג אירוע, סטטוס, טווח תאריכים
- חיפוש לפי מייל לקוח או מזהה
- מיון לפי תאריך, סטטוס, HTTP status
- Badge עם מספר אירועים שנכשלו
פעולות:
- Retry - שליחה חוזרת של webhook שנכשל
- Retry All Failed - שליחה חוזרת לכל האירועים הכושלים
- Clear Sent Events - מחיקת אירועים ישנים (7+ ימים)
- Copy Payload - העתקת ה-payload
חיבור למשאבים קיימים: כל אירוע מקושר אוטומטית למשאבים הרלוונטיים:
- Transaction - לחיצה מעבירה לעמוד הטרנזקציה
- Document - לחיצה מעבירה לעמוד המסמך
- Token - לחיצה מעבירה לעמוד הטוקן
- Subscription - לחיצה מעבירה לעמוד המנוי
סטטיסטיקות (Widget):
- אירועים היום
- אחוז הצלחה
- אירועים שנכשלו
- זמן תגובה ממוצע
- גרף 7 ימים אחרונים
שימוש בסיסי
1. הגדרת Webhook בשרת חיצוני
כדי לקבל התראות, צרו endpoint בשרת שלכם שמקבל בקשות POST:
// routes/api.php Route::post('/webhooks/sumit', [WebhookController::class, 'handle']);
// app/Http/Controllers/WebhookController.php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; class WebhookController extends Controller { public function handle(Request $request) { // 1. אימות החתימה $signature = $request->header('X-Webhook-Signature'); $payload = $request->getContent(); $secret = config('services.sumit.webhook_secret'); $expectedSignature = hash_hmac('sha256', $payload, $secret); if (!hash_equals($expectedSignature, $signature)) { Log::warning('Invalid webhook signature'); return response('Invalid signature', 401); } // 2. עיבוד האירוע $event = $request->input('event'); $data = $request->all(); switch ($event) { case 'payment_completed': $this->handlePaymentCompleted($data); break; case 'payment_failed': $this->handlePaymentFailed($data); break; case 'document_created': $this->handleDocumentCreated($data); break; case 'subscription_charged': $this->handleSubscriptionCharged($data); break; } return response('OK', 200); } protected function handlePaymentCompleted(array $data): void { $orderId = $data['order_id']; $transactionId = $data['transaction_id']; $amount = $data['amount']; // עדכון הזמנה $order = Order::find($orderId); $order->update([ 'status' => 'paid', 'paid_at' => now(), ]); // שליחת אישור ללקוח Mail::to($data['customer_email'])->send(new PaymentConfirmation($order)); // עדכון CRM CrmService::updateCustomer($data['customer_email'], [ 'last_purchase' => now(), 'total_spent' => $amount, ]); } protected function handlePaymentFailed(array $data): void { $orderId = $data['order_id']; $error = $data['error'] ?? 'Unknown error'; // עדכון הזמנה Order::find($orderId)?->update(['status' => 'payment_failed']); // התראה לצוות Notification::route('slack', config('services.slack.webhook')) ->notify(new PaymentFailedNotification($orderId, $error)); } protected function handleDocumentCreated(array $data): void { // שמירת קישור למסמך $orderId = $data['order_id']; $documentUrl = $data['document_url'] ?? null; Order::find($orderId)?->update(['invoice_url' => $documentUrl]); } protected function handleSubscriptionCharged(array $data): void { $subscriptionId = $data['subscription_id']; $amount = $data['amount']; // רישום חיוב SubscriptionCharge::create([ 'subscription_id' => $subscriptionId, 'amount' => $amount, 'charged_at' => now(), ]); } }
2. הגדרת URL ב-Admin Panel
- גשו ל-SUMIT Gateway > Gateway Settings > Custom Event Webhooks
- הזינו את ה-URL של ה-endpoint שלכם בשדה המתאים
- הגדירו סוד (Secret) לאימות החתימה
- שמרו את ההגדרות
שימוש מתקדם בקוד
שליפת אירועים ב-Eloquent
use OfficeGuy\LaravelSumitGateway\Models\WebhookEvent; // קבלת כל האירועים שנכשלו $failedEvents = WebhookEvent::failed()->get(); // קבלת אירועים של לקוח ספציפי $customerEvents = WebhookEvent::forCustomer('customer@example.com')->get(); // קבלת אירועים מסוג מסוים $paymentEvents = WebhookEvent::ofType('payment_completed') ->with(['transaction', 'document']) ->get(); // אירועים מוכנים לשליחה חוזרת $pendingRetries = WebhookEvent::readyForRetry()->get(); // אירועים ממוינים לפי תאריך $recentEvents = WebhookEvent::orderBy('created_at', 'desc') ->limit(100) ->get();
גישה למשאבים מקושרים
// לכל אירוע יש גישה למשאבים הקשורים אליו foreach ($paymentEvents as $event) { // גישה לטרנזקציה $transaction = $event->transaction; if ($transaction) { echo "Transaction ID: {$transaction->payment_id}"; echo "Amount: {$transaction->amount}"; } // גישה למסמך $document = $event->document; if ($document) { echo "Document Number: {$document->document_number}"; echo "Document URL: {$document->url}"; } // גישה לטוקן $token = $event->token; if ($token) { echo "Card: ****{$token->last_digits}"; } // גישה למנוי $subscription = $event->subscription; if ($subscription) { echo "Subscription: {$subscription->name}"; echo "Next Charge: {$subscription->next_charge_at}"; } // גישה להזמנה (polymorphic) $order = $event->order; if ($order) { echo "Order ID: {$order->id}"; } }
שליחה חוזרת של אירועים
use OfficeGuy\LaravelSumitGateway\Services\WebhookService; // שליחה חוזרת של אירוע בודד $event = WebhookEvent::find(123); if ($event->canRetry()) { $webhookService = app(WebhookService::class); $success = $webhookService->send($event->event_type, $event->payload); if ($success) { $event->markAsSent(200); } else { $event->scheduleRetry(5); // retry in 5 minutes } } // שליחה חוזרת לכל האירועים שנכשלו $failedEvents = WebhookEvent::failed()->get(); foreach ($failedEvents as $event) { if ($event->canRetry()) { $event->scheduleRetry(); } }
יצירת אירוע ידנית
use OfficeGuy\LaravelSumitGateway\Models\WebhookEvent; // יצירת אירוע חדש $event = WebhookEvent::createEvent('payment_completed', [ 'order_id' => 123, 'amount' => 99.00, 'currency' => 'ILS', 'customer_email' => 'customer@example.com', ], [ 'transaction_id' => $transaction->id, 'document_id' => $document->id, 'webhook_url' => 'https://your-site.com/webhook', ]); // סימון כנשלח $event->markAsSent(200, ['received' => true]); // סימון ככישלון $event->markAsFailed('Connection timeout', 504);
בניית אוטומציות
דוגמה: סנכרון עם CRM
// app/Console/Commands/SyncWebhooksToCrm.php namespace App\Console\Commands; use Illuminate\Console\Command; use OfficeGuy\LaravelSumitGateway\Models\WebhookEvent; use App\Services\CrmService; class SyncWebhooksToCrm extends Command { protected $signature = 'crm:sync-webhooks'; protected $description = 'Sync payment webhooks to CRM'; public function handle(CrmService $crm) { // קבלת כל האירועים שטרם סונכרנו $events = WebhookEvent::ofType('payment_completed') ->sent() ->where('synced_to_crm', false) ->with(['transaction', 'document']) ->get(); foreach ($events as $event) { $crm->recordPurchase([ 'email' => $event->customer_email, 'amount' => $event->amount, 'currency' => $event->currency, 'transaction_id' => $event->transaction?->payment_id, 'invoice_url' => $event->document?->url, ]); $event->update(['synced_to_crm' => true]); } $this->info("Synced {$events->count()} events to CRM"); } }
דוגמה: דוח יומי
// app/Console/Commands/WebhookDailyReport.php namespace App\Console\Commands; use Illuminate\Console\Command; use OfficeGuy\LaravelSumitGateway\Models\WebhookEvent; use Illuminate\Support\Facades\Mail; class WebhookDailyReport extends Command { protected $signature = 'webhooks:daily-report'; protected $description = 'Send daily webhook statistics report'; public function handle() { $today = now()->startOfDay(); $stats = [ 'total' => WebhookEvent::whereDate('created_at', $today)->count(), 'sent' => WebhookEvent::sent()->whereDate('created_at', $today)->count(), 'failed' => WebhookEvent::failed()->whereDate('created_at', $today)->count(), 'by_type' => WebhookEvent::whereDate('created_at', $today) ->selectRaw('event_type, count(*) as count') ->groupBy('event_type') ->pluck('count', 'event_type'), 'total_amount' => WebhookEvent::ofType('payment_completed') ->whereDate('created_at', $today) ->sum('amount'), ]; // שליחת דוח במייל Mail::to('admin@example.com')->send(new WebhookStatsReport($stats)); $this->info("Report sent. Total events: {$stats['total']}"); } }
דוגמה: ניטור כשלונות
// app/Console/Commands/MonitorWebhookFailures.php namespace App\Console\Commands; use Illuminate\Console\Command; use OfficeGuy\LaravelSumitGateway\Models\WebhookEvent; use Illuminate\Support\Facades\Notification; use App\Notifications\WebhookFailureAlert; class MonitorWebhookFailures extends Command { protected $signature = 'webhooks:monitor'; protected $description = 'Monitor webhook failures and alert'; public function handle() { $failedCount = WebhookEvent::failed() ->where('created_at', '>=', now()->subHour()) ->count(); if ($failedCount > 10) { // שליחת התראה Notification::route('slack', config('services.slack.webhook')) ->notify(new WebhookFailureAlert($failedCount)); $this->error("Alert sent: {$failedCount} failures in the last hour"); } else { $this->info("All good: {$failedCount} failures in the last hour"); } } }
תזמון משימות
הוסיפו ל-routes/console.php:
use Illuminate\Support\Facades\Schedule; // עיבוד webhooks שממתינים לשליחה חוזרת Schedule::command('sumit:process-webhook-retries')->everyFiveMinutes(); // דוח יומי Schedule::command('webhooks:daily-report')->dailyAt('09:00'); // ניטור כשלונות Schedule::command('webhooks:monitor')->everyThirtyMinutes(); // סנכרון עם CRM Schedule::command('crm:sync-webhooks')->hourly();
סוגי אירועים
| סוג אירוע | קבוע | תיאור | שדות עיקריים |
|---|---|---|---|
| Payment Completed | payment_completed |
תשלום הושלם בהצלחה | order_id, transaction_id, amount, customer_email |
| Payment Failed | payment_failed |
תשלום נכשל | order_id, error, customer_email |
| Document Created | document_created |
מסמך נוצר | order_id, document_id, document_number, document_url |
| Subscription Created | subscription_created |
מנוי חדש נוצר | subscription_id, customer_email, amount, interval |
| Subscription Charged | subscription_charged |
מנוי חויב | subscription_id, transaction_id, amount |
| Bit Payment | bit_payment_completed |
תשלום Bit הושלם | order_id, transaction_id, amount |
| Stock Synced | stock_synced |
מלאי סונכרן | items_count, sync_time |
סטטוסים
| סטטוס | קבוע | תיאור |
|---|---|---|
| Pending | pending |
ממתין לשליחה |
| Sent | sent |
נשלח בהצלחה |
| Failed | failed |
השליחה נכשלה |
| Retrying | retrying |
מתוזמן לשליחה חוזרת |
קבלת Webhooks מ-SUMIT (Incoming Webhooks)
מהי שליחת Webhook מ-SUMIT?
SUMIT יכולה לשלוח התראות (Webhooks) לאפליקציה שלכם כאשר מתרחשות פעולות במערכת SUMIT. זה מאפשר לכם לקבל עדכונים בזמן אמת על פעולות שבוצעו במערכת ניהול החשבונות.
מידע נוסף:
סוגי אירועים נתמכים
| פעולה | תיאור |
|---|---|
card_created |
יצירת כרטיס (לקוח, מסמך, פריט וכו') |
card_updated |
עדכון כרטיס |
card_deleted |
מחיקת כרטיס |
card_archived |
העברת כרטיס לארכיון |
סוגי כרטיסים
| סוג כרטיס | תיאור |
|---|---|
customer |
כרטיס לקוח |
document |
מסמך (חשבונית, קבלה) |
transaction |
עסקה |
item |
פריט מלאי |
payment |
תשלום |
כתובות Webhook
החבילה חושפת מספר endpoints לקבלת webhooks מ-SUMIT:
| כתובת | תיאור |
|---|---|
POST /officeguy/webhook/sumit |
Endpoint כללי (זיהוי אוטומטי) |
POST /officeguy/webhook/sumit/card-created |
יצירת כרטיס |
POST /officeguy/webhook/sumit/card-updated |
עדכון כרטיס |
POST /officeguy/webhook/sumit/card-deleted |
מחיקת כרטיס |
POST /officeguy/webhook/sumit/card-archived |
העברת לארכיון |
הגדרת Trigger ב-SUMIT
-
התקנת מודולים נדרשים ב-SUMIT:
- מודול טריגרים
- מודול API
- מודול ניהול תצוגות
-
יצירת תצוגה:
- הגדירו אילו כרטיסים יכללו
- בחרו אילו שדות יועברו ב-webhook
-
יצירת טריגר:
- בחרו תיקייה ותצוגה
- הגדירו תנאי הפעלה (יצירה/עדכון/מחיקה/ארכיון)
- בחרו פעולת HTTP
- הזינו את כתובת ה-webhook שלכם
-
הגדרת הכתובת:
https://your-domain.com/officeguy/webhook/sumitאו לאירוע ספציפי:
https://your-domain.com/officeguy/webhook/sumit/card-created
SUMIT Webhooks Resource (Admin Panel)
צפייה בכל ה-webhooks שהתקבלו מ-SUMIT ב-Admin Panel:
ב-Admin Panel: נווטו ל-SUMIT Gateway > SUMIT Webhooks
תכונות:
- צפייה בכל ה-webhooks שהתקבלו
- סינון לפי סוג אירוע, סוג כרטיס, סטטוס
- חיפוש לפי מזהה כרטיס, לקוח, מייל
- עיבוד webhooks שטרם טופלו
- סימון webhooks כמעובדים או מתעלמים
סטטיסטיקות:
- Webhooks היום
- ממתינים לעיבוד
- אחוז עיבוד
- webhooks שנכשלו
טיפול ב-Webhooks בקוד
האזנה לאירוע
// app/Providers/EventServiceProvider.php use OfficeGuy\LaravelSumitGateway\Events\SumitWebhookReceived; protected $listen = [ SumitWebhookReceived::class => [ \App\Listeners\HandleSumitWebhook::class, ], ];
יצירת Listener
// app/Listeners/HandleSumitWebhook.php namespace App\Listeners; use OfficeGuy\LaravelSumitGateway\Events\SumitWebhookReceived; use OfficeGuy\LaravelSumitGateway\Models\SumitWebhook; class HandleSumitWebhook { public function handle(SumitWebhookReceived $event): void { $webhook = $event->webhook; switch ($webhook->event_type) { case SumitWebhook::TYPE_CARD_CREATED: $this->handleCardCreated($webhook); break; case SumitWebhook::TYPE_CARD_UPDATED: $this->handleCardUpdated($webhook); break; case SumitWebhook::TYPE_CARD_DELETED: $this->handleCardDeleted($webhook); break; case SumitWebhook::TYPE_CARD_ARCHIVED: $this->handleCardArchived($webhook); break; } } protected function handleCardCreated(SumitWebhook $webhook): void { // טיפול ביצירת כרטיס $cardType = $webhook->card_type; $cardId = $webhook->card_id; $payload = $webhook->payload; if ($cardType === 'customer') { // סנכרון לקוח חדש למערכת Customer::create([ 'sumit_id' => $cardId, 'name' => $payload['Name'] ?? '', 'email' => $payload['Email'] ?? '', 'phone' => $payload['Phone'] ?? '', ]); } elseif ($cardType === 'document') { // שמירת מסמך חדש Document::create([ 'sumit_id' => $cardId, 'number' => $payload['Number'] ?? '', 'amount' => $payload['Amount'] ?? 0, ]); } // סימון כמעובד $webhook->markAsProcessed('Successfully synced'); } protected function handleCardUpdated(SumitWebhook $webhook): void { // עדכון כרטיס קיים $cardType = $webhook->card_type; $cardId = $webhook->card_id; if ($cardType === 'customer') { Customer::where('sumit_id', $cardId)->update([ 'name' => $webhook->payload['Name'] ?? '', 'email' => $webhook->payload['Email'] ?? '', ]); } $webhook->markAsProcessed('Successfully updated'); } protected function handleCardDeleted(SumitWebhook $webhook): void { // מחיקת כרטיס $cardType = $webhook->card_type; $cardId = $webhook->card_id; if ($cardType === 'customer') { Customer::where('sumit_id', $cardId)->delete(); } $webhook->markAsProcessed('Successfully deleted'); } protected function handleCardArchived(SumitWebhook $webhook): void { // סימון כרטיס כמאורכב $cardType = $webhook->card_type; $cardId = $webhook->card_id; if ($cardType === 'customer') { Customer::where('sumit_id', $cardId) ->update(['archived' => true]); } $webhook->markAsProcessed('Successfully archived'); } }
שימוש ב-Eloquent
use OfficeGuy\LaravelSumitGateway\Models\SumitWebhook; // קבלת webhooks שטרם טופלו $pending = SumitWebhook::received()->get(); // קבלת webhooks לפי סוג אירוע $createdCards = SumitWebhook::ofType('card_created')->get(); // קבלת webhooks לפי סוג כרטיס $customerWebhooks = SumitWebhook::ofCardType('customer')->get(); // קבלת webhooks שנכשלו $failed = SumitWebhook::failed()->get(); // קבלת webhooks של לקוח ספציפי $customerWebhooks = SumitWebhook::forCustomer('CUST123')->get(); // סימון webhook כמעובד $webhook->markAsProcessed('Synced to CRM', [ 'transaction_id' => $transaction->id, ]); // סימון webhook כנכשל $webhook->markAsFailed('API error: 500'); // סימון webhook כמתעלם $webhook->markAsIgnored('Duplicate webhook');
התמודדות עם ניסיונות חוזרים מ-SUMIT
SUMIT מבצעת ניסיונות חוזרים אוטומטיים:
- Timeout: המערכת ממתינה 10 שניות לתשובה
- Retry: אם אין תשובה, ממתינה 30 שניות ומנסה שוב
- Max Retries: לאחר 5 ניסיונות כושלים, הטריגר מושהה
- Resume: כשהטריגר מופעל מחדש, כל הפעולות שהצטברו נשלחות
המלצות:
// מומלץ: עיבוד אסינכרוני public function handle(Request $request): JsonResponse { // שמירה מהירה של ה-webhook $webhook = SumitWebhook::createFromRequest(...); // דחיית העיבוד ל-queue ProcessSumitWebhookJob::dispatch($webhook); // החזרת תשובה מיידית (תוך 10 שניות!) return response()->json(['success' => true], 200); }
דוגמאות שימוש נפוצות
סנכרון לקוחות
// app/Jobs/SyncCustomerFromSumit.php public function handle(): void { $webhook = $this->webhook; if ($webhook->card_type !== 'customer') { $webhook->markAsIgnored('Not a customer card'); return; } $payload = $webhook->payload; Customer::updateOrCreate( ['sumit_id' => $webhook->card_id], [ 'name' => $payload['Name'] ?? '', 'email' => $payload['Email'] ?? '', 'phone' => $payload['Phone'] ?? '', 'address' => $payload['Address'] ?? '', ] ); $webhook->markAsProcessed('Customer synced'); }
עדכון מלאי
// app/Jobs/SyncInventoryFromSumit.php public function handle(): void { $webhook = $this->webhook; if ($webhook->card_type !== 'item') { $webhook->markAsIgnored('Not an item card'); return; } $payload = $webhook->payload; Product::updateOrCreate( ['sumit_sku' => $payload['SKU'] ?? $webhook->card_id], [ 'name' => $payload['Name'] ?? '', 'price' => $payload['Price'] ?? 0, 'stock' => $payload['Stock'] ?? 0, ] ); $webhook->markAsProcessed('Inventory synced'); }
התראה על מסמך חדש
// app/Jobs/NotifyNewDocument.php public function handle(): void { $webhook = $this->webhook; if ($webhook->card_type !== 'document') { $webhook->markAsIgnored('Not a document'); return; } $payload = $webhook->payload; // שליחת התראה לצוות Notification::route('slack', config('services.slack.webhook')) ->notify(new NewDocumentFromSumit([ 'document_number' => $payload['Number'] ?? '', 'amount' => $payload['Amount'] ?? 0, 'customer' => $payload['CustomerName'] ?? '', ])); $webhook->markAsProcessed('Notification sent'); }
מיגרציות נתונים
טבלאות
| טבלה | תיאור |
|---|---|
officeguy_transactions |
טרנזקציות תשלום |
officeguy_tokens |
כרטיסי אשראי שמורים |
officeguy_documents |
חשבוניות וקבלות |
officeguy_settings |
הגדרות מערכת |
vendor_credentials |
credentials לספקים |
subscriptions |
מנויים |
officeguy_webhook_events |
אירועי Webhook (יוצאים) |
officeguy_sumit_webhooks |
Webhooks מ-SUMIT (נכנסים) |
המיגרציות נטענות אוטומטית מהחבילה. להעתקה מקומית:
php artisan vendor:publish --tag=officeguy-migrations
בדיקות
- phpunit / orchestra testbench מומלצים
- החבילה כוללת בסיס מיגרציות
- יש להגדיר מודל Order דמה ל-Payable
הרצת בדיקות:
composer test
קבצים לפרסום (Publishable Assets)
החבילה מציעה מספר קבצים לפרסום (publish) להתאמה אישית. להלן פירוט כל קובץ, מה הוא מכיל, ומתי כדאי להשתמש בו.
פקודת Publish כללית
# פרסום כל הקבצים בבת אחת php artisan vendor:publish --provider="OfficeGuy\LaravelSumitGateway\OfficeGuyServiceProvider" # או פרסום קבצים ספציפיים לפי תגית (tag) php artisan vendor:publish --tag=<tag-name>
1. קונפיגורציה (--tag=officeguy-config)
php artisan vendor:publish --tag=officeguy-config
מיקום: config/officeguy.php
מה מכיל:
- הגדרות חברה (Company ID, API Keys)
- מצב PCI (no/redirect/yes)
- הגדרות תשלומים ותשלומים מחולקים (installments)
- הגדרות Bit
- הגדרות מסמכים
- הגדרות טוקנים
- הגדרות מנויים, תרומות, Multi-Vendor ו-Upsell
- הגדרות נתיבים (Routes)
- הגדרות מלאי
- הגדרות לוגים ו-SSL
מתי להשתמש:
- כאשר רוצים להגדיר ערכים קבועים שאינם משתנים מ-.env
- כאשר צריך להגדיר resolvers או callbacks מותאמים אישית (למשל
order.resolver,stock.update_callback) - כאשר רוצים לשנות את רשימת המטבעות הנתמכים
- כאשר צריך להגדיר middleware מותאם אישית לנתיבים
דוגמה להתאמה אישית:
// config/officeguy.php return [ 'order' => [ 'resolver' => fn($id) => \App\Models\Order::with(['items', 'fees', 'customer'])->find($id), ], 'stock' => [ 'update_callback' => fn(array $stockItem) => \App\Services\InventoryService::updateStock($stockItem), ], 'multivendor' => [ 'enabled' => true, 'vendor_resolver' => fn(array $item) => \App\Models\Vendor::find($item['vendor_id']), ], ];
2. מיגרציות (--tag=officeguy-migrations)
php artisan vendor:publish --tag=officeguy-migrations
מיקום: database/migrations/
מה מכיל:
create_officeguy_transactions_table- טבלת טרנזקציותcreate_officeguy_tokens_table- טבלת טוקנים (כרטיסי אשראי שמורים)create_officeguy_documents_table- טבלת מסמכים (חשבוניות/קבלות)create_officeguy_settings_table- טבלת הגדרותcreate_vendor_credentials_table- טבלת credentials לספקים (Multi-Vendor)create_subscriptions_table- טבלת מנוייםadd_donation_and_vendor_fields- שדות נוספים לתרומות וספקים
מתי להשתמש:
- כאשר רוצים לשנות את מבנה הטבלאות (הוספת שדות, שינוי indexes)
- כאשר צריך להתאים שמות טבלאות לקונבנציות הפרויקט
- כאשר רוצים לשלב עם מיגרציות קיימות בפרויקט
- כאשר צריך שליטה על סדר הרצת המיגרציות
הערה חשובה: לאחר פרסום המיגרציות, החבילה תמשיך לטעון את המיגרציות שלה מ-vendor/. כדי למנוע כפילויות, ודאו שאתם לא מריצים את אותן מיגרציות פעמיים.
3. תצוגות (--tag=officeguy-views)
php artisan vendor:publish --tag=officeguy-views
מיקום: resources/views/vendor/officeguy/
מה מכיל:
components/payment-form.blade.php- טופס תשלום עם:- שדות כרטיס אשראי (מספר, תוקף, CVV, ת.ז.)
- בחירת אמצעי תשלום שמור (טוקן)
- בחירת מספר תשלומים
- תמיכה ב-RTL וולידציה צד-לקוח עם Alpine.js
pages/checkout.blade.php- עמוד תשלום ציבורי מלא עם:- תצוגת סיכום הזמנה
- פרטי לקוח
- בחירת אמצעי תשלום (כרטיס/Bit)
- תמיכה בתשלומים
- עיצוב מודרני עם Tailwind CSS
- תמיכה מלאה ב-RTL
filament/pages/officeguy-settings.blade.php- עמוד הגדרות ב-Filament Adminfilament/client/payment-methods/hosted-token-form.blade.php- טופס ניהול אמצעי תשלום ללקוח
מתי להשתמש:
- כאשר רוצים לשנות את עיצוב טופס התשלום
- כאשר צריך להתאים את הטופס לעיצוב הייחודי של האתר
- כאשר רוצים להוסיף שדות נוספים לטופס
- כאשר צריך לשנות את הטקסטים או התרגומים
- כאשר רוצים לשנות את לוגיקת הולידציה בצד הלקוח
דוגמה להתאמת טופס תשלום:
{{-- resources/views/vendor/officeguy/components/payment-form.blade.php --}} <div class="my-custom-payment-form"> {{-- הוספת לוגו חברה --}} <div class="company-logo mb-4"> <img src="{{ asset('images/logo.svg') }}" alt="Logo"> </div> {{-- שאר הטופס... --}} </div>
טבלת סיכום
| תגית | מיקום יעד | שימוש עיקרי |
|---|---|---|
officeguy-config |
config/officeguy.php |
הגדרות API, תשלומים, resolvers |
officeguy-migrations |
database/migrations/ |
התאמת מבנה מסד נתונים |
officeguy-views |
resources/views/vendor/officeguy/ |
התאמת עיצוב וממשק משתמש |
העתקה סלקטיבית
ניתן לפרסם מספר תגיות בבת אחת:
# פרסום קונפיג ותצוגות בלבד
php artisan vendor:publish --tag=officeguy-config --tag=officeguy-views
עמוד תשלום ציבורי (Public Checkout Page)
החבילה מספקת עמוד תשלום ציבורי שניתן לשייך לכל מודל המממש את הממשק Payable. זה מאפשר ליצור קישורי תשלום לכל סוג של מוצר, שירות או הזמנה במערכת.
הפעלה
ניתן להפעיל את עמוד התשלום הציבורי בשתי דרכים:
1. דרך Admin Panel (מומלץ):
גשו לעמוד ההגדרות ב-Filament Admin Panel:
- נווטו ל-SUMIT Gateway > Gateway Settings
- מצאו את הסעיף "Public Checkout Page"
- הפעילו את "Enable Public Checkout"
- הגדירו את "Payable Model Class" עם שם המודל המלא (לדוגמה:
App\Models\Order) - ניתן גם להגדיר נתיב מותאם אישית
2. דרך קובץ .env:
OFFICEGUY_ENABLE_PUBLIC_CHECKOUT=true OFFICEGUY_ORDER_MODEL=App\Models\Order
שימוש
לאחר ההפעלה, ניתן לגשת לעמוד התשלום בכתובת:
GET /officeguy/checkout/{id}
כאשר {id} הוא המזהה של המודל ה-Payable (למשל מזהה הזמנה).
דוגמה - יצירת קישור תשלום
// יצירת קישור תשלום להזמנה $order = Order::find(123); $checkoutUrl = route('officeguy.public.checkout', ['id' => $order->id]); // שליחת הקישור ללקוח Mail::to($order->customer_email)->send(new PaymentLinkEmail($checkoutUrl));
התאמה אישית של המודל
יש שתי דרכים לחבר את המודל שלכם לעמוד התשלום:
אפשרות 1: מיפוי שדות מ-Admin Panel (ללא שינוי קוד)
ניתן לחבר כל מודל קיים מבלי לשנות את הקוד שלו. פשוט הגדירו את מיפוי השדות ב-Admin Panel:
- גשו ל-SUMIT Gateway > Gateway Settings > Field Mapping
- הזינו את שמות השדות במודל שלכם:
- Amount Field - שדה הסכום (לדוגמה:
total,price,amount) - Currency Field - שדה המטבע (לדוגמה:
currency) או השאירו ריק עבור ILS - Customer Name Field - שדה שם הלקוח
- Customer Email Field - שדה האימייל
- Customer Phone Field - שדה הטלפון
- Description Field - שדה תיאור הפריט
- Amount Field - שדה הסכום (לדוגמה:
המערכת תעטוף אוטומטית את המודל שלכם ותמפה את השדות.
אפשרות 2: מימוש ממשק Payable (למודלים מורכבים)
use OfficeGuy\LaravelSumitGateway\Contracts\Payable; use OfficeGuy\LaravelSumitGateway\Support\Traits\PayableAdapter; class Order extends Model implements Payable { use PayableAdapter; // או מימוש ידני של המתודות }
התאמת העיצוב
פרסמו את התצוגות והתאימו את pages/checkout.blade.php:
php artisan vendor:publish --tag=officeguy-views
לאחר מכן ערכו את הקובץ resources/views/vendor/officeguy/pages/checkout.blade.php להתאמה לעיצוב האתר שלכם.
משתנים זמינים בתצוגה
| משתנה | תיאור |
|---|---|
$payable |
אובייקט ה-Payable (הזמנה/מוצר) |
$settings |
הגדרות שער התשלום |
$maxPayments |
מספר תשלומים מקסימלי |
$bitEnabled |
האם Bit מופעל |
$supportTokens |
האם שמירת כרטיסים מופעלת |
$savedTokens |
אוסף כרטיסים שמורים (למשתמש מחובר) |
$currency |
קוד מטבע (ILS, USD וכו') |
$currencySymbol |
סימן מטבע (₪, $ וכו') |
$checkoutUrl |
כתובת לשליחת הטופס |
Resolver מותאם אישית
ניתן להגדיר resolver מותאם אישית בקונפיגורציה:
// config/officeguy.php 'order' => [ 'resolver' => fn($id) => \App\Models\Product::with('prices')->find($id), ],
רישיון
MIT