PluginProbe
The Innovative Form Builder – IvyForms / 1.5
The Innovative Form Builder – IvyForms v1.5
1.5.1 1.5 1.4.1 1.4 trunk 0.1.2 0.2 0.2.1 0.3 0.3.1 0.4 0.5 0.6 0.6.1 0.6.1-backup 0.6.1.1 0.7 0.8 0.8.1 0.8.2 0.9 0.9.1 1.0 1.1 1.1.1 All 27 releases
ivyforms / backend / src / Services / Payment / PaymentManager.php

PaymentManager.php in The Innovative Form Builder – IvyForms 1.5, at backend/src/Services/Payment/PaymentManager.php

157 lines 4.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace IvyForms\Services\Payment;
4
5 use IvyForms\Common\Exceptions\QueryExecutionException;
6 use IvyForms\Entity\Payment\Payment;
7 use IvyForms\Repository\Payment\PaymentRepositoryInterface;
8
9 class PaymentManager
10 {
11 private PaymentRepositoryInterface $paymentRepository;
12
13 private PaymentListCustomerName $paymentListCustomerName;
14
15 public function __construct(
16 PaymentRepositoryInterface $paymentRepository,
17 PaymentListCustomerName $paymentListCustomerName
18 ) {
19 $this->paymentRepository = $paymentRepository;
20 $this->paymentListCustomerName = $paymentListCustomerName;
21 }
22
23 public function createPayment(Payment $payment): int
24 {
25 return $this->paymentRepository->add($payment);
26 }
27
28 public function getPaymentByEntryId(int $entryId): ?Payment
29 {
30 return $this->paymentRepository->getByEntryId($entryId);
31 }
32
33 public function paymentExistsByTransactionId(string $transactionId): bool
34 {
35 return $this->paymentRepository->existsByTransactionId($transactionId);
36 }
37
38 public function paymentAlreadyLinkedToEntry(string $transactionId): bool
39 {
40 $existing = $this->getByTransactionId($transactionId);
41
42 return $existing !== null && (int) $existing->getEntryId() > 0;
43 }
44
45 public function getByTransactionId(string $transactionId): ?Payment
46 {
47 return $this->paymentRepository->getByTransactionId($transactionId);
48 }
49
50 public function getPaymentByTransactionId(string $transactionId): ?Payment
51 {
52 return $this->getByTransactionId($transactionId);
53 }
54
55 public function getPaymentByProviderOrderId(string $orderId): ?Payment
56 {
57 return $this->paymentRepository->findByProviderOrderId($orderId);
58 }
59
60 public function updatePaymentStatus(int $id, string $status): bool
61 {
62 return $this->paymentRepository->updateStatus($id, $status);
63 }
64
65 public function updatePayment(Payment $payment): void
66 {
67 $this->paymentRepository->update($payment);
68 }
69
70 /**
71 * Insert or update a payment keyed by transactionId (Stripe PaymentIntent id).
72 * Returns false when a succeeded payment is already linked to an entry.
73 */
74 public function upsertByTransactionId(Payment $payment): bool
75 {
76 $existing = $this->getByTransactionId($payment->getTransactionId());
77 if ($existing === null) {
78 return $this->insertOrReload($payment);
79 }
80
81 return $this->updateExistingPayment($existing, $payment);
82 }
83
84 private function insertOrReload(Payment $payment): bool
85 {
86 try {
87 $this->createPayment($payment);
88
89 return true;
90 } catch (QueryExecutionException $e) {
91 $existing = $this->getByTransactionId($payment->getTransactionId());
92 if ($existing === null) {
93 throw $e;
94 }
95
96 return $this->updateExistingPayment($existing, $payment);
97 }
98 }
99
100 private function updateExistingPayment(Payment $existing, Payment $incoming): bool
101 {
102 if ($this->isDuplicateSucceeded($existing, $incoming)) {
103 return false;
104 }
105
106 if ($existing->getStatus() === 'succeeded' && $incoming->getStatus() !== 'succeeded') {
107 return true;
108 }
109
110 $this->mergePaymentUpdate($existing, $incoming);
111 $this->updatePayment($existing);
112
113 return true;
114 }
115
116 private function isDuplicateSucceeded(Payment $existing, Payment $incoming): bool
117 {
118 return $existing->getStatus() === 'succeeded'
119 && $existing->getEntryId()
120 && $incoming->getStatus() === 'succeeded'
121 && $incoming->getEntryId();
122 }
123
124 private function mergePaymentUpdate(Payment $existing, Payment $incoming): void
125 {
126 $existing->setStatus($incoming->getStatus());
127 if ($incoming->getEntryId()) {
128 $existing->setEntryId($incoming->getEntryId());
129 }
130 if ($incoming->getSquareReceiptUrl()) {
131 $existing->setSquareReceiptUrl($incoming->getSquareReceiptUrl());
132 }
133 if ($incoming->getProviderMeta()) {
134 $existing->setProviderMeta($incoming->getProviderMeta());
135 }
136 if ($incoming->getCustomerName()) {
137 $existing->setCustomerName($incoming->getCustomerName());
138 }
139 }
140
141 /**
142 * @param array<string, mixed> $criteria
143 * @return array{items: array<int, array<string, mixed>>, total: int, meta: array<string, mixed>}
144 */
145 public function searchPayments(array $criteria): array
146 {
147 $result = $this->paymentRepository->search($criteria);
148 $items = $this->paymentListCustomerName->attach($result['data'] ?? []);
149
150 return [
151 'items' => $items,
152 'total' => (int) ($result['meta']['total'] ?? 0),
153 'meta' => $result['meta'],
154 ];
155 }
156 }
157