Skip to content

Commit 02596af

Browse files
feat: Support transaction revisions (#112)
1 parent 6d11512 commit 02596af

File tree

28 files changed

+1121
-1
lines changed

28 files changed

+1121
-1
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66

77
Check our main [developer changelog](https://developer.paddle.com/?utm_source=dx&utm_medium=paddle-php-sdk) for information about changes to the Paddle Billing platform, the Paddle API, and other developer tools.
88

9+
## [Unreleased]
10+
11+
### Added
12+
13+
- Added `transactions.revise` operation to revise a transaction and added `revised_at` to `Transaction` entity, see [related changelog](https://developer.paddle.com/changelog/2024/revise-transaction-customer-information?utm_source=dx&utm_medium=paddle-php-sdk).
14+
- Added support for `transaction.revised` notification, see [related changelog](https://developer.paddle.com/changelog/2024/revise-transaction-customer-information?utm_source=dx&utm_medium=paddle-php-sdk).
15+
16+
### Fixed
17+
- Handle known entity types for events that are not supported by the current SDK version. `UndefinedEvent` will always return an `UndefinedEntity`.
18+
919
## [1.8.0] - 2024-12-19
1020

1121
### Added

examples/transaction_revision.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
use Paddle\SDK\Exceptions\ApiError;
6+
use Paddle\SDK\Exceptions\SdkExceptions\MalformedResponse;
7+
use Paddle\SDK\Resources\Transactions\Operations\Revise\TransactionReviseAddress;
8+
use Paddle\SDK\Resources\Transactions\Operations\Revise\TransactionReviseBusiness;
9+
use Paddle\SDK\Resources\Transactions\Operations\Revise\TransactionReviseCustomer;
10+
use Paddle\SDK\Resources\Transactions\Operations\ReviseTransaction;
11+
12+
require __DIR__ . '/../vendor/autoload.php';
13+
14+
$environment = Paddle\SDK\Environment::tryFrom(getenv('PADDLE_ENVIRONMENT') ?: '') ?? Paddle\SDK\Environment::SANDBOX;
15+
$apiKey = getenv('PADDLE_API_KEY') ?: null;
16+
$transactionId = getenv('PADDLE_TRANSACTION_ID') ?: null;
17+
18+
if (is_null($apiKey)) {
19+
echo "You must provide the PADDLE_API_KEY in the environment:\n";
20+
echo "PADDLE_API_KEY=your-key php examples/basic_usage.php\n";
21+
exit(1);
22+
}
23+
24+
$paddle = new Paddle\SDK\Client($apiKey, options: new Paddle\SDK\Options($environment));
25+
26+
// ┌───
27+
// │ Revise Transaction │
28+
// └────────────────────┘
29+
try {
30+
$transaction = $paddle->transactions->revise(
31+
$transactionId,
32+
new ReviseTransaction(
33+
address: new TransactionReviseAddress(
34+
firstLine: '123 Some Street',
35+
secondLine: null,
36+
),
37+
business: new TransactionReviseBusiness(
38+
name: 'Some Business',
39+
taxIdentifier: '555952383',
40+
),
41+
customer: new TransactionReviseCustomer(
42+
name: 'Some Name',
43+
),
44+
),
45+
);
46+
} catch (ApiError|MalformedResponse $e) {
47+
var_dump($e);
48+
exit;
49+
}
50+
51+
echo sprintf("Transaction ID: %s\n", $transaction->id);
52+
echo sprintf(" - Revised At: %s\n", $transaction->revisedAt->format(DATE_RFC3339_EXTENDED));

src/Entities/Event.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Paddle\SDK\Entities\Event\EventTypeName;
88
use Paddle\SDK\Notifications\Entities\Entity as NotificationEntity;
99
use Paddle\SDK\Notifications\Entities\EntityFactory;
10+
use Paddle\SDK\Notifications\Entities\UndefinedEntity;
1011
use Paddle\SDK\Notifications\Events\UndefinedEvent;
1112
use Psr\Http\Message\ServerRequestInterface;
1213

@@ -33,11 +34,16 @@ public static function from(array $data): self
3334
$event = UndefinedEvent::class;
3435
}
3536

37+
// Create an undefined entity for undefined events.
38+
$entity = $event === UndefinedEvent::class
39+
? UndefinedEntity::from($data['data'])
40+
: EntityFactory::create($data['event_type'], $data['data']);
41+
3642
return $event::fromEvent(
3743
$data['event_id'],
3844
EventTypeName::from($data['event_type']),
3945
DateTime::from($data['occurred_at']),
40-
EntityFactory::create($data['event_type'], $data['data']),
46+
$entity,
4147
$data['notification_id'] ?? null,
4248
);
4349
}

src/Entities/Event/EventTypeName.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
* @method static EventTypeName TransactionPastDue()
5353
* @method static EventTypeName TransactionPaymentFailed()
5454
* @method static EventTypeName TransactionReady()
55+
* @method static EventTypeName TransactionRevised()
5556
* @method static EventTypeName TransactionUpdated()
5657
* @method static EventTypeName ReportCreated()
5758
* @method static EventTypeName ReportUpdated()
@@ -103,6 +104,7 @@ final class EventTypeName extends PaddleEnum
103104
private const TransactionPastDue = 'transaction.past_due';
104105
private const TransactionPaymentFailed = 'transaction.payment_failed';
105106
private const TransactionReady = 'transaction.ready';
107+
private const TransactionRevised = 'transaction.revised';
106108
private const TransactionUpdated = 'transaction.updated';
107109
private const ReportCreated = 'report.created';
108110
private const ReportUpdated = 'report.updated';

src/Entities/Transaction.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ private function __construct(
6363
public Customer|null $customer,
6464
public Discount|null $discount,
6565
public array $availablePaymentMethods,
66+
public \DateTimeInterface|null $revisedAt,
6667
) {
6768
}
6869

@@ -98,6 +99,7 @@ public static function from(array $data): self
9899
customer: isset($data['customer']) ? Customer::from($data['customer']) : null,
99100
discount: isset($data['discount']) ? Discount::from($data['discount']) : null,
100101
availablePaymentMethods: array_map(fn (string $item): AvailablePaymentMethods => AvailablePaymentMethods::from($item), $data['available_payment_methods'] ?? []),
102+
revisedAt: isset($data['revised_at']) ? DateTime::from($data['revised_at']) : null,
101103
);
102104
}
103105
}

src/Notifications/Entities/Transaction.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ private function __construct(
5252
public \DateTimeInterface $createdAt,
5353
public \DateTimeInterface $updatedAt,
5454
public \DateTimeInterface|null $billedAt,
55+
public \DateTimeInterface|null $revisedAt,
5556
) {
5657
}
5758

@@ -80,6 +81,7 @@ public static function from(array $data): self
8081
createdAt: DateTime::from($data['created_at']),
8182
updatedAt: DateTime::from($data['updated_at']),
8283
billedAt: isset($data['billed_at']) ? DateTime::from($data['billed_at']) : null,
84+
revisedAt: isset($data['revised_at']) ? DateTime::from($data['revised_at']) : null,
8385
);
8486
}
8587
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Paddle\SDK\Notifications\Events;
6+
7+
use Paddle\SDK\Entities\Event;
8+
use Paddle\SDK\Entities\Event\EventTypeName;
9+
use Paddle\SDK\Notifications\Entities\Entity;
10+
use Paddle\SDK\Notifications\Entities\Transaction;
11+
12+
final class TransactionRevised extends Event
13+
{
14+
private function __construct(
15+
string $eventId,
16+
EventTypeName $eventType,
17+
\DateTimeInterface $occurredAt,
18+
public readonly Transaction $transaction,
19+
string|null $notificationId,
20+
) {
21+
parent::__construct($eventId, $eventType, $occurredAt, $transaction, $notificationId);
22+
}
23+
24+
/**
25+
* @param Transaction $data
26+
*/
27+
public static function fromEvent(
28+
string $eventId,
29+
EventTypeName $eventType,
30+
\DateTimeInterface $occurredAt,
31+
Entity $data,
32+
string|null $notificationId = null,
33+
): static {
34+
return new self($eventId, $eventType, $occurredAt, $data, $notificationId);
35+
}
36+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Paddle\SDK\Resources\Transactions\Operations\Revise;
6+
7+
use Paddle\SDK\FiltersUndefined;
8+
use Paddle\SDK\Undefined;
9+
10+
class TransactionReviseAddress implements \JsonSerializable
11+
{
12+
use FiltersUndefined;
13+
14+
public function __construct(
15+
public readonly string|Undefined $firstLine = new Undefined(),
16+
public readonly string|Undefined|null $secondLine = new Undefined(),
17+
public readonly string|Undefined $city = new Undefined(),
18+
public readonly string|Undefined $region = new Undefined(),
19+
) {
20+
}
21+
22+
public function jsonSerialize(): array
23+
{
24+
return $this->filterUndefined([
25+
'first_line' => $this->firstLine,
26+
'second_line' => $this->secondLine,
27+
'city' => $this->city,
28+
'region' => $this->region,
29+
]);
30+
}
31+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Paddle\SDK\Resources\Transactions\Operations\Revise;
6+
7+
use Paddle\SDK\FiltersUndefined;
8+
use Paddle\SDK\Undefined;
9+
10+
class TransactionReviseBusiness implements \JsonSerializable
11+
{
12+
use FiltersUndefined;
13+
14+
public function __construct(
15+
public readonly string|Undefined $name = new Undefined(),
16+
public readonly string|Undefined $taxIdentifier = new Undefined(),
17+
) {
18+
}
19+
20+
public function jsonSerialize(): array
21+
{
22+
return $this->filterUndefined([
23+
'name' => $this->name,
24+
'tax_identifier' => $this->taxIdentifier,
25+
]);
26+
}
27+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Paddle\SDK\Resources\Transactions\Operations\Revise;
6+
7+
use Paddle\SDK\FiltersUndefined;
8+
use Paddle\SDK\Undefined;
9+
10+
class TransactionReviseCustomer implements \JsonSerializable
11+
{
12+
use FiltersUndefined;
13+
14+
public function __construct(
15+
public readonly string|Undefined $name = new Undefined(),
16+
) {
17+
}
18+
19+
public function jsonSerialize(): array
20+
{
21+
return $this->filterUndefined([
22+
'name' => $this->name,
23+
]);
24+
}
25+
}

0 commit comments

Comments
 (0)