-
Notifications
You must be signed in to change notification settings - Fork 1
/
PayPalPayment.php
115 lines (93 loc) · 3.55 KB
/
PayPalPayment.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
<?php
declare( strict_types = 1 );
namespace WMDE\Fundraising\PaymentContext\Domain\Model;
use DateTimeImmutable;
use DomainException;
use WMDE\Euro\Euro;
use WMDE\Fundraising\PaymentContext\Domain\Model\BookingDataTransformers\PayPalBookingTransformer;
use WMDE\Fundraising\PaymentContext\Domain\Repositories\PaymentIDRepository;
class PayPalPayment extends Payment implements BookablePayment {
use LegacyBookingStatusTrait;
private const PAYMENT_METHOD = 'PPL';
/**
* @var array<string,string>
*/
private array $bookingData;
private ?PayPalPayment $parentPayment = null;
private ?DateTimeImmutable $valuationDate = null;
public function __construct( int $id, Euro $amount, PaymentInterval $interval ) {
parent::__construct( $id, $amount, $interval, self::PAYMENT_METHOD );
$this->bookingData = [];
}
public function getValuationDate(): ?DateTimeImmutable {
return $this->valuationDate;
}
public function isBooked(): bool {
return $this->valuationDate !== null && !empty( $this->bookingData );
}
public function canBeBooked( array $transactionData ): bool {
// Unbooked payments can always be booked
if ( !$this->isBooked() ) {
return true;
}
// Booked "parent" payments (where "parentPayment" is null) can be booked as followup payments
return $this->parentPayment === null && $this->isRecurringPayment();
}
/**
* @param array<string,mixed> $transactionData Payment information from PayPal
* @param PaymentIDRepository $idGenerator Used for creating followup payments
* @return PayPalPayment
*
*/
public function bookPayment( array $transactionData, PaymentIDRepository $idGenerator ): PayPalPayment {
$transformer = new PayPalBookingTransformer( $transactionData );
if ( !$this->canBeBooked( $transactionData ) ) {
throw new DomainException( 'Payment is already completed' );
}
if ( $this->isFollowupBooking() ) {
return $this->createFollowUpPayment( $transactionData, $idGenerator );
}
$this->bookingData = $transformer->getBookingData();
$this->valuationDate = $transformer->getValuationDate();
return $this;
}
protected function getPaymentName(): string {
return self::PAYMENT_METHOD;
}
protected function getPaymentSpecificLegacyData(): array {
if ( $this->isBooked() ) {
return ( new PayPalBookingTransformer( $this->bookingData ) )->getLegacyData();
}
return [];
}
/**
* Create a booked followup payment
*
* @param array<string,mixed> $transactionData
* @param PaymentIDRepository $idGenerator
* @return PayPalPayment
*/
private function createFollowUpPayment( array $transactionData, PaymentIDRepository $idGenerator ): PayPalPayment {
$followupPayment = new PayPalPayment( $idGenerator->getNewID(), $this->amount, $this->interval );
$followupPayment->parentPayment = $this;
return $followupPayment->bookPayment( $transactionData, $idGenerator );
}
private function isFollowupBooking(): bool {
// In the future, we might pass the new transaction data to this function, comparing
// `txn_id` of this payment with the booking data, to distinguish between double booking (should return false)
// and followup booking
// Tracked in https://phabricator.wikimedia.org/T305257
return $this->isBooked() && $this->parentPayment === null && $this->isRecurringPayment();
}
private function isRecurringPayment(): bool {
return $this->interval !== PaymentInterval::OneTime;
}
public function getDisplayValues(): array {
$parentValues = parent::getDisplayValues();
$subtypeValues = $this->getPaymentSpecificLegacyData();
return array_merge(
$parentValues,
$subtypeValues
);
}
}