mirror of
https://github.com/opensourcepos/opensourcepos.git
synced 2026-04-02 22:36:21 -04:00
This commit introduces a comprehensive payment provider architecture to enable
seamless integration with external payment gateways like SumUp and PayPal/Zettle.
Architecture:
- PaymentProviderInterface: Contract for all payment providers
- PaymentProviderBase: Abstract base class with common functionality
- PaymentProviderRegistry: Singleton registry for provider management
- PaymentTransaction model: Transaction tracking and status management
Infrastructure:
- Webhook controller: Endpoint for external payment callbacks
- Payment events: payment_initiated, payment_completed, sale_completed
- payment_helper.php: Helper functions for payment provider content
- Migration for ospos_payment_transactions table
Core changes:
- Add Events::trigger('payment_options') in locale_helper.php
- Add Events::trigger('sale_completed') in Sales controller
- Add Events::trigger('payment_initiated') in postAddPayment()
- Add webhook routes for /payments/webhook/{provider}
Provider stubs:
- SumUpProvider: Card reader terminal integration
- PayPalProvider: Card reader and QR code payment integration
Related issues: #4346, #4322, #3232, #3789, #3790, #2275
82 lines
2.3 KiB
PHP
82 lines
2.3 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use CodeIgniter\Model;
|
|
|
|
class PaymentTransaction extends Model
|
|
{
|
|
protected $table = 'payment_transactions';
|
|
protected $primaryKey = 'id';
|
|
protected $useAutoIncrement = true;
|
|
protected $useSoftDeletes = false;
|
|
protected $allowedFields = [
|
|
'provider_id',
|
|
'sale_id',
|
|
'transaction_id',
|
|
'amount',
|
|
'currency',
|
|
'status',
|
|
'metadata',
|
|
'created_at',
|
|
'updated_at'
|
|
];
|
|
protected $useTimestamps = true;
|
|
protected $createdField = 'created_at';
|
|
protected $updatedField = 'updated_at';
|
|
|
|
public const STATUS_PENDING = 'pending';
|
|
public const STATUS_AUTHORIZED = 'authorized';
|
|
public const STATUS_COMPLETED = 'completed';
|
|
public const STATUS_FAILED = 'failed';
|
|
public const STATUS_REFUNDED = 'refunded';
|
|
public const STATUS_CANCELLED = 'cancelled';
|
|
|
|
public function getTransaction(string $transactionId, ?string $providerId = null): ?array
|
|
{
|
|
$builder = $this->builder();
|
|
$builder->where('transaction_id', $transactionId);
|
|
|
|
if ($providerId !== null) {
|
|
$builder->where('provider_id', $providerId);
|
|
}
|
|
|
|
$result = $builder->get()->getRowArray();
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function getTransactionsBySale(int $saleId): array
|
|
{
|
|
return $this->where('sale_id', $saleId)
|
|
->orderBy('created_at', 'DESC')
|
|
->findAll();
|
|
}
|
|
|
|
public function getPendingTransactions(?string $providerId = null): array
|
|
{
|
|
$builder = $this->builder();
|
|
$builder->where('status', self::STATUS_PENDING);
|
|
|
|
if ($providerId !== null) {
|
|
$builder->where('provider_id', $providerId);
|
|
}
|
|
|
|
return $builder->get()->getResultArray();
|
|
}
|
|
|
|
public function updateStatus(int $id, string $status, array $additionalData = []): bool
|
|
{
|
|
$data = ['status' => $status];
|
|
|
|
if (!empty($additionalData['metadata'])) {
|
|
$existing = $this->find($id);
|
|
if ($existing) {
|
|
$existingMetadata = json_decode($existing['metadata'] ?? '{}', true);
|
|
$data['metadata'] = json_encode(array_merge($existingMetadata, $additionalData['metadata']));
|
|
}
|
|
}
|
|
|
|
return $this->update($id, $data);
|
|
}
|
|
} |