From 332b9d1b6a0532ed81516b3882fe72de8a6156e0 Mon Sep 17 00:00:00 2001 From: Sally Fancen Date: Tue, 9 Sep 2025 15:44:26 +0400 Subject: [PATCH 1/7] add Payment service --- src/Services/Sale/Payment/Batch.php | 82 +++++++++++ .../Result/AddedPaymentBatchResult.php | 34 +++++ .../Payment/Result/PaymentAddedResult.php | 33 +++++ .../Payment/Result/PaymentFieldsResult.php | 33 +++++ .../Sale/Payment/Result/PaymentItemResult.php | 73 +++++++++ .../Sale/Payment/Result/PaymentResult.php | 32 ++++ .../Payment/Result/PaymentUpdatedResult.php | 33 +++++ .../Sale/Payment/Result/PaymentsResult.php | 35 +++++ .../Result/UpdatedPaymentBatchResult.php | 34 +++++ src/Services/Sale/Payment/Service/Batch.php | 138 ++++++++++++++++++ src/Services/Sale/Payment/Service/Payment.php | 114 +++++++++++++++ src/Services/Sale/SaleServiceBuilder.php | 20 +++ 12 files changed, 661 insertions(+) create mode 100644 src/Services/Sale/Payment/Batch.php create mode 100644 src/Services/Sale/Payment/Result/AddedPaymentBatchResult.php create mode 100644 src/Services/Sale/Payment/Result/PaymentAddedResult.php create mode 100644 src/Services/Sale/Payment/Result/PaymentFieldsResult.php create mode 100644 src/Services/Sale/Payment/Result/PaymentItemResult.php create mode 100644 src/Services/Sale/Payment/Result/PaymentResult.php create mode 100644 src/Services/Sale/Payment/Result/PaymentUpdatedResult.php create mode 100644 src/Services/Sale/Payment/Result/PaymentsResult.php create mode 100644 src/Services/Sale/Payment/Result/UpdatedPaymentBatchResult.php create mode 100644 src/Services/Sale/Payment/Service/Batch.php create mode 100644 src/Services/Sale/Payment/Service/Payment.php diff --git a/src/Services/Sale/Payment/Batch.php b/src/Services/Sale/Payment/Batch.php new file mode 100644 index 00000000..5055f785 --- /dev/null +++ b/src/Services/Sale/Payment/Batch.php @@ -0,0 +1,82 @@ + + * + * 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; + +use Bitrix24\SDK\Core\Commands\Command; +use Bitrix24\SDK\Core\Commands\CommandCollection; +use Bitrix24\SDK\Core\Contracts\CoreInterface; +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Exceptions\InvalidArgumentException; +use Bitrix24\SDK\Core\Response\DTO\Pagination; +use Bitrix24\SDK\Core\Response\DTO\ResponseData; +use Bitrix24\SDK\Core\Response\DTO\Result; +use Bitrix24\SDK\Core\Response\DTO\Time; +use Bitrix24\SDK\Core\Response\Response; +use Generator; +use Psr\Log\LoggerInterface; + +/** + * Class Batch + * + * @package Bitrix24\SDK\Services\Sale\Payment + */ +class Batch extends \Bitrix24\SDK\Core\Batch +{ + /** + * Delete entity items with batch call + * + * + * @return Generator|ResponseData[] + * @throws \Bitrix24\SDK\Core\Exceptions\BaseException + */ + public function deleteEntityItems( + string $apiMethod, + array $entityItemId, + ?array $additionalParameters = null + ): Generator { + $this->logger->debug( + 'deleteEntityItems.start', + [ + 'apiMethod' => $apiMethod, + 'entityItemId' => $entityItemId, + 'additionalParameters' => $additionalParameters + ] + ); + + // create commands + $commandParams = []; + foreach ($entityItemId as $id) { + $commandParams[] = ['id' => $id]; + } + + // Build commands + $commands = new CommandCollection(); + foreach ($commandParams as $index => $commandParam) { + $commands->add( + new Command( + $apiMethod, + $commandParam, + sprintf('%s_%s', $apiMethod, $index) + ) + ); + } + + // Process batch commands and return results + foreach ($this->processBatch($commands) as $item) { + yield $item->getId() => $item->getResponseData(); + } + + $this->logger->debug('deleteEntityItems.finish'); + } +} diff --git a/src/Services/Sale/Payment/Result/AddedPaymentBatchResult.php b/src/Services/Sale/Payment/Result/AddedPaymentBatchResult.php new file mode 100644 index 00000000..5f5d594a --- /dev/null +++ b/src/Services/Sale/Payment/Result/AddedPaymentBatchResult.php @@ -0,0 +1,34 @@ + + * + * 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\AddedItemBatchResult; +use Bitrix24\SDK\Core\Exceptions\BaseException; + +/** + * Class AddedPaymentBatchResult + * Represents a result of batch add payments operation + * + * @package Bitrix24\SDK\Services\Sale\Payment\Result + */ +class AddedPaymentBatchResult extends AddedItemBatchResult +{ + /** + * @throws BaseException + */ + public function getId(): int + { + return (int)$this->getResponseData()->getResult()['payment']['id']; + } +} 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..eddc2084 --- /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 string|null $externalPayment External payment flag + * @property-read int|null $id Payment ID + * @property-read string|null $id1c Identifier in QuickBooks + * @property-read string|null $isReturn Return processed flag + * @property-read string|null $marked Problem marking flag + * @property-read int|null $orderId Order ID + * @property-read string|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 string|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 string|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 string|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 string|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..59404636 --- /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/Result/UpdatedPaymentBatchResult.php b/src/Services/Sale/Payment/Result/UpdatedPaymentBatchResult.php new file mode 100644 index 00000000..d247cf7a --- /dev/null +++ b/src/Services/Sale/Payment/Result/UpdatedPaymentBatchResult.php @@ -0,0 +1,34 @@ + + * + * 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\UpdatedItemBatchResult; +use Bitrix24\SDK\Core\Exceptions\BaseException; + +/** + * Class UpdatedPaymentBatchResult + * Represents a result of batch update payments operation + * + * @package Bitrix24\SDK\Services\Sale\Payment\Result + */ +class UpdatedPaymentBatchResult extends UpdatedItemBatchResult +{ + /** + * @throws BaseException + */ + public function isSuccess(): bool + { + return (bool)$this->getResponseData()->getResult()['payment']; + } +} diff --git a/src/Services/Sale/Payment/Service/Batch.php b/src/Services/Sale/Payment/Service/Batch.php new file mode 100644 index 00000000..77a5bd20 --- /dev/null +++ b/src/Services/Sale/Payment/Service/Batch.php @@ -0,0 +1,138 @@ + + * + * 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\ApiBatchMethodMetadata; +use Bitrix24\SDK\Attributes\ApiBatchServiceMetadata; +use Bitrix24\SDK\Core\Contracts\BatchOperationsInterface; +use Bitrix24\SDK\Core\Credentials\Scope; +use Bitrix24\SDK\Core\Exceptions\BaseException; +use Bitrix24\SDK\Core\Result\DeletedItemBatchResult; +use Bitrix24\SDK\Services\Sale\Payment\Result\UpdatedPaymentBatchResult; +use Bitrix24\SDK\Services\Sale\Payment\Result\AddedPaymentBatchResult; +use Bitrix24\SDK\Services\Sale\Payment\Result\PaymentItemResult; +use Generator; +use Psr\Log\LoggerInterface; + +#[ApiBatchServiceMetadata(new Scope(['sale']))] +class Batch +{ + /** + * Batch constructor. + */ + public function __construct(protected BatchOperationsInterface $batch, protected LoggerInterface $log) + { + } + + /** + * Batch add method for creating multiple payments + * + * @param array $payments Array of payment fields + * + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'sale.payment.add', + 'https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-add.html', + 'Creates a new payment' + )] + public function add(array $payments): Generator + { + $fields = []; + foreach ($payments as $payment) { + $fields[] = [ + 'fields' => $payment + ]; + } + + foreach ($this->batch->addEntityItems('sale.payment.add', $fields) as $key => $item) { + yield $key => new AddedPaymentBatchResult($item); + } + } + + /** + * Batch update method for updating multiple payments + * + * Update elements in array with structure + * element_id => [ // payment id + * 'fields' => [] // payment fields to update + * ] + * + * @param array $paymentsData + * @return Generator + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'sale.payment.update', + 'https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-update.html', + 'Updates an existing payment' + )] + public function update(array $paymentsData): Generator + { + foreach ($this->batch->updateEntityItems('sale.payment.update', $paymentsData) as $key => $item) { + yield $key => new UpdatedPaymentBatchResult($item); + } + } + + /** + * Batch list method for retrieving multiple payments + * + * @param array $filter Filter criteria + * @param array $order Sort order + * @param array $select Fields to select + * @param int|null $limit Maximum number of items to return + * + * @return Generator|PaymentItemResult[] + * @throws BaseException + */ + #[ApiBatchMethodMetadata( + 'sale.payment.list', + 'https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-list.html', + 'Retrieves a list of payments' + )] + public function list(array $filter = [], array $order = [], array $select = [], ?int $limit = null): Generator + { + foreach ($this->batch->getTraversableList( + 'sale.payment.list', + $order, + $filter, + $select, + $limit + ) as $key => $item) { + yield $key => new PaymentItemResult($item); + } + } + + /** + * Batch delete payments + * + * @param int[] $paymentIds + * + * @return Generator + * @throws BaseException + */ + #[ApiEndpointMetadata( + 'sale.payment.delete', + 'https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-delete.html', + 'Batch delete payments.' + )] + public function delete(array $paymentIds): Generator + { + foreach ($this->batch->deleteEntityItems('sale.payment.delete', $paymentIds) as $key => $item) { + yield $key => new DeletedItemBatchResult($item); + } + } +} diff --git a/src/Services/Sale/Payment/Service/Payment.php b/src/Services/Sale/Payment/Service/Payment.php new file mode 100644 index 00000000..77d3a480 --- /dev/null +++ b/src/Services/Sale/Payment/Service/Payment.php @@ -0,0 +1,114 @@ + + * + * 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\Core\Contracts\CoreInterface; +use Bitrix24\SDK\Core\Result\DeletedItemResult; +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; +use Bitrix24\SDK\Attributes\ApiServiceMetadata; +use Bitrix24\SDK\Attributes\ApiEndpointMetadata; + +#[ApiServiceMetadata(new \Bitrix24\SDK\Core\Credentials\Scope(['sale']))] +class Payment extends \Bitrix24\SDK\Services\AbstractService +{ + public function __construct(public Batch $batch, CoreInterface $core, LoggerInterface $logger) + { + parent::__construct($core, $logger); + } + + #[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 + { + $response = $this->core->call('sale.payment.add', [ + 'fields' => $fields + ]); + return new PaymentAddedResult($response); + } + + #[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 + { + $response = $this->core->call('sale.payment.update', [ + 'id' => $id, + 'fields' => $fields + ]); + return new PaymentUpdatedResult($response); + } + + #[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 + { + $response = $this->core->call('sale.payment.get', [ + 'id' => $id + ]); + return new PaymentResult($response); + } + + #[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 $filter = [], array $order = [], array $select = [], int $start = 0): PaymentsResult + { + $response = $this->core->call('sale.payment.list', [ + 'filter' => $filter, + 'order' => $order, + 'select' => $select, + 'start' => $start + ]); + return new PaymentsResult($response); + } + + #[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 + { + $response = $this->core->call('sale.payment.delete', [ + 'id' => $id + ]); + return new DeletedItemResult($response); + } + + #[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 + { + $response = $this->core->call('sale.payment.getFields', []); + return new PaymentFieldsResult($response); + } +} diff --git a/src/Services/Sale/SaleServiceBuilder.php b/src/Services/Sale/SaleServiceBuilder.php index cfa1aaa8..d1fa26d0 100644 --- a/src/Services/Sale/SaleServiceBuilder.php +++ b/src/Services/Sale/SaleServiceBuilder.php @@ -128,6 +128,26 @@ public function personType(): PersonType\Service\PersonType return $this->serviceCache[__METHOD__]; } + + /** + * Payment service (sale.payment.*) + */ + public function payment(): \Bitrix24\SDK\Services\Sale\Payment\Service\Payment + { + if (!isset($this->serviceCache[__METHOD__])) { + $batch = new \Bitrix24\SDK\Services\Sale\Payment\Batch( + $this->core, + $this->log + ); + $this->serviceCache[__METHOD__] = new \Bitrix24\SDK\Services\Sale\Payment\Service\Payment( + new \Bitrix24\SDK\Services\Sale\Payment\Service\Batch($batch, $this->log), + $this->core, + $this->log + ); + } + + return $this->serviceCache[__METHOD__]; + } public function propertyVariant(): PropertyVariant { From 2e03f066bb3169da3e041254c589122ab8b5d5c0 Mon Sep 17 00:00:00 2001 From: Sally Fancen Date: Tue, 9 Sep 2025 16:09:32 +0400 Subject: [PATCH 2/7] remove batch-methods --- src/Services/Sale/Payment/Batch.php | 82 ----------- .../Result/AddedPaymentBatchResult.php | 34 ----- .../Result/UpdatedPaymentBatchResult.php | 34 ----- src/Services/Sale/Payment/Service/Batch.php | 138 ------------------ src/Services/Sale/Payment/Service/Payment.php | 136 +++++++++++++---- src/Services/Sale/SaleServiceBuilder.php | 9 +- 6 files changed, 106 insertions(+), 327 deletions(-) delete mode 100644 src/Services/Sale/Payment/Batch.php delete mode 100644 src/Services/Sale/Payment/Result/AddedPaymentBatchResult.php delete mode 100644 src/Services/Sale/Payment/Result/UpdatedPaymentBatchResult.php delete mode 100644 src/Services/Sale/Payment/Service/Batch.php diff --git a/src/Services/Sale/Payment/Batch.php b/src/Services/Sale/Payment/Batch.php deleted file mode 100644 index 5055f785..00000000 --- a/src/Services/Sale/Payment/Batch.php +++ /dev/null @@ -1,82 +0,0 @@ - - * - * 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; - -use Bitrix24\SDK\Core\Commands\Command; -use Bitrix24\SDK\Core\Commands\CommandCollection; -use Bitrix24\SDK\Core\Contracts\CoreInterface; -use Bitrix24\SDK\Core\Exceptions\BaseException; -use Bitrix24\SDK\Core\Exceptions\InvalidArgumentException; -use Bitrix24\SDK\Core\Response\DTO\Pagination; -use Bitrix24\SDK\Core\Response\DTO\ResponseData; -use Bitrix24\SDK\Core\Response\DTO\Result; -use Bitrix24\SDK\Core\Response\DTO\Time; -use Bitrix24\SDK\Core\Response\Response; -use Generator; -use Psr\Log\LoggerInterface; - -/** - * Class Batch - * - * @package Bitrix24\SDK\Services\Sale\Payment - */ -class Batch extends \Bitrix24\SDK\Core\Batch -{ - /** - * Delete entity items with batch call - * - * - * @return Generator|ResponseData[] - * @throws \Bitrix24\SDK\Core\Exceptions\BaseException - */ - public function deleteEntityItems( - string $apiMethod, - array $entityItemId, - ?array $additionalParameters = null - ): Generator { - $this->logger->debug( - 'deleteEntityItems.start', - [ - 'apiMethod' => $apiMethod, - 'entityItemId' => $entityItemId, - 'additionalParameters' => $additionalParameters - ] - ); - - // create commands - $commandParams = []; - foreach ($entityItemId as $id) { - $commandParams[] = ['id' => $id]; - } - - // Build commands - $commands = new CommandCollection(); - foreach ($commandParams as $index => $commandParam) { - $commands->add( - new Command( - $apiMethod, - $commandParam, - sprintf('%s_%s', $apiMethod, $index) - ) - ); - } - - // Process batch commands and return results - foreach ($this->processBatch($commands) as $item) { - yield $item->getId() => $item->getResponseData(); - } - - $this->logger->debug('deleteEntityItems.finish'); - } -} diff --git a/src/Services/Sale/Payment/Result/AddedPaymentBatchResult.php b/src/Services/Sale/Payment/Result/AddedPaymentBatchResult.php deleted file mode 100644 index 5f5d594a..00000000 --- a/src/Services/Sale/Payment/Result/AddedPaymentBatchResult.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * 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\AddedItemBatchResult; -use Bitrix24\SDK\Core\Exceptions\BaseException; - -/** - * Class AddedPaymentBatchResult - * Represents a result of batch add payments operation - * - * @package Bitrix24\SDK\Services\Sale\Payment\Result - */ -class AddedPaymentBatchResult extends AddedItemBatchResult -{ - /** - * @throws BaseException - */ - public function getId(): int - { - return (int)$this->getResponseData()->getResult()['payment']['id']; - } -} diff --git a/src/Services/Sale/Payment/Result/UpdatedPaymentBatchResult.php b/src/Services/Sale/Payment/Result/UpdatedPaymentBatchResult.php deleted file mode 100644 index d247cf7a..00000000 --- a/src/Services/Sale/Payment/Result/UpdatedPaymentBatchResult.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * 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\UpdatedItemBatchResult; -use Bitrix24\SDK\Core\Exceptions\BaseException; - -/** - * Class UpdatedPaymentBatchResult - * Represents a result of batch update payments operation - * - * @package Bitrix24\SDK\Services\Sale\Payment\Result - */ -class UpdatedPaymentBatchResult extends UpdatedItemBatchResult -{ - /** - * @throws BaseException - */ - public function isSuccess(): bool - { - return (bool)$this->getResponseData()->getResult()['payment']; - } -} diff --git a/src/Services/Sale/Payment/Service/Batch.php b/src/Services/Sale/Payment/Service/Batch.php deleted file mode 100644 index 77a5bd20..00000000 --- a/src/Services/Sale/Payment/Service/Batch.php +++ /dev/null @@ -1,138 +0,0 @@ - - * - * 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\ApiBatchMethodMetadata; -use Bitrix24\SDK\Attributes\ApiBatchServiceMetadata; -use Bitrix24\SDK\Core\Contracts\BatchOperationsInterface; -use Bitrix24\SDK\Core\Credentials\Scope; -use Bitrix24\SDK\Core\Exceptions\BaseException; -use Bitrix24\SDK\Core\Result\DeletedItemBatchResult; -use Bitrix24\SDK\Services\Sale\Payment\Result\UpdatedPaymentBatchResult; -use Bitrix24\SDK\Services\Sale\Payment\Result\AddedPaymentBatchResult; -use Bitrix24\SDK\Services\Sale\Payment\Result\PaymentItemResult; -use Generator; -use Psr\Log\LoggerInterface; - -#[ApiBatchServiceMetadata(new Scope(['sale']))] -class Batch -{ - /** - * Batch constructor. - */ - public function __construct(protected BatchOperationsInterface $batch, protected LoggerInterface $log) - { - } - - /** - * Batch add method for creating multiple payments - * - * @param array $payments Array of payment fields - * - * @return Generator - * @throws BaseException - */ - #[ApiBatchMethodMetadata( - 'sale.payment.add', - 'https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-add.html', - 'Creates a new payment' - )] - public function add(array $payments): Generator - { - $fields = []; - foreach ($payments as $payment) { - $fields[] = [ - 'fields' => $payment - ]; - } - - foreach ($this->batch->addEntityItems('sale.payment.add', $fields) as $key => $item) { - yield $key => new AddedPaymentBatchResult($item); - } - } - - /** - * Batch update method for updating multiple payments - * - * Update elements in array with structure - * element_id => [ // payment id - * 'fields' => [] // payment fields to update - * ] - * - * @param array $paymentsData - * @return Generator - * @throws BaseException - */ - #[ApiBatchMethodMetadata( - 'sale.payment.update', - 'https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-update.html', - 'Updates an existing payment' - )] - public function update(array $paymentsData): Generator - { - foreach ($this->batch->updateEntityItems('sale.payment.update', $paymentsData) as $key => $item) { - yield $key => new UpdatedPaymentBatchResult($item); - } - } - - /** - * Batch list method for retrieving multiple payments - * - * @param array $filter Filter criteria - * @param array $order Sort order - * @param array $select Fields to select - * @param int|null $limit Maximum number of items to return - * - * @return Generator|PaymentItemResult[] - * @throws BaseException - */ - #[ApiBatchMethodMetadata( - 'sale.payment.list', - 'https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-list.html', - 'Retrieves a list of payments' - )] - public function list(array $filter = [], array $order = [], array $select = [], ?int $limit = null): Generator - { - foreach ($this->batch->getTraversableList( - 'sale.payment.list', - $order, - $filter, - $select, - $limit - ) as $key => $item) { - yield $key => new PaymentItemResult($item); - } - } - - /** - * Batch delete payments - * - * @param int[] $paymentIds - * - * @return Generator - * @throws BaseException - */ - #[ApiEndpointMetadata( - 'sale.payment.delete', - 'https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-delete.html', - 'Batch delete payments.' - )] - public function delete(array $paymentIds): Generator - { - foreach ($this->batch->deleteEntityItems('sale.payment.delete', $paymentIds) as $key => $item) { - yield $key => new DeletedItemBatchResult($item); - } - } -} diff --git a/src/Services/Sale/Payment/Service/Payment.php b/src/Services/Sale/Payment/Service/Payment.php index 77d3a480..9aacd6cc 100644 --- a/src/Services/Sale/Payment/Service/Payment.php +++ b/src/Services/Sale/Payment/Service/Payment.php @@ -13,25 +13,39 @@ 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; -use Bitrix24\SDK\Attributes\ApiServiceMetadata; -use Bitrix24\SDK\Attributes\ApiEndpointMetadata; -#[ApiServiceMetadata(new \Bitrix24\SDK\Core\Credentials\Scope(['sale']))] -class Payment extends \Bitrix24\SDK\Services\AbstractService +#[ApiServiceMetadata(new Scope(['sale']))] +class Payment extends AbstractService { - public function __construct(public Batch $batch, CoreInterface $core, LoggerInterface $logger) + 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', @@ -39,12 +53,24 @@ public function __construct(public Batch $batch, CoreInterface $core, LoggerInte )] public function add(array $fields): PaymentAddedResult { - $response = $this->core->call('sale.payment.add', [ - 'fields' => $fields - ]); - return new PaymentAddedResult($response); + 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', @@ -52,13 +78,24 @@ public function add(array $fields): PaymentAddedResult )] public function update(int $id, array $fields): PaymentUpdatedResult { - $response = $this->core->call('sale.payment.update', [ - 'id' => $id, - 'fields' => $fields - ]); - return new PaymentUpdatedResult($response); + 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', @@ -66,28 +103,53 @@ public function update(int $id, array $fields): PaymentUpdatedResult )] public function get(int $id): PaymentResult { - $response = $this->core->call('sale.payment.get', [ - 'id' => $id - ]); - return new PaymentResult($response); + 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 $filter = [], array $order = [], array $select = [], int $start = 0): PaymentsResult + public function list(array $select = [], array $filter = [], array $order = [], int $start = 0): PaymentsResult { - $response = $this->core->call('sale.payment.list', [ - 'filter' => $filter, - 'order' => $order, - 'select' => $select, - 'start' => $start - ]); - return new PaymentsResult($response); + 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', @@ -95,12 +157,21 @@ public function list(array $filter = [], array $order = [], array $select = [], )] public function delete(int $id): DeletedItemResult { - $response = $this->core->call('sale.payment.delete', [ - 'id' => $id - ]); - return new DeletedItemResult($response); + 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', @@ -108,7 +179,8 @@ public function delete(int $id): DeletedItemResult )] public function getFields(): PaymentFieldsResult { - $response = $this->core->call('sale.payment.getFields', []); - return new PaymentFieldsResult($response); + return new PaymentFieldsResult( + $this->core->call('sale.payment.getFields', []) + ); } } diff --git a/src/Services/Sale/SaleServiceBuilder.php b/src/Services/Sale/SaleServiceBuilder.php index d1fa26d0..39b5c9e6 100644 --- a/src/Services/Sale/SaleServiceBuilder.php +++ b/src/Services/Sale/SaleServiceBuilder.php @@ -132,15 +132,10 @@ public function personType(): PersonType\Service\PersonType /** * Payment service (sale.payment.*) */ - public function payment(): \Bitrix24\SDK\Services\Sale\Payment\Service\Payment + public function payment(): Payment\Service\Payment { if (!isset($this->serviceCache[__METHOD__])) { - $batch = new \Bitrix24\SDK\Services\Sale\Payment\Batch( - $this->core, - $this->log - ); - $this->serviceCache[__METHOD__] = new \Bitrix24\SDK\Services\Sale\Payment\Service\Payment( - new \Bitrix24\SDK\Services\Sale\Payment\Service\Batch($batch, $this->log), + $this->serviceCache[__METHOD__] = new Payment\Service\Payment( $this->core, $this->log ); From d60b3f531f211eb8fe4e44c30d30bc9a424f5504 Mon Sep 17 00:00:00 2001 From: Sally Fancen Date: Tue, 9 Sep 2025 17:14:36 +0400 Subject: [PATCH 3/7] add tests; run tests and linters --- Makefile | 4 + phpunit.xml.dist | 3 + .../Sale/Payment/Result/PaymentItemResult.php | 16 +- .../Sale/Payment/Result/PaymentsResult.php | 2 +- src/Services/Sale/Payment/Service/Payment.php | 2 +- src/Services/Sale/SaleServiceBuilder.php | 2 +- .../Sale/Payment/Service/PaymentTest.php | 330 ++++++++++++++++++ 7 files changed, 348 insertions(+), 11 deletions(-) create mode 100644 tests/Integration/Services/Sale/Payment/Service/PaymentTest.php 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/PaymentItemResult.php b/src/Services/Sale/Payment/Result/PaymentItemResult.php index eddc2084..f7dcc5c8 100644 --- a/src/Services/Sale/Payment/Result/PaymentItemResult.php +++ b/src/Services/Sale/Payment/Result/PaymentItemResult.php @@ -36,27 +36,27 @@ * @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 string|null $externalPayment External payment flag + * @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 string|null $isReturn Return processed flag - * @property-read string|null $marked Problem marking flag + * @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 string|null $paid Payment status + * @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 string|null $paySystemIsCash Is cash payment system + * @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 string|null $priceCod Cost of payment upon delivery + * @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 string|null $psStatus Payment system status + * @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 @@ -64,7 +64,7 @@ * @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 string|null $updated1c Updated via QuickBooks flag + * @property-read bool|null $updated1c Updated via QuickBooks flag * @property-read string|null $version1c Payment document version * @property-read string|null $xmlId External identifier */ diff --git a/src/Services/Sale/Payment/Result/PaymentsResult.php b/src/Services/Sale/Payment/Result/PaymentsResult.php index 59404636..4e25988f 100644 --- a/src/Services/Sale/Payment/Result/PaymentsResult.php +++ b/src/Services/Sale/Payment/Result/PaymentsResult.php @@ -23,7 +23,7 @@ class PaymentsResult extends AbstractResult { /** * Returns an array of payment items - * + * * @return PaymentItemResult[] array of payment item results */ public function getPayments(): array diff --git a/src/Services/Sale/Payment/Service/Payment.php b/src/Services/Sale/Payment/Service/Payment.php index 9aacd6cc..a13ba569 100644 --- a/src/Services/Sale/Payment/Service/Payment.php +++ b/src/Services/Sale/Payment/Service/Payment.php @@ -146,7 +146,7 @@ public function list(array $select = [], array $filter = [], array $order = [], * @link https://apidocs.bitrix24.com/api-reference/sale/payment/sale-payment-delete.html * * @param int $id Payment identifier - * + * * @throws BaseException * @throws TransportException */ diff --git a/src/Services/Sale/SaleServiceBuilder.php b/src/Services/Sale/SaleServiceBuilder.php index 39b5c9e6..8c7e9a5b 100644 --- a/src/Services/Sale/SaleServiceBuilder.php +++ b/src/Services/Sale/SaleServiceBuilder.php @@ -128,7 +128,7 @@ public function personType(): PersonType\Service\PersonType return $this->serviceCache[__METHOD__]; } - + /** * Payment service (sale.payment.*) */ 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..3f9e311c --- /dev/null +++ b/tests/Integration/Services/Sale/Payment/Service/PaymentTest.php @@ -0,0 +1,330 @@ + + * + * 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')] +#[\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); + } + + /** + * 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 = $result ?? []; + + if (empty($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 + } + } + + 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); + } + + /** + * @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); + } +} From 83af31796e40420803c483bbcb0128505ecef659 Mon Sep 17 00:00:00 2001 From: Sally Fancen Date: Tue, 9 Sep 2025 17:20:19 +0400 Subject: [PATCH 4/7] run phpstan --- tests/Integration/Services/Sale/Payment/Service/PaymentTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Integration/Services/Sale/Payment/Service/PaymentTest.php b/tests/Integration/Services/Sale/Payment/Service/PaymentTest.php index 3f9e311c..4b1fe128 100644 --- a/tests/Integration/Services/Sale/Payment/Service/PaymentTest.php +++ b/tests/Integration/Services/Sale/Payment/Service/PaymentTest.php @@ -100,7 +100,7 @@ protected function getPaySystemId(): int ]); $result = $response->getResponseData()->getResult(); - $paySystems = $result ?? []; + $paySystems = (is_array($result)) ? $result : []; if (empty($paySystems)) { $this->markTestSkipped('No payment systems available for testing'); From b57afdf52778a21bdaab986c93f3d833c8b9fb94 Mon Sep 17 00:00:00 2001 From: Sally Fancen Date: Tue, 9 Sep 2025 17:24:03 +0400 Subject: [PATCH 5/7] run rector --- tests/Integration/Services/Sale/Payment/Service/PaymentTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Integration/Services/Sale/Payment/Service/PaymentTest.php b/tests/Integration/Services/Sale/Payment/Service/PaymentTest.php index 4b1fe128..ad2b51d2 100644 --- a/tests/Integration/Services/Sale/Payment/Service/PaymentTest.php +++ b/tests/Integration/Services/Sale/Payment/Service/PaymentTest.php @@ -102,7 +102,7 @@ protected function getPaySystemId(): int $result = $response->getResponseData()->getResult(); $paySystems = (is_array($result)) ? $result : []; - if (empty($paySystems)) { + if ($paySystems === []) { $this->markTestSkipped('No payment systems available for testing'); } From 6b47750cd233c1bde2c5a8ad66529343f5934fea Mon Sep 17 00:00:00 2001 From: Sally Fancen Date: Wed, 10 Sep 2025 09:28:35 +0400 Subject: [PATCH 6/7] update changelog --- CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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 From 922898d2aea8a859513aa3d1a9dccb1fb9a7b5fe Mon Sep 17 00:00:00 2001 From: Sally Fancen Date: Wed, 10 Sep 2025 13:56:38 +0400 Subject: [PATCH 7/7] add annotations tests --- .../Sale/Payment/Service/PaymentTest.php | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/tests/Integration/Services/Sale/Payment/Service/PaymentTest.php b/tests/Integration/Services/Sale/Payment/Service/PaymentTest.php index ad2b51d2..e0c22ee8 100644 --- a/tests/Integration/Services/Sale/Payment/Service/PaymentTest.php +++ b/tests/Integration/Services/Sale/Payment/Service/PaymentTest.php @@ -36,6 +36,8 @@ #[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 { @@ -65,6 +67,23 @@ protected function tearDown(): void $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 */ @@ -138,23 +157,6 @@ protected function deleteTestOrder(int $id): void } } - 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); - } - /** * @throws BaseException * @throws TransportException