Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81e1b17f10 | ||
|
|
c6876af1d0 | ||
|
|
75451c6ba3 | ||
|
|
3e6ab646fa | ||
|
|
ff667252d8 | ||
|
|
a3f4a60400 | ||
|
|
90c6ff52d3 | ||
|
|
bb8e7e8bf0 | ||
|
|
5d19edcff8 | ||
|
|
261bb459a3 | ||
|
|
158ab833f4 |
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@v5
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Run PHP CS Fixer
|
||||
uses: docker://oskarstark/php-cs-fixer-ga
|
||||
|
||||
105
.github/workflows/phpunit.yml
vendored
105
.github/workflows/phpunit.yml
vendored
@ -1,53 +1,52 @@
|
||||
#name: PHP Unit Tests
|
||||
#env:
|
||||
# BTCPAY_HOST: ${{ secrets.BTCPAY_HOST }}
|
||||
# BTCPAY_API_KEY: ${{ secrets.BTCPAY_API_KEY }}
|
||||
# BTCPAY_STORE_ID: ${{ secrets.BTCPAY_STORE_ID }}
|
||||
# BTCPAY_NODE_URI: ${{ secrets.BTCPAY_NODE_URI }}
|
||||
#on: [ push, pull_request ]
|
||||
#
|
||||
#jobs:
|
||||
# phpunit:
|
||||
# runs-on: ubuntu-latest
|
||||
# strategy:
|
||||
# matrix:
|
||||
# php-versions: ['8.0', '8.1']
|
||||
# phpunit-versions: ['latest']
|
||||
#
|
||||
#
|
||||
# steps:
|
||||
# - name: Checkout
|
||||
# uses: actions/checkout@v3
|
||||
# with:
|
||||
# fetch-depth: '0'
|
||||
#
|
||||
# - name: Setup PHP, with composer and extensions
|
||||
# uses: shivammathur/setup-php@v2
|
||||
# with:
|
||||
# php-version: ${{ matrix.php-versions }}
|
||||
# tools: composer:v2, phpunit:${{ matrix.phpunit-versions }}
|
||||
# extensions: curl, json, mbstring, bcmath
|
||||
# coverage: xdebug #optional
|
||||
#
|
||||
# - name: Get composer cache directory
|
||||
# id: composer-cache
|
||||
# run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
#
|
||||
# - name: Cache composer dependencies
|
||||
# uses: actions/cache@v2
|
||||
# with:
|
||||
# path: ${{ steps.composer-cache.outputs.dir }}
|
||||
# key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
# restore-keys: ${{ runner.os }}-composer-
|
||||
#
|
||||
# - name: Install Composer dependencies
|
||||
# run: composer install --no-progress --optimize-autoloader
|
||||
#
|
||||
# - name: Test with phpunit
|
||||
# run: vendor/bin/phpunit --coverage-text
|
||||
#
|
||||
# - name: Setup problem matchers for PHP
|
||||
# run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
|
||||
#
|
||||
# - name: Setup problem matchers for PHPUnit
|
||||
# run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
|
||||
# name: PHP Unit Tests
|
||||
# env:
|
||||
# BTCPAY_HOST: ${{ secrets.BTCPAY_HOST }}
|
||||
# BTCPAY_API_KEY: ${{ secrets.BTCPAY_API_KEY }}
|
||||
# BTCPAY_STORE_ID: ${{ secrets.BTCPAY_STORE_ID }}
|
||||
# BTCPAY_NODE_URI: ${{ secrets.BTCPAY_NODE_URI }}
|
||||
# on: [push, pull_request]
|
||||
|
||||
# jobs:
|
||||
# phpunit:
|
||||
# runs-on: ubuntu-latest
|
||||
# strategy:
|
||||
# matrix:
|
||||
# php-versions: ["8.0", "8.1"]
|
||||
# phpunit-versions: ["latest"]
|
||||
|
||||
# steps:
|
||||
# - name: Checkout
|
||||
# uses: actions/checkout@v3
|
||||
# with:
|
||||
# fetch-depth: "0"
|
||||
|
||||
# - name: Setup PHP, with composer and extensions
|
||||
# uses: shivammathur/setup-php@v2
|
||||
# with:
|
||||
# php-version: ${{ matrix.php-versions }}
|
||||
# tools: composer:v2, phpunit:${{ matrix.phpunit-versions }}
|
||||
# extensions: curl, json, mbstring, bcmath
|
||||
# coverage: xdebug #optional
|
||||
|
||||
# - name: Get composer cache directory
|
||||
# id: composer-cache
|
||||
# run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
# - name: Cache composer dependencies
|
||||
# uses: actions/cache@v2
|
||||
# with:
|
||||
# path: ${{ steps.composer-cache.outputs.dir }}
|
||||
# key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
# restore-keys: ${{ runner.os }}-composer-
|
||||
|
||||
# - name: Install Composer dependencies
|
||||
# run: composer install --no-progress --optimize-autoloader
|
||||
|
||||
# - name: Test with phpunit
|
||||
# run: vendor/bin/phpunit --coverage-text
|
||||
|
||||
# - name: Setup problem matchers for PHP
|
||||
# run: echo "::add-matcher::${{ runner.tool_cache }}/php.json"
|
||||
|
||||
# - name: Setup problem matchers for PHPUnit
|
||||
# run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
|
||||
|
||||
8
.github/workflows/psalm.yml
vendored
8
.github/workflows/psalm.yml
vendored
@ -9,12 +9,12 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php-versions: ['8.0']
|
||||
php-versions: ["8.0"]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: '0'
|
||||
fetch-depth: "0"
|
||||
|
||||
- name: Setup PHP, with composer and extensions
|
||||
uses: shivammathur/setup-php@v2
|
||||
@ -27,7 +27,7 @@ jobs:
|
||||
run: echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
|
||||
- name: Cache composer dependencies
|
||||
uses: actions/cache@v5
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -4,4 +4,5 @@
|
||||
*.cache
|
||||
composer.lock
|
||||
/tests/.env
|
||||
/.claude/
|
||||
/tests/.env.testnet
|
||||
/tests/.env.mainnet
|
||||
19
README.md
19
README.md
@ -1,11 +1,14 @@
|
||||
# BTCPay Server Greenfield API PHP client library
|
||||
|
||||
This library makes it easier to integrate BTCPay Server in your PHP application.
|
||||
|
||||
## Approach
|
||||
|
||||
This library takes an opinionated approach to Greenfield API with the aim of making your developer life as easy and convenient as possible.
|
||||
For this reason, we have decided to structure arguments a bit differently, but still allow full and advanced use cases.
|
||||
|
||||
The general reasoning behind the arguments an API client takes are in this order:
|
||||
|
||||
- First the required parameters => method arguments with NULL not allowed
|
||||
- Recommended parameters => method arguments with NULL as default
|
||||
- Optional parameters => arguments with NULL as default
|
||||
@ -14,11 +17,13 @@ The general reasoning behind the arguments an API client takes are in this order
|
||||
Methods that return a Unix timestamp always end with `Timestamp` like `getReceivedTimestamp()` to avoid format and timezone confusion. These are always in seconds (not milliseconds).
|
||||
|
||||
## Features
|
||||
|
||||
- No external dependencies. You can just drop this code in your project using composer or without composer.
|
||||
- Requires PHP 8.0 and up. End-of-life'd versions will not be actively supported.
|
||||
- All calls needed for eCommerce are included, but there are more we still need to add.
|
||||
|
||||
## TODO
|
||||
|
||||
- convert examples to tests
|
||||
- Getters and setters
|
||||
- Expand beyond the eCommerce related API calls and make this library 100% complete.
|
||||
@ -28,13 +33,17 @@ Methods that return a Unix timestamp always end with `Timestamp` like `getReceiv
|
||||
```
|
||||
composer require btcpayserver/btcpayserver-greenfield-php
|
||||
```
|
||||
|
||||
If you use some framework or other project you likely are ready to go. If you start from scratch make sure to include Composer autoloader.
|
||||
|
||||
```
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
```
|
||||
|
||||
## How to use without composer (not recommended)
|
||||
|
||||
In the `src` directory we have a custom `autoload.php` which you can require and avoid using composer if needed.
|
||||
|
||||
```
|
||||
// Require the autoload file.
|
||||
require __DIR__ . '/../src/autoload.php';
|
||||
@ -52,19 +61,25 @@ try {
|
||||
```
|
||||
|
||||
## Best practices
|
||||
|
||||
- Always use an API key with as little permissions as possible.
|
||||
- If you only interact with specific stores, use an API key that is limited to that store or those stores only.
|
||||
- When processing an incoming webhook, always load the data fresh using the API as the data may be stale or changed in the meantime. Webhook payloads can be resent on error, so you could be seeing outdated information. By loading the data fresh, you are also protecting yourself from possibly spoofed (fake) requests.
|
||||
- When processing an incoming webhook, always load the data fresh using the API as the data may be stale or changed in the meantime. Webhook payloads can be resent on error, so you could be seeing outdated information. By loading the data fresh, you are also protecting yourself from possibly spoofed (fake) requests.
|
||||
|
||||
## FAQ
|
||||
|
||||
### Where to get the API key from?
|
||||
The API keys for Greenfield API are *not* on the store level "Access Tokens" anymore. You need to go to your account profile: "My Settings" (user profile icon) -> "API Keys" instead. You can even redirect the users to generate the API keys there.
|
||||
|
||||
The API keys for Greenfield API are _not_ on the store level "Access Tokens" anymore. You need to go to your account profile: "My Settings" (user profile icon) -> "API Keys" instead. You can even redirect the users to generate the API keys there.
|
||||
|
||||
## Contribute
|
||||
|
||||
We run static analyzer [Psalm](https://psalm.dev/) and [PHP-CS-fixer](https://github.com/FriendsOfPhp/PHP-CS-Fixer) for codestyle when you open a pull-request. Please check if there are any errors and fix them accordingly.
|
||||
|
||||
### Codestyle
|
||||
|
||||
We use PSR-12 code style to ensure proper formatting and spacing. You can test and format your code using composer commands. Before doing a PR you can run `composer cs-check` and `composer cs-fix` which will run php-cs-fixer.
|
||||
|
||||
### Greenfield API coverage
|
||||
|
||||
Currently implemented functionality is tracked in [this sheet](https://docs.google.com/spreadsheets/d/1A1tMWYHGVkFWRgqfkW9GSGBRjzKZzsu5XMIW1NLs-xg/edit#gid=0) and will be updated sporadically. Check to see which areas still need work in case you want to contribute.
|
||||
|
||||
@ -28,11 +28,17 @@
|
||||
"friendsofphp/php-cs-fixer": "^3.0",
|
||||
"vimeo/psalm": "^4.8",
|
||||
"phpunit/phpunit": "^9.5",
|
||||
"vlucas/phpdotenv": "^5.5"
|
||||
"vlucas/phpdotenv": "^5.5",
|
||||
"pestphp/pest": "^1.22"
|
||||
},
|
||||
"scripts": {
|
||||
"cs-check": [ "vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php --allow-risky=yes --using-cache=no --verbose --dry-run" ],
|
||||
"cs-fix": [ "vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php --allow-risky=yes --using-cache=no" ],
|
||||
"psalm": [ "vendor/bin/psalm" ]
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"pestphp/pest-plugin": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,10 +8,9 @@ use BTCPayServer\Client\Store;
|
||||
$apiKey = '';
|
||||
$host = ''; // e.g. https://your.btcpay-server.tld
|
||||
$storeId = '';
|
||||
$updateStoreId = '';
|
||||
$invoiceId = '';
|
||||
|
||||
// Get information about store on BTCPay Server.
|
||||
|
||||
try {
|
||||
$client = new Store($host, $apiKey);
|
||||
var_dump($client->getStore($storeId));
|
||||
@ -22,17 +21,7 @@ try {
|
||||
// Create a new store.
|
||||
try {
|
||||
$client = new Store($host, $apiKey);
|
||||
$newStore = $client->createStore('New store', null, 'EUR');
|
||||
var_dump($newStore);
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error: " . $e->getMessage();
|
||||
}
|
||||
|
||||
// Update a store.
|
||||
// You need to pass all variables to make sure it does not get reset to defaults if you want to preserve them.
|
||||
try {
|
||||
$client = new Store($host, $apiKey);
|
||||
var_dump($client->updateStore($updateStoreId, 'Store name CHANGED'));
|
||||
var_dump($client->createStore('my new store'));
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error: " . $e->getMessage();
|
||||
}
|
||||
@ -22,22 +22,3 @@ try {
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error: " . $e->getMessage();
|
||||
}
|
||||
|
||||
// Get 2 invoices, skip 2
|
||||
try {
|
||||
echo 'Get invoices:' . PHP_EOL;
|
||||
$client = new Invoice($host, $apiKey);
|
||||
var_dump($client->getAllInvoices($storeId, 2, 2));
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error: " . $e->getMessage();
|
||||
}
|
||||
|
||||
// Get newer/equal than 2024-10-20
|
||||
try {
|
||||
echo 'Get invoices newer/equal than 2024-10-20:' . PHP_EOL;
|
||||
$date = new DateTime('2024-10-20');
|
||||
$client = new Invoice($host, $apiKey);
|
||||
var_dump($client->getAllInvoicesWithFilter($storeId, null, null, null, $date->getTimestamp()));
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error: " . $e->getMessage();
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ class PullPayments
|
||||
$autoApproveClaims = false;
|
||||
$startsAt = null;
|
||||
$expiresAt = null;
|
||||
$paymentMethods = ['BTC-CHAIN'];
|
||||
$paymentMethods = ['BTC'];
|
||||
|
||||
try {
|
||||
$client = new PullPayment($this->host, $this->apiKey);
|
||||
@ -113,7 +113,7 @@ class PullPayments
|
||||
|
||||
public function approvePayout()
|
||||
{
|
||||
$payoutId = '';
|
||||
$payoutId ='';
|
||||
try {
|
||||
$client = new PullPayment($this->host, $this->apiKey);
|
||||
var_dump($client->approvePayout(
|
||||
@ -163,7 +163,7 @@ class PullPayments
|
||||
$pullPaymentId = '';
|
||||
$destination = '';
|
||||
$amount = PreciseNumber::parseString('0.000001');
|
||||
$paymentMethod = 'BTC-CHAIN';
|
||||
$paymentMethod = '';
|
||||
|
||||
try {
|
||||
$client = new PullPayment($this->host, $this->apiKey);
|
||||
|
||||
@ -32,21 +32,6 @@ class StoreOnChainWallets
|
||||
}
|
||||
}
|
||||
|
||||
public function createStoreOnChainWallet()
|
||||
{
|
||||
$cryptoCode = 'BTC';
|
||||
|
||||
try {
|
||||
$client = new StoreOnChainWallet($this->host, $this->apiKey);
|
||||
var_dump($client->createStoreOnchainWallet(
|
||||
$this->storeId,
|
||||
$cryptoCode
|
||||
));
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
public function getStoreOnChainWalletFeeRate()
|
||||
{
|
||||
$cryptoCode = 'BTC';
|
||||
@ -186,4 +171,3 @@ $store = new StoreOnChainWallets();
|
||||
$store->getStoreOnChainWalletTransactions();
|
||||
//$store->getStoreOnChainWalletTransaction();
|
||||
//$store->getStoreOnChainWalletUTXOs();
|
||||
//$store->createStoreOnChainWallet();
|
||||
|
||||
@ -1,242 +0,0 @@
|
||||
<?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";
|
||||
}
|
||||
@ -49,7 +49,7 @@ class Users
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteUser($userId)
|
||||
public function deleteUser(string $userId)
|
||||
{
|
||||
try {
|
||||
$client = new User($this->host, $this->apiKey);
|
||||
@ -59,7 +59,7 @@ class Users
|
||||
}
|
||||
}
|
||||
|
||||
public function setUserLock($userId, $toggle)
|
||||
public function setUserLock(string $userId, bool $toggle)
|
||||
{
|
||||
try {
|
||||
$client = new User($this->host, $this->apiKey);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -4,9 +4,11 @@ declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Client;
|
||||
|
||||
use BTCPayServer\Result\Health as ResultHealth;
|
||||
|
||||
class Health extends AbstractClient
|
||||
{
|
||||
public function getHealthStatus(): bool
|
||||
public function getHealthStatus(): ResultHealth
|
||||
{
|
||||
$url = $this->getApiUrl() . 'health';
|
||||
$headers = $this->getRequestHeaders();
|
||||
@ -15,7 +17,9 @@ class Health extends AbstractClient
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return true;
|
||||
return new ResultHealth(
|
||||
json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR)
|
||||
);
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
|
||||
@ -7,7 +7,6 @@ namespace BTCPayServer\Client;
|
||||
use BTCPayServer\Result\Invoice as ResultInvoice;
|
||||
use BTCPayServer\Result\InvoiceList;
|
||||
use BTCPayServer\Result\InvoicePaymentMethod;
|
||||
use BTCPayServer\Result\PullPayment as ResultPullPayment;
|
||||
use BTCPayServer\Util\PreciseNumber;
|
||||
|
||||
class Invoice extends AbstractClient
|
||||
@ -116,71 +115,19 @@ class Invoice extends AbstractClient
|
||||
}
|
||||
}
|
||||
|
||||
public function getAllInvoices(
|
||||
string $storeId,
|
||||
?int $take = null,
|
||||
?int $skip = null
|
||||
): InvoiceList {
|
||||
return $this->getAllInvoicesWithFilter($storeId, null, null, null, null, null, $take, $skip);
|
||||
public function getAllInvoices(string $storeId): InvoiceList
|
||||
{
|
||||
return $this->_getAllInvoicesWithFilter($storeId, null);
|
||||
}
|
||||
|
||||
public function getInvoicesByOrderIds(
|
||||
string $storeId,
|
||||
array $orderIds,
|
||||
?int $take = null,
|
||||
?int $skip = null
|
||||
): InvoiceList {
|
||||
return $this->getAllInvoicesWithFilter($storeId, $orderIds, null, null, null, null, $take, $skip);
|
||||
public function getInvoicesByOrderIds(string $storeId, array $orderIds): InvoiceList
|
||||
{
|
||||
return $this->_getAllInvoicesWithFilter($storeId, $orderIds);
|
||||
}
|
||||
|
||||
public function getInvoicesByText(
|
||||
private function _getAllInvoicesWithFilter(
|
||||
string $storeId,
|
||||
string $text,
|
||||
?int $take = null,
|
||||
?int $skip = null
|
||||
): InvoiceList {
|
||||
return $this->getAllInvoicesWithFilter($storeId, null, $text, null, null, null, $take, $skip);
|
||||
}
|
||||
|
||||
public function getInvoicesByStatus(
|
||||
string $storeId,
|
||||
array $status,
|
||||
?int $take = null,
|
||||
?int $skip = null
|
||||
): InvoiceList {
|
||||
return $this->getAllInvoicesWithFilter($storeId, null, null, $status, null, null, $take, $skip);
|
||||
}
|
||||
|
||||
public function getInvoicesByStartDate(
|
||||
string $storeId,
|
||||
int $startDate,
|
||||
?int $take = null,
|
||||
?int $skip = null
|
||||
): InvoiceList {
|
||||
return $this->getAllInvoicesWithFilter($storeId, null, null, null, $startDate, null, $take, $skip);
|
||||
}
|
||||
|
||||
public function getInvoicesByEndDate(
|
||||
string $storeId,
|
||||
int $endDate,
|
||||
?int $take = null,
|
||||
?int $skip = null
|
||||
): InvoiceList {
|
||||
return $this->getAllInvoicesWithFilter($storeId, null, null, null, null, $endDate, $take, $skip);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Invoices_GetInvoices
|
||||
*/
|
||||
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
|
||||
): InvoiceList {
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/invoices?';
|
||||
if ($filterByOrderIds !== null) {
|
||||
@ -188,26 +135,6 @@ class Invoice extends AbstractClient
|
||||
$url .= 'orderId=' . urlencode($filterByOrderId) . '&';
|
||||
}
|
||||
}
|
||||
if ($filterByText !== null) {
|
||||
$url .= 'textSearch=' . urlencode($filterByText) . '&';
|
||||
}
|
||||
if ($filterByStatus !== null) {
|
||||
foreach ($filterByStatus as $filterByStatusItem) {
|
||||
$url .= 'status=' . urlencode($filterByStatusItem) . '&';
|
||||
}
|
||||
}
|
||||
if ($filterByStartDate !== null) {
|
||||
$url .= 'startDate=' . $filterByStartDate . '&';
|
||||
}
|
||||
if ($filterByEndDate !== null) {
|
||||
$url .= 'endDate=' . $filterByEndDate . '&';
|
||||
}
|
||||
if ($take !== null) {
|
||||
$url .= 'take=' . $take . '&';
|
||||
}
|
||||
if ($skip !== null) {
|
||||
$url .= 'skip=' . $skip . '&';
|
||||
}
|
||||
|
||||
// Clean URL.
|
||||
$url = rtrim($url, '&');
|
||||
@ -232,8 +159,7 @@ class Invoice extends AbstractClient
|
||||
public function getPaymentMethods(string $storeId, string $invoiceId): array
|
||||
{
|
||||
$method = 'GET';
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/invoices/'
|
||||
. urlencode($invoiceId) . '/payment-methods';
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/invoices/' . urlencode($invoiceId) . '/payment-methods';
|
||||
$headers = $this->getRequestHeaders();
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers);
|
||||
|
||||
@ -255,15 +181,11 @@ class Invoice extends AbstractClient
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark an invoice status.
|
||||
*
|
||||
* @see https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Invoices_MarkInvoiceStatus
|
||||
* @throws \JsonException
|
||||
*/
|
||||
public function markInvoiceStatus(string $storeId, string $invoiceId, string $markAs): ResultInvoice
|
||||
{
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/invoices/' . urlencode($invoiceId) . '/status';
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode(
|
||||
$storeId
|
||||
) . '/invoices/' . urlencode($invoiceId) . '/status';
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'POST';
|
||||
|
||||
@ -285,36 +207,18 @@ class Invoice extends AbstractClient
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refund an invoice.
|
||||
*
|
||||
* @see https://docs.btcpayserver.org/API/Greenfield/v1/#operation/Invoices_Refund
|
||||
* @throws \JsonException
|
||||
*/
|
||||
public function refundInvoice(
|
||||
string $storeId,
|
||||
string $invoiceId,
|
||||
?string $refundVariant = 'CurrentRate',
|
||||
?string $paymentMethod = 'BTC',
|
||||
?string $name = null,
|
||||
?string $description = null,
|
||||
?float $subtractPercentage = 0.0,
|
||||
?PreciseNumber $customAmount = null,
|
||||
?string $customCurrency = null
|
||||
): ResultPullPayment {
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/invoices/' . urlencode($invoiceId) . '/refund';
|
||||
public function archiveInvoice(string $storeId, string $invoiceId): bool
|
||||
{
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode(
|
||||
$storeId
|
||||
) . '/invoices/' . urlencode($invoiceId);
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'POST';
|
||||
$method = 'DELETE';
|
||||
|
||||
$body = json_encode(
|
||||
[
|
||||
'name' => $name,
|
||||
'description' => $description,
|
||||
'paymentMethod' => $paymentMethod,
|
||||
'refundVariant' => $refundVariant,
|
||||
'subtractPercentage' => $subtractPercentage,
|
||||
'customAmount' => $customAmount?->__toString(),
|
||||
'customCurrency' => $customCurrency
|
||||
'storeId' => $storeId,
|
||||
'invoiceId' => $invoiceId
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
@ -322,9 +226,61 @@ class Invoice extends AbstractClient
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers, $body);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new ResultPullPayment(
|
||||
json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR)
|
||||
);
|
||||
return true;
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
public function unarchiveInvoice(string $storeId, string $invoiceId): bool
|
||||
{
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode(
|
||||
$storeId
|
||||
) . '/invoices/' . urlencode($invoiceId) . '/unarchive';
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'POST';
|
||||
|
||||
$body = json_encode(
|
||||
[
|
||||
'storeId' => $storeId,
|
||||
'invoiceId' => $invoiceId
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers, $body);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return true;
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
public function activatePaymentMethod(
|
||||
string $storeId,
|
||||
string $invoiceId,
|
||||
string $paymentMethod,
|
||||
): bool {
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode(
|
||||
$storeId
|
||||
) . '/invoices/' . urlencode($invoiceId) . '/payment-methods/' . urlencode($paymentMethod) . '/activate';
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'POST';
|
||||
|
||||
$body = json_encode(
|
||||
[
|
||||
'storeId' => $storeId,
|
||||
'invoiceId' => $invoiceId,
|
||||
'paymentMethod' => $paymentMethod
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers, $body);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return true;
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ class InvoiceCheckoutOptions
|
||||
/** @var int */
|
||||
protected $monitoringMinutes;
|
||||
|
||||
/** @var int */
|
||||
/** @var float */
|
||||
protected $paymentTolerance;
|
||||
|
||||
/** @var string */
|
||||
@ -38,15 +38,19 @@ class InvoiceCheckoutOptions
|
||||
/** @var string */
|
||||
protected $defaultLanguage;
|
||||
|
||||
/** @var bool */
|
||||
protected $requiresRefundEmail;
|
||||
|
||||
public static function create(
|
||||
?string $speedPolicy,
|
||||
?array $paymentMethods,
|
||||
?int $expirationMinutes,
|
||||
?int $monitoringMinutes,
|
||||
?int $paymentTolerance,
|
||||
?float $paymentTolerance,
|
||||
?string $redirectURL,
|
||||
?bool $redirectAutomatically,
|
||||
?string $defaultLanguage
|
||||
?string $defaultLanguage,
|
||||
?bool $requiresRefundEmail = false,
|
||||
) {
|
||||
$options = new InvoiceCheckoutOptions();
|
||||
$options->setSpeedPolicy($speedPolicy);
|
||||
@ -56,7 +60,9 @@ class InvoiceCheckoutOptions
|
||||
$options->paymentTolerance = $paymentTolerance;
|
||||
$options->redirectURL = $redirectURL;
|
||||
$options->redirectAutomatically = $redirectAutomatically;
|
||||
$options->requiresRefundEmail = $requiresRefundEmail;
|
||||
$options->defaultLanguage = $defaultLanguage;
|
||||
$options->requiresRefundEmail = $requiresRefundEmail;
|
||||
return $options;
|
||||
}
|
||||
|
||||
@ -113,12 +119,12 @@ class InvoiceCheckoutOptions
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPaymentTolerance(): ?int
|
||||
public function getPaymentTolerance(): ?float
|
||||
{
|
||||
return $this->paymentTolerance;
|
||||
}
|
||||
|
||||
public function setPaymentTolerance(?int $paymentTolerance): self
|
||||
public function setPaymentTolerance(?float $paymentTolerance): self
|
||||
{
|
||||
$this->paymentTolerance = $paymentTolerance;
|
||||
return $this;
|
||||
@ -146,6 +152,17 @@ class InvoiceCheckoutOptions
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isRequiresRefundEmail(): ?bool
|
||||
{
|
||||
return $this->requiresRefundEmail;
|
||||
}
|
||||
|
||||
public function setRequiresRefundEmail(?bool $requiresRefundEmail): self
|
||||
{
|
||||
$this->requiresRefundEmail = $requiresRefundEmail;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDefaultLanguage(): ?string
|
||||
{
|
||||
return $this->defaultLanguage;
|
||||
@ -170,7 +187,7 @@ class InvoiceCheckoutOptions
|
||||
|
||||
$lastIndex = strrpos($k, $separator);
|
||||
if ($lastIndex !== false) {
|
||||
$k = substr($k, $lastIndex + 1);
|
||||
$k = substr($k, $lastIndex +1);
|
||||
}
|
||||
$array[$k] = $v;
|
||||
}
|
||||
|
||||
@ -138,9 +138,16 @@ class LightningInternalNode extends AbstractClient
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Amount wrapped in a string, represented in a millistatoshi string.
|
||||
* (1000 millisatoshi = 1 satoshi.
|
||||
*
|
||||
* @param string $amount
|
||||
*/
|
||||
public function payLightningInvoice(
|
||||
string $cryptoCode,
|
||||
string $BOLT11,
|
||||
?string $amount,
|
||||
?string $maxFeePercent,
|
||||
?string $maxFeeFlat
|
||||
): LightningPayment {
|
||||
@ -153,6 +160,7 @@ class LightningInternalNode extends AbstractClient
|
||||
$body = json_encode(
|
||||
[
|
||||
'BOLT11' => $BOLT11,
|
||||
'amount' => $amount,
|
||||
'maxFeePercent' => $maxFeePercent,
|
||||
'maxFeeFlat' => $maxFeeFlat,
|
||||
],
|
||||
|
||||
@ -129,7 +129,7 @@ class LightningStore extends AbstractClient
|
||||
}
|
||||
}
|
||||
|
||||
public function getInvoice(
|
||||
public function getLightningInvoice(
|
||||
string $cryptoCode,
|
||||
string $storeId,
|
||||
string $id
|
||||
@ -152,21 +152,33 @@ class LightningStore extends AbstractClient
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Amount wrapped in a string, represented in a millistatoshi string.
|
||||
* (1000 millisatoshi = 1 satoshi.
|
||||
*
|
||||
* @param string $amount
|
||||
*/
|
||||
public function payLightningInvoice(
|
||||
string $cryptoCode,
|
||||
string $storeId,
|
||||
string $BOLT11
|
||||
string $BOLT11,
|
||||
?string $amount = null,
|
||||
?string $maxFeePercent = null,
|
||||
?string $maxFeeFlat = null,
|
||||
): LightningPayment {
|
||||
$url = $this->getApiUrl() . 'stores/' .
|
||||
urlencode($storeId) . '/lightning/' .
|
||||
urlencode($cryptoCode) . '/info';
|
||||
urlencode($cryptoCode) . '/invoices/pay';
|
||||
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'POST';
|
||||
|
||||
$body = json_encode(
|
||||
[
|
||||
'BOLT11' => $BOLT11
|
||||
'BOLT11' => $BOLT11,
|
||||
'amount' => $amount,
|
||||
'maxFeePercent' => $maxFeePercent,
|
||||
'maxFeeFlat' => $maxFeeFlat,
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
|
||||
@ -4,14 +4,14 @@ declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Client;
|
||||
|
||||
use BTCPayServer\Result\InvoiceCheckoutHTML;
|
||||
use BTCPayServer\Result\InvoiceCheckoutHtml;
|
||||
use BTCPayServer\Result\LanguageCodeList;
|
||||
use BTCPayServer\Result\PermissionMetadata;
|
||||
use BTCPayServer\Result\PermissionMetadataList;
|
||||
use BTCPayServer\Result\RateSourceList;
|
||||
|
||||
class Miscellaneous extends AbstractClient
|
||||
{
|
||||
public function getPermissionMetadata(): PermissionMetadata
|
||||
public function getPermissionMetadata(): PermissionMetadataList
|
||||
{
|
||||
$url = $this->getBaseUrl() . '/misc/permissions';
|
||||
$headers = $this->getRequestHeaders();
|
||||
@ -20,7 +20,7 @@ class Miscellaneous extends AbstractClient
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new PermissionMetadata(
|
||||
return new PermissionMetadataList(
|
||||
json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR)
|
||||
);
|
||||
} else {
|
||||
@ -48,7 +48,7 @@ class Miscellaneous extends AbstractClient
|
||||
public function getInvoiceCheckout(
|
||||
string $invoiceId,
|
||||
?string $lang
|
||||
): InvoiceCheckoutHTML {
|
||||
): InvoiceCheckoutHtml {
|
||||
$url = $this->getBaseUrl() . '/i/' . urlencode($invoiceId);
|
||||
|
||||
//set language query parameter if passed
|
||||
@ -62,9 +62,7 @@ class Miscellaneous extends AbstractClient
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new InvoiceCheckoutHTML(
|
||||
json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR)
|
||||
);
|
||||
return new InvoiceCheckoutHtml($response->getBody());
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
|
||||
@ -17,19 +17,13 @@ class PullPayment extends AbstractClient
|
||||
bool $includeArchived
|
||||
): PullPaymentList {
|
||||
$url = $this->getApiUrl() . 'stores/' .
|
||||
urlencode($storeId) . '/pull-payments';
|
||||
urlencode($storeId) . '/pull-payments?includeArchived=' .
|
||||
($includeArchived ? 'true' : 'false');
|
||||
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'GET';
|
||||
|
||||
$body = json_encode(
|
||||
[
|
||||
'includeArchived' => $includeArchived,
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers, $body);
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new PullPaymentList(
|
||||
@ -50,8 +44,7 @@ class PullPayment extends AbstractClient
|
||||
?bool $autoApproveClaims = false,
|
||||
?int $startsAt,
|
||||
?int $expiresAt,
|
||||
?array $paymentMethods = null,
|
||||
?string $description = null
|
||||
array $paymentMethods
|
||||
): ResultPullPayment {
|
||||
$url = $this->getApiUrl() . 'stores/' .
|
||||
urlencode($storeId) . '/pull-payments';
|
||||
@ -62,7 +55,6 @@ class PullPayment extends AbstractClient
|
||||
$body = json_encode(
|
||||
[
|
||||
'name' => $name,
|
||||
'description' => $description,
|
||||
'amount' => $amount->__toString(),
|
||||
'currency' => $currency,
|
||||
'period' => $period,
|
||||
@ -70,8 +62,7 @@ class PullPayment extends AbstractClient
|
||||
'autoApproveClaims' => $autoApproveClaims,
|
||||
'startsAt' => $startsAt,
|
||||
'expiresAt' => $expiresAt,
|
||||
'paymentMethods' => $paymentMethods,
|
||||
'payoutMethods' => $paymentMethods
|
||||
'paymentMethods' => $paymentMethods
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
@ -244,7 +235,6 @@ class PullPayment extends AbstractClient
|
||||
'destination' => $destination,
|
||||
'amount' => $amount->__toString(),
|
||||
'paymentMethod' => $paymentMethod,
|
||||
'payoutMethodId' => $paymentMethod, // BTCPay 2.0.0 compatibilty
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
|
||||
@ -5,6 +5,7 @@ declare(strict_types=1);
|
||||
namespace BTCPayServer\Client;
|
||||
|
||||
use BTCPayServer\Result\Store as ResultStore;
|
||||
use BTCPayServer\Result\StoreList;
|
||||
|
||||
class Store extends AbstractClient
|
||||
{
|
||||
@ -20,7 +21,7 @@ class Store extends AbstractClient
|
||||
int $paymentTolerance = 0,
|
||||
bool $anyoneCanCreateInvoice = false,
|
||||
bool $requiresRefundEmail = false,
|
||||
?string $checkoutType = 'V2',
|
||||
?string $checkoutType = 'V1',
|
||||
?array $receipt = null,
|
||||
bool $lightningAmountInSatoshi = false,
|
||||
bool $lightningPrivateRouteHints = false,
|
||||
@ -35,15 +36,7 @@ class Store extends AbstractClient
|
||||
string $networkFeeMode = 'MultiplePaymentsOnly',
|
||||
bool $payJoinEnabled = false,
|
||||
bool $lazyPaymentMethods = false,
|
||||
string $defaultPaymentMethod = 'BTC',
|
||||
?string $supportUrl = null,
|
||||
bool $archived = false,
|
||||
bool $autodetectLanguage = false,
|
||||
bool $showPayInWalletButton = true,
|
||||
bool $showStoreHeader = true,
|
||||
bool $celebratePayment = true,
|
||||
bool $playSoundOnPayment = false,
|
||||
?array $paymentMethodCriteria = null
|
||||
string $defaultPaymentMethod = 'BTC'
|
||||
): ResultStore {
|
||||
$url = $this->getApiUrl() . 'stores';
|
||||
$headers = $this->getRequestHeaders();
|
||||
@ -53,7 +46,6 @@ class Store extends AbstractClient
|
||||
[
|
||||
"name" => $name,
|
||||
"website" => $website,
|
||||
"supportUrl" => $supportUrl,
|
||||
"defaultCurrency" => $defaultCurrency,
|
||||
"invoiceExpiration" => $invoiceExpiration,
|
||||
"displayExpirationTimer" => $displayExpirationTimer,
|
||||
@ -61,7 +53,6 @@ class Store extends AbstractClient
|
||||
"speedPolicy" => $speedPolicy,
|
||||
"lightningDescriptionTemplate" => $lightningDescriptionTemplate,
|
||||
"paymentTolerance" => $paymentTolerance,
|
||||
"archived" => $archived,
|
||||
"anyoneCanCreateInvoice" => $anyoneCanCreateInvoice,
|
||||
"requiresRefundEmail" => $requiresRefundEmail,
|
||||
"checkoutType" => $checkoutType,
|
||||
@ -78,14 +69,8 @@ class Store extends AbstractClient
|
||||
"htmlTitle" => $htmlTitle,
|
||||
"networkFeeMode" => $networkFeeMode,
|
||||
"payJoinEnabled" => $payJoinEnabled,
|
||||
"autodetectLanguage" => $autodetectLanguage,
|
||||
"showPayInWalletButton" => $showPayInWalletButton,
|
||||
"showStoreHeader" => $showStoreHeader,
|
||||
"celebratePayment" => $celebratePayment,
|
||||
"playSoundOnPayment" => $playSoundOnPayment,
|
||||
"lazyPaymentMethods" => $lazyPaymentMethods,
|
||||
"defaultPaymentMethod" => $defaultPaymentMethod,
|
||||
"paymentMethodCriteria" => $paymentMethodCriteria
|
||||
"defaultPaymentMethod" => $defaultPaymentMethod
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
@ -114,118 +99,9 @@ class Store extends AbstractClient
|
||||
}
|
||||
|
||||
/**
|
||||
* Update store settings. Make sure to pass all the settings, even if you don't want to change them.
|
||||
* @return \BTCPayServer\Result\StoreList
|
||||
*/
|
||||
public function updateStore(
|
||||
string $storeId,
|
||||
string $name,
|
||||
?string $website = null,
|
||||
string $defaultCurrency = 'USD',
|
||||
int $invoiceExpiration = 900,
|
||||
int $displayExpirationTimer = 300,
|
||||
int $monitoringExpiration = 3600,
|
||||
string $speedPolicy = 'MediumSpeed',
|
||||
?string $lightningDescriptionTemplate = null,
|
||||
int $paymentTolerance = 0,
|
||||
bool $anyoneCanCreateInvoice = false,
|
||||
bool $requiresRefundEmail = false,
|
||||
?string $checkoutType = 'V2',
|
||||
?array $receipt = null,
|
||||
bool $lightningAmountInSatoshi = false,
|
||||
bool $lightningPrivateRouteHints = false,
|
||||
bool $onChainWithLnInvoiceFallback = false,
|
||||
bool $redirectAutomatically = false,
|
||||
bool $showRecommendedFee = true,
|
||||
int $recommendedFeeBlockTarget = 1,
|
||||
string $defaultLang = 'en',
|
||||
?string $customLogo = null,
|
||||
?string $customCSS = null,
|
||||
?string $htmlTitle = null,
|
||||
string $networkFeeMode = 'MultiplePaymentsOnly',
|
||||
bool $payJoinEnabled = false,
|
||||
bool $lazyPaymentMethods = false,
|
||||
string $defaultPaymentMethod = 'BTC',
|
||||
?string $supportUrl = null,
|
||||
bool $archived = false,
|
||||
bool $autodetectLanguage = false,
|
||||
bool $showPayInWalletButton = true,
|
||||
bool $showStoreHeader = true,
|
||||
bool $celebratePayment = true,
|
||||
bool $playSoundOnPayment = false,
|
||||
?array $paymentMethodCriteria = null
|
||||
): ResultStore {
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId);
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'PUT';
|
||||
|
||||
$body = json_encode(
|
||||
[
|
||||
"name" => $name,
|
||||
"website" => $website,
|
||||
"supportUrl" => $supportUrl,
|
||||
"defaultCurrency" => $defaultCurrency,
|
||||
"invoiceExpiration" => $invoiceExpiration,
|
||||
"displayExpirationTimer" => $displayExpirationTimer,
|
||||
"monitoringExpiration" => $monitoringExpiration,
|
||||
"speedPolicy" => $speedPolicy,
|
||||
"lightningDescriptionTemplate" => $lightningDescriptionTemplate,
|
||||
"paymentTolerance" => $paymentTolerance,
|
||||
"archived" => $archived,
|
||||
"anyoneCanCreateInvoice" => $anyoneCanCreateInvoice,
|
||||
"requiresRefundEmail" => $requiresRefundEmail,
|
||||
"checkoutType" => $checkoutType,
|
||||
"receipt" => $receipt,
|
||||
"lightningAmountInSatoshi" => $lightningAmountInSatoshi,
|
||||
"lightningPrivateRouteHints" => $lightningPrivateRouteHints,
|
||||
"onChainWithLnInvoiceFallback" => $onChainWithLnInvoiceFallback,
|
||||
"redirectAutomatically" => $redirectAutomatically,
|
||||
"showRecommendedFee" => $showRecommendedFee,
|
||||
"recommendedFeeBlockTarget" => $recommendedFeeBlockTarget,
|
||||
"defaultLang" => $defaultLang,
|
||||
"customLogo" => $customLogo,
|
||||
"customCSS" => $customCSS,
|
||||
"htmlTitle" => $htmlTitle,
|
||||
"networkFeeMode" => $networkFeeMode,
|
||||
"payJoinEnabled" => $payJoinEnabled,
|
||||
"autodetectLanguage" => $autodetectLanguage,
|
||||
"showPayInWalletButton" => $showPayInWalletButton,
|
||||
"showStoreHeader" => $showStoreHeader,
|
||||
"celebratePayment" => $celebratePayment,
|
||||
"playSoundOnPayment" => $playSoundOnPayment,
|
||||
"lazyPaymentMethods" => $lazyPaymentMethods,
|
||||
"defaultPaymentMethod" => $defaultPaymentMethod,
|
||||
"paymentMethodCriteria" => $paymentMethodCriteria
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers, $body);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new ResultStore(json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR));
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteStore(string $storeId): bool
|
||||
{
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId);
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'DELETE';
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return true;
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \BTCPayServer\Result\Store[]
|
||||
*/
|
||||
public function getStores(): array
|
||||
public function getStores(): StoreList
|
||||
{
|
||||
$url = $this->getApiUrl() . 'stores';
|
||||
$headers = $this->getRequestHeaders();
|
||||
@ -233,13 +109,8 @@ class Store extends AbstractClient
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
$r = [];
|
||||
$data = json_decode($response->getBody(), true);
|
||||
foreach ($data as $item) {
|
||||
$item = new ResultStore($item);
|
||||
$r[] = $item;
|
||||
}
|
||||
return $r;
|
||||
return new StoreList($data);
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ use BTCPayServer\Result\StoreOnChainWalletAddress;
|
||||
use BTCPayServer\Result\StoreOnChainWalletFeeRate;
|
||||
use BTCPayServer\Result\StoreOnChainWalletTransaction;
|
||||
use BTCPayServer\Result\StoreOnChainWalletTransactionList;
|
||||
use BTCPayServer\Result\StoreOnChainWalletUTXOList;
|
||||
use BTCPayServer\Result\StoreOnChainWalletUtxoList;
|
||||
|
||||
class StoreOnChainWallet extends AbstractClient
|
||||
{
|
||||
@ -35,50 +35,6 @@ class StoreOnChainWallet extends AbstractClient
|
||||
}
|
||||
}
|
||||
|
||||
public function createStoreOnChainWallet(
|
||||
string $storeId,
|
||||
string $cryptoCode,
|
||||
?string $existingMnemonic = null,
|
||||
?string $passphrase = null,
|
||||
int $accountNumber = 0,
|
||||
bool $savePrivateKeys = false,
|
||||
bool $importKeysToRPC = false,
|
||||
string $wordList = 'English',
|
||||
int $wordCount = 12,
|
||||
string $scriptPubKeyType = 'Segwit'
|
||||
): ResultStoreOnChainWallet {
|
||||
$url = $this->getApiUrl() . 'stores/' .
|
||||
urlencode($storeId) . '/payment-methods/onchain/' .
|
||||
urlencode($cryptoCode) . '/generate';
|
||||
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'POST';
|
||||
|
||||
$body = json_encode(
|
||||
[
|
||||
'existingMnemonic' => $existingMnemonic,
|
||||
'passphrase' => $passphrase,
|
||||
'accountNumber' => $accountNumber,
|
||||
'savePrivateKeys' => $savePrivateKeys,
|
||||
'importKeysToRPC' => $importKeysToRPC,
|
||||
'wordList' => $wordList,
|
||||
'wordCount' => $wordCount,
|
||||
'scriptPubKeyType' => $scriptPubKeyType
|
||||
],
|
||||
JSON_THROW_ON_ERROR
|
||||
);
|
||||
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers, $body);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new ResultStoreOnChainWallet(
|
||||
json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR)
|
||||
);
|
||||
} else {
|
||||
throw $this->getExceptionByStatusCode($method, $url, $response);
|
||||
}
|
||||
}
|
||||
|
||||
public function getStoreOnChainWalletFeeRate(
|
||||
string $storeId,
|
||||
string $cryptoCode,
|
||||
@ -285,10 +241,10 @@ class StoreOnChainWallet extends AbstractClient
|
||||
}
|
||||
}
|
||||
|
||||
public function getStoreOnChainWalletUTXOs(
|
||||
public function getStoreOnChainWalletUtxos(
|
||||
string $storeId,
|
||||
string $cryptoCode
|
||||
): StoreOnChainWalletUTXOList {
|
||||
): StoreOnChainWalletUtxoList {
|
||||
$url = $this->getApiUrl() . 'stores/' .
|
||||
urlencode($storeId) . '/payment-methods' . '/OnChain' . '/' .
|
||||
urlencode($cryptoCode) . '/wallet' . '/utxos';
|
||||
@ -299,7 +255,7 @@ class StoreOnChainWallet extends AbstractClient
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers);
|
||||
|
||||
if ($response->getStatus() === 200) {
|
||||
return new StoreOnChainWalletUTXOList(
|
||||
return new StoreOnChainWalletUtxoList(
|
||||
json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR)
|
||||
);
|
||||
} else {
|
||||
|
||||
@ -15,12 +15,9 @@ use BTCPayServer\Result\StorePaymentMethodCollection;
|
||||
*/
|
||||
class StorePaymentMethod extends AbstractClient
|
||||
{
|
||||
public function getPaymentMethods(string $storeId, bool $includeConfig = false): array
|
||||
public function getPaymentMethods(string $storeId): array
|
||||
{
|
||||
$url = $this->getApiUrl() . 'stores/' . urlencode($storeId) . '/payment-methods';
|
||||
if ($includeConfig) {
|
||||
$url .= '?includeConfig=true';
|
||||
}
|
||||
$headers = $this->getRequestHeaders();
|
||||
$method = 'GET';
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers);
|
||||
|
||||
@ -10,8 +10,6 @@ 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,8 +10,6 @@ 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
|
||||
{
|
||||
@ -135,7 +133,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();
|
||||
|
||||
@ -1,493 +0,0 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -59,7 +59,7 @@ class User extends AbstractClient
|
||||
|
||||
$response = $this->getHttpClient()->request($method, $url, $headers, $body);
|
||||
|
||||
if ($response->getStatus() === 201) {
|
||||
if ($response->getStatus() === 200) {
|
||||
return new ResultUser(
|
||||
json_decode($response->getBody(), true, 512, JSON_THROW_ON_ERROR)
|
||||
);
|
||||
|
||||
@ -238,7 +238,7 @@ class Webhook extends AbstractClient
|
||||
if ($requestBody && $btcpaySigHeader) {
|
||||
$expectedHeader = 'sha256=' . hash_hmac('sha256', $requestBody, $secret);
|
||||
|
||||
if (hash_equals($expectedHeader, $btcpaySigHeader)) {
|
||||
if ($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'])) {
|
||||
|
||||
@ -6,18 +6,4 @@ namespace BTCPayServer\Result;
|
||||
|
||||
class ApiKey extends AbstractResult
|
||||
{
|
||||
public function getApiKey(): string
|
||||
{
|
||||
return $this->getData()['apiKey'];
|
||||
}
|
||||
|
||||
public function getLabel(): string
|
||||
{
|
||||
return $this->getData()['label'];
|
||||
}
|
||||
|
||||
public function getPermissions(): array
|
||||
{
|
||||
return $this->getData()['permissions'];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
<?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'];
|
||||
}
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
<?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'];
|
||||
}
|
||||
}
|
||||
14
src/Result/Health.php
Normal file
14
src/Result/Health.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
class Health extends AbstractResult
|
||||
{
|
||||
public function isSyncronized(): bool
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['synchronized'];
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
use BTCPayServer\Client\InvoiceCheckoutOptions;
|
||||
use BTCPayServer\Util\PreciseNumber;
|
||||
|
||||
class Invoice extends AbstractResult
|
||||
@ -26,6 +27,11 @@ class Invoice extends AbstractResult
|
||||
|
||||
public const ADDITIONAL_STATUS_PAID_LATE = 'PaidLate';
|
||||
|
||||
public function getMetaData(): array
|
||||
{
|
||||
return $this->getData()['metadata'];
|
||||
}
|
||||
|
||||
public function getId(): string
|
||||
{
|
||||
return $this->getData()['id'];
|
||||
@ -36,6 +42,11 @@ class Invoice extends AbstractResult
|
||||
return PreciseNumber::parseString($this->getData()['amount']);
|
||||
}
|
||||
|
||||
public function getStoreId(): string
|
||||
{
|
||||
return $this->getData()['storeId'];
|
||||
}
|
||||
|
||||
public function getCurrency(): string
|
||||
{
|
||||
return $this->getData()['currency'];
|
||||
@ -61,9 +72,9 @@ class Invoice extends AbstractResult
|
||||
return $this->getData()['expirationTime'];
|
||||
}
|
||||
|
||||
public function getMonitoringTime(): int
|
||||
public function getMonitoringExpiration(): int
|
||||
{
|
||||
return $this->getData()['monitoringTime'];
|
||||
return $this->getData()['monitoringExpiration'];
|
||||
}
|
||||
|
||||
public function isArchived(): bool
|
||||
@ -71,6 +82,28 @@ class Invoice extends AbstractResult
|
||||
return $this->getData()['archived'];
|
||||
}
|
||||
|
||||
public function getCheckoutOptions(): InvoiceCheckoutOptions
|
||||
{
|
||||
$options = new InvoiceCheckoutOptions();
|
||||
$options->setSpeedPolicy($this->getData()['checkout']['speedPolicy']);
|
||||
$options->setPaymentMethods($this->getData()['checkout']['paymentMethods']);
|
||||
$options->setExpirationMinutes($this->getData()['checkout']['expirationMinutes']);
|
||||
$options->setMonitoringMinutes($this->getData()['checkout']['monitoringMinutes']);
|
||||
$options->setPaymentTolerance($this->getData()['checkout']['paymentTolerance']);
|
||||
$options->setRedirectURL($this->getData()['checkout']['redirectURL']);
|
||||
$options->setRedirectAutomatically($this->getData()['checkout']['redirectAutomatically']);
|
||||
$options->setRequiresRefundEmail($this->getData()['checkout']['requiresRefundEmail']);
|
||||
$options->setDefaultLanguage($this->getData()['checkout']['defaultLanguage']);
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
public function isPaid(): bool
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['status'] === self::STATUS_SETTLED || $data['additionalStatus'] === self::ADDITIONAL_STATUS_PAID_PARTIAL;
|
||||
}
|
||||
|
||||
public function isNew(): bool
|
||||
{
|
||||
$data = $this->getData();
|
||||
@ -88,6 +121,11 @@ class Invoice extends AbstractResult
|
||||
return $this->getData()['status'];
|
||||
}
|
||||
|
||||
public function getAdditionalStatus(): string
|
||||
{
|
||||
return $this->getData()['additionalStatus'];
|
||||
}
|
||||
|
||||
public function isExpired(): bool
|
||||
{
|
||||
$data = $this->getData();
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
class InvoiceCheckoutHTML extends AbstractResult
|
||||
{
|
||||
}
|
||||
28
src/Result/InvoiceCheckoutHtml.php
Normal file
28
src/Result/InvoiceCheckoutHtml.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
class InvoiceCheckoutHtml
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $html;
|
||||
|
||||
public function __construct(string $html)
|
||||
{
|
||||
$this->html = $html;
|
||||
}
|
||||
|
||||
public function getHtml(): string
|
||||
{
|
||||
return $this->html;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->html;
|
||||
}
|
||||
}
|
||||
@ -59,37 +59,25 @@ class InvoicePaymentMethod extends AbstractResult
|
||||
public function getNetworkFee(): string
|
||||
{
|
||||
$data = $this->getData();
|
||||
// BTCPay 2.0.0 compatibility: networkFee was renamed to paymentMethodFee.
|
||||
return $data['networkFee'] ?? $data['paymentMethodFee'];
|
||||
return $data['networkFee'];
|
||||
}
|
||||
|
||||
public function getPaymentMethod(): string
|
||||
{
|
||||
$data = $this->getData();
|
||||
// BTCPay 2.0.0 compatibility: paymentMethod was renamed to paymentMethodId.
|
||||
return $data['paymentMethod'] ?? $data['paymentMethodId'];
|
||||
return $data['paymentMethod'];
|
||||
}
|
||||
|
||||
public function getCryptoCode(): string
|
||||
{
|
||||
$data = $this->getData();
|
||||
|
||||
// For future compatibility check if cryptoCode exists.
|
||||
if (isset($data['cryptoCode'])) {
|
||||
return $data['cryptoCode'];
|
||||
} else {
|
||||
// Extract cryptoCode from paymentMethod string.
|
||||
$parts = explode('-', $this->getPaymentMethod());
|
||||
$parts = explode('-', $data['paymentMethod']);
|
||||
return $parts[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* New field as of BTCPay 2.0.0.
|
||||
*/
|
||||
public function getCurrency(): ?string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['currency'] ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,13 +7,13 @@ namespace BTCPayServer\Result;
|
||||
class LanguageCodeList extends AbstractListResult
|
||||
{
|
||||
/**
|
||||
* @return \BTCPayServer\Result\LanguageCode[]
|
||||
* @return LanguageCode[]
|
||||
*/
|
||||
public function all(): array
|
||||
{
|
||||
$languageCodes = [];
|
||||
foreach ($this->getData() as $languageCode) {
|
||||
$languageCodes[] = new \BTCPayServer\Result\LanguageCode($languageCode);
|
||||
$languageCodes[] = new LanguageCode($languageCode);
|
||||
}
|
||||
return $languageCodes;
|
||||
}
|
||||
|
||||
@ -1,66 +0,0 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
@ -1,81 +0,0 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
20
src/Result/PermissionMetadataList.php
Normal file
20
src/Result/PermissionMetadataList.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
class PermissionMetadataList extends AbstractListResult
|
||||
{
|
||||
/**
|
||||
* @return PermissionMetadata[]
|
||||
*/
|
||||
public function all(): array
|
||||
{
|
||||
$permissionMetadataList = [];
|
||||
foreach ($this->getData() as $permissionMetadata) {
|
||||
$permissionMetadataList[] = new PermissionMetadata($permissionMetadata);
|
||||
}
|
||||
return $permissionMetadataList;
|
||||
}
|
||||
}
|
||||
@ -1,113 +0,0 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
<?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'];
|
||||
}
|
||||
}
|
||||
@ -20,12 +20,6 @@ class PullPayment extends AbstractResult
|
||||
return $data['name'];
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['description'];
|
||||
}
|
||||
|
||||
public function getCurrency(): string
|
||||
{
|
||||
$data = $this->getData();
|
||||
|
||||
@ -10,61 +10,53 @@ class PullPaymentPayout extends AbstractResult
|
||||
{
|
||||
public function getId(): string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['id'];
|
||||
return $this->getData()['id'];
|
||||
}
|
||||
|
||||
public function getRevision(): int
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['revision'];
|
||||
return $this->getData()['revision'];
|
||||
}
|
||||
|
||||
public function getPullPaymentId(): string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['pullPaymentId'];
|
||||
return $this->getData()['pullPaymentId'];
|
||||
}
|
||||
|
||||
public function getDate(): string
|
||||
public function getDate(): int
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['date'];
|
||||
return $this->getData()['date'];
|
||||
}
|
||||
|
||||
public function getDestination(): string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['destination'];
|
||||
return $this->getData()['destination'];
|
||||
}
|
||||
|
||||
public function getAmount(): PreciseNumber
|
||||
{
|
||||
$data = $this->getData();
|
||||
return PreciseNumber::parseString($data['amount']);
|
||||
return PreciseNumber::parseString($this->getData()['amount']);
|
||||
}
|
||||
|
||||
public function getPaymentMethod(): string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['paymentMethod'];
|
||||
return $this->getData()['paymentMethod'];
|
||||
}
|
||||
|
||||
public function getCryptoCode(): string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['cryptoCode'];
|
||||
return $this->getData()['cryptoCode'];
|
||||
}
|
||||
|
||||
public function getPaymentMethodAmount(): PreciseNumber
|
||||
public function getPaymentMethodAmount(): ?PreciseNumber
|
||||
{
|
||||
$data = $this->getData();
|
||||
return PreciseNumber::parseString($data['paymentMethodAmount']);
|
||||
return (isset($this->getData()['paymentMethodAmount']))
|
||||
? PreciseNumber::parseString($this->getData()['paymentMethodAmount'])
|
||||
: null;
|
||||
}
|
||||
|
||||
public function getState(): string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['state'];
|
||||
return $this->getData()['state'];
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,5 +32,8 @@ class ServerInfo extends AbstractResult
|
||||
return $this->getData()['supportedPaymentMethods'];
|
||||
}
|
||||
|
||||
// TODO add "syncStatus" structure
|
||||
public function getSyncStatus(): ServerSyncStatusList
|
||||
{
|
||||
return new ServerSyncStatusList($this->getData()['syncStatus']);
|
||||
}
|
||||
}
|
||||
|
||||
33
src/Result/ServerSyncStatus.php
Normal file
33
src/Result/ServerSyncStatus.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
class ServerSyncStatus extends AbstractResult
|
||||
{
|
||||
public function getChainHeight(): int
|
||||
{
|
||||
return $this->getData()['chainHeight'];
|
||||
}
|
||||
|
||||
public function getSyncHeight(): int
|
||||
{
|
||||
return $this->getData()['syncHeight'];
|
||||
}
|
||||
|
||||
public function getNodeInformation(): ServerSyncStatusNodeInformation
|
||||
{
|
||||
return new ServerSyncStatusNodeInformation($this->getData()['nodeInformation']);
|
||||
}
|
||||
|
||||
public function getCryptoCode(): string
|
||||
{
|
||||
return $this->getData()['cryptoCode'];
|
||||
}
|
||||
|
||||
public function isAvailable(): bool
|
||||
{
|
||||
return $this->getData()['available'];
|
||||
}
|
||||
}
|
||||
20
src/Result/ServerSyncStatusList.php
Normal file
20
src/Result/ServerSyncStatusList.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
class ServerSyncStatusList extends AbstractResult
|
||||
{
|
||||
/**
|
||||
* @return \BTCPayServer\Result\ServerSyncStatus[]
|
||||
*/
|
||||
public function all(): array
|
||||
{
|
||||
$serverSyncStatuses = [];
|
||||
foreach ($this->getData() as $serverSyncStatus) {
|
||||
$serverSyncStatuses[] = new \BTCPayServer\Result\ServerSyncStatus($serverSyncStatus);
|
||||
}
|
||||
return $serverSyncStatuses;
|
||||
}
|
||||
}
|
||||
25
src/Result/ServerSyncStatusNodeInformation.php
Normal file
25
src/Result/ServerSyncStatusNodeInformation.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
use BTCPayServer\Util\PreciseNumber;
|
||||
|
||||
class ServerSyncStatusNodeInformation extends AbstractResult
|
||||
{
|
||||
public function getHeaders(): int
|
||||
{
|
||||
return $this->getData()['headers'];
|
||||
}
|
||||
|
||||
public function getBlocks(): int
|
||||
{
|
||||
return $this->getData()['blocks'];
|
||||
}
|
||||
|
||||
public function getVerificationProgress(): PreciseNumber
|
||||
{
|
||||
return PreciseNumber::parseFloat($this->getData()['verificationProgress']);
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,8 @@ declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
use BTCPayServer\Util\PreciseNumber;
|
||||
|
||||
class Store extends AbstractResult
|
||||
{
|
||||
public function getName(): string
|
||||
@ -12,13 +14,13 @@ class Store extends AbstractResult
|
||||
return $data['name'];
|
||||
}
|
||||
|
||||
public function getWebsite(): string
|
||||
public function getWebsite(): ?string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['website'];
|
||||
}
|
||||
|
||||
public function getDefaultCurrency(): string
|
||||
public function getDefaultCurrency(): ?string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['defaultCurrency'];
|
||||
@ -48,10 +50,10 @@ class Store extends AbstractResult
|
||||
return $data['lightningDescriptionTemplate'];
|
||||
}
|
||||
|
||||
public function getPaymentTolerance(): int
|
||||
public function getPaymentTolerance(): PreciseNumber
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['paymentTolerance'];
|
||||
return PreciseNumber::parseFloat($data['paymentTolerance']);
|
||||
}
|
||||
|
||||
public function anyoneCanCreateInvoice(): bool
|
||||
@ -102,25 +104,25 @@ class Store extends AbstractResult
|
||||
return $data['recommendedFeeBlockTarget'];
|
||||
}
|
||||
|
||||
public function getDefaultLang(): string
|
||||
public function getDefaultLang(): ?string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['defaultLang'];
|
||||
}
|
||||
|
||||
public function getCustomLogo(): string
|
||||
public function getCustomLogo(): ?string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['customLogo'];
|
||||
}
|
||||
|
||||
public function getCustomCSS(): string
|
||||
public function getCustomCSS(): ?string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['customCSS'];
|
||||
}
|
||||
|
||||
public function getHtmlTitle(): string
|
||||
public function getHtmlTitle(): ?string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['htmlTitle'];
|
||||
@ -144,7 +146,7 @@ class Store extends AbstractResult
|
||||
return $data['lazyPaymentMethods'];
|
||||
}
|
||||
|
||||
public function getDefaultPaymentMethod(): string
|
||||
public function getDefaultPaymentMethod(): ?string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['defaultPaymentMethod'];
|
||||
|
||||
@ -6,39 +6,45 @@ namespace BTCPayServer\Result;
|
||||
|
||||
class StoreEmailSettings extends AbstractResult
|
||||
{
|
||||
public function getServer(): string
|
||||
public function getServer(): ?string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['server'];
|
||||
}
|
||||
|
||||
public function getPort(): string
|
||||
public function getPort(): ?int
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['port'];
|
||||
}
|
||||
|
||||
public function getUsername(): string
|
||||
public function getUsername(): ?string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['login'];
|
||||
}
|
||||
|
||||
public function getPassword(): string
|
||||
public function getPassword(): ?string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['password'];
|
||||
}
|
||||
|
||||
public function getFromEmail(): string
|
||||
public function getFromEmail(): ?string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['from'];
|
||||
}
|
||||
|
||||
public function getFromName(): string
|
||||
public function getFromName(): ?string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['fromDisplay'];
|
||||
}
|
||||
|
||||
public function getDisableCertificateCheck(): ?bool
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['disableCertificateCheck'];
|
||||
}
|
||||
}
|
||||
|
||||
20
src/Result/StoreList.php
Normal file
20
src/Result/StoreList.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
class StoreList extends AbstractListResult
|
||||
{
|
||||
/**
|
||||
* @return Store[]
|
||||
*/
|
||||
public function all(): array
|
||||
{
|
||||
$stores = [];
|
||||
foreach ($this->getData() as $store) {
|
||||
$stores[] = new Store($store);
|
||||
}
|
||||
return $stores;
|
||||
}
|
||||
}
|
||||
@ -25,4 +25,10 @@ class StoreOnChainWallet extends AbstractResult
|
||||
$data = $this->getData();
|
||||
return PreciseNumber::parseString($data['confirmedBalance']);
|
||||
}
|
||||
|
||||
public function getLabel(): string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['label'];
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,11 +4,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
use BTCPayServer\Util\PreciseNumber;
|
||||
|
||||
class StoreOnChainWalletFeeRate extends AbstractResult
|
||||
{
|
||||
public function getFeeRate(): float
|
||||
public function getFeeRate(): PreciseNumber
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['feeRate'];
|
||||
return PreciseNumber::parseFloat($data['feeRate']);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,50 +4,61 @@ declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
use BTCPayServer\Util\PreciseNumber;
|
||||
|
||||
class StoreOnChainWalletTransaction extends AbstractResult
|
||||
{
|
||||
public function getDestinations(): StoreOnChainWalletTransactionDestinationList
|
||||
public function getTransactionHash(): string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return new StoreOnChainWalletTransactionDestinationList($data['destinations']);
|
||||
return $data['transactionHash'];
|
||||
}
|
||||
|
||||
public function getFeeRate(): StoreOnChainWalletFeeRate
|
||||
public function getComment(): string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return new StoreOnChainWalletFeeRate($data['feeRate']);
|
||||
return $data['comment'];
|
||||
}
|
||||
|
||||
public function proceedWithPayjoin(): bool
|
||||
public function getAmount(): PreciseNumber
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['proceedWithPayjoin'];
|
||||
return new PreciseNumber($data['amount']);
|
||||
}
|
||||
|
||||
public function proceedWithBroadcast(): bool
|
||||
public function getLabels(): array
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['proceedWithBroadcast'];
|
||||
return $data['labels'];
|
||||
}
|
||||
|
||||
public function noChange(): bool
|
||||
public function getBlockHash(): ?string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['noChange'];
|
||||
return $data['blockHash'];
|
||||
}
|
||||
|
||||
public function rbf(): bool
|
||||
public function getBlockHeight(): ?int
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['rbf'];
|
||||
return $data['blockHeight'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array strings
|
||||
*/
|
||||
public function selectedInputs(): array
|
||||
public function getConfirmations(): int
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['selectedInputs'];
|
||||
return $data['confirmations'];
|
||||
}
|
||||
|
||||
public function getTimestamp(): int
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['timestamp'];
|
||||
}
|
||||
|
||||
public function getStatus(): string
|
||||
{
|
||||
$data = $this->getData();
|
||||
return $data['status'];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
class StoreOnChainWalletUTXOList extends AbstractListResult
|
||||
{
|
||||
/**
|
||||
* @return \BTCPayServer\Result\StoreOnChainWalletUTXO[]
|
||||
*/
|
||||
public function all(): array
|
||||
{
|
||||
$storeWalletUTXOs = [];
|
||||
foreach ($this->getData() as $storeWalletUTXO) {
|
||||
$storeWalletUTXOs[] = new \BTCPayServer\Result\StoreOnChainWalletUTXO($storeWalletUTXO);
|
||||
}
|
||||
return $storeWalletUTXOs;
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,7 @@ namespace BTCPayServer\Result;
|
||||
|
||||
use BTCPayServer\Util\PreciseNumber;
|
||||
|
||||
class StoreOnChainWalletUTXO extends AbstractResult
|
||||
class StoreOnChainWalletUtxo extends AbstractResult
|
||||
{
|
||||
public function getComment(): string
|
||||
{
|
||||
20
src/Result/StoreOnChainWalletUtxoList.php
Normal file
20
src/Result/StoreOnChainWalletUtxoList.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Result;
|
||||
|
||||
class StoreOnChainWalletUtxoList extends AbstractListResult
|
||||
{
|
||||
/**
|
||||
* @return \BTCPayServer\Result\StoreOnChainWalletUtxo[]
|
||||
*/
|
||||
public function all(): array
|
||||
{
|
||||
$storeWalletUtxos = [];
|
||||
foreach ($this->getData() as $storeWalletUtxo) {
|
||||
$storeWalletUtxos[] = new StoreOnChainWalletUtxo($storeWalletUtxo);
|
||||
}
|
||||
return $storeWalletUtxos;
|
||||
}
|
||||
}
|
||||
@ -13,40 +13,17 @@ class StorePaymentMethodCollection extends AbstractListResult
|
||||
{
|
||||
$r = [];
|
||||
foreach ($this->getData() as $paymentMethod => $paymentMethodData) {
|
||||
// BTCPay 2.0 compatibility: List is not a keyed array anymore so fix it here.
|
||||
if (is_numeric($paymentMethod)) {
|
||||
$paymentMethod = $paymentMethodData['paymentMethodId'];
|
||||
// Extract the cryptoCode from the paymentMethodId. e.g. "BTC-CHAIN" -> "BTC"
|
||||
$parts = explode('-', $paymentMethod);
|
||||
$extractedCryptoCode = $parts[0];
|
||||
}
|
||||
|
||||
// Consistency: Flatten the array to be consistent with the specific
|
||||
// payment method endpoints.
|
||||
if (isset($paymentMethodData['data'])) {
|
||||
$paymentMethodData += $paymentMethodData['data'];
|
||||
unset($paymentMethodData['data']);
|
||||
}
|
||||
$paymentMethodData += $paymentMethodData['data'];
|
||||
unset($paymentMethodData['data']);
|
||||
|
||||
// BTCPay 2.0 compatibility: Handle config data if exists.
|
||||
if (isset($paymentMethodData['config'])) {
|
||||
$paymentMethodData += $paymentMethodData['config'];
|
||||
unset($paymentMethodData['config']);
|
||||
}
|
||||
|
||||
// BTCPay 2.0 compatibility: Check for renamed LN payment method id.
|
||||
if (preg_match('/(LightningNetwork|-LN$)/', $paymentMethod)) {
|
||||
if (strpos($paymentMethod, 'LightningNetwork') !== false) {
|
||||
// Consistency: Add back the cryptoCode missing on this endpoint
|
||||
// results until it is there.
|
||||
if (!isset($paymentMethodData['cryptoCode'])) {
|
||||
$paymentMethodData['cryptoCode'] = str_replace('-LightningNetwork', '', $paymentMethod);
|
||||
}
|
||||
|
||||
// BTCPay 2.0 compatibility: put the extracted cryptoCode in the cryptoCode field.
|
||||
if (isset($extractedCryptoCode)) {
|
||||
$paymentMethodData['cryptoCode'] = $extractedCryptoCode;
|
||||
}
|
||||
|
||||
$r[] = new StorePaymentMethodLightningNetwork($paymentMethodData, $paymentMethod);
|
||||
} else {
|
||||
// Consistency: Add back the cryptoCode missing on this endpoint
|
||||
@ -54,12 +31,6 @@ class StorePaymentMethodCollection extends AbstractListResult
|
||||
if (!isset($paymentMethodData['cryptoCode'])) {
|
||||
$paymentMethodData['cryptoCode'] = $paymentMethod;
|
||||
}
|
||||
|
||||
// BTCPay 2.0 compatibility: put the currency code in the cryptoCode field.
|
||||
if (isset($extractedCryptoCode)) {
|
||||
$paymentMethodData['cryptoCode'] = $extractedCryptoCode;
|
||||
}
|
||||
|
||||
$r[] = new StorePaymentMethodOnChain($paymentMethodData, $paymentMethod);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,93 +0,0 @@
|
||||
<?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'];
|
||||
}
|
||||
}
|
||||
@ -32,7 +32,7 @@ class BaseTest extends TestCase
|
||||
$this->storeId = $_ENV['BTCPAY_STORE_ID'];
|
||||
}
|
||||
|
||||
public function testThatAllTheVariablesAreSet(): void
|
||||
public function testItSetsAllTheEnvironmentVariables(): void
|
||||
{
|
||||
$this->assertIsString($this->apiKey);
|
||||
$this->assertIsString($this->host);
|
||||
@ -44,4 +44,10 @@ class BaseTest extends TestCase
|
||||
$this->assertNotEmpty($this->storeId);
|
||||
$this->assertNotEmpty($this->nodeUri);
|
||||
}
|
||||
|
||||
public function dd($var): void
|
||||
{
|
||||
var_dump($var);
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
27
tests/HealthTest.php
Normal file
27
tests/HealthTest.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Tests;
|
||||
|
||||
use BTCPayServer\Client\Health;
|
||||
use BTCPayServer\Result\Health as ResultHealth;
|
||||
|
||||
final class HealthTest extends BaseTest
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
/** @group getHealthStatus */
|
||||
public function testItCanGetHealthStatus(): void
|
||||
{
|
||||
$healthClient = new Health($this->host, $this->apiKey);
|
||||
$health = $healthClient->getHealthStatus();
|
||||
|
||||
$this->assertInstanceOf(ResultHealth::class, $health);
|
||||
|
||||
$this->assertIsBool($health->isSyncronized());
|
||||
}
|
||||
}
|
||||
215
tests/InvoiceTest.php
Normal file
215
tests/InvoiceTest.php
Normal file
@ -0,0 +1,215 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Tests;
|
||||
|
||||
use BTCPayServer\Client\Invoice;
|
||||
use BTCPayServer\Client\InvoiceCheckoutOptions;
|
||||
use BTCPayServer\Result\Invoice as ResultInvoice;
|
||||
use BTCPayServer\Result\InvoicePaymentMethod;
|
||||
use BTCPayServer\Util\PreciseNumber;
|
||||
|
||||
final class InvoiceTest extends BaseTest
|
||||
{
|
||||
private ResultInvoice $resultInvoice;
|
||||
private Invoice $invoiceClient;
|
||||
private InvoiceCheckoutOptions $invoiceCheckoutOptions;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->invoiceClient = new Invoice($this->host, $this->apiKey);
|
||||
|
||||
$this->invoiceCheckoutOptions = new InvoiceCheckoutOptions();
|
||||
$this->invoiceCheckoutOptions->setRedirectAutomatically(true);
|
||||
$this->invoiceCheckoutOptions->setRedirectURL('https://example.com/redirect');
|
||||
$this->invoiceCheckoutOptions->setDefaultLanguage('EN');
|
||||
$this->invoiceCheckoutOptions->setPaymentMethods(['BTC-LightningNetwork']);
|
||||
$this->invoiceCheckoutOptions->setRequiresRefundEmail(true);
|
||||
|
||||
$this->resultInvoice = $this->invoiceClient->createInvoice(
|
||||
storeId: $this->storeId,
|
||||
currency: 'SATS',
|
||||
amount: PreciseNumber::parseString('1000'),
|
||||
orderId: '1234',
|
||||
buyerEmail: 'testing@btcpayserver.org',
|
||||
metaData: [
|
||||
'user_id' => '123456789',
|
||||
],
|
||||
checkoutOptions: $this->invoiceCheckoutOptions,
|
||||
);
|
||||
}
|
||||
|
||||
/** @group createInvoice */
|
||||
public function testItCanCreateAnInvoiceAndSetCheckoutOptions(): void
|
||||
{
|
||||
$this->assertInvoiceGettersAreSet($this->resultInvoice);
|
||||
}
|
||||
|
||||
/** @group getInvoice */
|
||||
public function testItCanGetAnInvoiceWithCheckoutOptions(): void
|
||||
{
|
||||
$invoice = $this->invoiceClient->getInvoice(
|
||||
storeId: $this->storeId,
|
||||
invoiceId: $this->resultInvoice->getId()
|
||||
);
|
||||
|
||||
$this->assertInvoiceGettersAreSet($invoice);
|
||||
}
|
||||
|
||||
private function assertInvoiceGettersAreSet(ResultInvoice $invoice): void
|
||||
{
|
||||
$this->assertInstanceOf(ResultInvoice::class, $invoice);
|
||||
$this->assertIsString($invoice->getId());
|
||||
$this->assertIsString($invoice->getStoreId());
|
||||
$this->assertIsString($invoice->getCurrency());
|
||||
$this->assertIsString($invoice->getType());
|
||||
$this->assertIsString($invoice->getCheckoutLink());
|
||||
$this->assertIsInt($invoice->getCreatedTime());
|
||||
$this->assertIsInt($invoice->getExpirationTime());
|
||||
$this->assertIsInt($invoice->getMonitoringExpiration());
|
||||
$this->assertisString($invoice->getAdditionalStatus());
|
||||
$this->assertIsString($invoice->getStatus());
|
||||
$this->assertIsArray($invoice->getMetaData());
|
||||
|
||||
// Checkout Options Assertions
|
||||
$this->assertInstanceOf(InvoiceCheckoutOptions::class, $invoice->getCheckoutOptions());
|
||||
$this->assertIsArray($invoice->getCheckoutOptions()->getPaymentMethods());
|
||||
|
||||
// Assert that RedirectURL is either null or string
|
||||
if ($invoice->getCheckoutOptions()->getRedirectURL() !== null) {
|
||||
$this->assertIsString($invoice->getCheckoutOptions()->getRedirectURL());
|
||||
} else {
|
||||
$this->assertNull($invoice->getCheckoutOptions()->getRedirectURL());
|
||||
}
|
||||
|
||||
$this->assertIsInt($invoice->getCheckoutOptions()->getExpirationMinutes());
|
||||
$this->assertIsInt($invoice->getCheckoutOptions()->getMonitoringMinutes());
|
||||
$this->assertIsFloat($invoice->getCheckoutOptions()->getPaymentTolerance());
|
||||
$this->assertIsBool($invoice->getCheckoutOptions()->isRedirectAutomatically());
|
||||
|
||||
// Assert that DefaultLanguage is either null or bool
|
||||
if ($invoice->getCheckoutOptions()->getDefaultLanguage() !== null) {
|
||||
$this->assertIsString($invoice->getCheckoutOptions()->getDefaultLanguage());
|
||||
} else {
|
||||
$this->assertNull($invoice->getCheckoutOptions()->getDefaultLanguage());
|
||||
}
|
||||
}
|
||||
|
||||
public function testItCanGetInvoicePaymentMethodsAndGetters(): void
|
||||
{
|
||||
$paymentMethods = $this->invoiceClient->getPaymentMethods(
|
||||
storeId: $this->storeId,
|
||||
invoiceId: $this->resultInvoice->getId()
|
||||
);
|
||||
|
||||
$this->assertIsArray($paymentMethods);
|
||||
|
||||
foreach ($paymentMethods as $paymentMethod) {
|
||||
$this->assertInstanceOf(InvoicePaymentMethod::class, $paymentMethod);
|
||||
$this->assertIsArray($paymentMethod->getPayments());
|
||||
$this->assertIsString($paymentMethod->getPaymentMethod());
|
||||
$this->assertIsString($paymentMethod->getDestination());
|
||||
$this->assertIsString($paymentMethod->getRate());
|
||||
$this->assertIsString($paymentMethod->getPaymentMethodPaid());
|
||||
$this->assertIsString($paymentMethod->getTotalPaid());
|
||||
$this->assertIsString($paymentMethod->getDue());
|
||||
$this->assertIsString($paymentMethod->getAmount());
|
||||
$this->assertIsString($paymentMethod->getNetworkFee());
|
||||
$this->assertIsString($paymentMethod->getCryptoCode());
|
||||
}
|
||||
}
|
||||
|
||||
public function testItCanUpdateAnInvoice(): void
|
||||
{
|
||||
$invoice = $this->invoiceClient->updateInvoice(
|
||||
storeId: $this->storeId,
|
||||
invoiceId: $this->resultInvoice->getId(),
|
||||
metaData: [
|
||||
'user_id' => '987654321',
|
||||
],
|
||||
);
|
||||
|
||||
$this->assertIsArray($invoice->getMetaData());
|
||||
$this->assertEquals('987654321', $invoice->getMetaData()['user_id']);
|
||||
|
||||
$this->assertInvoiceGettersAreSet($invoice);
|
||||
}
|
||||
|
||||
public function testItCanMarkInvoiceStatus(): void
|
||||
{
|
||||
$invoice = $this->invoiceClient->markInvoiceStatus(
|
||||
storeId: $this->storeId,
|
||||
invoiceId: $this->resultInvoice->getId(),
|
||||
markAs: 'Invalid'
|
||||
);
|
||||
|
||||
$this->assertInvoiceGettersAreSet($invoice);
|
||||
|
||||
$this->assertEquals('Invalid', $invoice->getStatus());
|
||||
|
||||
$invoice = $this->invoiceClient->markInvoiceStatus(
|
||||
storeId: $this->storeId,
|
||||
invoiceId: $this->resultInvoice->getId(),
|
||||
markAs: 'Settled'
|
||||
);
|
||||
|
||||
$this->assertEquals('Settled', $invoice->getStatus());
|
||||
}
|
||||
|
||||
public function testItCanArchiveAndUnarchiveAnInvoice(): void
|
||||
{
|
||||
$archiveInvoice = $this->invoiceClient->archiveInvoice(
|
||||
storeId: $this->storeId,
|
||||
invoiceId: $this->resultInvoice->getId()
|
||||
);
|
||||
|
||||
$this->assertTrue($archiveInvoice);
|
||||
|
||||
// Get the invoice again as a new object with hydrated properties.
|
||||
$invoice = $this->invoiceClient->getInvoice(
|
||||
storeId: $this->storeId,
|
||||
invoiceId: $this->resultInvoice->getId()
|
||||
);
|
||||
|
||||
$this->assertTrue($invoice->isArchived());
|
||||
|
||||
$unarchiveInvoice = $this->invoiceClient->unarchiveInvoice(
|
||||
storeId: $this->storeId,
|
||||
invoiceId: $this->resultInvoice->getId()
|
||||
);
|
||||
|
||||
$this->assertTrue($unarchiveInvoice);
|
||||
|
||||
// Get the invoice again as a new object with hydrated properties.
|
||||
$invoice = $this->invoiceClient->getInvoice(
|
||||
storeId: $this->storeId,
|
||||
invoiceId: $this->resultInvoice->getId()
|
||||
);
|
||||
|
||||
$this->assertFalse($invoice->isArchived());
|
||||
}
|
||||
|
||||
public function testItCanActivatePaymentMethod(): void
|
||||
{
|
||||
$activatePaymentMethod = $this->invoiceClient->activatePaymentMethod(
|
||||
storeId: $this->storeId,
|
||||
invoiceId: $this->resultInvoice->getId(),
|
||||
paymentMethod: 'BTC-LightningNetwork'
|
||||
);
|
||||
|
||||
$this->assertTrue($activatePaymentMethod);
|
||||
}
|
||||
|
||||
public function tearDown(): void
|
||||
{
|
||||
$achivedInvoice = $this->invoiceClient->archiveInvoice(
|
||||
storeId: $this->storeId,
|
||||
invoiceId: $this->resultInvoice->getId()
|
||||
);
|
||||
|
||||
$this->assertIsBool($achivedInvoice);
|
||||
}
|
||||
}
|
||||
197
tests/LightningStoreTest.php
Normal file
197
tests/LightningStoreTest.php
Normal file
@ -0,0 +1,197 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Tests;
|
||||
|
||||
use BTCPayServer\Client\LightningStore;
|
||||
use BTCPayServer\Result\LightningChannel;
|
||||
use BTCPayServer\Result\LightningChannelList;
|
||||
use BTCPayServer\Result\LightningInvoice;
|
||||
use BTCPayServer\Result\LightningPayment;
|
||||
use BTCPayServer\Util\PreciseNumber;
|
||||
use Exception;
|
||||
|
||||
final class LightningStoreTest extends BaseTest
|
||||
{
|
||||
protected LightningStore $lightningStoreClient;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->lightningStoreClient = new LightningStore($this->host, $this->apiKey);
|
||||
}
|
||||
|
||||
/** @group createLightningInvoice */
|
||||
public function testItCanCreateALightningInvoiceAndReturnsLightningInvoiceObject(): void
|
||||
{
|
||||
$lightningInvoice = $this->lightningStoreClient->createLightningInvoice(
|
||||
cryptoCode: 'BTC',
|
||||
storeId: $this->storeId,
|
||||
amount: '100000', // milisats
|
||||
expiry: 111111,
|
||||
description: 'Test invoice description',
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(LightningInvoice::class, $lightningInvoice);
|
||||
|
||||
$this->lightningInvoice = $lightningInvoice;
|
||||
|
||||
$this->assertIsString($lightningInvoice->getId());
|
||||
$this->assertIsString($lightningInvoice->getStatus());
|
||||
$this->assertIsString($lightningInvoice->getBolt11());
|
||||
|
||||
// If the lightning invoice is paid, assert the paid at is an int
|
||||
if ($lightningInvoice->getPaidAt()) {
|
||||
$this->assertIsInt($lightningInvoice->getPaidAt());
|
||||
}
|
||||
|
||||
$this->assertIsInt($lightningInvoice->getExpiresAt());
|
||||
$this->assertInstanceOf(PreciseNumber::class, $lightningInvoice->getAmount());
|
||||
|
||||
// If the lightning invoice is paid, assert the amount received is a PreciseNumber
|
||||
if ($lightningInvoice->getAmountReceived()) {
|
||||
$this->assertInstanceOf(PreciseNumber::class, $lightningInvoice->getAmountReceived());
|
||||
}
|
||||
}
|
||||
|
||||
/** @group payLightningInvoice */
|
||||
public function testItReceivesLightningPaymentObjectAfterPayingLightningInvoiceWithAllGetters(): void
|
||||
{
|
||||
$this->markTestSkipped('Requires a new invoice on each test run');
|
||||
$bolt11 = '';
|
||||
|
||||
$lightningPayment = $this->lightningStoreClient->payLightningInvoice(
|
||||
cryptoCode: 'BTC',
|
||||
storeId: $this->storeId,
|
||||
BOLT11: $bolt11,
|
||||
maxFeePercent: 0.1,
|
||||
maxFeeFlat: 100,
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(LightningPayment::class, $lightningPayment);
|
||||
|
||||
// There is a bug in Greenfield API that is returning null values on everything except total and fee amounts.
|
||||
// Uncomment these lines when the bug is fixed.
|
||||
// https://github.com/btcpayserver/btcpayserver/issues/4229
|
||||
|
||||
// $this->assertIsString($lightningPayment->getId());
|
||||
// $this->assertIsString($lightningPayment->getStatus());
|
||||
// $this->assertIsString($lightningPayment->getBolt11());
|
||||
// $this->assertIsString($lightningPayment->getPaymentHash());
|
||||
// $this->assertIsString($lightningPayment->getPreimage());
|
||||
// $this->assertIsInt($lightningPayment->getCreatedAt());
|
||||
// $this->assertInstanceOf(PreciseNumber::class, $lightningPayment->getTotalAmount());
|
||||
// $this->assertInstanceOf(PreciseNumber::class, $lightningPayment->getFeeAmount());
|
||||
}
|
||||
|
||||
/** @group connectToLightningNode */
|
||||
public function testItCanConnectToALightningNodeAndReturnsLightningNodeConnectionObject(): void
|
||||
{
|
||||
$this->markTestSkipped('This test is skipped because I always get 503.');
|
||||
try {
|
||||
$lightningNodeConnection = $this->lightningStoreClient->connectToLightningNode(
|
||||
cryptoCode: 'BTC',
|
||||
storeId: $this->storeId,
|
||||
nodeURI: $this->nodeUri,
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(LightningNodeConnection::class, $lightningNodeConnection);
|
||||
} catch (Exception $e) {
|
||||
die($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/** @group getNodeInformation */
|
||||
public function testItCanGetNodeInformationAndReturnsLightningNodeInformationObject(): void
|
||||
{
|
||||
$lightningNodeInformation = $this->lightningStoreClient->getNodeInformation(
|
||||
cryptoCode: 'BTC',
|
||||
storeId: $this->storeId,
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(\BTCPayServer\Result\LightningNode::class, $lightningNodeInformation);
|
||||
|
||||
$this->assertIsArray($lightningNodeInformation->getNodeURIs());
|
||||
$this->assertIsInt($lightningNodeInformation->getBlockHeight());
|
||||
$this->assertIsString($lightningNodeInformation->getAlias());
|
||||
$this->assertIsString($lightningNodeInformation->getColor());
|
||||
$this->assertIsString($lightningNodeInformation->getVersion());
|
||||
$this->assertIsInt($lightningNodeInformation->getPeersCount());
|
||||
$this->assertIsInt($lightningNodeInformation->getPendingChannelsCount());
|
||||
$this->assertIsInt($lightningNodeInformation->getActiveChannelsCount());
|
||||
$this->assertIsInt($lightningNodeInformation->getInactiveChannelsCount());
|
||||
}
|
||||
|
||||
/** @group getChannels */
|
||||
public function testItCanGetChannelsAndReturnsLightningChannelListObject(): void
|
||||
{
|
||||
$lightningChannels = $this->lightningStoreClient->getChannels(
|
||||
cryptoCode: 'BTC',
|
||||
storeId: $this->storeId,
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(LightningChannelList::class, $lightningChannels);
|
||||
|
||||
$this->assertIsArray($lightningChannels->all());
|
||||
|
||||
foreach ($lightningChannels->all() as $channel) {
|
||||
$this->assertInstanceOf(LightningChannel::class, $channel);
|
||||
$this->assertIsString($channel->getRemoteNode());
|
||||
$this->assertIsString($channel->getChannelPoint());
|
||||
$this->assertIsString($channel->getCapacity());
|
||||
$this->assertIsString($channel->getLocalBalance());
|
||||
$this->assertIsBool($channel->isActive());
|
||||
$this->assertIsBool($channel->isPublic());
|
||||
}
|
||||
}
|
||||
|
||||
/** @group getDepositAddress */
|
||||
public function testItCanGetANewDepositAddress(): void
|
||||
{
|
||||
$depositAddress = $this->lightningStoreClient->getDepositAddress(
|
||||
cryptoCode: 'BTC',
|
||||
storeId: $this->storeId,
|
||||
);
|
||||
|
||||
$this->assertIsString($depositAddress);
|
||||
}
|
||||
|
||||
/** @group getLightningInvoice */
|
||||
public function testItCanGetAnInvoiceAndReturnsLightningInvoiceObject(): void
|
||||
{
|
||||
$getLightningInvoice = $this->lightningStoreClient->createLightningInvoice(
|
||||
cryptoCode: 'BTC',
|
||||
storeId: $this->storeId,
|
||||
amount: '100000', // milisats
|
||||
expiry: 111111,
|
||||
description: 'Test invoice description',
|
||||
);
|
||||
|
||||
$lightningInvoice = $this->lightningStoreClient->getLightningInvoice(
|
||||
'BTC',
|
||||
$this->storeId,
|
||||
$getLightningInvoice->getId(),
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(LightningInvoice::class, $lightningInvoice);
|
||||
|
||||
$this->assertIsString($lightningInvoice->getId());
|
||||
$this->assertIsString($lightningInvoice->getStatus());
|
||||
$this->assertIsString($lightningInvoice->getBolt11());
|
||||
|
||||
// If the invoice get Paid at is not null, assert it's int
|
||||
if ($lightningInvoice->getPaidAt() !== null) {
|
||||
$this->assertIsInt($lightningInvoice->getPaidAt());
|
||||
}
|
||||
|
||||
$this->assertIsInt($lightningInvoice->getExpiresAt());
|
||||
$this->assertInstanceOf(PreciseNumber::class, $lightningInvoice->getAmount());
|
||||
|
||||
// If the invoice get Paid amount is not null, assert it's PreciseNumber
|
||||
if ($lightningInvoice->getAmountReceived() !== null) {
|
||||
$this->assertInstanceOf(PreciseNumber::class, $lightningInvoice->getAmountReceived());
|
||||
}
|
||||
}
|
||||
}
|
||||
68
tests/MiscellaneousTest.php
Normal file
68
tests/MiscellaneousTest.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Tests;
|
||||
|
||||
use BTCPayServer\Client\Invoice;
|
||||
use BTCPayServer\Client\Miscellaneous;
|
||||
use BTCPayServer\Result\InvoiceCheckoutHtml;
|
||||
use BTCPayServer\Result\LanguageCode;
|
||||
use BTCPayServer\Result\LanguageCodeList;
|
||||
use BTCPayServer\Result\PermissionMetadata;
|
||||
use BTCPayServer\Result\PermissionMetadataList;
|
||||
use BTCPayServer\Util\PreciseNumber;
|
||||
|
||||
final class MiscellaneousTest extends BaseTest
|
||||
{
|
||||
private Miscellaneous $miscellaneousClient;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->miscellaneousClient = new Miscellaneous($this->host, $this->apiKey);
|
||||
}
|
||||
|
||||
public function testItCanGetPermissionMetadata(): void
|
||||
{
|
||||
$result = $this->miscellaneousClient->getPermissionMetadata();
|
||||
|
||||
$this->assertInstanceOf(PermissionMetadataList::class, $result);
|
||||
|
||||
foreach ($result->all() as $permissionMetadata) {
|
||||
$this->assertInstanceOf(PermissionMetadata::class, $permissionMetadata);
|
||||
$this->assertIsString($permissionMetadata->getName());
|
||||
$this->assertIsArray($permissionMetadata->getIncluded());
|
||||
}
|
||||
}
|
||||
|
||||
public function testItCanGetLanguageCodes(): void
|
||||
{
|
||||
$result = $this->miscellaneousClient->getLanguageCodes();
|
||||
|
||||
$this->assertInstanceOf(LanguageCodeList::class, $result);
|
||||
|
||||
foreach ($result->all() as $languageCode) {
|
||||
$this->assertInstanceOf(LanguageCode::class, $languageCode);
|
||||
$this->assertIsString($languageCode->getCode());
|
||||
$this->assertIsString($languageCode->getCurrentLanguage());
|
||||
}
|
||||
}
|
||||
|
||||
public function testItCanGetInvoiceCheckout(): void
|
||||
{
|
||||
$invoiceClient = new Invoice($this->host, $this->apiKey);
|
||||
|
||||
$invoice = $invoiceClient->createInvoice(
|
||||
storeId: $this->storeId,
|
||||
currency: 'SATS',
|
||||
amount: PreciseNumber::parseString('1000'),
|
||||
);
|
||||
|
||||
$result = $this->miscellaneousClient->getInvoiceCheckout($invoice->getId(), null);
|
||||
|
||||
$this->assertInstanceOf(InvoiceCheckoutHtml::class, $result);
|
||||
$this->assertStringContainsString('<!DOCTYPE html>', $result->getHtml());
|
||||
}
|
||||
}
|
||||
83
tests/NotificationTest.php
Normal file
83
tests/NotificationTest.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Tests;
|
||||
|
||||
use BTCPayServer\Client\Notification;
|
||||
use BTCPayServer\Result\NotificationList;
|
||||
|
||||
final class NotificationTest extends BaseTest
|
||||
{
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->notificationClient = new Notification($this->host, $this->apiKey);
|
||||
}
|
||||
|
||||
/** @group getNotifications */
|
||||
public function testItCanGetNotifications(): void
|
||||
{
|
||||
$notifications = $this->notificationClient->getNotifications();
|
||||
|
||||
$this->assertInstanceOf(NotificationList::class, $notifications);
|
||||
foreach ($notifications->all() as $notification) {
|
||||
$this->assertIsString($notification->getId());
|
||||
$this->assertIsString($notification->getBody());
|
||||
$this->assertIsString($notification->getLink());
|
||||
$this->assertIsInt($notification->getCreatedTime());
|
||||
$this->assertIsBool($notification->isSeen());
|
||||
}
|
||||
}
|
||||
|
||||
/** @group getNotification */
|
||||
public function testItCanGetNotification(): void
|
||||
{
|
||||
$notifications = $this->notificationClient->getNotifications();
|
||||
|
||||
if (empty($notifications->all())) {
|
||||
$this->markTestSkipped('No notifications found');
|
||||
}
|
||||
|
||||
$notification = $this->notificationClient->getNotification($notifications->all()[0]->getId());
|
||||
|
||||
$this->assertIsString($notification->getId());
|
||||
$this->assertIsString($notification->getBody());
|
||||
$this->assertIsString($notification->getLink());
|
||||
$this->assertIsInt($notification->getCreatedTime());
|
||||
$this->assertIsBool($notification->isSeen());
|
||||
}
|
||||
|
||||
/** @group updateNotification */
|
||||
public function testItCanUpdateNotification(): void
|
||||
{
|
||||
$notifications = $this->notificationClient->getNotifications();
|
||||
|
||||
if (empty($notifications->all())) {
|
||||
$this->markTestSkipped('No notifications found');
|
||||
}
|
||||
|
||||
$notification = $this->notificationClient->updateNotification($notifications->all()[0]->getId(), true);
|
||||
|
||||
$this->assertIsString($notification->getId());
|
||||
$this->assertIsString($notification->getBody());
|
||||
$this->assertIsString($notification->getLink());
|
||||
$this->assertIsInt($notification->getCreatedTime());
|
||||
$this->assertTrue($notification->isSeen());
|
||||
}
|
||||
|
||||
/** @group removeNotification */
|
||||
public function testItCanRemoveNotification(): void
|
||||
{
|
||||
$notifications = $this->notificationClient->getNotifications();
|
||||
|
||||
if (empty($notifications->all())) {
|
||||
$this->markTestSkipped('No notifications found');
|
||||
}
|
||||
|
||||
$notification = $this->notificationClient->removeNotification($notifications->all()[0]->getId());
|
||||
|
||||
$this->assertTrue($notification);
|
||||
}
|
||||
}
|
||||
190
tests/PullPaymentTest.php
Normal file
190
tests/PullPaymentTest.php
Normal file
@ -0,0 +1,190 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Tests;
|
||||
|
||||
use BTCPayServer\Client\PullPayment;
|
||||
use BTCPayServer\Result\PullPayment as ResultPullPayment;
|
||||
use BTCPayServer\Result\PullPaymentList;
|
||||
use BTCPayServer\Result\PullPaymentPayout;
|
||||
use BTCPayServer\Util\PreciseNumber;
|
||||
|
||||
final class PullPaymentTest extends BaseTest
|
||||
{
|
||||
public PullPayment $pullPaymentClient;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->pullPaymentClient = new PullPayment($this->host, $this->apiKey);
|
||||
}
|
||||
|
||||
/** @group createPullPayment */
|
||||
public function testItCanCreatePullPayment(): void
|
||||
{
|
||||
$pullPayment = $this->pullPaymentClient->createPullPayment(
|
||||
storeId: $this->storeId,
|
||||
name: 'Test Pull Payment',
|
||||
amount: PreciseNumber::parseString('100'),
|
||||
currency: 'SATS',
|
||||
period: 30,
|
||||
BOLT11Expiration: 30,
|
||||
autoApproveClaims: false,
|
||||
startsAt: time(),
|
||||
expiresAt: time() + 30,
|
||||
paymentMethods: ['BTC-LightningNetwork']
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(ResultPullPayment::class, $pullPayment);
|
||||
$this->assertNotEmpty($pullPayment->getId());
|
||||
$this->assertEquals('Test Pull Payment', $pullPayment->getName());
|
||||
$this->assertEquals('SATS', $pullPayment->getCurrency());
|
||||
$this->assertEquals('100', $pullPayment->getAmount());
|
||||
$this->assertEquals(30, $pullPayment->getPeriod());
|
||||
$this->assertEquals(30, $pullPayment->getBOLT11Expiration());
|
||||
$this->assertFalse($pullPayment->isArchived());
|
||||
$this->assertNotEmpty($pullPayment->getViewLink());
|
||||
}
|
||||
|
||||
/** @group getStorePullPayments */
|
||||
public function testGetStorePullPayments(): void
|
||||
{
|
||||
$pullPayments = $this->pullPaymentClient->getStorePullPayments($this->storeId, false);
|
||||
|
||||
$this->assertInstanceOf(PullPaymentList::class, $pullPayments);
|
||||
$this->assertNotEmpty($pullPayments->all());
|
||||
$this->assertIsArray($pullPayments->all());
|
||||
|
||||
foreach ($pullPayments->all() as $pullPayment) {
|
||||
$this->assertInstanceOf(ResultPullPayment::class, $pullPayment);
|
||||
$this->assertIsString($pullPayment->getId());
|
||||
$this->assertIsString($pullPayment->getName());
|
||||
$this->assertIsString($pullPayment->getCurrency());
|
||||
$this->assertInstanceOf(PreciseNumber::class, $pullPayment->getAmount());
|
||||
$this->assertIsInt($pullPayment->getPeriod());
|
||||
$this->assertIsInt($pullPayment->getBOLT11Expiration());
|
||||
$this->assertIsBool($pullPayment->isArchived());
|
||||
$this->assertIsString($pullPayment->getViewLink());
|
||||
}
|
||||
}
|
||||
|
||||
/** @group getPullPayment */
|
||||
public function testGetPullPayment(): void
|
||||
{
|
||||
$pullPayments = $this->pullPaymentClient->getStorePullPayments($this->storeId, false);
|
||||
$pullPayment = $this->pullPaymentClient->getPullPayment($pullPayments->all()[0]->getId());
|
||||
|
||||
$this->assertInstanceOf(ResultPullPayment::class, $pullPayment);
|
||||
$this->assertIsString($pullPayment->getId());
|
||||
$this->assertIsString($pullPayment->getName());
|
||||
$this->assertIsString($pullPayment->getCurrency());
|
||||
$this->assertInstanceOf(PreciseNumber::class, $pullPayment->getAmount());
|
||||
$this->assertIsInt($pullPayment->getPeriod());
|
||||
$this->assertIsInt($pullPayment->getBOLT11Expiration());
|
||||
$this->assertIsBool($pullPayment->isArchived());
|
||||
$this->assertIsString($pullPayment->getViewLink());
|
||||
}
|
||||
|
||||
/** @group archivePullPayment */
|
||||
public function testArchivePullPayment(): void
|
||||
{
|
||||
// Grab the first unarchived pull payment and archive it.
|
||||
$pullPayment = $this->pullPaymentClient->getStorePullPayments($this->storeId, false)->all()[0];
|
||||
$this->pullPaymentClient->archivePullPayment($this->storeId, $pullPayment->getId());
|
||||
|
||||
// Get All Pull Payments, including archived, as an array.
|
||||
$allPullPayments = $this->pullPaymentClient->getStorePullPayments($this->storeId, true)->all();
|
||||
|
||||
// Find the the archived pull payment by id.
|
||||
$archivedPullPayment = array_filter($allPullPayments, function ($pullPayment) {
|
||||
return $pullPayment->getId() === $pullPayment->getId();
|
||||
});
|
||||
|
||||
// Assert that the pull payment is archived.
|
||||
$this->assertTrue($archivedPullPayment[0]->isArchived());
|
||||
}
|
||||
|
||||
/** @group payouts */
|
||||
public function testItCanGetAllPayoutMethods(): void
|
||||
{
|
||||
// Create a pull payment.
|
||||
$pullPayment = $this->pullPaymentClient->createPullPayment(
|
||||
storeId: $this->storeId,
|
||||
name: 'Test Pull Payment',
|
||||
amount: PreciseNumber::parseFloat(0.00001),
|
||||
currency: 'BTC',
|
||||
period: 1,
|
||||
BOLT11Expiration: 1,
|
||||
autoApproveClaims: false,
|
||||
startsAt: time(),
|
||||
expiresAt: time() + 100,
|
||||
paymentMethods: ['BTC-LightningNetwork']
|
||||
);
|
||||
|
||||
$lightningClient = new \BTCPayServer\Client\LightningInternalNode($this->host, $this->apiKey);
|
||||
$lightningInvoice = $lightningClient->createLightningInvoice(
|
||||
'BTC',
|
||||
'1000000', // milisats
|
||||
111111,
|
||||
'Test invoice description',
|
||||
);
|
||||
|
||||
$bolt11 = $lightningInvoice["BOLT11"];
|
||||
|
||||
// Create a payout associated with the pull payment.
|
||||
$payout = $this->pullPaymentClient->createPayout(
|
||||
pullPaymentId: $pullPayment->getId(),
|
||||
destination: $bolt11,
|
||||
amount: PreciseNumber::parseFloat(0.00001),
|
||||
paymentMethod: 'BTC-LightningNetwork'
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(PullPaymentPayout::class, $payout);
|
||||
$this->assertIsString($payout->getId());
|
||||
$this->assertIsInt($payout->getRevision());
|
||||
$this->assertIsString($payout->getPullPaymentId());
|
||||
$this->assertIsInt($payout->getDate());
|
||||
$this->assertIsString($payout->getDestination());
|
||||
$this->assertInstanceOf(PreciseNumber::class, $payout->getAmount());
|
||||
$this->assertIsString($payout->getPaymentMethod());
|
||||
$this->assertIsString($payout->getCryptoCode());
|
||||
$this->assertIsString($payout->getState());
|
||||
$this->assertEquals('AwaitingApproval', $payout->getState());
|
||||
|
||||
// If PaymentMethodAmount is not null, assert it's an int.
|
||||
if ($payout->getPaymentMethodAmount() !== null) {
|
||||
$this->assertIsInt($payout->getPaymentMethodAmount());
|
||||
}
|
||||
|
||||
// Test that we can get the payout.
|
||||
$getPayout = $this->pullPaymentClient->getPayout($pullPayment->getId(), $payout->getId());
|
||||
|
||||
// Assert that the payout is the same as the one we created.
|
||||
$this->assertEquals($payout, $getPayout);
|
||||
|
||||
// Approve the payout.
|
||||
$approve = $this->pullPaymentClient->approvePayout(
|
||||
storeId: $this->storeId,
|
||||
payoutId: $payout->getId(),
|
||||
revision: $payout->getRevision(),
|
||||
rateRule: null,
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(PullPaymentPayout::class, $approve);
|
||||
$this->assertEquals('AwaitingPayment', $approve->getState());
|
||||
|
||||
// Mark the Payout as Paid.
|
||||
$paid = $this->pullPaymentClient->markPayoutAsPaid(
|
||||
storeId: $this->storeId,
|
||||
payoutId: $payout->getId(),
|
||||
);
|
||||
|
||||
$this->assertTrue($paid);
|
||||
|
||||
// Archive the new pull payment.
|
||||
$archive = $this->pullPaymentClient->archivePullPayment($this->storeId, $pullPayment->getId());
|
||||
$this->assertTrue($archive);
|
||||
}
|
||||
}
|
||||
49
tests/ServerTest.php
Normal file
49
tests/ServerTest.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Tests;
|
||||
|
||||
use BTCPayServer\Client\Server;
|
||||
use BTCPayServer\Result\ServerInfo;
|
||||
use BTCPayServer\Result\ServerSyncStatusList;
|
||||
use BTCPayServer\Result\ServerSyncStatusNodeInformation;
|
||||
use BTCPayServer\Util\PreciseNumber;
|
||||
|
||||
final class ServerTest extends BaseTest
|
||||
{
|
||||
public Server $serverClient;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->serverClient = new Server($this->host, $this->apiKey);
|
||||
}
|
||||
|
||||
/** @group getServerInfo */
|
||||
public function testItGetsServerInfoAndAllGetters(): void
|
||||
{
|
||||
$serverInfo = $this->serverClient->getInfo();
|
||||
|
||||
$this->assertInstanceOf(ServerInfo::class, $serverInfo);
|
||||
$this->assertIsString($serverInfo->getVersion());
|
||||
$this->assertIsString($serverInfo->getOnionUrl());
|
||||
$this->assertIsBool($serverInfo->isFullySynced());
|
||||
$this->assertIsArray($serverInfo->getSupportedPaymentMethods());
|
||||
|
||||
$this->assertInstanceOf(ServerSyncStatusList::class, $serverInfo->getSyncStatus());
|
||||
|
||||
foreach ($serverInfo->getSyncStatus()->all() as $serverSyncStatus) {
|
||||
$this->assertIsInt($serverSyncStatus->getChainHeight());
|
||||
$this->assertIsInt($serverSyncStatus->getSyncHeight());
|
||||
$this->assertIsString($serverSyncStatus->getCryptoCode());
|
||||
$this->assertIsBool($serverSyncStatus->isAvailable());
|
||||
|
||||
$this->assertInstanceOf(ServerSyncStatusNodeInformation::class, $serverSyncStatus->getNodeInformation());
|
||||
$this->assertIsInt($serverSyncStatus->getNodeInformation()->getHeaders());
|
||||
$this->assertIsInt($serverSyncStatus->getNodeInformation()->getBlocks());
|
||||
$this->assertInstanceOf(PreciseNumber::class, $serverSyncStatus->getNodeInformation()->getVerificationProgress());
|
||||
}
|
||||
}
|
||||
}
|
||||
114
tests/StoreEmailTest.php
Normal file
114
tests/StoreEmailTest.php
Normal file
@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Tests;
|
||||
|
||||
use BTCPayServer\Client\Store;
|
||||
use BTCPayServer\Client\StoreEmail;
|
||||
use BTCPayServer\Result\Store as ResultStore;
|
||||
use BTCPayServer\Result\StoreEmailSettings;
|
||||
|
||||
final class StoreEmailTest extends BaseTest
|
||||
{
|
||||
public Store $storeClient;
|
||||
public ResultStore $store;
|
||||
public StoreEmail $storeEmailClient;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->storeClient = new Store($this->host, $this->apiKey);
|
||||
$this->store = $this->storeClient->createStore(
|
||||
name: 'Test Store',
|
||||
website: 'https://example.com',
|
||||
defaultCurrency: 'USD',
|
||||
invoiceExpiration: 900,
|
||||
displayExpirationTimer: 300,
|
||||
monitoringExpiration: 3600,
|
||||
speedPolicy: 'MediumSpeed',
|
||||
lightningDescriptionTemplate: null,
|
||||
paymentTolerance: 0,
|
||||
anyoneCanCreateInvoice: false,
|
||||
requiresRefundEmail: false,
|
||||
checkoutType: 'V1',
|
||||
receipt: null,
|
||||
lightningAmountInSatoshi: false,
|
||||
lightningPrivateRouteHints: false,
|
||||
onChainWithLnInvoiceFallback: false,
|
||||
redirectAutomatically: false,
|
||||
showRecommendedFee: true,
|
||||
recommendedFeeBlockTarget: 1,
|
||||
defaultLang: 'en',
|
||||
customLogo: 'https://test.com',
|
||||
customCSS: 'auto: 100px;',
|
||||
htmlTitle: 'the best store ever',
|
||||
networkFeeMode: 'MultiplePaymentsOnly',
|
||||
payJoinEnabled: false,
|
||||
lazyPaymentMethods: false,
|
||||
defaultPaymentMethod: 'BTC'
|
||||
);
|
||||
|
||||
$this->storeEmailClient = new StoreEmail($this->host, $this->apiKey);
|
||||
}
|
||||
|
||||
/** @group getSettings */
|
||||
public function testItCanGetEmailSettings(): void
|
||||
{
|
||||
$storeEmailSettings = $this->storeEmailClient->getSettings($this->store->getId());
|
||||
$this->assertEmailSettingsGettersAreSet($storeEmailSettings);
|
||||
}
|
||||
|
||||
/** @group updateSettings */
|
||||
public function testItCanUpdateEmailSettings(): void
|
||||
{
|
||||
$storeEmailSettings = $this->storeEmailClient->updateSettings(
|
||||
$this->store->getId(),
|
||||
server: 'smtp.example.com',
|
||||
port: 587,
|
||||
username: 'tester',
|
||||
password: 'password',
|
||||
fromEmail: 'tester@btcpayserver.org',
|
||||
fromName: 'Tester',
|
||||
disableCertificateCheck: false,
|
||||
);
|
||||
|
||||
$this->assertEmailSettingsGettersAreSet($storeEmailSettings);
|
||||
}
|
||||
|
||||
/** @group sendMail */
|
||||
public function testItCanSendMail(): void
|
||||
{
|
||||
$email = $this->storeEmailClient->sendMail(
|
||||
storeId: $this->store->getId(),
|
||||
email: 'testing@btcpayserver.org',
|
||||
subject: 'Test Email',
|
||||
body: 'This is a test email',
|
||||
);
|
||||
|
||||
$this->assertTrue($email);
|
||||
}
|
||||
|
||||
private function assertEmailSettingsGettersAreSet($storeEmailSettings): void
|
||||
{
|
||||
$this->assertInstanceOf(StoreEmailSettings::class, $storeEmailSettings);
|
||||
if ($storeEmailSettings->getServer()) {
|
||||
$this->assertIsString($storeEmailSettings->getServer());
|
||||
}
|
||||
if ($storeEmailSettings->getPort()) {
|
||||
$this->assertIsInt($storeEmailSettings->getPort());
|
||||
}
|
||||
if ($storeEmailSettings->getUsername()) {
|
||||
$this->assertIsString($storeEmailSettings->getUsername());
|
||||
}
|
||||
if ($storeEmailSettings->getPassword()) {
|
||||
$this->assertIsString($storeEmailSettings->getPassword());
|
||||
}
|
||||
if ($storeEmailSettings->getFromEmail()) {
|
||||
$this->assertIsString($storeEmailSettings->getFromEmail());
|
||||
}
|
||||
// @TODO: Re-enable when bug is fixed - https://github.com/btcpayserver/btcpayserver/issues/5139
|
||||
// if ($storeEmailSettings->getFromName()) $this->assertIsString($storeEmailSettings->getFromName());
|
||||
}
|
||||
}
|
||||
198
tests/StoreOnChainWalletTest.php
Normal file
198
tests/StoreOnChainWalletTest.php
Normal file
@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Tests;
|
||||
|
||||
use BTCPayServer\Client\Store;
|
||||
use BTCPayServer\Client\StoreOnChainWallet;
|
||||
use BTCPayServer\Result\StoreOnChainWallet as ResultStoreOnChainWallet;
|
||||
use BTCPayServer\Result\StoreOnChainWalletAddress;
|
||||
use BTCPayServer\Result\StoreOnChainWalletFeeRate;
|
||||
use BTCPayServer\Result\StoreOnChainWalletTransaction;
|
||||
use BTCPayServer\Result\StoreOnChainWalletTransactionList;
|
||||
use BTCPayServer\Result\StoreOnChainWalletUtxo;
|
||||
use BTCPayServer\Result\StoreOnChainWalletUtxoList;
|
||||
use BTCPayServer\Util\PreciseNumber;
|
||||
|
||||
final class StoreOnChainWalletTest extends BaseTest
|
||||
{
|
||||
public Store $storeClient;
|
||||
public StoreOnChainWallet $storeOnChainWalletClient;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->storeClient = new Store($this->host, $this->apiKey);
|
||||
$this->storeOnChainWalletClient = new StoreOnChainWallet($this->host, $this->apiKey);
|
||||
}
|
||||
|
||||
/** @group getStoreOnChainWalletOverview */
|
||||
public function testItCanGetStoreOnChainWalletOverview(): void
|
||||
{
|
||||
//$this->markTestIncomplete('BTC doesnt have any derivation scheme set');
|
||||
$overview = $this->storeOnChainWalletClient->getStoreOnChainWalletOverview(
|
||||
$this->storeId,
|
||||
'BTC'
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(ResultStoreOnChainWallet::class, $overview);
|
||||
$this->assertInstanceOf(PreciseNumber::class, $overview->getBalance());
|
||||
$this->assertInstanceOf(PreciseNumber::class, $overview->getUnconfirmedBalance());
|
||||
$this->assertInstanceOf(PreciseNumber::class, $overview->getConfirmedBalance());
|
||||
$this->assertIsString($overview->getLabel());
|
||||
}
|
||||
|
||||
/** @group getStoreOnChainWalletFeeRate */
|
||||
public function testItCanGetStoreOnChainWalletFeeRate(): void
|
||||
{
|
||||
$feeRate = $this->storeOnChainWalletClient->getStoreOnChainWalletFeeRate(
|
||||
$this->storeId,
|
||||
'BTC'
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(StoreOnChainWalletFeeRate::class, $feeRate);
|
||||
$this->assertInstanceOf(PreciseNumber::class, $feeRate->getFeeRate());
|
||||
}
|
||||
|
||||
/** @group getStoreOnChainWalletAddress */
|
||||
public function testItCanGetStoreOnChainWalletAddress(): void
|
||||
{
|
||||
$address = $this->storeOnChainWalletClient->getStoreOnChainWalletAddress(
|
||||
$this->storeId,
|
||||
'BTC'
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(StoreOnChainWalletAddress::class, $address);
|
||||
$this->assertIsString($address->getAddress());
|
||||
$this->assertIsString($address->getKeyPath());
|
||||
$this->assertIsString($address->getPaymentLink());
|
||||
}
|
||||
|
||||
/** @group unReserveLastStoreOnChainWalletAddress */
|
||||
public function testItCanunReserveLastStoreOnChainWalletAddress(): void
|
||||
{
|
||||
$address = $this->storeOnChainWalletClient->unReserveLastStoreOnChainWalletAddress(
|
||||
$this->storeId,
|
||||
'BTC'
|
||||
);
|
||||
|
||||
$this->assertIsBool($address);
|
||||
}
|
||||
|
||||
/** @group getStoreOnChainWalletTransactions */
|
||||
public function testItCanGetStoreOnChainWalletTransactions(): void
|
||||
{
|
||||
$transactions = $this->storeOnChainWalletClient->getStoreOnChainWalletTransactions(
|
||||
$this->storeId,
|
||||
'BTC'
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(StoreOnChainWalletTransactionList::class, $transactions);
|
||||
$this->assertIsArray($transactions->all());
|
||||
|
||||
foreach ($transactions->all() as $transaction) {
|
||||
$this->assertInstanceOf(StoreOnChainWalletTransaction::class, $transaction);
|
||||
$this->assertIsString($transaction->getTransactionHash());
|
||||
$this->assertIsString($transaction->getComment());
|
||||
$this->assertIsArray($transaction->getLabels());
|
||||
$this->assertIsInt($transaction->getConfirmations());
|
||||
$this->assertIsInt($transaction->getTimestamp());
|
||||
$this->assertIsString($transaction->getStatus());
|
||||
}
|
||||
}
|
||||
|
||||
/** @group createStoreOnChainWalletTransaction */
|
||||
public function testItCanCreateGetUpdateStoreOnChainWalletTransaction(): void
|
||||
{
|
||||
$destination =
|
||||
[
|
||||
'destination' => 'tb1q2yy5gxpdlsr40xjvy7v6x4gjxr5y8t428nqppa',
|
||||
'amount' => "0.00001",
|
||||
'subtractFromAmount' => true,
|
||||
];
|
||||
|
||||
$transaction = $this->storeOnChainWalletClient->createStoreOnChainWalletTransaction(
|
||||
$this->storeId,
|
||||
'BTC',
|
||||
[$destination],
|
||||
2.0,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(StoreOnChainWalletTransaction::class, $transaction);
|
||||
$this->assertIsString($transaction->getTransactionHash());
|
||||
$this->assertIsString($transaction->getComment());
|
||||
$this->assertIsArray($transaction->getLabels());
|
||||
$this->assertIsInt($transaction->getConfirmations());
|
||||
$this->assertIsInt($transaction->getTimestamp());
|
||||
$this->assertIsString($transaction->getStatus());
|
||||
|
||||
if ($transaction->getBlockHash() !== null) {
|
||||
$this->assertIsString($transaction->getBlockHash());
|
||||
}
|
||||
|
||||
if ($transaction->getBlockHeight() !== null) {
|
||||
$this->assertIsInt($transaction->getBlockHeight());
|
||||
}
|
||||
|
||||
$getTransaction = $this->storeOnChainWalletClient->getStoreOnChainWalletTransaction(
|
||||
$this->storeId,
|
||||
'BTC',
|
||||
$transaction->getTransactionHash(),
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(StoreOnChainWalletTransaction::class, $getTransaction);
|
||||
$this->assertIsString($getTransaction->getTransactionHash());
|
||||
$this->assertIsString($getTransaction->getComment());
|
||||
$this->assertIsArray($getTransaction->getLabels());
|
||||
$this->assertIsInt($getTransaction->getConfirmations());
|
||||
$this->assertIsInt($getTransaction->getTimestamp());
|
||||
$this->assertIsString($getTransaction->getStatus());
|
||||
|
||||
$updatedTransaction = $this->storeOnChainWalletClient->updateStoreOnChainWalletTransaction(
|
||||
$this->storeId,
|
||||
'BTC',
|
||||
$transaction->getTransactionHash(),
|
||||
'test comment',
|
||||
['test label'],
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(StoreOnChainWalletTransaction::class, $updatedTransaction);
|
||||
$this->assertIsString($updatedTransaction->getTransactionHash());
|
||||
$this->assertIsString($updatedTransaction->getComment());
|
||||
$this->assertIsArray($updatedTransaction->getLabels());
|
||||
$this->assertIsInt($updatedTransaction->getConfirmations());
|
||||
$this->assertIsInt($updatedTransaction->getTimestamp());
|
||||
$this->assertIsString($updatedTransaction->getStatus());
|
||||
|
||||
$this->assertEquals('test comment', $updatedTransaction->getComment());
|
||||
}
|
||||
|
||||
/** @group getStoreOnChainWalletUtxos */
|
||||
public function testItCanGetStoreOnChainWalletUtxos(): void
|
||||
{
|
||||
$utxos = $this->storeOnChainWalletClient->getStoreOnChainWalletUtxos(
|
||||
$this->storeId,
|
||||
'BTC'
|
||||
);
|
||||
|
||||
$this->assertInstanceOf(StoreOnChainWalletUtxoList::class, $utxos);
|
||||
|
||||
foreach($utxos as $utxo) {
|
||||
$this->assertInstanceOf(StoreOnChainWalletUtxo::class, $utxo);
|
||||
$this->assertIsString($utxo->getComment());
|
||||
$this->assertIsString($utxo->getAmount());
|
||||
$this->assertIsString($utxo->getOutpoint());
|
||||
$this->assertIsString($utxo->getLink());
|
||||
$this->assertIsArray($utxo->getLabels());
|
||||
$this->assertIsInt($utxo->getTimestamp());
|
||||
$this->assertIsString($utxo->getKeyPath());
|
||||
$this->assertIsString($utxo->getAddress());
|
||||
$this->assertIsInt($utxo->getConfirmations());
|
||||
}
|
||||
}
|
||||
}
|
||||
119
tests/StoreTest.php
Normal file
119
tests/StoreTest.php
Normal file
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BTCPayServer\Tests;
|
||||
|
||||
use BTCPayServer\Client\Store;
|
||||
use BTCPayServer\Result\Store as ResultStore;
|
||||
use BTCPayServer\Result\StoreList;
|
||||
use BTCPayServer\Util\PreciseNumber;
|
||||
|
||||
final class StoreTest extends BaseTest
|
||||
{
|
||||
public Store $storeClient;
|
||||
public ResultStore $store;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->storeClient = new Store($this->host, $this->apiKey);
|
||||
$this->store = $this->storeClient->createStore(
|
||||
name: 'Test Store',
|
||||
website: 'https://example.com',
|
||||
defaultCurrency: 'USD',
|
||||
invoiceExpiration: 900,
|
||||
displayExpirationTimer: 300,
|
||||
monitoringExpiration: 3600,
|
||||
speedPolicy: 'MediumSpeed',
|
||||
lightningDescriptionTemplate: null,
|
||||
paymentTolerance: 0,
|
||||
anyoneCanCreateInvoice: false,
|
||||
requiresRefundEmail: false,
|
||||
checkoutType: 'V1',
|
||||
receipt: null,
|
||||
lightningAmountInSatoshi: false,
|
||||
lightningPrivateRouteHints: false,
|
||||
onChainWithLnInvoiceFallback: false,
|
||||
redirectAutomatically: false,
|
||||
showRecommendedFee: true,
|
||||
recommendedFeeBlockTarget: 1,
|
||||
defaultLang: 'en',
|
||||
customLogo: 'https://test.com',
|
||||
customCSS: 'auto: 100px;',
|
||||
htmlTitle: 'the best store ever',
|
||||
networkFeeMode: 'MultiplePaymentsOnly',
|
||||
payJoinEnabled: false,
|
||||
lazyPaymentMethods: false,
|
||||
defaultPaymentMethod: 'BTC'
|
||||
);
|
||||
}
|
||||
|
||||
/** @group createStore */
|
||||
public function testItCanCreateAStore(): void
|
||||
{
|
||||
$this->assertStoreGettersAreSet($this->store);
|
||||
}
|
||||
|
||||
/** @group getStores */
|
||||
public function testItCanGetAllStores(): void
|
||||
{
|
||||
$stores = $this->storeClient->getStores();
|
||||
|
||||
$this->assertInstanceOf(StoreList::class, $stores);
|
||||
|
||||
foreach ($stores->all() as $store) {
|
||||
$this->assertStoreGettersAreSet($store);
|
||||
}
|
||||
}
|
||||
|
||||
/** @group getStore */
|
||||
public function testItCanGetAnIndividualStore(): void
|
||||
{
|
||||
$store = $this->storeClient->getStore($this->store->getId());
|
||||
$this->assertStoreGettersAreSet($store);
|
||||
}
|
||||
|
||||
private function assertStoreGettersAreSet(ResultStore $store): void
|
||||
{
|
||||
$this->assertInstanceOf(ResultStore::class, $store);
|
||||
$this->assertIsString($store->getName());
|
||||
$this->assertIsInt($store->getInvoiceExpiration());
|
||||
$this->assertIsInt($store->getMonitoringExpiration());
|
||||
$this->assertIsString($store->getSpeedPolicy());
|
||||
$this->assertIsString($store->getLightningDescriptionTemplate());
|
||||
$this->assertInstanceOf(PreciseNumber::class, $store->getPaymentTolerance());
|
||||
$this->assertIsBool($store->anyoneCanCreateInvoice());
|
||||
$this->assertIsBool($store->requiresRefundEmail());
|
||||
$this->assertIsBool($store->lightningAmountInSatoshi());
|
||||
$this->assertIsBool($store->lightningPrivateRouteHints());
|
||||
$this->assertIsBool($store->onChainWithLnInvoiceFallback());
|
||||
$this->assertIsBool($store->redirectAutomatically());
|
||||
$this->assertIsBool($store->showRecommendedFee());
|
||||
$this->assertIsInt($store->getRecommendedFeeBlockTarget());
|
||||
|
||||
if ($store->getCustomLogo() !== null) {
|
||||
$this->assertIsString($store->getCustomLogo());
|
||||
}
|
||||
|
||||
if ($store->getCustomCSS() !== null) {
|
||||
$this->assertIsString($store->getCustomCSS());
|
||||
}
|
||||
|
||||
if ($store->getHtmlTitle() !== null) {
|
||||
$this->assertIsString($store->getHtmlTitle());
|
||||
}
|
||||
if ($store->getWebsite() !== null) {
|
||||
$this->assertIsString($store->getWebsite());
|
||||
}
|
||||
if ($store->getDefaultPaymentMethod() !== null) {
|
||||
$this->assertIsString($store->getDefaultPaymentMethod());
|
||||
}
|
||||
|
||||
$this->assertIsString($store->getNetworkFeeMode());
|
||||
$this->assertIsBool($store->payJoinEnabled());
|
||||
$this->assertIsBool($store->lazyPaymentMethods());
|
||||
$this->assertIsString($store->getId());
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user