decodeMetadata($transaction->metadata_json); $applied = !empty($payload['goal_amount_applied']); $goal = null; if ((int)$transaction->goal_id > 0) { $goal = DonationGoal::findOne([ 'id' => (int)$transaction->goal_id, 'contentcontainer_id' => (int)$transaction->contentcontainer_id, ]); } if (!$applied) { if ($goal instanceof DonationGoal) { $goal->current_amount = round((float)$goal->current_amount + (float)$transaction->amount, 2); $goal->save(false); $payload['goal_amount_applied'] = 1; $payload['goal_amount_applied_at'] = date('c'); $payload['goal_amount_applied_value'] = (float)$transaction->amount; } } foreach ($metadata as $key => $value) { $payload[$key] = $value; } $transaction->status = DonationTransaction::STATUS_SUCCEEDED; $event = new DonationSettlementEvent(); $event->transaction = $transaction; $event->goal = $goal; $event->payload = $payload; Event::trigger(self::class, self::EVENT_AFTER_SUCCEEDED, $event); if (is_array($event->payload)) { $payload = $event->payload; } $transaction->metadata_json = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); $transaction->save(false); } public function markRefundedAndRevert(DonationTransaction $transaction, array $metadata = []): void { $payload = $this->decodeMetadata($transaction->metadata_json); $applied = !empty($payload['goal_amount_applied']); $reverted = !empty($payload['goal_amount_reverted']); $goal = null; if ((int)$transaction->goal_id > 0) { $goal = DonationGoal::findOne([ 'id' => (int)$transaction->goal_id, 'contentcontainer_id' => (int)$transaction->contentcontainer_id, ]); } if ($applied && !$reverted) { if ($goal instanceof DonationGoal) { $nextAmount = round((float)$goal->current_amount - (float)$transaction->amount, 2); $goal->current_amount = max(0.0, $nextAmount); $goal->save(false); $payload['goal_amount_reverted'] = 1; $payload['goal_amount_reverted_at'] = date('c'); $payload['goal_amount_reverted_value'] = (float)$transaction->amount; } } foreach ($metadata as $key => $value) { $payload[$key] = $value; } $transaction->status = DonationTransaction::STATUS_REFUNDED; $event = new DonationSettlementEvent(); $event->transaction = $transaction; $event->goal = $goal; $event->payload = $payload; Event::trigger(self::class, self::EVENT_AFTER_REFUNDED, $event); if (is_array($event->payload)) { $payload = $event->payload; } $transaction->metadata_json = json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); $transaction->save(false); } private function decodeMetadata(?string $json): array { $data = json_decode((string)$json, true); return is_array($data) ? $data : []; } }