109 lines
3.8 KiB
PHP
109 lines
3.8 KiB
PHP
<?php
|
|
|
|
namespace humhub\modules\donations\services;
|
|
|
|
use humhub\modules\donations\events\DonationSettlementEvent;
|
|
use humhub\modules\donations\models\DonationGoal;
|
|
use humhub\modules\donations\models\DonationTransaction;
|
|
use yii\base\Event;
|
|
|
|
class DonationSettlementService
|
|
{
|
|
public const EVENT_AFTER_SUCCEEDED = 'afterSucceeded';
|
|
public const EVENT_AFTER_REFUNDED = 'afterRefunded';
|
|
|
|
public function markSucceededAndApply(DonationTransaction $transaction, array $metadata = []): void
|
|
{
|
|
$payload = $this->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 : [];
|
|
}
|
|
}
|