update to provisioner code nwew paddle code
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Services\Payments;
|
||||
|
||||
use Illuminate\Http\Client\PendingRequest;
|
||||
use Illuminate\Http\Client\Response;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use RuntimeException;
|
||||
@@ -19,60 +20,147 @@ final class PaddleClient
|
||||
if (! $response->successful()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$data = $response->json('data');
|
||||
|
||||
return is_array($data) ? $data : null;
|
||||
}
|
||||
|
||||
public function updateSubscriptionPrice(string $subscriptionID, string $priceID): array
|
||||
public function subscription(string $subscriptionID): array
|
||||
{
|
||||
$this->requireWritableConfiguration();
|
||||
|
||||
$response = $this->request()->patch('/subscriptions/'.$subscriptionID, [
|
||||
'proration_billing_mode' => 'prorated_immediately',
|
||||
'items' => [[
|
||||
'price_id' => $priceID,
|
||||
'quantity' => 1,
|
||||
]],
|
||||
]);
|
||||
$response = $this->request()
|
||||
->get('/subscriptions/'.$subscriptionID);
|
||||
|
||||
return $this->subscriptionData($response, 'Paddle could not update the subscription.');
|
||||
return $this->subscriptionData(
|
||||
$response,
|
||||
'Paddle could not retrieve the subscription.'
|
||||
);
|
||||
}
|
||||
|
||||
public function cancelSubscriptionImmediately(string $subscriptionID): array
|
||||
{
|
||||
public function updateSubscriptionPrice(
|
||||
string $subscriptionID,
|
||||
string $priceID
|
||||
): array {
|
||||
$this->requireWritableConfiguration();
|
||||
|
||||
$response = $this->request()->post('/subscriptions/'.$subscriptionID.'/cancel', [
|
||||
'effective_from' => 'immediately',
|
||||
]);
|
||||
/*
|
||||
* Paddle restricts subscription item changes while a subscription
|
||||
* is trialing. Existing item quantities may only be updated using
|
||||
* do_not_bill during the trial.
|
||||
*
|
||||
* Once the subscription is outside its trial we can use normal
|
||||
* immediate proration.
|
||||
*/
|
||||
$subscription = $this->subscription($subscriptionID);
|
||||
|
||||
return $this->subscriptionData($response, 'Paddle could not cancel the subscription.');
|
||||
$status = (string) ($subscription['status'] ?? '');
|
||||
|
||||
$prorationBillingMode = $status === 'trialing'
|
||||
? 'do_not_bill'
|
||||
: 'prorated_immediately';
|
||||
|
||||
/*
|
||||
* Preserve the existing subscription item and replace its price.
|
||||
*
|
||||
* Paddle treats the submitted items array as the desired
|
||||
* subscription items, so quantity is retained where possible.
|
||||
*/
|
||||
$existingItems = is_array($subscription['items'] ?? null)
|
||||
? $subscription['items']
|
||||
: [];
|
||||
|
||||
$existingItem = $existingItems[0] ?? [];
|
||||
|
||||
$quantity = max(
|
||||
1,
|
||||
(int) ($existingItem['quantity'] ?? 1)
|
||||
);
|
||||
|
||||
$response = $this->request()->patch(
|
||||
'/subscriptions/'.$subscriptionID,
|
||||
[
|
||||
'proration_billing_mode' => $prorationBillingMode,
|
||||
'items' => [
|
||||
[
|
||||
'price_id' => $priceID,
|
||||
'quantity' => $quantity,
|
||||
],
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
return $this->subscriptionData(
|
||||
$response,
|
||||
'Paddle could not update the subscription.'
|
||||
);
|
||||
}
|
||||
|
||||
private function request()
|
||||
public function cancelSubscriptionImmediately(
|
||||
string $subscriptionID
|
||||
): array {
|
||||
$this->requireWritableConfiguration();
|
||||
|
||||
$response = $this->request()->post(
|
||||
'/subscriptions/'.$subscriptionID.'/cancel',
|
||||
[
|
||||
'effective_from' => 'immediately',
|
||||
]
|
||||
);
|
||||
|
||||
return $this->subscriptionData(
|
||||
$response,
|
||||
'Paddle could not cancel the subscription.'
|
||||
);
|
||||
}
|
||||
|
||||
private function request(): PendingRequest
|
||||
{
|
||||
return Http::baseUrl((string) config('sonardesk.paddle.api_url'))
|
||||
->withToken((string) config('sonardesk.paddle.api_key'))
|
||||
return Http::baseUrl(
|
||||
(string) config('sonardesk.paddle.api_url')
|
||||
)
|
||||
->withToken(
|
||||
(string) config('sonardesk.paddle.api_key')
|
||||
)
|
||||
->acceptJson()
|
||||
->timeout(15);
|
||||
}
|
||||
|
||||
private function requireWritableConfiguration(): void
|
||||
{
|
||||
if (trim((string) config('sonardesk.paddle.api_key')) === '') {
|
||||
throw new RuntimeException('Paddle subscription management is not configured.');
|
||||
if (
|
||||
trim(
|
||||
(string) config('sonardesk.paddle.api_key')
|
||||
) === ''
|
||||
) {
|
||||
throw new RuntimeException(
|
||||
'Paddle subscription management is not configured.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function subscriptionData(Response $response, string $fallback): array
|
||||
{
|
||||
private function subscriptionData(
|
||||
Response $response,
|
||||
string $fallback
|
||||
): array {
|
||||
if (! $response->successful()) {
|
||||
$detail = trim((string) ($response->json('error.detail') ?? ''));
|
||||
throw new RuntimeException($detail !== '' ? $detail : $fallback);
|
||||
$detail = trim(
|
||||
(string) (
|
||||
$response->json('error.detail')
|
||||
?? ''
|
||||
)
|
||||
);
|
||||
|
||||
throw new RuntimeException(
|
||||
$detail !== ''
|
||||
? $detail
|
||||
: $fallback
|
||||
);
|
||||
}
|
||||
|
||||
$data = $response->json('data');
|
||||
|
||||
if (! is_array($data)) {
|
||||
throw new RuntimeException($fallback);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user