PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.0
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.0
1.6.6 1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 All 49 releases
fluent-cart / app / Services / Payments / Refund.php

Refund.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.6.0, at app/Services/Payments/Refund.php

184 lines 7.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Services\Payments;
4
5 use FluentCart\Api\Resource\OrderResource;
6 use FluentCart\App\App;
7 use FluentCart\App\Events\Order\OrderRefund;
8 use FluentCart\App\Helpers\Helper;
9 use FluentCart\App\Helpers\Status;
10 use FluentCart\App\Models\Order;
11 use FluentCart\App\Models\OrderTransaction;
12 use FluentCart\App\Services\DateTime\DateTime;
13 use FluentCart\Framework\Support\Arr;
14
15 class Refund
16 {
17 public function processRefund($transaction, $refundAmount, $args = [])
18 {
19
20 $args = wp_parse_args($args, [
21 'reason' => '',
22 'item_ids' => [],
23 'manageStock' => false,
24 ]);
25
26 $order = $transaction->order;
27
28
29 if ($refundAmount <= 0) {
30 return new \WP_Error('invalid_refund_amount', __('Invalid refund amount.', 'fluent-cart'));
31 }
32
33 $netOrderPaidAmount = $order->total_paid - $order->total_refunded;
34 if ($refundAmount > $netOrderPaidAmount) {
35 return new \WP_Error('invalid_refund_amount', __('Refund amount exceeds the net paid amount for this order.', 'fluent-cart'));
36 }
37
38 if ($transaction->getMaxRefundableAmount() < $refundAmount) {
39 return new \WP_Error('invalid_refund_amount', __('Refund amount exceeds the maximum refundable amount for this transaction.', 'fluent-cart'));
40 }
41
42 $orderTransactions = [
43 'order_id' => $transaction->order_id,
44 'order_type' => $order->type,
45 'payment_method' => $transaction->payment_method,
46 'payment_mode' => $transaction->payment_mode,
47 'payment_method_type' => $transaction->payment_method_type,
48 'transaction_type' => Status::TRANSACTION_TYPE_REFUND,
49 'subscription_id' => $transaction->subscription_id,
50 'status' => Status::TRANSACTION_REFUNDED,
51 'currency' => $transaction->currency,
52 'total' => $refundAmount,
53 'meta' => [
54 'parent_id' => $transaction->id,
55 'reason' => $args['reason'] ?? '',
56 ],
57 'uuid' => md5(time() . wp_generate_uuid4())
58 ];
59
60 $refundTransaction = OrderTransaction::query()->create($orderTransactions);
61
62 // update the main parent transaction meta
63 PaymentHelper::updateTransactionRefundedTotal($transaction, $refundAmount);
64
65 $manualRefund = apply_filters('fluent_cart/order_refund_manually', [
66 'status' => 'no',
67 'source' => ''
68 ], [
69 'refund_amount' => $refundAmount,
70 'transaction' => $transaction,
71 'order' => $order,
72 'args' => $args
73 ]);
74
75 if (!is_array($manualRefund)) {
76 $manualRefund = ['status' => 'no', 'source' => ''];
77 }
78
79 $vendorRefundId = null;
80
81
82 if (Arr::get($manualRefund, 'status') !== 'yes') {
83 if ($gateway = App::gateway($transaction->payment_method)) {
84 if ($gateway->has('refund')) {
85 $vendorRefundId = $gateway->processRefund($transaction, $refundAmount, $args);
86 }
87 }
88
89 if (!is_wp_error($vendorRefundId) && $vendorRefundId) {
90 $refundTransaction->vendor_charge_id = $vendorRefundId;
91 $refundTransaction->save();
92 }
93 }
94
95 $manageStock = filter_var(Arr::get($args, 'manageStock'), FILTER_VALIDATE_BOOLEAN);
96
97 (new OrderRefund($order, $refundTransaction, Arr::get($args, 'item_ids'), $manageStock, Arr::get($args, 'refunded_items', [])))->dispatch();
98
99 return [
100 'refund_transaction' => $refundTransaction,
101 'vendor_refund_id' => $vendorRefundId,
102 'manual_refund' => $manualRefund
103 ];
104 }
105
106
107 public static function createOrRecordRefund($refundData, OrderTransaction $parentTransaction)
108 {
109 /*
110 * check for existing refund transaction with this vendor charge ID
111 * check for local refunds
112 * */
113 // check for existing refund transactions
114 $allRefunds = OrderTransaction::query()
115 ->where('order_id', $parentTransaction->order_id)
116 ->where('transaction_type', Status::TRANSACTION_TYPE_REFUND)
117 ->orderBy('id', 'DESC')
118 ->get();
119
120 foreach ($allRefunds as $refund) {
121 if ($refund->vendor_charge_id == $refundData['vendor_charge_id']) {
122 // this refund already exists
123 return $refund;
124 }
125
126 if (!$refund->vendor_charge_id) { // this is a local refund without vendor charge id
127 $refundParentId = Arr::get($refund->meta, 'parent_id', '');
128 $isTransactionMatched = $refundParentId == $parentTransaction->id;
129 // this is a local refund without vendor charge id, we will update it
130 if ($refund->total == $refundData['total'] && $isTransactionMatched) {
131 // this refund already exists
132 $refund->vendor_charge_id = $refundData['vendor_charge_id'];
133 $refund->save();
134 return $refund;
135 }
136 }
137 }
138
139 return self::recordRefund($refundData, $parentTransaction);
140 }
141
142 public static function recordRefund($refundData, OrderTransaction $parentTransaction)
143 {
144 if (empty($refundData['total']) || $refundData['total'] <= 0) {
145 return new \WP_Error('invalid_refund_amount', __('Invalid refund amount.', 'fluent-cart'));
146 }
147
148 $status = Arr::get($refundData, 'status', Status::TRANSACTION_REFUNDED);
149
150
151 $defaults = [
152 'order_id' => $parentTransaction->order_id,
153 'order_type' => $parentTransaction->order_type,
154 'transaction_type' => Status::TRANSACTION_TYPE_REFUND,
155 'subscription_id' => $parentTransaction->subscription_id,
156 'card_last_4' => $parentTransaction->card_last_4,
157 'card_brand' => $parentTransaction->card_brand,
158 'payment_method' => $parentTransaction->payment_method,
159 'payment_mode' => $parentTransaction->payment_mode,
160 'payment_method_type' => $parentTransaction->payment_method_type,
161 'status' => $status,
162 'currency' => $parentTransaction->currency,
163 'meta' => [
164 'parent_id' => $parentTransaction->id,
165 'reason' => Arr::get($refundData, 'reason', ''),
166 ]
167 ];
168
169 unset($refundData['reason']);
170
171 $refundData = wp_parse_args($refundData, $defaults);
172 $createdRefund = OrderTransaction::query()->create($refundData);
173
174 PaymentHelper::updateTransactionRefundedTotal($parentTransaction, $createdRefund->total);
175
176 if ($status === Status::TRANSACTION_REFUNDED) {
177 (new OrderRefund($parentTransaction->order, $createdRefund))->dispatch();
178 }
179
180 return $createdRefund;
181 }
182
183 }
184