Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a3004b382b | ||
|
|
60e6be57f9 | ||
|
|
7d244da111 | ||
|
|
e9b01b5266 | ||
|
|
db79fee3d2 | ||
|
|
3118f9e4e0 |
2
.github/workflows/code_style.yml
vendored
2
.github/workflows/code_style.yml
vendored
@ -8,7 +8,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Run PHP CS Fixer
|
||||
uses: docker://oskarstark/php-cs-fixer-ga
|
||||
|
||||
4
.github/workflows/psalm.yml
vendored
4
.github/workflows/psalm.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
||||
php-versions: ['8.0']
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: '0'
|
||||
|
||||
@ -27,7 +27,7 @@ jobs:
|
||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- name: Cache composer dependencies
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -3,4 +3,5 @@
|
||||
.php-cs-fixer.cache
|
||||
*.cache
|
||||
composer.lock
|
||||
/tests/.env
|
||||
/tests/.env
|
||||
/.claude/
|
||||
@ -43,7 +43,7 @@ class PullPayments
|
||||
$autoApproveClaims = false;
|
||||
$startsAt = null;
|
||||
$expiresAt = null;
|
||||
$paymentMethods = ['BTC'];
|
||||
$paymentMethods = ['BTC-CHAIN'];
|
||||
|
||||
try {
|
||||
$client = new PullPayment($this->host, $this->apiKey);
|
||||
@ -163,7 +163,7 @@ class PullPayments
|
||||
$pullPaymentId = '';
|
||||
$destination = '';
|
||||
$amount = PreciseNumber::parseString('0.000001');
|
||||
$paymentMethod = '';
|
||||
$paymentMethod = 'BTC-CHAIN';
|
||||
|
||||
try {
|
||||
$client = new PullPayment($this->host, $this->apiKey);
|
||||
|
||||
242
examples/subscriptions.php
Normal file
242
examples/subscriptions.php
Normal file
@ -0,0 +1,242 @@
|
||||
<?php
|
||||
|
||||
// Include autoload file.
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
// Import Subscriptions client class.
|
||||
use BTCPayServer\Client\Subscriptions;
|
||||
|
||||
// Fill in with your BTCPay Server data.
|
||||
$apiKey = '';
|
||||
$host = ''; // e.g. https://your.btcpay-server.tld
|
||||
$storeId = '';
|
||||
|
||||
// Create the subscriptions client.
|
||||
try {
|
||||
$client = new Subscriptions($host, $apiKey);
|
||||
|
||||
echo "=== BTCPay Server Subscriptions API Examples ===\n\n";
|
||||
|
||||
// 1. Create a new offering
|
||||
echo "1. Creating a new offering...\n";
|
||||
$offering = $client->createOffering(
|
||||
$storeId,
|
||||
'Premium SaaS App',
|
||||
'https://example.com/success',
|
||||
[
|
||||
'category' => 'saas',
|
||||
'region' => 'us',
|
||||
'version' => '1.0'
|
||||
],
|
||||
[
|
||||
['id' => 'feature-analytics', 'description' => 'Advanced analytics dashboard'],
|
||||
['id' => 'feature-support', 'description' => '24/7 priority support'],
|
||||
['id' => 'feature-api', 'description' => 'Unlimited API access']
|
||||
]
|
||||
);
|
||||
echo "Offering created with ID: " . $offering->getId() . "\n";
|
||||
echo "App Name: " . $offering->getAppName() . "\n\n";
|
||||
|
||||
$offeringId = $offering->getId();
|
||||
|
||||
// 2. Create plans for the offering
|
||||
echo "2. Creating plans for the offering...\n";
|
||||
|
||||
// Basic plan
|
||||
$basicPlan = $client->createOfferingPlan(
|
||||
$storeId,
|
||||
$offeringId,
|
||||
'Basic monthly subscription with essential features',
|
||||
'USD',
|
||||
7,
|
||||
'Basic Plan',
|
||||
true,
|
||||
'1.99',
|
||||
true,
|
||||
null,
|
||||
['tier' => 'basic'],
|
||||
'Monthly',
|
||||
['feature-analytics']
|
||||
);
|
||||
echo "Basic plan created with ID: " . $basicPlan->getId() . "\n";
|
||||
|
||||
// Premium plan
|
||||
$premiumPlan = $client->createOfferingPlan(
|
||||
$storeId,
|
||||
$offeringId,
|
||||
'Premium monthly subscription with all features',
|
||||
'USD',
|
||||
7,
|
||||
'Premium Plan',
|
||||
true,
|
||||
'29.99',
|
||||
true,
|
||||
14,
|
||||
['tier' => 'premium'],
|
||||
'Monthly',
|
||||
['feature-analytics', 'feature-support', 'feature-api']
|
||||
);
|
||||
echo "Premium plan created with ID: " . $premiumPlan->getId() . "\n\n";
|
||||
|
||||
$basicPlanId = $basicPlan->getId();
|
||||
$premiumPlanId = $premiumPlan->getId();
|
||||
|
||||
// 2b. Update the offering
|
||||
echo "2b. Updating the offering...\n";
|
||||
$updatedOffering = $client->updateOffering(
|
||||
$storeId,
|
||||
$offeringId,
|
||||
'Premium SaaS App v2',
|
||||
'https://example.com/success-v2',
|
||||
['category' => 'saas', 'region' => 'eu', 'version' => '2.0']
|
||||
);
|
||||
echo "Offering updated: " . $updatedOffering->getAppName() . "\n\n";
|
||||
|
||||
// 2c. Update a plan
|
||||
echo "2c. Updating the basic plan...\n";
|
||||
$updatedPlan = $client->updateOfferingPlan(
|
||||
$storeId,
|
||||
$offeringId,
|
||||
$basicPlanId,
|
||||
'Updated basic monthly subscription',
|
||||
'USD',
|
||||
7,
|
||||
'Basic Plan v2',
|
||||
null,
|
||||
'2.99'
|
||||
);
|
||||
echo "Plan updated: " . $updatedPlan->getName() . " - " . $updatedPlan->getPrice() . " " . $updatedPlan->getCurrency() . "\n\n";
|
||||
|
||||
// 3. Get all offerings for the store
|
||||
echo "3. Getting all offerings for the store...\n";
|
||||
$offerings = $client->getOfferings($storeId);
|
||||
foreach ($offerings->all() as $off) {
|
||||
echo "- Offering: " . $off->getAppName() . " (ID: " . $off->getId() . ")\n";
|
||||
foreach ($off->getPlans() as $plan) {
|
||||
echo " - Plan: " . $plan->getName() . " - " . $plan->getPrice() . " " . $plan->getCurrency() . "/" . $plan->getRecurringType() . "\n";
|
||||
}
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
// 4. Get a specific offering
|
||||
echo "4. Getting specific offering details...\n";
|
||||
$specificOffering = $client->getOffering($storeId, $offeringId);
|
||||
echo "Offering: " . $specificOffering->getAppName() . "\n";
|
||||
echo "Success URL: " . $specificOffering->getSuccessRedirectUrl() . "\n";
|
||||
echo "Number of plans: " . count($specificOffering->getPlans()) . "\n\n";
|
||||
|
||||
// 5. Get a specific plan
|
||||
echo "5. Getting specific plan details...\n";
|
||||
$specificPlan = $client->getOfferingPlan($storeId, $offeringId, $basicPlanId);
|
||||
echo "Plan: " . $specificPlan->getName() . "\n";
|
||||
echo "Price: " . $specificPlan->getPrice() . " " . $specificPlan->getCurrency() . "\n";
|
||||
echo "Trial Days: " . $specificPlan->getTrialDays() . "\n";
|
||||
echo "Features: " . implode(', ', $specificPlan->getFeatures()) . "\n\n";
|
||||
|
||||
// 6. Create a plan checkout session
|
||||
echo "6. Creating a plan checkout session...\n";
|
||||
$checkout = $client->createPlanCheckout(
|
||||
$storeId,
|
||||
$offeringId,
|
||||
$basicPlanId,
|
||||
null, // If the customer already exists on BTCPay, fill the email or other id here.
|
||||
60,
|
||||
'SoftMigration',
|
||||
['source' => 'web'],
|
||||
['campaign' => 'summer2026'],
|
||||
['flow' => 'new_signup'],
|
||||
false,
|
||||
null, // You can override the plan price here if you want to force more credit or custom amount.
|
||||
'https://example.com/welcome',
|
||||
'test@example.com' // This is optional and will prefill the checkout page with the email.
|
||||
);
|
||||
echo "Checkout created with ID: " . $checkout->getId() . "\n";
|
||||
echo "Checkout URL: " . $checkout->getUrl() . "\n";
|
||||
echo "Is Trial: " . ($checkout->isTrial() ? 'Yes' : 'No') . "\n";
|
||||
echo "New Subscriber: " . ($checkout->isNewSubscriber() ? 'Yes' : 'No') . "\n\n";
|
||||
|
||||
$checkoutId = $checkout->getId();
|
||||
|
||||
// 7. Get plan checkout details
|
||||
echo "7. Getting plan checkout details...\n";
|
||||
$checkoutDetails = $client->getPlanCheckout($checkoutId);
|
||||
echo "Checkout ID: " . $checkoutDetails->getId() . "\n";
|
||||
echo "Plan: " . $checkoutDetails->getPlan()->getName() . "\n";
|
||||
$subscriber = $checkoutDetails->getSubscriber();
|
||||
if ($subscriber && $subscriber->getCustomer()->getIdentities()) {
|
||||
echo "Subscriber Email: " . ($subscriber->getCustomer()->getIdentities()['Email'] ?? 'N/A') . "\n";
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
// 8. Subscriber management examples
|
||||
/*
|
||||
// Fill these variables with actual values to test subscriber operations
|
||||
$offeringId = ''; // e.g. "offering_GFbMSBpybM6i5uEiqc"
|
||||
$customerSelector = ''; // e.g. "ps_N71XxcPDnKNgNDxKHZ" or customer email
|
||||
$suspensionReason = 'User requested cancellation';
|
||||
|
||||
if (!empty($storeId) && !empty($offeringId) && !empty($customerSelector)) {
|
||||
try {
|
||||
// Get subscriber details
|
||||
echo "8. Getting subscriber details...\n";
|
||||
$subscriber = $client->getSubscriber($storeId, $offeringId, $customerSelector);
|
||||
echo "Customer ID: " . $subscriber->getCustomer()->getId() . "\n";
|
||||
echo "Active: " . ($subscriber->isActive() ? 'Yes' : 'No') . "\n";
|
||||
echo "Phase: " . $subscriber->getPhase() . "\n";
|
||||
echo "Created: " . date('Y-m-d H:i:s', $subscriber->getCreated()) . "\n";
|
||||
echo "\n";
|
||||
|
||||
// Suspend subscriber
|
||||
if (!empty($suspensionReason)) {
|
||||
echo "9. Suspending subscriber...\n";
|
||||
$client->suspendSubscriber($storeId, $offeringId, $customerSelector, $suspensionReason);
|
||||
echo "Subscriber suspended successfully!\n";
|
||||
|
||||
// Check status after suspension
|
||||
$suspendedSubscriber = $client->getSubscriber($storeId, $offeringId, $customerSelector);
|
||||
echo "Status after suspension: " . ($suspendedSubscriber->isActive() ? 'Active' : 'Suspended') . "\n";
|
||||
echo "Suspension reason: " . ($suspendedSubscriber->getSuspensionReason() ?? 'N/A') . "\n\n";
|
||||
|
||||
// Update subscriber dates
|
||||
echo "9b. Updating subscriber dates...\n";
|
||||
$updatedSubscriber = $client->updateSubscriberDates(
|
||||
$storeId,
|
||||
$offeringId,
|
||||
$customerSelector,
|
||||
null,
|
||||
time() + (30 * 24 * 60 * 60) // 30 days from now
|
||||
);
|
||||
echo "Subscriber expiration updated\n";
|
||||
echo "Scheduled plan: " . ($updatedSubscriber->getScheduledPlan() ? $updatedSubscriber->getScheduledPlan()->getName() : 'None') . "\n";
|
||||
echo "Scheduled plan activates at: " . ($updatedSubscriber->getScheduledPlanActivatesAt() ? date('Y-m-d H:i:s', $updatedSubscriber->getScheduledPlanActivatesAt()) : 'N/A') . "\n\n";
|
||||
|
||||
// Unsuspend subscriber
|
||||
echo "10. Unsuspending subscriber...\n";
|
||||
$client->unsuspendSubscriber($storeId, $offeringId, $customerSelector);
|
||||
echo "Subscriber unsuspended successfully!\n";
|
||||
|
||||
// Check status after unsuspending
|
||||
$reactivatedSubscriber = $client->getSubscriber($storeId, $offeringId, $customerSelector);
|
||||
echo "Status after unsuspending: " . ($reactivatedSubscriber->isActive() ? 'Active' : 'Suspended') . "\n";
|
||||
echo "Suspension reason: " . ($reactivatedSubscriber->getSuspensionReason() ?? 'N/A') . "\n\n";
|
||||
}
|
||||
|
||||
// Delete subscriber
|
||||
echo "11. Deleting subscriber...\n";
|
||||
$client->deleteSubscriber($storeId, $offeringId, $customerSelector);
|
||||
echo "Subscriber deleted successfully!\n\n";
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error in subscriber management: " . $e->getMessage() . "\n";
|
||||
}
|
||||
} else {
|
||||
echo "8. Subscriber management examples skipped - please fill in storeId, offeringId, and customerSelector variables\n";
|
||||
}
|
||||
*/
|
||||
|
||||
echo "=== Examples completed successfully! ===\n";
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error: " . $e->getMessage() . "\n";
|
||||
echo "Stack trace:\n" . $e->getTraceAsString() . "\n";
|
||||
}
|
||||
@ -22,7 +22,7 @@ class AbstractClient
|
||||
/** @var ClientInterface */
|
||||
private $httpClient;
|
||||
|
||||
public function __construct(string $baseUrl, string $apiKey, ClientInterface $client = null)
|
||||
public function __construct(string $baseUrl, string $apiKey, ?ClientInterface $client = null)
|
||||
{
|
||||
$this->baseUrl = rtrim($baseUrl, '/');
|
||||
$this->apiKey = $apiKey;
|
||||
|
||||
@ -118,8 +118,8 @@ class Invoice extends AbstractClient
|
||||
|
||||
public function getAllInvoices(
|
||||
string $storeId,
|
||||
int $take = null,
|
||||
int $skip = null
|
||||
?int $take = null,
|
||||
?int $skip = null
|
||||
): InvoiceList {
|
||||
return $this->getAllInvoicesWithFilter($storeId, null, null, null, null, null, $take, $skip);
|
||||
}
|
||||
@ -127,8 +127,8 @@ class Invoice extends AbstractClient
|
||||
public function getInvoicesByOrderIds(
|
||||
string $storeId,
|
||||
array $orderIds,
|
||||
int $take = null,
|
||||
int $skip = null
|
||||
?int $take = null,
|
||||
?int $skip = null
|
||||
): InvoiceList {
|
||||
return $this->getAllInvoicesWithFilter($storeId, $orderIds, null, null, null, null, $take, $skip);
|
||||
}
|
||||
@ -136,8 +136,8 @@ class Invoice extends AbstractClient
|
||||
public function getInvoicesByText(
|
||||
string $storeId,
|
||||
string $text,
|
||||
int $take = null,
|
||||
int $skip = null
|
||||
?int $take = null,
|
||||
?int $skip = null
|
||||
): InvoiceList {
|
||||
return $this->getAllInvoicesWithFilter($storeId, null, $text, null, null, null, $take, $skip);
|
||||
}
|
||||
@ -145,8 +145,8 @@ class Invoice extends AbstractClient
|
||||
public function getInvoicesByStatus(
|
||||
string $storeId,
|
||||
array $status,
|
||||
int $take = null,
|
||||
int $skip = null
|
||||
?int $take = null,
|
||||
?int $skip = null
|
||||
): InvoiceList {
|
||||
return $this->getAllInvoicesWithFilter($storeId, null, null, $status, null, null, $take, $skip);
|
||||
}
|
||||
@ -154,8 +154,8 @@ class Invoice extends AbstractClient
|
||||
public function getInvoicesByStartDate(
|
||||
string $storeId,
|
||||
int $startDate,
|
||||
int $take = null,
|
||||
int $skip = null
|
||||
?int $take = null,
|
||||
?int $skip = null
|
||||
): InvoiceList {
|
||||
return $this->getAllInvoicesWithFilter($storeId, null, null, null, $startDate, null, $take, $skip);
|
||||
}
|
||||
@ -163,8 +163,8 @@ class Invoice extends AbstractClient
|
||||
public function getInvoicesByEndDate(
|
||||
string $storeId,
|
||||
int $endDate,
|
||||
int $take = null,
|
||||
int $skip = null
|
||||
?int $take = null,
|
||||
?int $skip = null
|
||||
): InvoiceList {
|
||||
return $this->getAllInvoicesWithFilter($storeId, null, null, null, null, $endDate, $take, $skip);
|
||||
}
|
||||
@ -174,13 +174,13 @@ class Invoice extends AbstractClient
|
||||
*/
|
||||
public function getAllInvoicesWithFilter(
|
||||
string $storeId,
|
||||
array $filterByOrderIds = null,
|
||||
string $filterByText = null,
|
||||
array $filterByStatus = null,
|
||||
int $filterByStartDate = null,
|
||||
int $filterByEndDate = null,
|
||||
int $take = null,
|
||||
int $skip = null
|
||||
?array $filterByOrderIds = null,
|
||||
?string $filterByText = null,
|
||||
?array $filterByStatus = null,
|
||||
?int $filterByStartDate = null,
|
||||
?int $filterByEndDate = null,
|
||||
?int $take = null,
|
||||
?int $skip = null
|
||||
): InvoiceList {
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/invoices?';
|
||||
if ($filterByOrderIds !== null) {
|
||||
|
||||
@ -50,7 +50,7 @@ class PullPayment extends AbstractClient
|
||||
?bool $autoApproveClaims = false,
|
||||
?int $startsAt,
|
||||
?int $expiresAt,
|
||||
array $paymentMethods,
|
||||
?array $paymentMethods = null,
|
||||
?string $description = null
|
||||
): ResultPullPayment {
|
||||
$url = $this->getApiUrl() . 'stores/' .
|
||||
@ -70,7 +70,8 @@ class PullPayment extends AbstractClient
|
||||
'autoApproveClaims' => $autoApproveClaims,
|
||||
'startsAt' => $startsAt,
|
||||
'expiresAt' => $expiresAt,
|
||||
'paymentMethods' => $paymentMethods
|
||||
'paymentMethods' => $paymentMethods,
|
||||
'payoutMethods' => $paymentMethods
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
@ -243,6 +244,7 @@ class PullPayment extends AbstractClient
|
||||
'destination' => $destination,
|
||||
'amount' => $amount->__toString(),
|
||||
'paymentMethod' => $paymentMethod,
|
||||
'payoutMethodId' => $paymentMethod, // BTCPay 2.0.0 compatibilty
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
|
||||
@ -10,6 +10,8 @@ use BTCPayServer\Result\StorePaymentMethodLightningNetwork as ResultStorePayment
|
||||
* Handles a stores LightningNetwork payment methods.
|
||||
*
|
||||
* @see https://docs.btcpayserver.org/API/Greenfield/v1/#tag/Store-Payment-Methods-(Lightning-Network)
|
||||
*
|
||||
* @deprecated with BTCPay 2.0. Use \BTCPayServer\Client\StorePaymentMethod->getPaymentMethods() instead.
|
||||
*/
|
||||
class StorePaymentMethodLightningNetwork extends AbstractStorePaymentMethodClient
|
||||
{
|
||||
|
||||
@ -10,6 +10,8 @@ use BTCPayServer\Result\StorePaymentMethodOnChain as ResultStorePaymentMethodOnC
|
||||
* Handles stores on chain payment methods.
|
||||
*
|
||||
* @see https://docs.btcpayserver.org/API/Greenfield/v1/#tag/Store-Payment-Methods-(On-Chain)
|
||||
*
|
||||
* @deprecated with BTCPay 2.0. Use \BTCPayServer\Client\StorePaymentMethod->getPaymentMethods() instead.
|
||||
*/
|
||||
class StorePaymentMethodOnChain extends AbstractStorePaymentMethodClient
|
||||
{
|
||||
@ -133,7 +135,7 @@ class StorePaymentMethodOnChain extends AbstractStorePaymentMethodClient
|
||||
string $storeId,
|
||||
string $cryptoCode,
|
||||
string $derivationScheme,
|
||||
string $accountKeyPath = null
|
||||
?string $accountKeyPath = null
|
||||
): array {
|
||||
// todo: add offset + amount query parameters + check structure of derivationScheme etc.
|
||||
|
||||
|
||||
@ -97,7 +97,7 @@ class StoreRate extends AbstractClient
|
||||
|
||||
public function getRates(
|
||||
string $storeId,
|
||||
array $currencyPairs = null
|
||||
?array $currencyPairs = null
|
||||
): StoreRateList {
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/rates?';
|
||||
$headers = $this->getRequestHeaders();
|
||||
|
||||
493
src/Client/Subscriptions.php
Normal file
493
src/Client/Subscriptions.php
Normal file
@ -0,0 +1,493 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Client;
|
||||
|
||||
use BTCPayServer\Result\Credit;
|
||||
use BTCPayServer\Result\Offering;
|
||||
use BTCPayServer\Result\OfferingList;
|
||||
use BTCPayServer\Result\OfferingPlan;
|
||||
use BTCPayServer\Result\PlanCheckout;
|
||||
use BTCPayServer\Result\PortalSession;
|
||||
use BTCPayServer\Result\Subscriber;
|
||||
|
||||
/**
|
||||
* Handles subscriptions operations.
|
||||
*
|
||||
* @see https://docs.btcpayserver.org/API/Greenfield/v1/#tag/Subscriptions
|
||||
*/
|
||||
class Subscriptions extends AbstractClient
|
||||
{
|
||||
// Offering endpoints
|
||||
|
||||
public function getOffering(string $storeId, string $offeringId): Offering
|
||||
{
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/offerings/' . urlencode($offeringId);
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'GET';
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new Offering(json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR));
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
public function getOfferings(string $storeId): OfferingList
|
||||
{
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/offerings';
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'GET';
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new OfferingList(json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR));
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
public function createOffering(
|
||||
string $storeId,
|
||||
?string $appName = null,
|
||||
?string $successRedirectUrl = null,
|
||||
?array $metadata = null,
|
||||
?array $features = null
|
||||
): Offering {
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/offerings';
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'POST';
|
||||
|
||||
$body = json_encode(
|
||||
[
|
||||
'appName' => $appName,
|
||||
'successRedirectUrl' => $successRedirectUrl,
|
||||
'metadata' => $metadata,
|
||||
'features' => $features
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers, $body);
|
||||
|
||||
if ($response->getStatus() === 200 || $response->getStatus() === 201) {
|
||||
return new Offering(json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR));
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
public function updateOffering(
|
||||
string $storeId,
|
||||
string $offeringId,
|
||||
?string $appName = null,
|
||||
?string $successRedirectUrl = null,
|
||||
?array $metadata = null,
|
||||
?array $features = null
|
||||
): Offering {
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/offerings/' . urlencode($offeringId);
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'PUT';
|
||||
|
||||
$body = json_encode(
|
||||
[
|
||||
'appName' => $appName,
|
||||
'successRedirectUrl' => $successRedirectUrl,
|
||||
'metadata' => $metadata,
|
||||
'features' => $features
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers, $body);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new Offering(json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR));
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
// Plan endpoints
|
||||
|
||||
public function createOfferingPlan(
|
||||
string $storeId,
|
||||
string $offeringId,
|
||||
?string $description = null,
|
||||
?string $currency = null,
|
||||
?int $gracePeriodDays = null,
|
||||
?string $name = null,
|
||||
?bool $optimisticActivation = null,
|
||||
?string $price = null,
|
||||
?bool $renewable = null,
|
||||
?int $trialDays = null,
|
||||
?array $metadata = null,
|
||||
?string $recurringType = null,
|
||||
?array $features = null
|
||||
): OfferingPlan {
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/offerings/' . urlencode($offeringId) . '/plans';
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'POST';
|
||||
|
||||
$body = json_encode(
|
||||
[
|
||||
'description' => $description,
|
||||
'currency' => $currency,
|
||||
'gracePeriodDays' => $gracePeriodDays,
|
||||
'name' => $name,
|
||||
'optimisticActivation' => $optimisticActivation,
|
||||
'price' => $price,
|
||||
'renewable' => $renewable,
|
||||
'trialDays' => $trialDays,
|
||||
'metadata' => $metadata,
|
||||
'recurringType' => $recurringType,
|
||||
'features' => $features
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers, $body);
|
||||
|
||||
if ($response->getStatus() === 200 || $response->getStatus() === 201) {
|
||||
return new OfferingPlan(json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR));
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
public function getOfferingPlan(string $storeId, string $offeringId, string $planId): OfferingPlan
|
||||
{
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/offerings/' . urlencode($offeringId) . '/plans/' . urlencode($planId);
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'GET';
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new OfferingPlan(json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR));
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
public function updateOfferingPlan(
|
||||
string $storeId,
|
||||
string $offeringId,
|
||||
string $planId,
|
||||
?string $description = null,
|
||||
?string $currency = null,
|
||||
?int $gracePeriodDays = null,
|
||||
?string $name = null,
|
||||
?bool $optimisticActivation = null,
|
||||
?string $price = null,
|
||||
?bool $renewable = null,
|
||||
?int $trialDays = null,
|
||||
?array $metadata = null,
|
||||
?string $recurringType = null,
|
||||
?array $features = null
|
||||
): OfferingPlan {
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/offerings/' . urlencode($offeringId) . '/plans/' . urlencode($planId);
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'PUT';
|
||||
|
||||
$body = json_encode(
|
||||
[
|
||||
'description' => $description,
|
||||
'currency' => $currency,
|
||||
'gracePeriodDays' => $gracePeriodDays,
|
||||
'name' => $name,
|
||||
'optimisticActivation' => $optimisticActivation,
|
||||
'price' => $price,
|
||||
'renewable' => $renewable,
|
||||
'trialDays' => $trialDays,
|
||||
'metadata' => $metadata,
|
||||
'recurringType' => $recurringType,
|
||||
'features' => $features
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers, $body);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new OfferingPlan(json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR));
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
// Subscriber endpoints
|
||||
|
||||
public function getSubscriber(string $storeId, string $offeringId, string $customerSelector): Subscriber
|
||||
{
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/offerings/' . urlencode($offeringId) . '/subscribers/' . urlencode($customerSelector);
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'GET';
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new Subscriber(json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR));
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteSubscriber(string $storeId, string $offeringId, string $customerSelector): void
|
||||
{
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/offerings/' . urlencode($offeringId) . '/subscribers/' . urlencode($customerSelector);
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'DELETE';
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers);
|
||||
|
||||
if ($response->getStatus() !== 204) {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
public function updateSubscriberDates(
|
||||
string $storeId,
|
||||
string $offeringId,
|
||||
string $customerSelector,
|
||||
?int $startDate = null,
|
||||
?int $expirationDate = null
|
||||
): Subscriber {
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/offerings/' . urlencode($offeringId) . '/subscribers/' . urlencode($customerSelector) . '/dates';
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'PUT';
|
||||
|
||||
$body = json_encode(
|
||||
[
|
||||
'startDate' => $startDate,
|
||||
'expirationDate' => $expirationDate
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers, $body);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new Subscriber(json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR));
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
public function suspendSubscriber(string $storeId, string $offeringId, string $customerSelector, string $reason): Subscriber
|
||||
{
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/offerings/' . urlencode($offeringId) . '/subscribers/' . urlencode($customerSelector) . '/suspend';
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'POST';
|
||||
|
||||
$body = json_encode(
|
||||
[
|
||||
'reason' => $reason
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers, $body);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new Subscriber(json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR));
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
public function unsuspendSubscriber(string $storeId, string $offeringId, string $customerSelector): Subscriber
|
||||
{
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/offerings/' . urlencode($offeringId) . '/subscribers/' . urlencode($customerSelector) . '/unsuspend';
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'POST';
|
||||
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new Subscriber(json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR));
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
// Credit endpoints
|
||||
|
||||
public function getCredit(string $storeId, string $offeringId, string $customerSelector, string $currency): Credit
|
||||
{
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/offerings/' . urlencode($offeringId) . '/subscribers/' . urlencode($customerSelector) . '/credits/' . urlencode($currency);
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'GET';
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new Credit(json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR));
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
public function updateCredit(
|
||||
string $storeId,
|
||||
string $offeringId,
|
||||
string $customerSelector,
|
||||
string $currency,
|
||||
?string $credit = null,
|
||||
?string $charge = null,
|
||||
?string $description = null,
|
||||
?bool $allowOverdraft = null
|
||||
): Credit {
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/offerings/' . urlencode($offeringId) . '/subscribers/' . urlencode($customerSelector) . '/credits/' . urlencode($currency);
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'POST';
|
||||
|
||||
$body = json_encode(
|
||||
[
|
||||
'credit' => $credit,
|
||||
'charge' => $charge,
|
||||
'description' => $description,
|
||||
'allowOverdraft' => $allowOverdraft
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers, $body);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new Credit(json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR));
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
// Plan checkout endpoints
|
||||
|
||||
public function getPlanCheckout(string $checkoutId): PlanCheckout
|
||||
{
|
||||
$url = $this->getApiUrl() . 'plan-checkout/' . urlencode($checkoutId);
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'GET';
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new PlanCheckout(json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR));
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
public function proceedPlanCheckout(string $checkoutId, ?string $email = null): PlanCheckout
|
||||
{
|
||||
$url = $this->getApiUrl() . 'plan-checkout/' . urlencode($checkoutId);
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'POST';
|
||||
|
||||
$params = [];
|
||||
if ($email !== null) {
|
||||
$params['email'] = $email;
|
||||
}
|
||||
|
||||
if (!empty($params)) {
|
||||
$url .= '?' . http_build_query($params);
|
||||
}
|
||||
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new PlanCheckout(json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR));
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
public function createPlanCheckout(
|
||||
string $storeId,
|
||||
string $offeringId,
|
||||
string $planId,
|
||||
?string $customerSelector = null,
|
||||
?int $durationMinutes = null,
|
||||
?string $onPayBehavior = null,
|
||||
?array $newSubscriberMetadata = null,
|
||||
?array $invoiceMetadata = null,
|
||||
?array $metadata = null,
|
||||
?bool $isTrial = null,
|
||||
?string $creditPurchase = null,
|
||||
?string $successRedirectLink = null,
|
||||
?string $newSubscriberEmail = null
|
||||
): PlanCheckout {
|
||||
$url = $this->getApiUrl() . 'plan-checkout';
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'POST';
|
||||
|
||||
$body = json_encode(
|
||||
[
|
||||
'storeId' => $storeId,
|
||||
'offeringId' => $offeringId,
|
||||
'planId' => $planId,
|
||||
'customerSelector' => $customerSelector,
|
||||
'durationMinutes' => $durationMinutes,
|
||||
'onPayBehavior' => $onPayBehavior,
|
||||
'newSubscriberMetadata' => $newSubscriberMetadata,
|
||||
'invoiceMetadata' => $invoiceMetadata,
|
||||
'metadata' => $metadata,
|
||||
'isTrial' => $isTrial,
|
||||
'creditPurchase' => $creditPurchase,
|
||||
'successRedirectLink' => $successRedirectLink,
|
||||
'newSubscriberEmail' => $newSubscriberEmail
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers, $body);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new PlanCheckout(json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR));
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
// Portal session endpoints
|
||||
|
||||
public function createPortalSession(
|
||||
string $storeId,
|
||||
string $offeringId,
|
||||
string $customerSelector,
|
||||
?int $durationMinutes = null
|
||||
): PortalSession {
|
||||
$url = $this->getApiUrl() . 'subscriber-portal';
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'POST';
|
||||
|
||||
$body = json_encode(
|
||||
[
|
||||
'storeId' => $storeId,
|
||||
'offeringId' => $offeringId,
|
||||
'customerSelector' => $customerSelector,
|
||||
'durationMinutes' => $durationMinutes
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers, $body);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new PortalSession(json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR));
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
public function getPortalSession(string $portalSessionId): PortalSession
|
||||
{
|
||||
$url = $this->getApiUrl() . 'subscriber-portal/' . urlencode($portalSessionId);
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'GET';
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new PortalSession(json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR));
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -238,7 +238,7 @@ class Webhook extends AbstractClient
|
||||
if ($requestBody && $btcpaySigHeader) {
|
||||
$expectedHeader = 'sha256=' . hash_hmac('sha256', $requestBody, $secret);
|
||||
|
||||
if ($expectedHeader === $btcpaySigHeader) {
|
||||
if (hash_equals($expectedHeader, $btcpaySigHeader)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ namespace BTCPayServer\Exception;
|
||||
|
||||
class BTCPayException extends \RuntimeException
|
||||
{
|
||||
public function __construct(string $message, int $code, \Throwable $previous = null)
|
||||
public function __construct(string $message, int $code, ?\Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ namespace BTCPayServer\Result;
|
||||
|
||||
abstract class AbstractStorePaymentMethodResult extends AbstractResult
|
||||
{
|
||||
public function __construct(array $data, string $paymentMethod = null)
|
||||
public function __construct(array $data, ?string $paymentMethod = null)
|
||||
{
|
||||
// Temporary workaround until the api provides paymentMethod.
|
||||
if (!isset($data['paymentMethod'])) {
|
||||
|
||||
18
src/Result/Credit.php
Normal file
18
src/Result/Credit.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
class Credit extends AbstractResult
|
||||
{
|
||||
public function getCurrency(): string
|
||||
{
|
||||
return $this->getData()['currency'];
|
||||
}
|
||||
|
||||
public function getValue(): string
|
||||
{
|
||||
return $this->getData()['value'];
|
||||
}
|
||||
}
|
||||
33
src/Result/Customer.php
Normal file
33
src/Result/Customer.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
class Customer extends AbstractResult
|
||||
{
|
||||
public function getStoreId(): string
|
||||
{
|
||||
return $this->getData()['storeId'];
|
||||
}
|
||||
|
||||
public function getId(): string
|
||||
{
|
||||
return $this->getData()['id'];
|
||||
}
|
||||
|
||||
public function getExternalId(): ?string
|
||||
{
|
||||
return $this->getData()['externalId'] ?? null;
|
||||
}
|
||||
|
||||
public function getIdentities(): ?array
|
||||
{
|
||||
return $this->getData()['identities'] ?? null;
|
||||
}
|
||||
|
||||
public function getMetadata(): ?array
|
||||
{
|
||||
return $this->getData()['metadata'] ?? null;
|
||||
}
|
||||
}
|
||||
18
src/Result/Feature.php
Normal file
18
src/Result/Feature.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
class Feature extends AbstractResult
|
||||
{
|
||||
public function getId(): string
|
||||
{
|
||||
return $this->getData()['id'];
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return $this->getData()['description'];
|
||||
}
|
||||
}
|
||||
66
src/Result/Offering.php
Normal file
66
src/Result/Offering.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
class Offering extends AbstractResult
|
||||
{
|
||||
public function getId(): string
|
||||
{
|
||||
return $this->getData()['id'];
|
||||
}
|
||||
|
||||
public function getStoreId(): string
|
||||
{
|
||||
return $this->getData()['storeId'];
|
||||
}
|
||||
|
||||
public function getAppId(): ?string
|
||||
{
|
||||
return $this->getData()['appId'] ?? null;
|
||||
}
|
||||
|
||||
public function getAppName(): ?string
|
||||
{
|
||||
return $this->getData()['appName'] ?? null;
|
||||
}
|
||||
|
||||
public function getSuccessRedirectUrl(): ?string
|
||||
{
|
||||
return $this->getData()['successRedirectUrl'] ?? null;
|
||||
}
|
||||
|
||||
public function getMetadata(): ?array
|
||||
{
|
||||
return $this->getData()['metadata'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return OfferingPlan[]
|
||||
*/
|
||||
public function getPlans(): array
|
||||
{
|
||||
$plans = [];
|
||||
if (isset($this->getData()['plans']) && is_array($this->getData()['plans'])) {
|
||||
foreach ($this->getData()['plans'] as $plan) {
|
||||
$plans[] = new OfferingPlan($plan);
|
||||
}
|
||||
}
|
||||
return $plans;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Feature[]
|
||||
*/
|
||||
public function getFeatures(): array
|
||||
{
|
||||
$features = [];
|
||||
if (isset($this->getData()['features']) && is_array($this->getData()['features'])) {
|
||||
foreach ($this->getData()['features'] as $feature) {
|
||||
$features[] = new Feature($feature);
|
||||
}
|
||||
}
|
||||
return $features;
|
||||
}
|
||||
}
|
||||
20
src/Result/OfferingList.php
Normal file
20
src/Result/OfferingList.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
class OfferingList extends AbstractListResult
|
||||
{
|
||||
/**
|
||||
* @return Offering[]
|
||||
*/
|
||||
public function all(): array
|
||||
{
|
||||
$result = [];
|
||||
foreach ($this->getData() as $item) {
|
||||
$result[] = new Offering($item);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
81
src/Result/OfferingPlan.php
Normal file
81
src/Result/OfferingPlan.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
class OfferingPlan extends AbstractResult
|
||||
{
|
||||
public function getId(): string
|
||||
{
|
||||
return $this->getData()['id'];
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->getData()['name'];
|
||||
}
|
||||
|
||||
public function getStatus(): string
|
||||
{
|
||||
return $this->getData()['status'];
|
||||
}
|
||||
|
||||
public function getPrice(): string
|
||||
{
|
||||
return $this->getData()['price'];
|
||||
}
|
||||
|
||||
public function getCurrency(): string
|
||||
{
|
||||
return $this->getData()['currency'];
|
||||
}
|
||||
|
||||
public function getRecurringType(): string
|
||||
{
|
||||
return $this->getData()['recurringType'];
|
||||
}
|
||||
|
||||
public function getGracePeriodDays(): int
|
||||
{
|
||||
return $this->getData()['gracePeriodDays'];
|
||||
}
|
||||
|
||||
public function getTrialDays(): int
|
||||
{
|
||||
return $this->getData()['trialDays'];
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return $this->getData()['description'];
|
||||
}
|
||||
|
||||
public function getMemberCount(): int
|
||||
{
|
||||
return $this->getData()['memberCount'];
|
||||
}
|
||||
|
||||
public function isOptimisticActivation(): bool
|
||||
{
|
||||
return $this->getData()['optimisticActivation'];
|
||||
}
|
||||
|
||||
public function isRenewable(): bool
|
||||
{
|
||||
return $this->getData()['renewable'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getFeatures(): array
|
||||
{
|
||||
return $this->getData()['features'] ?? [];
|
||||
}
|
||||
|
||||
public function getMetadata(): ?array
|
||||
{
|
||||
return $this->getData()['metadata'] ?? null;
|
||||
}
|
||||
}
|
||||
113
src/Result/PlanCheckout.php
Normal file
113
src/Result/PlanCheckout.php
Normal file
@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
class PlanCheckout extends AbstractResult
|
||||
{
|
||||
public function getId(): string
|
||||
{
|
||||
return $this->getData()['id'];
|
||||
}
|
||||
|
||||
public function getSubscriber(): ?Subscriber
|
||||
{
|
||||
return isset($this->getData()['subscriber']) ? new Subscriber($this->getData()['subscriber']) : null;
|
||||
}
|
||||
|
||||
public function getPlan(): OfferingPlan
|
||||
{
|
||||
return new OfferingPlan($this->getData()['plan']);
|
||||
}
|
||||
|
||||
public function getBaseUrl(): string
|
||||
{
|
||||
return $this->getData()['baseUrl'];
|
||||
}
|
||||
|
||||
public function getInvoiceId(): ?string
|
||||
{
|
||||
return $this->getData()['invoiceId'] ?? null;
|
||||
}
|
||||
|
||||
public function getSuccessRedirectUrl(): ?string
|
||||
{
|
||||
return $this->getData()['successRedirectUrl'] ?? null;
|
||||
}
|
||||
|
||||
public function getExpiration(): int
|
||||
{
|
||||
return $this->getData()['expiration'];
|
||||
}
|
||||
|
||||
public function getRedirectUrl(): string
|
||||
{
|
||||
return $this->getData()['redirectUrl'];
|
||||
}
|
||||
|
||||
public function getInvoiceMetadata(): ?array
|
||||
{
|
||||
return $this->getData()['invoiceMetadata'] ?? null;
|
||||
}
|
||||
|
||||
public function getMetadata(): ?array
|
||||
{
|
||||
return $this->getData()['metadata'] ?? null;
|
||||
}
|
||||
|
||||
public function isNewSubscriber(): bool
|
||||
{
|
||||
return $this->getData()['newSubscriber'];
|
||||
}
|
||||
|
||||
public function isTrial(): bool
|
||||
{
|
||||
return $this->getData()['isTrial'];
|
||||
}
|
||||
|
||||
public function getCreated(): int
|
||||
{
|
||||
return $this->getData()['created'];
|
||||
}
|
||||
|
||||
public function isPlanStarted(): bool
|
||||
{
|
||||
return $this->getData()['planStarted'];
|
||||
}
|
||||
|
||||
public function getNewSubscriberMetadata(): ?array
|
||||
{
|
||||
return $this->getData()['newSubscriberMetadata'] ?? null;
|
||||
}
|
||||
|
||||
public function getRefundAmount(): ?string
|
||||
{
|
||||
return $this->getData()['refundAmount'] ?? null;
|
||||
}
|
||||
|
||||
public function getCreditedByInvoice(): ?string
|
||||
{
|
||||
return $this->getData()['creditedByInvoice'] ?? null;
|
||||
}
|
||||
|
||||
public function getOnPayBehavior(): ?string
|
||||
{
|
||||
return $this->getData()['onPayBehavior'] ?? null;
|
||||
}
|
||||
|
||||
public function isExpired(): bool
|
||||
{
|
||||
return $this->getData()['isExpired'];
|
||||
}
|
||||
|
||||
public function getUrl(): string
|
||||
{
|
||||
return $this->getData()['url'];
|
||||
}
|
||||
|
||||
public function getCreditPurchase(): ?string
|
||||
{
|
||||
return $this->getData()['creditPurchase'] ?? null;
|
||||
}
|
||||
}
|
||||
38
src/Result/PortalSession.php
Normal file
38
src/Result/PortalSession.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
class PortalSession extends AbstractResult
|
||||
{
|
||||
public function getId(): string
|
||||
{
|
||||
return $this->getData()['id'];
|
||||
}
|
||||
|
||||
public function getBaseUrl(): string
|
||||
{
|
||||
return $this->getData()['baseUrl'];
|
||||
}
|
||||
|
||||
public function getSubscriber(): Subscriber
|
||||
{
|
||||
return new Subscriber($this->getData()['subscriber']);
|
||||
}
|
||||
|
||||
public function getExpiration(): ?int
|
||||
{
|
||||
return $this->getData()['expiration'] ?? null;
|
||||
}
|
||||
|
||||
public function isExpired(): bool
|
||||
{
|
||||
return $this->getData()['isExpired'];
|
||||
}
|
||||
|
||||
public function getUrl(): string
|
||||
{
|
||||
return $this->getData()['url'];
|
||||
}
|
||||
}
|
||||
93
src/Result/Subscriber.php
Normal file
93
src/Result/Subscriber.php
Normal file
@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
class Subscriber extends AbstractResult
|
||||
{
|
||||
public function getCreated(): int
|
||||
{
|
||||
return $this->getData()['created'];
|
||||
}
|
||||
|
||||
public function getCustomer(): Customer
|
||||
{
|
||||
return new Customer($this->getData()['customer']);
|
||||
}
|
||||
|
||||
public function getOffering(): Offering
|
||||
{
|
||||
return new Offering($this->getData()['offering']);
|
||||
}
|
||||
|
||||
public function getPlan(): OfferingPlan
|
||||
{
|
||||
return new OfferingPlan($this->getData()['plan']);
|
||||
}
|
||||
|
||||
public function getPeriodEnd(): ?int
|
||||
{
|
||||
return $this->getData()['periodEnd'] ?? null;
|
||||
}
|
||||
|
||||
public function getTrialEnd(): ?int
|
||||
{
|
||||
return $this->getData()['trialEnd'] ?? null;
|
||||
}
|
||||
|
||||
public function getGracePeriodEnd(): ?int
|
||||
{
|
||||
return $this->getData()['gracePeriodEnd'] ?? null;
|
||||
}
|
||||
|
||||
public function isActive(): bool
|
||||
{
|
||||
return $this->getData()['isActive'];
|
||||
}
|
||||
|
||||
public function isSuspended(): bool
|
||||
{
|
||||
return $this->getData()['isSuspended'];
|
||||
}
|
||||
|
||||
public function getSuspensionReason(): ?string
|
||||
{
|
||||
return $this->getData()['suspensionReason'] ?? null;
|
||||
}
|
||||
|
||||
public function isAutoRenew(): bool
|
||||
{
|
||||
return $this->getData()['autoRenew'];
|
||||
}
|
||||
|
||||
public function getMetadata(): ?array
|
||||
{
|
||||
return $this->getData()['metadata'] ?? null;
|
||||
}
|
||||
|
||||
public function getProcessingInvoiceId(): ?string
|
||||
{
|
||||
return $this->getData()['processingInvoiceId'] ?? null;
|
||||
}
|
||||
|
||||
public function getNextPlan(): ?OfferingPlan
|
||||
{
|
||||
return isset($this->getData()['nextPlan']) ? new OfferingPlan($this->getData()['nextPlan']) : null;
|
||||
}
|
||||
|
||||
public function getScheduledPlan(): ?OfferingPlan
|
||||
{
|
||||
return isset($this->getData()['scheduledPlan']) ? new OfferingPlan($this->getData()['scheduledPlan']) : null;
|
||||
}
|
||||
|
||||
public function getScheduledPlanActivatesAt(): ?int
|
||||
{
|
||||
return $this->getData()['scheduledPlanActivatesAt'] ?? null;
|
||||
}
|
||||
|
||||
public function getPhase(): string
|
||||
{
|
||||
return $this->getData()['phase'];
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user