diff --git a/CHANGELOG.md b/CHANGELOG.md
index f9516dad..e825c544 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,18 @@
# b24-php-sdk change log
+## Upcoming 1.7.0 - 2025.10.01
+
+### Added
+
+- Added service `Services\Sale\Payment\Service\Payment` with support methods,
+ see [sale.payment.* methods](https://github.com/bitrix24/b24phpsdk/issues/248):
+ - `add` adds a payment
+ - `update` updates the fields of a payment
+ - `get` returns a payment by its identifier
+ - `list` returns a list of payments
+ - `delete` deletes a payment
+ - `getFields` returns the fields and settings for payments
+
## 1.6.0 – 2025.09.01
### Added
diff --git a/Makefile b/Makefile
index ec463b54..784d1e5e 100644
--- a/Makefile
+++ b/Makefile
@@ -290,6 +290,10 @@ integration_tests_task:
.PHONY: integration_tests_sale
integration_tests_sale:
docker-compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_sale
+
+.PHONY: integration_tests_sale_payment
+integration_tests_sale_payment:
+ docker-compose run --rm php-cli vendor/bin/phpunit --testsuite integration_tests_sale_payment
# work dev environment
.PHONY: php-dev-server-up
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index fc7be9d0..c77ba328 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -124,6 +124,9 @@
./tests/Integration/Services/Sale/
+
+ ./tests/Integration/Services/Sale/Payment/
+
./tests/Integration/Services/Sale/Order/
diff --git a/src/Services/Sale/Payment/Result/PaymentAddedResult.php b/src/Services/Sale/Payment/Result/PaymentAddedResult.php
new file mode 100644
index 00000000..02f14e38
--- /dev/null
+++ b/src/Services/Sale/Payment/Result/PaymentAddedResult.php
@@ -0,0 +1,33 @@
+
+ *
+ * For the full copyright and license information, please view the MIT-LICENSE.txt
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Bitrix24\SDK\Services\Sale\Payment\Result;
+
+use Bitrix24\SDK\Core\Exceptions\BaseException;
+use Bitrix24\SDK\Core\Result\AddedItemResult;
+
+/**
+ * Class PaymentAddedResult
+ * Represents the result of an add payment operation.
+ */
+class PaymentAddedResult extends AddedItemResult
+{
+ /**
+ * @throws BaseException
+ */
+ public function getId(): int
+ {
+ $result = $this->getCoreResponse()->getResponseData()->getResult();
+ return isset($result['payment']['id']) ? (int)$result['payment']['id'] : 0;
+ }
+}
diff --git a/src/Services/Sale/Payment/Result/PaymentFieldsResult.php b/src/Services/Sale/Payment/Result/PaymentFieldsResult.php
new file mode 100644
index 00000000..8a5b3f96
--- /dev/null
+++ b/src/Services/Sale/Payment/Result/PaymentFieldsResult.php
@@ -0,0 +1,33 @@
+
+ *
+ * For the full copyright and license information, please view the MIT-LICENSE.txt
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Bitrix24\SDK\Services\Sale\Payment\Result;
+
+use Bitrix24\SDK\Core\Exceptions\BaseException;
+use Bitrix24\SDK\Core\Result\AbstractResult;
+
+/**
+ * Class PaymentFieldsResult
+ * Represents the result of a get payment fields operation.
+ */
+class PaymentFieldsResult extends AbstractResult
+{
+ /**
+ * @throws BaseException
+ */
+ public function getFieldsDescription(): array
+ {
+ $result = $this->getCoreResponse()->getResponseData()->getResult();
+ return $result['payment'] ?? [];
+ }
+}
diff --git a/src/Services/Sale/Payment/Result/PaymentItemResult.php b/src/Services/Sale/Payment/Result/PaymentItemResult.php
new file mode 100644
index 00000000..f7dcc5c8
--- /dev/null
+++ b/src/Services/Sale/Payment/Result/PaymentItemResult.php
@@ -0,0 +1,73 @@
+
+ *
+ * For the full copyright and license information, please view the MIT-LICENSE.txt
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Bitrix24\SDK\Services\Sale\Payment\Result;
+
+use Bitrix24\SDK\Core\Result\AbstractItem;
+use Carbon\CarbonImmutable;
+use Money\Money;
+
+/**
+ * Class PaymentItemResult
+ * Represents a single payment item (payment) returned by Bitrix24 REST API.
+ *
+ * Fields and their types are taken from Bitrix24 API (sale.payment.getfields).
+ *
+ * @property-read string|null $accountNumber Payment account number
+ * @property-read string|null $comments Payment comments
+ * @property-read int|null $companyId Company identifier
+ * @property-read string|null $currency Payment currency code
+ * @property-read CarbonImmutable|null $dateBill Invoice date
+ * @property-read CarbonImmutable|null $dateMarked Date when payment was marked
+ * @property-read CarbonImmutable|null $datePaid Payment date
+ * @property-read CarbonImmutable|null $datePayBefore Date by which the invoice must be paid
+ * @property-read CarbonImmutable|null $dateResponsibleId Date when responsible was assigned
+ * @property-read int|null $empMarkedId User who marked the payment
+ * @property-read int|null $empPaidId User who made the payment
+ * @property-read int|null $empResponsibleId User who assigned the responsible
+ * @property-read int|null $empReturnId User who processed the return
+ * @property-read bool|null $externalPayment External payment flag
+ * @property-read int|null $id Payment ID
+ * @property-read string|null $id1c Identifier in QuickBooks
+ * @property-read bool|null $isReturn Return processed flag
+ * @property-read bool|null $marked Problem marking flag
+ * @property-read int|null $orderId Order ID
+ * @property-read bool|null $paid Payment status
+ * @property-read string|null $payReturnComment Return comment
+ * @property-read CarbonImmutable|null $payReturnDate Return document date
+ * @property-read string|null $payReturnNum Return document number
+ * @property-read int|null $paySystemId Payment system ID
+ * @property-read bool|null $paySystemIsCash Is cash payment system
+ * @property-read string|null $paySystemName Payment system name
+ * @property-read string|null $paySystemXmlId Payment system XML ID
+ * @property-read CarbonImmutable|null $payVoucherDate Payment document date
+ * @property-read string|null $payVoucherNum Payment document number
+ * @property-read Money|null $priceCod Cost of payment upon delivery
+ * @property-read string|null $psCurrency Payment system currency
+ * @property-read string|null $psInvoiceId Payment ID in payment system
+ * @property-read CarbonImmutable|null $psResponseDate Payment system response date
+ * @property-read bool|null $psStatus Payment system status
+ * @property-read string|null $psStatusCode Payment system status code
+ * @property-read string|null $psStatusDescription Description of payment system result
+ * @property-read string|null $psStatusMessage Message from payment system
+ * @property-read Money|null $psSum Payment system amount
+ * @property-read string|null $reasonMarked Reason for marking
+ * @property-read int|null $responsibleId User responsible for payment
+ * @property-read Money|null $sum Payment amount
+ * @property-read bool|null $updated1c Updated via QuickBooks flag
+ * @property-read string|null $version1c Payment document version
+ * @property-read string|null $xmlId External identifier
+ */
+class PaymentItemResult extends AbstractItem
+{
+}
diff --git a/src/Services/Sale/Payment/Result/PaymentResult.php b/src/Services/Sale/Payment/Result/PaymentResult.php
new file mode 100644
index 00000000..13e859d1
--- /dev/null
+++ b/src/Services/Sale/Payment/Result/PaymentResult.php
@@ -0,0 +1,32 @@
+
+ *
+ * For the full copyright and license information, please view the MIT-LICENSE.txt
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Bitrix24\SDK\Services\Sale\Payment\Result;
+
+use Bitrix24\SDK\Core\Result\AbstractResult;
+
+/**
+ * Class PaymentResult
+ * Represents the result of a single payment operation.
+ */
+class PaymentResult extends AbstractResult
+{
+ /**
+ * Returns the payment as PaymentItemResult
+ */
+ public function payment(): PaymentItemResult
+ {
+ $result = $this->getCoreResponse()->getResponseData()->getResult();
+ return new PaymentItemResult($result['payment'] ?? []);
+ }
+}
diff --git a/src/Services/Sale/Payment/Result/PaymentUpdatedResult.php b/src/Services/Sale/Payment/Result/PaymentUpdatedResult.php
new file mode 100644
index 00000000..e697eb93
--- /dev/null
+++ b/src/Services/Sale/Payment/Result/PaymentUpdatedResult.php
@@ -0,0 +1,33 @@
+
+ *
+ * For the full copyright and license information, please view the MIT-LICENSE.txt
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Bitrix24\SDK\Services\Sale\Payment\Result;
+
+use Bitrix24\SDK\Core\Exceptions\BaseException;
+use Bitrix24\SDK\Core\Result\UpdatedItemResult;
+
+/**
+ * Class PaymentUpdatedResult
+ * Represents the result of an update payment operation.
+ */
+class PaymentUpdatedResult extends UpdatedItemResult
+{
+ /**
+ * @throws BaseException
+ */
+ public function isSuccess(): bool
+ {
+ $result = $this->getCoreResponse()->getResponseData()->getResult();
+ return isset($result['payment']) && !empty($result['payment']);
+ }
+}
diff --git a/src/Services/Sale/Payment/Result/PaymentsResult.php b/src/Services/Sale/Payment/Result/PaymentsResult.php
new file mode 100644
index 00000000..4e25988f
--- /dev/null
+++ b/src/Services/Sale/Payment/Result/PaymentsResult.php
@@ -0,0 +1,35 @@
+
+ *
+ * For the full copyright and license information, please view the MIT-LICENSE.txt
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Bitrix24\SDK\Services\Sale\Payment\Result;
+
+use Bitrix24\SDK\Core\Result\AbstractResult;
+
+/**
+ * Class PaymentsResult
+ * Represents the result of a list payments operation.
+ */
+class PaymentsResult extends AbstractResult
+{
+ /**
+ * Returns an array of payment items
+ *
+ * @return PaymentItemResult[] array of payment item results
+ */
+ public function getPayments(): array
+ {
+ $result = $this->getCoreResponse()->getResponseData()->getResult();
+ $payments = $result['payments'] ?? [];
+ return array_map(fn ($payment): PaymentItemResult => new PaymentItemResult($payment), $payments);
+ }
+}
diff --git a/src/Services/Sale/Payment/Service/Payment.php b/src/Services/Sale/Payment/Service/Payment.php
new file mode 100644
index 00000000..a13ba569
--- /dev/null
+++ b/src/Services/Sale/Payment/Service/Payment.php
@@ -0,0 +1,186 @@
+
+ *
+ * For the full copyright and license information, please view the MIT-LICENSE.txt
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Bitrix24\SDK\Services\Sale\Payment\Service;
+
+use Bitrix24\SDK\Attributes\ApiEndpointMetadata;
+use Bitrix24\SDK\Attributes\ApiServiceMetadata;
+use Bitrix24\SDK\Core\Contracts\CoreInterface;
+use Bitrix24\SDK\Core\Credentials\Scope;
+use Bitrix24\SDK\Core\Exceptions\BaseException;
+use Bitrix24\SDK\Core\Exceptions\TransportException;
+use Bitrix24\SDK\Core\Result\DeletedItemResult;
+use Bitrix24\SDK\Services\AbstractService;
+use Bitrix24\SDK\Services\Sale\Payment\Result\PaymentResult;
+use Bitrix24\SDK\Services\Sale\Payment\Result\PaymentsResult;
+use Bitrix24\SDK\Services\Sale\Payment\Result\PaymentFieldsResult;
+use Bitrix24\SDK\Services\Sale\Payment\Result\PaymentAddedResult;
+use Bitrix24\SDK\Services\Sale\Payment\Result\PaymentUpdatedResult;
+use Psr\Log\LoggerInterface;
+
+#[ApiServiceMetadata(new Scope(['sale']))]
+class Payment extends AbstractService
+{
+ public function __construct(CoreInterface $core, LoggerInterface $logger)
+ {
+ parent::__construct($core, $logger);
+ }
+
+ /**
+ * Adds a payment.
+ *
+ * @link https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-add.html
+ *
+ * @param array $fields Field values for creating a payment
+ *
+ * @throws BaseException
+ * @throws TransportException
+ */
+ #[ApiEndpointMetadata(
+ 'sale.payment.add',
+ 'https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-add.html',
+ 'Creates a new payment.'
+ )]
+ public function add(array $fields): PaymentAddedResult
+ {
+ return new PaymentAddedResult(
+ $this->core->call('sale.payment.add', [
+ 'fields' => $fields
+ ])
+ );
+ }
+
+ /**
+ * Updates the fields of a payment.
+ *
+ * @link https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-update.html
+ *
+ * @param int $id Payment identifier
+ * @param array $fields Field values for update
+ *
+ * @throws BaseException
+ * @throws TransportException
+ */
+ #[ApiEndpointMetadata(
+ 'sale.payment.update',
+ 'https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-update.html',
+ 'Updates an existing payment.'
+ )]
+ public function update(int $id, array $fields): PaymentUpdatedResult
+ {
+ return new PaymentUpdatedResult(
+ $this->core->call('sale.payment.update', [
+ 'id' => $id,
+ 'fields' => $fields
+ ])
+ );
+ }
+
+ /**
+ * Returns a payment by its identifier.
+ *
+ * @link https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-get.html
+ *
+ * @param int $id Payment identifier
+ *
+ * @throws BaseException
+ * @throws TransportException
+ */
+ #[ApiEndpointMetadata(
+ 'sale.payment.get',
+ 'https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-get.html',
+ 'Retrieves information about a payment.'
+ )]
+ public function get(int $id): PaymentResult
+ {
+ return new PaymentResult(
+ $this->core->call('sale.payment.get', [
+ 'id' => $id
+ ])
+ );
+ }
+
+ /**
+ * Returns a list of payments.
+ *
+ * @link https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-list.html
+ *
+ * @param array $filter Filter criteria
+ * @param array $order Sort order
+ * @param array $select Fields to select
+ * @param int $start Pagination start (offset)
+ *
+ * @throws BaseException
+ * @throws TransportException
+ */
+ #[ApiEndpointMetadata(
+ 'sale.payment.list',
+ 'https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-list.html',
+ 'Retrieves a list of payments.'
+ )]
+ public function list(array $select = [], array $filter = [], array $order = [], int $start = 0): PaymentsResult
+ {
+ return new PaymentsResult(
+ $this->core->call('sale.payment.list', [
+ 'select' => $select,
+ 'filter' => $filter,
+ 'order' => $order,
+ 'start' => $start
+ ])
+ );
+ }
+
+ /**
+ * Deletes a payment.
+ *
+ * @link https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-delete.html
+ *
+ * @param int $id Payment identifier
+ *
+ * @throws BaseException
+ * @throws TransportException
+ */
+ #[ApiEndpointMetadata(
+ 'sale.payment.delete',
+ 'https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-delete.html',
+ 'Deletes a payment.'
+ )]
+ public function delete(int $id): DeletedItemResult
+ {
+ return new DeletedItemResult(
+ $this->core->call('sale.payment.delete', [
+ 'id' => $id
+ ])
+ );
+ }
+
+ /**
+ * Returns the fields and settings for payments.
+ *
+ * @link https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-get-fields.html
+ *
+ * @throws BaseException
+ * @throws TransportException
+ */
+ #[ApiEndpointMetadata(
+ 'sale.payment.getFields',
+ 'https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-get-fields.html',
+ 'Retrieves the description of payment fields.'
+ )]
+ public function getFields(): PaymentFieldsResult
+ {
+ return new PaymentFieldsResult(
+ $this->core->call('sale.payment.getFields', [])
+ );
+ }
+}
diff --git a/src/Services/Sale/SaleServiceBuilder.php b/src/Services/Sale/SaleServiceBuilder.php
index cfa1aaa8..8c7e9a5b 100644
--- a/src/Services/Sale/SaleServiceBuilder.php
+++ b/src/Services/Sale/SaleServiceBuilder.php
@@ -129,6 +129,21 @@ public function personType(): PersonType\Service\PersonType
return $this->serviceCache[__METHOD__];
}
+ /**
+ * Payment service (sale.payment.*)
+ */
+ public function payment(): Payment\Service\Payment
+ {
+ if (!isset($this->serviceCache[__METHOD__])) {
+ $this->serviceCache[__METHOD__] = new Payment\Service\Payment(
+ $this->core,
+ $this->log
+ );
+ }
+
+ return $this->serviceCache[__METHOD__];
+ }
+
public function propertyVariant(): PropertyVariant
{
if (!isset($this->serviceCache[__METHOD__])) {
diff --git a/tests/Integration/Services/Sale/Payment/Service/PaymentTest.php b/tests/Integration/Services/Sale/Payment/Service/PaymentTest.php
new file mode 100644
index 00000000..e0c22ee8
--- /dev/null
+++ b/tests/Integration/Services/Sale/Payment/Service/PaymentTest.php
@@ -0,0 +1,332 @@
+
+ *
+ * For the full copyright and license information, please view the MIT-LICENSE.txt
+ * file that was distributed with this source code.
+ */
+
+declare(strict_types=1);
+
+namespace Bitrix24\SDK\Tests\Integration\Services\Sale\Payment\Service;
+
+use Bitrix24\SDK\Core\Exceptions\BaseException;
+use Bitrix24\SDK\Core\Exceptions\TransportException;
+use Bitrix24\SDK\Core;
+use Bitrix24\SDK\Services\Sale\Order\Service\Order;
+use Bitrix24\SDK\Services\Sale\Payment\Result\PaymentItemResult;
+use Bitrix24\SDK\Services\Sale\Payment\Service\Payment;
+use Bitrix24\SDK\Services\Sale\Service\PersonType;
+use Bitrix24\SDK\Tests\CustomAssertions\CustomBitrix24Assertions;
+use Bitrix24\SDK\Tests\Integration\Fabric;
+use PHPUnit\Framework\Attributes\CoversMethod;
+use PHPUnit\Framework\TestCase;
+
+/**
+ * Class PaymentTest
+ *
+ * @package Bitrix24\SDK\Tests\Integration\Services\Sale\Payment\Service
+ */
+#[CoversMethod(Payment::class,'add')]
+#[CoversMethod(Payment::class,'update')]
+#[CoversMethod(Payment::class,'get')]
+#[CoversMethod(Payment::class,'list')]
+#[CoversMethod(Payment::class,'delete')]
+#[CoversMethod(Payment::class,'getFields')]
+#[CoversMethod(PaymentTest::class,'testAllSystemFieldsAnnotated')]
+#[CoversMethod(PaymentTest::class,'testAllSystemFieldsHasValidTypeAnnotation')]
+#[\PHPUnit\Framework\Attributes\CoversClass(\Bitrix24\SDK\Services\Sale\Payment\Service\Payment::class)]
+class PaymentTest extends TestCase
+{
+ use CustomBitrix24Assertions;
+
+ protected Payment $paymentService;
+
+ protected int $orderId = 0;
+
+ protected int $personTypeId = 0;
+
+ protected int $paySystemId = 0;
+
+ protected function setUp(): void
+ {
+ $serviceBuilder = Fabric::getServiceBuilder();
+ $this->paymentService = $serviceBuilder->getSaleScope()->payment();
+ $this->personTypeId = $this->getPersonTypeId();
+ $this->paySystemId = $this->getPaySystemId();
+ $this->orderId = $this->createTestOrder();
+ }
+
+ protected function tearDown(): void
+ {
+ // Clean up created resources
+ $this->deleteTestOrder($this->orderId);
+ $this->deletePersonType($this->personTypeId);
+ }
+
+ public function testAllSystemFieldsAnnotated(): void
+ {
+ $propListFromApi = (new Core\Fields\FieldsFilter())->filterSystemFields(array_keys($this->paymentService->getFields()->getFieldsDescription()));
+ $this->assertBitrix24AllResultItemFieldsAnnotated($propListFromApi, PaymentItemResult::class);
+ }
+
+ public function testAllSystemFieldsHasValidTypeAnnotation(): void
+ {
+ $allFields = $this->paymentService->getFields()->getFieldsDescription();
+ $systemFieldsCodes = (new Core\Fields\FieldsFilter())->filterSystemFields(array_keys($allFields));
+ $systemFields = array_filter($allFields, static fn($code): bool => in_array($code, $systemFieldsCodes, true), ARRAY_FILTER_USE_KEY);
+
+ $this->assertBitrix24AllResultItemFieldsHasValidTypeAnnotation(
+ $systemFields,
+ PaymentItemResult::class);
+ }
+
+ /**
+ * Helper method to create a person type for testing
+ */
+ protected function getPersonTypeId(): int
+ {
+ $personTypeService = Fabric::getServiceBuilder()->getSaleScope()->personType();
+ return $personTypeService->add([
+ 'name' => 'Test Person Type for Payment',
+ 'sort' => 100,
+ ])->getId();
+ }
+
+ /**
+ * Helper method to delete a person type after testing
+ */
+ protected function deletePersonType(int $id): void
+ {
+ $personTypeService = Fabric::getServiceBuilder()->getSaleScope()->personType();
+ $personTypeService->delete($id);
+ }
+
+ /**
+ * Helper method to get a payment system for testing
+ * We fetch an existing one from the system
+ */
+ protected function getPaySystemId(): int
+ {
+ $core = Fabric::getCore();
+ $response = $core->call('sale.paysystem.list', [
+ 'select' => ['id'],
+ 'filter' => ['active' => 'Y'],
+ 'order' => ['id' => 'ASC']
+ ]);
+
+ $result = $response->getResponseData()->getResult();
+ $paySystems = (is_array($result)) ? $result : [];
+
+ if ($paySystems === []) {
+ $this->markTestSkipped('No payment systems available for testing');
+ }
+
+ return (int)$paySystems[0]['ID'];
+ }
+
+ /**
+ * Helper method to create a test order
+ */
+ protected function createTestOrder(): int
+ {
+ $orderService = Fabric::getServiceBuilder()->getSaleScope()->order();
+ $orderFields = [
+ 'lid' => 's1',
+ 'personTypeId' => $this->personTypeId,
+ 'currency' => 'USD',
+ 'price' => 100.00
+ ];
+
+ return $orderService->add($orderFields)->getId();
+ }
+
+ /**
+ * Helper method to delete a test order
+ */
+ protected function deleteTestOrder(int $id): void
+ {
+ $orderService = Fabric::getServiceBuilder()->getSaleScope()->order();
+ try {
+ $orderService->delete($id);
+ } catch (\Exception) {
+ // Ignore if order doesn't exist
+ }
+ }
+
+ /**
+ * @throws BaseException
+ * @throws TransportException
+ */
+ public function testAdd(): void
+ {
+ // Create a payment
+ $paymentFields = [
+ 'orderId' => $this->orderId,
+ 'paySystemId' => $this->paySystemId,
+ 'sum' => 100.00,
+ 'currency' => 'USD'
+ ];
+
+ $paymentAddedResult = $this->paymentService->add($paymentFields);
+ $paymentId = $paymentAddedResult->getId();
+
+ self::assertGreaterThan(0, $paymentId);
+
+ // Clean up
+ $this->paymentService->delete($paymentId);
+ }
+
+ /**
+ * @throws BaseException
+ * @throws TransportException
+ */
+ public function testUpdate(): void
+ {
+ // Create a payment
+ $paymentFields = [
+ 'orderId' => $this->orderId,
+ 'paySystemId' => $this->paySystemId,
+ 'sum' => 100.00,
+ 'currency' => 'USD'
+ ];
+
+ $paymentAddedResult = $this->paymentService->add($paymentFields);
+ $paymentId = $paymentAddedResult->getId();
+
+ // Update the payment
+ $updateFields = [
+ 'paySystemId' => $this->paySystemId,
+ 'comments' => 'Updated Test Payment',
+ 'sum' => 150.00
+ ];
+
+ $this->paymentService->update($paymentId, $updateFields);
+
+ // Verify the update
+ $payment = $this->paymentService->get($paymentId)->payment();
+ self::assertEquals('Updated Test Payment', $payment->comments);
+
+ // Clean up
+ $this->paymentService->delete($paymentId);
+ }
+
+ /**
+ * @throws BaseException
+ * @throws TransportException
+ */
+ public function testGet(): void
+ {
+ // Create a payment
+ $paymentFields = [
+ 'orderId' => $this->orderId,
+ 'paySystemId' => $this->paySystemId,
+ 'sum' => 100.00,
+ 'currency' => 'USD',
+ 'comments' => 'Test Payment Comment'
+ ];
+
+ $paymentAddedResult = $this->paymentService->add($paymentFields);
+ $paymentId = $paymentAddedResult->getId();
+
+ // Get the payment
+ $payment = $this->paymentService->get($paymentId)->payment();
+
+ self::assertEquals($paymentId, $payment->id);
+ self::assertEquals('Test Payment Comment', $payment->comments);
+
+ // Clean up
+ $this->paymentService->delete($paymentId);
+ }
+
+ /**
+ * @throws BaseException
+ * @throws TransportException
+ */
+ public function testList(): void
+ {
+ // Create a payment
+ $paymentFields = [
+ 'orderId' => $this->orderId,
+ 'paySystemId' => $this->paySystemId,
+ 'sum' => 100.00,
+ 'currency' => 'USD',
+ 'comments' => 'Test List Payment'
+ ];
+
+ $paymentAddedResult = $this->paymentService->add($paymentFields);
+ $paymentId = $paymentAddedResult->getId();
+
+ // List payments
+ $filter = ['orderId' => $this->orderId];
+ $paymentsResult = $this->paymentService->list([], $filter);
+ $payments = $paymentsResult->getPayments();
+
+ self::assertGreaterThan(0, count($payments));
+
+ // Verify our payment is in the list
+ $found = false;
+ foreach ($payments as $payment) {
+ if ((int)$payment->id === $paymentId) {
+ $found = true;
+ break;
+ }
+ }
+
+ self::assertTrue($found);
+
+ // Clean up
+ $this->paymentService->delete($paymentId);
+ }
+
+ /**
+ * @throws BaseException
+ * @throws TransportException
+ */
+ public function testDelete(): void
+ {
+ // Create a payment
+ $paymentFields = [
+ 'orderId' => $this->orderId,
+ 'paySystemId' => $this->paySystemId,
+ 'sum' => 100.00,
+ 'currency' => 'USD'
+ ];
+
+ $paymentAddedResult = $this->paymentService->add($paymentFields);
+ $paymentId = $paymentAddedResult->getId();
+
+ // Delete the payment
+ $this->paymentService->delete($paymentId);
+
+ // Verify payment no longer exists
+ try {
+ $this->paymentService->get($paymentId);
+ self::fail('Expected exception when getting deleted payment');
+ } catch (\Exception $exception) {
+ // Expected exception - check for error message indicating payment doesn't exist
+ self::assertStringContainsString('payment is not exists', $exception->getMessage());
+ }
+ }
+
+ /**
+ * @throws BaseException
+ * @throws TransportException
+ */
+ public function testGetFields(): void
+ {
+ // Get fields for payment
+ $paymentFieldsResult = $this->paymentService->getFields();
+ $fields = $paymentFieldsResult->getFieldsDescription();
+
+ // Verify fields structure
+ self::assertIsArray($fields);
+ // Verify basic payment fields are present
+ self::assertArrayHasKey('orderId', $fields);
+ self::assertArrayHasKey('paySystemId', $fields);
+ self::assertArrayHasKey('sum', $fields);
+ }
+}