From 3eebc00ef25e7170ced6d3c0da98e8581c3cbc5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D1=82=D0=BE=D0=BD=20=D0=9D=2E=20=D0=9D=D0=B8?= =?UTF-8?q?=D0=BA=D0=BE=D0=BB=D0=B0=D0=B5=D0=B2?= Date: Tue, 1 Dec 2020 15:39:32 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BD=D0=B0=D1=8F=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D1=8F?= =?UTF-8?q?=20SDK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 + LICENSE.md | 22 + README.en.md | 63 + README.md | 63 + composer.json | 27 + lib/Client.php | 768 ++++++++++ lib/Client/ApiClientInterface.php | 79 + lib/Client/BaseClient.php | 389 +++++ lib/Client/CurlClient.php | 527 +++++++ lib/Client/UserAgent.php | 320 ++++ lib/Common/AbstractEnum.php | 74 + lib/Common/AbstractObject.php | 243 +++ lib/Common/AbstractPaymentRequest.php | 223 +++ lib/Common/AbstractPaymentRequestBuilder.php | 336 ++++ lib/Common/AbstractRequest.php | 72 + lib/Common/AbstractRequestBuilder.php | 119 ++ .../Exceptions/ApiConnectionException.php | 32 + lib/Common/Exceptions/ApiException.php | 73 + lib/Common/Exceptions/AuthorizeException.php | 32 + .../Exceptions/BadApiRequestException.php | 64 + .../EmptyPropertyValueException.php | 31 + .../Exceptions/ExtensionNotFoundException.php | 46 + lib/Common/Exceptions/ForbiddenException.php | 64 + lib/Common/Exceptions/InternalServerError.php | 64 + .../Exceptions/InvalidPropertyException.php | 55 + .../InvalidPropertyValueException.php | 58 + .../InvalidPropertyValueTypeException.php | 62 + .../Exceptions/InvalidRequestException.php | 62 + lib/Common/Exceptions/JsonException.php | 46 + lib/Common/Exceptions/NotFoundException.php | 64 + .../ResponseProcessingException.php | 56 + .../Exceptions/TooManyRequestsException.php | 64 + .../Exceptions/UnauthorizedException.php | 64 + lib/Common/HttpVerb.php | 48 + lib/Common/LoggerWrapper.php | 192 +++ lib/Common/ResponseObject.php | 73 + lib/Common/legacy_json_serializable.php | 31 + lib/Helpers/Config/ConfigurationLoader.php | 52 + .../Config/ConfigurationLoaderInterface.php | 40 + lib/Helpers/Random.php | 166 ++ lib/Helpers/RawHeadersParser.php | 63 + lib/Helpers/StringObject.php | 58 + lib/Helpers/TypeCast.php | 126 ++ lib/Helpers/UUID.php | 23 + lib/Model/Airline.php | 256 ++++ lib/Model/AirlineInterface.php | 59 + lib/Model/AmountInterface.php | 67 + lib/Model/AuthorizationDetails.php | 127 ++ lib/Model/AuthorizationDetailsInterface.php | 51 + lib/Model/CancellationDetails.php | 127 ++ lib/Model/CancellationDetailsInterface.php | 51 + lib/Model/CancellationDetailsPartyCode.php | 57 + lib/Model/CancellationDetailsReasonCode.php | 77 + .../Confirmation/AbstractConfirmation.php | 83 + .../ConfirmationCodeVerification.php | 42 + .../Confirmation/ConfirmationDeepLink.php | 42 + .../Confirmation/ConfirmationEmbedded.php | 68 + .../Confirmation/ConfirmationExternal.php | 43 + .../Confirmation/ConfirmationFactory.php | 92 ++ lib/Model/Confirmation/ConfirmationQr.php | 69 + .../Confirmation/ConfirmationRedirect.php | 143 ++ .../AbstractConfirmationAttributes.php | 112 ++ ...ConfirmationAttributesCodeVerification.php | 42 + .../ConfirmationAttributesDeepLink.php | 42 + .../ConfirmationAttributesEmbedded.php | 37 + .../ConfirmationAttributesExternal.php | 42 + .../ConfirmationAttributesFactory.php | 92 ++ .../ConfirmationAttributesQr.php | 37 + .../ConfirmationAttributesRedirect.php | 109 ++ lib/Model/ConfirmationType.php | 59 + lib/Model/CurrencyCode.php | 53 + lib/Model/Leg.php | 129 ++ lib/Model/LegInterface.php | 45 + lib/Model/Metadata.php | 59 + lib/Model/MonetaryAmount.php | 224 +++ .../Notification/AbstractNotification.php | 138 ++ .../Notification/NotificationCanceled.php | 99 ++ .../Notification/NotificationFactory.php | 63 + .../NotificationRefundSucceeded.php | 98 ++ .../Notification/NotificationSucceeded.php | 105 ++ .../NotificationWaitingForCapture.php | 109 ++ lib/Model/NotificationEventType.php | 44 + lib/Model/NotificationType.php | 38 + lib/Model/Passenger.php | 112 ++ lib/Model/PassengerInterface.php | 41 + lib/Model/Payment.php | 704 +++++++++ lib/Model/PaymentData/AbstractPaymentData.php | 78 + .../PaymentData/B2b/Sberbank/VatData.php | 167 ++ .../B2b/Sberbank/VatDataInterface.php | 60 + .../PaymentData/B2b/Sberbank/VatDataRate.php | 54 + .../PaymentData/B2b/Sberbank/VatDataType.php | 51 + lib/Model/PaymentData/PaymentDataAlfabank.php | 74 + lib/Model/PaymentData/PaymentDataApplePay.php | 78 + .../PaymentData/PaymentDataB2bSberbank.php | 120 ++ lib/Model/PaymentData/PaymentDataBankCard.php | 80 + .../PaymentData/PaymentDataBankCardCard.php | 239 +++ lib/Model/PaymentData/PaymentDataCash.php | 81 + lib/Model/PaymentData/PaymentDataFactory.php | 95 ++ .../PaymentData/PaymentDataGooglePay.php | 108 ++ .../PaymentData/PaymentDataInstallments.php | 40 + .../PaymentData/PaymentDataMobileBalance.php | 82 + lib/Model/PaymentData/PaymentDataQiwi.php | 81 + lib/Model/PaymentData/PaymentDataSberbank.php | 86 ++ .../PaymentData/PaymentDataTinkoffBank.php | 37 + lib/Model/PaymentData/PaymentDataWebmoney.php | 41 + lib/Model/PaymentData/PaymentDataWechat.php | 40 + lib/Model/PaymentData/PaymentDataYooMoney.php | 40 + lib/Model/PaymentInterface.php | 172 +++ .../PaymentMethod/AbstractPaymentMethod.php | 162 ++ .../B2b/Sberbank/PayerBankDetails.php | 243 +++ .../Sberbank/PayerBankDetailsInterface.php | 101 ++ lib/Model/PaymentMethod/BankCardSource.php | 26 + .../PaymentMethod/PaymentMethodAlfaBank.php | 74 + .../PaymentMethod/PaymentMethodApplePay.php | 42 + .../PaymentMethodB2bSberbank.php | 124 ++ .../PaymentMethod/PaymentMethodBankCard.php | 343 +++++ .../PaymentMethod/PaymentMethodCardType.php | 63 + lib/Model/PaymentMethod/PaymentMethodCash.php | 42 + .../PaymentMethod/PaymentMethodFactory.php | 114 ++ .../PaymentMethod/PaymentMethodGooglePay.php | 42 + .../PaymentMethodInstallments.php | 42 + .../PaymentMethodMobileBalance.php | 83 + lib/Model/PaymentMethod/PaymentMethodPsb.php | 37 + lib/Model/PaymentMethod/PaymentMethodQiwi.php | 42 + .../PaymentMethod/PaymentMethodSberbank.php | 87 ++ .../PaymentMethodTinkoffBank.php | 36 + .../PaymentMethod/PaymentMethodWebmoney.php | 42 + .../PaymentMethod/PaymentMethodWechat.php | 40 + .../PaymentMethod/PaymentMethodYooMoney.php | 85 ++ lib/Model/PaymentMethodType.php | 85 ++ lib/Model/PaymentStatus.php | 54 + lib/Model/Receipt.php | 406 +++++ lib/Model/Receipt/AgentType.php | 28 + lib/Model/Receipt/PaymentMode.php | 50 + lib/Model/Receipt/PaymentSubject.php | 72 + lib/Model/Receipt/ReceiptItemAmount.php | 220 +++ lib/Model/Receipt/SettlementType.php | 44 + lib/Model/ReceiptCustomer.php | 228 +++ lib/Model/ReceiptCustomerInterface.php | 76 + lib/Model/ReceiptInterface.php | 90 ++ lib/Model/ReceiptItem.php | 690 +++++++++ lib/Model/ReceiptItemInterface.php | 138 ++ lib/Model/ReceiptRegistrationStatus.php | 63 + lib/Model/ReceiptType.php | 55 + lib/Model/Recipient.php | 122 ++ lib/Model/RecipientInterface.php | 57 + lib/Model/Refund.php | 384 +++++ lib/Model/RefundInterface.php | 100 ++ lib/Model/RefundStatus.php | 51 + lib/Model/Requestor.php | 140 ++ lib/Model/RequestorInterface.php | 30 + lib/Model/Settlement.php | 152 ++ lib/Model/SettlementInterface.php | 50 + lib/Model/Source.php | 187 +++ lib/Model/SourceInterface.php | 95 ++ lib/Model/Supplier.php | 129 ++ lib/Model/SupplierInterface.php | 68 + lib/Model/Transfer.php | 222 +++ lib/Model/TransferInterface.php | 101 ++ lib/Model/TransferStatus.php | 55 + lib/Model/Webhook/Webhook.php | 117 ++ .../Payments/AbstractPaymentResponse.php | 218 +++ lib/Request/Payments/CreatePaymentRequest.php | 586 +++++++ .../Payments/CreatePaymentRequestBuilder.php | 351 +++++ .../CreatePaymentRequestInterface.php | 223 +++ .../CreatePaymentRequestSerializer.php | 359 +++++ .../Payments/CreatePaymentResponse.php | 35 + .../Payments/Payment/CancelResponse.php | 37 + .../Payments/Payment/CreateCaptureRequest.php | 74 + .../Payment/CreateCaptureRequestBuilder.php | 75 + .../Payment/CreateCaptureRequestInterface.php | 79 + .../CreateCaptureRequestSerializer.php | 155 ++ .../Payment/CreateCaptureResponse.php | 37 + lib/Request/Payments/PaymentResponse.php | 35 + lib/Request/Payments/PaymentsRequest.php | 669 ++++++++ .../Payments/PaymentsRequestBuilder.php | 248 +++ .../Payments/PaymentsRequestInterface.php | 181 +++ .../Payments/PaymentsRequestSerializer.php | 76 + lib/Request/Payments/PaymentsResponse.php | 186 +++ .../Receipts/AbstractReceiptResponse.php | 576 +++++++ .../Receipts/CreatePostReceiptRequest.php | 434 ++++++ .../CreatePostReceiptRequestBuilder.php | 209 +++ .../CreatePostReceiptRequestInterface.php | 166 ++ .../CreatePostReceiptRequestSerializer.php | 95 ++ .../Receipts/PaymentReceiptResponse.php | 89 ++ .../Receipts/ReceiptResponseFactory.php | 74 + .../Receipts/ReceiptResponseInterface.php | 102 ++ lib/Request/Receipts/ReceiptResponseItem.php | 387 +++++ .../Receipts/ReceiptResponseItemInterface.php | 82 + lib/Request/Receipts/ReceiptsRequest.php | 509 ++++++ .../Receipts/ReceiptsRequestBuilder.php | 195 +++ .../Receipts/ReceiptsRequestInterface.php | 153 ++ .../Receipts/ReceiptsRequestSerializer.php | 73 + lib/Request/Receipts/ReceiptsResponse.php | 120 ++ .../Receipts/RefundReceiptResponse.php | 89 ++ .../Receipts/SimpleReceiptResponse.php | 46 + .../Refunds/AbstractRefundResponse.php | 67 + lib/Request/Refunds/CreateRefundRequest.php | 208 +++ .../Refunds/CreateRefundRequestBuilder.php | 118 ++ .../Refunds/CreateRefundRequestInterface.php | 90 ++ .../Refunds/CreateRefundRequestSerializer.php | 136 ++ lib/Request/Refunds/CreateRefundResponse.php | 35 + lib/Request/Refunds/RefundResponse.php | 35 + lib/Request/Refunds/RefundsRequest.php | 462 ++++++ lib/Request/Refunds/RefundsRequestBuilder.php | 181 +++ .../Refunds/RefundsRequestInterface.php | 128 ++ .../Refunds/RefundsRequestSerializer.php | 72 + lib/Request/Refunds/RefundsResponse.php | 90 ++ lib/Request/Webhook/WebhookListResponse.php | 66 + lib/autoload.php | 47 + lib/configuration.json | 3 + phpunit.xml.dist | 28 + tests/AutoloadTest.php | 65 + tests/Client/ClientTest.php | 1360 +++++++++++++++++ tests/Client/CurlClientTest.php | 91 ++ tests/Client/UserAgentTest.php | 122 ++ .../fixtures/cancelPaymentFixtures.json | 35 + .../fixtures/capturePaymentFixtures.json | 39 + .../createPaymentErrorsGeneralFixtures.json | 34 + .../fixtures/createPaymentFixtures.json | 39 + .../fixtures/createReceiptFixtures.json | 49 + .../Client/fixtures/createRefundFixtures.json | 17 + .../Client/fixtures/getPaymentsFixtures.json | 52 + .../Client/fixtures/paymentInfoFixtures.json | 36 + .../fixtures/paymentOptionsFixtures.json | 19 + tests/Client/fixtures/refundInfoFixtures.json | 17 + .../Client/fixtures/refundsInfoFixtures.json | 27 + tests/Common/AbstractEnumTest.php | 67 + tests/Common/AbstractObjectTest.php | 236 +++ tests/Common/AbstractRequestBuilderTest.php | 139 ++ .../AbstractApiRequestExceptionTest.php | 178 +++ tests/Common/Exceptions/ApiExceptionTest.php | 74 + .../Exceptions/AuthorizeExceptionTest.php | 13 + .../Exceptions/BadApiRequestExceptionTest.php | 18 + .../EmptyPropertyValueExceptionTest.php | 18 + .../ExtensionNotFoundExceptionTest.php | 41 + .../Exceptions/ForbiddenExceptionTest.php | 18 + .../Exceptions/InternalServerErrorTest.php | 18 + .../InvalidPropertyExceptionTest.php | 39 + .../InvalidPropertyValueExceptionTest.php | 39 + .../InvalidPropertyValueTypeExceptionTest.php | 49 + .../InvalidRequestExceptionTest.php | 39 + tests/Common/Exceptions/JsonExceptionTest.php | 36 + .../Exceptions/NotFoundExceptionTest.php | 18 + .../ResponseProcessingExceptionTest.php | 134 ++ .../TooManyRequestsExceptionTest.php | 18 + .../Exceptions/UnauthorizedExceptionTest.php | 18 + tests/Common/LegacyJsonInterfaceTest.php | 21 + tests/Common/LoggerWrapperTest.php | 125 ++ .../Config/ConfigurationLoaderTest.php | 33 + tests/Helpers/Config/test_config.json | 4 + tests/Helpers/RandomTest.php | 192 +++ tests/Helpers/RawHeadersParserTest.php | 90 ++ tests/Helpers/StringObjectTest.php | 27 + tests/Helpers/TypeCastTest.php | 151 ++ tests/Helpers/UUIDTest.php | 16 + tests/Model/AirlineTest.php | 216 +++ tests/Model/AuthorizationDetailsTest.php | 152 ++ tests/Model/CancellationDetailsTest.php | 148 ++ .../Confirmation/AbstractConfirmationTest.php | 63 + .../ConfirmationCodeVerificationTest.php | 25 + .../Confirmation/ConfirmationDeepLinkTest.php | 25 + .../Confirmation/ConfirmationEmbeddedTest.php | 71 + .../Confirmation/ConfirmationExternalTest.php | 26 + .../Confirmation/ConfirmationFactoryTest.php | 175 +++ .../Model/Confirmation/ConfirmationQrTest.php | 152 ++ .../Confirmation/ConfirmationRedirectTest.php | 288 ++++ .../AbstractConfirmationAttributesTest.php | 122 ++ ...irmationAttributesCodeVerificationTest.php | 25 + .../ConfirmationAttributesDeepLinkTest.php | 25 + .../ConfirmationAttributesEmbeddedTest.php | 29 + .../ConfirmationAttributesExternalTest.php | 25 + .../ConfirmationAttributesFactoryTest.php | 148 ++ .../ConfirmationAttributesQrTest.php | 25 + .../ConfirmationAttributesRedirectTest.php | 209 +++ tests/Model/LegTest.php | 109 ++ tests/Model/MetadataTest.php | 89 ++ tests/Model/MonetaryAmountTest.php | 335 ++++ .../Notification/AbstractNotificationTest.php | 146 ++ .../Notification/NotificationCanceledTest.php | 117 ++ .../Notification/NotificationFactoryTest.php | 214 +++ .../NotificationRefundSucceededTest.php | 90 ++ .../NotificationSucceededTest.php | 117 ++ .../NotificationWaitingForCaptureTest.php | 113 ++ tests/Model/PassengerTest.php | 134 ++ .../AbstractPaymentDataApplePayTest.php | 115 ++ .../AbstractPaymentDataGooglePayTest.php | 93 ++ .../AbstractPaymentDataPhoneTest.php | 85 ++ .../PaymentData/AbstractPaymentDataTest.php | 59 + .../PaymentData/B2b/Sberbank/VatDataTest.php | 287 ++++ .../PaymentData/PaymentDataAlfabankTest.php | 90 ++ .../PaymentData/PaymentDataApplePayTest.php | 25 + .../PaymentDataB2bSberbankTest.php | 195 +++ .../PaymentDataBankCardCardTest.php | 384 +++++ .../PaymentData/PaymentDataBankCardTest.php | 119 ++ .../Model/PaymentData/PaymentDataCashTest.php | 56 + .../PaymentData/PaymentDataFactoryTest.php | 180 +++ .../PaymentData/PaymentDataGooglePayTest.php | 25 + .../PaymentDataInstallmentsTest.php | 25 + .../PaymentDataMobileBalanceTest.php | 25 + .../Model/PaymentData/PaymentDataQiwiTest.php | 25 + .../PaymentData/PaymentDataSberbankTest.php | 25 + .../PaymentDataTinkoffBankTest.php | 30 + .../PaymentData/PaymentDataWebmoneyTest.php | 25 + .../PaymentData/PaymentDataWechatTest.php | 25 + .../PaymentData/PaymentDataYooMoneyTest.php | 25 + .../AbstractPaymentMethodPhoneTest.php | 85 ++ .../AbstractPaymentMethodTest.php | 276 ++++ .../B2b/Sberbank/PayerBankDetailsTest.php | 157 ++ .../PaymentMethodAlfaBankTest.php | 90 ++ .../PaymentMethodApplePayTest.php | 25 + .../PaymentMethodBankCardTest.php | 565 +++++++ .../PaymentMethod/PaymentMethodCashTest.php | 25 + .../PaymentMethodFactoryTest.php | 255 ++++ .../PaymentMethodGooglePayTest.php | 25 + .../PaymentMethodInstallmentsTest.php | 25 + .../PaymentMethodMobileBalanceTest.php | 25 + .../PaymentMethod/PaymentMethodQiwiTest.php | 25 + .../PaymentMethodSberbankTest.php | 25 + .../PaymentMethodTinkoffBankTest.php | 29 + .../PaymentMethodWebmoneyTest.php | 25 + .../PaymentMethod/PaymentMethodWechatTest.php | 25 + .../PaymentMethodYooMoneyTest.php | 115 ++ tests/Model/PaymentTest.php | 996 ++++++++++++ tests/Model/ReceiptCustomerTest.php | 509 ++++++ tests/Model/ReceiptItemTest.php | 1206 +++++++++++++++ tests/Model/ReceiptTest.php | 734 +++++++++ tests/Model/RecipientTest.php | 161 ++ tests/Model/RefundTest.php | 598 ++++++++ tests/Model/SettlementTest.php | 195 +++ tests/Model/SourceTest.php | 279 ++++ tests/Model/TransferTest.php | 363 +++++ tests/Model/Webhook/WebhookTest.php | 71 + .../Payments/AbstractPaymentResponseTest.php | 409 +++++ .../CreatePaymentRequestBuilderTest.php | 1028 +++++++++++++ .../CreatePaymentRequestSerializerTest.php | 357 +++++ .../Payments/CreatePaymentRequestTest.php | 837 ++++++++++ .../Payments/CreatePaymentResponseTest.php | 13 + .../Payments/Payment/CancelResponseTest.php | 14 + .../CreateCaptureRequestBuilderTest.php | 549 +++++++ .../CreateCaptureRequestSerializerTest.php | 138 ++ .../Payment/CreateCaptureRequestTest.php | 94 ++ .../Payment/CreateCaptureResponseTest.php | 14 + .../Request/Payments/PaymentResponseTest.php | 13 + .../Payments/PaymentsRequestBuilderTest.php | 331 ++++ .../PaymentsRequestSerializerTest.php | 110 ++ .../Request/Payments/PaymentsRequestTest.php | 410 +++++ .../Request/Payments/PaymentsResponseTest.php | 204 +++ .../Receipts/AbstractReceiptResponseTest.php | 183 +++ .../CreatePostReceiptRequestBuilderTest.php | 329 ++++ ...CreatePostReceiptRequestSerializerTest.php | 183 +++ .../Receipts/CreatePostReceiptRequestTest.php | 314 ++++ .../Receipts/PaymentReceiptResponseTest.php | 33 + .../Request/Receipts/ReceiptsResponseTest.php | 133 ++ .../Receipts/RefundReceiptResponseTest.php | 32 + .../Refunds/AbstractRefundResponseTest.php | 148 ++ .../CreateRefundRequestBuilderTest.php | 612 ++++++++ .../CreateRefundRequestSerializerTest.php | 137 ++ .../Refunds/CreateRefundRequestTest.php | 270 ++++ .../Refunds/CreateRefundResponseTest.php | 17 + tests/Request/Refunds/RefundResponseTest.php | 17 + .../Refunds/RefundsRequestBuilderTest.php | 233 +++ .../Refunds/RefundsRequestSerializerTest.php | 98 ++ tests/Request/Refunds/RefundsRequestTest.php | 639 ++++++++ tests/Request/Refunds/RefundsResponseTest.php | 120 ++ 365 files changed, 50275 insertions(+) create mode 100644 CHANGELOG.md create mode 100644 LICENSE.md create mode 100644 README.en.md create mode 100644 README.md create mode 100644 composer.json create mode 100644 lib/Client.php create mode 100644 lib/Client/ApiClientInterface.php create mode 100644 lib/Client/BaseClient.php create mode 100644 lib/Client/CurlClient.php create mode 100644 lib/Client/UserAgent.php create mode 100644 lib/Common/AbstractEnum.php create mode 100644 lib/Common/AbstractObject.php create mode 100644 lib/Common/AbstractPaymentRequest.php create mode 100644 lib/Common/AbstractPaymentRequestBuilder.php create mode 100644 lib/Common/AbstractRequest.php create mode 100644 lib/Common/AbstractRequestBuilder.php create mode 100644 lib/Common/Exceptions/ApiConnectionException.php create mode 100644 lib/Common/Exceptions/ApiException.php create mode 100644 lib/Common/Exceptions/AuthorizeException.php create mode 100644 lib/Common/Exceptions/BadApiRequestException.php create mode 100644 lib/Common/Exceptions/EmptyPropertyValueException.php create mode 100644 lib/Common/Exceptions/ExtensionNotFoundException.php create mode 100644 lib/Common/Exceptions/ForbiddenException.php create mode 100644 lib/Common/Exceptions/InternalServerError.php create mode 100644 lib/Common/Exceptions/InvalidPropertyException.php create mode 100644 lib/Common/Exceptions/InvalidPropertyValueException.php create mode 100644 lib/Common/Exceptions/InvalidPropertyValueTypeException.php create mode 100644 lib/Common/Exceptions/InvalidRequestException.php create mode 100644 lib/Common/Exceptions/JsonException.php create mode 100644 lib/Common/Exceptions/NotFoundException.php create mode 100644 lib/Common/Exceptions/ResponseProcessingException.php create mode 100644 lib/Common/Exceptions/TooManyRequestsException.php create mode 100644 lib/Common/Exceptions/UnauthorizedException.php create mode 100644 lib/Common/HttpVerb.php create mode 100644 lib/Common/LoggerWrapper.php create mode 100644 lib/Common/ResponseObject.php create mode 100644 lib/Common/legacy_json_serializable.php create mode 100644 lib/Helpers/Config/ConfigurationLoader.php create mode 100644 lib/Helpers/Config/ConfigurationLoaderInterface.php create mode 100644 lib/Helpers/Random.php create mode 100644 lib/Helpers/RawHeadersParser.php create mode 100644 lib/Helpers/StringObject.php create mode 100644 lib/Helpers/TypeCast.php create mode 100644 lib/Helpers/UUID.php create mode 100644 lib/Model/Airline.php create mode 100644 lib/Model/AirlineInterface.php create mode 100644 lib/Model/AmountInterface.php create mode 100644 lib/Model/AuthorizationDetails.php create mode 100644 lib/Model/AuthorizationDetailsInterface.php create mode 100644 lib/Model/CancellationDetails.php create mode 100644 lib/Model/CancellationDetailsInterface.php create mode 100644 lib/Model/CancellationDetailsPartyCode.php create mode 100644 lib/Model/CancellationDetailsReasonCode.php create mode 100644 lib/Model/Confirmation/AbstractConfirmation.php create mode 100644 lib/Model/Confirmation/ConfirmationCodeVerification.php create mode 100644 lib/Model/Confirmation/ConfirmationDeepLink.php create mode 100644 lib/Model/Confirmation/ConfirmationEmbedded.php create mode 100644 lib/Model/Confirmation/ConfirmationExternal.php create mode 100644 lib/Model/Confirmation/ConfirmationFactory.php create mode 100644 lib/Model/Confirmation/ConfirmationQr.php create mode 100644 lib/Model/Confirmation/ConfirmationRedirect.php create mode 100644 lib/Model/ConfirmationAttributes/AbstractConfirmationAttributes.php create mode 100644 lib/Model/ConfirmationAttributes/ConfirmationAttributesCodeVerification.php create mode 100644 lib/Model/ConfirmationAttributes/ConfirmationAttributesDeepLink.php create mode 100644 lib/Model/ConfirmationAttributes/ConfirmationAttributesEmbedded.php create mode 100644 lib/Model/ConfirmationAttributes/ConfirmationAttributesExternal.php create mode 100644 lib/Model/ConfirmationAttributes/ConfirmationAttributesFactory.php create mode 100644 lib/Model/ConfirmationAttributes/ConfirmationAttributesQr.php create mode 100644 lib/Model/ConfirmationAttributes/ConfirmationAttributesRedirect.php create mode 100644 lib/Model/ConfirmationType.php create mode 100644 lib/Model/CurrencyCode.php create mode 100644 lib/Model/Leg.php create mode 100644 lib/Model/LegInterface.php create mode 100644 lib/Model/Metadata.php create mode 100644 lib/Model/MonetaryAmount.php create mode 100644 lib/Model/Notification/AbstractNotification.php create mode 100644 lib/Model/Notification/NotificationCanceled.php create mode 100644 lib/Model/Notification/NotificationFactory.php create mode 100644 lib/Model/Notification/NotificationRefundSucceeded.php create mode 100644 lib/Model/Notification/NotificationSucceeded.php create mode 100644 lib/Model/Notification/NotificationWaitingForCapture.php create mode 100644 lib/Model/NotificationEventType.php create mode 100644 lib/Model/NotificationType.php create mode 100644 lib/Model/Passenger.php create mode 100644 lib/Model/PassengerInterface.php create mode 100644 lib/Model/Payment.php create mode 100644 lib/Model/PaymentData/AbstractPaymentData.php create mode 100644 lib/Model/PaymentData/B2b/Sberbank/VatData.php create mode 100644 lib/Model/PaymentData/B2b/Sberbank/VatDataInterface.php create mode 100644 lib/Model/PaymentData/B2b/Sberbank/VatDataRate.php create mode 100644 lib/Model/PaymentData/B2b/Sberbank/VatDataType.php create mode 100644 lib/Model/PaymentData/PaymentDataAlfabank.php create mode 100644 lib/Model/PaymentData/PaymentDataApplePay.php create mode 100644 lib/Model/PaymentData/PaymentDataB2bSberbank.php create mode 100644 lib/Model/PaymentData/PaymentDataBankCard.php create mode 100644 lib/Model/PaymentData/PaymentDataBankCardCard.php create mode 100644 lib/Model/PaymentData/PaymentDataCash.php create mode 100644 lib/Model/PaymentData/PaymentDataFactory.php create mode 100644 lib/Model/PaymentData/PaymentDataGooglePay.php create mode 100644 lib/Model/PaymentData/PaymentDataInstallments.php create mode 100644 lib/Model/PaymentData/PaymentDataMobileBalance.php create mode 100644 lib/Model/PaymentData/PaymentDataQiwi.php create mode 100644 lib/Model/PaymentData/PaymentDataSberbank.php create mode 100644 lib/Model/PaymentData/PaymentDataTinkoffBank.php create mode 100644 lib/Model/PaymentData/PaymentDataWebmoney.php create mode 100644 lib/Model/PaymentData/PaymentDataWechat.php create mode 100644 lib/Model/PaymentData/PaymentDataYooMoney.php create mode 100644 lib/Model/PaymentInterface.php create mode 100644 lib/Model/PaymentMethod/AbstractPaymentMethod.php create mode 100644 lib/Model/PaymentMethod/B2b/Sberbank/PayerBankDetails.php create mode 100644 lib/Model/PaymentMethod/B2b/Sberbank/PayerBankDetailsInterface.php create mode 100644 lib/Model/PaymentMethod/BankCardSource.php create mode 100644 lib/Model/PaymentMethod/PaymentMethodAlfaBank.php create mode 100644 lib/Model/PaymentMethod/PaymentMethodApplePay.php create mode 100644 lib/Model/PaymentMethod/PaymentMethodB2bSberbank.php create mode 100644 lib/Model/PaymentMethod/PaymentMethodBankCard.php create mode 100644 lib/Model/PaymentMethod/PaymentMethodCardType.php create mode 100644 lib/Model/PaymentMethod/PaymentMethodCash.php create mode 100644 lib/Model/PaymentMethod/PaymentMethodFactory.php create mode 100644 lib/Model/PaymentMethod/PaymentMethodGooglePay.php create mode 100644 lib/Model/PaymentMethod/PaymentMethodInstallments.php create mode 100644 lib/Model/PaymentMethod/PaymentMethodMobileBalance.php create mode 100644 lib/Model/PaymentMethod/PaymentMethodPsb.php create mode 100644 lib/Model/PaymentMethod/PaymentMethodQiwi.php create mode 100644 lib/Model/PaymentMethod/PaymentMethodSberbank.php create mode 100644 lib/Model/PaymentMethod/PaymentMethodTinkoffBank.php create mode 100644 lib/Model/PaymentMethod/PaymentMethodWebmoney.php create mode 100644 lib/Model/PaymentMethod/PaymentMethodWechat.php create mode 100644 lib/Model/PaymentMethod/PaymentMethodYooMoney.php create mode 100644 lib/Model/PaymentMethodType.php create mode 100644 lib/Model/PaymentStatus.php create mode 100644 lib/Model/Receipt.php create mode 100644 lib/Model/Receipt/AgentType.php create mode 100644 lib/Model/Receipt/PaymentMode.php create mode 100644 lib/Model/Receipt/PaymentSubject.php create mode 100644 lib/Model/Receipt/ReceiptItemAmount.php create mode 100644 lib/Model/Receipt/SettlementType.php create mode 100644 lib/Model/ReceiptCustomer.php create mode 100644 lib/Model/ReceiptCustomerInterface.php create mode 100644 lib/Model/ReceiptInterface.php create mode 100644 lib/Model/ReceiptItem.php create mode 100644 lib/Model/ReceiptItemInterface.php create mode 100644 lib/Model/ReceiptRegistrationStatus.php create mode 100644 lib/Model/ReceiptType.php create mode 100644 lib/Model/Recipient.php create mode 100644 lib/Model/RecipientInterface.php create mode 100644 lib/Model/Refund.php create mode 100644 lib/Model/RefundInterface.php create mode 100644 lib/Model/RefundStatus.php create mode 100644 lib/Model/Requestor.php create mode 100644 lib/Model/RequestorInterface.php create mode 100644 lib/Model/Settlement.php create mode 100644 lib/Model/SettlementInterface.php create mode 100644 lib/Model/Source.php create mode 100644 lib/Model/SourceInterface.php create mode 100644 lib/Model/Supplier.php create mode 100644 lib/Model/SupplierInterface.php create mode 100644 lib/Model/Transfer.php create mode 100644 lib/Model/TransferInterface.php create mode 100644 lib/Model/TransferStatus.php create mode 100644 lib/Model/Webhook/Webhook.php create mode 100644 lib/Request/Payments/AbstractPaymentResponse.php create mode 100644 lib/Request/Payments/CreatePaymentRequest.php create mode 100644 lib/Request/Payments/CreatePaymentRequestBuilder.php create mode 100644 lib/Request/Payments/CreatePaymentRequestInterface.php create mode 100644 lib/Request/Payments/CreatePaymentRequestSerializer.php create mode 100644 lib/Request/Payments/CreatePaymentResponse.php create mode 100644 lib/Request/Payments/Payment/CancelResponse.php create mode 100644 lib/Request/Payments/Payment/CreateCaptureRequest.php create mode 100644 lib/Request/Payments/Payment/CreateCaptureRequestBuilder.php create mode 100644 lib/Request/Payments/Payment/CreateCaptureRequestInterface.php create mode 100644 lib/Request/Payments/Payment/CreateCaptureRequestSerializer.php create mode 100644 lib/Request/Payments/Payment/CreateCaptureResponse.php create mode 100644 lib/Request/Payments/PaymentResponse.php create mode 100644 lib/Request/Payments/PaymentsRequest.php create mode 100644 lib/Request/Payments/PaymentsRequestBuilder.php create mode 100644 lib/Request/Payments/PaymentsRequestInterface.php create mode 100644 lib/Request/Payments/PaymentsRequestSerializer.php create mode 100644 lib/Request/Payments/PaymentsResponse.php create mode 100644 lib/Request/Receipts/AbstractReceiptResponse.php create mode 100644 lib/Request/Receipts/CreatePostReceiptRequest.php create mode 100644 lib/Request/Receipts/CreatePostReceiptRequestBuilder.php create mode 100644 lib/Request/Receipts/CreatePostReceiptRequestInterface.php create mode 100644 lib/Request/Receipts/CreatePostReceiptRequestSerializer.php create mode 100644 lib/Request/Receipts/PaymentReceiptResponse.php create mode 100644 lib/Request/Receipts/ReceiptResponseFactory.php create mode 100644 lib/Request/Receipts/ReceiptResponseInterface.php create mode 100644 lib/Request/Receipts/ReceiptResponseItem.php create mode 100644 lib/Request/Receipts/ReceiptResponseItemInterface.php create mode 100644 lib/Request/Receipts/ReceiptsRequest.php create mode 100644 lib/Request/Receipts/ReceiptsRequestBuilder.php create mode 100644 lib/Request/Receipts/ReceiptsRequestInterface.php create mode 100644 lib/Request/Receipts/ReceiptsRequestSerializer.php create mode 100644 lib/Request/Receipts/ReceiptsResponse.php create mode 100644 lib/Request/Receipts/RefundReceiptResponse.php create mode 100644 lib/Request/Receipts/SimpleReceiptResponse.php create mode 100644 lib/Request/Refunds/AbstractRefundResponse.php create mode 100644 lib/Request/Refunds/CreateRefundRequest.php create mode 100644 lib/Request/Refunds/CreateRefundRequestBuilder.php create mode 100644 lib/Request/Refunds/CreateRefundRequestInterface.php create mode 100644 lib/Request/Refunds/CreateRefundRequestSerializer.php create mode 100644 lib/Request/Refunds/CreateRefundResponse.php create mode 100644 lib/Request/Refunds/RefundResponse.php create mode 100644 lib/Request/Refunds/RefundsRequest.php create mode 100644 lib/Request/Refunds/RefundsRequestBuilder.php create mode 100644 lib/Request/Refunds/RefundsRequestInterface.php create mode 100644 lib/Request/Refunds/RefundsRequestSerializer.php create mode 100644 lib/Request/Refunds/RefundsResponse.php create mode 100644 lib/Request/Webhook/WebhookListResponse.php create mode 100644 lib/autoload.php create mode 100644 lib/configuration.json create mode 100644 phpunit.xml.dist create mode 100644 tests/AutoloadTest.php create mode 100644 tests/Client/ClientTest.php create mode 100644 tests/Client/CurlClientTest.php create mode 100644 tests/Client/UserAgentTest.php create mode 100644 tests/Client/fixtures/cancelPaymentFixtures.json create mode 100644 tests/Client/fixtures/capturePaymentFixtures.json create mode 100644 tests/Client/fixtures/createPaymentErrorsGeneralFixtures.json create mode 100644 tests/Client/fixtures/createPaymentFixtures.json create mode 100644 tests/Client/fixtures/createReceiptFixtures.json create mode 100644 tests/Client/fixtures/createRefundFixtures.json create mode 100644 tests/Client/fixtures/getPaymentsFixtures.json create mode 100644 tests/Client/fixtures/paymentInfoFixtures.json create mode 100644 tests/Client/fixtures/paymentOptionsFixtures.json create mode 100644 tests/Client/fixtures/refundInfoFixtures.json create mode 100644 tests/Client/fixtures/refundsInfoFixtures.json create mode 100644 tests/Common/AbstractEnumTest.php create mode 100644 tests/Common/AbstractObjectTest.php create mode 100644 tests/Common/AbstractRequestBuilderTest.php create mode 100644 tests/Common/Exceptions/AbstractApiRequestExceptionTest.php create mode 100644 tests/Common/Exceptions/ApiExceptionTest.php create mode 100644 tests/Common/Exceptions/AuthorizeExceptionTest.php create mode 100644 tests/Common/Exceptions/BadApiRequestExceptionTest.php create mode 100644 tests/Common/Exceptions/EmptyPropertyValueExceptionTest.php create mode 100644 tests/Common/Exceptions/ExtensionNotFoundExceptionTest.php create mode 100644 tests/Common/Exceptions/ForbiddenExceptionTest.php create mode 100644 tests/Common/Exceptions/InternalServerErrorTest.php create mode 100644 tests/Common/Exceptions/InvalidPropertyExceptionTest.php create mode 100644 tests/Common/Exceptions/InvalidPropertyValueExceptionTest.php create mode 100644 tests/Common/Exceptions/InvalidPropertyValueTypeExceptionTest.php create mode 100644 tests/Common/Exceptions/InvalidRequestExceptionTest.php create mode 100644 tests/Common/Exceptions/JsonExceptionTest.php create mode 100644 tests/Common/Exceptions/NotFoundExceptionTest.php create mode 100644 tests/Common/Exceptions/ResponseProcessingExceptionTest.php create mode 100644 tests/Common/Exceptions/TooManyRequestsExceptionTest.php create mode 100644 tests/Common/Exceptions/UnauthorizedExceptionTest.php create mode 100644 tests/Common/LegacyJsonInterfaceTest.php create mode 100644 tests/Common/LoggerWrapperTest.php create mode 100644 tests/Helpers/Config/ConfigurationLoaderTest.php create mode 100644 tests/Helpers/Config/test_config.json create mode 100644 tests/Helpers/RandomTest.php create mode 100644 tests/Helpers/RawHeadersParserTest.php create mode 100644 tests/Helpers/StringObjectTest.php create mode 100644 tests/Helpers/TypeCastTest.php create mode 100644 tests/Helpers/UUIDTest.php create mode 100644 tests/Model/AirlineTest.php create mode 100644 tests/Model/AuthorizationDetailsTest.php create mode 100644 tests/Model/CancellationDetailsTest.php create mode 100644 tests/Model/Confirmation/AbstractConfirmationTest.php create mode 100644 tests/Model/Confirmation/ConfirmationCodeVerificationTest.php create mode 100644 tests/Model/Confirmation/ConfirmationDeepLinkTest.php create mode 100644 tests/Model/Confirmation/ConfirmationEmbeddedTest.php create mode 100644 tests/Model/Confirmation/ConfirmationExternalTest.php create mode 100644 tests/Model/Confirmation/ConfirmationFactoryTest.php create mode 100644 tests/Model/Confirmation/ConfirmationQrTest.php create mode 100644 tests/Model/Confirmation/ConfirmationRedirectTest.php create mode 100644 tests/Model/ConfirmationAttributes/AbstractConfirmationAttributesTest.php create mode 100644 tests/Model/ConfirmationAttributes/ConfirmationAttributesCodeVerificationTest.php create mode 100644 tests/Model/ConfirmationAttributes/ConfirmationAttributesDeepLinkTest.php create mode 100644 tests/Model/ConfirmationAttributes/ConfirmationAttributesEmbeddedTest.php create mode 100644 tests/Model/ConfirmationAttributes/ConfirmationAttributesExternalTest.php create mode 100644 tests/Model/ConfirmationAttributes/ConfirmationAttributesFactoryTest.php create mode 100644 tests/Model/ConfirmationAttributes/ConfirmationAttributesQrTest.php create mode 100644 tests/Model/ConfirmationAttributes/ConfirmationAttributesRedirectTest.php create mode 100644 tests/Model/LegTest.php create mode 100644 tests/Model/MetadataTest.php create mode 100644 tests/Model/MonetaryAmountTest.php create mode 100644 tests/Model/Notification/AbstractNotificationTest.php create mode 100644 tests/Model/Notification/NotificationCanceledTest.php create mode 100644 tests/Model/Notification/NotificationFactoryTest.php create mode 100644 tests/Model/Notification/NotificationRefundSucceededTest.php create mode 100644 tests/Model/Notification/NotificationSucceededTest.php create mode 100644 tests/Model/Notification/NotificationWaitingForCaptureTest.php create mode 100644 tests/Model/PassengerTest.php create mode 100644 tests/Model/PaymentData/AbstractPaymentDataApplePayTest.php create mode 100644 tests/Model/PaymentData/AbstractPaymentDataGooglePayTest.php create mode 100644 tests/Model/PaymentData/AbstractPaymentDataPhoneTest.php create mode 100644 tests/Model/PaymentData/AbstractPaymentDataTest.php create mode 100644 tests/Model/PaymentData/B2b/Sberbank/VatDataTest.php create mode 100644 tests/Model/PaymentData/PaymentDataAlfabankTest.php create mode 100644 tests/Model/PaymentData/PaymentDataApplePayTest.php create mode 100644 tests/Model/PaymentData/PaymentDataB2bSberbankTest.php create mode 100644 tests/Model/PaymentData/PaymentDataBankCardCardTest.php create mode 100644 tests/Model/PaymentData/PaymentDataBankCardTest.php create mode 100644 tests/Model/PaymentData/PaymentDataCashTest.php create mode 100644 tests/Model/PaymentData/PaymentDataFactoryTest.php create mode 100644 tests/Model/PaymentData/PaymentDataGooglePayTest.php create mode 100644 tests/Model/PaymentData/PaymentDataInstallmentsTest.php create mode 100644 tests/Model/PaymentData/PaymentDataMobileBalanceTest.php create mode 100644 tests/Model/PaymentData/PaymentDataQiwiTest.php create mode 100644 tests/Model/PaymentData/PaymentDataSberbankTest.php create mode 100644 tests/Model/PaymentData/PaymentDataTinkoffBankTest.php create mode 100644 tests/Model/PaymentData/PaymentDataWebmoneyTest.php create mode 100644 tests/Model/PaymentData/PaymentDataWechatTest.php create mode 100644 tests/Model/PaymentData/PaymentDataYooMoneyTest.php create mode 100644 tests/Model/PaymentMethod/AbstractPaymentMethodPhoneTest.php create mode 100644 tests/Model/PaymentMethod/AbstractPaymentMethodTest.php create mode 100644 tests/Model/PaymentMethod/B2b/Sberbank/PayerBankDetailsTest.php create mode 100644 tests/Model/PaymentMethod/PaymentMethodAlfaBankTest.php create mode 100644 tests/Model/PaymentMethod/PaymentMethodApplePayTest.php create mode 100644 tests/Model/PaymentMethod/PaymentMethodBankCardTest.php create mode 100644 tests/Model/PaymentMethod/PaymentMethodCashTest.php create mode 100644 tests/Model/PaymentMethod/PaymentMethodFactoryTest.php create mode 100644 tests/Model/PaymentMethod/PaymentMethodGooglePayTest.php create mode 100644 tests/Model/PaymentMethod/PaymentMethodInstallmentsTest.php create mode 100644 tests/Model/PaymentMethod/PaymentMethodMobileBalanceTest.php create mode 100644 tests/Model/PaymentMethod/PaymentMethodQiwiTest.php create mode 100644 tests/Model/PaymentMethod/PaymentMethodSberbankTest.php create mode 100644 tests/Model/PaymentMethod/PaymentMethodTinkoffBankTest.php create mode 100644 tests/Model/PaymentMethod/PaymentMethodWebmoneyTest.php create mode 100644 tests/Model/PaymentMethod/PaymentMethodWechatTest.php create mode 100644 tests/Model/PaymentMethod/PaymentMethodYooMoneyTest.php create mode 100644 tests/Model/PaymentTest.php create mode 100644 tests/Model/ReceiptCustomerTest.php create mode 100644 tests/Model/ReceiptItemTest.php create mode 100644 tests/Model/ReceiptTest.php create mode 100644 tests/Model/RecipientTest.php create mode 100644 tests/Model/RefundTest.php create mode 100644 tests/Model/SettlementTest.php create mode 100644 tests/Model/SourceTest.php create mode 100644 tests/Model/TransferTest.php create mode 100644 tests/Model/Webhook/WebhookTest.php create mode 100644 tests/Request/Payments/AbstractPaymentResponseTest.php create mode 100644 tests/Request/Payments/CreatePaymentRequestBuilderTest.php create mode 100644 tests/Request/Payments/CreatePaymentRequestSerializerTest.php create mode 100644 tests/Request/Payments/CreatePaymentRequestTest.php create mode 100644 tests/Request/Payments/CreatePaymentResponseTest.php create mode 100644 tests/Request/Payments/Payment/CancelResponseTest.php create mode 100644 tests/Request/Payments/Payment/CreateCaptureRequestBuilderTest.php create mode 100644 tests/Request/Payments/Payment/CreateCaptureRequestSerializerTest.php create mode 100644 tests/Request/Payments/Payment/CreateCaptureRequestTest.php create mode 100644 tests/Request/Payments/Payment/CreateCaptureResponseTest.php create mode 100644 tests/Request/Payments/PaymentResponseTest.php create mode 100644 tests/Request/Payments/PaymentsRequestBuilderTest.php create mode 100644 tests/Request/Payments/PaymentsRequestSerializerTest.php create mode 100644 tests/Request/Payments/PaymentsRequestTest.php create mode 100644 tests/Request/Payments/PaymentsResponseTest.php create mode 100644 tests/Request/Receipts/AbstractReceiptResponseTest.php create mode 100644 tests/Request/Receipts/CreatePostReceiptRequestBuilderTest.php create mode 100644 tests/Request/Receipts/CreatePostReceiptRequestSerializerTest.php create mode 100644 tests/Request/Receipts/CreatePostReceiptRequestTest.php create mode 100644 tests/Request/Receipts/PaymentReceiptResponseTest.php create mode 100644 tests/Request/Receipts/ReceiptsResponseTest.php create mode 100644 tests/Request/Receipts/RefundReceiptResponseTest.php create mode 100644 tests/Request/Refunds/AbstractRefundResponseTest.php create mode 100644 tests/Request/Refunds/CreateRefundRequestBuilderTest.php create mode 100644 tests/Request/Refunds/CreateRefundRequestSerializerTest.php create mode 100644 tests/Request/Refunds/CreateRefundRequestTest.php create mode 100644 tests/Request/Refunds/CreateRefundResponseTest.php create mode 100644 tests/Request/Refunds/RefundResponseTest.php create mode 100644 tests/Request/Refunds/RefundsRequestBuilderTest.php create mode 100644 tests/Request/Refunds/RefundsRequestSerializerTest.php create mode 100644 tests/Request/Refunds/RefundsRequestTest.php create mode 100644 tests/Request/Refunds/RefundsResponseTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..890bcb44 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,2 @@ +### v2.0.0 от 01.12.2020 +* Обновленная версия SDK \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000..b07267ab --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,22 @@ + +The MIT License + +Copyright (c) 2020 "YooMoney", NBСO LLC + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.en.md b/README.en.md new file mode 100644 index 00000000..07b12650 --- /dev/null +++ b/README.en.md @@ -0,0 +1,63 @@ +# The YooKassa API PHP Client Library + +[![Build Status](https://travis-ci.org/yoomoney/yookassa-sdk-php.svg?branch=master)](https://travis-ci.org/yoomoney/yookassa-sdk-php) +[![Latest Stable Version](https://poser.pugx.org/yoomoney/yookassa-sdk-php/v/stable)](https://packagist.org/packages/yoomoney/yookassa-sdk-php) +[![Total Downloads](https://poser.pugx.org/yoomoney/yookassa-sdk-php/downloads)](https://packagist.org/packages/yoomoney/yookassa-sdk-php) +[![Monthly Downloads](https://poser.pugx.org/yoomoney/yookassa-sdk-php/d/monthly)](https://packagist.org/packages/yoomoney/yookassa-sdk-php) +[![License](https://poser.pugx.org/yoomoney/yookassa-sdk-php/license)](https://packagist.org/packages/yoomoney/yookassa-sdk-php) + +[Russian](https://github.com/yoomoney/yookassa-sdk-php/blob/master/README.md) | English + +This product is used for managing payments under [The YooKassa API](https://yookassa.ru/en/developers/api) +For usage by those who implemented YooKassa using the API method. + +## Requirements +PHP 5.3.2 (or later version) with the libcurl library + +## Installation +### Under console using Composer + +1. Install Composer, a package manager. +2. In the console, run the following command: +```bash +composer require yoomoney/yookassa-sdk-php +``` + +### Do the following for the composer.json file of your project: +1. Add a string `"yoomoney/yookassa-sdk-php": "^2.0"` to the list of dependencies of your project in the composer.json file +``` +... + "require": { + "php": ">=5.3.2", + "yoomoney/yookassa-sdk-php": "^2.0" +... +``` +2. Refresh the project's dependencies. In the console, navigate to the catalog with composer.json and run the following command: +```bash +composer update +``` +3. Adjust your project's code to activate automated uploading of files for our product: +```php +require __DIR__ . '/vendor/autoload.php'; +``` + +### Manually + +1. Download [the YooKassa API PHP Client Library archive](https://github.com/yoomoney/yookassa-sdk-php/archive/master.zip), extract it and copy the lib catalog to the required place of your project. +2. Adjust your project's code to activate automated uploading of files for our product: +```php +require __DIR__ . '/lib/autoload.php'; +``` + +## Commencing work + +1. Import required classes +```php +use YooKassa\Client; +``` +2. Create a sample of a client object, then set the store's identifier and secret key (you can get them under your YooKassa's Merchant Profile). [Issuing a secret key](https://yookassa.ru/docs/support/merchant/payments/implement/keys?lang=en) +```php +$client = new Client(); +$client->setAuth('shopId', 'secretKey'); +``` +3. Call the required API method. [More details in our documentation for the YooKassa API](https://yookassa.ru/en/developers/api#create_payment) diff --git a/README.md b/README.md new file mode 100644 index 00000000..0cbbdafa --- /dev/null +++ b/README.md @@ -0,0 +1,63 @@ +# YooKassa API PHP Client Library + +[![Build Status](https://travis-ci.org/yoomoney/yookassa-sdk-php.svg?branch=master)](https://travis-ci.org/yoomoney/yookassa-sdk-php) +[![Latest Stable Version](https://poser.pugx.org/yoomoney/yookassa-sdk-php/v/stable)](https://packagist.org/packages/yoomoney/yookassa-sdk-php) +[![Total Downloads](https://poser.pugx.org/yoomoney/yookassa-sdk-php/downloads)](https://packagist.org/packages/yoomoney/yookassa-sdk-php) +[![Monthly Downloads](https://poser.pugx.org/yoomoney/yookassa-sdk-php/d/monthly)](https://packagist.org/packages/yoomoney/yookassa-sdk-php) +[![License](https://poser.pugx.org/yoomoney/yookassa-sdk-php/license)](https://packagist.org/packages/yoomoney/yookassa-sdk-php) + +Russian | [English](https://github.com/yoomoney/yookassa-sdk-php/blob/master/README.en.md) + +Клиент для работы с платежами по [API ЮKassa](https://yookassa.ru/developers/api) +Подходит тем, у кого способ подключения к ЮKassa называется API. + +## Требования +PHP 5.3.2 (и выше) с расширением libcurl + +## Установка +### В консоли с помощью Composer + +1. Установите менеджер пакетов Composer. +2. В консоли выполните команду +```bash +composer require yoomoney/yookassa-sdk-php +``` + +### В файле composer.json своего проекта +1. Добавьте строку `"yoomoney/yookassa-sdk-php": "^2.0"` в список зависимостей вашего проекта в файле composer.json +``` +... + "require": { + "php": ">=5.3.2", + "yoomoney/yookassa-sdk-php": "^2.0" +... +``` +2. Обновите зависимости проекта. В консоли перейдите в каталог, где лежит composer.json, и выполните команду: +```bash +composer update +``` +3. В коде вашего проекта подключите автозагрузку файлов нашего клиента: +```php +require __DIR__ . '/vendor/autoload.php'; +``` + +### Вручную + +1. Скачайте [архив YooKassa API PHP Client Library](https://github.com/yoomoney/yookassa-sdk-php/archive/master.zip), распакуйте его и скопируйте каталог lib в нужное место в вашем проекте. +2. В коде вашего проекта подключите автозагрузку файлов нашего клиента: +```php +require __DIR__ . '/lib/autoload.php'; +``` + +## Начало работы + +1. Импортируйте нужные классы +```php +use YooKassa\Client; +``` +2. Создайте экземпляр объекта клиента и задайте идентификатор магазина и секретный ключ (их можно получить в личном кабинете ЮKassa). [Как выпустить секретный ключ](https://yookassa.ru/docs/support/merchant/payments/implement/keys) +```php +$client = new Client(); +$client->setAuth('shopId', 'secretKey'); +``` +3. Вызовите нужный метод API. [Подробнее в документации к API ЮKassa](https://yookassa.ru/developers/api#create_payment) diff --git a/composer.json b/composer.json new file mode 100644 index 00000000..ce8c971d --- /dev/null +++ b/composer.json @@ -0,0 +1,27 @@ +{ + "name": "yoomoney/yookassa-sdk-php", + "license": "MIT", + "version": "0.0.1", + "require": { + "php": ">=5.3.0", + "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "psr/log": "^1.0" + }, + "require-dev": { + "ext-xml": "*", + "phpunit/phpunit": "^4.8.35 || ^5.7", + "mockery/mockery": "^0.9.9" + }, + "autoload": { + "psr-4": { + "YooKassa\\": "lib/" + } + }, + "autoload-dev": { + "psr-4": { + "Tests\\YooKassa\\": "tests/" + } + } +} diff --git a/lib/Client.php b/lib/Client.php new file mode 100644 index 00000000..2f72179b --- /dev/null +++ b/lib/Client.php @@ -0,0 +1,768 @@ +build($filter); + } + $serializer = new PaymentsRequestSerializer(); + $queryParams = $serializer->serialize($filter); + } + + $response = $this->execute($path, HttpVerb::GET, $queryParams); + + $paymentResponse = null; + if ($response->getCode() == 200) { + $responseArray = $this->decodeData($response); + $paymentResponse = new PaymentsResponse($responseArray); + } else { + $this->handleError($response); + } + + return $paymentResponse; + } + + /** + * Создание платежа. + * + * Чтобы принять оплату, необходимо создать объект платежа — `Payment`. Он содержит всю необходимую информацию + * для проведения оплаты (сумму, валюту и статус). У платежа линейный жизненный цикл, он последовательно + * переходит из статуса в статус. + * + * Необходимо указать один из параметров: + * + * + * Если не указан ни один параметр и `confirmation.type = redirect`, то в качестве `confirmation_url` + * возвращается ссылка, по которой пользователь сможет самостоятельно выбрать подходящий способ оплаты. + * Дополнительные параметры: + * + * + * @param CreatePaymentRequestInterface|array $payment + * @param string|null $idempotenceKey {@link https://yookassa.ru/developers/using-api/basics?lang=php#idempotence} + * + * @return CreatePaymentResponse + * @throws ApiException + * @throws BadApiRequestException + * @throws ForbiddenException + * @throws InternalServerError + * @throws NotFoundException + * @throws ResponseProcessingException + * @throws TooManyRequestsException + * @throws UnauthorizedException + * @throws Exception + */ + public function createPayment($payment, $idempotenceKey = null) + { + $path = self::PAYMENTS_PATH; + + $headers = array(); + + if ($idempotenceKey) { + $headers[self::IDEMPOTENCY_KEY_HEADER] = $idempotenceKey; + } else { + $headers[self::IDEMPOTENCY_KEY_HEADER] = UUID::v4(); + } + if (is_array($payment)) { + $payment = CreatePaymentRequest::builder()->build($payment); + } + + $serializer = new CreatePaymentRequestSerializer(); + $serializedData = $serializer->serialize($payment); + $httpBody = $this->encodeData($serializedData); + + $response = $this->execute($path, HttpVerb::POST, null, $httpBody, $headers); + + $paymentResponse = null; + if ($response->getCode() == 200) { + $resultArray = $this->decodeData($response); + $paymentResponse = new CreatePaymentResponse($resultArray); + } else { + $this->handleError($response); + } + + return $paymentResponse; + } + + /** + * Получить информацию о платеже + * + * Выдает объект платежа {@link PaymentInterface} по его уникальному идентификатору. + * + * @param string $paymentId + * + * @return PaymentInterface + * @throws ApiException + * @throws BadApiRequestException + * @throws ForbiddenException + * @throws InternalServerError + * @throws NotFoundException + * @throws ResponseProcessingException + * @throws TooManyRequestsException + * @throws UnauthorizedException + * @throws ExtensionNotFoundException + */ + public function getPaymentInfo($paymentId) + { + if ($paymentId === null) { + throw new \InvalidArgumentException('Missing the required parameter $paymentId'); + } elseif (!TypeCast::canCastToString($paymentId)) { + throw new \InvalidArgumentException('Invalid paymentId value: string required'); + } elseif (strlen($paymentId) !== 36) { + throw new \InvalidArgumentException('Invalid paymentId value'); + } + + $path = self::PAYMENTS_PATH.'/'.$paymentId; + + $response = $this->execute($path, HttpVerb::GET, null); + + $result = null; + if ($response->getCode() == 200) { + $resultArray = $this->decodeData($response); + $result = new PaymentResponse($resultArray); + } else { + $this->handleError($response); + } + + return $result; + } + + /** + * Подтверждение платежа + * + * Подтверждает вашу готовность принять платеж. Платеж можно подтвердить, только если он находится + * в статусе `waiting_for_capture`. Если платеж подтвержден успешно — значит, оплата прошла, и вы можете выдать + * товар или оказать услугу пользователю. На следующий день после подтверждения платеж попадет в реестр, + * и ЮKassa переведет деньги на ваш расчетный счет. Если вы не подтверждаете платеж до момента, указанного + * в `expire_at`, по умолчанию он отменяется, а деньги возвращаются пользователю. При оплате банковской картой + * у вас есть 7 дней на подтверждение платежа. Для остальных способов оплаты платеж необходимо подтвердить + * в течение 6 часов. + * + * @param CreateCaptureRequestInterface|array $captureRequest + * @param $paymentId + * @param $idempotencyKey {@link https://yookassa.ru/developers/using-api/basics?lang=php#idempotence} + * + * @return CreateCaptureResponse + * @throws ApiException + * @throws BadApiRequestException + * @throws ForbiddenException + * @throws InternalServerError + * @throws NotFoundException + * @throws ResponseProcessingException + * @throws TooManyRequestsException + * @throws UnauthorizedException + * @throws Exception + */ + public function capturePayment($captureRequest, $paymentId, $idempotencyKey = null) + { + if ($paymentId === null) { + throw new \InvalidArgumentException('Missing the required parameter $paymentId'); + } elseif (!TypeCast::canCastToString($paymentId)) { + throw new \InvalidArgumentException('Invalid paymentId value: string required'); + } elseif (strlen($paymentId) !== 36) { + throw new \InvalidArgumentException('Invalid paymentId value'); + } + + $path = '/payments/'.$paymentId.'/capture'; + + $headers = array(); + + if ($idempotencyKey) { + $headers[self::IDEMPOTENCY_KEY_HEADER] = $idempotencyKey; + } else { + $headers[self::IDEMPOTENCY_KEY_HEADER] = UUID::v4(); + } + if (is_array($captureRequest)) { + $captureRequest = CreateCaptureRequest::builder()->build($captureRequest); + } + + $serializer = new CreateCaptureRequestSerializer(); + $serializedData = $serializer->serialize($captureRequest); + $httpBody = $this->encodeData($serializedData); + + $response = $this->execute($path, HttpVerb::POST, null, $httpBody, $headers); + + $result = null; + if ($response->getCode() == 200) { + $resultArray = $this->decodeData($response); + $result = new CreateCaptureResponse($resultArray); + } else { + $this->handleError($response); + } + + return $result; + } + + /** + * Отменить незавершенную оплату заказа. + * + * Отменяет платеж, находящийся в статусе `waiting_for_capture`. Отмена платежа значит, что вы + * не готовы выдать пользователю товар или оказать услугу. Как только вы отменяете платеж, мы начинаем + * возвращать деньги на счет плательщика. Для платежей банковскими картами отмена происходит мгновенно. + * Для остальных способов оплаты возврат может занимать до нескольких дней. + * + * @param $paymentId + * @param $idempotencyKey {@link https://yookassa.ru/developers/using-api/basics?lang=php#idempotence} + * + * @return CancelResponse + * @throws ApiException + * @throws BadApiRequestException + * @throws ForbiddenException + * @throws InternalServerError + * @throws NotFoundException + * @throws ResponseProcessingException + * @throws TooManyRequestsException + * @throws UnauthorizedException + * @throws Exception + */ + public function cancelPayment($paymentId, $idempotencyKey = null) + { + if ($paymentId === null) { + throw new \InvalidArgumentException('Missing the required parameter $paymentId'); + } elseif (!TypeCast::canCastToString($paymentId)) { + throw new \InvalidArgumentException('Invalid paymentId value: string required'); + } elseif (strlen($paymentId) !== 36) { + throw new \InvalidArgumentException('Invalid paymentId value'); + } + + $path = self::PAYMENTS_PATH.'/'.$paymentId.'/cancel'; + $headers = array(); + if ($idempotencyKey) { + $headers[self::IDEMPOTENCY_KEY_HEADER] = $idempotencyKey; + } else { + $headers[self::IDEMPOTENCY_KEY_HEADER] = UUID::v4(); + } + + $response = $this->execute($path, HttpVerb::POST, null, null, $headers); + + $result = null; + if ($response->getCode() == 200) { + $resultArray = $this->decodeData($response); + $result = new CancelResponse($resultArray); + } else { + $this->handleError($response); + } + + return $result; + } + + /** + * Получить список возвратов платежей + * + * @param RefundsRequestInterface|array|null $filter + * + * @return RefundsResponse + * @throws ApiException + * @throws BadApiRequestException + * @throws ForbiddenException + * @throws InternalServerError + * @throws NotFoundException + * @throws ResponseProcessingException + * @throws TooManyRequestsException + * @throws UnauthorizedException + * @throws ExtensionNotFoundException + */ + public function getRefunds($filter = null) + { + $path = self::REFUNDS_PATH; + + if ($filter === null) { + $queryParams = array(); + } else { + if (is_array($filter)) { + $filter = RefundsRequest::builder()->build($filter); + } + $serializer = new RefundsRequestSerializer(); + $queryParams = $serializer->serialize($filter); + } + + $response = $this->execute($path, HttpVerb::GET, $queryParams); + + $refundsResponse = null; + if ($response->getCode() == 200) { + $resultArray = $this->decodeData($response); + $refundsResponse = new RefundsResponse($resultArray); + } else { + $this->handleError($response); + } + + return $refundsResponse; + } + + /** + * Проведение возврата платежа + * + * Создает объект возврата — `Refund`. Возвращает успешно завершенный платеж по уникальному идентификатору + * этого платежа. Создание возврата возможно только для платежей в статусе `succeeded`. Комиссии за проведение + * возврата нет. Комиссия, которую ЮKassa берёт за проведение исходного платежа, не возвращается. + * + * @param CreateRefundRequestInterface|array $request + * @param null $idempotencyKey {@link https://yookassa.ru/developers/using-api/basics?lang=php#idempotence} + * + * @return CreateRefundResponse + * @throws ApiException + * @throws BadApiRequestException + * @throws ForbiddenException + * @throws InternalServerError + * @throws NotFoundException + * @throws ResponseProcessingException + * @throws TooManyRequestsException + * @throws UnauthorizedException + * @throws Exception + */ + public function createRefund($request, $idempotencyKey = null) + { + $path = self::REFUNDS_PATH; + + $headers = array(); + + if ($idempotencyKey) { + $headers[self::IDEMPOTENCY_KEY_HEADER] = $idempotencyKey; + } else { + $headers[self::IDEMPOTENCY_KEY_HEADER] = UUID::v4(); + } + if (is_array($request)) { + $request = CreateRefundRequest::builder()->build($request); + } + + $serializer = new CreateRefundRequestSerializer(); + $serializedData = $serializer->serialize($request); + $httpBody = $this->encodeData($serializedData); + + $response = $this->execute($path, HttpVerb::POST, null, $httpBody, $headers); + + $result = null; + if ($response->getCode() == 200) { + $resultArray = $this->decodeData($response); + $result = new CreateRefundResponse($resultArray); + } else { + $this->handleError($response); + } + + return $result; + } + + /** + * Получить информацию о возврате + * + * @param $refundId + * + * @return RefundResponse + * @throws ApiException + * @throws BadApiRequestException + * @throws ForbiddenException + * @throws InternalServerError + * @throws NotFoundException + * @throws ResponseProcessingException + * @throws TooManyRequestsException + * @throws UnauthorizedException + * @throws ExtensionNotFoundException + */ + public function getRefundInfo($refundId) + { + if ($refundId === null) { + throw new \InvalidArgumentException('Missing the required parameter $refundId'); + } elseif (!TypeCast::canCastToString($refundId)) { + throw new \InvalidArgumentException('Invalid refundId value: string required'); + } elseif (strlen($refundId) !== 36) { + throw new \InvalidArgumentException('Invalid refundId value'); + } + $path = self::REFUNDS_PATH.'/'.$refundId; + + $response = $this->execute($path, HttpVerb::GET, null); + + $result = null; + if ($response->getCode() == 200) { + $resultArray = $this->decodeData($response); + $result = new RefundResponse($resultArray); + } else { + $this->handleError($response); + } + + return $result; + } + + /** + * Создание Webhook + * Запрос позволяет подписаться на уведомления о событии (например, на переход платежа в статус successed). + * + * @param $request + * @param null $idempotencyKey + * @return Webhook|null + * + * @throws ApiException + * @throws BadApiRequestException + * @throws AuthorizeException + * @throws ForbiddenException + * @throws InternalServerError + * @throws NotFoundException + * @throws ResponseProcessingException + * @throws TooManyRequestsException + * @throws UnauthorizedException + * @throws Exception + */ + public function addWebhook($request, $idempotencyKey = null) + { + $path = self::WEBHOOKS_PATH; + + $headers = array(); + + if ($idempotencyKey) { + $headers[self::IDEMPOTENCY_KEY_HEADER] = $idempotencyKey; + } else { + $headers[self::IDEMPOTENCY_KEY_HEADER] = UUID::v4(); + } + if (is_array($request)) { + $webhook = new Webhook($request); + } else { + $webhook = $request; + } + + if (!($webhook instanceof Webhook)) { + throw new InvalidArgumentException(); + } + + $httpBody = $this->encodeData($webhook->jsonSerialize()); + + $response = $this->execute($path, HttpVerb::POST, null, $httpBody, $headers); + + $result = null; + if ($response->getCode() == 200) { + $resultArray = $this->decodeData($response); + $result = new Webhook($resultArray); + } else { + $this->handleError($response); + } + + return $result; + } + + /** + * Удаление Webhook + * Запрос позволяет отписаться от уведомлений о событии для переданного OAuth-токена. Чтобы удалить webhook, вам нужно передать в запросе его идентификатор. + * + * @param $webhookId + * @param null $idempotencyKey + + * @return Webhook|null + * + * @throws ApiException + * @throws BadApiRequestException + * @throws Common\Exceptions\AuthorizeException + * @throws ForbiddenException + * @throws InternalServerError + * @throws NotFoundException + * @throws ResponseProcessingException + * @throws TooManyRequestsException + * @throws UnauthorizedException + * @throws Exception + */ + public function removeWebhook($webhookId, $idempotencyKey = null) + { + $headers = array(); + + if ($idempotencyKey) { + $headers[self::IDEMPOTENCY_KEY_HEADER] = $idempotencyKey; + } else { + $headers[self::IDEMPOTENCY_KEY_HEADER] = UUID::v4(); + } + $path = self::WEBHOOKS_PATH.'/'.$webhookId; + + $response = $this->execute($path, HttpVerb::DELETE, null, null, $headers); + + $result = null; + if ($response->getCode() == 200) { + $resultArray = $this->decodeData($response); + $result = new Webhook($resultArray); + } else { + $this->handleError($response); + } + + return $result; + } + + /** + * Список созданных Webhook + * Запрос позволяет узнать, какие webhook есть для переданного OAuth-токена. + * + * @return WebhookListResponse|null + * + * @throws ApiException + * @throws BadApiRequestException + * @throws Common\Exceptions\AuthorizeException + * @throws ForbiddenException + * @throws InternalServerError + * @throws NotFoundException + * @throws ResponseProcessingException + * @throws TooManyRequestsException + * @throws UnauthorizedException + * @throws ExtensionNotFoundException + */ + public function getWebhooks() + { + $path = self::WEBHOOKS_PATH; + + $response = $this->execute($path, HttpVerb::GET, null); + + $result = null; + if ($response->getCode() == 200) { + $responseArray = $this->decodeData($response); + $result = new WebhookListResponse($responseArray); + } else { + $this->handleError($response); + } + + return $result; + } + + /** + * Получить список платежей магазина. + * + * @param PaymentInterface|RefundInterface|array|null $filter + * + * @return ReceiptsResponse + * + * @throws ApiException + * @throws BadApiRequestException + * @throws ForbiddenException + * @throws InternalServerError + * @throws NotFoundException + * @throws ResponseProcessingException + * @throws TooManyRequestsException + * @throws UnauthorizedException + * @throws ExtensionNotFoundException + * @throws Exception + */ + public function getReceipts($filter = null) + { + $path = self::RECEIPTS_PATH; + + if ($filter === null) { + $queryParams = array(); + } else { + if (is_array($filter)) { + $filter = ReceiptsRequest::builder()->build($filter); + } + $serializer = new ReceiptsRequestSerializer(); + $queryParams = $serializer->serialize($filter); + } + + $response = $this->execute($path, HttpVerb::GET, $queryParams); + + $receiptsResponse = null; + if ($response->getCode() == 200) { + $responseArray = $this->decodeData($response); + $receiptsResponse = new ReceiptsResponse($responseArray); + } else { + $this->handleError($response); + } + + return $receiptsResponse; + } + + /** + * @param CreatePostReceiptRequestInterface|array $receipt + * @param string|null $idempotenceKey + * + * @return AbstractReceiptResponse|null + * + * @throws ApiException + * @throws BadApiRequestException + * @throws Common\Exceptions\ApiConnectionException + * @throws Common\Exceptions\AuthorizeException + * @throws ForbiddenException + * @throws InternalServerError + * @throws NotFoundException + * @throws ResponseProcessingException + * @throws TooManyRequestsException + * @throws UnauthorizedException + * @throws Exception + */ + public function createReceipt($receipt, $idempotenceKey = null) + { + $path = self::RECEIPTS_PATH; + + $headers = array(); + + if ($idempotenceKey) { + $headers[self::IDEMPOTENCY_KEY_HEADER] = $idempotenceKey; + } else { + $headers[self::IDEMPOTENCY_KEY_HEADER] = UUID::v4(); + } + + if (is_array($receipt)) { + $receipt = CreatePostReceiptRequest::builder()->build($receipt); + } + + $serializer = new CreatePostReceiptRequestSerializer(); + $serializedData = $serializer->serialize($receipt); + $httpBody = $this->encodeData($serializedData); + + $response = $this->execute($path, HttpVerb::POST, null, $httpBody, $headers); + + $receiptResponse = null; + if ($response->getCode() == 200) { + $resultArray = $this->decodeData($response); + $factory = new ReceiptResponseFactory(); + $receiptResponse = $factory->factory($resultArray); + } else { + $this->handleError($response); + } + + return $receiptResponse; + } + + /** + * Информация о магазине + * Запрос позволяет получить информацию о магазине для переданного OAuth-токена. + * + * @return array|null + * + * @throws ApiException + * @throws BadApiRequestException + * @throws Common\Exceptions\AuthorizeException + * @throws ForbiddenException + * @throws InternalServerError + * @throws NotFoundException + * @throws ResponseProcessingException + * @throws TooManyRequestsException + * @throws UnauthorizedException + * @throws ExtensionNotFoundException + */ + public function me() + { + $path = self::ME_PATH; + + $response = $this->execute($path, HttpVerb::GET, null); + + $result = null; + if ($response->getCode() == 200) { + $responseArray = $this->decodeData($response); + $result = $responseArray; + } else { + $this->handleError($response); + } + + return $result; + } +} \ No newline at end of file diff --git a/lib/Client/ApiClientInterface.php b/lib/Client/ApiClientInterface.php new file mode 100644 index 00000000..40a0f262 --- /dev/null +++ b/lib/Client/ApiClientInterface.php @@ -0,0 +1,79 @@ +load()->getConfig(); + $this->setConfig($config); + $apiClient->setConfig($config); + + $this->attempts = self::DEFAULT_ATTEMPTS_COUNT; + $this->apiClient = $apiClient; + } + + /** + * @param $login + * @param $password + * + * @return static $this + */ + public function setAuth($login, $password) + { + $this->login = $login; + $this->password = $password; + + $this->apiClient + ->setBearerToken(null) + ->setShopId($this->login) + ->setShopPassword($this->password); + + return $this; + } + + /** + * @param $token + * + * @return $this + */ + public function setAuthToken($token) + { + $this->apiClient + ->setShopId(null) + ->setShopPassword(null) + ->setBearerToken($token); + + return $this; + } + + /** + * @return ApiClientInterface + */ + public function getApiClient() + { + return $this->apiClient; + } + + /** + * @param ApiClientInterface $apiClient + * + * @return static $this + */ + public function setApiClient(ApiClientInterface $apiClient) + { + $this->apiClient = $apiClient; + $this->apiClient->setConfig($this->config); + $this->apiClient->setLogger($this->logger); + + return $this; + } + + /** + * Устанавливает логгер приложения + * + * @param null|callable|object|LoggerInterface $value Инстанс логгера + */ + public function setLogger($value) + { + if ($value === null || $value instanceof LoggerInterface) { + $this->logger = $value; + } else { + $this->logger = new LoggerWrapper($value); + } + if ($this->apiClient !== null) { + $this->apiClient->setLogger($this->logger); + } + } + + /** + * @return array + */ + public function getConfig() + { + return $this->config; + } + + /** + * @param array $config + */ + public function setConfig($config) + { + $this->config = $config; + } + + /** + * Установка значение задержки между повторными запросами + * + * @param int $timeout + * + * @return static + */ + public function setRetryTimeout($timeout) + { + $this->timeout = $timeout; + + return $this; + } + + /** + * Установка значения количества попыток повторных запросов при статусе 202 + * + * @param int $attempts + * + * @return static + */ + public function setMaxRequestAttempts($attempts) + { + $this->attempts = $attempts; + + return $this; + } + + /** + * @param $serializedData + * + * @return string + * @throws Exception + */ + protected function encodeData($serializedData) + { + if ($serializedData === array()) { + return '{}'; + } + + $result = json_encode($serializedData); + if ($result === false) { + $errorCode = json_last_error(); + throw new JsonException("Failed serialize json.", $errorCode); + } + + return $result; + } + + /** + * @param ResponseObject $response + * + * @return array + */ + protected function decodeData(ResponseObject $response) + { + $resultArray = json_decode($response->getBody(), true); + if ($resultArray === null) { + throw new JsonException('Failed to decode response', json_last_error()); + } + + return $resultArray; + } + + /** + * @param ResponseObject $response + * + * @throws ApiException + * @throws BadApiRequestException + * @throws ForbiddenException + * @throws InternalServerError + * @throws NotFoundException + * @throws ResponseProcessingException + * @throws TooManyRequestsException + * @throws UnauthorizedException + */ + protected function handleError(ResponseObject $response) + { + switch ($response->getCode()) { + case BadApiRequestException::HTTP_CODE: + throw new BadApiRequestException($response->getHeaders(), $response->getBody()); + break; + case ForbiddenException::HTTP_CODE: + throw new ForbiddenException($response->getHeaders(), $response->getBody()); + break; + case UnauthorizedException::HTTP_CODE: + throw new UnauthorizedException($response->getHeaders(), $response->getBody()); + break; + case InternalServerError::HTTP_CODE: + throw new InternalServerError($response->getHeaders(), $response->getBody()); + break; + case NotFoundException::HTTP_CODE: + throw new NotFoundException($response->getHeaders(), $response->getBody()); + break; + case TooManyRequestsException::HTTP_CODE: + throw new TooManyRequestsException($response->getHeaders(), $response->getBody()); + break; + case ResponseProcessingException::HTTP_CODE: + throw new ResponseProcessingException($response->getHeaders(), $response->getBody()); + break; + default: + if ($response->getCode() > 399) { + throw new ApiException( + 'Unexpected response error code', + $response->getCode(), + $response->getHeaders(), + $response->getBody() + ); + } + } + } + + /** + * Задержка между повторными запросами + * + * @param $response + */ + protected function delay($response) + { + $timeout = $this->timeout; + $responseData = $this->decodeData($response); + if ($timeout) { + $delay = $timeout; + } else { + if (isset($responseData['retry_after'])) { + $delay = $responseData['retry_after']; + } else { + $delay = self::DEFAULT_DELAY; + } + } + usleep($delay * 1000); + } + + /** + * Выполнение запроса и обработка 202 статуса + * + * @param $path + * @param $method + * @param $queryParams + * @param null $httpBody + * @param array $headers + * + * @return mixed|ResponseObject + * @throws ApiException + * @throws AuthorizeException + * @throws ApiConnectionException + * @throws ExtensionNotFoundException + */ + protected function execute($path, $method, $queryParams, $httpBody = null, $headers = array()) + { + $attempts = $this->attempts; + $response = $this->apiClient->call($path, $method, $queryParams, $httpBody, $headers); + + while (in_array($response->getCode(), array(202, 500)) && $attempts > 0) { + $this->delay($response); + $attempts--; + $response = $this->apiClient->call($path, $method, $queryParams, $httpBody, $headers); + } + + return $response; + } +} \ No newline at end of file diff --git a/lib/Client/CurlClient.php b/lib/Client/CurlClient.php new file mode 100644 index 00000000..a2ccf255 --- /dev/null +++ b/lib/Client/CurlClient.php @@ -0,0 +1,527 @@ + 'application/json', + 'Accept' => 'application/json', + ); + + /** + * @var resource + */ + private $curl; + + /** + * @var LoggerInterface|null + */ + private $logger; + + /** + * CurlClient constructor. + */ + public function __construct() + { + $this->userAgent = new UserAgent(); + } + + /** + * @param LoggerInterface|null $logger + */ + public function setLogger($logger) + { + $this->logger = $logger; + } + + /** + * @inheritdoc + * + * @param $path + * @param $method + * @param $queryParams + * @param null $httpBody + * @param array $headers + * + * @return ResponseObject + * @throws ApiConnectionException + * @throws ApiException + * @throws AuthorizeException + * @throws ExtensionNotFoundException + */ + public function call($path, $method, $queryParams, $httpBody = null, $headers = array()) + { + $headers = $this->prepareHeaders($headers); + + $this->logRequestParams($path, $method, $queryParams, $httpBody, $headers); + + $url = $this->prepareUrl($path, $queryParams); + + $this->prepareCurl($method, $httpBody, $this->implodeHeaders($headers), $url); + + list($httpHeaders, $httpBody, $responseInfo) = $this->sendRequest(); + + if (!$this->keepAlive) { + $this->closeCurlConnection(); + } + + $this->logResponse($httpBody, $responseInfo, $httpHeaders); + + return new ResponseObject(array( + 'code' => $responseInfo['http_code'], + 'headers' => $httpHeaders, + 'body' => $httpBody, + )); + } + + /** + * @param $optionName + * @param $optionValue + * + * @return bool + */ + public function setCurlOption($optionName, $optionValue) + { + return curl_setopt($this->curl, $optionName, $optionValue); + } + + + /** + * @return resource + * @throws ExtensionNotFoundException + */ + private function initCurl() + { + if (!extension_loaded('curl')) { + throw new ExtensionNotFoundException('curl'); + } + + if (!$this->curl || !$this->keepAlive) { + $this->curl = curl_init(); + } + + return $this->curl; + } + + /** + * Close connection + */ + public function closeCurlConnection() + { + if ($this->curl !== null) { + curl_close($this->curl); + } + } + + /** + * @return array + * @throws ApiConnectionException + */ + public function sendRequest() + { + $response = curl_exec($this->curl); + $httpHeaderSize = curl_getinfo($this->curl, CURLINFO_HEADER_SIZE); + $httpHeaders = RawHeadersParser::parse(substr($response, 0, $httpHeaderSize)); + $httpBody = substr($response, $httpHeaderSize); + $responseInfo = curl_getinfo($this->curl); + $curlError = curl_error($this->curl); + $curlErrno = curl_errno($this->curl); + if ($response === false) { + $this->handleCurlError($curlError, $curlErrno); + } + + return array($httpHeaders, $httpBody, $responseInfo); + } + + /** + * @param $method + * @param $httpBody + */ + public function setBody($method, $httpBody) + { + + $this->setCurlOption(CURLOPT_CUSTOMREQUEST, $method); + if(!empty($httpBody)) { + $this->setCurlOption(CURLOPT_POSTFIELDS, $httpBody); + } + } + + /** + * @param mixed $shopId + * + * @return CurlClient + */ + public function setShopId($shopId) + { + $this->shopId = $shopId; + + return $this; + } + + /** + * @param mixed $shopPassword + * + * @return CurlClient + */ + public function setShopPassword($shopPassword) + { + $this->shopPassword = $shopPassword; + + return $this; + } + + /** + * @return mixed + */ + public function getTimeout() + { + return $this->timeout; + } + + /** + * @param mixed $timeout + */ + public function setTimeout($timeout) + { + $this->timeout = $timeout; + } + + /** + * @return mixed + */ + public function getConnectionTimeout() + { + return $this->connectionTimeout; + } + + /** + * @param mixed $connectionTimeout + */ + public function setConnectionTimeout($connectionTimeout) + { + $this->connectionTimeout = $connectionTimeout; + } + + /** + * @return string + * @since 1.0.14 + */ + public function getProxy() + { + return $this->proxy; + } + + /** + * @param string $proxy + * + * @since 1.0.14 + */ + public function setProxy($proxy) + { + $this->proxy = $proxy; + } + + /** + * @return mixed + */ + public function getConfig() + { + return $this->config; + } + + /** + * @inheritDoc + */ + public function setConfig($config) + { + $this->config = $config; + } + + /** + * @return UserAgent + */ + public function getUserAgent() + { + return $this->userAgent; + } + + /** + * @param string $bearerToken + * + * @return static $this + */ + public function setBearerToken($bearerToken) + { + $this->bearerToken = $bearerToken; + + return $this; + } + + /** + * @param bool $keepAlive + * + * @return CurlClient + */ + public function setKeepAlive($keepAlive) + { + $this->keepAlive = $keepAlive; + + return $this; + } + + /** + * @param string $error + * @param int $errno + * + * @throws ApiConnectionException + */ + private function handleCurlError($error, $errno) + { + switch ($errno) { + case CURLE_COULDNT_CONNECT: + case CURLE_COULDNT_RESOLVE_HOST: + case CURLE_OPERATION_TIMEOUTED: + $msg = 'Could not connect to YooKassa API. Please check your internet connection and try again.'; + break; + case CURLE_SSL_CACERT: + case CURLE_SSL_PEER_CERTIFICATE: + $msg = 'Could not verify SSL certificate.'; + break; + default: + $msg = 'Unexpected error communicating.'; + } + $msg .= "\n\n(Network error [errno $errno]: $error)"; + throw new ApiConnectionException($msg); + } + + /** + * @return mixed + */ + private function getUrl() + { + $config = $this->config; + + return $config['url']; + } + + /** + * @param $headers + * + * @return array + * @throws AuthorizeException + */ + private function prepareHeaders($headers) + { + $headers = array_merge($this->defaultHeaders, $headers); + + $headers[UserAgent::HEADER] = $this->getUserAgent()->getHeaderString(); + + if ($this->shopId && $this->shopPassword) { + $encodedAuth = base64_encode($this->shopId . ':' . $this->shopPassword); + $headers['Authorization'] = 'Basic ' . $encodedAuth; + } else if ($this->bearerToken) { + $headers['Authorization'] = 'Bearer ' . $this->bearerToken; + } + + if (empty($headers['Authorization'])) { + throw new AuthorizeException('Authorization headers not set'); + } + + return $headers; + } + + /** + * @param array $headers + * @return array + */ + private function implodeHeaders($headers) + { + return array_map(function ($key, $value) { return $key . ':' . $value; }, array_keys($headers), $headers); + } + + /** + * @param $path + * @param $method + * @param $queryParams + * @param $httpBody + * @param $headers + */ + private function logRequestParams($path, $method, $queryParams, $httpBody, $headers) + { + if ($this->logger !== null) { + $message = 'Send request: ' . $method . ' ' . $path; + $context = array(); + if (!empty($queryParams)) { + $context['_params'] = $queryParams; + } + if (!empty($httpBody)) { + $data = json_decode($httpBody, true); + if (JSON_ERROR_NONE !== json_last_error()) { + $data = $httpBody; + } + $context['_body'] = $data; + } + if (!empty($headers)) { + $context['_headers'] = $headers; + } + $this->logger->info($message, $context); + } + } + + /** + * @param $path + * @param $queryParams + * + * @return string + */ + private function prepareUrl($path, $queryParams) + { + $url = $this->getUrl() . $path; + + if (!empty($queryParams)) { + $url = $url . '?' . http_build_query($queryParams); + } + + return $url; + } + + /** + * @param $httpBody + * @param $responseInfo + * @param $httpHeaders + */ + private function logResponse($httpBody, $responseInfo, $httpHeaders) + { + if ($this->logger !== null) { + $message = 'Response with code ' . $responseInfo['http_code'] . ' received.'; + $context = array(); + if (!empty($httpBody)) { + $data = json_decode($httpBody, true); + if (JSON_ERROR_NONE !== json_last_error()) { + $data = $httpBody; + } + $context['_body'] = $data; + } + if (!empty($httpHeaders)) { + $context['_headers'] = $httpHeaders; + } + $this->logger->info($message, $context); + } + } + + /** + * @param $method + * @param $httpBody + * @param $headers + * @param $url + * @throws ExtensionNotFoundException + */ + private function prepareCurl($method, $httpBody, $headers, $url) + { + $this->initCurl(); + + $this->setCurlOption(CURLOPT_URL, $url); + + $this->setCurlOption(CURLOPT_RETURNTRANSFER, true); + + $this->setCurlOption(CURLOPT_HEADER, true); + + $this->setCurlOption(CURLOPT_BINARYTRANSFER, true); + + if ($this->proxy) { + $this->setCurlOption(CURLOPT_PROXY, $this->proxy); + $this->setCurlOption(CURLOPT_HTTPPROXYTUNNEL, true); + } + + $this->setBody($method, $httpBody); + + $this->setCurlOption(CURLOPT_HTTPHEADER, $headers); + + $this->setCurlOption(CURLOPT_CONNECTTIMEOUT, $this->connectionTimeout); + + $this->setCurlOption(CURLOPT_TIMEOUT, $this->timeout); + } +} \ No newline at end of file diff --git a/lib/Client/UserAgent.php b/lib/Client/UserAgent.php new file mode 100644 index 00000000..54474611 --- /dev/null +++ b/lib/Client/UserAgent.php @@ -0,0 +1,320 @@ +defineOs()) { + $this->setOs($os['name'], $os['version']); + } + if ($php = $this->definePhp()) { + $this->setPhp($php['name'], $php['version']); + } + $this->setSdk('YooKassa.PHP', Client::SDK_VERSION); + } + + /** + * @return string + */ + public function getHeaderString() + { + $result = array(); + + $result[] = $this->getOs(); + $result[] = $this->getPhp(); + + if ($string = $this->getFramework()) { + $result[] = $string; + } + if ($string = $this->getCms()) { + $result[] = $string; + } + if ($string = $this->getModule()) { + $result[] = $string; + } + + $result[] = $this->getSdk(); + + return implode(self::PART_DELIMITER, $result); + } + + /** + * @return string + */ + public function getOs() + { + return $this->_os; + } + + /** + * @param string $name + * @param string $version + */ + private function setOs($name, $version) + { + $this->_os = $this->createVersion($name, $version); + } + + /** + * @return string + */ + public function getPhp() + { + return $this->_php; + } + + /** + * @param string $name + * @param string $version + */ + private function setPhp($name, $version) + { + $this->_php = $this->createVersion($name, $version); + } + + /** + * @return string|null + */ + public function getFramework() + { + return $this->_framework; + } + + /** + * @param string $name + * @param string $version + */ + public function setFramework($name, $version) + { + $this->_framework = $this->createVersion($name, $version); + } + + /** + * @return null + */ + public function getCms() + { + return $this->_cms; + } + + /** + * @param string $name + * @param string $version + */ + public function setCms($name, $version) + { + $this->_cms = $this->createVersion($name, $version); + } + + /** + * @return string + */ + public function getModule() + { + return $this->_module; + } + + /** + * @param string $name + * @param string $version + */ + public function setModule($name, $version) + { + $this->_module = $this->createVersion($name, $version); + } + + /** + * @return string + */ + public function getSdk() + { + return $this->_sdk; + } + + /** + * @param string $name + * @param string $version + */ + private function setSdk($name, $version) + { + $this->_sdk = $this->createVersion($name, $version); + } + + /** + * Попытка определить систему + * @return array + */ + private function defineOs() + { + if (strtolower(substr(PHP_OS, 0, 5)) === 'linux') { + if ($result = $this->parseSimpleLinuxRelease()) { + return $result; + } elseif ($result = $this->parseSmartLinuxRelease()) { + return $result; + } + } else { + return array( 'name' => php_uname('s'), 'version' => php_uname('r') ); + } + + return array( 'name' => 'Undefined', 'version' => '0.0.0' ); + } + + /** + * Возвращает информацию о версии системы + * Используется сложный вариант + * @return array|null + */ + private function parseSmartLinuxRelease() + { + $vars = array(); + + if ($files = glob('/etc/*elease')) { + foreach ($files as $file) { + if (is_file($file)) { + $lines = array_filter(array_map(array($this, 'callbackSmartLinux'), file($file))); + if (is_array($lines)) { + foreach ($lines as $line) { + $vars[strtoupper($line[0])] = trim($line[1]); + } + } + } + } + + if (!empty($vars['NAME']) && !empty($vars['VERSION_ID'])) { + return array('name' => $vars['NAME'], 'version' => $vars['VERSION_ID']); + } + } + + return null; + } + + /** + * @param string $line + * @return array|bool + */ + private static function callbackSmartLinux($line) + { + $parts = explode('=', $line); + if (count($parts) !== 2) { + return false; + } + $parts[1] = trim(str_replace(array('"', "'"), '', $parts[1])); + return $parts; + } + + /** + * Возвращает информацию о версии системы + * Используется простой вариант + * @return array|null + */ + private function parseSimpleLinuxRelease() + { + $vars = array(); + + if ($files = glob('/etc/*elease')) { + foreach ($files as $file) { + if (is_file($file)) { + $data = array_map(array($this, 'callbackSimpleLinux'), file($file)); + if (!empty($data)) { + $array = array_shift($data); + if (!empty($array) && is_array($array)) { + $vars = array_merge($vars, $array); + } + } + } + } + } + + return !empty($vars['name']) && !empty($vars['version']) ? $vars : null; + } + + /** + * @param string $line + * @return array + */ + private static function callbackSimpleLinux($line) + { + $parse = array(); + preg_match('/(.+) release (.+) (.+)/iu', $line, $parts); + if (!empty($parts[1])) { + $parse['name'] = str_replace(' ', '.', trim($parts[1])); + } + if (!empty($parts[2])) { + $parse['version'] = trim($parts[2]); + } + return $parse; + } + + /** + * Определение версии PHP + * @return array + */ + private function definePhp() + { + return array( + 'name' => 'PHP', + 'version' => PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION + ); + } + + /** + * Создание строки версии компонента + * @param string $name + * @param string $version + * @return string + */ + public function createVersion($name, $version) + { + return str_replace(array(self::PART_DELIMITER, self::VERSION_DELIMITER), '.', trim($name)) + . self::VERSION_DELIMITER + . str_replace(array(self::PART_DELIMITER, self::VERSION_DELIMITER), '.', trim($version)); + } + +} \ No newline at end of file diff --git a/lib/Common/AbstractEnum.php b/lib/Common/AbstractEnum.php new file mode 100644 index 00000000..ee448416 --- /dev/null +++ b/lib/Common/AbstractEnum.php @@ -0,0 +1,74 @@ + $enabled) { + if ($enabled) { + $result[] = $key; + } + } + return $result; + } +} diff --git a/lib/Common/AbstractObject.php b/lib/Common/AbstractObject.php new file mode 100644 index 00000000..a9e11adf --- /dev/null +++ b/lib/Common/AbstractObject.php @@ -0,0 +1,243 @@ +fromArray($data); + } + } + + /** + * Проверяет наличие свойства + * @param string $offset Имя проверяемого свойства + * @return bool True если свойство имеется, false если нет + */ + public function offsetExists($offset) + { + $method = 'get' . ucfirst($offset); + if (method_exists($this, $method)) { + return true; + } + $method = 'get' . self::matchPropertyName($offset); + if (method_exists($this, $method)) { + return true; + } + return array_key_exists($offset, $this->unknownProperties); + } + + /** + * Возвращает значение свойства + * @param string $offset Имя свойства + * @return mixed Значение свойства + */ + public function offsetGet($offset) + { + $method = 'get' . ucfirst($offset); + if (method_exists($this, $method)) { + return $this->{$method} (); + } + $method = 'get' . self::matchPropertyName($offset); + if (method_exists($this, $method)) { + return $this->{$method} (); + } + return array_key_exists($offset, $this->unknownProperties) ? $this->unknownProperties[$offset] : null; + } + + /** + * Устанавливает значение свойства + * @param string $offset Имя свойства + * @param mixed $value Значение свойства + */ + public function offsetSet($offset, $value) + { + $method = 'set' . ucfirst($offset); + if (method_exists($this, $method)) { + $this->{$method}($value); + } else { + $method = 'set' . self::matchPropertyName($offset); + if (method_exists($this, $method)) { + $this->{$method}($value); + } else { + $this->unknownProperties[$offset] = $value; + } + } + } + + /** + * Удаляет свойство + * @param string $offset Имя удаляемого свойства + */ + public function offsetUnset($offset) + { + $method = 'set' . ucfirst($offset); + if (method_exists($this, $method)) { + $this->{$method} (null); + } else { + $method = 'set' . self::matchPropertyName($offset); + if (method_exists($this, $method)) { + $this->{$method} (null); + } else { + unset($this->unknownProperties[$offset]); + } + } + } + + /** + * Возвращает значение свойства + * @param string $propertyName Имя свойства + * @return mixed Значение свойства + */ + public function __get($propertyName) + { + return $this->offsetGet($propertyName); + } + + /** + * Устанавливает значение свойства + * @param string $propertyName Имя свойства + * @param mixed $value Значение свойства + */ + public function __set($propertyName, $value) + { + $this->offsetSet($propertyName, $value); + } + + /** + * Проверяет наличие свойства + * @param string $propertyName Имя проверяемого свойства + * @return bool True если свойство имеется, false если нет + */ + public function __isset($propertyName) + { + return $this->offsetExists($propertyName); + } + + /** + * Удаляет свойство + * @param string $propertyName Имя удаляемого свойства + */ + public function __unset($propertyName) + { + $this->offsetUnset($propertyName); + } + + /** + * Устанавливает значения свойств текущего объекта из массива + * @param array|\Traversable $sourceArray Ассоциативный массив с найтройками + */ + public function fromArray($sourceArray) + { + foreach ($sourceArray as $key => $value) { + $this->offsetSet($key, $value); + } + } + + /** + * Возвращает ассоциативный массив со свойствами текущего объекта для его дальнейшей JSON сериализации + * @return array Ассоциативный массив со свойствами текущего объекта + */ + public function jsonSerialize() + { + $result = array(); + foreach (get_class_methods($this) as $method) { + if (strncmp('get', $method, 3) === 0) { + if ($method === 'getUnknownProperties') { + continue; + } + if ($method === 'getIterator') { + continue; + } + $property = strtolower(preg_replace('/[A-Z]/', '_\0', lcfirst(substr($method, 3)))); + $value = $this->serializeValueToJson($this->{$method} ()); + if ($value !== null) { + $result[$property] = $value; + } + } + } + if (!empty($this->unknownProperties)) { + foreach ($this->unknownProperties as $property => $value) { + if (!array_key_exists($property, $result)) { + $result[$property] = $this->serializeValueToJson($value); + } + } + } + return $result; + } + + private function serializeValueToJson($value) + { + if ($value === null || is_scalar($value) || is_array($value)) { + return $value; + } elseif (is_object($value) && $value instanceof \JsonSerializable) { + return $value->jsonSerialize(); + } elseif (is_object($value) && $value instanceof \DateTime) { + return $value->format(DATE_ATOM); + } + return $value; + } + + /** + * Возвращает массив свойств которые не существуют, но были заданы у объекта + * @return array Ассоциативный массив с не существующими у текущего объекта свойствами + */ + protected function getUnknownProperties() + { + return $this->unknownProperties; + } + + /** + * Преобразует имя свойства из snake_case в camelCase + * @param string $property Преобразуемое значение + * @return string Значение в камэл кейсе + */ + private static function matchPropertyName($property) + { + return preg_replace('/\_(\w)/', '\1', $property); + } +} diff --git a/lib/Common/AbstractPaymentRequest.php b/lib/Common/AbstractPaymentRequest.php new file mode 100644 index 00000000..a36369a0 --- /dev/null +++ b/lib/Common/AbstractPaymentRequest.php @@ -0,0 +1,223 @@ +_amount; + } + + /** + * Проверяет была ли установлена сумма оплаты + * @return bool True если сумма оплаты была установлена, false если нет + */ + public function hasAmount() + { + return !empty($this->_amount); + } + + /** + * Устанавливает сумму оплаты + * @param AmountInterface $value Сумма оплаты + */ + public function setAmount(AmountInterface $value) + { + $this->_amount = $value; + } + + /** + * Возвращает чек, если он есть + * @return ReceiptInterface|null Данные фискального чека 54-ФЗ или null если чека нет + */ + public function getReceipt() + { + return $this->_receipt; + } + + /** + * Устанавливает чек + * @param ReceiptInterface|null $value Инстанс чека или null для удаления информации о чеке + * @throws InvalidPropertyValueTypeException Выбрасывается если передан не инстанс класса чека и не null + */ + public function setReceipt($value) + { + if ($value === null || $value instanceof ReceiptInterface) { + $this->_receipt = $value; + } else { + throw new InvalidPropertyValueTypeException('Invalid receipt in Refund', 0, 'Refund.receipt', $value); + } + } + + /** + * Проверяет наличие чека + * @return bool True если чек есть, false если нет + */ + public function hasReceipt() + { + return $this->_receipt !== null && $this->_receipt->notEmpty(); + } + + /** + * Удаляет чек из запроса + */ + public function removeReceipt() + { + $this->_receipt = null; + } + + /** + * Устанавливает transfers (массив распределения денег между магазинами) + * @param TransferInterface[]|array $value + */ + public function setTransfers($value) + { + if (!is_array($value)) { + $message = 'Transfers must be an array of TransferInterface'; + throw new InvalidPropertyValueTypeException($message, 0, 'Payment.transfers', $value); + } + + $transfers = array(); + foreach ($value as $item) { + if (is_array($item)) { + $item = new Transfer($item); + } + + if (!($item instanceof TransferInterface)) { + $message = 'Transfers must be an array of TransferInterface'; + throw new InvalidPropertyValueTypeException($message, 0, 'Payment.transfers', $value); + } + + $transfers[] = $item; + } + + $this->_transfers = $transfers; + } + + /** + * Валидирует объект запроса + * @return bool True если запрос валиден и его можно отправить в API, false если нет + */ + public function validate() + { + if ($this->_amount === null) { + $this->setValidationError('Payment amount not specified'); + return false; + } + + $value = $this->_amount->getValue(); + if (empty($value) || $value <= 0.0) { + $this->setValidationError('Invalid payment amount value: ' . $value); + + return false; + } + + if (!empty($this->_transfers)) { + $sum = 0; + foreach ($this->_transfers as $transfer) { + if ($transfer->getAmount() === null) { + $this->setValidationError('Payment amount not specified'); + return false; + } + + $value = $transfer->getAmount()->getValue(); + if (empty($value) || $value <= 0.0) { + $this->setValidationError('Invalid transfer amount value: ' . $value); + return false; + } + $sum += (float) $value; + + $accountId = $transfer->getAccountId(); + if (empty($accountId)) { + $this->setValidationError('Transfer account id not specified'); + return false; + } + } + + if ($sum !== (float) $this->getAmount()->getValue()) { + $this->setValidationError('Transfer amount sum does not match top-level amount'); + } + } + + if ($this->getReceipt() && $this->getReceipt()->notEmpty()) { + $email = $this->getReceipt()->getCustomer()->getEmail(); + $phone = $this->getReceipt()->getCustomer()->getPhone(); + if (empty($email) && empty($phone)) { + $this->setValidationError('Both email and phone values are empty in receipt'); + return false; + } + } + + return true; + } + + public function hasTransfers() + { + return !empty($this->_transfers); + } + + public function getTransfers() + { + return $this->_transfers; + } +} \ No newline at end of file diff --git a/lib/Common/AbstractPaymentRequestBuilder.php b/lib/Common/AbstractPaymentRequestBuilder.php new file mode 100644 index 00000000..6f17d5e7 --- /dev/null +++ b/lib/Common/AbstractPaymentRequestBuilder.php @@ -0,0 +1,336 @@ +amount = new MonetaryAmount(); + $this->receipt = new Receipt(); + $this->transfers = array(); + + return $this; + } + + /** + * {@inheritDoc} + */ + public function build(array $options = null) + { + return parent::build($options); + } + + /** + * Устанавливает сумму + * + * @param AmountInterface|array|string $value Сумма оплаты + * + * @return self Инстанс билдера запросов + */ + public function setAmount($value) + { + if ($value === null || $value === '') { + $this->amount = new MonetaryAmount(); + } elseif ($value instanceof AmountInterface) { + $this->amount->setValue($value->getValue()); + $this->amount->setCurrency($value->getCurrency()); + } elseif (is_array($value)) { + $this->amount->fromArray($value); + } else { + $this->amount->setValue($value); + } + + return $this; + } + + /** + * Устанавливает трансферы + * + * @param array|string $value Массив трансферов + * + * @return self Инстанс билдера запросов + */ + public function setTransfers($value) + { + $value = (array)$value; + $this->transfers = array(); + + foreach ($value as $item) { + $transfer = new Transfer(); + + if ($item instanceof TransferInterface) { + $transfer->setAmount($item->getAmount()); + $transfer->setAccountId($item->getAccountId()); + if ($item->hasPlatformFeeAmount()) { + $transfer->setPlatformFeeAmount($item->getPlatformFeeAmount()); + } + } elseif (is_array($item)) { + $transfer->fromArray($item); + } + + $this->transfers[] = $transfer; + } + + return $this; + } + + /** + * Устанавливает валюту в которой будет происходить подтверждение оплаты заказа + * + * @param string $value Валюта в которой подтверждается оплата + * + * @return self Инстанс билдера запросов + */ + public function setCurrency($value) + { + $this->amount->setCurrency($value); + foreach ($this->receipt->getItems() as $item) { + $item->getPrice()->setCurrency($value); + } + + return $this; + } + + /** + * Устанавливает чек + * + * @param ReceiptInterface|array $value Инстанс чека или ассоциативный массив с данными чека + * + * @return self + * + * @throws InvalidPropertyValueTypeException Генерируется если было передано значение невалидного типа + */ + public function setReceipt($value) + { + if (is_array($value)) { + $this->receipt->fromArray($value); + } elseif ($value instanceof ReceiptInterface) { + $this->receipt = clone $value; + } else { + throw new InvalidPropertyValueTypeException('Invalid receipt value type', 0, 'receipt', $value); + } + + return $this; + } + + /** + * Устанавлвиает список товаров для создания чека + * + * @param array $value Массив товаров в заказе + * + * @return self Инстанс билдера запросов + * + * @throws InvalidPropertyValueException Выбрасывается если хотя бы один из товаров имеет неверную структуру + */ + public function setReceiptItems($value) + { + $this->receipt->setItems(array()); + $index = 0; + foreach ($value as $item) { + if ($item instanceof ReceiptItemInterface) { + $this->receipt->addItem($item); + } else { + if (empty($item['title']) && empty($item['description'])) { + throw new InvalidPropertyValueException( + 'Item#'.$index.' title or description not specified', + 0, + 'AbstractPaymentRequestBuilder.items['.$index.'].title', + json_encode($item) + ); + } + foreach (array('price', 'quantity', 'vatCode') as $property) { + if (empty($item[$property])) { + throw new InvalidPropertyValueException( + 'Item#'.$index.' '.$property.' not specified', + 0, + 'AbstractPaymentRequestBuilder.items['.$index.'].'.$property, + json_encode($item) + ); + } + } + $this->addReceiptItem( + empty($item['title']) ? $item['description'] : $item['title'], + $item['price'], + $item['quantity'], + $item['vatCode'] + ); + } + $index++; + } + + return $this; + } + + /** + * Добавляет в чек товар + * + * @param string $title Название или описание товара + * @param string $price Цена товара в валюте, заданной в заказе + * @param float $quantity Количество товара + * @param int $vatCode Ставка НДС + * + * @param null|string $paymentSubject значение перечисления PaymentSubject + * @see \YooKassa\Model\Receipt\PaymentSubject::class + * + * @param null|string $paymentMode значение перечисления PaymentMode + * @see \YooKassa\Model\Receipt\PaymentMode::class + * + * @return self Инстанс билдера запросов + */ + public function addReceiptItem($title, $price, $quantity, $vatCode, $paymentMode = null, $paymentSubject = null) + { + $item = new ReceiptItem(); + $item->setDescription($title); + $item->setQuantity($quantity); + $item->setVatCode($vatCode); + $item->setPrice(new ReceiptItemAmount($price, $this->amount->getCurrency())); + $item->setPaymentSubject($paymentSubject); + $item->setPaymentMode($paymentMode); + $this->receipt->addItem($item); + + return $this; + } + + /** + * Добавляет в чек доставку товара + * + * @param string $title Название доставки в чеке + * @param string $price Стоимость доставки + * @param int $vatCode Ставка НДС + * + * @param null|string $paymentSubject значение перечисления PaymentSubject + * @see \YooKassa\Model\Receipt\PaymentSubject::class + * + * @param null|string $paymentMode значение перечисления PaymentMode + * @see \YooKassa\Model\Receipt\PaymentMode::class + * + * @return self Инстанс билдера запросов + */ + public function addReceiptShipping($title, $price, $vatCode, $paymentMode = null, $paymentSubject = null) + { + $item = new ReceiptItem(); + $item->setDescription($title); + $item->setQuantity(1); + $item->setVatCode($vatCode); + $item->setIsShipping(true); + $item->setPrice(new ReceiptItemAmount($price, $this->amount->getCurrency())); + $item->setPaymentMode($paymentMode); + $item->setPaymentSubject($paymentSubject); + $this->receipt->addItem($item); + + return $this; + } + + /** + * Устанавливает адрес электронной почты получателя чека + * + * @param string $value Email получателя чека + * + * @return self Инстанс билдера запросов + */ + public function setReceiptEmail($value) + { + if (!$this->receipt->getCustomer()) { + $this->receipt->setCustomer(new ReceiptCustomer()); + } + $this->receipt->getCustomer()->setEmail($value); + + return $this; + } + + /** + * Устанавливает телефон получателя чека + * + * @param string $value Телефон получателя чека + * @return self Инстанс билдера запросов + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве значения была передана не строка + */ + public function setReceiptPhone($value) + { + if (!$this->receipt->getCustomer()) { + $this->receipt->setCustomer(new ReceiptCustomer()); + } + $this->receipt->getCustomer()->setPhone($value); + + return $this; + } + + /** + * Устанавливает код системы налогообложения. + * + * @param int $value Код системы налогообложения. Число 1-6. + * + * @return self Инстанс билдера запросов + */ + public function setTaxSystemCode($value) + { + $this->receipt->setTaxSystemCode($value); + + return $this; + } + +} \ No newline at end of file diff --git a/lib/Common/AbstractRequest.php b/lib/Common/AbstractRequest.php new file mode 100644 index 00000000..de642bb4 --- /dev/null +++ b/lib/Common/AbstractRequest.php @@ -0,0 +1,72 @@ +_validationError = null; + } + + /** + * Устанавливает ошибку валидации + * @param string $value Ошибка, произошедшая при валидации объекта + */ + protected function setValidationError($value) + { + $this->_validationError = $value; + } + + /** + * Возвращает последнюю ошибку валидации + * @return string Последняя произошедшая ошибка валидации + */ + public function getLastValidationError() + { + return $this->_validationError; + } +} diff --git a/lib/Common/AbstractRequestBuilder.php b/lib/Common/AbstractRequestBuilder.php new file mode 100644 index 00000000..d669fa3d --- /dev/null +++ b/lib/Common/AbstractRequestBuilder.php @@ -0,0 +1,119 @@ +currentObject = $this->initCurrentObject(); + } + + /** + * Инициализирует пустой запрос + * @return AbstractRequest Инстанс запроса который будем собирать + */ + abstract protected function initCurrentObject(); + + /** + * Строит запрос, валидирует его и возвращает, если все прошло нормально + * @param array $options Массив свойств запроса, если нужно их установить перед сборкой + * @return AbstractRequest Инстанс собранного запроса + * + * @throws InvalidRequestException Выбрасывается если при валидации запроса произошла ошибка + * @throws InvalidPropertyException Выбрасывается если не удалось установить один из параметров, переданныч в + * массиве настроек + */ + public function build(array $options = null) + { + if (!empty($options)) { + $this->setOptions($options); + } + try { + $this->currentObject->clearValidationError(); + if (!$this->currentObject->validate()) { + throw new InvalidRequestException($this->currentObject); + } + } catch (InvalidRequestException $e) { + throw $e; + } catch (\Exception $e) { + throw new InvalidRequestException($this->currentObject, 0, $e); + } + $result = $this->currentObject; + $this->currentObject = $this->initCurrentObject(); + return $result; + } + + /** + * Устанавливает свойства запроса из массива + * @param array|\Traversable $options Массив свойств запроса + * @return AbstractRequestBuilder Инстанс текущего билдера запросов + * + * @throws \InvalidArgumentException Выбрасывается если аргумент не массив и не итерируемый объект + * @throws InvalidPropertyException Выбрасывается если не удалось установить один из параметров, переданныч + * в массиве настроек + */ + public function setOptions($options) + { + if (empty($options)) { + return $this; + } + if (!is_array($options) && !($options instanceof \Traversable)) { + throw new \InvalidArgumentException('Invalid options value in setOptions method'); + } + foreach ($options as $property => $value) { + $method = 'set' . ucfirst($property); + if (method_exists($this, $method)) { + $this->{$method} ($value); + } else { + $property = str_replace('.', '_', $property); + $field = implode('', array_map('ucfirst', explode('_', $property))); + $method = 'set' . ucfirst($field); + if (method_exists($this, $method)) { + $this->{$method} ($value); + } + } + } + return $this; + } +} diff --git a/lib/Common/Exceptions/ApiConnectionException.php b/lib/Common/Exceptions/ApiConnectionException.php new file mode 100644 index 00000000..f0de7d81 --- /dev/null +++ b/lib/Common/Exceptions/ApiConnectionException.php @@ -0,0 +1,32 @@ +responseHeaders = $responseHeaders; + $this->responseBody = $responseBody; + } + + /** + * @return string[] + */ + public function getResponseHeaders() + { + return $this->responseHeaders; + } + + /** + * @return mixed + */ + public function getResponseBody() + { + return $this->responseBody; + } +} \ No newline at end of file diff --git a/lib/Common/Exceptions/AuthorizeException.php b/lib/Common/Exceptions/AuthorizeException.php new file mode 100644 index 00000000..25a283b3 --- /dev/null +++ b/lib/Common/Exceptions/AuthorizeException.php @@ -0,0 +1,32 @@ +retryAfter = $errorData['retry_after']; + } + + if (isset($errorData['type'])) { + $this->type = $errorData['type']; + } + + parent::__construct(trim($message), self::HTTP_CODE, $responseHeaders, $responseBody); + } +} \ No newline at end of file diff --git a/lib/Common/Exceptions/EmptyPropertyValueException.php b/lib/Common/Exceptions/EmptyPropertyValueException.php new file mode 100644 index 00000000..b54c39cc --- /dev/null +++ b/lib/Common/Exceptions/EmptyPropertyValueException.php @@ -0,0 +1,31 @@ +retryAfter = $errorData['retry_after']; + } + + if (isset($errorData['type'])) { + $this->type = $errorData['type']; + } + + parent::__construct(trim($message), self::HTTP_CODE, $responseHeaders, $responseBody); + } +} \ No newline at end of file diff --git a/lib/Common/Exceptions/InternalServerError.php b/lib/Common/Exceptions/InternalServerError.php new file mode 100644 index 00000000..ee1b2f74 --- /dev/null +++ b/lib/Common/Exceptions/InternalServerError.php @@ -0,0 +1,64 @@ +retryAfter = $errorData['retry_after']; + } + + if (isset($errorData['type'])) { + $this->type = $errorData['type']; + } + + parent::__construct(trim($message), self::HTTP_CODE, $responseHeaders, $responseBody); + } +} \ No newline at end of file diff --git a/lib/Common/Exceptions/InvalidPropertyException.php b/lib/Common/Exceptions/InvalidPropertyException.php new file mode 100644 index 00000000..ffb5f523 --- /dev/null +++ b/lib/Common/Exceptions/InvalidPropertyException.php @@ -0,0 +1,55 @@ +propertyName = (string)$property; + } + + /** + * @return string + */ + public function getProperty() + { + return $this->propertyName; + } +} diff --git a/lib/Common/Exceptions/InvalidPropertyValueException.php b/lib/Common/Exceptions/InvalidPropertyValueException.php new file mode 100644 index 00000000..11fa9eca --- /dev/null +++ b/lib/Common/Exceptions/InvalidPropertyValueException.php @@ -0,0 +1,58 @@ +invalidValue = $value; + } + } + + /** + * @return mixed + */ + public function getValue() + { + return $this->invalidValue; + } +} \ No newline at end of file diff --git a/lib/Common/Exceptions/InvalidPropertyValueTypeException.php b/lib/Common/Exceptions/InvalidPropertyValueTypeException.php new file mode 100644 index 00000000..bb54de45 --- /dev/null +++ b/lib/Common/Exceptions/InvalidPropertyValueTypeException.php @@ -0,0 +1,62 @@ +type = 'null'; + } elseif (is_object($value)) { + $this->type = get_class($value); + } else { + $this->type = gettype($value); + } + } + + /** + * @return string + */ + public function getType() + { + return $this->type; + } +} \ No newline at end of file diff --git a/lib/Common/Exceptions/InvalidRequestException.php b/lib/Common/Exceptions/InvalidRequestException.php new file mode 100644 index 00000000..65e65114 --- /dev/null +++ b/lib/Common/Exceptions/InvalidRequestException.php @@ -0,0 +1,62 @@ +getLastValidationError().'"'; + $this->errorRequest = $error; + } else { + $message = $error; + } + parent::__construct($message, $code, $previous); + } + + /** + * @return AbstractRequest|null + */ + public function getRequestObject() + { + return $this->errorRequest; + } +} \ No newline at end of file diff --git a/lib/Common/Exceptions/JsonException.php b/lib/Common/Exceptions/JsonException.php new file mode 100644 index 00000000..5771894d --- /dev/null +++ b/lib/Common/Exceptions/JsonException.php @@ -0,0 +1,46 @@ + 'No error', + JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', + JSON_ERROR_STATE_MISMATCH => 'State mismatch (invalid or malformed JSON)', + JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded', + JSON_ERROR_SYNTAX => 'Syntax error', + JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded' + ); + + public function __construct($message = "", $code = 0, $previous = null) + { + $errorMsg = isset(self::$errorLabels[$code]) ? self::$errorLabels[$code] : 'Unknown error'; + $message = sprintf('%s %s', $message, $errorMsg); + parent::__construct($message, $code, $previous); + } +} \ No newline at end of file diff --git a/lib/Common/Exceptions/NotFoundException.php b/lib/Common/Exceptions/NotFoundException.php new file mode 100644 index 00000000..409ceb8d --- /dev/null +++ b/lib/Common/Exceptions/NotFoundException.php @@ -0,0 +1,64 @@ +retryAfter = $errorData['retry_after']; + } + + if (isset($errorData['type'])) { + $this->type = $errorData['type']; + } + + parent::__construct(trim($message), self::HTTP_CODE, $responseHeaders, $responseBody); + } +} \ No newline at end of file diff --git a/lib/Common/Exceptions/ResponseProcessingException.php b/lib/Common/Exceptions/ResponseProcessingException.php new file mode 100644 index 00000000..62ecc1ba --- /dev/null +++ b/lib/Common/Exceptions/ResponseProcessingException.php @@ -0,0 +1,56 @@ +retryAfter = $errorData['retry_after']; + } + + if (isset($errorData['type'])) { + $this->type = $errorData['type']; + } + + parent::__construct(trim($message), self::HTTP_CODE, $responseHeaders, $responseBody); + } +} \ No newline at end of file diff --git a/lib/Common/Exceptions/TooManyRequestsException.php b/lib/Common/Exceptions/TooManyRequestsException.php new file mode 100644 index 00000000..aa94567f --- /dev/null +++ b/lib/Common/Exceptions/TooManyRequestsException.php @@ -0,0 +1,64 @@ +retryAfter = $errorData['retry_after']; + } + + if (isset($errorData['type'])) { + $this->type = $errorData['type']; + } + + parent::__construct(trim($message), self::HTTP_CODE, $responseHeaders, $responseBody); + } +} \ No newline at end of file diff --git a/lib/Common/Exceptions/UnauthorizedException.php b/lib/Common/Exceptions/UnauthorizedException.php new file mode 100644 index 00000000..647c3c67 --- /dev/null +++ b/lib/Common/Exceptions/UnauthorizedException.php @@ -0,0 +1,64 @@ +retryAfter = $errorData['retry_after']; + } + + if (isset($errorData['type'])) { + $this->type = $errorData['type']; + } + + parent::__construct(trim($message), self::HTTP_CODE, $responseHeaders, $responseBody); + } +} \ No newline at end of file diff --git a/lib/Common/HttpVerb.php b/lib/Common/HttpVerb.php new file mode 100644 index 00000000..eb04e5d7 --- /dev/null +++ b/lib/Common/HttpVerb.php @@ -0,0 +1,48 @@ + true, + 'POST' => true, + 'PATCH' => true, + 'HEAD' => true, + 'OPTIONS' => true, + 'PUT' => true, + 'DELETE' => true + ); +} \ No newline at end of file diff --git a/lib/Common/LoggerWrapper.php b/lib/Common/LoggerWrapper.php new file mode 100644 index 00000000..85df21dc --- /dev/null +++ b/lib/Common/LoggerWrapper.php @@ -0,0 +1,192 @@ +loggerInstance = $wrapped; + } elseif (is_callable($wrapped)) { + $this->loggerCallback = $wrapped; + } else { + throw new InvalidArgumentException('Invalid wrapped logger'); + } + } + + /** + * System is unusable. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function emergency($message, array $context = array()) + { + $this->log(LogLevel::EMERGENCY, $message, $context); + } + + /** + * Action must be taken immediately. + * + * Example: Entire website down, database unavailable, etc. This should + * trigger the SMS alerts and wake you up. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function alert($message, array $context = array()) + { + $this->log(LogLevel::ALERT, $message, $context); + } + + /** + * Critical conditions. + * + * Example: Application component unavailable, unexpected exception. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function critical($message, array $context = array()) + { + $this->log(LogLevel::CRITICAL, $message, $context); + } + + /** + * Runtime errors that do not require immediate action but should typically + * be logged and monitored. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function error($message, array $context = array()) + { + $this->log(LogLevel::ERROR, $message, $context); + } + + /** + * Exceptional occurrences that are not errors. + * + * Example: Use of deprecated APIs, poor use of an API, undesirable things + * that are not necessarily wrong. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function warning($message, array $context = array()) + { + $this->log(LogLevel::WARNING, $message, $context); + } + + /** + * Normal but significant events. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function notice($message, array $context = array()) + { + $this->log(LogLevel::NOTICE, $message, $context); + } + + /** + * Interesting events. + * + * Example: User logs in, SQL logs. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function info($message, array $context = array()) + { + $this->log(LogLevel::INFO, $message, $context); + } + + /** + * Detailed debug information. + * + * @param string $message + * @param array $context + * + * @return void + */ + public function debug($message, array $context = array()) + { + $this->log(LogLevel::DEBUG, $message, $context); + } + + /** + * Logs with an arbitrary level. + * + * @param mixed $level + * @param string $message + * @param array $context + * + * @return void + */ + public function log($level, $message, array $context = array()) + { + if ($this->loggerInstance !== null) { + $this->loggerInstance->log($level, $message, $context); + } elseif ($this->loggerCallback !== null) { + call_user_func_array($this->loggerCallback, array($level, $message, $context)); + } + } +} \ No newline at end of file diff --git a/lib/Common/ResponseObject.php b/lib/Common/ResponseObject.php new file mode 100644 index 00000000..f062468a --- /dev/null +++ b/lib/Common/ResponseObject.php @@ -0,0 +1,73 @@ +headers = $config['headers']; + } + + if (isset($config['body'])) { + $this->body = $config['body']; + } + + if (isset($config['code'])) { + $this->code = $config['code']; + } + } + + /** + * @return mixed + */ + public function getHeaders() + { + return $this->headers; + } + + /** + * @return mixed + */ + public function getBody() + { + return $this->body; + } + + /** + * @return mixed + */ + public function getCode() + { + return $this->code; + } +} \ No newline at end of file diff --git a/lib/Common/legacy_json_serializable.php b/lib/Common/legacy_json_serializable.php new file mode 100644 index 00000000..e8d82109 --- /dev/null +++ b/lib/Common/legacy_json_serializable.php @@ -0,0 +1,31 @@ +configParams = $paramsArray; + + return $this; + } + + public function getConfig() + { + return $this->configParams; + } +} \ No newline at end of file diff --git a/lib/Helpers/Config/ConfigurationLoaderInterface.php b/lib/Helpers/Config/ConfigurationLoaderInterface.php new file mode 100644 index 00000000..50a3cd1a --- /dev/null +++ b/lib/Helpers/Config/ConfigurationLoaderInterface.php @@ -0,0 +1,40 @@ +value = (string)$value; + } + + /** + * Возвращает строковое значение текущего объекта + * @return string Строковое представление объекта + */ + public function __toString() + { + return $this->value; + } +} diff --git a/lib/Helpers/TypeCast.php b/lib/Helpers/TypeCast.php new file mode 100644 index 00000000..8cc4367a --- /dev/null +++ b/lib/Helpers/TypeCast.php @@ -0,0 +1,126 @@ += 0; + } elseif (is_string($value)) { + return $value !== ''; + } elseif (is_object($value)) { + return method_exists($value, '__toString') && ((string)$value) !== ''; + } + return false; + } + + /** + * Преобразует переданне значение в объект типа \DateTime + * @param string|int|DateTime $value Преобразуемое значение + * @return DateTime|null Объект типа \DateTime или null если при парсинг даты не удался + * @throws Exception + */ + public static function castToDateTime($value) + { + if ($value instanceof DateTime) { + return clone $value; + } + if (is_numeric($value)) { + $date = new DateTime(); + $date->setTimestamp((int)$value); + } elseif (is_string($value) || (is_object($value) && method_exists($value, '__toString'))) { + $date = date_create((string)$value); + if ($date === false) { + $date = null; + } + } else { + $date = null; + } + return $date; + } + + /** + * Проверяет можно ли преобразовать переданное значение в буллево значение + * @param mixed $value Проверяемое значение + * @return bool True если значение качтится в bool, false если нет + */ + public static function canCastToBoolean($value) + { + if (is_numeric($value) || is_bool($value)) { + return true; + } + return false; + } +} \ No newline at end of file diff --git a/lib/Helpers/UUID.php b/lib/Helpers/UUID.php new file mode 100644 index 00000000..cc304531 --- /dev/null +++ b/lib/Helpers/UUID.php @@ -0,0 +1,23 @@ +_bookingReference; + } + + /** + * @param string $value + */ + public function setBookingReference($value) + { + if ($value === null || $value === '') { + $this->_bookingReference = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException('Invalid booking reference value type', 0, + 'airline.booking_reference'); + } elseif (mb_strlen((string)$value, 'utf-8') > 20) { + throw new InvalidPropertyValueException('Invalid booking reference value: "'.$value.'"', 0, + 'airline.booking_reference'); + } else { + $this->_bookingReference = (string)$value; + } + } + + /** + * @inheritdoc + */ + public function getTicketNumber() + { + return $this->_ticketNumber; + } + + /** + * @param string $value + */ + public function setTicketNumber($value) + { + if ($value === null || $value === '') { + $this->_ticketNumber = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException('Invalid ticket number value type', 0, + 'airline.ticket_number'); + } elseif (!preg_match('/^[0-9]{1,150}$/', (string)$value)) { + throw new InvalidPropertyValueException('Invalid ticket_number value: "'.$value.'"', 0, + 'airline.ticket_number'); + } else { + $this->_ticketNumber = (string)$value; + } + } + + /** + * @inheritdoc + */ + public function getPassengers() + { + return $this->_passengers; + } + + /** + * @param array|PassengerInterface[] $value + */ + public function setPassengers($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty passengers value in airline', 0, 'airline.passengers'); + } + if (!is_array($value) && !($value instanceof \Traversable)) { + throw new InvalidPropertyValueTypeException( + 'Invalid passengers value type in airline', 0, 'airline.passengers', $value + ); + } + $this->_passengers = array(); + foreach ($value as $key => $val) { + try { + $this->addPassenger($val); + } catch (InvalidPropertyValueTypeException $exception) { + throw new InvalidPropertyValueTypeException( + 'Invalid passenger value type in airline', 0, 'airline.passengers['.$key.']', $val + ); + } + } + } + + /** + * @param array|PassengerInterface $value + */ + public function addPassenger($value) + { + if ($value instanceof PassengerInterface) { + $this->_passengers[] = $value; + } elseif (is_array($value)) { + $passenger = new Passenger(); + $passenger->fromArray($value); + $this->_passengers[] = $passenger; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid passenger value type in airline', 0 + ); + } + } + + /** + * @inheritdoc + */ + public function getLegs() + { + return $this->_legs; + } + + /** + * @param array|LegInterface[] $value + */ + public function setLegs($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty legs value in airline', 0, 'airline.passengers'); + } + if (!is_array($value) && !($value instanceof \Traversable)) { + throw new InvalidPropertyValueTypeException( + 'Invalid legs value type in airline', 0, 'airline.legs', $value + ); + } + $this->_legs = array(); + foreach ($value as $key => $val) { + try { + $this->addLeg($val); + } catch (InvalidPropertyValueTypeException $exception) { + throw new InvalidPropertyValueTypeException( + 'Invalid legs value type in airline', 0, 'airline.legs['.$key.']', $val + ); + } + } + } + + /** + * @param array|LegInterface $value + */ + public function addLeg($value) + { + if ($value instanceof LegInterface) { + $this->_legs[] = $value; + } elseif (is_array($value)) { + $leg = new Leg(); + $leg->fromArray($value); + $this->_legs[] = $leg; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid passenger value type in airline', 0 + ); + } + } + + /** + * Првоерка на наличие данных + * @return bool + */ + public function notEmpty() + { + return $this->_legs || $this->_passengers || $this->_ticketNumber || $this->_bookingReference; + } + + /** + * @inheritdoc + */ + public function fromArray($sourceArray) + { + if (is_array($sourceArray['passengers']) && !empty($sourceArray['passengers'])) { + $sourceArray['passengers'] = array_map(function ($passengerData) { + if (is_array($passengerData)) { + $passenger = new Passenger(); + $passenger->fromArray($passengerData); + + return $passenger; + } elseif ($passengerData instanceof PassengerInterface) { + return $passengerData; + } + }, $sourceArray['passengers']); + } + + if (is_array($sourceArray['legs']) && !empty($sourceArray['legs'])) { + $sourceArray['legs'] = array_map(function ($legData) { + if (is_array($legData)) { + $leg = new Leg(); + $leg->fromArray($legData); + + return $leg; + } elseif ($legData instanceof LegInterface) { + return $legData; + } + }, $sourceArray['legs']); + } + parent::fromArray($sourceArray); + } +} \ No newline at end of file diff --git a/lib/Model/AirlineInterface.php b/lib/Model/AirlineInterface.php new file mode 100644 index 00000000..b46ce224 --- /dev/null +++ b/lib/Model/AirlineInterface.php @@ -0,0 +1,59 @@ +setRrn($rrn); + } + if ($authCode !== null) { + $this->setAuthCode($authCode); + } + } + + /** + * Возвращает уникальный идентификатор транзакции + * + * @return string|null Уникальный идентификатор транзакции + */ + public function getRrn() + { + return $this->_rrn; + } + + /** + * Возвращает код авторизации банковской карты + * + * @return string|null Код авторизации банковской карты + */ + public function getAuthCode() + { + return $this->_authCode; + } + + /** + * @return array + */ + public function jsonSerialize() + { + return array( + 'rrn' => $this->_rrn, + 'auth_code' => $this->_authCode, + ); + } + + /** + * Устанавливает уникальный идентификатор транзакции + * @param $value + */ + public function setRrn($value) + { + if ($value === null || $value === '') { + $this->_rrn = $value; + } elseif (TypeCast::canCastToEnumString($value)) { + $this->_rrn = (string)$value; + } else { + throw new InvalidPropertyValueTypeException('Invalid rrn value type', 0, + 'authorization_details.rrn', $value); + } + } + + /** + * Устанавливает код авторизации банковской карты + * @param $value + */ + public function setAuthCode($value) + { + if ($value === null || $value === '') { + $this->_authCode = $value; + } elseif (TypeCast::canCastToEnumString($value)) { + $this->_authCode = (string)$value; + } else { + throw new InvalidPropertyValueTypeException('Invalid auth_code value type', 0, + 'authorization_details.auth_code', $value); + } + } +} \ No newline at end of file diff --git a/lib/Model/AuthorizationDetailsInterface.php b/lib/Model/AuthorizationDetailsInterface.php new file mode 100644 index 00000000..72d0b6ce --- /dev/null +++ b/lib/Model/AuthorizationDetailsInterface.php @@ -0,0 +1,51 @@ +setParty($party); + } + if ($reason !== null) { + $this->setReason($reason); + } + } + + /** + * Возвращает участника процесса платежа, который принял решение об отмене транзакции + * + * @return string Инициатор отмены платежа + */ + public function getParty() + { + return $this->_party; + } + + /** + * Возвращает причину отмены платежа + * + * @return string Причина отмены платежа + */ + public function getReason() + { + return $this->_reason; + } + + /** + * @return array + */ + public function jsonSerialize() + { + return array( + 'party' => $this->_party, + 'reason' => $this->_reason, + ); + } + + /** + * Устанавливает участника процесса платежа, который принял решение об отмене транзакции + * @param $value + */ + public function setParty($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty party value', 0, 'cancellation_details.party'); + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException('Invalid party value type', 0, 'cancellation_details.party', $value); + } else { + $this->_party = strtolower((string)$value); + } + } + + /** + * Устанавливает причину отмены платежа + * @param $value + */ + public function setReason($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty reason value', 0, 'cancellation_details.reason'); + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException('Invalid reason value type', 0, 'cancellation_details.reason'); + } else { + $this->_reason = strtolower((string)$value); + } + } +} \ No newline at end of file diff --git a/lib/Model/CancellationDetailsInterface.php b/lib/Model/CancellationDetailsInterface.php new file mode 100644 index 00000000..1f149e60 --- /dev/null +++ b/lib/Model/CancellationDetailsInterface.php @@ -0,0 +1,51 @@ + true, + self::YOO_KASSA => true, + self::PAYMENT_NETWORK => true, + ); +} diff --git a/lib/Model/CancellationDetailsReasonCode.php b/lib/Model/CancellationDetailsReasonCode.php new file mode 100644 index 00000000..58f5cef5 --- /dev/null +++ b/lib/Model/CancellationDetailsReasonCode.php @@ -0,0 +1,77 @@ + true, + self::CALL_ISSUER => true, + self::CARD_EXPIRED => true, + self::COUNTRY_FORBIDDEN => true, + self::FRAUD_SUSPECTED => true, + self::GENERAL_DECLINE => true, + self::IDENTIFICATION_REQUIRED => true, + self::INSUFFICIENT_FUNDS => true, + self::INVALID_CARD_NUMBER => true, + self::INVALID_CSC => true, + self::ISSUER_UNAVAILABLE => true, + self::PAYMENT_METHOD_LIMIT_EXCEEDED => true, + self::PAYMENT_METHOD_RESTRICTED => true, + self::PERMISSION_REVOKED => true, + self::INTERNAL_TIMEOUT => true, + self::CANCELED_BY_MERCHANT => true, + self::PAYMENT_EXPIRED => true, + self::EXPIRED_ON_CONFIRMATION => true, + self::EXPIRED_ON_CAPTURE => true, + ); +} diff --git a/lib/Model/Confirmation/AbstractConfirmation.php b/lib/Model/Confirmation/AbstractConfirmation.php new file mode 100644 index 00000000..ac1dc98e --- /dev/null +++ b/lib/Model/Confirmation/AbstractConfirmation.php @@ -0,0 +1,83 @@ +_type; + } + + /** + * @param string $value + */ + protected function _setType($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty value for "type" parameter in Confirmation', 0, 'confirmation.type' + ); + } elseif (TypeCast::canCastToEnumString($value)) { + if (ConfirmationType::valueExists($value)) { + $this->_type = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid value for "type" parameter in Confirmation', 0, 'confirmation.type', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for "type" parameter in Confirmation', 0, 'confirmation.type', $value + ); + } + } +} diff --git a/lib/Model/Confirmation/ConfirmationCodeVerification.php b/lib/Model/Confirmation/ConfirmationCodeVerification.php new file mode 100644 index 00000000..9b4afac3 --- /dev/null +++ b/lib/Model/Confirmation/ConfirmationCodeVerification.php @@ -0,0 +1,42 @@ +_setType(ConfirmationType::CODE_VERIFICATION); + } +} \ No newline at end of file diff --git a/lib/Model/Confirmation/ConfirmationDeepLink.php b/lib/Model/Confirmation/ConfirmationDeepLink.php new file mode 100644 index 00000000..4cf5e28a --- /dev/null +++ b/lib/Model/Confirmation/ConfirmationDeepLink.php @@ -0,0 +1,42 @@ +_setType(ConfirmationType::DEEPLINK); + } +} \ No newline at end of file diff --git a/lib/Model/Confirmation/ConfirmationEmbedded.php b/lib/Model/Confirmation/ConfirmationEmbedded.php new file mode 100644 index 00000000..3cfa3942 --- /dev/null +++ b/lib/Model/Confirmation/ConfirmationEmbedded.php @@ -0,0 +1,68 @@ +_setType(ConfirmationType::EMBEDDED); + } + + /** + * @return string + */ + public function getConfirmationToken() + { + return $this->confirmationToken; + } + + /** + * @param string $confirmationToken + */ + public function setConfirmationToken($confirmationToken) + { + if ($confirmationToken === null || $confirmationToken === '') { + $this->confirmationToken = null; + } elseif (TypeCast::canCastToString($confirmationToken)) { + $this->confirmationToken = (string)$confirmationToken; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid confirmationToken value type', 0, 'confirmationEmbedded.confirmationToken', $confirmationToken + ); + } + } +} \ No newline at end of file diff --git a/lib/Model/Confirmation/ConfirmationExternal.php b/lib/Model/Confirmation/ConfirmationExternal.php new file mode 100644 index 00000000..54cb8952 --- /dev/null +++ b/lib/Model/Confirmation/ConfirmationExternal.php @@ -0,0 +1,43 @@ +_setType(ConfirmationType::EXTERNAL); + } +} diff --git a/lib/Model/Confirmation/ConfirmationFactory.php b/lib/Model/Confirmation/ConfirmationFactory.php new file mode 100644 index 00000000..faf4dc64 --- /dev/null +++ b/lib/Model/Confirmation/ConfirmationFactory.php @@ -0,0 +1,92 @@ + 'ConfirmationCodeVerification', + ConfirmationType::DEEPLINK => 'ConfirmationDeepLink', + ConfirmationType::EXTERNAL => 'ConfirmationExternal', + ConfirmationType::REDIRECT => 'ConfirmationRedirect', + ConfirmationType::EMBEDDED => 'ConfirmationEmbedded', + ConfirmationType::QR => 'ConfirmationQr', + ); + + /** + * @param string $type + * + * @return AbstractConfirmation + */ + public function factory($type) + { + if (!is_string($type)) { + throw new \InvalidArgumentException('Invalid confirmation value in confirmation factory'); + } + if (!array_key_exists($type, $this->typeClassMap)) { + throw new \InvalidArgumentException('Invalid confirmation value type "'.$type.'"'); + } + $className = __NAMESPACE__.'\\'.$this->typeClassMap[$type]; + + return new $className(); + } + + /** + * @param array $data + * @param string|null $type + * + * @return AbstractConfirmation + */ + public function factoryFromArray(array $data, $type = null) + { + if ($type === null) { + if (array_key_exists('type', $data)) { + $type = $data['type']; + unset($data['type']); + } else { + throw new \InvalidArgumentException( + 'Parameter type not specified in ConfirmationFactory.factoryFromArray()' + ); + } + } + $confirmation = $this->factory($type); + foreach ($data as $key => $value) { + if ($confirmation->offsetExists($key)) { + $confirmation->offsetSet($key, $value); + } + } + + return $confirmation; + } +} \ No newline at end of file diff --git a/lib/Model/Confirmation/ConfirmationQr.php b/lib/Model/Confirmation/ConfirmationQr.php new file mode 100644 index 00000000..9310f12e --- /dev/null +++ b/lib/Model/Confirmation/ConfirmationQr.php @@ -0,0 +1,69 @@ +_setType(ConfirmationType::QR); + } + + /** + * @return string + */ + public function getConfirmationData() + { + return $this->_confirmationData; + } + + /** + * @param string $confirmationData + */ + public function setConfirmationData($confirmationData) + { + if ($confirmationData === null || $confirmationData === '') { + $this->_confirmationData = null; + } elseif (TypeCast::canCastToString($confirmationData)) { + $this->_confirmationData = (string)$confirmationData; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid confirmationData value type', 0, 'confirmationQr.confirmationData', $confirmationData + ); + } + } +} \ No newline at end of file diff --git a/lib/Model/Confirmation/ConfirmationRedirect.php b/lib/Model/Confirmation/ConfirmationRedirect.php new file mode 100644 index 00000000..b041d5d2 --- /dev/null +++ b/lib/Model/Confirmation/ConfirmationRedirect.php @@ -0,0 +1,143 @@ +_setType(ConfirmationType::REDIRECT); + } + + /** + * @return bool Требование принудительного подтверждения платежа покупателем, требование 3-D Secure для + * оплаты банковскими картами. По умолчанию определяется политикой платежной системы. + */ + public function getEnforce() + { + return $this->_enforce; + } + + /** + * @param bool $value Требование принудительного подтверждения платежа покупателем, требование 3-D Secure + * для оплаты банковскими картами. По умолчанию определяется политикой платежной системы. + */ + public function setEnforce($value) + { + if ($value === null || $value === '') { + $this->_enforce = null; + } elseif (TypeCast::canCastToBoolean($value)) { + $this->_enforce = (bool)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid enforce value type', 0, 'confirmationRedirect.enforce', $value + ); + } + } + + /** + * @return string URL на который вернется плательщик после подтверждения или отмены платежа на странице партнера. + */ + public function getReturnUrl() + { + return $this->_returnUrl; + } + + /** + * @param string $value URL на который вернется плательщик после подтверждения или отмены платежа на + * странице партнера. + */ + public function setReturnUrl($value) + { + if ($value === null || $value === '') { + $this->_returnUrl = null; + } elseif (TypeCast::canCastToString($value)) { + $this->_returnUrl = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid returnUrl value type', 0, 'confirmationRedirect.returnUrl', $value + ); + } + } + + /** + * @return string URL на который необходимо перенаправить плательщика для подтверждения оплаты. + */ + public function getConfirmationUrl() + { + return $this->_confirmationUrl; + } + + /** + * @param string $value URL на который необходимо перенаправить плательщика для подтверждения оплаты. + */ + public function setConfirmationUrl($value) + { + if ($value === null || $value === '') { + $this->_confirmationUrl = null; + } elseif (TypeCast::canCastToString($value)) { + $this->_confirmationUrl = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid confirmationUrl value type', 0, 'confirmationRedirect.confirmationUrl', $value + ); + } + } +} diff --git a/lib/Model/ConfirmationAttributes/AbstractConfirmationAttributes.php b/lib/Model/ConfirmationAttributes/AbstractConfirmationAttributes.php new file mode 100644 index 00000000..1e9b1c02 --- /dev/null +++ b/lib/Model/ConfirmationAttributes/AbstractConfirmationAttributes.php @@ -0,0 +1,112 @@ +_type; + } + + /** + * @param string $value + */ + protected function _setType($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty value for "type" parameter in ConfirmationAttributes', 0, 'confirmationAttributes.type' + ); + } elseif (TypeCast::canCastToEnumString($value)) { + if (ConfirmationType::valueExists($value)) { + $this->_type = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid value for "type" parameter in ConfirmationAttributes', 0, 'confirmationAttributes.type', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for "type" parameter in ConfirmationAttributes', 0, 'confirmationAttributes.type', $value + ); + } + } + + /** + * @return string + */ + public function getLocale() + { + return $this->_locale; + } + + /** + * @param string $value + */ + public function setLocale($value) + { + if ($value === null || $value === '') { + $this->_locale = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for "locale" parameter in ConfirmationAttributes', 0, 'confirmationAttributes.locale', $value + ); + } elseif (!preg_match('/^[a-z]{2}_[A-Z]{2}$/', (string)$value)) { + throw new InvalidPropertyValueException( + 'Invalid value type for "locale" parameter in ConfirmationAttributes', 0, 'confirmationAttributes.locale', $value + ); + } else { + $this->_locale = (string)$value; + } + } +} diff --git a/lib/Model/ConfirmationAttributes/ConfirmationAttributesCodeVerification.php b/lib/Model/ConfirmationAttributes/ConfirmationAttributesCodeVerification.php new file mode 100644 index 00000000..d63942a6 --- /dev/null +++ b/lib/Model/ConfirmationAttributes/ConfirmationAttributesCodeVerification.php @@ -0,0 +1,42 @@ +_setType(ConfirmationType::CODE_VERIFICATION); + } +} diff --git a/lib/Model/ConfirmationAttributes/ConfirmationAttributesDeepLink.php b/lib/Model/ConfirmationAttributes/ConfirmationAttributesDeepLink.php new file mode 100644 index 00000000..36b1ddd7 --- /dev/null +++ b/lib/Model/ConfirmationAttributes/ConfirmationAttributesDeepLink.php @@ -0,0 +1,42 @@ +_setType(ConfirmationType::DEEPLINK); + } +} \ No newline at end of file diff --git a/lib/Model/ConfirmationAttributes/ConfirmationAttributesEmbedded.php b/lib/Model/ConfirmationAttributes/ConfirmationAttributesEmbedded.php new file mode 100644 index 00000000..de36f19c --- /dev/null +++ b/lib/Model/ConfirmationAttributes/ConfirmationAttributesEmbedded.php @@ -0,0 +1,37 @@ +_setType(ConfirmationType::EMBEDDED); + } +} \ No newline at end of file diff --git a/lib/Model/ConfirmationAttributes/ConfirmationAttributesExternal.php b/lib/Model/ConfirmationAttributes/ConfirmationAttributesExternal.php new file mode 100644 index 00000000..14cddf08 --- /dev/null +++ b/lib/Model/ConfirmationAttributes/ConfirmationAttributesExternal.php @@ -0,0 +1,42 @@ +_setType(ConfirmationType::EXTERNAL); + } +} \ No newline at end of file diff --git a/lib/Model/ConfirmationAttributes/ConfirmationAttributesFactory.php b/lib/Model/ConfirmationAttributes/ConfirmationAttributesFactory.php new file mode 100644 index 00000000..e1ae4290 --- /dev/null +++ b/lib/Model/ConfirmationAttributes/ConfirmationAttributesFactory.php @@ -0,0 +1,92 @@ + 'ConfirmationAttributesCodeVerification', + ConfirmationType::DEEPLINK => 'ConfirmationAttributesDeepLink', + ConfirmationType::EXTERNAL => 'ConfirmationAttributesExternal', + ConfirmationType::REDIRECT => 'ConfirmationAttributesRedirect', + ConfirmationType::EMBEDDED => 'ConfirmationAttributesEmbedded', + ConfirmationType::QR => 'ConfirmationAttributesQr', + ); + + /** + * @param string $type + * + * @return AbstractConfirmationAttributes + */ + public function factory($type) + { + if (!is_string($type)) { + throw new \InvalidArgumentException('Invalid confirmation attributes value in confirmation factory'); + } + if (!array_key_exists($type, $this->typeClassMap)) { + throw new \InvalidArgumentException('Invalid confirmation attributes value type "'.$type.'"'); + } + $className = __NAMESPACE__.'\\'.$this->typeClassMap[$type]; + + return new $className(); + } + + /** + * @param array $data + * @param string|null $type + * + * @return AbstractConfirmationAttributes + */ + public function factoryFromArray(array $data, $type = null) + { + if ($type === null) { + if (array_key_exists('type', $data)) { + $type = $data['type']; + unset($data['type']); + } else { + throw new \InvalidArgumentException( + 'Parameter type not specified in ConfirmationAttributesFactory.factoryFromArray()' + ); + } + } + $confirmation = $this->factory($type); + foreach ($data as $key => $value) { + if ($confirmation->offsetExists($key)) { + $confirmation->offsetSet($key, $value); + } + } + + return $confirmation; + } +} \ No newline at end of file diff --git a/lib/Model/ConfirmationAttributes/ConfirmationAttributesQr.php b/lib/Model/ConfirmationAttributes/ConfirmationAttributesQr.php new file mode 100644 index 00000000..3949666b --- /dev/null +++ b/lib/Model/ConfirmationAttributes/ConfirmationAttributesQr.php @@ -0,0 +1,37 @@ +_setType(ConfirmationType::QR); + } +} \ No newline at end of file diff --git a/lib/Model/ConfirmationAttributes/ConfirmationAttributesRedirect.php b/lib/Model/ConfirmationAttributes/ConfirmationAttributesRedirect.php new file mode 100644 index 00000000..f2c585ca --- /dev/null +++ b/lib/Model/ConfirmationAttributes/ConfirmationAttributesRedirect.php @@ -0,0 +1,109 @@ +_setType(ConfirmationType::REDIRECT); + } + + /** + * @return bool Требование принудительного подтверждения платежа покупателем, требование 3-D Secure для + * оплаты банковскими картами. По умолчанию определяется политикой платежной системы. + */ + public function getEnforce() + { + return $this->_enforce; + } + + /** + * @param bool $value Требование принудительного подтверждения платежа покупателем, требование 3-D Secure + * для оплаты банковскими картами. По умолчанию определяется политикой платежной системы. + */ + public function setEnforce($value) + { + if ($value === null || $value === '') { + $this->_enforce = null; + } elseif (TypeCast::canCastToBoolean($value)) { + $this->_enforce = (bool)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid enforce value type', 0, 'confirmationAttributesRedirect.enforce', $value + ); + } + } + + /** + * @return string URL на который вернется плательщик после подтверждения или отмены платежа на странице партнера. + */ + public function getReturnUrl() + { + return $this->_returnUrl; + } + + /** + * @param string $value URL на который вернется плательщик после подтверждения или отмены платежа + * на странице партнера. + */ + public function setReturnUrl($value) + { + if ($value === null || $value === '') { + $this->_returnUrl = null; + } elseif (TypeCast::canCastToString($value)) { + $this->_returnUrl = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid returnUrl value type', 0, 'confirmationAttributesRedirect.returnUrl', $value + ); + } + } +} diff --git a/lib/Model/ConfirmationType.php b/lib/Model/ConfirmationType.php new file mode 100644 index 00000000..1a81d073 --- /dev/null +++ b/lib/Model/ConfirmationType.php @@ -0,0 +1,59 @@ + true, + self::EXTERNAL => true, + self::DEEPLINK => false, + self::CODE_VERIFICATION => false, + self::EMBEDDED => true, + self::QR => true, + ); +} diff --git a/lib/Model/CurrencyCode.php b/lib/Model/CurrencyCode.php new file mode 100644 index 00000000..6b183106 --- /dev/null +++ b/lib/Model/CurrencyCode.php @@ -0,0 +1,53 @@ + true, + self::USD => true, + self::EUR => true, + self::BYN => true, + self::CNY => true, + self::KZT => true, + self::UAH => true, + ); +} diff --git a/lib/Model/Leg.php b/lib/Model/Leg.php new file mode 100644 index 00000000..92250ebe --- /dev/null +++ b/lib/Model/Leg.php @@ -0,0 +1,129 @@ +_departureAirport; + } + + /** + * @param string $value + */ + public function setDepartureAirport($value) + { + if (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException('Invalid departure_airport value type', 0, + 'airline.departure_airport'); + } elseif (!preg_match('/^[A-Z]{3}$/', (string)$value)) { + throw new InvalidPropertyValueException('Invalid departure_airport value: "'.$value.'"', 0, + 'airline.departure_airport'); + } else { + $this->_departureAirport = (string)$value; + } + } + + /** + * @inheritdoc + */ + public function getDestinationAirport() + { + return $this->_destinationAirport; + } + + /** + * @param string $value + */ + public function setDestinationAirport($value) + { + if (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException('Invalid destination_airport value type', 0, + 'airline.destination_airport'); + } elseif (!preg_match('/^[A-Z]{3}$/', (string)$value)) { + throw new InvalidPropertyValueException('Invalid destination_airport value: "'.$value.'"', 0, + 'airline.destination_airport'); + } else { + $this->_destinationAirport = (string)$value; + } + } + + /** + * @inheritdoc + */ + public function getDepartureDate() + { + return $this->_departureDate; + } + + /** + * @param \DateTime|string $value + * @throws \Exception + */ + public function setDepartureDate($value) + { + if (TypeCast::canCastToDateTime($value)) { + $departureDate = TypeCast::castToDateTime($value); + if ($departureDate === null) { + throw new InvalidPropertyValueException( + 'Invalid departure_date value in airline.legs', 0, 'airline.legs' + ); + } + $this->_departureDate = $departureDate->format(self::ISO8601); + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid departure_date value type in airline.legs', 0, 'airline.legs' + ); + } + } +} \ No newline at end of file diff --git a/lib/Model/LegInterface.php b/lib/Model/LegInterface.php new file mode 100644 index 00000000..417cb7b0 --- /dev/null +++ b/lib/Model/LegInterface.php @@ -0,0 +1,45 @@ +getUnknownProperties(); + } + + /** + * @return \Iterator + */ + public function getIterator() + { + return new \ArrayIterator($this->getUnknownProperties()); + } + + /** + * @return int + */ + public function count() + { + return count($this->getUnknownProperties()); + } +} diff --git a/lib/Model/MonetaryAmount.php b/lib/Model/MonetaryAmount.php new file mode 100644 index 00000000..fb169307 --- /dev/null +++ b/lib/Model/MonetaryAmount.php @@ -0,0 +1,224 @@ + 0.0) { + $this->setValue($value); + } + if ($currency !== null) { + $this->setCurrency($currency); + } + } + + /** + * Возвращает значение суммы + * @return string Сумма + */ + public function getValue() + { + if ($this->_value < 10) { + return '0.0' . $this->_value; + } elseif ($this->_value < 100) { + return '0.' . $this->_value; + } else { + return substr($this->_value, 0, -2) . '.' . substr($this->_value, -2); + } + } + + /** + * Устанавливает сумму + * @param string $value Сумма + * + * @throws EmptyPropertyValueException Генерируется если было передано пустое значение + * @throws InvalidPropertyValueTypeException Генерируется если было передано значение невалидного типа + * @throws InvalidPropertyValueException Генерируется если было передано не валидное значение + */ + public function setValue($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty amount value', 0, 'amount.value'); + } + if (!is_numeric($value)) { + throw new InvalidPropertyValueTypeException('Invalid amount value type', 0, 'amount.value', $value); + } + if ($value <= 0.0) { + throw new InvalidPropertyValueException('Invalid amount value: "'.$value.'"', 0, 'amount.value', $value); + } + $castedValue = (int)round($value * 100.0); + if ($castedValue <= 0.0) { + throw new InvalidPropertyValueException('Invalid amount value: "'.$value.'"', 0, 'amount.value', $value); + } + $this->_value = $castedValue; + } + + /** + * Возвращает сумму в копейках в виде целого числа + * @return int Сумма в копейках/центах + */ + public function getIntegerValue() + { + return $this->_value; + } + + /** + * Возвращает валюту + * @return string Код валюты + */ + public function getCurrency() + { + return $this->_currency; + } + + /** + * Устанавливает код валюты + * @param string $value Код валюты + * + * @throws EmptyPropertyValueException Генерируется если было передано пустое значение + * @throws InvalidPropertyValueTypeException Генерируется если было передано значение невалидного типа + * @throws InvalidPropertyValueException Генерируется если был передан неподдерживаемый код валюты + */ + public function setCurrency($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty currency value', 0, 'amount.currency'); + } + if (TypeCast::canCastToEnumString($value)) { + $value = strtoupper((string)$value); + if (CurrencyCode::valueExists($value)) { + $this->_currency = $value; + } else { + throw new InvalidPropertyValueException( + 'Invalid currency value: "' . $value . '"', 0, 'amount.currency', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException('Invalid currency value type', 0, 'amount.currency', $value); + } + } + + /** + * Умножает текущую сумму на указанный коэффициент + * @param float $coefficient Множитель + * + * @throws EmptyPropertyValueException Выбрасывается если передано пустое значение + * @throws InvalidPropertyValueTypeException Выбрасывается если было передано не число + * @throws InvalidPropertyValueException Выбрасывается если переданное значение меньше или равно нулю, либо если + * после умножения получили значение равное нулю + */ + public function multiply($coefficient) + { + if ($coefficient === null || $coefficient === '') { + throw new EmptyPropertyValueException('Empty coefficient in multiply method', 0, 'amount.value'); + } + if (!is_numeric($coefficient)) { + throw new InvalidPropertyValueTypeException( + 'Invalid coefficient type in multiply method', 0, 'amount.value', $coefficient + ); + } + if ($coefficient <= 0.0) { + throw new InvalidPropertyValueException( + 'Invalid coefficient in multiply method: "' . $coefficient . '"', 0, 'amount.value', $coefficient + ); + } + $castedValue = (int)round($coefficient * $this->_value); + if ($castedValue === 0) { + throw new InvalidPropertyValueException( + 'Invalid coefficient value in multiply method: "' . $coefficient . '"', 0, 'amount.value', $coefficient + ); + } + $this->_value = $castedValue; + } + + /** + * Увеличивает сумму на указанное значение + * @param int $value Значение которое будет прибавлено к текущему + * + * @throws EmptyPropertyValueException Выбрасывается если передано пустое значение + * @throws InvalidPropertyValueTypeException Выбрасывается если было передано не число + * @throws InvalidPropertyValueException Выбрасывается если после сложения получилась сумма меньше или равная нулю + */ + public function increase($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty amount value in increase method', 0, 'amount.value'); + } + if (!is_numeric($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid amount value type in increase method', 0, 'amount.value', $value + ); + } + $castedValue = (int)round($this->_value + $value * 100.0); + if ($castedValue <= 0) { + throw new InvalidPropertyValueException( + 'Invalid amount value in increase method: "' . $value . '"', 0, 'amount.value', $value + ); + } + $this->_value = $castedValue; + } + + /** + * @return array + */ + public function jsonSerialize() + { + return array( + 'value' => sprintf('%.2f',$this->_value / 100.0), + 'currency' => $this->_currency, + ); + } +} diff --git a/lib/Model/Notification/AbstractNotification.php b/lib/Model/Notification/AbstractNotification.php new file mode 100644 index 00000000..30b7ecb1 --- /dev/null +++ b/lib/Model/Notification/AbstractNotification.php @@ -0,0 +1,138 @@ +_type; + } + + /** + * Устанавливает тип уведомления + * + * @param string $value Тип уведомления + * + * @throws EmptyPropertyValueException Выбрасывается если в качестве значения было передано пустое значение + * @throws InvalidPropertyValueException Выбрасывается если переданное значение не найдено в перечислении типов + * нотификаций + * @throws InvalidPropertyValueTypeException Выбрасывается если переданное значение не является строкой + */ + protected function _setType($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty parameter "type" in Notification', 0, 'notification.type'); + } elseif (TypeCast::canCastToEnumString($value)) { + if (NotificationType::valueExists($value)) { + $this->_type = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid value for "type" parameter in Notification', 0, 'notification.type', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for "type" parameter in Notification', 0, 'notification.type', $value + ); + } + } + + /** + * Возвращает тип события + * + * Тип события - одна из констант, указанных в перечислении {@link NotificationEventType}. + * + * @return string Тип события + */ + public function getEvent() + { + return $this->_event; + } + + /** + * Устанавливает тип события + * + * @param string $value Тип события + * + * @throws EmptyPropertyValueException Выбрасывается если в качестве значения было передано пустое значение + * @throws InvalidPropertyValueException Выбрасывается если переданное значение не найдено в перечислении типов + * событий + * @throws InvalidPropertyValueTypeException Выбрасывается если переданное значение не является строкой + */ + protected function _setEvent($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty parameter "event" in Notification', 0, 'notification.event'); + } elseif (TypeCast::canCastToEnumString($value)) { + if (NotificationEventType::valueExists($value)) { + $this->_event = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid value for "event" parameter in Notification', 0, 'notification.event', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for "event" parameter in Notification', 0, 'notification.event', $value + ); + } + } +} \ No newline at end of file diff --git a/lib/Model/Notification/NotificationCanceled.php b/lib/Model/Notification/NotificationCanceled.php new file mode 100644 index 00000000..57bdad08 --- /dev/null +++ b/lib/Model/Notification/NotificationCanceled.php @@ -0,0 +1,99 @@ +_setType(NotificationType::NOTIFICATION); + $this->_setEvent(NotificationEventType::PAYMENT_CANCELED); + if (!empty($source['type'])) { + if ($this->getType() !== $source['type']) { + throw new InvalidPropertyValueException( + 'Invalid value for "type" parameter in Notification', 0, 'notification.type', $source['type'] + ); + } + } + if (!empty($source['event'])) { + if ($this->getEvent() !== $source['event']) { + throw new InvalidPropertyValueException( + 'Invalid value for "event" parameter in Notification', 0, 'notification.event', $source['event'] + ); + } + } + if (empty($source['object'])) { + throw new EmptyPropertyValueException('Parameter object in NotificationSucceeded is empty'); + } + $this->_object = new PaymentResponse($source['object']); + } + + /** + * Возвращает объект с информацией о платеже, уведомление о котором хранится в текущем объекте + * + * Так как нотификация может быть сгенерирована и поставлена в очередь на отправку гораздо раньше, чем она будет + * получена на сайте, то опираться на статус пришедшего платежа не стоит, лучше запросить текущую информацию о + * платеже у API. + * + * @return PaymentInterface Объект с информацией о платеже + */ + public function getObject() + { + return $this->_object; + } +} \ No newline at end of file diff --git a/lib/Model/Notification/NotificationFactory.php b/lib/Model/Notification/NotificationFactory.php new file mode 100644 index 00000000..7146109a --- /dev/null +++ b/lib/Model/Notification/NotificationFactory.php @@ -0,0 +1,63 @@ + 'NotificationCanceled', + NotificationEventType::REFUND_SUCCEEDED => 'NotificationRefundSucceeded', + NotificationEventType::PAYMENT_SUCCEEDED => 'NotificationSucceeded', + NotificationEventType::PAYMENT_WAITING_FOR_CAPTURE => 'NotificationWaitingForCapture', + ); + + /** + * @param array $data + * @return AbstractNotification + */ + public function factory(array $data) + { + if (!array_key_exists('event', $data)) { + throw new \InvalidArgumentException( + 'Parameter event not specified in NotificationFactory.factory()' + ); + } + if (!is_string($data['event'])) { + throw new \InvalidArgumentException('Invalid notification type value in notification factory'); + } + if (!array_key_exists($data['event'], $this->typeClassMap)) { + throw new \InvalidArgumentException('Invalid notification data type "' . $data['event'] . '"'); + } + $className = __NAMESPACE__ . '\\' . $this->typeClassMap[$data['event']]; + + return new $className($data); + } + +} diff --git a/lib/Model/Notification/NotificationRefundSucceeded.php b/lib/Model/Notification/NotificationRefundSucceeded.php new file mode 100644 index 00000000..92afbdaf --- /dev/null +++ b/lib/Model/Notification/NotificationRefundSucceeded.php @@ -0,0 +1,98 @@ +_setType(NotificationType::NOTIFICATION); + $this->_setEvent(NotificationEventType::REFUND_SUCCEEDED); + if (!empty($source['type'])) { + if ($this->getType() !== $source['type']) { + throw new InvalidPropertyValueException( + 'Invalid value for "type" parameter in Notification', 0, 'notification.type', $source['type'] + ); + } + } + if (!empty($source['event'])) { + if ($this->getEvent() !== $source['event']) { + throw new InvalidPropertyValueException( + 'Invalid value for "event" parameter in Notification', 0, 'notification.event', $source['event'] + ); + } + } + if (empty($source['object'])) { + throw new EmptyPropertyValueException('Parameter object in NotificationSucceeded is empty'); + } + $this->_object = new RefundResponse($source['object']); + } + + /** + * Возвращает объект с информацией о возврате, уведомление о котором хранится в текущем объекте + * + * Так как нотификация может быть сгенерирована и поставлена в очередь на отправку гораздо раньше, чем она будет + * получена на сайте, то опираться на статус пришедшего возврата не стоит, лучше запросить текущую информацию о + * возврате у API. + * + * @return RefundInterface Объект с информацией о возврате + */ + public function getObject() + { + return $this->_object; + } +} \ No newline at end of file diff --git a/lib/Model/Notification/NotificationSucceeded.php b/lib/Model/Notification/NotificationSucceeded.php new file mode 100644 index 00000000..623dc009 --- /dev/null +++ b/lib/Model/Notification/NotificationSucceeded.php @@ -0,0 +1,105 @@ +_setType(NotificationType::NOTIFICATION); + $this->_setEvent(NotificationEventType::PAYMENT_SUCCEEDED); + if (!empty($source['type'])) { + if ($this->getType() !== $source['type']) { + throw new InvalidPropertyValueException( + 'Invalid value for "type" parameter in Notification', 0, 'notification.type', $source['type'] + ); + } + } + if (!empty($source['event'])) { + if ($this->getEvent() !== $source['event']) { + throw new InvalidPropertyValueException( + 'Invalid value for "event" parameter in Notification', 0, 'notification.event', $source['event'] + ); + } + } + if (empty($source['object'])) { + throw new EmptyPropertyValueException('Parameter object in NotificationSucceeded is empty'); + } + $this->_object = new PaymentResponse($source['object']); + } + + /** + * Возвращает объект с информацией о платеже, уведомление о котором хранится в текущем объекте + * + * Так как нотификация может быть сгенерирована и поставлена в очередь на отправку гораздо раньше, чем она будет + * получена на сайте, то опираться на статус пришедшего платежа не стоит, лучше запросить текущую информацию о + * платеже у API. + * + * @return PaymentInterface Объект с информацией о платеже + */ + public function getObject() + { + return $this->_object; + } +} \ No newline at end of file diff --git a/lib/Model/Notification/NotificationWaitingForCapture.php b/lib/Model/Notification/NotificationWaitingForCapture.php new file mode 100644 index 00000000..307b9f30 --- /dev/null +++ b/lib/Model/Notification/NotificationWaitingForCapture.php @@ -0,0 +1,109 @@ +_setType(NotificationType::NOTIFICATION); + $this->_setEvent(NotificationEventType::PAYMENT_WAITING_FOR_CAPTURE); + if (!empty($source['type'])) { + if ($this->getType() !== $source['type']) { + throw new InvalidPropertyValueException( + 'Invalid value for "type" parameter in Notification', 0, 'notification.type', $source['type'] + ); + } + } + if (!empty($source['event'])) { + if ($this->getEvent() !== $source['event']) { + throw new InvalidPropertyValueException( + 'Invalid value for "event" parameter in Notification', 0, 'notification.event', $source['event'] + ); + } + } + if (empty($source['object'])) { + throw new EmptyPropertyValueException('Parameter object in NotificationWaitingForCapture is empty'); + } + $this->_object = new PaymentResponse($source['object']); + } + + /** + * Возвращает объект с информацией о платеже, уведомление о котором хранится в текущем объекте + * + * Так как нотификация может быть сгенерирована и поставлена в очередь на отправку гораздо раньше, чем она будет + * получена на сайте, то опираться на статус пришедшего платежа не стоит, лучше запросить текущую информацию о + * платеже у API. + * + * @return PaymentInterface Объект с информацией о платеже, который можно подтвердить или отменить + */ + public function getObject() + { + return $this->_object; + } +} \ No newline at end of file diff --git a/lib/Model/NotificationEventType.php b/lib/Model/NotificationEventType.php new file mode 100644 index 00000000..280585ac --- /dev/null +++ b/lib/Model/NotificationEventType.php @@ -0,0 +1,44 @@ + true, + self::PAYMENT_SUCCEEDED => true, + self::PAYMENT_CANCELED => true, + self::REFUND_SUCCEEDED => true, + ); +} \ No newline at end of file diff --git a/lib/Model/NotificationType.php b/lib/Model/NotificationType.php new file mode 100644 index 00000000..d4809a18 --- /dev/null +++ b/lib/Model/NotificationType.php @@ -0,0 +1,38 @@ + true, + ); +} \ No newline at end of file diff --git a/lib/Model/Passenger.php b/lib/Model/Passenger.php new file mode 100644 index 00000000..ff0ceafb --- /dev/null +++ b/lib/Model/Passenger.php @@ -0,0 +1,112 @@ +_firstName; + } + + /** + * @param $value + */ + public function setFirstName($value) + { + if (empty($value) || is_numeric($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid first_name value type in Passenger object', 0, 'airline.passengers', $value + ); + } else if (TypeCast::canCastToString($value)) { + $length = mb_strlen((string)$value, 'utf-8'); + if ($length > 64) { + throw new InvalidPropertyValueException( + 'Invalid first_name value length in Passenger object', + 0, 'airline.passengers', $value + ); + } + $this->_firstName = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid first_name value type in Passenger object', 0, 'airline.passengers', $value + ); + } + } + + /** + * @inheritdoc + */ + public function getLastName() + { + return $this->_lastName; + } + + /** + * @param $value + */ + public function setLastName($value) + { + if (empty($value) || is_numeric($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid last_name value type in Passenger object', 0, 'airline.passengers', $value + ); + } else if (TypeCast::canCastToString($value)) { + $length = mb_strlen((string)$value, 'utf-8'); + if ($length > 64) { + throw new InvalidPropertyValueException( + 'Invalid last_name value length in Passenger object', + 0, 'airline.passengers', $value + ); + } + $this->_lastName = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid last_name value type in Passenger object', 0, 'airline.passengers', $value + ); + } + } +} \ No newline at end of file diff --git a/lib/Model/PassengerInterface.php b/lib/Model/PassengerInterface.php new file mode 100644 index 00000000..9721c2e8 --- /dev/null +++ b/lib/Model/PassengerInterface.php @@ -0,0 +1,41 @@ +_id; + } + + /** + * Устанавливает идентификатор платежа + * @param string $value Идентификатор платежа + * + * @throws InvalidPropertyValueException Выбрасывается если длина переданной строки не равна 36 + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setId($value) + { + if (TypeCast::canCastToString($value)) { + $length = mb_strlen($value, 'utf-8'); + if ($length != 36) { + throw new InvalidPropertyValueException('Invalid payment id value', 0, 'Payment.id', $value); + } + $this->_id = (string)$value; + } else { + throw new InvalidPropertyValueTypeException('Invalid payment id value type', 0, 'Payment.id', $value); + } + } + + /** + * Возвращает состояние платежа + * @return string Текущее состояние платежа + */ + public function getStatus() + { + return $this->_status; + } + + /** + * Устанавливает статус платежа + * @param string $value Статус платежа + * + * @throws InvalidPropertyValueException Выбрасывается если переданная строка не является валидным статусом + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setStatus($value) + { + if (TypeCast::canCastToEnumString($value)) { + if (!PaymentStatus::valueExists((string)$value)) { + throw new InvalidPropertyValueException('Invalid payment status value', 0, 'Payment.status', $value); + } + $this->_status = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid payment status value type', 0, 'Payment.status', $value + ); + } + } + + /** + * Возвращает получателя платежа + * @return RecipientInterface|null Получатель платежа или null если получатель не задан + */ + public function getRecipient() + { + return $this->_recipient; + } + + /** + * Устанавливает получателя платежа + * @param RecipientInterface $value Объект с информацией о получателе платежа + */ + public function setRecipient(RecipientInterface $value) + { + $this->_recipient = $value; + } + + /** + * Возвращает сумму + * @return AmountInterface Сумма платежа + */ + public function getAmount() + { + return $this->_amount; + } + + /** + * Устанавливает сумму платежа + * @param AmountInterface $value Сумма платежа + */ + public function setAmount(AmountInterface $value) + { + $this->_amount = $value; + } + + /** + * Возвращает описание транзакции + * @return string + */ + public function getDescription() + { + return $this->_description; + } + + /** + * Устанавливает описание транзакции + * @param string $value + * + * @throws InvalidPropertyValueException Выбрасывается если переданное значение превышает допустимую длину + * @throws InvalidPropertyValueTypeException Выбрасывается если переданное значение не является строкой + */ + public function setDescription($value) + { + if ($value === null || $value === '') { + $this->_description = null; + } elseif (TypeCast::canCastToString($value)) { + $length = mb_strlen((string)$value, 'utf-8'); + if ($length > self::MAX_LENGTH_DESCRIPTION) { + throw new InvalidPropertyValueException( + 'Invalid description value', 0, 'CreatePaymentRequest.description', $value + ); + } + $this->_description = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid description value type', 0, 'CreatePaymentRequest.description', $value + ); + } + } + + /** + * Возвращает используемый способ проведения платежа + * @return AbstractPaymentMethod Способ проведения платежа + */ + public function getPaymentMethod() + { + return $this->_paymentMethod; + } + + /** + * @param AbstractPaymentMethod $value + */ + public function setPaymentMethod(AbstractPaymentMethod $value) + { + $this->_paymentMethod = $value; + } + + /** + * Возвращает время создания заказа + * @return \DateTime Время создания заказа + */ + public function getCreatedAt() + { + return $this->_createdAt; + } + + /** + * Устанавливает время создания заказа + * @param \DateTime|string|int $value Время создания заказа + * + * @throws EmptyPropertyValueException Выбрасывается если в метод была передана пустая дата + * @throws InvalidPropertyValueException Выбрасвается если передали строку, которую не удалось привести к дате + * @throws InvalidPropertyValueTypeException|\Exception Выбрасывается если был передан аргумент, который невозможно + * интерпретировать как дату или время + */ + public function setCreatedAt($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty created_at value', 0, 'payment.createdAt'); + } elseif (TypeCast::canCastToDateTime($value)) { + $dateTime = TypeCast::castToDateTime($value); + if ($dateTime === null) { + throw new InvalidPropertyValueException('Invalid created_at value', 0, 'payment.createdAt', $value); + } + $this->_createdAt = $dateTime; + } else { + throw new InvalidPropertyValueTypeException('Invalid created_at value', 0, 'payment.createdAt', $value); + } + } + + /** + * Возвращает время подтверждения платежа магазином или null если если время не задано + * @return \DateTime|null Время подтверждения платежа магазином + */ + public function getCapturedAt() + { + return $this->_capturedAt; + } + + /** + * Устанавливает время подтверждения платежа магазином + * @param \DateTime|string|int|null $value Время подтверждения платежа магазином + * + * @throws InvalidPropertyValueException Выбрасвается если передали строку, которую не удалось привести к дате + * @throws InvalidPropertyValueTypeException|\Exception Выбрасывается если был передан аргумент, который невозможно + * интерпретировать как дату или время + */ + public function setCapturedAt($value) + { + if ($value === null || $value === '') { + $this->_capturedAt = null; + } elseif (TypeCast::canCastToDateTime($value)) { + $dateTime = TypeCast::castToDateTime($value); + if ($dateTime === null) { + throw new InvalidPropertyValueException('Invalid captured_at value', 0, 'payment.capturedAt', $value); + } + $this->_capturedAt = $dateTime; + } else { + throw new InvalidPropertyValueTypeException('Invalid captured_at value', 0, 'payment.capturedAt', $value); + } + } + + /** + * Возвращает способ подтверждения платежа + * @return Confirmation\AbstractConfirmation Способ подтверждения платежа + */ + public function getConfirmation() + { + return $this->_confirmation; + } + + /** + * Устанавливает способ подтверждения платежа + * @param Confirmation\AbstractConfirmation $value Способ подтверждения платежа + */ + public function setConfirmation(Confirmation\AbstractConfirmation $value) + { + $this->_confirmation = $value; + } + + /** + * Возвращает сумму возвращенных средств + * @return AmountInterface Сумма возвращенных средств платежа + */ + public function getRefundedAmount() + { + return $this->_refundedAmount; + } + + /** + * Устанавливает сумму возвращенных средств + * @param AmountInterface $value Сумма возвращенных средств платежа + */ + public function setRefundedAmount(AmountInterface $value) + { + $this->_refundedAmount = $value; + } + + /** + * Проверяет был ли уже оплачен заказ + * @return bool Признак оплаты заказа, true если заказ оплачен, false если нет + */ + public function getPaid() + { + return $this->_paid; + } + + /** + * Устанавливает флаг оплаты заказа + * @param bool $value Признак оплаты заказа + * + * @throws EmptyPropertyValueException Выбрасывается если переданный аргумент пуст + * @throws InvalidPropertyValueTypeException Выбрасывается если переданный аргумент не кастится в булево значение + */ + public function setPaid($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty payment paid flag value', 0, 'Payment.paid'); + } elseif (TypeCast::canCastToBoolean($value)) { + $this->_paid = (bool)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid payment paid flag value type', 0, 'Payment.paid', $value + ); + } + } + + /** + * Проверяет возможность провести возврат по API + * @return bool Возможность провести возврат по API, true если есть, false если нет + */ + public function getRefundable() + { + return $this->_refundable; + } + + /** + * Устанавливает возможность провести возврат по API + * @param bool $value Возможность провести возврат по API + * + * @throws EmptyPropertyValueException Выбрасывается если переданный аргумент пуст + * @throws InvalidPropertyValueTypeException Выбрасывается если переданный аргумент не кастится в булево значение + */ + public function setRefundable($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty payment refundable flag value', 0, 'Payment.refundable'); + } elseif (TypeCast::canCastToBoolean($value)) { + $this->_refundable = (bool)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid payment refundable flag value type', 0, 'Payment.refundable', $value + ); + } + } + + /** + * Возвращает состояние регистрации фискального чека + * @return string Состояние регистрации фискального чека + */ + public function getReceiptRegistration() + { + return $this->_receiptRegistration; + } + + /** + * Устанавливает состояние регистрации фискального чека + * @param string $value Состояние регистрации фискального чека + * + * @throws InvalidPropertyValueException Выбрасывается если переданное состояние регистрации не существует + * @throws InvalidPropertyValueTypeException Выбрасывается если переданный аргумент не строка + */ + public function setReceiptRegistration($value) + { + if ($value === null || $value === '') { + $this->_receiptRegistration = null; + } elseif (TypeCast::canCastToEnumString($value)) { + if (ReceiptRegistrationStatus::valueExists($value)) { + $this->_receiptRegistration = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid receipt_registration value', 0, 'payment.receiptRegistration', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid receipt_registration value type', 0, 'payment.receiptRegistration', $value + ); + } + } + + /** + * Возвращает метаданные платежа установленные мерчантом + * @return Metadata Метаданные платежа указанные мерчантом + */ + public function getMetadata() + { + return $this->_metadata; + } + + /** + * Устанавливает метаданные платежа + * @param Metadata $value Метаданные платежа указанные мерчантом + */ + public function setMetadata(Metadata $value) + { + $this->_metadata = $value; + } + + /** + * Возвращает время до которого можно бесплатно отменить или подтвердить платеж или null если оно не задано + * @return \DateTime|null Время, до которого можно бесплатно отменить или подтвердить платеж + * + * @since 1.0.2 + */ + public function getExpiresAt() + { + return $this->_expiresAt; + } + + /** + * Устанавливает время до которого можно бесплатно отменить или подтвердить платеж + * @param \DateTime|string|int|null $value Время, до которого можно бесплатно отменить или подтвердить платеж + * + * @throws InvalidPropertyValueException Выбрасывается если передали строку, которую не удалось привести к дате + * @throws InvalidPropertyValueTypeException|\Exception Выбрасывается если был передан аргумент, который невозможно + * интерпретировать как дату или время + * + * @since 1.0.2 + */ + public function setExpiresAt($value) + { + if ($value === null || $value === '') { + $this->_expiresAt = null; + } elseif (TypeCast::canCastToDateTime($value)) { + $dateTime = TypeCast::castToDateTime($value); + if ($dateTime === null) { + throw new InvalidPropertyValueException('Invalid expires_at value', 0, 'payment.expires_at', $value); + } + $this->_expiresAt = $dateTime; + } else { + throw new InvalidPropertyValueTypeException('Invalid expires_at value', 0, 'payment.expires_at', $value); + } + } + + /** + * Возвращает комментарий к статусу canceled: кто отменил платеж и по какой причине + * @return CancellationDetailsInterface|null Комментарий к статусу canceled + * @since 1.0.13 + */ + public function getCancellationDetails() + { + return $this->_cancellationDetails; + } + + /** + * Устанавливает комментарий к статусу canceled: кто отменил платеж и по какой причине + * @param CancellationDetailsInterface $value Комментарий к статусу canceled + */ + public function setCancellationDetails(CancellationDetailsInterface $value) + { + $this->_cancellationDetails = $value; + } + /** + * Возвращает данные об авторизации платежа + * @return AuthorizationDetailsInterface|null Данные об авторизации платежа + * @since 1.0.18 + */ + public function getAuthorizationDetails() + { + return $this->_authorizationDetails; + } + + /** + * Устанавливает данные об авторизации платежа + * @param AuthorizationDetailsInterface $value Данные об авторизации платежа + */ + public function setAuthorizationDetails(AuthorizationDetailsInterface $value) + { + $this->_authorizationDetails = $value; + } + + /** + * Устанавливает transfers (массив распределения денег между магазинами) + * @param $value + */ + public function setTransfers($value) + { + if (!is_array($value)) { + $message = 'Transfers must be an array of TransferInterface'; + throw new InvalidPropertyValueTypeException($message, 0, 'Payment.transfers', $value); + } + + foreach ($value as $item) { + if (!($item instanceof TransferInterface)) { + $message = 'Transfers must be an array of TransferInterface'; + throw new InvalidPropertyValueTypeException($message, 0, 'Payment.transfers', $value); + } + } + + $this->_transfers = $value; + } + + public function getTransfers() + { + return $this->_transfers; + } + + /** + * @param MonetaryAmount $amount + */ + public function setIncomeAmount(MonetaryAmount $amount) + { + $this->_incomeAmount = $amount; + } + + public function getIncomeAmount() + { + return $this->_incomeAmount; + } + + /** + * @param $value + */ + public function setRequestor($value) + { + if (is_array($value)) { + $value = new Requestor($value); + } + + if (!($value instanceof RequestorInterface)) { + throw new InvalidPropertyValueTypeException('Invalid Requestor type', 0, 'Payment.requestor', $value); + } + + $this->_requestor = $value; + } + + /** + * @return RequestorInterface + */ + public function getRequestor() + { + return $this->_requestor; + } + + /** + * @return bool + */ + public function getTest() + { + return $this->_test; + } + + /** + * @param bool $test + */ + public function setTest($test) + { + if ($test === null || $test === '') { + throw new EmptyPropertyValueException('Empty payment test flag value', 0, 'Payment.test'); + } elseif (TypeCast::canCastToBoolean($test)) { + $this->_test = (bool)$test; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid payment test flag value type', 0, 'Payment.test', $test + ); + } + } +} \ No newline at end of file diff --git a/lib/Model/PaymentData/AbstractPaymentData.php b/lib/Model/PaymentData/AbstractPaymentData.php new file mode 100644 index 00000000..bb91a547 --- /dev/null +++ b/lib/Model/PaymentData/AbstractPaymentData.php @@ -0,0 +1,78 @@ +_type; + } + + /** + * @param string $value + */ + protected function _setType($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty payment data type', 0, 'paymentData.type' + ); + } elseif (TypeCast::canCastToEnumString($value)) { + if (PaymentMethodType::valueExists($value)) { + $this->_type = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid value for "type" parameter in PaymentData', 0, 'paymentData.type', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for "type" parameter in PaymentData', 0, 'paymentData.type', $value + ); + } + } +} diff --git a/lib/Model/PaymentData/B2b/Sberbank/VatData.php b/lib/Model/PaymentData/B2b/Sberbank/VatData.php new file mode 100644 index 00000000..7e94f4a3 --- /dev/null +++ b/lib/Model/PaymentData/B2b/Sberbank/VatData.php @@ -0,0 +1,167 @@ +setType($type); + } + if ($rate !== null) { + $this->setRate($rate); + } + if ($amount !== null) { + $this->setAmount($amount); + } + } + + /** + * @return string Способ расчёта НДС + */ + public function getType() + { + return $this->_type; + } + + /** + * Устанавливает способ расчёта НДС + * @param string $value Способ расчёта НДС + * + * @throws InvalidPropertyValueException Выбрасывается если переданная строка не является валидным способом + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setType($value) + { + if (TypeCast::canCastToEnumString($value)) { + if (!VatDataType::valueExists((string)$value)) { + throw new InvalidPropertyValueException('Invalid B2bSberbankVatData.type value', 0, + 'B2bSberbankVatData.type', $value); + } + $this->_type = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid B2bSberbankVatData.type value type', 0, 'B2bSberbankVatData.type', $value + ); + } + } + + /** + * @return string Налоговая ставка НДС + */ + public function getRate() + { + return $this->_rate; + } + + /** + * Устанавливает налоговую ставку НДС + * @param string $value Налоговая ставка НДС + * + * @throws InvalidPropertyValueException Выбрасывается если переданная строка не является валидной ставкой + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setRate($value) + { + if (TypeCast::canCastToString($value)) { + if (!VatDataRate::valueExists((string)$value)) { + throw new InvalidPropertyValueException('Invalid B2bSberbankVatData.rate value', 0, + 'B2bSberbankVatData.rate', $value); + } + $this->_rate = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid B2bSberbankVatData.rate value type', 0, 'B2bSberbankVatData.rate', $value + ); + } + } + + /** + * Возвращает сумму НДС + * @return AmountInterface Сумма НДС + */ + public function getAmount() + { + return $this->_amount; + } + + /** + * Устанавливает сумму НДС + * @param AmountInterface|array|null $value Сумма НДС + */ + public function setAmount($value) + { + if ($value === null) { + $this->_amount = null; + } elseif ($value instanceof AmountInterface) { + $this->_amount = $value; + } elseif (is_array($value)) { + $this->_amount = new MonetaryAmount(); + $this->_amount->fromArray($value); + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid B2bSberbankVatData.amount value type', 0, 'B2bSberbankVatData.amount', $value + ); + } + } + +} diff --git a/lib/Model/PaymentData/B2b/Sberbank/VatDataInterface.php b/lib/Model/PaymentData/B2b/Sberbank/VatDataInterface.php new file mode 100644 index 00000000..74ddbe6a --- /dev/null +++ b/lib/Model/PaymentData/B2b/Sberbank/VatDataInterface.php @@ -0,0 +1,60 @@ + true, + self::RATE_10 => true, + self::RATE_18 => true, + self::RATE_20 => true, + ); + +} diff --git a/lib/Model/PaymentData/B2b/Sberbank/VatDataType.php b/lib/Model/PaymentData/B2b/Sberbank/VatDataType.php new file mode 100644 index 00000000..edc3575e --- /dev/null +++ b/lib/Model/PaymentData/B2b/Sberbank/VatDataType.php @@ -0,0 +1,51 @@ + true, + self::MIXED => true, + self::UNTAXED => true, + ); + +} diff --git a/lib/Model/PaymentData/PaymentDataAlfabank.php b/lib/Model/PaymentData/PaymentDataAlfabank.php new file mode 100644 index 00000000..655ed305 --- /dev/null +++ b/lib/Model/PaymentData/PaymentDataAlfabank.php @@ -0,0 +1,74 @@ +_setType(PaymentMethodType::ALFABANK); + } + + /** + * @return string Имя пользователя в Альфа-Клике + */ + public function getLogin() + { + return $this->_login; + } + + /** + * @param string $value Имя пользователя в Альфа-Клике + */ + public function setLogin($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty login value', 0, 'PaymentDataAlfabank.login'); + } elseif (TypeCast::canCastToString($value)) { + $this->_login = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid login value type', 0, 'PaymentDataAlfabank.login', $value + ); + } + } +} diff --git a/lib/Model/PaymentData/PaymentDataApplePay.php b/lib/Model/PaymentData/PaymentDataApplePay.php new file mode 100644 index 00000000..fc60948c --- /dev/null +++ b/lib/Model/PaymentData/PaymentDataApplePay.php @@ -0,0 +1,78 @@ +_setType(PaymentMethodType::APPLE_PAY); + } + + /** + * @return string содержимое поля paymentData объекта PKPaymentToken, закодированное в Base64 + */ + public function getPaymentData() + { + return $this->_paymentData; + } + + /** + * @param string $value содержимое поля paymentData объекта PKPaymentToken, закодированное в Base64 + */ + public function setPaymentData($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty value for paymentData', 0, 'PaymentDataApplePay.paymentData' + ); + } elseif (TypeCast::canCastToString($value)) { + $this->_paymentData = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for paymentData', 0, 'PaymentDataApplePay.paymentData', $value + ); + } + } +} diff --git a/lib/Model/PaymentData/PaymentDataB2bSberbank.php b/lib/Model/PaymentData/PaymentDataB2bSberbank.php new file mode 100644 index 00000000..b55caf79 --- /dev/null +++ b/lib/Model/PaymentData/PaymentDataB2bSberbank.php @@ -0,0 +1,120 @@ +_setType(PaymentMethodType::B2B_SBERBANK); + } + + /** + * @return string Назначение платежа + */ + public function getPaymentPurpose() + { + return $this->_paymentPurpose; + } + + /** + * @param string $value Назначение платежа + */ + public function setPaymentPurpose($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty paymentPurpose value', 0, + 'PaymentDataB2bSberbank.paymentPurpose'); + } elseif (TypeCast::canCastToString($value)) { + if (preg_match('/^.{1,210}$/', $value)) { + $this->_paymentPurpose = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid paymentPurpose value', 0, 'PaymentDataB2bSberbank.paymentPurpose', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid paymentPurpose value type', 0, 'PaymentDataB2bSberbank.paymentPurpose', $value + ); + } + } + + /** + * @return VatData Данные об НДС + */ + public function getVatData() + { + return $this->_vatData; + } + + /** + * @param VatData|array|null $value Данные об НДС + */ + public function setVatData($value) + { + if ($value === null || $value === array()) { + $this->_vatData = null; + } elseif ($value instanceof VatData) { + $this->_vatData = $value; + } elseif (is_array($value) || $value instanceof \Traversable) { + $vatData = new VatData(); + foreach ($value as $property => $val) { + $vatData->offsetSet($property, $val); + } + $this->_vatData = $vatData; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid vatData value type in PaymentDataB2BSberbank', 0, + 'PaymentDataB2BSberbank.vatData', $value + ); + } + } +} diff --git a/lib/Model/PaymentData/PaymentDataBankCard.php b/lib/Model/PaymentData/PaymentDataBankCard.php new file mode 100644 index 00000000..597b8606 --- /dev/null +++ b/lib/Model/PaymentData/PaymentDataBankCard.php @@ -0,0 +1,80 @@ +_setType(PaymentMethodType::BANK_CARD); + } + + /** + * @return PaymentDataBankCardCard Данные банковской карты + */ + public function getCard() + { + return $this->_card; + } + + /** + * @param PaymentDataBankCardCard|array $value Данные банковской карты + */ + public function setCard($value) + { + if ($value === null || $value === '' || $value === array()) { + $this->_card = null; + } elseif (is_object($value) && $value instanceof PaymentDataBankCardCard) { + $this->_card = $value; + } elseif (is_array($value) || $value instanceof \Traversable) { + $card = new PaymentDataBankCardCard(); + foreach ($value as $property => $val) { + $card->offsetSet($property, $val); + } + $this->_card = $card; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid card value type in PaymentDataBankCard', 0, 'PaymentDataBankCard.card', $value + ); + } + } +} diff --git a/lib/Model/PaymentData/PaymentDataBankCardCard.php b/lib/Model/PaymentData/PaymentDataBankCardCard.php new file mode 100644 index 00000000..b5898cb0 --- /dev/null +++ b/lib/Model/PaymentData/PaymentDataBankCardCard.php @@ -0,0 +1,239 @@ +_number; + } + + /** + * @param string $value Номер банковской карты + */ + public function setNumber($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty card number value', 0, 'PaymentDataBankCardCard.number'); + } elseif (TypeCast::canCastToString($value)) { + if (preg_match('/^[0-9]{16,19}$/', (string)$value)) { + $this->_number = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid card number value', 0, 'PaymentDataBankCardCard.number', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid card number value type', 0, 'PaymentDataBankCardCard.number', $value + ); + } + } + + /** + * @return string Срок действия, год, YYYY + */ + public function getExpiryYear() + { + return $this->_expiryYear; + } + + /** + * @param string $value Срок действия, год, YYYY + */ + public function setExpiryYear($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty card expiry year value', 0, 'PaymentDataBankCardCard.expiryYear' + ); + } elseif (is_numeric($value)) { + if (!preg_match('/^\d\d\d\d$/', $value) || $value < 2000 || $value > 2200) { + throw new InvalidPropertyValueException( + 'Invalid card expiry year value', 0, 'PaymentDataBankCardCard.expiryYear', $value + ); + } + $this->_expiryYear = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid card expiry year value', 0, 'PaymentDataBankCardCard.expiryYear', $value + ); + } + } + + /** + * @return string Срок действия, месяц, MM + */ + public function getExpiryMonth() + { + return $this->_expiryMonth; + } + + /** + * @param string $value Срок действия, месяц, MM + */ + public function setExpiryMonth($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty card expiry month value', 0, 'PaymentDataBankCardCard.expiryMonth' + ); + } elseif (is_numeric($value)) { + if (!preg_match('/^\d\d$/', $value)) { + throw new InvalidPropertyValueException( + 'Invalid card expiry month value', 0, 'PaymentDataBankCardCard.expiryMonth', $value + ); + } + if (is_string($value) && $value[0] == '0') { + $month = (int)($value[1]); + } else { + $month = (int)$value; + } + if ($month < 1 || $month > 12) { + throw new InvalidPropertyValueException( + 'Invalid card expiry month value', 0, 'PaymentDataBankCardCard.expiryMonth', $value + ); + } else { + $this->_expiryMonth = (string)$value; + } + } else { + throw new InvalidPropertyValueException( + 'Invalid card expiry month value', 0, 'PaymentDataBankCardCard.expiryMonth', $value + ); + } + } + + /** + * @return string CVV2/CVC2 код + */ + public function getCsc() + { + return $this->_csc; + } + + /** + * @param string $value CVV2/CVC2 код + */ + public function setCsc($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty card CSC code value', 0, 'PaymentDataBankCardCard.csc' + ); + } elseif (is_numeric($value)) { + if (preg_match('/^\d{3,4}$/', $value)) { + $this->_csc = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid card CSC code value', 0, 'PaymentDataBankCardCard.csc', $value + ); + } + } else { + throw new InvalidPropertyValueException( + 'Invalid card CSC code value', 0, 'PaymentDataBankCardCard.csc', $value + ); + } + } + + /** + * @return string Имя держателя карты + */ + public function getCardholder() + { + return $this->_cardholder; + } + + /** + * @param string $value Имя держателя карты + */ + public function setCardholder($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty card holder value', 0, 'PaymentDataBankCardCard.cardholder' + ); + } elseif (TypeCast::canCastToString($value)) { + if (preg_match('/^[a-zA-Z\s]{1,26}$/', $value)) { + $this->_cardholder = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid card holder value', 0, 'PaymentDataBankCardCard.cardholder', $value + ); + } + } else { + throw new InvalidPropertyValueException( + 'Invalid card holder value', 0, 'PaymentDataBankCardCard.cardholder', $value + ); + } + } +} diff --git a/lib/Model/PaymentData/PaymentDataCash.php b/lib/Model/PaymentData/PaymentDataCash.php new file mode 100644 index 00000000..86c06bec --- /dev/null +++ b/lib/Model/PaymentData/PaymentDataCash.php @@ -0,0 +1,81 @@ +_setType(PaymentMethodType::CASH); + } + + /** + * @return string + */ + public function getPhone() + { + return $this->_phone; + } + + /** + * @param string $value + */ + public function setPhone($value) + { + if ($value === null || $value === '') { + $this->_phone = null; + } elseif (TypeCast::canCastToString($value)) { + if (preg_match('/^[0-9]{4,15}$/', $value)) { + $this->_phone = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid phone value', 0, 'PaymentDataCash.phone', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid phone value type', 0, 'PaymentDataCash.phone', $value + ); + } + } +} diff --git a/lib/Model/PaymentData/PaymentDataFactory.php b/lib/Model/PaymentData/PaymentDataFactory.php new file mode 100644 index 00000000..f309d8d4 --- /dev/null +++ b/lib/Model/PaymentData/PaymentDataFactory.php @@ -0,0 +1,95 @@ + 'PaymentDataYooMoney', + PaymentMethodType::BANK_CARD => 'PaymentDataBankCard', + PaymentMethodType::SBERBANK => 'PaymentDataSberbank', + PaymentMethodType::CASH => 'PaymentDataCash', + PaymentMethodType::MOBILE_BALANCE => 'PaymentDataMobileBalance', + PaymentMethodType::APPLE_PAY => 'PaymentDataApplePay', + PaymentMethodType::GOOGLE_PAY => 'PaymentDataGooglePay', + PaymentMethodType::QIWI => 'PaymentDataQiwi', + PaymentMethodType::WEBMONEY => 'PaymentDataWebmoney', + PaymentMethodType::ALFABANK => 'PaymentDataAlfabank', + PaymentMethodType::INSTALLMENTS => 'PaymentDataInstallments', + PaymentMethodType::B2B_SBERBANK => 'PaymentDataB2bSberbank', + PaymentMethodType::TINKOFF_BANK => 'PaymentDataTinkoffBank', + PaymentMethodType::WECHAT => 'PaymentDataWechat', + ); + + /** + * @param string $type + * + * @return AbstractPaymentData + */ + public function factory($type) + { + if (!is_string($type)) { + throw new \InvalidArgumentException('Invalid payment type value in payment factory'); + } + if (!array_key_exists($type, $this->typeClassMap)) { + throw new \InvalidArgumentException('Invalid payment data type "'.$type.'"'); + } + $className = __NAMESPACE__.'\\'.$this->typeClassMap[$type]; + + return new $className(); + } + + /** + * @param array $data + * @param string|null $type + * + * @return AbstractPaymentData + */ + public function factoryFromArray(array $data, $type = null) + { + if ($type === null) { + if (array_key_exists('type', $data)) { + $type = $data['type']; + unset($data['type']); + } else { + throw new \InvalidArgumentException( + 'Parameter type not specified in PaymentDataFactory.factoryFromArray()' + ); + } + } + $paymentData = $this->factory($type); + foreach ($data as $key => $value) { + if ($paymentData->offsetExists($key)) { + $paymentData->offsetSet($key, $value); + } + } + + return $paymentData; + } +} diff --git a/lib/Model/PaymentData/PaymentDataGooglePay.php b/lib/Model/PaymentData/PaymentDataGooglePay.php new file mode 100644 index 00000000..6465dfd0 --- /dev/null +++ b/lib/Model/PaymentData/PaymentDataGooglePay.php @@ -0,0 +1,108 @@ +_setType(PaymentMethodType::GOOGLE_PAY); + } + + /** + * @return string Криптограмма Payment Token Cryptography для проведения оплаты через Google Pay + */ + public function getPaymentMethodToken() + { + return $this->_paymentMethodToken; + } + + /** + * @param string $value Криптограмма Payment Token Cryptography для проведения оплаты через Google Pay + */ + public function setPaymentMethodToken($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty value for paymentMethodToken', 0, 'PaymentDataGooglePay.paymentMethodToken' + ); + } elseif (TypeCast::canCastToString($value)) { + $this->_paymentMethodToken = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for paymentMethodToken', 0, 'PaymentDataGooglePay.paymentMethodToken', $value + ); + } + } + + /** + * @return string Уникальный идентификатор транзакции, выданный Google + */ + public function getGoogleTransactionId() + { + return $this->_googleTransactionId; + } + + /** + * @param string $value Уникальный идентификатор транзакции, выданный Google + */ + public function setGoogleTransactionId($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty value for googleTransactionId', 0, 'PaymentDataGooglePay.googleTransactionId' + ); + } elseif (TypeCast::canCastToString($value)) { + $this->_googleTransactionId = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for googleTransactionId', 0, 'PaymentDataGooglePay.googleTransactionId', $value + ); + } + } +} diff --git a/lib/Model/PaymentData/PaymentDataInstallments.php b/lib/Model/PaymentData/PaymentDataInstallments.php new file mode 100644 index 00000000..e103542d --- /dev/null +++ b/lib/Model/PaymentData/PaymentDataInstallments.php @@ -0,0 +1,40 @@ +_setType(PaymentMethodType::INSTALLMENTS); + } +} diff --git a/lib/Model/PaymentData/PaymentDataMobileBalance.php b/lib/Model/PaymentData/PaymentDataMobileBalance.php new file mode 100644 index 00000000..f26bff73 --- /dev/null +++ b/lib/Model/PaymentData/PaymentDataMobileBalance.php @@ -0,0 +1,82 @@ +_setType(PaymentMethodType::MOBILE_BALANCE); + } + + /** + * @return string + */ + public function getPhone() + { + return $this->_phone; + } + + /** + * @param string $value + */ + public function setPhone($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty phone value', 0, 'PaymentDataMobileBalance.phone'); + } elseif (TypeCast::canCastToString($value)) { + if (preg_match('/^[0-9]{4,15}$/', $value)) { + $this->_phone = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid phone value', 0, 'PaymentDataMobileBalance.phone', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid phone value type', 0, 'PaymentDataMobileBalance.phone', $value + ); + } + } +} diff --git a/lib/Model/PaymentData/PaymentDataQiwi.php b/lib/Model/PaymentData/PaymentDataQiwi.php new file mode 100644 index 00000000..5f6542f6 --- /dev/null +++ b/lib/Model/PaymentData/PaymentDataQiwi.php @@ -0,0 +1,81 @@ +_setType(PaymentMethodType::QIWI); + } + + /** + * @return string + */ + public function getPhone() + { + return $this->_phone; + } + + /** + * @param string $value + */ + public function setPhone($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty phone value', 0, 'PaymentDataQiwi.phone'); + } elseif (TypeCast::canCastToString($value)) { + if (preg_match('/^[0-9]{4,15}$/', $value)) { + $this->_phone = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid phone value', 0, 'PaymentDataQiwi.phone', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid phone value type', 0, 'PaymentDataQiwi.phone', $value + ); + } + } +} diff --git a/lib/Model/PaymentData/PaymentDataSberbank.php b/lib/Model/PaymentData/PaymentDataSberbank.php new file mode 100644 index 00000000..57cf11a2 --- /dev/null +++ b/lib/Model/PaymentData/PaymentDataSberbank.php @@ -0,0 +1,86 @@ +_setType(PaymentMethodType::SBERBANK); + } + + /** + * @return string + */ + public function getPhone() + { + return $this->_phone; + } + + /** + * @param string $value + */ + public function setPhone($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty phone value', 0, 'PaymentDataSberbank.phone'); + } elseif (TypeCast::canCastToString($value)) { + if (preg_match('/^[0-9]{4,15}$/', $value)) { + $this->_phone = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid phone value', 0, 'PaymentDataSberbank.phone', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid phone value type', 0, 'PaymentDataSberbank.phone', $value + ); + } + } +} diff --git a/lib/Model/PaymentData/PaymentDataTinkoffBank.php b/lib/Model/PaymentData/PaymentDataTinkoffBank.php new file mode 100644 index 00000000..b5a2fc52 --- /dev/null +++ b/lib/Model/PaymentData/PaymentDataTinkoffBank.php @@ -0,0 +1,37 @@ +_setType(PaymentMethodType::TINKOFF_BANK); + } +} \ No newline at end of file diff --git a/lib/Model/PaymentData/PaymentDataWebmoney.php b/lib/Model/PaymentData/PaymentDataWebmoney.php new file mode 100644 index 00000000..7a4a68ab --- /dev/null +++ b/lib/Model/PaymentData/PaymentDataWebmoney.php @@ -0,0 +1,41 @@ +_setType(PaymentMethodType::WEBMONEY); + } +} diff --git a/lib/Model/PaymentData/PaymentDataWechat.php b/lib/Model/PaymentData/PaymentDataWechat.php new file mode 100644 index 00000000..39a2690d --- /dev/null +++ b/lib/Model/PaymentData/PaymentDataWechat.php @@ -0,0 +1,40 @@ +_setType(PaymentMethodType::WECHAT); + } +} \ No newline at end of file diff --git a/lib/Model/PaymentData/PaymentDataYooMoney.php b/lib/Model/PaymentData/PaymentDataYooMoney.php new file mode 100644 index 00000000..d6c40167 --- /dev/null +++ b/lib/Model/PaymentData/PaymentDataYooMoney.php @@ -0,0 +1,40 @@ +_setType(PaymentMethodType::YOO_MONEY); + } +} diff --git a/lib/Model/PaymentInterface.php b/lib/Model/PaymentInterface.php new file mode 100644 index 00000000..a1183d68 --- /dev/null +++ b/lib/Model/PaymentInterface.php @@ -0,0 +1,172 @@ +_type; + } + + /** + * @param string $value Тип объекта + */ + protected function _setType($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty payment data type', 0, 'PaymentMethod.type' + ); + } elseif (TypeCast::canCastToEnumString($value)) { + if (PaymentMethodType::valueExists($value)) { + $this->_type = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid value for "type" parameter in PaymentMethod', 0, 'PaymentMethod.type', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for "type" parameter in PaymentMethod', 0, 'PaymentMethod.type', $value + ); + } + } + + /** + * @return string Идентификатор записи о сохраненных платежных данных + */ + public function getId() + { + return $this->_id; + } + + /** + * @param string $value Идентификатор записи о сохраненных платежных данных + */ + public function setId($value) + { + if ($value === null || $value === '') { + $this->_id = null; + } elseif (TypeCast::canCastToString($value)) { + $this->_id = (string)$value; + } else { + throw new InvalidPropertyValueTypeException('Invalid id value type', 0, 'PaymentMethod.id', $value); + } + } + + /** + * @return bool Возможность многократного использования + */ + public function getSaved() + { + return $this->_saved; + } + + /** + * @param bool $value Возможность многократного использования + */ + public function setSaved($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty saved value', 0, 'PaymentMethod.saved'); + } elseif (TypeCast::canCastToBoolean($value)) { + $this->_saved = (bool)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid saved value type', 0, 'PaymentMethod.saved', $value + ); + } + } + + /** + * @return string|null Название метода оплаты + */ + public function getTitle() + { + return $this->_title; + } + + /** + * @param string $value Название метода оплаты + */ + public function setTitle($value) + { + if ($value === null || $value === '') { + $this->_title = null; + } elseif (TypeCast::canCastToString($value)) { + $this->_title = (string)$value; + } else { + throw new InvalidPropertyValueTypeException('Invalid title value type', 0, 'PaymentMethod.title', $value); + } + } +} diff --git a/lib/Model/PaymentMethod/B2b/Sberbank/PayerBankDetails.php b/lib/Model/PaymentMethod/B2b/Sberbank/PayerBankDetails.php new file mode 100644 index 00000000..d75afec2 --- /dev/null +++ b/lib/Model/PaymentMethod/B2b/Sberbank/PayerBankDetails.php @@ -0,0 +1,243 @@ +_fullName; + } + + /** + * @param string $value + */ + public function setFullName($value) + { + $this->_fullName = $value; + } + + /** + * Возвращает сокращенное наименование организации + * @return string Сокращенное наименование организации + */ + public function getShortName() + { + return $this->_shortName; + } + + /** + * @param string $value + */ + public function setShortName($value) + { + $this->_shortName = $value; + } + + /** + * Возвращает адрес организации + * @return string Адрес организации + */ + public function getAddress() + { + return $this->_address; + } + + /** + * @param string $value + */ + public function setAddress($value) + { + $this->_address = $value; + } + + /** + * Возвращает ИНН организации + * @return string ИНН организации + */ + public function getInn() + { + return $this->_inn; + } + + /** + * @param string $value + */ + public function setInn($value) + { + $this->_inn = $value; + } + + /** + * Возвращает КПП организации + * @return string КПП организации + */ + public function getKpp() + { + return $this->_kpp; + } + + /** + * @param string $value + */ + public function setKpp($value) + { + $this->_kpp = $value; + } + + /** + * Возвращает наименование банка организации + * @return string Наименование банка организации + */ + public function getBankName() + { + return $this->_bankName; + } + + /** + * @param string $value + */ + public function setBankName($value) + { + $this->_bankName = $value; + } + + /** + * Возвращает отделение банка организации + * @return string Отделение банка организации + */ + public function getBankBranch() + { + return $this->_bankBranch; + } + + /** + * @param string $value + */ + public function setBankBranch($value) + { + $this->_bankBranch = $value; + } + + /** + * Возвращает БИК банка организации + * @return string БИК банка организации + */ + public function getBankBik() + { + return $this->_bankBik; + } + + /** + * @param string $value + */ + public function setBankBik($value) + { + $this->_bankBik = $value; + } + + /** + * Возвращает номер счета организации + * @return string Номер счета организации + */ + public function getAccount() + { + return $this->_account; + } + + /** + * @param string $value + */ + public function setAccount($value) + { + $this->_account = $value; + } + +} \ No newline at end of file diff --git a/lib/Model/PaymentMethod/B2b/Sberbank/PayerBankDetailsInterface.php b/lib/Model/PaymentMethod/B2b/Sberbank/PayerBankDetailsInterface.php new file mode 100644 index 00000000..6e797bb3 --- /dev/null +++ b/lib/Model/PaymentMethod/B2b/Sberbank/PayerBankDetailsInterface.php @@ -0,0 +1,101 @@ + true, + self::GOOGLE_PAY => true, + ); +} \ No newline at end of file diff --git a/lib/Model/PaymentMethod/PaymentMethodAlfaBank.php b/lib/Model/PaymentMethod/PaymentMethodAlfaBank.php new file mode 100644 index 00000000..da78cd76 --- /dev/null +++ b/lib/Model/PaymentMethod/PaymentMethodAlfaBank.php @@ -0,0 +1,74 @@ +_setType(PaymentMethodType::ALFABANK); + } + + /** + * @return string Имя пользователя в Альфа-Клике + */ + public function getLogin() + { + return $this->_login; + } + + /** + * @param string $value Имя пользователя в Альфа-Клике + */ + public function setLogin($value) + { + if ($value === null) { + $this->_login = ''; + } elseif (TypeCast::canCastToString($value)) { + $this->_login = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid login value type', 0, 'PaymentMethodAlfaBank.login', $value + ); + } + } +} diff --git a/lib/Model/PaymentMethod/PaymentMethodApplePay.php b/lib/Model/PaymentMethod/PaymentMethodApplePay.php new file mode 100644 index 00000000..68057e4f --- /dev/null +++ b/lib/Model/PaymentMethod/PaymentMethodApplePay.php @@ -0,0 +1,42 @@ +_setType(PaymentMethodType::APPLE_PAY); + } +} diff --git a/lib/Model/PaymentMethod/PaymentMethodB2bSberbank.php b/lib/Model/PaymentMethod/PaymentMethodB2bSberbank.php new file mode 100644 index 00000000..eddf15df --- /dev/null +++ b/lib/Model/PaymentMethod/PaymentMethodB2bSberbank.php @@ -0,0 +1,124 @@ +_setType(PaymentMethodType::B2B_SBERBANK); + } + + /** + * @return string + */ + public function getPaymentPurpose() + { + return $this->_paymentPurpose; + } + + /** + * @param string $paymentPurpose + */ + public function setPaymentPurpose($paymentPurpose) + { + $this->_paymentPurpose = $paymentPurpose; + } + + /** + * @return VatData + */ + public function getVatData() + { + return $this->_vatData; + } + + /** + * @param VatData $vatData + */ + public function setVatData($vatData) + { + if(is_array($vatData)) { + $value = new VatData(); + $value->fromArray($vatData); + $this->_vatData = $value; + } else if($vatData instanceof VatData){ + $this->_vatData = $vatData; + } else{ + throw new InvalidPropertyValueException('Invalid $vatData property type'); + } + + } + + /** + * @return PayerBankDetails + */ + public function getPayerBankDetails() + { + return $this->_payerBankDetails; + } + + /** + * @param $payerBankDetails + */ + public function setPayerBankDetails($payerBankDetails) + { + if(is_array($payerBankDetails)) { + $value = new PayerBankDetails(); + $value->fromArray($payerBankDetails); + $this->_payerBankDetails = $value; + } else if($payerBankDetails instanceof PayerBankDetails){ + $this->_payerBankDetails = $payerBankDetails; + } else{ + throw new InvalidPropertyValueException('Invalid $payerBankDetails property type'); + } + } +} diff --git a/lib/Model/PaymentMethod/PaymentMethodBankCard.php b/lib/Model/PaymentMethod/PaymentMethodBankCard.php new file mode 100644 index 00000000..7c50b28c --- /dev/null +++ b/lib/Model/PaymentMethod/PaymentMethodBankCard.php @@ -0,0 +1,343 @@ +_setType(PaymentMethodType::BANK_CARD); + } + + /** + * @return string Последние 4 цифры номера карты + */ + public function getLast4() + { + return $this->_last4; + } + + /** + * @param string $value Последние 4 цифры номера карты + */ + public function setLast4($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty card last4 value', 0, 'PaymentMethodBankCard.last4'); + } elseif (TypeCast::canCastToString($value)) { + if (preg_match('/^[0-9]{4}$/', (string)$value)) { + $this->_last4 = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid card last4 value', 0, 'PaymentMethodBankCard.last4', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid card last4 value type', 0, 'PaymentMethodBankCard.last4', $value + ); + } + } + + /** + * @return string + * @since 1.0.14 + */ + public function getFirst6() + { + return $this->_first6; + } + + /** + * @param $value + * @since 1.0.14 + */ + public function setFirst6($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty card first6 value', 0, 'PaymentMethodBankCard.first6'); + } elseif (TypeCast::canCastToString($value)) { + if (preg_match('/^[0-9]{6}$/', (string)$value)) { + $this->_first6 = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid card first6 value', 0, 'PaymentMethodBankCard.first6', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid card first6 value type', 0, 'PaymentMethodBankCard.first6', $value + ); + } + } + + /** + * @return string Срок действия, год + */ + public function getExpiryYear() + { + return $this->_expiryYear; + } + + /** + * @param string $value Срок действия, год + */ + public function setExpiryYear($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty card expiry year value', 0, 'PaymentMethodBankCard.expiryYear' + ); + } elseif (is_numeric($value)) { + if (!preg_match('/^\d\d\d\d$/', $value) || $value < 2000 || $value > 2200) { + throw new InvalidPropertyValueException( + 'Invalid card expiry year value', 0, 'PaymentMethodBankCard.expiryYear', $value + ); + } + $this->_expiryYear = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid card expiry year value', 0, 'PaymentMethodBankCard.expiryYear', $value + ); + } + } + + /** + * @return string Срок действия, месяц + */ + public function getExpiryMonth() + { + return $this->_expiryMonth; + } + + /** + * @param string $value Срок действия, месяц + */ + public function setExpiryMonth($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty card expiry month value', 0, 'PaymentMethodBankCard.expiryMonth' + ); + } elseif (is_numeric($value)) { + if (!preg_match('/^\d\d$/', $value)) { + throw new InvalidPropertyValueException( + 'Invalid card expiry month value', 0, 'PaymentMethodBankCard.expiryMonth', $value + ); + } + if (is_string($value) && $value[0] == '0') { + $month = (int)($value[1]); + } else { + $month = (int)$value; + } + if ($month < 1 || $month > 12) { + throw new InvalidPropertyValueException( + 'Invalid card expiry month value', 0, 'PaymentMethodBankCard.expiryMonth', $value + ); + } else { + $this->_expiryMonth = (string)$value; + } + } else { + throw new InvalidPropertyValueException( + 'Invalid card expiry month value', 0, 'PaymentMethodBankCard.expiryMonth', $value + ); + } + } + + /** + * @return string Тип банковской карты + */ + public function getCardType() + { + return $this->_cardType; + } + + /** + * @param string $value Тип банковской карты + */ + public function setCardType($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty cardType value', 0, 'PaymentMethodBankCard.cardType'); + } elseif (TypeCast::canCastToString($value)) { + $this->_cardType = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid cardType value type', 0, 'PaymentMethodBankCard.cardType', $value + ); + } + } + + /** + * @return string + */ + public function getIssuerCountry() + { + return $this->_issuerCountry; + } + + /** + * @param string $value + */ + public function setIssuerCountry($value) + { + if ($value === null || $value === '') { + $this->_issuerCountry = (string)$value; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid issuerCountry value type', 0, 'PaymentMethodBankCard.issuerCountry', $value + ); + } elseif (strlen($value) !== self::ISO_3166_CODE_LENGTH) { + throw new InvalidPropertyValueException( + 'Invalid issuerCountry value', 0, 'PaymentMethodBankCard.issuerCountry', $value + ); + } + + $this->_issuerCountry = (string)$value; + } + + /** + * @param string $value + */ + public function setIssuerName($value) + { + if ($value === null || $value === '') { + $this->_issuerName = (string)$value; + } elseif (!TypeCast::canCastToString($value)) { + throw new EmptyPropertyValueException( + 'Empty issuerName value', 0, 'PaymentMethodBankCard.issuerName' + ); + } + + $this->_issuerName = (string)$value; + } + + /** + * @return string + */ + public function getIssuerName() + { + return $this->_issuerName; + } + + /** + * @param string $value + */ + public function setSource($value) + { + if ($value === null || $value === '') { + $this->_source = (string)$value; + } elseif (!TypeCast::canCastToEnumString($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid source value type', 0, 'PaymentMethodBankCard.source', $value + ); + } elseif (!BankCardSource::valueExists($value)) { + throw new InvalidPropertyValueException( + 'Invalid source value', 0, 'PaymentMethodBankCard.source', $value + ); + } + + $this->_source = (string)$value; + } + + /** + * @return string + */ + public function getSource() + { + return $this->_source; + } +} diff --git a/lib/Model/PaymentMethod/PaymentMethodCardType.php b/lib/Model/PaymentMethod/PaymentMethodCardType.php new file mode 100644 index 00000000..095c4dec --- /dev/null +++ b/lib/Model/PaymentMethod/PaymentMethodCardType.php @@ -0,0 +1,63 @@ + true, + self::VISA => true, + self::MIR => true, + self::UNION_PAY => true, + self::JCB => true, + self::AMERICAN_EXPRESS => true, + self::DINERS_CLUB => true, + self::UNKNOWN => true, + ); +} \ No newline at end of file diff --git a/lib/Model/PaymentMethod/PaymentMethodCash.php b/lib/Model/PaymentMethod/PaymentMethodCash.php new file mode 100644 index 00000000..9f054f64 --- /dev/null +++ b/lib/Model/PaymentMethod/PaymentMethodCash.php @@ -0,0 +1,42 @@ +_setType(PaymentMethodType::CASH); + } +} diff --git a/lib/Model/PaymentMethod/PaymentMethodFactory.php b/lib/Model/PaymentMethod/PaymentMethodFactory.php new file mode 100644 index 00000000..3bdff079 --- /dev/null +++ b/lib/Model/PaymentMethod/PaymentMethodFactory.php @@ -0,0 +1,114 @@ + 'PaymentMethodYooMoney', + PaymentMethodType::BANK_CARD => 'PaymentMethodBankCard', + PaymentMethodType::SBERBANK => 'PaymentMethodSberbank', + PaymentMethodType::CASH => 'PaymentMethodCash', + PaymentMethodType::MOBILE_BALANCE => 'PaymentMethodMobileBalance', + PaymentMethodType::APPLE_PAY => 'PaymentMethodApplePay', + PaymentMethodType::GOOGLE_PAY => 'PaymentMethodGooglePay', + PaymentMethodType::QIWI => 'PaymentMethodQiwi', + PaymentMethodType::WEBMONEY => 'PaymentMethodWebmoney', + PaymentMethodType::ALFABANK => 'PaymentMethodAlfaBank', + PaymentMethodType::INSTALLMENTS => 'PaymentMethodInstallments', + PaymentMethodType::B2B_SBERBANK => 'PaymentMethodB2bSberbank', + PaymentMethodType::TINKOFF_BANK => 'PaymentMethodTinkoffBank', + PaymentMethodType::PSB => 'PaymentMethodPsb', + PaymentMethodType::WECHAT => 'PaymentMethodWechat', + ); + + private $optionsMap = array( + 'card_type' => 'cardType', + 'expiry_month' => 'expiryMonth', + 'expiry_year' => 'expiryYear', + 'account_number' => 'accountNumber', + ); + + /** + * @param string $type + * + * @return AbstractPaymentMethod + */ + public function factory($type) + { + if (!is_string($type)) { + throw new \InvalidArgumentException('Invalid payment method type value in payment factory'); + } + if (!array_key_exists($type, $this->typeClassMap)) { + throw new \InvalidArgumentException('Invalid payment method data type "'.$type.'"'); + } + $className = __NAMESPACE__.'\\'.$this->typeClassMap[$type]; + + return new $className(); + } + + /** + * @param array $data + * @param string|null $type + * + * @return AbstractPaymentMethod + */ + public function factoryFromArray(array $data, $type = null) + { + if ($type === null) { + if (array_key_exists('type', $data)) { + $type = $data['type']; + unset($data['type']); + } else { + throw new \InvalidArgumentException( + 'Parameter type not specified in PaymentDataFactory.factoryFromArray()' + ); + } + } + + $paymentData = $this->factory($type); + $this->fillModel($paymentData, $data); + + return $paymentData; + } + + private function fillModel(AbstractPaymentMethod $paymentData, array $data) + { + foreach ($data as $key => $value) { + if (array_key_exists($key, $this->optionsMap)) { + $key = $this->optionsMap[$key]; + } + if ($paymentData->offsetExists($key)) { + $paymentData->offsetSet($key, $value); + } else if (is_array($value)) { + $this->fillModel($paymentData, $value); + } + } + } +} \ No newline at end of file diff --git a/lib/Model/PaymentMethod/PaymentMethodGooglePay.php b/lib/Model/PaymentMethod/PaymentMethodGooglePay.php new file mode 100644 index 00000000..53db42e6 --- /dev/null +++ b/lib/Model/PaymentMethod/PaymentMethodGooglePay.php @@ -0,0 +1,42 @@ +_setType(PaymentMethodType::GOOGLE_PAY); + } +} diff --git a/lib/Model/PaymentMethod/PaymentMethodInstallments.php b/lib/Model/PaymentMethod/PaymentMethodInstallments.php new file mode 100644 index 00000000..df110079 --- /dev/null +++ b/lib/Model/PaymentMethod/PaymentMethodInstallments.php @@ -0,0 +1,42 @@ +_setType(PaymentMethodType::INSTALLMENTS); + } +} diff --git a/lib/Model/PaymentMethod/PaymentMethodMobileBalance.php b/lib/Model/PaymentMethod/PaymentMethodMobileBalance.php new file mode 100644 index 00000000..291ce376 --- /dev/null +++ b/lib/Model/PaymentMethod/PaymentMethodMobileBalance.php @@ -0,0 +1,83 @@ +_setType(PaymentMethodType::MOBILE_BALANCE); + } + + /** + * @return string + */ + public function getPhone() + { + return $this->_phone; + } + + /** + * @param string $value + */ + public function setPhone($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty phone value', 0, 'PaymentMethodMobileBalance.phone'); + } elseif (TypeCast::canCastToString($value)) { + if (preg_match('/^[0-9]{4,15}$/', $value)) { + $this->_phone = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid phone value', 0, 'PaymentMethodMobileBalance.phone', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid phone value type', 0, 'PaymentMethodMobileBalance.phone', $value + ); + } + } +} diff --git a/lib/Model/PaymentMethod/PaymentMethodPsb.php b/lib/Model/PaymentMethod/PaymentMethodPsb.php new file mode 100644 index 00000000..704ed65d --- /dev/null +++ b/lib/Model/PaymentMethod/PaymentMethodPsb.php @@ -0,0 +1,37 @@ +_setType(PaymentMethodType::PSB); + } +} \ No newline at end of file diff --git a/lib/Model/PaymentMethod/PaymentMethodQiwi.php b/lib/Model/PaymentMethod/PaymentMethodQiwi.php new file mode 100644 index 00000000..b5032c5c --- /dev/null +++ b/lib/Model/PaymentMethod/PaymentMethodQiwi.php @@ -0,0 +1,42 @@ +_setType(PaymentMethodType::QIWI); + } +} diff --git a/lib/Model/PaymentMethod/PaymentMethodSberbank.php b/lib/Model/PaymentMethod/PaymentMethodSberbank.php new file mode 100644 index 00000000..b0796729 --- /dev/null +++ b/lib/Model/PaymentMethod/PaymentMethodSberbank.php @@ -0,0 +1,87 @@ +_setType(PaymentMethodType::SBERBANK); + } + + /** + * @return string + */ + public function getPhone() + { + return $this->_phone; + } + + /** + * @param string $value + */ + public function setPhone($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty phone value', 0, 'PaymentMethodSberbank.phone'); + } elseif (TypeCast::canCastToString($value)) { + if (preg_match('/^[0-9]{4,15}$/', $value)) { + $this->_phone = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid phone value', 0, 'PaymentMethodSberbank.phone', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid phone value type', 0, 'PaymentMethodSberbank.phone', $value + ); + } + } +} diff --git a/lib/Model/PaymentMethod/PaymentMethodTinkoffBank.php b/lib/Model/PaymentMethod/PaymentMethodTinkoffBank.php new file mode 100644 index 00000000..d4cce22b --- /dev/null +++ b/lib/Model/PaymentMethod/PaymentMethodTinkoffBank.php @@ -0,0 +1,36 @@ +_setType(PaymentMethodType::TINKOFF_BANK); + } +} \ No newline at end of file diff --git a/lib/Model/PaymentMethod/PaymentMethodWebmoney.php b/lib/Model/PaymentMethod/PaymentMethodWebmoney.php new file mode 100644 index 00000000..15239701 --- /dev/null +++ b/lib/Model/PaymentMethod/PaymentMethodWebmoney.php @@ -0,0 +1,42 @@ +_setType(PaymentMethodType::WEBMONEY); + } +} diff --git a/lib/Model/PaymentMethod/PaymentMethodWechat.php b/lib/Model/PaymentMethod/PaymentMethodWechat.php new file mode 100644 index 00000000..2e2d1b42 --- /dev/null +++ b/lib/Model/PaymentMethod/PaymentMethodWechat.php @@ -0,0 +1,40 @@ +_setType(PaymentMethodType::WECHAT); + } +} \ No newline at end of file diff --git a/lib/Model/PaymentMethod/PaymentMethodYooMoney.php b/lib/Model/PaymentMethod/PaymentMethodYooMoney.php new file mode 100644 index 00000000..5a808471 --- /dev/null +++ b/lib/Model/PaymentMethod/PaymentMethodYooMoney.php @@ -0,0 +1,85 @@ +_setType(PaymentMethodType::YOO_MONEY); + } + + /** + * @return string Номер кошелька в ЮMoney с которого была произведена оплата. + */ + public function getAccountNumber() + { + return $this->_accountNumber; + } + + /** + * @param string $value Номер кошелька в ЮMoney с которого была произведена оплата. + */ + public function setAccountNumber($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty accountNumber value', 0, 'PaymentMethodYooMoney.accountNumber' + ); + } elseif (TypeCast::canCastToString($value)) { + if (preg_match('/^[0-9]{11,33}$/', $value)) { + $this->_accountNumber = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid accountNumber value', 0, 'PaymentMethodYooMoney.accountNumber', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid accountNumber value type', 0, 'PaymentMethodYooMoney.accountNumber', $value + ); + } + } +} diff --git a/lib/Model/PaymentMethodType.php b/lib/Model/PaymentMethodType.php new file mode 100644 index 00000000..f8c82cbb --- /dev/null +++ b/lib/Model/PaymentMethodType.php @@ -0,0 +1,85 @@ + true, + self::BANK_CARD => true, + self::SBERBANK => true, + self::CASH => true, + self::MOBILE_BALANCE => false, + self::APPLE_PAY => false, + self::GOOGLE_PAY => false, + self::QIWI => true, + self::WEBMONEY => true, + self::ALFABANK => true, + self::TINKOFF_BANK => true, + self::INSTALLMENTS => true, + self::B2B_SBERBANK => true, + self::PSB => false, + self::WECHAT => true, + ); +} diff --git a/lib/Model/PaymentStatus.php b/lib/Model/PaymentStatus.php new file mode 100644 index 00000000..eed55098 --- /dev/null +++ b/lib/Model/PaymentStatus.php @@ -0,0 +1,54 @@ + true, + self::WAITING_FOR_CAPTURE => true, + self::SUCCEEDED => true, + self::CANCELED => true, + ); +} diff --git a/lib/Model/Receipt.php b/lib/Model/Receipt.php new file mode 100644 index 00000000..fd6b4978 --- /dev/null +++ b/lib/Model/Receipt.php @@ -0,0 +1,406 @@ +_customer) { + $this->_customer = new ReceiptCustomer(); + } + return $this->_customer; + } + + /** + * @param ReceiptCustomer $customer + */ + public function setCustomer($customer) + { + $this->_customer = $customer; + } + + /** + * Возвращает список позиций в текущем чеке + * + * @return ReceiptItemInterface[] Список товаров в заказе + */ + public function getItems() + { + return $this->_items; + } + + /** + * Устанавливает список позиций в чеке + * + * Если до этого в чеке уже были установлены значения, они удаляются и полностью заменяются переданным списком + * позиций. Все передаваемые значения в массиве позиций должны быть объектами класса, реализующего интерфейс + * ReceiptItemInterface, в противном случае будет выброшено исключение InvalidPropertyValueTypeException. + * + * @param ReceiptItemInterface[] $value Список товаров в заказе + * + * @throws EmptyPropertyValueException Выбрасывается если передали пустой массив значений + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве значения был передан не массив и не + * итератор, либо если одно из переданных значений не реализует интерфейс ReceiptItemInterface + */ + public function setItems($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty items value in receipt', 0, 'receipt.items'); + } + if (!is_array($value) && !($value instanceof \Traversable)) { + throw new InvalidPropertyValueTypeException( + 'Invalid items value type in receipt', 0, 'receipt.items', $value + ); + } + $this->_items = array(); + $this->_shippingItems = array(); + foreach ($value as $key => $val) { + if (is_object($val) && $val instanceof ReceiptItemInterface) { + $this->addItem($val); + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid item value type in receipt', 0, 'receipt.items['.$key.']', $val + ); + } + } + } + + /** + * Добавляет товар в чек + * + * @param ReceiptItemInterface $value Объект добавляемой в чек позиции + */ + public function addItem($value) + { + $this->_items[] = $value; + if ($value->isShipping()) { + $this->_shippingItems[] = $value; + } + } + + /** + * Возвращает массив оплат, обеспечивающих выдачу товара. + * + * @return SettlementInterface[] Массив оплат, обеспечивающих выдачу товара. + */ + public function getSettlements() + { + return $this->_settlements; + } + + /** + * Возвращает массив оплат, обеспечивающих выдачу товара. + * @param SettlementInterface[] $value + */ + public function setSettlements($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty settlements value in receipt', 0, 'receipt.settlements'); + } + if (!is_array($value) && !($value instanceof \Traversable)) { + throw new InvalidPropertyValueTypeException( + 'Invalid settlements value type in receipt', 0, 'receipt.settlements', $value + ); + } + $this->_settlements = array(); + foreach ($value as $key => $val) { + if (is_object($val) && $val instanceof SettlementInterface) { + $this->addSettlement($val); + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid settlements value type in receipt', 0, 'receipt.settlements['.$key.']', $val + ); + } + } + } + + /** + * Добавляет оплату в чек + * + * @param SettlementInterface $value Объект добавляемой в чек позиции + */ + public function addSettlement($value) + { + $this->_settlements[] = $value; + } + + /** + * Возвращает код системы налогообложения + * + * @return int Код системы налогообложения. Число 1-6. + */ + public function getTaxSystemCode() + { + return $this->_taxSystemCode; + } + + /** + * Устанавливает код системы налогообложения + * + * @param int $value Код системы налогообложения. Число 1-6 + * + * @throws InvalidPropertyValueTypeException Выбрасывается если переданный аргумент - не число + * @throws InvalidPropertyValueException Выбрасывается если переданный аргумент меньше одного или больше шести + */ + public function setTaxSystemCode($value) + { + if ($value === null || $value === '') { + $this->_taxSystemCode = null; + } elseif (!is_numeric($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid taxSystemCode value type', 0, 'receipt.taxSystemCode' + ); + } else { + $castedValue = (int)$value; + if ($castedValue < 1 || $castedValue > 6) { + throw new InvalidPropertyValueException( + 'Invalid taxSystemCode value: '.$value, 0, 'receipt.taxSystemCode' + ); + } + $this->_taxSystemCode = $castedValue; + } + } + + /** + * Проверяет есть ли в чеке хотя бы одна позиция + * + * @return bool True если чек не пуст, false если в чеке нет ни одной позиции + */ + public function notEmpty() + { + return !empty($this->_items); + } + + /** + * Возвращает стоимость заказа исходя из состава чека + * + * @param bool $withShipping Добавить ли к стоимости заказа стоимость доставки + * + * @return int Общая стоимость заказа в центах/копейках + */ + public function getAmountValue($withShipping = true) + { + $result = 0; + foreach ($this->_items as $item) { + if ($withShipping || !$item->isShipping()) { + $result += $item->getAmount(); + } + } + + return $result; + } + + /** + * Возвращает стоимость доставки исходя из состава чека + * @return int Стоимость доставки из состава чека в центах/копейках + */ + public function getShippingAmountValue() + { + $result = 0; + foreach ($this->_items as $item) { + if ($item->isShipping()) { + $result += $item->getAmount(); + } + } + + return $result; + } + + /** + * Подгоняет стоимость товаров в чеке к общей цене заказа + * + * @param AmountInterface $orderAmount Общая стоимость заказа + * @param bool $withShipping Поменять ли заодно и цену доставки + */ + public function normalize(AmountInterface $orderAmount, $withShipping = false) + { + $amount = $orderAmount->getIntegerValue(); + if (!$withShipping) { + if ($this->_shippingItems !== null) { + if ($amount > $this->getShippingAmountValue()) { + $amount -= $this->getShippingAmountValue(); + } else { + $withShipping = true; + } + } + } + $realAmount = $this->getAmountValue($withShipping); + + if ($realAmount !== $amount) { + $coefficient = (float)$amount / (float)$realAmount; + $items = array(); + $realAmount = 0; + foreach ($this->_items as $item) { + if ($withShipping || !$item->isShipping()) { + $price = round($coefficient * $item->getPrice()->getIntegerValue()); + if ($price < 1.0) { + if ($item->getPrice()->getIntegerValue() > 1) { + $item->getPrice()->setValue(0.01); + } + $amount -= $item->getAmount(); + } else { + $items[] = $item; + $realAmount += $item->getAmount(); + } + } + } + uasort($items, function (ReceiptItemInterface $a, ReceiptItemInterface $b) { + if ($a->getPrice()->getIntegerValue() > $b->getPrice()->getIntegerValue()) { + return -1; + } + if ($a->getPrice()->getIntegerValue() < $b->getPrice()->getIntegerValue()) { + return 1; + } + + return 0; + }); + + $coefficient = (float)$amount / (float)$realAmount; + $realAmount = 0; + $aloneId = null; + foreach ($items as $index => $item) { + if ($withShipping || !$item->isShipping()) { + $item->applyDiscountCoefficient($coefficient); + $realAmount += $item->getAmount(); + if ($aloneId === null && $item->getQuantity() === 1.0 && !$item->isShipping()) { + $aloneId = $index; + } + } + } + if ($aloneId === null) { + foreach ($this->_items as $index => $item) { + if (!$item->isShipping()) { + $aloneId = $index; + break; + } + } + } + if ($aloneId === null) { + $aloneId = 0; + } + $diff = $amount - $realAmount; + if (abs($diff) >= 0.1) { + if ($this->_items[$aloneId]->getQuantity() === 1.0) { + $this->_items[$aloneId]->increasePrice($diff / 100.0); + } elseif ($this->_items[$aloneId]->getQuantity() > 1.0) { + $item = $this->_items[$aloneId]->fetchItem(1); + $item->increasePrice($diff / 100.0); + array_splice($this->_items, $aloneId + 1, 0, array($item)); + } else { + $item = $this->_items[$aloneId]->fetchItem($this->_items[$aloneId]->getQuantity() / 2); + $item->increasePrice($diff / 100.0); + array_splice($this->_items, $aloneId + 1, 0, array($item)); + } + } + } + } + + /** + * Устанавливает значения свойств текущего объекта из массива + * @param array|\Traversable $sourceArray Ассоциативный массив с настройками + */ + public function fromArray($sourceArray) + { + if (!empty($sourceArray['customer'])) { + $sourceArray['customer'] = new ReceiptCustomer($sourceArray['customer']); + } + + if (!empty($sourceArray['items'])) { + foreach ($sourceArray['items'] as $i => $itemArray) { + if (is_array($itemArray)) { + $sourceArray['items'][$i] = new ReceiptItem($itemArray); + } + } + } + + if (!empty($sourceArray['settlements'])) { + foreach ($sourceArray['settlements'] as $i => $itemArray) { + if (is_array($itemArray)) { + $sourceArray['settlements'][$i] = new Settlement($itemArray); + } + } + } + + parent::fromArray($sourceArray); + } + + /** + * Возвращает Id объекта чека + * + * @return string Id объекта чека + */ + public function getObjectId() + { + return null; + } + +} diff --git a/lib/Model/Receipt/AgentType.php b/lib/Model/Receipt/AgentType.php new file mode 100644 index 00000000..580c9d98 --- /dev/null +++ b/lib/Model/Receipt/AgentType.php @@ -0,0 +1,28 @@ + true, + self::BANKING_PAYMENT_SUBAGENT => true, + self::PAYMENT_AGENT => true, + self::PAYMENT_SUBAGENT => true, + self::ATTORNEY => true, + self::COMMISSIONER => true, + self::AGENT => true, + ); +} \ No newline at end of file diff --git a/lib/Model/Receipt/PaymentMode.php b/lib/Model/Receipt/PaymentMode.php new file mode 100644 index 00000000..7de3aac8 --- /dev/null +++ b/lib/Model/Receipt/PaymentMode.php @@ -0,0 +1,50 @@ + true, + self::PARTIAL_PREPAYMENT => true, + self::ADVANCE => true, + self::FULL_PAYMENT => true, + self::PARTIAL_PAYMENT => true, + self::CREDIT => true, + self::CREDIT_PAYMENT => true, + ); +} \ No newline at end of file diff --git a/lib/Model/Receipt/PaymentSubject.php b/lib/Model/Receipt/PaymentSubject.php new file mode 100644 index 00000000..fb5c19ef --- /dev/null +++ b/lib/Model/Receipt/PaymentSubject.php @@ -0,0 +1,72 @@ + true, + self::EXCISE => true, + self::JOB => true, + self::SERVICE => true, + self::GAMBLING_BET => true, + self::GAMBLING_PRIZE => true, + self::LOTTERY => true, + self::LOTTERY_PRIZE => true, + self::INTELLECTUAL_ACTIVITY => true, + self::PAYMENT => true, + self::AGENT_COMMISSION => true, + self::PROPERTY_RIGHT => true, + self::NON_OPERATING_GAIN => true, + self::INSURANCE_PREMIUM => true, + self::SALES_TAX => true, + self::RESORT_FEE => true, + self::COMPOSITE => true, + self::ANOTHER => true, + ); +} \ No newline at end of file diff --git a/lib/Model/Receipt/ReceiptItemAmount.php b/lib/Model/Receipt/ReceiptItemAmount.php new file mode 100644 index 00000000..fe043936 --- /dev/null +++ b/lib/Model/Receipt/ReceiptItemAmount.php @@ -0,0 +1,220 @@ + 0.0) { + $this->setValue($value); + } + if ($currency !== null) { + $this->setCurrency($currency); + } + } + + /** + * Возвращает значение суммы + * @return string Сумма + */ + public function getValue() + { + if ($this->_value < 10) { + return '0.0' . $this->_value; + } elseif ($this->_value < 100) { + return '0.' . $this->_value; + } else { + return substr($this->_value, 0, -2) . '.' . substr($this->_value, -2); + } + } + /** + * @inheritdoc + */ + public function setValue($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty amount value', 0, 'amount.value'); + } + if (!is_numeric($value)) { + throw new InvalidPropertyValueTypeException('Invalid amount value type', 0, 'amount.value', $value); + } + if ($value < 0.0) { + throw new InvalidPropertyValueException('Invalid amount value: "'.$value.'"', 0, 'amount.value', $value); + } + $castedValue = (int)round($value * 100.0); + if ($castedValue < 0.0) { + throw new InvalidPropertyValueException('Invalid amount value: "'.$value.'"', 0, 'amount.value', $value); + } + $this->_value = $castedValue; + } + + /** + * Возвращает сумму в копейках в виде целого числа + * @return int Сумма в копейках/центах + */ + public function getIntegerValue() + { + return $this->_value; + } + + /** + * Возвращает валюту + * @return string Код валюты + */ + public function getCurrency() + { + return $this->_currency; + } + + /** + * Устанавливает код валюты + * @param string $value Код валюты + * + * @throws EmptyPropertyValueException Генерируется если было передано пустое значение + * @throws InvalidPropertyValueTypeException Генерируется если было передано значение невалидного типа + * @throws InvalidPropertyValueException Генерируется если был передан неподдерживаемый код валюты + */ + public function setCurrency($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty currency value', 0, 'amount.currency'); + } + if (TypeCast::canCastToEnumString($value)) { + $value = strtoupper((string)$value); + if (CurrencyCode::valueExists($value)) { + $this->_currency = $value; + } else { + throw new InvalidPropertyValueException( + 'Invalid currency value: "' . $value . '"', 0, 'amount.currency', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException('Invalid currency value type', 0, 'amount.currency', $value); + } + } + + /** + * Умножает текущую сумму на указанный коэффициент + * @param float $coefficient Множитель + * + * @throws EmptyPropertyValueException Выбрасывается если передано пустое значение + * @throws InvalidPropertyValueTypeException Выбрасывается если было передано не число + * @throws InvalidPropertyValueException Выбрасывается если переданное значение меньше или равно нулю, либо если + * после умножения получили значение равное нулю + */ + public function multiply($coefficient) + { + if ($coefficient === null || $coefficient === '') { + throw new EmptyPropertyValueException('Empty coefficient in multiply method', 0, 'amount.value'); + } + if (!is_numeric($coefficient)) { + throw new InvalidPropertyValueTypeException( + 'Invalid coefficient type in multiply method', 0, 'amount.value', $coefficient + ); + } + if ($coefficient <= 0.0) { + throw new InvalidPropertyValueException( + 'Invalid coefficient in multiply method: "' . $coefficient . '"', 0, 'amount.value', $coefficient + ); + } + $castedValue = (int)round($coefficient * $this->_value); + if ($castedValue === 0) { + throw new InvalidPropertyValueException( + 'Invalid coefficient value in multiply method: "' . $coefficient . '"', 0, 'amount.value', $coefficient + ); + } + $this->_value = $castedValue; + } + + /** + * Увеличивает сумму на указанное значение + * @param int $value Значение которое будет прибавлено к текущему + * + * @throws EmptyPropertyValueException Выбрасывается если передано пустое значение + * @throws InvalidPropertyValueTypeException Выбрасывается если было передано не число + * @throws InvalidPropertyValueException Выбрасывается если после сложения получилась сумма меньше или равная нулю + */ + public function increase($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty amount value in increase method', 0, 'amount.value'); + } + if (!is_numeric($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid amount value type in increase method', 0, 'amount.value', $value + ); + } + $castedValue = (int)round($this->_value + $value * 100.0); + if ($castedValue <= 0) { + throw new InvalidPropertyValueException( + 'Invalid amount value in increase method: "' . $value . '"', 0, 'amount.value', $value + ); + } + $this->_value = $castedValue; + } + + /** + * @return array + */ + public function jsonSerialize() + { + return array( + 'value' => sprintf('%.2f',$this->_value / 100.0), + 'currency' => $this->_currency, + ); + } +} \ No newline at end of file diff --git a/lib/Model/Receipt/SettlementType.php b/lib/Model/Receipt/SettlementType.php new file mode 100644 index 00000000..32d67dde --- /dev/null +++ b/lib/Model/Receipt/SettlementType.php @@ -0,0 +1,44 @@ + true, + self::PREPAYMENT => true, + self::POSTPAYMENT => true, + self::CONSIDERATION => true, + ); +} \ No newline at end of file diff --git a/lib/Model/ReceiptCustomer.php b/lib/Model/ReceiptCustomer.php new file mode 100644 index 00000000..b894c141 --- /dev/null +++ b/lib/Model/ReceiptCustomer.php @@ -0,0 +1,228 @@ +fromArray($data); + } + } + + /** + * Возвращает для юрлица — название организации, для ИП и физического лица — ФИО + * @return string Название организации или ФИО + */ + public function getFullName() + { + return $this->_fullName; + } + + /** + * Устанавливает Название организации или ФИО + * + * @param string $value Название организации или ФИО + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве значения была передана не строка + */ + public function setFullName($value) + { + if ($value === null || $value === '') { + $this->_fullName = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException('Invalid full_name value type', 0, 'receipt.customer.full_name'); + } elseif (strlen((string)$value) > 256) { + throw new InvalidPropertyValueException( + 'Invalid full_name value: "'.$value.'"', 0, 'receipt.customer.full_name', $value + ); + } else { + $this->_fullName = (string)$value; + } + } + + /** + * Возвращает номер телефона плательщика в формате ITU-T E.164 на который будет выслан чек + * + * @return string Номер телефона плательщика + */ + public function getPhone() + { + return $this->_phone; + } + + /** + * Устанавливливает номер телефона плательщика в формате ITU-T E.164 на который будет выслан чек + * + * @param string $value Номер телефона плательщика в формате ITU-T E.164 + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве значения была передана не строка + */ + public function setPhone($value) + { + if ($value === null || $value === '') { + $this->_phone = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException('Invalid phone value type', 0, 'receipt.customer.phone'); + } else { + $this->_phone = (string)$value; + } + } + + /** + * Возвращает адрес электронной почты на который будет выслан чек + * + * @return string E-mail адрес плательщика + */ + public function getEmail() + { + return $this->_email; + } + + /** + * Устанавливает адрес электронной почты на который будет выслан чек + * + * @param string $value E-mail адрес плательщика + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве значения была передана не строка + */ + public function setEmail($value) + { + if ($value === null || $value === '') { + $this->_email = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException('Invalid email value type', 0, 'receipt.customer.email'); + } else { + $this->_email = (string)$value; + } + } + + /** + * @return string + */ + public function getInn() + { + return $this->_inn; + } + + /** + * Устанавливает ИНН плательщика + * + * @param string $value ИНН плательщика (10 или 12 цифр) + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве значения была передана не строка + * @throws InvalidPropertyValueException Выбрасывается если ИНН не соответствует формату 10 или 12 цифр + */ + public function setInn($value) + { + if ($value === null || $value === '') { + $this->_inn = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException('Invalid inn value type', 0, 'receipt.customer.inn'); + } elseif (!preg_match('/^([0-9]{10}|[0-9]{12})$/', (string)$value)) { + throw new InvalidPropertyValueException('Invalid inn value: "'.$value.'"', 0, 'receipt.customer.inn'); + } else { + $this->_inn = (string)$value; + } + } + + /** + * Проверка на заполненность объекта + * @return bool + */ + public function isEmpty() + { + return empty($this->getFullName() . $this->getEmail() . $this->getPhone() . $this->getInn()); + } + + /** + * @return array + */ + public function jsonSerialize() + { + $result = array(); + + $value = $this->getFullName(); + if (!empty($value)) { + $result['full_name'] = $value; + } + $value = $this->getEmail(); + if (!empty($value)) { + $result['email'] = $value; + } + $value = $this->getPhone(); + if (!empty($value)) { + $result['phone'] = $value; + } + $value = $this->getInn(); + if (!empty($value)) { + $result['inn'] = $value; + } + + return $result; + } + +} diff --git a/lib/Model/ReceiptCustomerInterface.php b/lib/Model/ReceiptCustomerInterface.php new file mode 100644 index 00000000..f33fd410 --- /dev/null +++ b/lib/Model/ReceiptCustomerInterface.php @@ -0,0 +1,76 @@ +fromArray($data); + } + } + + /** + * Возвращает наименование товара + * @return string Наименование товара + */ + public function getDescription() + { + return $this->_description; + } + + /** + * Устанавливает наименование товара + * + * @param string $value Наименование товара + * + * @throws EmptyPropertyValueException Выбрасывается если было передано пустое значение + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве аргумента была передана не строка + */ + public function setDescription($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty description value in ReceiptItem', 0, 'ReceiptItem.description' + ); + } elseif (TypeCast::canCastToString($value)) { + $castedValue = (string)$value; + if ($castedValue === '') { + throw new EmptyPropertyValueException( + 'Empty description value in ReceiptItem', 0, 'ReceiptItem.description' + ); + } + $this->_description = mb_substr($castedValue, 0, 128); + } else { + throw new InvalidPropertyValueTypeException( + 'Empty description value in ReceiptItem', 0, 'ReceiptItem.description', $value + ); + } + } + + /** + * Возвращает количество товара + * @return float Количество купленного товара + */ + public function getQuantity() + { + return $this->_quantity; + } + + /** + * Устанавливает количество покупаемого товара + * + * @param int $value Количество + * + * @throws EmptyPropertyValueException Выбрасывается если было передано пустое значение + * @throws InvalidPropertyValueException Выбрасывается если в качестве аргумента был передан ноль + * или отрицательное число + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве аргумента было передано не число + */ + public function setQuantity($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty quantity value in ReceiptItem', 0, 'ReceiptItem.quantity'); + } elseif (!is_numeric($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid quantity value type in ReceiptItem', 0, 'ReceiptItem.quantity', $value + ); + } elseif ($value <= 0.0) { + throw new InvalidPropertyValueException( + 'Invalid quantity value in ReceiptItem', 0, 'ReceiptItem.quantity', $value + ); + } else { + $this->_quantity = (float)$value; + } + } + + /** + * Возвращает общую стоимость покупаемого товара в копейках/центах + * @return int Сумма стоимости покупаемого товара + */ + public function getAmount() + { + return (int)round($this->_amount->getIntegerValue() * $this->_quantity); + } + + /** + * Возвращает цену товара + * @return AmountInterface Цена товара + */ + public function getPrice() + { + return $this->_amount; + } + + /** + * Устанавливает цену товара + * + * @param AmountInterface $value Цена товара + */ + public function setPrice(AmountInterface $value) + { + $this->_amount = $value; + } + + /** + * Возвращает ставку НДС + * @return int|null Ставка НДС, число 1-6, или null если ставка не задана + */ + public function getVatCode() + { + return $this->_vatCode; + } + + /** + * Устанавливает ставку НДС + * + * @param int $value Ставка НДС, число 1-6 + * + * @throws InvalidPropertyValueException Выбрасывается если в качестве аргумента было передано число меньше одного + * или больше шести + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве аргумента было передано не число + */ + public function setVatCode($value) + { + if ($value === null || $value === '') { + $this->_vatCode = null; + } elseif (!is_numeric($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid vatId value type in ReceiptItem', 0, 'ReceiptItem.vatId', $value + ); + } elseif ($value < 1 || $value > 6) { + throw new InvalidPropertyValueException( + 'Invalid vatId value in ReceiptItem', 0, 'ReceiptItem.vatId', $value + ); + } else { + $this->_vatCode = (int)$value; + } + } + + /** + * Возвращает признак предмета расчета + * @return string|null Признак предмета расчета + */ + public function getPaymentSubject() + { + return $this->_paymentSubject; + } + + /** + * Устанавливает признак предмета расчета + * + * @param string $value Признак предмета расчета + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве аргумента была передана не строка + */ + public function setPaymentSubject($value) + { + if ($value === null || $value === '') { + $this->_paymentSubject = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException('Invalid paymentSubject value type', 0, 'ReceiptItem.paymentSubject'); + } else { + $this->_paymentSubject = $value; + } + } + + /** + * Возвращает признак способа расчета + * @return string|null Признак способа расчета + */ + public function getPaymentMode() + { + return $this->_paymentMode; + } + + /** + * Устанавливает признак способа расчета + * + * @param string $value Признак способа расчета + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве аргумента была передана не строка + */ + public function setPaymentMode($value) + { + if ($value === null || $value === '') { + $this->_paymentMode = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid paymentMode value type', 0, 'ReceiptItem.paymentMode', $value + ); + } else { + $this->_paymentMode = $value; + } + } + + /** + * Возвращает код товара — уникальный номер, который присваивается экземпляру товара при маркировке + * @return string|null Код товара + */ + public function getProductCode() + { + return $this->_productCode; + } + + /** + * Устанавливает код товара — уникальный номер, который присваивается экземпляру товара при маркировке + * + * @param string $value Код товара + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве аргумента была передана не строка + */ + public function setProductCode($value) + { + if ($value === null || $value === '') { + $this->_productCode = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid productCode value type', 0, 'ReceiptItem.productCode', $value + ); + } elseif (strlen((string)$value) > 96) { + throw new InvalidPropertyValueException( + 'Invalid productCode value: "'.$value.'"', 0, 'ReceiptItem.productCode', $value + ); + } elseif (!preg_match('/^[0-9A-F ]{2,96}$/', (string)$value)) { + throw new InvalidPropertyValueException( + 'Invalid productCode value: "'.$value.'"', 0, 'ReceiptItem.productCode', $value + ); + } else { + $this->_productCode = $value; + } + } + + /** + * Возвращает код страны происхождения товара по общероссийскому классификатору стран мира + * @return string|null Код страны происхождения товара + */ + public function getCountryOfOriginCode() + { + return $this->_countryOfOriginCode; + } + + /** + * Устанавливает код страны происхождения товара по общероссийскому классификатору стран мира + * + * @param string $value Код страны происхождения товара + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве аргумента была передана не строка + */ + public function setCountryOfOriginCode($value) + { + if ($value === null || $value === '') { + $this->_countryOfOriginCode = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid countryOfOriginCode value type', 0, 'ReceiptItem.countryOfOriginCode', $value + ); + } elseif (strlen((string)$value) != 2) { + throw new InvalidPropertyValueException( + 'Invalid countryOfOriginCode value: "'.$value.'"', 0, 'ReceiptItem.countryOfOriginCode', $value + ); + } elseif (!preg_match('/^[A-Z]{2}$/', (string)$value)) { + throw new InvalidPropertyValueException( + 'Invalid countryOfOriginCode value: "'.$value.'"', 0, 'ReceiptItem.countryOfOriginCode', $value + ); + } else { + $this->_countryOfOriginCode = $value; + } + } + + /** + * Возвращает номер таможенной декларации + * @return string|null Номер таможенной декларации (от 1 до 32 символов) + */ + public function getCustomsDeclarationNumber() + { + return $this->_customsDeclarationNumber; + } + + /** + * Устанавливает номер таможенной декларации (от 1 до 32 символов) + * + * @param string $value Номер таможенной декларации + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве аргумента была передана не строка + */ + public function setCustomsDeclarationNumber($value) + { + if ($value === null || $value === '') { + $this->_customsDeclarationNumber = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid customsDeclarationNumber value type', 0, 'ReceiptItem.customsDeclarationNumber', $value + ); + } elseif (strlen((string)$value) > 32) { + throw new InvalidPropertyValueException( + 'Invalid customsDeclarationNumber value: "'.$value.'"', 0, 'ReceiptItem.customsDeclarationNumber', $value + ); + } else { + $this->_customsDeclarationNumber = $value; + } + } + + /** + * Возвращает сумму акциза товара с учетом копеек + * @return float|null Сумма акциза товара с учетом копеек + */ + public function getExcise() + { + return $this->_excise; + } + + /** + * Устанавливает сумму акциза товара с учетом копеек + * + * @param float $value Сумма акциза товара с учетом копеек + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве аргумента было передано не число + */ + public function setExcise($value) + { + if ($value === null || $value === '') { + $this->_excise = null; + } elseif (!is_numeric($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid excise value type', 0, 'ReceiptItem.excise', $value + ); + } elseif ($value <= 0.0) { + throw new InvalidPropertyValueException( + 'Invalid excise value in ReceiptItem', 0, 'ReceiptItem.excise', $value + ); + } else { + $this->_excise = $value; + } + } + + /** + * Устанавливает флаг доставки для текущего объекта айтема в чеке + * + * @param bool $value True если айтем является доставкой, false если нет + * + * @return ReceiptItem + * @throws InvalidPropertyValueException Генерируется если передано значение невалидного типа + */ + public function setIsShipping($value) + { + if ($value === null || $value === '') { + $this->_shipping = false; + } elseif (TypeCast::canCastToBoolean($value)) { + $this->_shipping = $value ? true : false; + } else { + throw new InvalidPropertyValueException( + 'Invalid isShipping value in ReceiptItem', 0, 'ReceiptItem.isShipping', $value + ); + } + + return $this; + } + + /** + * Возвращает информацию о поставщике товара или услуги. + * + * @return SupplierInterface + */ + public function getSupplier() + { + return $this->_supplier; + } + + /** + * Устанавливает информацию о поставщике товара или услуги. + * + * @param SupplierInterface|array $value + */ + public function setSupplier($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty supplier value in receipt', 0, 'Receipt.supplier' + ); + } + + if (is_array($value)) { + $value = new Supplier($value); + } + + if (!($value instanceof SupplierInterface)) { + throw new InvalidPropertyValueTypeException( + 'Invalid supplier value type in receipt', 0, 'Receipt.supplier', $value + ); + } + + $this->_supplier = $value; + } + + /** + * @param string $value + */ + public function setAgentType($value) + { + if ($value === null || $value === '') { + $this->_paymentMode = null; + } elseif (!TypeCast::canCastToEnumString($value)) { + throw new InvalidPropertyValueException( + 'Invalid value for "agentType" parameter in Receipt.item.agentType', + 0, + 'Receipt.item.agentType', + $value + ); + } elseif (!AgentType::valueExists($value)) { + throw new InvalidPropertyValueException( + 'Invalid value for "agentType" parameter in Receipt.item.agentType', + 0, + 'Receipt.item.agentType', + $value + ); + } + + $this->_agentType = $value; + } + + public function getAgentType() + { + return $this->_agentType; + } + + + /** + * Проверяет, является ли текущий элемент чека доствкой + * @return bool True если доставка, false если обычный товар + */ + public function isShipping() + { + return $this->_shipping; + } + + /** + * Применяет для товара скидку + * + * @param float $coefficient Множитель скидки + */ + public function applyDiscountCoefficient($coefficient) + { + $this->_amount->multiply($coefficient); + } + + /** + * Увеличивает цену товара на указанную величину + * + * @param float $value Сумма на которую цену товара увеличиваем + */ + public function increasePrice($value) + { + $this->_amount->increase($value); + } + + /** + * Уменьшает количество покупаемого товара на указанное, возвращает объект позиции в чеке с уменьшаемым количеством + * + * @param float $count Количество на которое уменьшаем позицию в чеке + * + * @return ReceiptItem + * + * @throws EmptyPropertyValueException Выбрасывается если было передано пустое значение + * @throws InvalidPropertyValueException Выбрасывается если в качестве аргумента был передан ноль + * или отрицательное число, или число больше текущего количества покупаемого товара + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве аргумента было передано не число + */ + public function fetchItem($count) + { + if ($count === null || $count === '') { + throw new EmptyPropertyValueException( + 'Empty quantity value in ReceiptItem in fetchItem method', 0, 'ReceiptItem.quantity' + ); + } elseif (!is_numeric($count)) { + throw new InvalidPropertyValueTypeException( + 'Invalid quantity value type in ReceiptItem in fetchItem method', 0, 'ReceiptItem.quantity', $count + ); + } elseif ($count <= 0.0 || $count >= $this->_quantity) { + throw new InvalidPropertyValueException( + 'Invalid quantity value in ReceiptItem in fetchItem method', 0, 'ReceiptItem.quantity', $count + ); + } + + $result = clone $this; + $result->setPrice(clone $this->getPrice()); + $result->setQuantity($count); + $this->_quantity -= $count; + + return $result; + } + + /** + * Устанавливает значения свойств текущего объекта из массива + * @param array|\Traversable $sourceArray Ассоциативный массив с настройками + */ + public function fromArray($sourceArray) + { + $amount = new ReceiptItemAmount(); + $amount->fromArray($sourceArray['amount']); + $sourceArray['price'] = $amount; + unset($sourceArray['amount']); + + parent::fromArray($sourceArray); + } + + /** + * @return array + */ + public function jsonSerialize() + { + $result = array( + 'description' => $this->getDescription(), + 'amount' => array( + 'value' => $this->getPrice()->getValue(), + 'currency' => $this->getPrice()->getCurrency(), + ), + 'quantity' => $this->getQuantity(), + 'vat_code' => $this->getVatCode(), + ); + + if ($this->getPaymentSubject()) { + $result['payment_subject'] = $this->getPaymentSubject(); + } + + if ($this->getPaymentMode()) { + $result['payment_mode'] = $this->getPaymentMode(); + } + + if ($this->getProductCode()) { + $result['product_code'] = $this->getProductCode(); + } + + if ($this->getCountryOfOriginCode()) { + $result['country_of_origin_code'] = $this->getCountryOfOriginCode(); + } + + if ($this->getCustomsDeclarationNumber()) { + $result['customs_declaration_number'] = $this->getCustomsDeclarationNumber(); + } + + if ($this->getExcise()) { + $result['excise'] = $this->getExcise(); + } + + if ($this->getSupplier()) { + $result['supplier'] = $this->getSupplier()->jsonSerialize(); + } + + if ($this->getAgentType()) { + $result['agent_type'] = $this->getAgentType(); + } + + return $result; + } +} diff --git a/lib/Model/ReceiptItemInterface.php b/lib/Model/ReceiptItemInterface.php new file mode 100644 index 00000000..a39e770e --- /dev/null +++ b/lib/Model/ReceiptItemInterface.php @@ -0,0 +1,138 @@ + + *
  • pending - Чек ожидает доставки
  • + *
  • succeeded - Успешно доставлен
  • + *
  • canceled - Чек не доставлен
  • + * + */ +class ReceiptRegistrationStatus extends AbstractEnum +{ + /** + * @var string Состояние регистрации фискального чека: ожидает доставки + */ + const PENDING = 'pending'; + + /** + * @var string Состояние регистрации фискального чека: успешно доставлен + */ + const SUCCEEDED = 'succeeded'; + + /** + * @var string Состояние регистрации фискального чека: не доставлен + */ + const CANCELED = 'canceled'; + + protected static $validValues = array( + self::PENDING => true, + self::SUCCEEDED => true, + self::CANCELED => true, + ); +} diff --git a/lib/Model/ReceiptType.php b/lib/Model/ReceiptType.php new file mode 100644 index 00000000..b1a44a61 --- /dev/null +++ b/lib/Model/ReceiptType.php @@ -0,0 +1,55 @@ + true, + self::REFUND => true, + self::SIMPLE => true, + ); +} diff --git a/lib/Model/Recipient.php b/lib/Model/Recipient.php new file mode 100644 index 00000000..e909244f --- /dev/null +++ b/lib/Model/Recipient.php @@ -0,0 +1,122 @@ +_accountId; + } + + /** + * Устанавливает идентификатор магазина + * + * @param string $value Идентификатор магазина + * + * @throws EmptyPropertyValueException Выбрасывается если было передано пустое значение + * @throws InvalidPropertyValueTypeException Выбрасывается если было передано не строковое значение + */ + public function setAccountId($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty accountId value in Recipient', 0, 'Recipient.accountId'); + } elseif (TypeCast::canCastToString($value)) { + $this->_accountId = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid accountId value type in Recipient', 0, 'Recipient.accountId', $value + ); + } + } + + /** + * Возвращает идентификатор шлюза. + * + * Идентификатор шлюза используется для разделения потоков платежей в рамках одного аккаунта. + * + * @return string Идентификатор шлюза + */ + public function getGatewayId() + { + return $this->_gatewayId; + } + + /** + * Устанавливает идентификатор шлюза + * + * @param string $value Идентификатор шлюза + * + * @throws EmptyPropertyValueException Выбрасывается если было передано пустое значение + * @throws InvalidPropertyValueTypeException Выбрасывается если было передано не строковое значение + */ + public function setGatewayId($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty gatewayId value in Recipient', 0, 'Recipient.gatewayId' + ); + } elseif (TypeCast::canCastToString($value)) { + $this->_gatewayId = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid gatewayId value type in Recipient', 0, 'Recipient.gatewayId', $value + ); + } + } +} diff --git a/lib/Model/RecipientInterface.php b/lib/Model/RecipientInterface.php new file mode 100644 index 00000000..84b936c3 --- /dev/null +++ b/lib/Model/RecipientInterface.php @@ -0,0 +1,57 @@ +_id; + } + + /** + * Устанавливает идентификатор возврата + * @param string $value Идентификатор возврата + * + * @throws EmptyPropertyValueException Выбрасывается если был передан пустой аргумент + * @throws InvalidPropertyValueException Выбрасывается если було передано невалидное значение + * @throws InvalidPropertyValueTypeException Выбрасывается если аргумент не является строкой + */ + public function setId($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty refund id', 0, 'Refund.id'); + } elseif (TypeCast::canCastToString($value)) { + $castedValue = (string)$value; + $length = mb_strlen($castedValue, 'utf-8'); + if ($length === 36) { + $this->_id = $castedValue; + } else { + throw new InvalidPropertyValueException('Invalid refund id value', 0, 'Refund.id', $value); + } + } else { + throw new InvalidPropertyValueTypeException('Invalid refund id value type', 0, 'Refund.id', $value); + } + } + + /** + * Возвращает идентификатор платежа + * @return string Идентификатор платежа + */ + public function getPaymentId() + { + return $this->_paymentId; + } + + /** + * Устанавливает идентификатор платежа + * @param string $value Идентификатор платежа + * + * @throws EmptyPropertyValueException Выбрасывается если был передан пустой аргумент + * @throws InvalidPropertyValueException Выбрасывается если було передано невалидное значение + * @throws InvalidPropertyValueTypeException Выбрасывается если аргумент не является строкой + */ + public function setPaymentId($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty refund paymentId', 0, 'Refund.paymentId'); + } elseif (TypeCast::canCastToString($value)) { + $castedValue = (string)$value; + $length = mb_strlen($castedValue, 'utf-8'); + if ($length === 36) { + $this->_paymentId = $castedValue; + } else { + throw new InvalidPropertyValueException( + 'Invalid refund paymentId value', 0, 'Refund.paymentId', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid refund paymentId value type', 0, 'Refund.paymentId', $value + ); + } + } + + /** + * Возвращает статус текущего возврата + * @return string Статус возврата + */ + public function getStatus() + { + return $this->_status; + } + + /** + * Усианавливает стутус возврата платежа + * @param string $value Статус возврата платежа + * + * @throws EmptyPropertyValueException Выбрасывается если был передан пустой аргумент + * @throws InvalidPropertyValueException Выбрасывается если було передано невалидное значение + * @throws InvalidPropertyValueTypeException Выбрасывается если аргумент не является строкой + */ + public function setStatus($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty refund status', 0, 'Refund.status'); + } elseif (TypeCast::canCastToEnumString($value)) { + $castedValue = (string)$value; + if (RefundStatus::valueExists($castedValue)) { + $this->_status = $castedValue; + } else { + throw new InvalidPropertyValueException( + 'Invalid refund status value', 0, 'Refund.status', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid refund status value type', 0, 'Refund.status', $value + ); + } + } + + /** + * Возвращает дату создания возврата + * @return \DateTime Время создания возврата + */ + public function getCreatedAt() + { + return $this->_createdAt; + } + + /** + * Устанавливает вермя создания возврата + * @param \DateTime $value Время создания возврата + * + * @throws EmptyPropertyValueException Выбрасывается если быо передано пустое значение + * @throws InvalidPropertyValueException Выбрасывается если переданную строку или число не удалось интерпретировать + * как дату и время + * @throws InvalidPropertyValueTypeException|\Exception Выбрасывается если было передано значение невалидного типа + */ + public function setCreatedAt($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty refund created_at value', 0, 'Refund.createdAt'); + } elseif (TypeCast::canCastToDateTime($value)) { + $dateTime = TypeCast::castToDateTime($value); + if ($dateTime === null) { + throw new InvalidPropertyValueException('Invalid created_at value', 0, 'Refund.createdAt', $value); + } + $this->_createdAt = $dateTime; + } else { + throw new InvalidPropertyValueTypeException('Invalid created_at value', 0, 'Refund.createdAt', $value); + } + } + + /** + * Возвращает сумму возврата + * @return AmountInterface Сумма возврата + */ + public function getAmount() + { + return $this->_amount; + } + + /** + * Устанавливает сумму возврата + * @param AmountInterface $value Сумма возврата + * + * @throws InvalidPropertyValueException Выбрасывается если переданная сумма меньше или равна нулю + */ + public function setAmount(AmountInterface $value) + { + if ($value->getIntegerValue() <= 0) { + throw new InvalidPropertyValueException('Invalid refund amount', 0, 'Refund.amount', $value->getValue()); + } + $this->_amount = $value; + } + + /** + * Возвращает статус регистрации чека + * @return string Статус регистрации чека + */ + public function getReceiptRegistration() + { + return $this->_receiptRegistration; + } + + /** + * Устанавливает статус регистрации чека + * @param string $value Статус регистрации чека + * + * @throws EmptyPropertyValueException Выбрасывается если был передан пустой аргумент + * @throws InvalidPropertyValueException Выбрасывается если було передано невалидное значение + * @throws InvalidPropertyValueTypeException Выбрасывается если аргумент не является строкой + */ + public function setReceiptRegistration($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty refund receiptRegistration', 0, 'Refund.receiptRegistration'); + } elseif (TypeCast::canCastToEnumString($value)) { + $castedValue = (string)$value; + if (ReceiptRegistrationStatus::valueExists($castedValue)) { + $this->_receiptRegistration = $castedValue; + } else { + throw new InvalidPropertyValueException( + 'Invalid refund receiptRegistration value', 0, 'Refund.receiptRegistration', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid refund receiptRegistration value type', 0, 'Refund.receiptRegistration', $value + ); + } + } + + /** + * Возвращает комментарий к возврату + * @return string Комментарий, основание для возврата средств покупателю + */ + public function getDescription() + { + return $this->_description; + } + + /** + * Устанавливает комментарий к возврату + * @param string $value Комментарий, основание для возврата средств покупателю + * + * @throws EmptyPropertyValueException Выбрасывается если был передан пустой аргумент + * @throws InvalidPropertyValueTypeException Выбрасывается если аргумент не является строкой + */ + public function setDescription($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty refund description', 0, 'Refund.description'); + } elseif (TypeCast::canCastToEnumString($value)) { + $this->_description = (string)$value; + } else { + throw new InvalidPropertyValueTypeException('Empty refund description', 0, 'Refund.description', $value); + } + } + + /** + * @return SourceInterface[] + */ + public function getSources() + { + return $this->_sources; + } + + /** + * Устанавливает sources (массив распределения денег между магазинами) + * @param SourceInterface[]|array $value + */ + public function setSources($value) + { + if (!is_array($value)) { + $message = 'Sources must be an array of SourceInterface'; + throw new InvalidPropertyValueTypeException($message, 0, 'Refund.sources', $value); + } + + $sources = array(); + foreach ($value as $item) { + if (is_array($item)) { + $item = new Source($item); + } + + if (!($item instanceof SourceInterface)) { + $message = 'Source must be instance of SourceInterface'; + throw new InvalidPropertyValueTypeException($message, 0, 'Refund.sources', $value); + } + $sources[] = $item; + } + + $this->_sources = $sources; + } + + /** + * @return RequestorInterface + */ + public function getRequestor() + { + return $this->_requestor; + } + + /** + * @param $value + */ + public function setRequestor($value) + { + if (is_array($value)) { + $value = new Requestor($value); + } + + if (!($value instanceof RequestorInterface)) { + throw new InvalidPropertyValueTypeException('Invalid Requestor type', 0, 'Refund.requestor', $value); + } + + $this->_requestor = $value; + } +} diff --git a/lib/Model/RefundInterface.php b/lib/Model/RefundInterface.php new file mode 100644 index 00000000..b810eb00 --- /dev/null +++ b/lib/Model/RefundInterface.php @@ -0,0 +1,100 @@ + true, + self::SUCCEEDED => true, + self::CANCELED => true, + ); +} diff --git a/lib/Model/Requestor.php b/lib/Model/Requestor.php new file mode 100644 index 00000000..303b529a --- /dev/null +++ b/lib/Model/Requestor.php @@ -0,0 +1,140 @@ +fromArray($data); + } + + /** + * @param $value + */ + public function setType($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty value for "accountId" parameter in Source', 0, 'source.accountId' + ); + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for "accountId" parameter in Source', 0, 'source.accountId' + ); + } else { + $this->_type = (string)$value; + } + } + + /** + * @return string + */ + public function getType() + { + return $this->_type; + } + + /** + * @param $value + */ + public function setAccountId($value) + { + if ($value === null || $value === '') { + $this->_accountId = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for "accountId" parameter in Source', 0, 'source.accountId' + ); + } else { + $this->_accountId = (string)$value; + } + } + + /** + * @return string|null + */ + public function getAccountId() + { + return $this->_accountId; + } + + /** + * @param string $value + */ + public function setClientId($value) + { + if ($value === null || $value === '') { + $this->_clientId = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for "accountId" parameter in Source', 0, 'source.accountId' + ); + } else { + $this->_clientId = (string)$value; + } + } + + /** + * @return string|null + */ + public function getClientId() + { + return $this->_clientId; + } + + /** + * @param string $value + */ + public function setClientName($value) + { + if ($value === null || $value === '') { + $this->_clientName = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for "accountId" parameter in Source', 0, 'source.accountId' + ); + } else { + $this->_clientName = (string)$value; + } + } + + /** + * @return string|null + */ + public function getClientName() + { + return $this->_clientName; + } +} \ No newline at end of file diff --git a/lib/Model/RequestorInterface.php b/lib/Model/RequestorInterface.php new file mode 100644 index 00000000..1012be06 --- /dev/null +++ b/lib/Model/RequestorInterface.php @@ -0,0 +1,30 @@ +setType($data['type']); + } + if (!empty($data['amount'])) { + $this->setAmount($this->factoryAmount($data['amount'])); + } + } + } + + /** + * Возвращает вид оплаты в чеке (cashless | prepayment | postpayment | consideration) + * @return string Вид оплаты в чеке + */ + public function getType() + { + return $this->_type; + } + + /** + * Устанавливает вид оплаты в чеке + * @param string $value + */ + public function setType($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty value for "type" parameter in Settlement', 0, 'settlement.type' + ); + } elseif (TypeCast::canCastToEnumString($value)) { + if (SettlementType::valueExists($value)) { + $this->_type = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid value for "type" parameter in Settlement', 0, 'settlement.type', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for "type" parameter in Settlement', 0, 'settlement.type', $value + ); + } + } + + /** + * Возвращает размер оплаты + * @return AmountInterface Размер оплаты + */ + public function getAmount() + { + return $this->_amount; + } + + /** + * Устанавливает сумму платежа + * @param AmountInterface|array $value Сумма платежа + */ + public function setAmount($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty value for "amount" parameter in Settlement', 0, 'settlement.amount' + ); + } elseif (is_array($value)) { + $this->_amount = $this->factoryAmount($value); + } elseif ($value instanceof AmountInterface) { + $this->_amount = $value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for "amount" parameter in Settlement', 0, 'settlement.amount', $value + ); + } + } + + /** + * Фабричный метод создания суммы + * + * @param array $options Сумма в виде ассоциативного массива + * + * @return AmountInterface Созданный инстанс суммы + */ + private function factoryAmount($options) + { + $amount = new MonetaryAmount(null, $options['currency']); + if ($options['value'] > 0) { + $amount->setValue($options['value']); + } + + return $amount; + } +} \ No newline at end of file diff --git a/lib/Model/SettlementInterface.php b/lib/Model/SettlementInterface.php new file mode 100644 index 00000000..6b2fccf0 --- /dev/null +++ b/lib/Model/SettlementInterface.php @@ -0,0 +1,50 @@ +setAccountId($data['account_id']); + } + if (!empty($data['amount'])) { + $this->setAmount($this->factoryAmount($data['amount'])); + } + if (!empty($data['platform_fee_amount'])) { + $this->setPlatformFeeAmount($this->factoryAmount($data['platform_fee_amount'])); + } + } + } + + /** + * @inheritDoc + */ + public function setAccountId($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty value for "accountId" parameter in Source', 0, 'source.accountId' + ); + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for "accountId" parameter in Source', 0, 'source.accountId' + ); + } else { + $this->_accountId = (string)$value; + } + } + + /** + * @inheritDoc + */ + public function getAccountId() + { + return $this->_accountId; + } + + /** + * @inheritDoc + */ + public function getAmount() + { + return $this->_amount; + } + + /** + * @inheritDoc + */ + public function hasAmount() + { + return !empty($this->_amount); + } + + /** + * @inheritDoc + */ + public function setAmount($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty value for "amount" parameter in Source', 0, 'source.amount' + ); + } elseif (is_array($value)) { + $this->_amount = $this->factoryAmount($value); + } elseif ($value instanceof AmountInterface) { + $this->_amount = $value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for "amount" parameter in Source', 0, 'source.amount', $value + ); + } + } + + /** + * @inheritDoc + */ + public function getPlatformFeeAmount() + { + return $this->_platform_fee_amount; + } + + /** + * @inheritDoc + */ + public function hasPlatformFeeAmount() + { + return !empty($this->_platform_fee_amount); + } + + /** + * @inheritDoc + */ + public function setPlatformFeeAmount($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty value for "platform_fee_amount" parameter in Source', 0, 'source.platform_fee_amount' + ); + } elseif (is_array($value)) { + $this->_platform_fee_amount = $this->factoryAmount($value); + } elseif ($value instanceof AmountInterface) { + $this->_platform_fee_amount = $value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for "platform_fee_amount" parameter in Source', 0, 'source.platform_fee_amount', $value + ); + } + } + + /** + * Фабричный метод создания суммы + * + * @param array $options Сумма в виде ассоциативного массива + * + * @return AmountInterface Созданный инстанс суммы + */ + private function factoryAmount($options) + { + $amount = new MonetaryAmount(null, $options['currency']); + if ($options['value'] > 0) { + $amount->setValue($options['value']); + } + + return $amount; + } +} diff --git a/lib/Model/SourceInterface.php b/lib/Model/SourceInterface.php new file mode 100644 index 00000000..f9e4874e --- /dev/null +++ b/lib/Model/SourceInterface.php @@ -0,0 +1,95 @@ +fromArray($data); + } + } + + /** + * @return string + */ + public function getName() + { + return $this->_name; + } + + /** + * @param string $value Наименование поставщика + */ + public function setName($value) + { + if ($value === null || $value === '') { + $this->_name = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException('Invalid name value type', 0, 'receipt.supplier.name'); + } else { + $this->_name = (string)$value; + } + } + + /** + * @return string + */ + public function getPhone() + { + return $this->_phone; + } + + /** + * @param string $value Номер телефона пользователя в формате ITU-T E.164 + */ + public function setPhone($value) + { + if ($value === null || $value === '') { + $this->_phone = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException('Invalid phone value type', 0, 'receipt.supplier.phone'); + } else { + $this->_phone = (string)$value; + } + } + + /** + * @return string + */ + public function getInn() + { + return $this->_inn; + } + + /** + * @param string $value ИНН пользователя (10 или 12 цифр) + */ + public function setInn($value) + { + if ($value === null || $value === '') { + $this->_inn = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException('Invalid inn value type', 0, 'receipt.supplier.inn'); + } elseif (!preg_match('/^([0-9]{10}|[0-9]{12})$/', (string)$value)) { + throw new InvalidPropertyValueException('Invalid inn value: "'.$value.'"', 0, 'receipt.supplier.inn'); + } else { + $this->_inn = (string)$value; + } + } +} \ No newline at end of file diff --git a/lib/Model/SupplierInterface.php b/lib/Model/SupplierInterface.php new file mode 100644 index 00000000..96e2dccb --- /dev/null +++ b/lib/Model/SupplierInterface.php @@ -0,0 +1,68 @@ +setAccountId($data['account_id']); + } + if (!empty($data['amount'])) { + $this->setAmount($this->factoryAmount($data['amount'])); + } + if (!empty($data['platform_fee_amount'])) { + $this->setPlatformFeeAmount($this->factoryAmount($data['platform_fee_amount'])); + } + if (!empty($data['status'])) { + $this->setStatus($data['status']); + } + } + } + + /** + * @inheritDoc + */ + public function setAccountId($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty value for "accountId" parameter in Transfer', 0, 'transfer.accountId' + ); + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for "accountId" parameter in Transfer', 0, 'transfer.accountId' + ); + } else { + $this->_accountId = (string)$value; + } + } + + /** + * @inheritDoc + */ + public function getAccountId() + { + return $this->_accountId; + } + + /** + * @inheritDoc + */ + public function getAmount() + { + return $this->_amount; + } + + /** + * @inheritDoc + */ + public function hasAmount() + { + return !empty($this->_amount); + } + + /** + * @inheritDoc + */ + public function setAmount($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty value for "amount" parameter in Transfer', 0, 'transfer.amount' + ); + } elseif (is_array($value)) { + $this->_amount = $this->factoryAmount($value); + } elseif ($value instanceof AmountInterface) { + $this->_amount = $value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for "amount" parameter in Transfer', 0, 'transfer.amount', $value + ); + } + } + + /** + * @inheritDoc + */ + public function getPlatformFeeAmount() + { + return $this->_platform_fee_amount; + } + + /** + * @inheritDoc + */ + public function hasPlatformFeeAmount() + { + return !empty($this->_platform_fee_amount); + } + + /** + * @inheritDoc + */ + public function setPlatformFeeAmount($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty value for "platform_fee_amount" parameter in Transfer', 0, 'transfer.platform_fee_amount' + ); + } elseif (is_array($value)) { + $this->_platform_fee_amount = $this->factoryAmount($value); + } elseif ($value instanceof AmountInterface) { + $this->_platform_fee_amount = $value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid value type for "platform_fee_amount" parameter in Transfer', 0, 'transfer.platform_fee_amount', $value + ); + } + } + + /** + * @param $value + */ + public function setStatus($value) + { + if (!TypeCast::canCastToEnumString($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid "status" value type', 0, 'transfer.status', $value + ); + } elseif (!TransferStatus::valueExists((string)$value)) { + throw new InvalidPropertyValueException( + 'Invalid "status" value', 0, 'transfer.status', $value + ); + } else { + $this->_status = (string)$value; + } + } + + /** + * @inheritDoc + */ + public function getStatus() + { + return $this->_status; + } + + /** + * Фабричный метод создания суммы + * + * @param array $options Сумма в виде ассоциативного массива + * + * @return AmountInterface Созданный инстанс суммы + */ + private function factoryAmount($options) + { + $amount = new MonetaryAmount(null, $options['currency']); + if ($options['value'] > 0) { + $amount->setValue($options['value']); + } + + return $amount; + } +} diff --git a/lib/Model/TransferInterface.php b/lib/Model/TransferInterface.php new file mode 100644 index 00000000..8c4dc6f0 --- /dev/null +++ b/lib/Model/TransferInterface.php @@ -0,0 +1,101 @@ + true, + self::WAITING_FOR_CAPTURE => true, + self::SUCCEEDED => true, + self::CANCELED => true, + ); +} \ No newline at end of file diff --git a/lib/Model/Webhook/Webhook.php b/lib/Model/Webhook/Webhook.php new file mode 100644 index 00000000..f5e8ba51 --- /dev/null +++ b/lib/Model/Webhook/Webhook.php @@ -0,0 +1,117 @@ +fromArray($initData); + } + } + + + /** + * @return mixed + */ + public function getId() + { + return $this->id; + } + + /** + * @param mixed $id + */ + public function setId($id) + { + $this->id = $id; + } + + /** + * @return mixed + */ + public function getEvent() + { + return $this->event; + } + + /** + * @param mixed $event + */ + public function setEvent($event) + { + $this->event = $event; + } + + /** + * @return mixed + */ + public function getUrl() + { + return $this->url; + } + + /** + * @param mixed $url + */ + public function setUrl($url) + { + $this->url = $url; + } +} \ No newline at end of file diff --git a/lib/Request/Payments/AbstractPaymentResponse.php b/lib/Request/Payments/AbstractPaymentResponse.php new file mode 100644 index 00000000..92a6bab5 --- /dev/null +++ b/lib/Request/Payments/AbstractPaymentResponse.php @@ -0,0 +1,218 @@ +setId($paymentInfo['id']); + $this->setStatus($paymentInfo['status']); + $this->setAmount($this->factoryAmount($paymentInfo['amount'])); + $this->setCreatedAt($paymentInfo['created_at']); + $this->setPaid($paymentInfo['paid']); + $this->setRefundable($paymentInfo['refundable']); + if (!empty($paymentInfo['test'])) { + $this->setTest($paymentInfo['test']); + } + if (!empty($paymentInfo['payment_method'])) { + $this->setPaymentMethod($this->factoryPaymentMethod($paymentInfo['payment_method'])); + } + + if (!empty($paymentInfo['description'])) { + $this->setDescription($paymentInfo['description']); + } + + if (!empty($paymentInfo['recipient'])) { + $recipient = new Recipient(); + if (!empty($paymentInfo['recipient']['account_id'])) { + $recipient->setAccountId($paymentInfo['recipient']['account_id']); + } + if (!empty($paymentInfo['recipient']['gateway_id'])) { + $recipient->setGatewayId($paymentInfo['recipient']['gateway_id']); + } + $this->setRecipient($recipient); + } + if (!empty($paymentInfo['captured_at'])) { + $this->setCapturedAt(strtotime($paymentInfo['captured_at'])); + } + if (!empty($paymentInfo['expires_at'])) { + $this->setExpiresAt($paymentInfo['expires_at']); + } + if (!empty($paymentInfo['confirmation'])) { + $confirmationType = $paymentInfo['confirmation']['type']; + switch ($confirmationType) { + case ConfirmationType::REDIRECT: + $confirmation = new ConfirmationRedirect(); + if (!empty($paymentInfo['confirmation']['confirmation_url'])) { + $confirmation->setConfirmationUrl($paymentInfo['confirmation']['confirmation_url']); + } + if (empty($paymentInfo['confirmation']['enforce'])) { + $confirmation->setEnforce(false); + } else { + $confirmation->setEnforce($paymentInfo['confirmation']['enforce']); + } + if (!empty($paymentInfo['confirmation']['return_url'])) { + $confirmation->setReturnUrl($paymentInfo['confirmation']['return_url']); + } + break; + + case ConfirmationType::EMBEDDED: + $confirmation = new ConfirmationEmbedded(); + if (!empty($paymentInfo['confirmation']['confirmation_token'])) { + $confirmation->setConfirmationToken($paymentInfo['confirmation']['confirmation_token']); + } + break; + + case ConfirmationType::EXTERNAL: + $confirmation = new ConfirmationExternal(); + break; + + case ConfirmationType::CODE_VERIFICATION: + $confirmation = new ConfirmationCodeVerification(); + break; + + case ConfirmationType::DEEPLINK: + $confirmation = new ConfirmationDeepLink(); + break; + + case ConfirmationType::QR: + $confirmation = new ConfirmationQr(); + if (!empty($paymentInfo['confirmation']['confirmation_data'])) { + $confirmation->setConfirmationData($paymentInfo['confirmation']['confirmation_data']); + } + break; + } + + if (isset($confirmation)) { + $this->setConfirmation($confirmation); + } else { + throw new InvalidArgumentException('confirmation type '.$confirmationType.' is incorrect'); + } + } + if (!empty($paymentInfo['refunded_amount'])) { + $this->setRefundedAmount($this->factoryAmount($paymentInfo['refunded_amount'])); + } + if (!empty($paymentInfo['receipt_registration'])) { + $this->setReceiptRegistration($paymentInfo['receipt_registration']); + } + if (!empty($paymentInfo['metadata'])) { + $metadata = new Metadata(); + foreach ($paymentInfo['metadata'] as $key => $value) { + $metadata->offsetSet($key, $value); + } + $this->setMetadata($metadata); + } + if (!empty($paymentInfo['cancellation_details'])) { + $cancellationDetails = $paymentInfo['cancellation_details']; + $party = isset($cancellationDetails['party']) ? $cancellationDetails['party'] : null; + $reason = isset($cancellationDetails['reason']) ? $cancellationDetails['reason'] : null; + $this->setCancellationDetails(new CancellationDetails($party, $reason)); + } + if (!empty($paymentInfo['authorization_details'])) { + $authorizationDetails = $paymentInfo['authorization_details']; + $rrn = isset($authorizationDetails['rrn']) ? $authorizationDetails['rrn'] : null; + $authCode = isset($authorizationDetails['auth_code']) ? $authorizationDetails['auth_code'] : null; + $this->setAuthorizationDetails(new AuthorizationDetails($rrn, $authCode)); + } + if (!empty($paymentInfo['transfers'])) { + $transfers = array(); + foreach ($paymentInfo['transfers'] as $transferDefinition) { + $transfers[] = new Transfer($transferDefinition); + } + + $this->setTransfers($transfers); + } + if (!empty($paymentInfo['income_amount'])) { + $this->setIncomeAmount($this->factoryAmount($paymentInfo['income_amount'])); + } + if (!empty($paymentInfo['requestor'])) { + $this->setRequestor($paymentInfo['requestor']); + } + } + + /** + * Фабричный метод для создания способа оплаты + * + * @param array $options Настройки способа оплаты в массиве + * + * @return AbstractPaymentMethod Инстанс способа оплаты нужного типа + */ + private function factoryPaymentMethod($options) + { + $factory = new PaymentMethodFactory(); + + return $factory->factoryFromArray($options); + } + + /** + * Фабричный метод создания суммы + * + * @param array $options Сумма в виде ассоциативного массива + * + * @return AmountInterface Созданный инстанс суммы + */ + private function factoryAmount($options) + { + $amount = new MonetaryAmount(null, $options['currency']); + if ($options['value'] > 0) { + $amount->setValue($options['value']); + } + + return $amount; + } +} \ No newline at end of file diff --git a/lib/Request/Payments/CreatePaymentRequest.php b/lib/Request/Payments/CreatePaymentRequest.php new file mode 100644 index 00000000..60f6dee9 --- /dev/null +++ b/lib/Request/Payments/CreatePaymentRequest.php @@ -0,0 +1,586 @@ +_recipient; + } + + /** + * Проверяет наличие получателя платежа в запросе + * @return bool True если получатель платежа задан, false если нет + */ + public function hasRecipient() + { + return !empty($this->_recipient); + } + + /** + * Возвращает описание транзакции + * @return string + */ + public function getDescription() + { + return $this->_description; + } + + /** + * Устанавливает описание транзакции + * @param string $value + * + * @throws InvalidPropertyValueException Выбрасывается если переданное значение превышает допустимую длину + * @throws InvalidPropertyValueTypeException Выбрасывается если переданное значение не является строкой + */ + public function setDescription($value) + { + if ($value === null || $value === '') { + $this->_description = null; + } elseif (TypeCast::canCastToString($value)) { + $length = mb_strlen((string)$value, 'utf-8'); + if ($length > Payment::MAX_LENGTH_DESCRIPTION) { + throw new InvalidPropertyValueException( + 'Invalid description value', 0, 'CreatePaymentRequest.description', $value + ); + } + $this->_description = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid description value type', 0, 'CreatePaymentRequest.description', $value + ); + } + } + + /** + * Проверяет наличие описания транзакции в создаваемом платеже + * @return bool True если описание транзакции есть, false если нет + */ + public function hasDescription() + { + return $this->_description !== null; + } + + /** + * Устанавливает объект с информацией о получателе платежа + * @param RecipientInterface|null $value Инстанс объекта информации о получателе платежа или null + */ + public function setRecipient($value) + { + if ($value === null || $value === '') { + $this->_recipient = null; + } elseif (is_object($value) && $value instanceof RecipientInterface) { + $this->_recipient = $value; + } else { + throw new \InvalidArgumentException('Invalid recipient value type'); + } + } + + /** + * Возвращает одноразовый токен для проведения оплаты + * @return string Одноразовый токен для проведения оплаты, сформированный YooKassa JS widget + */ + public function getPaymentToken() + { + return $this->_paymentToken; + } + + /** + * Проверяет наличие одноразового токена для проведения оплаты + * @return bool True если токен установлен, false если нет + */ + public function hasPaymentToken() + { + return !empty($this->_paymentToken); + } + + /** + * Устанавливает одноразовый токен для проведения оплаты, сформированный YooKassa JS widget + * @param string $value Одноразовый токен для проведения оплаты + * + * @throws InvalidPropertyValueException Выбрасывается если переданное значение превышает допустимую длину + * @throws InvalidPropertyValueTypeException Выбрасывается если переданное значение не является строкой + */ + public function setPaymentToken($value) + { + if ($value === null || $value === '') { + $this->_paymentToken = null; + } elseif (TypeCast::canCastToString($value)) { + $length = mb_strlen((string)$value, 'utf-8'); + if ($length > self::MAX_LENGTH_PAYMENT_TOKEN) { + throw new InvalidPropertyValueException( + 'Invalid paymentToken value', 0, 'CreatePaymentRequest.paymentToken', $value + ); + } + $this->_paymentToken = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid paymentToken value type', 0, 'CreatePaymentRequest.paymentToken', $value + ); + } + } + + /** + * Устанавливает идентификатор закиси платёжных данных покупателя + * @return string Идентификатор записи о сохраненных платежных данных покупателя + */ + public function getPaymentMethodId() + { + return $this->_paymentMethodId; + } + + /** + * Проверяет наличие идентификатора записи о платёжных данных покупателя + * @return bool True если идентификатор задан, false если нет + */ + public function hasPaymentMethodId() + { + return !empty($this->_paymentMethodId); + } + + /** + * Устанавливает идентификатор записи о сохранённых данных покупателя + * @param string $value Идентификатор записи о сохраненных платежных данных покупателя + * + * @throws InvalidPropertyValueTypeException Генерируется если переданные значение не является строкой или null + */ + public function setPaymentMethodId($value) + { + if ($value === null || $value === '') { + $this->_paymentMethodId = null; + } elseif (TypeCast::canCastToString($value)) { + $this->_paymentMethodId = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid paymentMethodId value type in CreatePaymentRequest', + 0, + 'CreatePaymentRequest.CreatePaymentRequest', + $value + ); + } + } + + /** + * Возвращает данные для создания метода оплаты + * @return AbstractPaymentData Данные используемые для создания метода оплаты + */ + public function getPaymentMethodData() + { + return $this->_paymentMethodData; + } + + /** + * Проверяет установлен ли объект с методом оплаты + * @return bool True если объект метода оплаты установлен, false если нет + */ + public function hasPaymentMethodData() + { + return !empty($this->_paymentMethodData); + } + + /** + * Устанавливает объект с информацией для создания метода оплаты + * @param AbstractPaymentData|null $value Объект с создания метода оплаты или null + * + * @throws InvalidPropertyValueTypeException Выбрасывается если был передан объект невалидного типа + */ + public function setPaymentMethodData($value) + { + if ($value === null || $value === '') { + $this->_paymentMethodData = null; + } elseif (is_object($value) && $value instanceof AbstractPaymentData) { + $this->_paymentMethodData = $value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid paymentMethodData value type in CreatePaymentRequest', + 0, + 'CreatePaymentRequest.paymentMethodData', + $value + ); + } + } + + /** + * Возвращает способ подтверждения платежа + * @return AbstractConfirmationAttributes Способ подтверждения платежа + */ + public function getConfirmation() + { + return $this->_confirmation; + } + + /** + * Проверяет был ли установлен способ подтверждения платежа + * @return bool True если способ подтверждения платежа был установлен, false если нет + */ + public function hasConfirmation() + { + return $this->_confirmation !== null; + } + + /** + * Устанавливает способ подтверждения платежа + * @param AbstractConfirmationAttributes|null $value Способ подтверждения платежа + * + * @throws InvalidPropertyValueTypeException Выбрасывается если переданное значение не является объектом типа + * AbstractConfirmationAttributes или null + */ + public function setConfirmation($value) + { + if ($value === null || $value === '') { + $this->_confirmation = null; + } elseif (is_object($value) && $value instanceof AbstractConfirmationAttributes) { + $this->_confirmation = $value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid confirmation value type in CreatePaymentRequest', + 0, + 'CreatePaymentRequest.confirmation', + $value + ); + } + } + + /** + * Возвращает флаг сохранения платёжных данных + * @return bool Флаг сохранения платёжных данных + */ + public function getSavePaymentMethod() + { + return $this->_savePaymentMethod; + } + + /** + * Проверяет был ли установлен флаг сохранения платёжных данных + * @return bool True если флыг был установлен, false если нет + */ + public function hasSavePaymentMethod() + { + return $this->_savePaymentMethod !== null; + } + + /** + * Устанавливает флаг сохранения платёжных данных. Значение true инициирует создание многоразового payment_method. + * @param bool $value Сохранить платежные данные для последующего использования + * + * @throws InvalidPropertyValueTypeException Генерируется если переданный аргумент не кастится в bool + */ + public function setSavePaymentMethod($value) + { + if ($value === null || $value === '') { + $this->_savePaymentMethod = null; + } elseif (TypeCast::canCastToBoolean($value)) { + $this->_savePaymentMethod = (bool)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid savePaymentMethod value type in CreatePaymentRequest', + 0, + 'CreatePaymentRequest.savePaymentMethod', + $value + ); + } + } + + /** + * Возвращает флаг автоматического принятия поступившей оплаты + * @return bool True если требуется автоматически принять поступившую оплату, false если нет + */ + public function getCapture() + { + return $this->_capture; + } + + /** + * Проверяет был ли установлен флаг автоматического приняти поступившей оплаты + * @return bool True если флаг автоматического принятия оплаты был установлен, false если нет + */ + public function hasCapture() + { + return $this->_capture !== null; + } + + /** + * Устанавливает флаг автоматического принятия поступившей оплаты + * @param bool $value Автоматически принять поступившую оплату + * + * @throws InvalidPropertyValueTypeException Генерируется если переданный аргумент не кастится в bool + */ + public function setCapture($value) + { + if ($value === null || $value === '') { + $this->_capture = null; + } elseif (TypeCast::canCastToBoolean($value)) { + $this->_capture = (bool)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid capture value type in CreatePaymentRequest', 0, 'CreatePaymentRequest.capture', $value + ); + } + } + + /** + * Возвращает IPv4 или IPv6-адрес покупателя + * @return string IPv4 или IPv6-адрес покупателя + */ + public function getClientIp() + { + return $this->_clientIp; + } + + /** + * Проверяет был ли установлен IPv4 или IPv6-адрес покупателя + * @return bool True если IP адрес покупателя был установлен, false если нет + */ + public function hasClientIp() + { + return $this->_clientIp !== null; + } + + /** + * Устанавливает IP адрес покупателя + * @param string $value IPv4 или IPv6-адрес покупателя + * + * @throws InvalidPropertyValueTypeException Выбрасывается если переданный аргумент не является строкой + */ + public function setClientIp($value) + { + if ($value === null || $value === '') { + $this->_clientIp = null; + } elseif (TypeCast::canCastToString($value)) { + $this->_clientIp = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid clientIp value type in CreatePaymentRequest', 0, 'CreatePaymentRequest.clientIp', $value + ); + } + } + + /** + * @return AirlineInterface + */ + public function getAirline() + { + return $this->_airline; + } + + + /** + * @param AirlineInterface $value + */ + public function setAirline(AirlineInterface $value) + { + $this->_airline = $value; + } + + /** + * Проверяет были ли установлены данные длинной записи + * @return bool + */ + function hasAirline() + { + return $this->_airline !== null; + } + + /** + * Возвращает данные оплаты установленные мерчантом + * @return Metadata Метаданные, привязанные к платежу + */ + public function getMetadata() + { + return $this->_metadata; + } + + /** + * Проверяет были ли установлены метаданные заказа + * @return bool True если метаданные были установлены, false если нет + */ + public function hasMetadata() + { + return !empty($this->_metadata) && $this->_metadata->count() > 0; + } + + /** + * Устанавливает метаданные, привязанные к платежу + * @param Metadata|array|null $value Метаданные платежа, устанавливаемые мерчантом + * + * @throws InvalidPropertyValueTypeException Выбрасывается если переданные данные не удалось интерпретировать как + * метаданные платежа + */ + public function setMetadata($value) + { + if ($value === null || (is_array($value) && empty($value))) { + $this->_metadata = null; + } elseif (is_object($value) && $value instanceof Metadata) { + $this->_metadata = $value; + } elseif (is_array($value)) { + $this->_metadata = new Metadata(); + foreach ($value as $key => $val) { + $this->_metadata->offsetSet($key, (string)$val); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid metadata value type in CreatePaymentRequest', 0, 'CreatePaymentRequest.metadata', $value + ); + } + } + + /** + * Проверяет на валидность текущий объект + * @return bool True если объект запроса валиден, false если нет + */ + public function validate() + { + if (!parent::validate()) { + return false; + } + if ($this->hasPaymentToken()) { + if ($this->hasPaymentMethodId()) { + $this->setValidationError('Both paymentToken and paymentMethodID values are specified'); + return false; + } + if ($this->hasPaymentMethodData()) { + $this->setValidationError('Both paymentToken and paymentData values are specified'); + return false; + } + } elseif ($this->hasPaymentMethodId()) { + if ($this->hasPaymentMethodData()) { + $this->setValidationError('Both paymentMethodID and paymentData values are specified'); + return false; + } + } + return true; + } + + /** + * Возвращает билдер объектов запросов создания платежа + * @return CreatePaymentRequestBuilder Инстанс билдера объектов запрсов + */ + public static function builder() + { + return new CreatePaymentRequestBuilder(); + } +} diff --git a/lib/Request/Payments/CreatePaymentRequestBuilder.php b/lib/Request/Payments/CreatePaymentRequestBuilder.php new file mode 100644 index 00000000..06686d23 --- /dev/null +++ b/lib/Request/Payments/CreatePaymentRequestBuilder.php @@ -0,0 +1,351 @@ +recipient = new Recipient(); + $this->airline = new Airline(); + + return $request; + } + + /** + * Устанавливает идентификатор магазина получателя платежа + * @param string $value Идентификатор магазина + * @return CreatePaymentRequestBuilder Инстанс текущего билдера + * + * @throws EmptyPropertyValueException Выбрасывается если было передано пустое значение + * @throws InvalidPropertyValueTypeException Выбрасывается если было передано не строковое значение + */ + public function setAccountId($value) + { + $this->recipient->setAccountId($value); + return $this; + } + + /** + * Устанавливает идентификатор шлюза + * @param string $value Идентификатор шлюза + * @return CreatePaymentRequestBuilder Инстанс текущего билдера + * + * @throws EmptyPropertyValueException Выбрасывается если было передано пустое значение + * @throws InvalidPropertyValueTypeException Выбрасывается если было передано не строковое значение + */ + public function setGatewayId($value) + { + $this->recipient->setGatewayId($value); + return $this; + } + + /** + * Устанавливает получателя платежа из объекта или ассоциативного массива + * @param RecipientInterface|array $value Получатель платежа + * @return CreatePaymentRequestBuilder + * @throws InvalidPropertyValueTypeException Выбрасывается если передан аргумент не валидного типа + */ + public function setRecipient($value) + { + if (is_array($value)) { + $this->recipient->fromArray($value); + } elseif ($value instanceof RecipientInterface) { + $this->recipient->setAccountId($value->getAccountId()); + $this->recipient->setGatewayId($value->getGatewayId()); + } else { + throw new InvalidPropertyValueTypeException('Invalid recipient value', 0, 'recipient', $value); + } + return $this; + } + + /** + * @param AirlineInterface|array $value объект данных длинной записи или ассоциативный массив с данными + * + * @return CreatePaymentRequestBuilder + */ + public function setAirline($value) + { + if (is_array($value)) { + $this->airline->fromArray($value); + } elseif ($value instanceof AirlineInterface) { + $this->airline = clone $value; + } else { + throw new InvalidPropertyValueTypeException('Invalid receipt value type', 0, 'receipt', $value); + } + + + return $this; + } + + /** + * Устанавливает одноразовый токен для проведения оплаты + * @param string $value Одноразовый токен для проведения оплаты + * @return CreatePaymentRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueException Выбрасывается если переданное значение превышает допустимую длину + * @throws InvalidPropertyValueTypeException Выбрасывается если переданное значение не является строкой + */ + public function setPaymentToken($value) + { + $this->currentObject->setPaymentToken($value); + return $this; + } + + /** + * Устанавливает идентификатор записи о сохранённых данных покупателя + * @param string $value Идентификатор записи о сохраненных платежных данных покупателя + * @return CreatePaymentRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueTypeException Генерируется если переданные значение не является строкой или null + */ + public function setPaymentMethodId($value) + { + $this->currentObject->setPaymentMethodId($value); + return $this; + } + + /** + * Устанавливает объект с информацией для создания метода оплаты + * @param AbstractPaymentData|string|array|null $value Объект с создания метода оплаты или null + * @param array $options Настройки способа оплаты в виде ассоциативного массива + * @return CreatePaymentRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueTypeException Выбрасывается если был передан объект невалидного типа + */ + public function setPaymentMethodData($value, array $options = null) + { + if (is_string($value) && $value !== '') { + if (empty($options)) { + $value = $this->getPaymentDataFactory()->factory($value); + } else { + $value = $this->getPaymentDataFactory()->factoryFromArray($options, $value); + } + } elseif (is_array($value)) { + $value = $this->getPaymentDataFactory()->factoryFromArray($value); + } + $this->currentObject->setPaymentMethodData($value); + return $this; + } + + /** + * Устанавливает способ подтверждения платежа + * @param AbstractConfirmationAttributes|string|array|null $value Способ подтверждения платежа + * @param array|null $options Настройки способа подтверждения платежа в виде массива + * @return CreatePaymentRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueTypeException Выбрасывается если переданное значение не является объектом типа + * AbstractConfirmationAttributes или null + */ + public function setConfirmation($value, array $options = null) + { + if (is_string($value) && $value !== '') { + if (empty($options)) { + $value = $this->getConfirmationFactory()->factory($value); + } else { + $value = $this->getConfirmationFactory()->factoryFromArray($options, $value); + } + } elseif (is_array($value)) { + $value = $this->getConfirmationFactory()->factoryFromArray($value); + } + $this->currentObject->setConfirmation($value); + return $this; + } + + /** + * Устанавливает флаг сохранения платёжных данных. Значение true инициирует создание многоразового payment_method. + * @param bool $value Сохранить платежные данные для последующего использования + * @return CreatePaymentRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueTypeException Генерируется если переданный аргумент не кастится в bool + */ + public function setSavePaymentMethod($value) + { + $this->currentObject->setSavePaymentMethod($value); + return $this; + } + + /** + * Устанавливает флаг автоматического принятия поступившей оплаты + * @param bool $value Автоматически принять поступившую оплату + * @return CreatePaymentRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueTypeException Генерируется если переданный аргумент не кастится в bool + + */ + public function setCapture($value) + { + $this->currentObject->setCapture($value); + return $this; + } + + /** + * Устанавливает IP адрес покупателя + * @param string $value IPv4 или IPv6-адрес покупателя + * @return CreatePaymentRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueTypeException Выбрасывается если переданный аргумент не является строкой + */ + public function setClientIp($value) + { + $this->currentObject->setClientIp($value); + return $this; + } + + /** + * Устанавливает метаданные, привязанные к платежу + * @param Metadata|array|null $value Метаданные платежа, устанавливаемые мерчантом + * @return CreatePaymentRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueTypeException Выбрасывается если переданные данные не удалось интерпретировать как + * метаданные платежа + */ + public function setMetadata($value) + { + $this->currentObject->setMetadata($value); + return $this; + } + + /** + * Устанавливает описание транзакции + * @param string $value Описание транзакции + * @return CreatePaymentRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueException Выбрасывается если переданное значение превышает допустимую длину + * @throws InvalidPropertyValueTypeException Выбрасывается если переданное значение не является строкой + */ + public function setDescription($value) + { + $this->currentObject->setDescription($value); + return $this; + } + + /** + * Строит и возвращает объект запроса для отправки в API яндекс денег + * @param array|null $options Массив параметров для установки в объект запроса + * @return CreatePaymentRequestInterface Инстанс объекта запроса + * + * @throws InvalidRequestException Выбрасывается если собрать объект запроса не удалось + */ + public function build(array $options = null) + { + if (!empty($options)) { + $this->setOptions($options); + } + $gatewayId = $this->recipient->getGatewayId(); + if (!empty($gatewayId)) { + $this->currentObject->setRecipient($this->recipient); + } + if ($this->receipt->notEmpty()) { + $this->currentObject->setReceipt($this->receipt); + } + if($this->airline->notEmpty()){ + $this->currentObject->setAirline($this->airline); + } + $this->currentObject->setAmount($this->amount); + $this->currentObject->setTransfers($this->transfers); + + return parent::build(); + } + + /** + * Возвращает фабрику методов проведения платежей + * @return PaymentDataFactory Фабрика методов проведения платежей + */ + protected function getPaymentDataFactory() + { + if ($this->paymentDataFactory === null) { + $this->paymentDataFactory = new PaymentDataFactory(); + } + return $this->paymentDataFactory; + } + + /** + * Возвращает фабрику для создания методов подтверждения платежей + * @return ConfirmationAttributesFactory Фабрика объектов методов подтверждения платежей + */ + protected function getConfirmationFactory() + { + if ($this->confirmationFactory === null) { + $this->confirmationFactory = new ConfirmationAttributesFactory(); + } + return $this->confirmationFactory; + } +} \ No newline at end of file diff --git a/lib/Request/Payments/CreatePaymentRequestInterface.php b/lib/Request/Payments/CreatePaymentRequestInterface.php new file mode 100644 index 00000000..e4834903 --- /dev/null +++ b/lib/Request/Payments/CreatePaymentRequestInterface.php @@ -0,0 +1,223 @@ + 'referenceId', + 'payment_token' => 'paymentToken', + 'payment_method_id' => 'paymentMethodId', + 'client_ip' => 'clientIp', + ); + + private static $paymentDataSerializerMap = array( + PaymentMethodType::BANK_CARD => 'serializePaymentDataBankCard', + PaymentMethodType::YOO_MONEY => 'serializePaymentDataYooMoney', + PaymentMethodType::APPLE_PAY => 'serializePaymentDataMobile', + PaymentMethodType::GOOGLE_PAY => 'serializePaymentDataGooglePay', + PaymentMethodType::SBERBANK => 'serializePaymentDataSberbank', + PaymentMethodType::ALFABANK => 'serializePaymentDataAlfabank', + PaymentMethodType::WEBMONEY => 'serializePaymentData', + PaymentMethodType::QIWI => 'serializePaymentDataMobilePhone', + PaymentMethodType::CASH => 'serializePaymentDataMobilePhone', + PaymentMethodType::MOBILE_BALANCE => 'serializePaymentDataMobilePhone', + PaymentMethodType::INSTALLMENTS => 'serializePaymentData', + PaymentMethodType::B2B_SBERBANK => 'serializePaymentDataB2BSberbank', + PaymentMethodType::TINKOFF_BANK => 'serializePaymentData', + PaymentMethodType::WECHAT => 'serializePaymentData', + ); + + public function serialize(CreatePaymentRequestInterface $request) + { + $result = array(); + + if ($request->getAmount()->getValue() > 0) { + $result['amount'] = $this->serializeAmount($request->getAmount()); + } + + if ($request->hasTransfers()) { + $result['transfers'] = $this->serializeTransfers($request->getTransfers()); + } + + if ($request->hasDescription()) { + $result['description'] = $request->getDescription(); + } + if ($request->hasReceipt()) { + $receipt = $request->getReceipt(); + if ($receipt->notEmpty()) { + $result['receipt'] = $this->serializeReceipt($receipt); + } + } + if ($request->hasRecipient()) { + $result['recipient']['account_id'] = $request->getRecipient()->getAccountId(); + $result['recipient']['gateway_id'] = $request->getRecipient()->getGatewayId(); + } + if ($request->hasPaymentMethodData()) { + $method = self::$paymentDataSerializerMap[$request->getPaymentMethodData()->getType()]; + $result['payment_method_data'] = $this->{$method}($request->getPaymentMethodData()); + } + if ($request->hasConfirmation()) { + $confirmation = $request->getConfirmation(); + $result['confirmation'] = $this->serializeConfirmation($confirmation); + } + if ($request->hasMetadata()) { + $result['metadata'] = $request->getMetadata()->toArray(); + } + if ($request->hasCapture()) { + $result['capture'] = $request->getCapture(); + } + if ($request->hasSavePaymentMethod()) { + $result['save_payment_method'] = $request->getSavePaymentMethod(); + } + if ($request->hasAirline()) { + $airline = $request->getAirline(); + $result['airline'] = array(); + + $ticketNumber = $airline->getTicketNumber(); + if (!empty($ticketNumber)) { + $result['airline']['ticket_number'] = $ticketNumber; + } + $bookingReference = $airline->getBookingReference(); + if (!empty($bookingReference)) { + $result['airline']['booking_reference'] = $bookingReference; + } + + /** @var PassengerInterface $passenger */ + foreach ($airline->getPassengers() as $passenger) { + $result['airline']['passengers'][] = array( + 'first_name' => $passenger->getFirstName(), + 'last_name' => $passenger->getLastName(), + ); + } + + /** @var LegInterface $leg */ + foreach ($airline->getLegs() as $leg) { + $result['airline']['legs'][] = array( + 'departure_airport' => $leg->getDepartureAirport(), + 'destination_airport' => $leg->getDestinationAirport(), + 'departure_date' => $leg->getDepartureDate(), + ); + } + } + + foreach (self::$propertyMap as $name => $property) { + $value = $request->{$property}; + if (!empty($value)) { + $result[$name] = $value; + } + } + + return $result; + } + + private function serializeConfirmation(AbstractConfirmationAttributes $confirmation) + { + $result = array( + 'type' => $confirmation->getType(), + ); + if ($locale = $confirmation->getLocale()) { + $result['locale'] = $locale; + } + if ($confirmation->getType() === ConfirmationType::REDIRECT) { + /** @var ConfirmationAttributesRedirect $confirmation */ + if ($confirmation->getEnforce()) { + $result['enforce'] = $confirmation->getEnforce(); + } + $result['return_url'] = $confirmation->getReturnUrl(); + } + + return $result; + } + + private function serializeReceipt(ReceiptInterface $receipt) + { + $result = array(); + + /** @var ReceiptItem $item */ + foreach ($receipt->getItems() as $item) { + $result['items'][] = $item->jsonSerialize(); + } + + $customer = $receipt->getCustomer(); + if (!empty($customer)) { + $result['customer'] = $customer->jsonSerialize(); + } + + $value = $receipt->getTaxSystemCode(); + if (!empty($value)) { + $result['tax_system_code'] = $value; + } + + return $result; + } + + private function serializeAmount(AmountInterface $amount) + { + return array( + 'value' => $amount->getValue(), + 'currency' => $amount->getCurrency(), + ); + } + + private function serializePaymentDataBankCard(PaymentDataBankCard $paymentData) + { + $result = array( + 'type' => $paymentData->getType(), + ); + if ($paymentData->getCard() !== null) { + $result['card'] = array( + 'cardholder' => $paymentData->getCard()->getCardholder(), + 'expiry_year' => $paymentData->getCard()->getExpiryYear(), + 'expiry_month' => $paymentData->getCard()->getExpiryMonth(), + 'number' => $paymentData->getCard()->getNumber(), + 'csc' => $paymentData->getCard()->getCsc(), + ); + } + + return $result; + } + + private function serializePaymentDataYooMoney(PaymentDataYooMoney $paymentData) + { + $result = array( + 'type' => $paymentData->getType(), + ); + + return $result; + } + + private function serializePaymentDataMobile(AbstractPaymentData $paymentData) + { + $result = array( + 'type' => $paymentData->getType(), + ); + if ($paymentData->getPaymentData() !== null) { + $result['payment_data'] = $paymentData->getPaymentData(); + } + + return $result; + } + + private function serializePaymentDataSberbank(PaymentDataSberbank $paymentData) + { + $result = array( + 'type' => $paymentData->getType(), + ); + if ($paymentData->getPhone() !== null) { + $result['phone'] = $paymentData->getPhone(); + } + + return $result; + } + + private function serializePaymentDataAlfabank(PaymentDataAlfabank $paymentData) + { + $result = array( + 'type' => $paymentData->getType(), + ); + if ($paymentData->getLogin() !== null) { + $result['login'] = $paymentData->getLogin(); + } + + return $result; + } + + private function serializePaymentData(AbstractPaymentData $paymentData) + { + return array( + 'type' => $paymentData->getType(), + ); + } + + private function serializePaymentDataMobilePhone(AbstractPaymentData $paymentData) + { + $result = array( + 'type' => $paymentData->getType(), + ); + if ($paymentData->getPhone() !== null) { + $result['phone'] = $paymentData->getPhone(); + } + + return $result; + } + + /** + * @param PaymentDataGooglePay $paymentData + * + * @return array + */ + private function serializePaymentDataGooglePay(PaymentDataGooglePay $paymentData) + { + $result = array( + 'type' => $paymentData->getType(), + 'payment_method_token' => $paymentData->getPaymentMethodToken(), + 'google_transaction_id' => $paymentData->getGoogleTransactionId(), + ); + + return $result; + } + + /** + * @param PaymentDataB2bSberbank $paymentData + * + * @return array + */ + private function serializePaymentDataB2BSberbank(PaymentDataB2bSberbank $paymentData) + { + $result = array( + 'type' => $paymentData->getType(), + ); + + if ($paymentData->getPaymentPurpose() !== null) { + $result['payment_purpose'] = $paymentData->getPaymentPurpose(); + } + + if ($paymentData->getVatData() !== null) { + $vatData = array( + 'type' => $paymentData->getVatData()->getType(), + ); + + if ($paymentData->getVatData()->getRate() !== null) { + $vatData['rate'] = $paymentData->getVatData()->getRate(); + } + + if ($paymentData->getVatData()->getAmount() !== null) { + $vatData['amount'] = $this->serializeAmount($paymentData->getVatData()->getAmount()); + } + + $result['vat_data'] = $vatData; + } + + return $result; + } + + /** + * @param TransferInterface[] $transfers + * + * @return array + */ + private function serializeTransfers(array $transfers) + { + $result = array(); + foreach ($transfers as $transfer) { + $result[] = array( + 'account_id' => $transfer->getAccountId(), + 'amount' => $this->serializeAmount($transfer->getAmount()) + ); + } + + return $result; + } +} \ No newline at end of file diff --git a/lib/Request/Payments/CreatePaymentResponse.php b/lib/Request/Payments/CreatePaymentResponse.php new file mode 100644 index 00000000..12046035 --- /dev/null +++ b/lib/Request/Payments/CreatePaymentResponse.php @@ -0,0 +1,35 @@ +_amount !== null) { + $value = $this->_amount->getValue(); + if (empty($value) || $value <= 0.0) { + $this->setValidationError('Invalid amount value: ' . $value); + return false; + } + } + if ($this->getReceipt() && $this->getReceipt()->notEmpty()) { + $email = $this->getReceipt()->getCustomer()->getEmail(); + $phone = $this->getReceipt()->getCustomer()->getPhone(); + if (empty($email) && empty($phone)) { + $this->setValidationError('Both email and phone values are empty in receipt'); + return false; + } + } + return true; + } + + /** + * Возвращает билдер объектов запросов на подтверждение оплаты + * @return CreateCaptureRequestBuilder Инстанс билдера + */ + public static function builder() + { + return new CreateCaptureRequestBuilder(); + } +} diff --git a/lib/Request/Payments/Payment/CreateCaptureRequestBuilder.php b/lib/Request/Payments/Payment/CreateCaptureRequestBuilder.php new file mode 100644 index 00000000..1c4303fd --- /dev/null +++ b/lib/Request/Payments/Payment/CreateCaptureRequestBuilder.php @@ -0,0 +1,75 @@ +setOptions($options); + } + if (!empty($this->transfers)) { + $this->currentObject->setTransfers($this->transfers); + } + if ($this->amount->getValue() > 0) { + $this->currentObject->setAmount($this->amount); + } + if ($this->receipt->notEmpty()) { + $this->currentObject->setReceipt($this->receipt); + } + return parent::build(); + } +} diff --git a/lib/Request/Payments/Payment/CreateCaptureRequestInterface.php b/lib/Request/Payments/Payment/CreateCaptureRequestInterface.php new file mode 100644 index 00000000..a5d1f11b --- /dev/null +++ b/lib/Request/Payments/Payment/CreateCaptureRequestInterface.php @@ -0,0 +1,79 @@ +hasAmount()) { + $result['amount'] = $this->serializeAmount($request->getAmount()); + } + if ($request->hasTransfers()) { + $result['transfers'] = $this->serializeTransfers($request->getTransfers()); + } + if ($request->hasReceipt()) { + $receipt = $request->getReceipt(); + if ($receipt->notEmpty()) { + $result['receipt'] = array(); + /** @var ReceiptItem $item */ + foreach ($receipt->getItems() as $item) { + $itemArray = array( + 'description' => $item->getDescription(), + 'amount' => array( + 'value' => $item->getPrice()->getValue(), + 'currency' => $item->getPrice()->getCurrency(), + ), + 'quantity' => $item->getQuantity(), + 'vat_code' => $item->getVatCode(), + ); + + if ($value = $item->getPaymentSubject()) { + $itemArray['payment_subject'] = $value; + } + + if ($value = $item->getPaymentMode()) { + $itemArray['payment_mode'] = $value; + } + + if ($value = $item->getProductCode()) { + $itemArray['product_code'] = $value; + } + + if ($value = $item->getCountryOfOriginCode()) { + $itemArray['country_of_origin_code'] = $value; + } + + if ($value = $item->getCustomsDeclarationNumber()) { + $itemArray['customs_declaration_number'] = $value; + } + + if ($value = $item->getExcise()) { + $itemArray['excise'] = $value; + } + + $result['receipt']['items'][] = $itemArray; + } + + if ($customer = $receipt->getCustomer()) { + $customerArray = array(); + + if ($value = $customer->getEmail()) { + $customerArray['email'] = $value; + } + + if ($value = $customer->getPhone()) { + $customerArray['phone'] = $value; + } + + if ($value = $customer->getFullName()) { + $customerArray['full_name'] = $value; + } + + if ($value = $customer->getInn()) { + $customerArray['inn'] = $value; + } + + $result['receipt']['customer'] = $customerArray; + } + + if ($value = $receipt->getTaxSystemCode()) { + $result['receipt']['tax_system_code'] = $value; + } + } + } + + return $result; + } + + private function serializeAmount(AmountInterface $amount) + { + return array( + 'value' => $amount->getValue(), + 'currency' => $amount->getCurrency(), + ); + } + + /** + * @param TransferInterface[] $transfers + * + * @return array + */ + private function serializeTransfers(array $transfers) + { + $result = array(); + foreach ($transfers as $transfer) { + $result[] = array( + 'account_id' => $transfer->getAccountId(), + 'amount' => $this->serializeAmount($transfer->getAmount()) + ); + } + + return $result; + } +} \ No newline at end of file diff --git a/lib/Request/Payments/Payment/CreateCaptureResponse.php b/lib/Request/Payments/Payment/CreateCaptureResponse.php new file mode 100644 index 00000000..7e4c49a2 --- /dev/null +++ b/lib/Request/Payments/Payment/CreateCaptureResponse.php @@ -0,0 +1,37 @@ +_createdAtGte; + } + + /** + * Проверяет была ли установлена дата создания от которой выбираются платежи + * @return bool True если дата была установлена, false если нет + */ + public function hasCreatedAtGte() + { + return $this->_createdAtGte !== null; + } + + /** + * Устанавливает дату создания от которой выбираются платежи + * @param \DateTime|string|int|null $value Время создания, от (включительно) или null чтобы удалить значение + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtGte($value) + { + if ($value === null || $value === '') { + $this->_createdAtGte = null; + } elseif (TypeCast::canCastToDateTime($value)) { + $dateTime = TypeCast::castToDateTime($value); + if ($dateTime === null) { + throw new InvalidPropertyValueException( + 'Invalid createdAtGte value in PaymentsRequest', 0, 'PaymentRequest.createdAtGte' + ); + } + $this->_createdAtGte = $dateTime; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid createdAtGte value type in PaymentsRequest', 0, 'PaymentRequest.createdAtGte' + ); + } + } + + /** + * Возвращает дату создания от которой будут возвращены платежи или null если дата не была установлена + * @return \DateTime|null Время создания, от (не включая) + */ + public function getCreatedAtGt() + { + return $this->_createdAtGt; + } + + /** + * Проверяет была ли установлена дата создания от которой выбираются платежи + * @return bool True если дата была установлена, false если нет + */ + public function hasCreatedAtGt() + { + return $this->_createdAtGt !== null; + } + + /** + * Устанавливает дату создания от которой выбираются платежи + * @param \DateTime|string|int|null $value Время создания, от (не включая) или null чтобы удалить значение + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtGt($value) + { + if ($value === null || $value === '') { + $this->_createdAtGt = null; + } elseif (TypeCast::canCastToDateTime($value)) { + $dateTime = TypeCast::castToDateTime($value); + if ($dateTime === null) { + throw new InvalidPropertyValueException( + 'Invalid createdAtGt value in PaymentsRequest', 0, 'PaymentRequest.createdAtGt' + ); + } + $this->_createdAtGt = $dateTime; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid createdAtGt value type in PaymentsRequest', 0, 'PaymentRequest.createdAtGt' + ); + } + } + + /** + * Возвращает дату создания до которой будут возвращены платежи или null если дата не была установлена + * @return \DateTime|null Время создания, до (включительно) + */ + public function getCreatedAtLte() + { + return $this->_createdAtLte; + } + + /** + * Проверяет была ли установлена дата создания до которой выбираются платежи + * @return bool True если дата была установлена, false если нет + */ + public function hasCreatedAtLte() + { + return $this->_createdAtLte !== null; + } + + /** + * Устанавливает дату создания до которой выбираются платежи + * @param \DateTime|string|int|null $value Время создания, до (включительно) или null чтобы удалить значение + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtLte($value) + { + if ($value === null || $value === '') { + $this->_createdAtLte = null; + } elseif (TypeCast::canCastToDateTime($value)) { + $dateTime = TypeCast::castToDateTime($value); + if ($dateTime === null) { + throw new InvalidPropertyValueException( + 'Invalid createdAtLte value in PaymentsRequest', 0, 'PaymentRequest.createdAtLte' + ); + } + $this->_createdAtLte = $dateTime; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid createdAtLte value type in PaymentsRequest', 0, 'PaymentRequest.createdAtLte' + ); + } + } + + /** + * Возвращает дату создания до которой будут возвращены платежи или null если дата не была установлена + * @return \DateTime|null Время создания, до (не включая) + */ + public function getCreatedAtLt() + { + return $this->_createdAtLt; + } + + /** + * Проверяет была ли установлена дата создания до которой выбираются платежи + * @return bool True если дата была установлена, false если нет + */ + public function hasCreatedAtLt() + { + return $this->_createdAtLt !== null; + } + + /** + * Устанавливает дату создания до которой выбираются платежи + * @param \DateTime|string|int|null $value Время создания, до (не включая) или null чтобы удалить значение + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtLt($value) + { + if ($value === null || $value === '') { + $this->_createdAtLt = null; + } elseif (TypeCast::canCastToDateTime($value)) { + $dateTime = TypeCast::castToDateTime($value); + if ($dateTime === null) { + throw new InvalidPropertyValueException( + 'Invalid createdAtLt value in PaymentsRequest', 0, 'PaymentRequest.createdAtLt' + ); + } + $this->_createdAtLt = $dateTime; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid createdAlLt value type in PaymentsRequest', 0, 'PaymentRequest.createdAtLt' + ); + } + } + + /** + * Возвращает дату подтверждения от которой будут возвращены платежи или null если дата не была установлена + * @return \DateTime|null Время подтверждения, от (включительно) + */ + public function getCapturedAtGte() + { + return $this->_capturedAtGte; + } + + /** + * Проверяет была ли установлена дата подтверждения от которой выбираются платежи + * @return bool True если дата была установлена, false если нет + */ + public function hasCapturedAtGte() + { + return $this->_capturedAtGte !== null; + } + + /** + * Устанавливает дату подтверждения от которой выбираются платежи + * @param \DateTime|string|int|null $value Время подтверждения, от (включительно) или null чтобы удалить значение + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCapturedAtGte($value) + { + if ($value === null || $value === '') { + $this->_capturedAtGte = null; + } elseif (TypeCast::canCastToDateTime($value)) { + $dateTime = TypeCast::castToDateTime($value); + if ($dateTime === null) { + throw new InvalidPropertyValueException( + 'Invalid capturedAtGte value in PaymentsRequest', 0, 'PaymentRequest.capturedAtGte' + ); + } + $this->_capturedAtGte = $dateTime; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid capturedAtGte value type in PaymentsRequest', 0, 'PaymentRequest.capturedAtGte' + ); + } + } + + /** + * Возвращает дату подтверждения от которой будут возвращены платежи или null если дата не была установлена + * @return \DateTime|null Время подтверждения, от (не включая) + */ + public function getCapturedAtGt() + { + return $this->_capturedAtGt; + } + + /** + * Проверяет была ли установлена дата подтверждения от которой выбираются платежи + * @return bool True если дата была установлена, false если нет + */ + public function hasCapturedAtGt() + { + return $this->_capturedAtGt !== null; + } + + /** + * Устанавливает дату подтверждения от которой выбираются платежи + * @param \DateTime|string|int|null $value Время подтверждения, от (не включая) или null чтобы удалить значение + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCapturedAtGt($value) + { + if ($value === null || $value === '') { + $this->_capturedAtGt = null; + } elseif (TypeCast::canCastToDateTime($value)) { + $dateTime = TypeCast::castToDateTime($value); + if ($dateTime === null) { + throw new InvalidPropertyValueException( + 'Invalid capturedAtGt value in PaymentsRequest', 0, 'PaymentRequest.capturedAtGt' + ); + } + $this->_capturedAtGt = $dateTime; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid capturedAtGt value type in PaymentsRequest', 0, 'PaymentRequest.capturedAtGt' + ); + } + } + + /** + * Возвращает дату подтверждения до которой будут возвращены платежи или null если дата не была установлена + * @return \DateTime|null Время подтверждения, до (включительно) + */ + public function getCapturedAtLte() + { + return $this->_capturedAtLte; + } + + /** + * Проверяет была ли установлена дата подтверждения до которой выбираются платежи + * @return bool True если дата была установлена, false если нет + */ + public function hasCapturedAtLte() + { + return $this->_capturedAtLte !== null; + } + + /** + * Устанавливает дату подтверждения до которой выбираются платежи + * @param \DateTime|string|int|null $value Время подтверждения, до (включительно) или null чтобы удалить значение + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCapturedAtLte($value) + { + if ($value === null || $value === '') { + $this->_capturedAtLte = null; + } elseif (TypeCast::canCastToDateTime($value)) { + $dateTime = TypeCast::castToDateTime($value); + if ($dateTime === null) { + throw new InvalidPropertyValueException( + 'Invalid capturedAtLte value in PaymentsRequest', 0, 'PaymentRequest.capturedAtLte' + ); + } + $this->_capturedAtLte = $dateTime; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid capturedAtLte value type in PaymentsRequest', 0, 'PaymentRequest.capturedAtLte' + ); + } + } + + /** + * Возвращает дату подтверждения до которой будут возвращены платежи или null если дата не была установлена + * @return \DateTime|null Время подтверждения, до (не включая) + */ + public function getCapturedAtLt() + { + return $this->_capturedAtLt; + } + + /** + * Проверяет была ли установлена дата подтверждения до которой выбираются платежи + * @return bool True если дата была установлена, false если нет + */ + public function hasCapturedAtLt() + { + return $this->_capturedAtLt !== null; + } + + /** + * Устанавливает дату подтверждения до которой выбираются платежи + * @param \DateTime|string|int|null $value Время подтверждения, до (не включая) или null чтобы удалить значение + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCapturedAtLt($value) + { + if ($value === null || $value === '') { + $this->_capturedAtLt = null; + } elseif (TypeCast::canCastToDateTime($value)) { + $dateTime = TypeCast::castToDateTime($value); + if ($dateTime === null) { + throw new InvalidPropertyValueException( + 'Invalid capturedAtLt value in PaymentsRequest', 0, 'PaymentRequest.capturedAtLt' + ); + } + $this->_capturedAtLt = $dateTime; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid capturedAlLt value type in PaymentsRequest', 0, 'PaymentRequest.capturedAtLt' + ); + } + } + + /** + * Возвращает статус выбираемых платежей или null если он до этого не был установлен + * @return string|null Статус выбираемых платежей + */ + public function getStatus() + { + return $this->_status; + } + + /** + * Проверяет был ли установлен статус выбираемых платежей + * @return bool True если статус был установлен, false если нет + */ + public function hasStatus() + { + return $this->_status !== null; + } + + /** + * Устанавливает статус выбираемых платежей + * @param string $value Статус выбираемых платежей или null чтобы удалить значение + * + * @throws InvalidPropertyValueException Выбрасывается если переданное значение не является валидным статусом + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setStatus($value) + { + if ($value === null || $value === '') { + $this->_status = null; + } elseif (TypeCast::canCastToEnumString($value)) { + if (!PaymentStatus::valueExists((string)$value)) { + throw new InvalidPropertyValueException( + 'Invalid status value in PaymentsRequest', 0, 'PaymentsRequest.status', $value + ); + } else { + $this->_status = (string)$value; + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid status value in PaymentsRequest', 0, 'PaymentsRequest.status', $value + ); + } + } + + /** + * Возвращает платежный метод выбираемых платежей или null если он до этого не был установлен + * @return string|null Платежный метод выбираемых платежей + */ + public function getPaymentMethod() + { + return $this->_paymentMethod; + } + + /** + * Проверяет был ли установлен платежный метод выбираемых платежей + * @return bool True если платежный метод был установлен, false если нет + */ + public function hasPaymentMethod() + { + return $this->_paymentMethod !== null; + } + + /** + * Устанавливает платежный метод выбираемых платежей + * @param string $value Платежный метод выбираемых платежей или null чтобы удалить значение + * + * @throws InvalidPropertyValueException Выбрасывается если переданное значение не является валидным статусом + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setPaymentMethod($value) + { + if ($value === null || $value === '') { + $this->_paymentMethod = null; + } elseif (TypeCast::canCastToEnumString($value)) { + if (!PaymentMethodType::valueExists((string)$value)) { + throw new InvalidPropertyValueException( + 'Invalid status value in PaymentsRequest', 0, 'PaymentsRequest.paymentMethod', $value + ); + } else { + $this->_paymentMethod = (string)$value; + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid status value type in PaymentsRequest', 0, 'PaymentsRequest.paymentMethod', $value + ); + } + } + + /** + * Ограничение количества объектов платежа + * @return integer|null Ограничение количества объектов платежа + */ + public function getLimit() + { + return $this->_limit; + } + + /** + * Проверяет был ли установлено ограничение количества объектов платежа + * @return bool True если было установлено, false если нет + */ + public function hasLimit() + { + return $this->_limit !== null; + } + + /** + * Устанавливает ограничение количества объектов платежа + * @param integer|null $value Ограничение количества объектов платежа или null чтобы удалить значение + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передано не целое число + */ + public function setLimit($value) + { + if ($value === null || $value === '') { + $this->_limit = null; + } elseif (is_int($value)) { + if ($value < 0 || $value > self::MAX_LIMIT_VALUE) { + throw new InvalidPropertyValueException( + 'Invalid limit value in PaymentsRequest', 0, 'PaymentsRequest.limit', $value + ); + } + $this->_limit = $value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid limit value type in PaymentsRequest', 0, 'PaymentsRequest.limit', $value + ); + } + } + + /** + * Страница выдачи результатов, которую необходимо отобразить + * @return string|null + */ + public function getCursor() + { + return $this->_cursor; + } + + /** + * Проверяет был ли установлена страница выдачи результатов, которую необходимо отобразить + * @return bool True если была установлена, false если нет + */ + public function hasCursor() + { + return $this->_cursor !== null; + } + + /** + * Устанавливает cтраницw выдачи результатов, которую необходимо отобразить + * @param string $value Страница выдачи результатов или null чтобы удалить значение + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setCursor($value) + { + if ($value === null || $value === '') { + $this->_cursor = null; + } elseif (TypeCast::canCastToString($value)) { + $this->_cursor = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid status value type in PaymentsRequest', 0, 'PaymentsRequest.limit', $value + ); + } + } + + /** + * Проверяет валидность текущего объекта запроса + * @return bool True если объект валиден, false если нет + */ + public function validate() + { + return true; + } + + /** + * Возвращает инстанс билдера объектов запросов списка платежей магазина + * @return PaymentsRequestBuilder Билдер объектов запросов списка платежей + */ + public static function builder() + { + return new PaymentsRequestBuilder(); + } +} diff --git a/lib/Request/Payments/PaymentsRequestBuilder.php b/lib/Request/Payments/PaymentsRequestBuilder.php new file mode 100644 index 00000000..1dbe4064 --- /dev/null +++ b/lib/Request/Payments/PaymentsRequestBuilder.php @@ -0,0 +1,248 @@ +currentObject->setCursor($value); + return $this; + } + + /** + * Устанавливает дату создания от которой выбираются платежи + * @param DateTime|string|int|null $value Время создания, от (не включая) или null чтобы удалить значение + * @return PaymentsRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtGt($value) + { + $this->currentObject->setCreatedAtGt($value); + return $this; + } + + /** + * Устанавливает дату создания от которой выбираются платежи + * @param DateTime|string|int|null $value Время создания, от (включительно) или null чтобы удалить значение + * @return PaymentsRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtGte($value) + { + $this->currentObject->setCreatedAtGte($value); + return $this; + } + + /** + * Устанавливает дату создания до которой выбираются платежи + * @param DateTime|string|int|null $value Время создания, до (не включая) или null чтобы удалить значение + * @return PaymentsRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtLt($value) + { + $this->currentObject->setCreatedAtLt($value); + return $this; + } + + /** + * Устанавливает дату создания до которой выбираются платежи + * @param DateTime|string|int|null $value Время создания, до (включительно) или null чтобы удалить значение + * @return PaymentsRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtLte($value) + { + $this->currentObject->setCreatedAtLte($value); + return $this; + } + + /** + * Устанавливает дату подтверждения от которой выбираются платежи + * @param DateTime|string|int|null $value Время создания, до (включительно) или null чтобы удалить значение + * @return PaymentsRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCapturedAtGt($value) + { + $this->currentObject->setCapturedAtGt($value); + return $this; + } + + /** + * Устанавливает дату подтверждения от которой выбираются платежи + * @param DateTime|string|int|null $value Время подтверждения, от (включительно) или null чтобы удалить значение + * @return PaymentsRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCapturedAtGte($value) + { + $this->currentObject->setCapturedAtGte($value); + return $this; + } + + /** + * Устанавливает дату подтверждения до которой выбираются платежи + * @param DateTime|string|int|null $value Время подтверждения, до (включительно) или null чтобы удалить значение + * @return PaymentsRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCapturedAtLt($value) + { + $this->currentObject->setCapturedAtLt($value); + return $this; + } + + /** + * Устанавливает дату подтверждения до которой выбираются платежи + * @param DateTime|string|int|null $value Время подтверждения, до (включительно) или null чтобы удалить значение + * @return PaymentsRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCapturedAtLte($value) + { + $this->currentObject->setCapturedAtLte($value); + return $this; + } + + /** + * Устанавливает ограничение количества объектов платежа + * @param string $value Ограничение количества объектов платежа или null чтобы удалить значение + * @return PaymentsRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод было передана не целое число + */ + public function setLimit($value) + { + $this->currentObject->setLimit($value); + return $this; + } + + /** + * Устанавливает статус выбираемых платежей + * @param string $value Статус выбираемых платежей или null чтобы удалить значение + * @return PaymentsRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueException Выбрасывается если переданное значение не является валидным статусом + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setStatus($value) + { + $this->currentObject->setStatus($value); + return $this; + } + + /** + * Устанавливает платежный метод выбираемых платежей + * @param string $value Платежный метод выбираемых платежей или null чтобы удалить значение + * @return PaymentsRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueException Выбрасывается если переданное значение не является валидным статусом + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setPaymentMethod($value) + { + $this->currentObject->setPaymentMethod($value); + return $this; + } + + /** + * Собирает и возвращает объект запроса списка платежей магазина + * @param array|null $options Массив с настройками запроса + * @return AbstractRequest Инстанс объекта запроса к API для получения списка платежей магазина + */ + public function build(array $options = null) + { + return parent::build($options); + } +} diff --git a/lib/Request/Payments/PaymentsRequestInterface.php b/lib/Request/Payments/PaymentsRequestInterface.php new file mode 100644 index 00000000..f1a918c0 --- /dev/null +++ b/lib/Request/Payments/PaymentsRequestInterface.php @@ -0,0 +1,181 @@ + 'created_at.gte', + 'createdAtGt' => 'created_at.gt', + 'createdAtLte' => 'created_at.lte', + 'createdAtLt' => 'created_at.lt', + 'capturedAtGte' => 'captured_at.gte', + 'capturedAtGt' => 'captured_at.gt', + 'capturedAtLte' => 'captured_at.lte', + 'capturedAtLt' => 'captured_at.lt', + 'status' => 'status', + 'paymentMethod' => 'payment_method', + 'limit' => 'limit', + 'cursor' => 'cursor', + ); + + /** + * Сериализует объект запроса к API для дальнейшей его отправки + * @param PaymentsRequestInterface $request Сериализуемый объект + * @return array Массив с инфомрацией, отпарвляемый в дальнейшем в API + */ + public function serialize(PaymentsRequestInterface $request) + { + $result = array(); + foreach (self::$propertyMap as $property => $name) { + $value = $request->{$property}; + if (!empty($value)) { + if ($value instanceof \DateTime) { + if ($value->getTimestamp() > 1) { + $result[$name] = $value->format(DATE_ATOM); + } + } else { + $result[$name] = $value; + } + } + } + return $result; + } +} diff --git a/lib/Request/Payments/PaymentsResponse.php b/lib/Request/Payments/PaymentsResponse.php new file mode 100644 index 00000000..64d865f2 --- /dev/null +++ b/lib/Request/Payments/PaymentsResponse.php @@ -0,0 +1,186 @@ +items = array(); + foreach ($options['items'] as $paymentInfo) { + $payment = new Payment(); + $payment->setId($paymentInfo['id']); + $payment->setStatus($paymentInfo['status']); + $payment->setAmount(new MonetaryAmount( + $paymentInfo['amount']['value'], + $paymentInfo['amount']['currency'] + )); + if (!empty($paymentInfo['description'])) { + $payment->setDescription($paymentInfo['description']); + } + $payment->setCreatedAt(strtotime($paymentInfo['created_at'])); + if (!empty($paymentInfo['payment_method']) + && $method = $this->factoryPaymentMethod($paymentInfo['payment_method'])) { + $payment->setPaymentMethod($method); + } + $payment->setPaid($paymentInfo['paid']); + $payment->setRefundable($paymentInfo['refundable']); + + if (!empty($paymentInfo['recipient'])) { + $recipient = new Recipient(); + $recipient->setAccountId($paymentInfo['recipient']['account_id']); + $recipient->setGatewayId($paymentInfo['recipient']['gateway_id']); + $payment->setRecipient($recipient); + } + if (!empty($paymentInfo['captured_at'])) { + $payment->setCapturedAt(strtotime($paymentInfo['captured_at'])); + } + if (!empty($paymentInfo['confirmation'])) { + if ($paymentInfo['confirmation']['type'] === ConfirmationType::REDIRECT) { + $confirmation = new ConfirmationRedirect(); + $confirmation->setConfirmationUrl($paymentInfo['confirmation']['confirmation_url']); + if (!empty($paymentInfo['confirmation']['enforce'])) { + $confirmation->setEnforce($paymentInfo['confirmation']['enforce']); + } + if (!empty($paymentInfo['confirmation']['return_url'])) { + $confirmation->setReturnUrl($paymentInfo['confirmation']['return_url']); + } + } else { + $confirmation = new ConfirmationExternal(); + } + $payment->setConfirmation($confirmation); + } + if (!empty($paymentInfo['refunded_amount'])) { + $payment->setRefundedAmount(new MonetaryAmount( + $paymentInfo['refunded_amount']['value'], $paymentInfo['refunded_amount']['currency'] + )); + } + if (!empty($paymentInfo['receipt_registration'])) { + $payment->setReceiptRegistration($paymentInfo['receipt_registration']); + } + if (!empty($paymentInfo['metadata'])) { + $metadata = new Metadata(); + foreach ($paymentInfo['metadata'] as $key => $value) { + $metadata->offsetSet($key, $value); + } + $payment->setMetadata($metadata); + } + if (!empty($paymentInfo['cancellation_details'])) { + $cancellationDetails = $paymentInfo['cancellation_details']; + $party = isset($cancellationDetails['party']) ? $cancellationDetails['party'] : null; + $reason = isset($cancellationDetails['reason']) ? $cancellationDetails['reason'] : null; + $payment->setCancellationDetails(new CancellationDetails($party, $reason)); + } + if (!empty($paymentInfo['authorization_details'])) { + $authorizationDetails = $paymentInfo['authorization_details']; + $rrn = isset($authorizationDetails['rrn']) ? $authorizationDetails['rrn'] : null; + $authCode = isset($authorizationDetails['auth_code']) ? $authorizationDetails['auth_code'] : null; + $payment->setAuthorizationDetails(new AuthorizationDetails($rrn, $authCode)); + } + $this->items[] = $payment; + } + if (!empty($options['next_cursor'])) { + $this->nextCursor = $options['next_cursor']; + } + } + + /** + * Возвращает список платежей + * @return PaymentInterface[] Список платежей + */ + public function getItems() + { + return $this->items; + } + + /** + * Возвращает токен следующей страницы, если он задан, или null + * @return string|null Токен следующей страницы + */ + public function getNextCursor() + { + return $this->nextCursor; + } + + /** + * Проверяет имееотся ли в ответе токен следующей страницы + * @return bool True если токен следующей страницы есть, false если нет + */ + public function hasNextCursor() + { + return $this->nextCursor !== null; + } + + /** + * Фабричный метод для создания объектов методов оплаты + * + * @param array $options Массив настроек метода оплаты + * + * @return AbstractPaymentMethod Используемый способ оплаты + */ + private function factoryPaymentMethod($options) + { + if (empty($options)) return null; + + $factory = new PaymentMethodFactory(); + + return $factory->factoryFromArray($options); + } +} diff --git a/lib/Request/Receipts/AbstractReceiptResponse.php b/lib/Request/Receipts/AbstractReceiptResponse.php new file mode 100644 index 00000000..c9b4b577 --- /dev/null +++ b/lib/Request/Receipts/AbstractReceiptResponse.php @@ -0,0 +1,576 @@ +setId($receiptData['id']); + $this->setType($receiptData['type']); + $this->setObjectId($this->factoryObjectId($receiptData)); + $this->setStatus($receiptData['status']); + + if (!empty($receiptData['tax_system_code'])) { + $this->setTaxSystemCode($receiptData['tax_system_code']); + } + if (!empty($receiptData['fiscal_document_number'])) { + $this->setFiscalDocumentNumber($receiptData['fiscal_document_number']); + } + if (!empty($receiptData['fiscal_storage_number'])) { + $this->setFiscalStorageNumber($receiptData['fiscal_storage_number']); + } + if (!empty($receiptData['fiscal_attribute'])) { + $this->setFiscalAttribute($receiptData['fiscal_attribute']); + } + if (!empty($receiptData['registered_at'])) { + $this->setRegisteredAt(new DateTime($receiptData['registered_at'])); + } + if (!empty($receiptData['fiscal_provider_id'])) { + $this->setFiscalProviderId($receiptData['fiscal_provider_id']); + } + if (!empty($receiptData['items'])) { + if (is_array($receiptData['items']) && count($receiptData['items'])) { + $itemsArray = array(); + foreach ($receiptData['items'] as $item) { + $itemsArray[] = new ReceiptResponseItem($item); + } + $this->setItems($itemsArray); + } else { + throw new EmptyPropertyValueException('Empty items value in receipt', 0, 'receipt.items'); + } + } else { + throw new EmptyPropertyValueException('Empty items value in receipt', 0, 'receipt.items'); + } + if (!empty($receiptData['settlements'])) { + if (is_array($receiptData['settlements']) && count($receiptData['settlements'])) { + $itemsArray = array(); + foreach ($receiptData['settlements'] as $item) { + $itemsArray[] = new Settlement($item); + } + $this->setSettlements($itemsArray); + } else { + throw new EmptyPropertyValueException('Empty settlements value in receipt', 0, 'receipt.settlements'); + } + } + if (!empty($receiptData['on_behalf_of'])) { + $this->setOnBehalfOf($receiptData['on_behalf_of']); + } + + $this->setSpecificProperties($receiptData); + } + + /** + * @return string + */ + public function getId() + { + return $this->_id; + } + + /** + * Устанавливает идентификатор чека + * @param string $value Идентификатор чека + * + * @throws InvalidPropertyValueException Выбрасывается если длина переданной строки не равна 40 + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setId($value) + { + if (TypeCast::canCastToString($value)) { + if (strlen((string)$value) !== self::LENGTH_RECEIPT_ID) { + throw new InvalidPropertyValueException('Invalid receipt id value', 0, 'Receipt.id', $value); + } + $this->_id = (string)$value; + } else { + throw new InvalidPropertyValueTypeException('Invalid receipt id value type', 0, 'Receipt.id', $value); + } + } + + /** + * @return string + */ + public function getType() + { + return $this->_type; + } + + /** + * Устанавливает типа чека + * @param string $value Тип чека + * + * @throws InvalidPropertyValueException Выбрасывается если переданная строка не является валидным типом + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setType($value) + { + if (TypeCast::canCastToEnumString($value)) { + if (!ReceiptType::valueExists((string)$value)) { + throw new InvalidPropertyValueException('Invalid receipt type value', 0, 'Receipt.type', $value); + } + $this->_type = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid receipt type value type', 0, 'Receipt.type', $value + ); + } + } + + /** + * Возвращает идентификатор платежа или возврата, для которого был сформирован чек. + * @return string + */ + public function getObjectId() + { + return $this->_object_id; + } + + /** + * Устанавливает идентификатор платежа или возврата, для которого был сформирован чек + * + * @param $value + */ + public function setObjectId($value) + { + if ($value === null || $value === '') { + $this->_object_id = null; + } elseif (TypeCast::canCastToString($value)) { + $this->_object_id = (string)$value; + } else { + throw new InvalidPropertyValueTypeException('Invalid receipt object_id type', 0, 'Receipt.object_id', $value); + } + } + + /** + * Фабричный метод создания идентификатора объекта, для которого был сформирован чек + * + * @param array $receiptData Массив данных чека + * @return string|null + */ + private function factoryObjectId($receiptData) + { + if (array_key_exists('refund_id', $receiptData)) { + return $receiptData['refund_id']; + } elseif (array_key_exists('payment_id', $receiptData)) { + return $receiptData['payment_id']; + } + return null; + } + + /** + * @return string + */ + public function getStatus() + { + return $this->_status; + } + + /** + * Устанавливает состояние регистрации фискального чека + * @param string $value Состояние регистрации фискального чека + * + * @return AbstractReceiptResponse + * + * @throws InvalidPropertyValueException Выбрасывается если переданное состояние регистрации не существует + * @throws InvalidPropertyValueTypeException Выбрасывается если переданный аргумент не строка + */ + public function setStatus($value) + { + if ($value === null || $value === '') { + $this->_status = null; + } elseif (TypeCast::canCastToEnumString($value)) { + if (ReceiptRegistrationStatus::valueExists($value)) { + $this->_status = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid status value', 0, 'Receipt.status', $value + ); + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid status value type', 0, 'Receipt.status', $value + ); + } + return $this; + } + + /** + * @return string + */ + public function getFiscalDocumentNumber() + { + return $this->_fiscalDocumentNumber; + } + + /** + * Устанавливает номер фискального документа + * @param string $value Номер фискального документа + * + * @throws InvalidPropertyValueTypeException Выбрасывается если переданный аргумент не строка + */ + public function setFiscalDocumentNumber($value) + { + if ($value === null || $value === '') { + $this->_fiscalDocumentNumber = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid fiscal_document_number value type', 0, 'Receipt.fiscalDocumentNumber', $value + ); + } else { + $this->_fiscalDocumentNumber = (string)$value; + } + } + + /** + * @return string + */ + public function getFiscalStorageNumber() + { + return $this->_fiscalStorageNumber; + } + + /** + * @param string $fiscal_storage_number + */ + public function setFiscalStorageNumber($fiscal_storage_number) + { + $this->_fiscalStorageNumber = $fiscal_storage_number; + } + + /** + * @return string + */ + public function getFiscalAttribute() + { + return $this->_fiscalAttribute; + } + + /** + * @param string $fiscal_attribute + */ + public function setFiscalAttribute($fiscal_attribute) + { + $this->_fiscalAttribute = $fiscal_attribute; + } + + /** + * @return DateTime + */ + public function getRegisteredAt() + { + return $this->_registeredAt; + } + + /** + * @param DateTime $registered_at + */ + public function setRegisteredAt($registered_at) + { + $this->_registeredAt = $registered_at; + } + + /** + * @return string + */ + public function getFiscalProviderId() + { + return $this->_fiscalProviderId; + } + + /** + * @param string $fiscal_provider_id + */ + public function setFiscalProviderId($fiscal_provider_id) + { + $this->_fiscalProviderId = $fiscal_provider_id; + } + + /** + * @return ReceiptResponseItem[] + */ + public function getItems() + { + return $this->_items; + } + + /** + * Устанавливает список позиций в чеке + * + * Если до этого в чеке уже были установлены значения, они удаляются и полностью заменяются переданным списком + * позиций. Все передаваемые значения в массиве позиций должны быть объектами класса, реализующего интерфейс + * ReceiptItemInterface, в противном случае будет выброшено исключение InvalidPropertyValueTypeException. + * + * @param ReceiptResponseItemInterface[] $value Список товаров в заказе + * + * @throws EmptyPropertyValueException Выбрасывается если передали пустой массив значений + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве значения был передан не массив и не + * итератор, лабо если одно из переданных значений не реализует интерфейс ReceiptItemInterface + */ + public function setItems($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty items value in receipt', 0, 'receipt.items'); + } + if (!is_array($value) && !($value instanceof \Traversable)) { + throw new InvalidPropertyValueTypeException( + 'Invalid items value type in receipt', 0, 'receipt.items', $value + ); + } + $this->_items = array(); + foreach ($value as $key => $val) { + if (is_object($val) && $val instanceof ReceiptResponseItemInterface) { + $this->addItem($val); + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid item value type in receipt', 0, 'receipt.items[' . $key . ']', $val + ); + } + } + } + + /** + * Добавляет товар в чек + * + * @param ReceiptResponseItemInterface $value Объект добавляемой в чек позиции + */ + public function addItem($value) + { + $this->_items[] = $value; + } + + /** + * Возвращает Массив оплат, обеспечивающих выдачу товара + * + * @return SettlementInterface[] + */ + public function getSettlements() + { + return $this->_settlements; + } + + /** + * @param SettlementInterface[] $value + */ + public function setSettlements($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty settlements value in receipt', 0, 'receipt.settlements'); + } + if (!is_array($value) && !($value instanceof \Traversable)) { + throw new InvalidPropertyValueTypeException( + 'Invalid settlements value type in receipt', 0, 'receipt.settlements', $value + ); + } + $this->_settlements = array(); + foreach ($value as $key => $val) { + if (is_object($val) && $val instanceof SettlementInterface) { + $this->addSettlement($val); + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid settlement value type in receipt', 0, 'receipt.settlements['.$key.']', $val + ); + } + } + } + + /** + * @param SettlementInterface $value + */ + public function addSettlement(SettlementInterface $value) + { + $this->_settlements[] = $value; + } + + + /** + * @return int + */ + public function getTaxSystemCode() + { + return $this->_taxSystemCode; + } + + /** + * Устанавливает код системы налогообложения + * + * @param int $value Код системы налогообложения. Число 1-6 + * + * @throws InvalidPropertyValueTypeException Выбрасывается если переданный аргумент - не число + * @throws InvalidPropertyValueException Выбрасывается если переданный аргумент меньше одного или больше шести + */ + public function setTaxSystemCode($value) + { + if ($value === null || $value === '') { + $this->_taxSystemCode = null; + } elseif (!is_numeric($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid tax_system_code value type', 0, 'receipt.taxSystemCode' + ); + } else { + $castedValue = (int)$value; + if ($castedValue < 1 || $castedValue > 6) { + throw new InvalidPropertyValueException( + 'Invalid tax_system_code value: ' . $value, 0, 'receipt.taxSystemCode' + ); + } + $this->_taxSystemCode = $castedValue; + } + } + + /** + * @return string|null + */ + public function getOnBehalfOf() + { + return $this->_onBehalfOf; + } + + /** + * @param string $value + */ + public function setOnBehalfOf($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty onBehalfOf value', 0, 'Receipt.onBehalfOf' + ); + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid onBehalfOf value type', 0, 'Receipt.onBehalfOf', $value + ); + } else { + $this->_onBehalfOf = (string)$value; + } + } + + /** + * Проверяет есть ли в чеке хотя бы одна позиция + * + * @return bool True если чек не пуст, false если в чеке нет ни одной позиции + */ + public function notEmpty() + { + return !empty($this->_items); + } + + /** + * Установка свойств, присущих конкретному объекту + * + * @param array $receiptData + * + * @return void + */ + abstract public function setSpecificProperties($receiptData); +} \ No newline at end of file diff --git a/lib/Request/Receipts/CreatePostReceiptRequest.php b/lib/Request/Receipts/CreatePostReceiptRequest.php new file mode 100644 index 00000000..1317bfa4 --- /dev/null +++ b/lib/Request/Receipts/CreatePostReceiptRequest.php @@ -0,0 +1,434 @@ +_object_id; + } + + /** + * Устанавливает Id объекта чека + * + * @param string $value + */ + public function setObjectId($value) + { + $this->_object_id = $value; + } + + /** + * @return bool + */ + public function hasCustomer() + { + return !empty($this->_customer); + } + + /** + * Возвращает информацию о плательщике + * + * @return ReceiptCustomerInterface информация о плательщике + */ + public function getCustomer() + { + return $this->_customer; + } + + /** + * Устанавливает информацию о плательщике + * + * @param ReceiptCustomerInterface $value + */ + public function setCustomer($value) + { + if (is_array($value)) { + $this->_customer = new ReceiptCustomer($value); + } elseif (is_object($value) && $value instanceof ReceiptCustomerInterface) { + $this->_customer = $value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid customer value type in receipt', 0, 'Receipt.customer', $value + ); + } + } + + /** + * Возвращает список позиций в текущем чеке + * + * @return ReceiptItemInterface[] Список товаров в заказе + */ + public function getItems() + { + return $this->_items; + } + + /** + * Устанавливает список позиций в чеке + * + * Если до этого в чеке уже были установлены значения, они удаляются и полностью заменяются переданным списком + * позиций. Все передаваемые значения в массиве позиций должны быть объектами класса, реализующего интерфейс + * ReceiptItemInterface, в противном случае будет выброшено исключение InvalidPropertyValueTypeException. + * + * @param ReceiptItemInterface[] $value Список товаров в заказе + * + * @throws EmptyPropertyValueException Выбрасывается если передали пустой массив значений + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве значения был передан не массив и не + * итератор, либо если одно из переданных значений не реализует интерфейс ReceiptItemInterface + */ + public function setItems($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty items value in receipt', 0, 'Receipt.items'); + } + if (!is_array($value) && !($value instanceof \Traversable)) { + throw new InvalidPropertyValueTypeException( + 'Invalid items value type in receipt', 0, 'Receipt.items', $value + ); + } + $this->_items = array(); + foreach ($value as $key => $val) { + if (is_array($val)) { + $this->addItem(new ReceiptItem($val)); + } elseif (is_object($val) && $val instanceof ReceiptItemInterface) { + $this->addItem($val); + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid item value type in receipt', 0, 'Receipt.items['.$key.']', $val + ); + } + } + } + + /** + * Добавляет товар в чек + * + * @param ReceiptItemInterface $value Объект добавляемой в чек позиции + */ + public function addItem($value) + { + $this->_items[] = $value; + } + + /** + * Возвращает код системы налогообложения + * + * @return int Код системы налогообложения. Число 1-6. + */ + public function getTaxSystemCode() + { + return $this->_taxSystemCode; + } + + /** + * Устанавливает код системы налогообложения + * + * @param int $value Код системы налогообложения. Число 1-6 + * + * @throws InvalidPropertyValueTypeException Выбрасывается если переданный аргумент - не число + * @throws InvalidPropertyValueException Выбрасывается если переданный аргумент меньше одного или больше шести + */ + public function setTaxSystemCode($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty taxSystemCode value in receipt', 0, 'Receipt.taxSystemCode'); + } elseif (!is_numeric($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid taxSystemCode value type', 0, 'Receipt.taxSystemCode' + ); + } else { + $castedValue = (int)$value; + if ($castedValue < 1 || $castedValue > 6) { + throw new InvalidPropertyValueException( + 'Invalid taxSystemCode value: '.$value, 0, 'Receipt.taxSystemCode' + ); + } + $this->_taxSystemCode = $castedValue; + } + } + + /** + * Возвращает тип чека в онлайн-кассе + * + * @return string Тип чека в онлайн-кассе: приход "payment" или возврат "refund". + */ + public function getType() + { + return $this->_type; + } + + /** + * Устанавливает тип чека в онлайн-кассе + * + * @param string $value Тип чека в онлайн-кассе: приход "payment" или возврат "refund". + */ + public function setType($value) + { + if (TypeCast::canCastToEnumString($value)) { + if (!ReceiptType::valueExists((string)$value)) { + throw new InvalidPropertyValueException('Invalid receipt type value', 0, 'Receipt.type', $value); + } + $this->_type = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid receipt type value type', 0, 'Receipt.type', $value + ); + } + } + + /** + * Возвращает признак отложенной отправки чека. + * + * @return bool Признак отложенной отправки чека. + */ + public function getSend() + { + return $this->_send; + } + + /** + * Устанавливает признак отложенной отправки чека. + * @param bool $value Признак отложенной отправки чека. + */ + public function setSend($value) + { + if (TypeCast::canCastToBoolean($value)) { + $this->_send = (bool)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid receipt type value send', 0, 'Receipt.send', $value + ); + } + } + + /** + * Возвращает массив оплат, обеспечивающих выдачу товара. + * + * @return SettlementInterface[] Массив оплат, обеспечивающих выдачу товара. + */ + public function getSettlements() + { + return $this->_settlements; + } + + /** + * Устанавливает массив оплат, обеспечивающих выдачу товара. + * + * @param SettlementInterface[] $value Массив оплат, обеспечивающих выдачу товара. + */ + public function setSettlements($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty settlements value in receipt', 0, 'Receipt.settlements'); + } + if (!is_array($value) && !($value instanceof \Traversable)) { + throw new InvalidPropertyValueTypeException( + 'Invalid settlements value type in receipt', 0, 'Receipt.settlements', $value + ); + } + $this->_settlements = array(); + foreach ($value as $key => $val) { + if (is_array($val) && !empty($val['type']) && !empty($val['amount'])) { + $this->addSettlement(new Settlement($val)); + } elseif (is_object($val) && $val instanceof SettlementInterface) { + $this->addSettlement($val); + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid settlement value type in receipt', 0, 'Receipt.settlements['.$key.']', $val + ); + } + } + } + + /** + * Добавляет оплату в перечень совершенных расчетов. + * + * @param SettlementInterface $value Информация о совершенных расчетах. + */ + public function addSettlement(SettlementInterface $value) + { + $this->_settlements[] = $value; + } + + /** + * @return string + */ + public function getOnBehalfOf() + { + return $this->_onBehalfOf; + } + + /** + * @param string $value + */ + public function setOnBehalfOf($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty onBehalfOf value', 0, 'Receipt.onBehalfOf' + ); + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid onBehalfOf value type', 0, 'Receipt.onBehalfOf', $value + ); + } else { + $this->_onBehalfOf = (string)$value; + } + } + + /** + * Проверяет есть ли в чеке хотя бы одна позиция товаров и оплат + * + * @return bool True если чек не пуст, false если в чеке нет ни одной позиции + */ + public function notEmpty() + { + return !empty($this->_items) && !empty($this->_settlements); + } + + /** + * Устанавливает значения свойств текущего объекта из массива + * @param array|\Traversable $sourceArray Ассоциативный массив с настройками + */ + public function fromArray($sourceArray) + { + if (!empty($sourceArray['customer'])) { + $sourceArray['customer'] = new ReceiptCustomer($sourceArray['customer']); + } + + if (!empty($sourceArray['items'])) { + foreach ($sourceArray['items'] as $i => $itemArray) { + if (is_array($itemArray)) { + $sourceArray['items'][$i] = new ReceiptItem($itemArray); + } + } + } + + if (!empty($sourceArray['settlements'])) { + foreach ($sourceArray['settlements'] as $i => $itemArray) { + if (is_array($itemArray)) { + $sourceArray['settlements'][$i] = new Settlement($itemArray); + } + } + } + + parent::fromArray($sourceArray); + } + + /** + * Валидирует текущий запрос, проверяет все ли нужные свойства установлены + * @return bool True если запрос валиден, false если нет + */ + public function validate() + { + if (empty($this->_customer)) { + $this->setValidationError('Receipt customer not specified'); + return false; + } + + if (empty($this->_type) || !ReceiptType::valueExists($this->_type)) { + $this->setValidationError('Receipt type not specified'); + return false; + } + + if (empty($this->_send)) { // todo: пока может быть только true + $this->setValidationError('Receipt send not specified'); + return false; + } + + if (empty($this->_settlements)) { + $this->setValidationError('Receipt settlements not specified'); + return false; + } + + if (empty($this->_items)) { + $this->setValidationError('Receipt items not specified'); + return false; + } + + return true; + } + +} \ No newline at end of file diff --git a/lib/Request/Receipts/CreatePostReceiptRequestBuilder.php b/lib/Request/Receipts/CreatePostReceiptRequestBuilder.php new file mode 100644 index 00000000..29e511a5 --- /dev/null +++ b/lib/Request/Receipts/CreatePostReceiptRequestBuilder.php @@ -0,0 +1,209 @@ +customer = new ReceiptCustomer(); + $this->amount = new MonetaryAmount(); + + return new CreatePostReceiptRequest(); + } + + /** + * Устанавливает сумму + * + * @param AmountInterface|array|string $value Сумма оплаты + * + * @return self Инстанс билдера запросов + */ + public function setAmount($value) + { + if (is_object($value) && $value instanceof AmountInterface) { + $this->amount->setValue($value->getValue()); + $this->amount->setCurrency($value->getCurrency()); + } elseif (is_array($value)) { + $this->amount->fromArray($value); + } else { + $this->amount->setValue($value); + } + + return $this; + } + + /** + * Устанавливает валюту в которой будет происходить подтверждение оплаты заказа + * + * @param string $value Валюта в которой подтверждается оплата + * + * @return self Инстанс билдера запросов + */ + public function setCurrency($value) + { + $this->amount->setCurrency($value); + foreach ($this->currentObject->getItems() as $item) { + $item->getPrice()->setCurrency($value); + } + + return $this; + } + + /** + * @param ReceiptCustomerInterface|array $value + * @return CreatePostReceiptRequestBuilder + */ + public function setCustomer($value) + { + if (is_array($value)) { + $this->customer->fromArray($value); + } elseif ($value instanceof ReceiptCustomerInterface) { + $this->customer = $value; + } else { + $this->customer = null; + } + $this->currentObject->setCustomer($this->customer); + return $this; + } + + /** + * @param ReceiptItemInterface[] $value + * @return CreatePostReceiptRequestBuilder + */ + public function setItems($value) + { + $this->currentObject->setItems($value); + return $this; + } + + /** + * @param int $value + * @return CreatePostReceiptRequestBuilder + */ + public function setTaxSystemCode($value) + { + $this->currentObject->setTaxSystemCode($value); + return $this; + } + + /** + * @param string $value + * @return CreatePostReceiptRequestBuilder + */ + public function setType($value) + { + $this->currentObject->setType($value); + return $this; + } + + /** + * @param bool $value + * @return CreatePostReceiptRequestBuilder + */ + public function setSend($value) + { + $this->currentObject->setSend($value); + return $this; + } + + /** + * @param string $value + * @return CreatePostReceiptRequestBuilder + */ + public function setOnBehalfOf($value) + { + $this->currentObject->setOnBehalfOf($value); + return $this; + } + + /** + * @param SettlementInterface[] $value + * @return CreatePostReceiptRequestBuilder + */ + public function setSettlements($value) + { + $this->currentObject->setSettlements($value); + return $this; + } + + /** + * @param string $value + * @return CreatePostReceiptRequestBuilder + */ + public function setObjectId($value) + { + $this->currentObject->setObjectId($value); + return $this; + } + + /** + * Строит и возвращает объект запроса для отправки в API яндекс денег + * @param array|null $options Массив параметров для установки в объект запроса + * @return CreatePostReceiptRequest Инстанс объекта запроса + * + * @throws InvalidRequestException Выбрасывается если собрать объект запроса не удалось + */ + public function build(array $options = null) + { + if (!empty($options)) { + $this->setOptions($options); + + if (!empty($options['payment_id'])) { + $this->setObjectId($options['payment_id']); + } elseif (!empty($options['refund_id'])) { + $this->setObjectId($options['refund_id']); + } + } + + return parent::build($options); + } + +} \ No newline at end of file diff --git a/lib/Request/Receipts/CreatePostReceiptRequestInterface.php b/lib/Request/Receipts/CreatePostReceiptRequestInterface.php new file mode 100644 index 00000000..a8980a5d --- /dev/null +++ b/lib/Request/Receipts/CreatePostReceiptRequestInterface.php @@ -0,0 +1,166 @@ + $request->getType(), + 'send' => $request->getSend(), + ), $this->serializeObjectId($request)); + + /** @var Settlement $item */ + foreach ($request->getSettlements() as $item) { + $result['settlements'][] = $item->jsonSerialize(); + } + + /** @var ReceiptItem $item */ + foreach ($request->getItems() as $item) { + $result['items'][] = $item->jsonSerialize(); + } + + $customer = $request->getCustomer(); + if (!empty($customer)) { + $result['customer'] = $customer->jsonSerialize(); + } + + $value = $request->getTaxSystemCode(); + if (!empty($value)) { + $result['tax_system_code'] = $value; + } + + $onBehalfOf = $request->getOnBehalfOf(); + if (!empty($onBehalfOf)) { + $result['on_behalf_of'] = $onBehalfOf; + } + + return $result; + } + + /** + * @param CreatePostReceiptRequestInterface $request + * @return array + */ + private function serializeObjectId(CreatePostReceiptRequestInterface $request) + { + $result = array(); + + if ($request->getType() === ReceiptType::PAYMENT) { + $result['payment_id'] = $request->getObjectId(); + } elseif ($request->getType() === ReceiptType::REFUND) { + $result['refund_id'] = $request->getObjectId(); + } + + return $result; + } +} \ No newline at end of file diff --git a/lib/Request/Receipts/PaymentReceiptResponse.php b/lib/Request/Receipts/PaymentReceiptResponse.php new file mode 100644 index 00000000..efe1e1d8 --- /dev/null +++ b/lib/Request/Receipts/PaymentReceiptResponse.php @@ -0,0 +1,89 @@ +setPaymentId($this->getObjectId()); + } + + /** + * @return string + */ + public function getPaymentId() + { + return $this->_payment_id; + } + + /** + * Устанавливает идентификатор платежа в ЮKassa + * + * @param string $value Идентификатор платежа в ЮKassa + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве значения была передана не строка + * @throws InvalidPropertyValueException Выбрасывается если длина переданной строки не равна 36 + */ + public function setPaymentId($value) + { + if ($value === null || $value === '') { + $this->_payment_id = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException('Invalid payment_id value type', 0, 'Receipt.paymentId'); + } elseif (strlen((string)$value) !== self::LENGTH_PAYMENT_ID) { + throw new InvalidPropertyValueException( + 'Invalid payment_id value: "'.$value.'"', 0, 'Receipt.paymentId', $value + ); + } else { + $this->_payment_id = (string)$value; + } + } + +} \ No newline at end of file diff --git a/lib/Request/Receipts/ReceiptResponseFactory.php b/lib/Request/Receipts/ReceiptResponseFactory.php new file mode 100644 index 00000000..5e53f19e --- /dev/null +++ b/lib/Request/Receipts/ReceiptResponseFactory.php @@ -0,0 +1,74 @@ + 'PaymentReceiptResponse', + ReceiptType::REFUND => 'RefundReceiptResponse', + ReceiptType::SIMPLE => 'SimpleReceiptResponse', + ); + + /** + * @param array $data + * + * @return AbstractReceiptResponse + */ + public function factory($data) + { + if (array_key_exists('type', $data)) { + if (array_key_exists('refund_id', $data)) { + $type = ReceiptType::REFUND; + } elseif (array_key_exists('payment_id', $data)) { + $type = ReceiptType::PAYMENT; + } else { + $type = ReceiptType::SIMPLE; + } + } else { + throw new \InvalidArgumentException( + 'Parameter type not specified in ReceiptResponseFactory.factory()' + ); + } + if (!is_string($type)) { + throw new \InvalidArgumentException('Invalid receipt type value in receipt factory'); + } + if (!in_array($type, ReceiptType::getValidValues())) { + throw new \InvalidArgumentException('Invalid receipt data type "' . $type . '"'); + } + $className = __NAMESPACE__ . '\\' . $this->typeClassMap[$type]; + + return new $className($data); + } +} diff --git a/lib/Request/Receipts/ReceiptResponseInterface.php b/lib/Request/Receipts/ReceiptResponseInterface.php new file mode 100644 index 00000000..0eaec09c --- /dev/null +++ b/lib/Request/Receipts/ReceiptResponseInterface.php @@ -0,0 +1,102 @@ +setDescription($itemData['description']); + $this->setQuantity($itemData['quantity']); + $this->setPrice($this->factoryAmount($itemData['amount'])); + $this->setVatCode($itemData['vat_code']); + + if (!empty($itemData['payment_mode'])) { + $this->setPaymentMode($itemData['payment_mode']); + } + + if (!empty($itemData['payment_subject'])) { + $this->setPaymentSubject($itemData['payment_subject']); + } + + if (!empty($itemData['supplier'])) { + $this->setSupplier($itemData['supplier']); + } + } + + /** + * Возвращает наименование товара + * @return string Наименование товара + */ + public function getDescription() + { + return $this->_description; + } + + /** + * Устанавливает наименование товара + * + * @param string $value Наименование товара + * + * @throws EmptyPropertyValueException Выбрасывается если было передано пустое значение + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве аргумента была передана не строка + */ + public function setDescription($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty description value in ReceiptItem', 0, 'ReceiptItem.description' + ); + } elseif (TypeCast::canCastToString($value)) { + $castedValue = (string)$value; + if ($castedValue === '') { + throw new EmptyPropertyValueException( + 'Empty description value in ReceiptItem', 0, 'ReceiptItem.description' + ); + } + $this->_description = $castedValue; + } else { + throw new InvalidPropertyValueTypeException( + 'Empty description value in ReceiptItem', 0, 'ReceiptItem.description', $value + ); + } + } + + /** + * Возвращает количество товара + * @return float Количество купленного товара + */ + public function getQuantity() + { + return $this->_quantity; + } + + /** + * Устанавливает количество покупаемого товара + * + * @param int $value Количество + * + * @throws EmptyPropertyValueException Выбрасывается если было передано пустое значение + * @throws InvalidPropertyValueException Выбрасывается если в качестве аргумента был передан ноль + * или отрицательное число + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве аргумента было передано не число + */ + public function setQuantity($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException('Empty quantity value in ReceiptItem', 0, 'ReceiptItem.quantity'); + } elseif (!is_numeric($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid quantity value type in ReceiptItem', 0, 'ReceiptItem.quantity', $value + ); + } elseif ($value <= 0.0) { + throw new InvalidPropertyValueException( + 'Invalid quantity value in ReceiptItem', 0, 'ReceiptItem.quantity', $value + ); + } else { + $this->_quantity = (float)$value; + } + } + + /** + * Возвращает общую стоимость покупаемого товара в копейках/центах + * @return int Сумма стоимости покупаемого товара + */ + public function getAmount() + { + return (int)round($this->_amount->getIntegerValue() * $this->_quantity); + } + + /** + * Возвращает цену товара + * @return AmountInterface Цена товара + */ + public function getPrice() + { + return $this->_amount; + } + + /** + * Устанавливает цену товара + * + * @param AmountInterface $value Цена товара + */ + public function setPrice(AmountInterface $value) + { + $this->_amount = $value; + } + + /** + * Возвращает ставку НДС + * @return int|null Ставка НДС, число 1-6, или null если ставка не задана + */ + public function getVatCode() + { + return $this->_vatCode; + } + + /** + * Устанавливает ставку НДС + * + * @param int $value Ставка НДС, число 1-6 + * + * @throws InvalidPropertyValueException Выбрасывается если в качестве аргумента было передано число меньше одного + * или больше шести + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве аргумента было передано не число + */ + public function setVatCode($value) + { + if ($value === null || $value === '') { + $this->_vatCode = null; + } elseif (!is_numeric($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid vatId value type in ReceiptItem', 0, 'ReceiptItem.vatId', $value + ); + } elseif ($value < 1 || $value > 6) { + throw new InvalidPropertyValueException( + 'Invalid vatId value in ReceiptItem', 0, 'ReceiptItem.vatId', $value + ); + } else { + $this->_vatCode = (int)$value; + } + } + + /** + * Возвращает признак предмета расчета + * @return string|null Признак предмета расчета + */ + public function getPaymentSubject() + { + return $this->_paymentSubject; + } + + /** + * Устанавливает признак предмета расчета + * + * @param string $value Признак предмета расчета + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве аргумента была передана не строка + */ + public function setPaymentSubject($value) + { + if ($value === null || $value === '') { + $this->_paymentSubject = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException('Invalid paymentSubject value type', 0, 'ReceiptItem.paymentSubject'); + } else { + $this->_paymentSubject = $value; + } + } + + /** + * Возвращает признак способа расчета + * @return string|null Признак способа расчета + */ + public function getPaymentMode() + { + return $this->_paymentMode; + } + + /** + * Устанавливает признак способа расчета + * + * @param string $value Признак способа расчета + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве аргумента была передана не строка + */ + public function setPaymentMode($value) + { + if ($value === null || $value === '') { + $this->_paymentMode = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException( + 'Invalid paymentMode value type', 0, 'ReceiptItem.paymentMode', $value + ); + } else { + $this->_paymentMode = $value; + } + } + + /** + * @return SupplierInterface + */ + public function getSupplier() + { + return $this->_supplier; + } + + /** + * Устанавливает информацию о поставщике товара или услуги. + * + * @param SupplierInterface|array $value + */ + public function setSupplier($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty supplier value in receipt', 0, 'Receipt.supplier' + ); + } + + if (is_array($value)) { + $value = new Supplier($value); + } + + if (!($value instanceof SupplierInterface)) { + throw new InvalidPropertyValueTypeException( + 'Invalid supplier value type in receipt', 0, 'Receipt.supplier', $value + ); + } + + $this->_supplier = $value; + } + + /** + * Фабричный метод создания суммы + * + * @param array $options Сумма в виде ассоциативного массива + * + * @return AmountInterface Созданный инстанс суммы + */ + private function factoryAmount($options) + { + $amount = new MonetaryAmount(null, $options['currency']); + if ($options['value'] > 0) { + $amount->setValue($options['value']); + } + + return $amount; + } + + /** + * @return array + */ + public function jsonSerialize() + { + $result = array( + 'description' => $this->getDescription(), + 'amount' => array( + 'value' => $this->getPrice()->getValue(), + 'currency' => $this->getPrice()->getCurrency(), + ), + 'quantity' => $this->getQuantity(), + 'vat_code' => $this->getVatCode(), + ); + + if ($this->getPaymentSubject()) { + $result['payment_subject'] = $this->getPaymentSubject(); + } + + if ($this->getPaymentMode()) { + $result['payment_mode'] = $this->getPaymentMode(); + } + + return $result; + } +} \ No newline at end of file diff --git a/lib/Request/Receipts/ReceiptResponseItemInterface.php b/lib/Request/Receipts/ReceiptResponseItemInterface.php new file mode 100644 index 00000000..d53572db --- /dev/null +++ b/lib/Request/Receipts/ReceiptResponseItemInterface.php @@ -0,0 +1,82 @@ +_refundId; + } + + /** + * Проверяет был ли установлен идентификатор возврата + * @return bool True если идентификатор возврата был установлен, false если не был + */ + public function hasRefundId() + { + return !empty($this->_refundId); + } + + /** + * Устанавливает идентификатор возврата + * @param string $value Идентификатор возврата, который ищется в API + */ + public function setRefundId($value) + { + if ($value === null || $value === '') { + $this->_refundId = null; + } elseif (TypeCast::canCastToString($value)) { + $length = mb_strlen((string)$value, 'utf-8'); + if ($length != 36) { + throw new InvalidPropertyValueException( + 'Invalid payment id value in ReceiptsRequest', 0, 'ReceiptsRequest.refundId', $value + ); + } + $this->_refundId = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid payment id value type in ReceiptsRequest', 0, 'ReceiptsRequest.refundId', $value + ); + } + } + + /** + * Возвращает идентификатор платежа если он задан или null + * @return string|null Идентификатор платежа + */ + public function getPaymentId() + { + return $this->_paymentId; + } + + /** + * Проверяет, был ли задан идентификатор платежа + * @return bool True если идентификатор был задан, false если нет + */ + public function hasPaymentId() + { + return !empty($this->_paymentId); + } + + /** + * Устанавливает идентификатор платежа или null если требуется его удалить + * @param string|null $value Идентификатор платежа + * + * @throws InvalidPropertyValueException Выбрасывается если длина переданной строки не равна 36 символам + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setPaymentId($value) + { + if ($value === null || $value === '') { + $this->_paymentId = null; + } elseif (TypeCast::canCastToString($value)) { + $length = mb_strlen((string)$value, 'utf-8'); + if ($length != 36) { + throw new InvalidPropertyValueException( + 'Invalid payment id value in ReceiptsRequest', 0, 'ReceiptsRequest.paymentId', $value + ); + } + $this->_paymentId = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid payment id value type in ReceiptsRequest', 0, 'ReceiptsRequest.paymentId', $value + ); + } + } + + /** + * Возвращает дату создания от которой будут возвращены возвраты или null если дата не была установлена + * @return \DateTime|null Время создания, от (включительно) + */ + public function getCreatedAtGte() + { + return $this->_createdAtGte; + } + + /** + * Проверяет была ли установлена дата создания от которой выбираются возвраты + * @return bool True если дата была установлена, false если нет + */ + public function hasCreatedAtGte() + { + return !empty($this->_createdAtGte); + } + + /** + * Устанавливает дату создания от которой выбираются возвраты + * @param \DateTime|string|int|null $value Время создания, от (включительно) или null чтобы удалить значение + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtGte($value) + { + if ($value === null || $value === '') { + $this->_createdAtGte = null; + } elseif (TypeCast::canCastToDateTime($value)) { + $dateTime = TypeCast::castToDateTime($value); + if ($dateTime === null) { + throw new InvalidPropertyValueException( + 'Invalid created_gte value in ReceiptsRequest', 0, 'ReceiptsRequest.createdAtGte' + ); + } + $this->_createdAtGte = $dateTime; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid created_gte value type in ReceiptsRequest', 0, 'ReceiptsRequest.createdAtGte' + ); + } + } + + /** + * Возвращает дату создания от которой будут возвращены возвраты или null если дата не была установлена + * @return \DateTime|null Время создания, от (не включая) + */ + public function getCreatedAtGt() + { + return $this->_createdAtGt; + } + + /** + * Проверяет была ли установлена дата создания от которой выбираются возвраты + * @return bool True если дата была установлена, false если нет + */ + public function hasCreatedAtGt() + { + return !empty($this->_createdAtGt); + } + + /** + * Устанавливает дату создания от которой выбираются возвраты + * @param \DateTime|string|int|null $value Время создания, от (не включая) или null чтобы удалить значение + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtGt($value) + { + if ($value === null || $value === '') { + $this->_createdAtGt = null; + } elseif (TypeCast::canCastToDateTime($value)) { + $dateTime = TypeCast::castToDateTime($value); + if ($dateTime === null) { + throw new InvalidPropertyValueException( + 'Invalid created_gt value in ReceiptsRequest', 0, 'ReceiptsRequest.createdAtGt' + ); + } + $this->_createdAtGt = $dateTime; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid created_gt value type in ReceiptsRequest', 0, 'ReceiptsRequest.createdAtGt' + ); + } + } + + /** + * Возвращает дату создания до которой будут возвращены возвраты или null если дата не была установлена + * @return \DateTime|null Время создания, до (включительно) + */ + public function getCreatedAtLte() + { + return $this->_createdAtLte; + } + + /** + * Проверяет была ли установлена дата создания до которой выбираются возвраты + * @return bool True если дата была установлена, false если нет + */ + public function hasCreatedAtLte() + { + return !empty($this->_createdAtLte); + } + + /** + * Устанавливает дату создания до которой выбираются возвраты + * @param \DateTime|string|int|null $value Время создания, до (включительно) или null чтобы удалить значение + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtLte($value) + { + if ($value === null || $value === '') { + $this->_createdAtLte = null; + } elseif (TypeCast::canCastToDateTime($value)) { + $dateTime = TypeCast::castToDateTime($value); + if ($dateTime === null) { + throw new InvalidPropertyValueException( + 'Invalid created_lte value in ReceiptsRequest', 0, 'ReceiptsRequest.createdLte' + ); + } + $this->_createdAtLte = $dateTime; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid created_lte value type in ReceiptsRequest', 0, 'ReceiptsRequest.createdLte' + ); + } + } + + /** + * Возвращает дату создания до которой будут возвращены возвраты или null если дата не была установлена + * @return \DateTime|null Время создания, до (не включая) + */ + public function getCreatedAtLt() + { + return $this->_createdAtLt; + } + + /** + * Проверяет была ли установлена дата создания до которой выбираются возвраты + * @return bool True если дата была установлена, false если нет + */ + public function hasCreatedAtLt() + { + return !empty($this->_createdAtLt); + } + + /** + * Устанавливает дату создания до которой выбираются возвраты + * @param \DateTime|string|int|null $value Время создания, до (не включая) или null чтобы удалить значение + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtLt($value) + { + if ($value === null || $value === '') { + $this->_createdAtLt = null; + } elseif (TypeCast::canCastToDateTime($value)) { + $dateTime = TypeCast::castToDateTime($value); + if ($dateTime === null) { + throw new InvalidPropertyValueException( + 'Invalid created_lt value in ReceiptsRequest', 0, 'ReceiptsRequest.createdLt' + ); + } + $this->_createdAtLt = $dateTime; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid created_lt value type in ReceiptsRequest', 0, 'ReceiptsRequest.createdLt' + ); + } + } + + /** + * Возвращает статус выбираемых возвратов или null если он до этого не был установлен + * @return string|null Статус выбираемых возвратов + */ + public function getStatus() + { + return $this->_status; + } + + /** + * Проверяет был ли установлен статус выбираемых возвратов + * @return bool True если статус был установлен, false если нет + */ + public function hasStatus() + { + return !empty($this->_status); + } + + /** + * Устанавливает статус выбираемых возвратов + * @param string $value Статус выбираемых платежей или null чтобы удалить значение + * + * @throws InvalidPropertyValueException Выбрасывается если переданное значение не является валидным статусом + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setStatus($value) + { + if ($value === null || $value === '') { + $this->_status = null; + } elseif (TypeCast::canCastToEnumString($value)) { + if (!RefundStatus::valueExists((string)$value)) { + throw new InvalidPropertyValueException( + 'Invalid status value in ReceiptsRequest', 0, 'ReceiptsRequest.status', $value + ); + } else { + $this->_status = (string)$value; + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid status value type in ReceiptsRequest', 0, 'ReceiptsRequest.status', $value + ); + } + } + + /** + * Возвращает токен для получения следующей страницы выборки + * @return string|null Токен для получения следующей страницы выборки + */ + public function getCursor() + { + return $this->_cursor; + } + + /** + * Проверяет был ли установлен токен следующей страницы + * @return bool True если токен был установлен, false если нет + */ + public function hasCursor() + { + return !empty($this->_cursor); + } + + /** + * Устанавливает токен следующей страницы выборки + * @param string $value Токен следующей страницы выборки или null чтобы удалить значение + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setCursor($value) + { + if ($value === null || $value === '') { + $this->_cursor = null; + } elseif (TypeCast::canCastToString($value)) { + $this->_cursor = (string) $value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid status value type in ReceiptsRequest', 0, 'ReceiptsRequest.cursor', $value + ); + } + } + + /** + * Ограничение количества объектов платежа + * @return integer|null Ограничение количества объектов платежа + */ + public function getLimit() + { + return $this->_limit; + } + + /** + * Проверяет был ли установлено ограничение количества объектов платежа + * @return bool True если было установлено, false если нет + */ + public function hasLimit() + { + return $this->_limit !== null; + } + + /** + * Устанавливает ограничение количества объектов платежа + * @param integer|null $value Ограничение количества объектов платежа или null чтобы удалить значение + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передано не целое число + */ + public function setLimit($value) + { + if ($value === null || $value === '') { + $this->_limit = null; + } elseif (is_int($value)) { + if ($value < 0 || $value > self::MAX_LIMIT_VALUE) { + throw new InvalidPropertyValueException( + 'Invalid limit value in ReceiptsRequest', 0, 'ReceiptsRequest.limit', $value + ); + } + $this->_limit = $value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid limit value type in ReceiptsRequest', 0, 'ReceiptsRequest.limit', $value + ); + } + } + + /** + * Проверяет валидность текущего объекта запроса + * @return bool True если объект валиден, false если нет + */ + public function validate() + { + return true; + } + + /** + * Возвращает инстанс билдера объектов запросов списка возвратов магазина + * @return ReceiptsRequestBuilder Билдер объектов запросов списка возвратов + */ + public static function builder() + { + return new ReceiptsRequestBuilder(); + } +} diff --git a/lib/Request/Receipts/ReceiptsRequestBuilder.php b/lib/Request/Receipts/ReceiptsRequestBuilder.php new file mode 100644 index 00000000..ad047332 --- /dev/null +++ b/lib/Request/Receipts/ReceiptsRequestBuilder.php @@ -0,0 +1,195 @@ +currentObject->setRefundId($value); + return $this; + } + + /** + * Устанавливает идентификатор платежа или null если требуется его удалить + * @param string|null $value Идентификатор платежа + * @return ReceiptsRequestBuilder Инстанс текущего объекта билдера + * + * @throws InvalidPropertyValueException Выбрасывается если длина переданной строки не равна 36 символам + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setPaymentId($value) + { + $this->currentObject->setPaymentId($value); + return $this; + } + + /** + * Устанавливает статус выбираемых чеков + * @param string $value Статус выбираемых платежей или null чтобы удалить значение + * @return ReceiptsRequestBuilder Инстанс текущего объекта билдера + * + * @throws InvalidPropertyValueException Выбрасывается если переданное значение не является валидным статусом + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setStatus($value) + { + $this->currentObject->setStatus($value); + return $this; + } + + /** + * Устанавливает ограничение количества объектов чеков + * @param string $value Ограничение количества объектов чеков или null чтобы удалить значение + * @return ReceiptsRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод было передана не целое число + */ + public function setLimit($value) + { + $this->currentObject->setLimit($value); + return $this; + } + + /** + * Устанавливает токен следующей страницы выборки + * @param string $value Токен следующей страницы выборки или null чтобы удалить значение + * @return ReceiptsRequestBuilder Инстанс текущего объекта билдера + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setCursor($value) + { + $this->currentObject->setCursor($value); + return $this; + } + + /** + * Устанавливает дату создания от которой выбираются чеки + * @param \DateTime|string|int|null $value Время создания, от (не включая) или null чтобы удалить значение + * @return ReceiptsRequestBuilder Инстанс текущего объекта билдера + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|\Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtGt($value) + { + $this->currentObject->setCreatedAtGt($value); + return $this; + } + + /** + * Устанавливает дату создания от которой выбираются чеки + * @param \DateTime|string|int|null $value Время создания, от (включительно) или null чтобы удалить значение + * @return ReceiptsRequestBuilder Инстанс текущего объекта билдера + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|\Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtGte($value) + { + $this->currentObject->setCreatedAtGte($value); + return $this; + } + + /** + * Устанавливает дату создания до которой выбираются чеки + * @param \DateTime|string|int|null $value Время создания, до (не включая) или null чтобы удалить значение + * @return ReceiptsRequestBuilder Инстанс текущего объекта билдера + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|\Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtLt($value) + { + $this->currentObject->setCreatedAtLt($value); + return $this; + } + + /** + * Устанавливает дату создания до которой выбираются чеки + * @param \DateTime|string|int|null $value Время создания, до (включительно) или null чтобы удалить значение + * @return ReceiptsRequestBuilder Инстанс текущего объекта билдера + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|\Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtLte($value) + { + $this->currentObject->setCreatedAtLte($value); + return $this; + } + + /** + * Собирает и возвращает объект запроса списка чеков магазина + * @param array|null $options Массив с настройками запроса + * @return ReceiptsRequestInterface Инстанс объекта запроса к API для получения списка чеков магазина + */ + public function build(array $options = null) + { + return parent::build($options); + } +} \ No newline at end of file diff --git a/lib/Request/Receipts/ReceiptsRequestInterface.php b/lib/Request/Receipts/ReceiptsRequestInterface.php new file mode 100644 index 00000000..c0d013d7 --- /dev/null +++ b/lib/Request/Receipts/ReceiptsRequestInterface.php @@ -0,0 +1,153 @@ + 'cursor', + 'createdAtGte' => 'created_at.gte', + 'createdAtGt' => 'created_at.gt', + 'createdAtLte' => 'created_at.lte', + 'createdAtLt' => 'created_at.lt', + 'limit' => 'limit', + 'paymentId' => 'payment_id', + 'refundId' => 'refund_id', + 'status' => 'status', + ); + + /** + * Сериализует объект запроса к API для дальнейшей его отправки + * @param ReceiptsRequestInterface $request Сериализуемый объект + * @return array Массив с инфомрацией, отпарвляемый в дальнейшем в API + */ + public function serialize(ReceiptsRequestInterface $request) + { + $result = array(); + foreach (self::$propertyMap as $property => $name) { + $value = $request->{$property}; + if (!empty($value)) { + if ($value instanceof \DateTime) { + if ($value->getTimestamp() > 1) { + $result[$name] = $value->format(DATE_ATOM); + } + } else { + $result[$name] = $value; + } + } + } + return $result; + } +} \ No newline at end of file diff --git a/lib/Request/Receipts/ReceiptsResponse.php b/lib/Request/Receipts/ReceiptsResponse.php new file mode 100644 index 00000000..cca3a9c6 --- /dev/null +++ b/lib/Request/Receipts/ReceiptsResponse.php @@ -0,0 +1,120 @@ +factory = new ReceiptResponseFactory(); + + if (!empty($response['type'])) { + $this->type = $response['type']; + } + + $this->items = array(); + foreach ($response['items'] as $item) { + if ($receipt = $this->factory->factory($item)) { + $this->items[] = $receipt; + } + } + + if (!empty($response['next_cursor'])) { + $this->nextCursor = $response['next_cursor']; + } + } + + /** + * Возвращает формат выдачи результатов запроса. Возможное значение: `list` (список). + * @return string Формат выдачи результатов запроса. + */ + public function getType() + { + return $this->type; + } + + /** + * Возаращает список чеков + * @return ReceiptResponseInterface[] Список чеков + */ + public function getItems() + { + return $this->items; + } + + /** + * Возвращает токен следующей страницы, если он задан, или null + * @return string|null Токен следующей страницы + */ + public function getNextCursor() + { + return $this->nextCursor; + } + + /** + * Проверяет имееотся ли в ответе токен следующей страницы + * @return bool True если токен следующей страницы есть, false если нет + */ + public function hasNextCursor() + { + return $this->nextCursor !== null; + } +} \ No newline at end of file diff --git a/lib/Request/Receipts/RefundReceiptResponse.php b/lib/Request/Receipts/RefundReceiptResponse.php new file mode 100644 index 00000000..e3bef1ea --- /dev/null +++ b/lib/Request/Receipts/RefundReceiptResponse.php @@ -0,0 +1,89 @@ +setRefundId($this->getObjectId()); + } + + /** + * @return string + */ + public function getRefundId() + { + return $this->_refund_id; + } + + /** + * Устанавливает идентификатор возврата в ЮKassa + * + * @param string $value идентификатор возврата в ЮKassa + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в качестве значения была передана не строка + * @throws InvalidPropertyValueException Выбрасывается если длина переданной строки не равна 36 + */ + public function setRefundId($value) + { + if ($value === null || $value === '') { + $this->_refund_id = null; + } elseif (!TypeCast::canCastToString($value)) { + throw new InvalidPropertyValueTypeException('Invalid refund_id value type', 0, 'Receipt.refundId'); + } elseif (strlen((string)$value) !== self::LENGTH_REFUND_ID) { + throw new InvalidPropertyValueException( + 'Invalid refund_id value: "'.$value.'"', 0, 'Receipt.refundId', $value + ); + } else { + $this->_refund_id = (string)$value; + } + } + +} \ No newline at end of file diff --git a/lib/Request/Receipts/SimpleReceiptResponse.php b/lib/Request/Receipts/SimpleReceiptResponse.php new file mode 100644 index 00000000..88e11253 --- /dev/null +++ b/lib/Request/Receipts/SimpleReceiptResponse.php @@ -0,0 +1,46 @@ +setId(empty($options['id']) ? null : $options['id']); + $this->setPaymentId(empty($options['payment_id']) ? null : $options['payment_id']); + $this->setStatus(empty($options['status']) ? null : $options['status']); + $this->setCreatedAt(empty($options['created_at']) ? null : $options['created_at']); + $this->setAmount(new MonetaryAmount($options['amount']['value'], $options['amount']['currency'])); + + if (!empty($options['requestor'])) { + $this->setRequestor($options['requestor']); + } + + if (!empty($options['sources'])) { + $this->setSources($options['sources']); + } + + if (!empty($options['receipt_registration'])) { + $this->setReceiptRegistration($options['receipt_registration']); + } + + if (!empty($options['description'])) { + $this->setDescription($options['description']); + } + } +} diff --git a/lib/Request/Refunds/CreateRefundRequest.php b/lib/Request/Refunds/CreateRefundRequest.php new file mode 100644 index 00000000..3660470f --- /dev/null +++ b/lib/Request/Refunds/CreateRefundRequest.php @@ -0,0 +1,208 @@ +_paymentId; + } + + /** + * Устанавливает айди платежа для которого создаётся возврат + * @param string $value Айди платежа + * + * @throws EmptyPropertyValueException Выбрасывается если передано пустое значение айди платежа + * @throws InvalidPropertyValueException Выбрасывается если переданное значение является строкой, но не является + * валидным значением айди платежа + * @throws InvalidPropertyValueTypeException Выбрасывается если передано значение не валидного типа + */ + public function setPaymentId($value) + { + if ($value === null || $value === '') { + throw new EmptyPropertyValueException( + 'Empty payment id value in CreateRefundRequest', 0, 'CreateRefundRequest.paymentId' + ); + } elseif (TypeCast::canCastToString($value)) { + $length = mb_strlen($value, 'utf-8'); + if ($length != 36) { + throw new InvalidPropertyValueException( + 'Invalid payment id value in CreateRefundRequest', 0, 'CreateRefundRequest.paymentId', $value + ); + } + $this->_paymentId = (string)$value; + } else { + throw new InvalidPropertyValueException( + 'Invalid payment id value type in CreateRefundRequest', 0, 'CreateRefundRequest.paymentId', $value + ); + } + } + + /** + * Возвращает комментарий к возврату или null, если комментарий не задан + * @return string Комментарий к операции возврата, основание для возврата средств покупателю. + */ + public function getDescription() + { + return $this->_description; + } + + /** + * Проверяет задан ли комментарий к создаваемому возврату + * @return bool True если комментарий установлен, false если нет + */ + public function hasDescription() + { + return $this->_description !== null; + } + + /** + * Устанавливает комментарий к возврату + * @param string $value Комментарий к операции возврата, основание для возврата средств покупателю + * + * @throws InvalidPropertyValueTypeException Выбрасывается если была передана не строка + */ + public function setDescription($value) + { + if ($value === null || $value === '') { + $this->_description = null; + } elseif (TypeCast::canCastToString($value)) { + $this->_description = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid description value type in CreateRefundRequest', 0, 'CreateRefundRequest.description', $value + ); + } + } + + /** + * Устанавливает transfers (массив распределения денег между магазинами) + * @param SourceInterface[]|array $value + */ + public function setSources($value) + { + if (!is_array($value)) { + $message = 'Sources must be an array of SourceInterface'; + throw new InvalidPropertyValueTypeException($message, 0, 'CreateRefundRequest.sources', $value); + } + + $sources = array(); + foreach ($value as $item) { + if (is_array($item)) { + $item = new Source($item); + } + + if (!($item instanceof SourceInterface)) { + $message = 'Source must be instance of SourceInterface'; + throw new InvalidPropertyValueTypeException($message, 0, 'CreateRefundRequest.sources', $value); + } + $sources[] = $item; + } + + $this->_sources = $sources; + } + + /** + * @return SourceInterface[] + */ + public function getSources() + { + return $this->_sources; + } + + /** + * @return bool + */ + public function hasSources() + { + return !empty($this->_sources); + } + + /** + * Валидирует текущий объект запроса + * @return bool True если текущий объект запроса валиден, false если нет + */ + public function validate() + { + if (!parent::validate()) { + return false; + } + + if (empty($this->_paymentId)) { + $this->setValidationError('Payment id not specified'); + return false; + } + return true; + } + + /** + * Возвращает билдер объектов текущего типа + * @return CreateRefundRequestBuilder Инстанс билдера запрсов + */ + public static function builder() + { + return new CreateRefundRequestBuilder(); + } +} diff --git a/lib/Request/Refunds/CreateRefundRequestBuilder.php b/lib/Request/Refunds/CreateRefundRequestBuilder.php new file mode 100644 index 00000000..cd197e21 --- /dev/null +++ b/lib/Request/Refunds/CreateRefundRequestBuilder.php @@ -0,0 +1,118 @@ +currentObject->setPaymentId($value); + return $this; + } + + /** + * Устанавливает комментарий к возврату + * @param string $value Комментарий к возврату + * @return CreateRefundRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueTypeException Выбрасывается если была передана не строка + */ + public function setDescription($value) + { + $this->currentObject->setDescription($value); + return $this; + } + + /** + * Устанавливает источники возврата + * + * @param SourceInterface[]|array $value Массив трансферов + * + * @return self Инстанс билдера запросов + */ + public function setSources($value) + { + $this->currentObject->setSources($value); + return $this; + } + + /** + * Строит объект запроса к API + * @param array|null $options Устаналвиваемые параметры запроса + * @return CreateRefundRequestInterface Инстанс сгенерированного объекта запроса к API + */ + public function build(array $options = null) + { + if (!empty($options)) { + $this->setOptions($options); + } + + $this->currentObject->setAmount($this->amount); + + if ($this->receipt->notEmpty()) { + $this->currentObject->setReceipt($this->receipt); + } + return parent::build(); + } +} \ No newline at end of file diff --git a/lib/Request/Refunds/CreateRefundRequestInterface.php b/lib/Request/Refunds/CreateRefundRequestInterface.php new file mode 100644 index 00000000..9943d65a --- /dev/null +++ b/lib/Request/Refunds/CreateRefundRequestInterface.php @@ -0,0 +1,90 @@ + $request->getPaymentId(), + 'amount' => array( + 'value' => $request->getAmount()->getValue(), + 'currency' => $request->getAmount()->getCurrency(), + ), + ); + if ($request->hasDescription()) { + $result['description'] = $request->getDescription(); + } + if ($request->hasReceipt()) { + $receipt = $request->getReceipt(); + $result['receipt'] = array(); + /** @var ReceiptItem $item */ + foreach ($receipt->getItems() as $item) { + $itemArray = array( + 'description' => $item->getDescription(), + 'amount' => array( + 'value' => $item->getPrice()->getValue(), + 'currency' => $item->getPrice()->getCurrency(), + ), + 'quantity' => $item->getQuantity(), + 'vat_code' => $item->getVatCode(), + ); + + if ($item->getPaymentSubject()) { + $itemArray['payment_subject'] = $item->getPaymentSubject(); + } + + if ($item->getPaymentMode()) { + $itemArray['payment_mode'] = $item->getPaymentMode(); + } + + $result['receipt']['items'][] = $itemArray; + } + + $value = $receipt->getCustomer()->getEmail(); + if (!empty($value)) { + $result['receipt']['customer']['email'] = $value; + } + $value = $receipt->getCustomer()->getPhone(); + if (!empty($value)) { + $result['receipt']['customer']['phone'] = $value; + } + $value = $receipt->getTaxSystemCode(); + if (!empty($value)) { + $result['receipt']['tax_system_code'] = $value; + } + } + + if ($request->hasSources()) { + $result['sources'] = $this->serializeSources($request->getSources()); + } + + return $result; + } + + /** + * @param AmountInterface $amount + * + * @return array + */ + private function serializeAmount(AmountInterface $amount) + { + return array( + 'value' => $amount->getValue(), + 'currency' => $amount->getCurrency(), + ); + } + + /** + * @param SourceInterface[] $transfers + * + * @return array + */ + private function serializeSources(array $sources) + { + $result = array(); + foreach ($sources as $source) { + $result[] = array( + 'account_id' => $source->getAccountId(), + 'amount' => $this->serializeAmount($source->getAmount()) + ); + } + + return $result; + } +} \ No newline at end of file diff --git a/lib/Request/Refunds/CreateRefundResponse.php b/lib/Request/Refunds/CreateRefundResponse.php new file mode 100644 index 00000000..466c539d --- /dev/null +++ b/lib/Request/Refunds/CreateRefundResponse.php @@ -0,0 +1,35 @@ +_paymentId; + } + + /** + * Проверяет, был ли задан идентификатор платежа + * @return bool True если идентификатор был задан, false если нет + */ + public function hasPaymentId() + { + return !empty($this->_paymentId); + } + + /** + * Устанавливает идентификатор платежа или null если требуется его удалить + * @param string|null $value Идентификатор платежа + * + * @throws InvalidPropertyValueException Выбрасывается если длина переданной строки не равна 36 символам + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setPaymentId($value) + { + if ($value === null || $value === '') { + $this->_paymentId = null; + } elseif (TypeCast::canCastToString($value)) { + $length = mb_strlen((string)$value, 'utf-8'); + if ($length != 36) { + throw new InvalidPropertyValueException( + 'Invalid payment id value in RefundsRequest', 0, 'RefundsRequest.paymentId', $value + ); + } + $this->_paymentId = (string)$value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid payment id value type in RefundsRequest', 0, 'RefundsRequest.paymentId', $value + ); + } + } + + /** + * Возвращает дату создания от которой будут возвращены возвраты или null если дата не была установлена + * @return \DateTime|null Время создания, от (включительно) + */ + public function getCreatedAtGte() + { + return $this->_createdAtGte; + } + + /** + * Проверяет была ли установлена дата создания от которой выбираются возвраты + * @return bool True если дата была установлена, false если нет + */ + public function hasCreatedAtGte() + { + return !empty($this->_createdAtGte); + } + + /** + * Устанавливает дату создания от которой выбираются возвраты + * @param \DateTime|string|int|null $value Время создания, от (включительно) или null чтобы удалить значение + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtGte($value) + { + if ($value === null || $value === '') { + $this->_createdAtGte = null; + } elseif (TypeCast::canCastToDateTime($value)) { + $dateTime = TypeCast::castToDateTime($value); + if ($dateTime === null) { + throw new InvalidPropertyValueException( + 'Invalid created_gte value in RefundsRequest', 0, 'RefundsRequest.createdAtGte' + ); + } + $this->_createdAtGte = $dateTime; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid created_gte value type in RefundsRequest', 0, 'RefundsRequest.createdAtGte' + ); + } + } + + /** + * Возвращает дату создания от которой будут возвращены возвраты или null если дата не была установлена + * @return \DateTime|null Время создания, от (не включая) + */ + public function getCreatedAtGt() + { + return $this->_createdAtGt; + } + + /** + * Проверяет была ли установлена дата создания от которой выбираются возвраты + * @return bool True если дата была установлена, false если нет + */ + public function hasCreatedAtGt() + { + return !empty($this->_createdAtGt); + } + + /** + * Устанавливает дату создания от которой выбираются возвраты + * @param \DateTime|string|int|null $value Время создания, от (не включая) или null чтобы удалить значение + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtGt($value) + { + if ($value === null || $value === '') { + $this->_createdAtGt = null; + } elseif (TypeCast::canCastToDateTime($value)) { + $dateTime = TypeCast::castToDateTime($value); + if ($dateTime === null) { + throw new InvalidPropertyValueException( + 'Invalid created_gt value in RefundsRequest', 0, 'RefundsRequest.createdAtGt' + ); + } + $this->_createdAtGt = $dateTime; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid created_gt value type in RefundsRequest', 0, 'RefundsRequest.createdAtGt' + ); + } + } + + /** + * Возвращает дату создания до которой будут возвращены возвраты или null если дата не была установлена + * @return \DateTime|null Время создания, до (включительно) + */ + public function getCreatedAtLte() + { + return $this->_createdAtLte; + } + + /** + * Проверяет была ли установлена дата создания до которой выбираются возвраты + * @return bool True если дата была установлена, false если нет + */ + public function hasCreatedAtLte() + { + return !empty($this->_createdAtLte); + } + + /** + * Устанавливает дату создания до которой выбираются возвраты + * @param \DateTime|string|int|null $value Время создания, до (включительно) или null чтобы удалить значение + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtLte($value) + { + if ($value === null || $value === '') { + $this->_createdAtLte = null; + } elseif (TypeCast::canCastToDateTime($value)) { + $dateTime = TypeCast::castToDateTime($value); + if ($dateTime === null) { + throw new InvalidPropertyValueException( + 'Invalid created_lte value in RefundsRequest', 0, 'RefundsRequest.createdLte' + ); + } + $this->_createdAtLte = $dateTime; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid created_lte value type in RefundsRequest', 0, 'RefundsRequest.createdLte' + ); + } + } + + /** + * Возвращает дату создания до которой будут возвращены возвраты или null если дата не была установлена + * @return \DateTime|null Время создания, до (не включая) + */ + public function getCreatedAtLt() + { + return $this->_createdAtLt; + } + + /** + * Проверяет была ли установлена дата создания до которой выбираются возвраты + * @return bool True если дата была установлена, false если нет + */ + public function hasCreatedAtLt() + { + return !empty($this->_createdAtLt); + } + + /** + * Устанавливает дату создания до которой выбираются возвраты + * @param \DateTime|string|int|null $value Время создания, до (не включая) или null чтобы удалить значение + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtLt($value) + { + if ($value === null || $value === '') { + $this->_createdAtLt = null; + } elseif (TypeCast::canCastToDateTime($value)) { + $dateTime = TypeCast::castToDateTime($value); + if ($dateTime === null) { + throw new InvalidPropertyValueException( + 'Invalid created_lt value in RefundsRequest', 0, 'RefundsRequest.createdLt' + ); + } + $this->_createdAtLt = $dateTime; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid created_lt value type in RefundsRequest', 0, 'RefundsRequest.createdLt' + ); + } + } + + /** + * Возвращает статус выбираемых возвратов или null если он до этого не был установлен + * @return string|null Статус выбираемых возвратов + */ + public function getStatus() + { + return $this->_status; + } + + /** + * Проверяет был ли установлен статус выбираемых возвратов + * @return bool True если статус был установлен, false если нет + */ + public function hasStatus() + { + return !empty($this->_status); + } + + /** + * Устанавливает статус выбираемых возвратов + * @param string $value Статус выбираемых платежей или null чтобы удалить значение + * + * @throws InvalidPropertyValueException Выбрасывается если переданное значение не является валидным статусом + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setStatus($value) + { + if ($value === null || $value === '') { + $this->_status = null; + } elseif (TypeCast::canCastToEnumString($value)) { + if (!RefundStatus::valueExists((string)$value)) { + throw new InvalidPropertyValueException( + 'Invalid status value in RefundsRequest', 0, 'RefundsRequest.status', $value + ); + } else { + $this->_status = (string)$value; + } + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid status value in RefundsRequest', 0, 'RefundsRequest.status', $value + ); + } + } + + /** + * Возвращает токен для получения следующей страницы выборки + * @return string|null Токен для получения следующей страницы выборки + */ + public function getCursor() + { + return $this->_cursor; + } + + /** + * Проверяет был ли установлен токен следующей страницы + * @return bool True если токен был установлен, false если нет + */ + public function hasCursor() + { + return !empty($this->_cursor); + } + + /** + * Устанавливает токен следующей страницы выборки + * @param string $value Токен следующей страницы выборки или null чтобы удалить значение + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setCursor($value) + { + if ($value === null || $value === '') { + $this->_cursor = null; + } elseif (TypeCast::canCastToString($value)) { + $this->_cursor = (string) $value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid status value in RefundsRequest', 0, 'RefundsRequest.cursor', $value + ); + } + } + + /** + * Ограничение количества объектов платежа + * @return integer|null Ограничение количества объектов платежа + */ + public function getLimit() + { + return $this->_limit; + } + + /** + * Проверяет был ли установлено ограничение количества объектов платежа + * @return bool True если было установлено, false если нет + */ + public function hasLimit() + { + return $this->_limit !== null; + } + + /** + * Устанавливает ограничение количества объектов платежа + * @param integer|null $value Ограничение количества объектов платежа или null чтобы удалить значение + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передано не целое число + */ + public function setLimit($value) + { + if ($value === null || $value === '') { + $this->_limit = null; + } elseif (is_int($value)) { + if ($value < 0 || $value > self::MAX_LIMIT_VALUE) { + throw new InvalidPropertyValueException( + 'Invalid limit value in RefundsRequest', 0, 'RefundsRequest.limit', $value + ); + } + $this->_limit = $value; + } else { + throw new InvalidPropertyValueTypeException( + 'Invalid limit value type in RefundsRequest', 0, 'RefundsRequest.limit', $value + ); + } + } + + /** + * Проверяет валидность текущего объекта запроса + * @return bool True если объект валиден, false если нет + */ + public function validate() + { + return true; + } + + /** + * Возвращает инстанс билдера объектов запросов списка возвратов магазина + * @return RefundsRequestBuilder Билдер объектов запросов списка возвратов + */ + public static function builder() + { + return new RefundsRequestBuilder(); + } +} diff --git a/lib/Request/Refunds/RefundsRequestBuilder.php b/lib/Request/Refunds/RefundsRequestBuilder.php new file mode 100644 index 00000000..8d0c4bc8 --- /dev/null +++ b/lib/Request/Refunds/RefundsRequestBuilder.php @@ -0,0 +1,181 @@ +currentObject->setPaymentId($value); + return $this; + } + + /** + * Устанавливает статус выбираемых возвратов + * @param string $value Статус выбираемых платежей или null чтобы удалить значение + * @return RefundsRequestBuilder Инстанс текущего объекта билдера + * + * @throws InvalidPropertyValueException Выбрасывается если переданное значение не является валидным статусом + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setStatus($value) + { + $this->currentObject->setStatus($value); + return $this; + } + + /** + * Устанавливает ограничение количества объектов возвратов + * @param string $value Ограничение количества объектов возвратов или null чтобы удалить значение + * @return RefundsRequestBuilder Инстанс текущего билдера + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод было передана не целое число + */ + public function setLimit($value) + { + $this->currentObject->setLimit($value); + return $this; + } + + /** + * Устанавливает токен следующей страницы выборки + * @param string $value Токен следующей страницы выборки или null чтобы удалить значение + * @return RefundsRequestBuilder Инстанс текущего объекта билдера + * + * @throws InvalidPropertyValueTypeException Выбрасывается если в метод была передана не строка + */ + public function setCursor($value) + { + $this->currentObject->setCursor($value); + return $this; + } + + /** + * Устанавливает дату создания от которой выбираются возвраты + * @param \DateTime|string|int|null $value Время создания, от (не включая) или null чтобы удалить значение + * @return RefundsRequestBuilder Инстанс текущего объекта билдера + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|\Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtGt($value) + { + $this->currentObject->setCreatedAtGt($value); + return $this; + } + + /** + * Устанавливает дату создания от которой выбираются возвраты + * @param \DateTime|string|int|null $value Время создания, от (включительно) или null чтобы удалить значение + * @return RefundsRequestBuilder Инстанс текущего объекта билдера + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|\Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtGte($value) + { + $this->currentObject->setCreatedAtGte($value); + return $this; + } + + /** + * Устанавливает дату создания до которой выбираются возвраты + * @param \DateTime|string|int|null $value Время создания, до (не включая) или null чтобы удалить значение + * @return RefundsRequestBuilder Инстанс текущего объекта билдера + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|\Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtLt($value) + { + $this->currentObject->setCreatedAtLt($value); + return $this; + } + + /** + * Устанавливает дату создания до которой выбираются возвраты + * @param \DateTime|string|int|null $value Время создания, до (включительно) или null чтобы удалить значение + * @return RefundsRequestBuilder Инстанс текущего объекта билдера + * + * @throws InvalidPropertyValueException Генерируется если была передана дата в невалидном формате (была передана + * строка или число, которые не удалось преобразовать в валидную дату) + * @throws InvalidPropertyValueTypeException|\Exception Генерируется если была передана дата с не тем типом (передана не + * строка, не число и не значение типа \DateTime) + */ + public function setCreatedAtLte($value) + { + $this->currentObject->setCreatedAtLte($value); + return $this; + } + + /** + * Собирает и возвращает объект запроса списка возвратов магазина + * @param array|null $options Массив с настройками запроса + * @return RefundsRequestInterface Инстанс объекта запроса к API для получения списка возвратов магазина + */ + public function build(array $options = null) + { + return parent::build($options); + } +} \ No newline at end of file diff --git a/lib/Request/Refunds/RefundsRequestInterface.php b/lib/Request/Refunds/RefundsRequestInterface.php new file mode 100644 index 00000000..b6208876 --- /dev/null +++ b/lib/Request/Refunds/RefundsRequestInterface.php @@ -0,0 +1,128 @@ + 'cursor', + 'createdAtGte' => 'created_at.gte', + 'createdAtGt' => 'created_at.gt', + 'createdAtLte' => 'created_at.lte', + 'createdAtLt' => 'created_at.lt', + 'limit' => 'limit', + 'paymentId' => 'payment_id', + 'status' => 'status', + ); + + /** + * Сериализует объект запроса к API для дальнейшей его отправки + * @param RefundsRequestInterface $request Сериализуемый объект + * @return array Массив с инфомрацией, отпарвляемый в дальнейшем в API + */ + public function serialize(RefundsRequestInterface $request) + { + $result = array(); + foreach (self::$propertyMap as $property => $name) { + $value = $request->{$property}; + if (!empty($value)) { + if ($value instanceof \DateTime) { + if ($value->getTimestamp() > 1) { + $result[$name] = $value->format(DATE_ATOM); + } + } else { + $result[$name] = $value; + } + } + } + return $result; + } +} \ No newline at end of file diff --git a/lib/Request/Refunds/RefundsResponse.php b/lib/Request/Refunds/RefundsResponse.php new file mode 100644 index 00000000..c46ad3c1 --- /dev/null +++ b/lib/Request/Refunds/RefundsResponse.php @@ -0,0 +1,90 @@ +items = array(); + foreach ($options['items'] as $item) { + $this->items[] = new RefundResponse($item); + } + if (!empty($options['next_cursor'])) { + $this->nextCursor = $options['next_cursor']; + } + } + + /** + * Возвращает список возвратов + * @return RefundInterface[] Список возвратов + */ + public function getItems() + { + return $this->items; + } + + /** + * Возвращает токен следующей страницы, если он задан, или null + * @return string|null Токен следующей страницы + */ + public function getNextCursor() + { + return $this->nextCursor; + } + + /** + * Проверяет имееотся ли в ответе токен следующей страницы + * @return bool True если токен следующей страницы есть, false если нет + */ + public function hasNextCursor() + { + return $this->nextCursor !== null; + } + +} diff --git a/lib/Request/Webhook/WebhookListResponse.php b/lib/Request/Webhook/WebhookListResponse.php new file mode 100644 index 00000000..8da52e07 --- /dev/null +++ b/lib/Request/Webhook/WebhookListResponse.php @@ -0,0 +1,66 @@ +type = $response['type']; + } + $this->items = array(); + foreach ($response['items'] as $item) { + $this->items[] = new Webhook($item); + } + } + + /** + * Возаращает список способов оплаты подходящих для оплаты заказа + * Если нет ни одного доступного способа оплаты, список будет пустым + * @return Webhook[] Список способов оплаты + */ + public function getItems() + { + return $this->items; + } +} \ No newline at end of file diff --git a/lib/autoload.php b/lib/autoload.php new file mode 100644 index 00000000..107f3f14 --- /dev/null +++ b/lib/autoload.php @@ -0,0 +1,47 @@ + + + + + + tests + + + + + + + + + + + ./lib + + + \ No newline at end of file diff --git a/tests/AutoloadTest.php b/tests/AutoloadTest.php new file mode 100644 index 00000000..5c87ad51 --- /dev/null +++ b/tests/AutoloadTest.php @@ -0,0 +1,65 @@ +walkDirectoriesAndTest(YOOKASSA_SDK_ROOT_PATH, 'YooKassa'); +// $this->walkDirectoriesAndTest(YOOKASSA_SDK_PSR_LOG_PATH, 'Psr\Log'); +// +// self::assertFalse(class_exists('Unknown\\Class\\Name')); +// +// spl_autoload_unregister($lastFunction); +// foreach ($functions as $function) { +// spl_autoload_register($function); +// } +// } +// +// private function walkDirectoriesAndTest($directoryName, $namespace) +// { +// $dir = opendir($directoryName); +// while (($entry = readdir($dir)) !== false) { +// if ($entry === '.' || $entry === '..') { +// continue; +// } +// $path = $directoryName . DIRECTORY_SEPARATOR . $entry; +// if (is_dir($entry)) { +// $this->walkDirectoriesAndTest($path, $namespace . '\\' . $entry); +// } else { +// $extension = pathinfo($entry, PATHINFO_EXTENSION); +// if ($extension === 'php' && strtoupper($entry[0]) === $entry[0]) { +// $className = $namespace . '\\' . pathinfo($entry, PATHINFO_FILENAME); +// if (!$this->classExists($className)) { +// yookassaSdkLoadClass($className); +// self::assertTrue($this->classExists($className), 'Class "' . $className . '" not exists'); +// } +// } +// } +// } +// closedir($dir); +// } +// +// private function classExists($className) +// { +// return class_exists($className, false) || interface_exists($className, false) || trait_exists($className, false); +// } +//} \ No newline at end of file diff --git a/tests/Client/ClientTest.php b/tests/Client/ClientTest.php new file mode 100644 index 00000000..05e40467 --- /dev/null +++ b/tests/Client/ClientTest.php @@ -0,0 +1,1360 @@ +setAmount(123) + ->setPaymentToken(Random::str(36)) + ->build(); + + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->once()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $this->getFixtures('createPaymentFixtures.json'), + array('http_code' => 200) + )); + + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->createPayment($payment); + + self::assertSame($curlClientStub, $apiClient->getApiClient()); + self::assertTrue($response instanceof CreatePaymentResponse); + + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->once()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $this->getFixtures('createPaymentFixtures.json'), + array('http_code' => 200) + )); + + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->createPayment(array( + 'amount' => array( + 'value' => 123, + 'currency' => 'USD', + ), + 'payment_token' => Random::str(36), + ), 123); + + self::assertSame($curlClientStub, $apiClient->getApiClient()); + self::assertTrue($response instanceof CreatePaymentResponse); + + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->any()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + '{"type":"error","code":"request_accepted","retry_after":1800}', + array('http_code' => 202) + )); + + try { + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->createPayment($payment, 123); + self::fail('Исключение не было выброшено'); + } catch (ApiException $e) { + self::assertInstanceOf('YooKassa\Common\Exceptions\ResponseProcessingException', $e); + return; + } + + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->any()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + '{"type":"error","code":"request_accepted"}', + array('http_code' => 202) + )); + + try { + $apiClient->setRetryTimeout(0); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->createPayment($payment, 123); + self::fail('Исключение не было выброшено'); + } catch (ResponseProcessingException $e) { + self::assertEquals(Client::DEFAULT_DELAY, $e->retryAfter); + return; + } + } + + /** + * @dataProvider errorResponseDataProvider + * @param $httpCode + * @param $errorResponse + * @param $requiredException + * @throws Exception + */ + public function testInvalidCreatePayment($httpCode, $errorResponse, $requiredException) + { + $payment = CreatePaymentRequest::builder() + ->setAmount(123) + ->setPaymentToken(Random::str(36)) + ->build(); + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->any()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $errorResponse, + array('http_code' => $httpCode) + )); + + $apiClient = new Client(); + $apiClient->setApiClient($curlClientStub)->setAuth('shopId', 'shopPassword'); + try { + $apiClient->createPayment($payment,123); + } catch (ApiException $e) { + self::assertInstanceOf($requiredException, $e); + return; + } + self::fail('Exception not thrown'); + } + + /** + * @dataProvider paymentsListDataProvider + * @param mixed $request + * @throws ApiException + * @throws ResponseProcessingException + * @throws BadApiRequestException + * @throws ForbiddenException + * @throws InternalServerError + * @throws NotFoundException + * @throws TooManyRequestsException + * @throws UnauthorizedException + */ + public function testPaymentsList($request) + { + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->once()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $this->getFixtures('getPaymentsFixtures.json'), + array('http_code' => 200) + )); + + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->getPayments($request); + + $this->assertTrue($response instanceof PaymentsResponse); + } + + public function paymentsListDataProvider() + { + return array( + array(null), + array(PaymentsRequest::builder()->build()), + array(array( + 'account_id' => 12, + )) + ); + } + + /** + * @dataProvider errorResponseDataProvider + * @param $httpCode + * @param $errorResponse + * @param $requiredException + */ + public function testInvalidPaymentsList($httpCode, $errorResponse, $requiredException) + { + $payments = PaymentsRequest::builder()->build(); + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->any()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $errorResponse, + array('http_code' => $httpCode) + )); + + $apiClient = new Client(); + $apiClient->setApiClient($curlClientStub)->setAuth('shopId', 'shopPassword'); + try { + $apiClient->getPayments($payments); + } catch (ApiException $e) { + self::assertInstanceOf($requiredException, $e); + return; + } + self::fail('Exception not thrown'); + } + + /** + * @dataProvider paymentInfoDataProvider + * @param mixed $paymentId + * @param string $exceptionClassName + * @throws ApiException + * @throws ResponseProcessingException + * @throws BadApiRequestException + * @throws ForbiddenException + * @throws InternalServerError + * @throws NotFoundException + * @throws TooManyRequestsException + * @throws UnauthorizedException + */ + public function testGetPaymentInfo($paymentId, $exceptionClassName = null) + { + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($exceptionClassName !== null ? self::never() : self::once()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $this->getFixtures('paymentInfoFixtures.json'), + array('http_code' => 200) + )); + + $apiClient = new Client(); + + if ($exceptionClassName !== null) { + $this->setExpectedException($exceptionClassName); + } + + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->getPaymentInfo($paymentId); + + self::assertTrue($response instanceof PaymentResponse); + } + + public function paymentInfoDataProvider() + { + return array( + array(null, '\InvalidArgumentException'), + array(Random::str(36)), + array(new StringObject(Random::str(36))), + array(true, '\InvalidArgumentException'), + array(false, '\InvalidArgumentException'), + array(0, '\InvalidArgumentException'), + array(1, '\InvalidArgumentException'), + array(0.1, '\InvalidArgumentException'), + array(Random::str(35), '\InvalidArgumentException'), + array(Random::str(37), '\InvalidArgumentException'), + array(new DateTime(), '\InvalidArgumentException'), + array(array(), '\InvalidArgumentException'), + ); + } + + /** + * @dataProvider errorResponseDataProvider + * @param $httpCode + * @param $errorResponse + * @param $requiredException + * @throws Exception + */ + public function testInvalidGetPaymentInfo($httpCode, $errorResponse, $requiredException) + { + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->once()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $errorResponse, + array('http_code' => $httpCode) + )); + + $apiClient = new Client(); + $apiClient->setApiClient($curlClientStub)->setAuth('shopId', 'shopPassword'); + try { + $apiClient->getPaymentInfo(Random::str(36)); + } catch (ApiException $e) { + self::assertInstanceOf($requiredException, $e); + return; + } + self::fail('Exception not thrown'); + } + + public function testCapturePayment() + { + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->once()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $this->getFixtures('capturePaymentFixtures.json'), + array('http_code' => 200) + )); + + $capturePaymentRequest = array( + 'amount' => array( + 'value' => 123, + 'currency' => 'EUR', + ) + ); + + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->capturePayment($capturePaymentRequest, '1ddd77af-0bd7-500d-895b-c475c55fdefc', 123); + + $this->assertTrue($response instanceof CreateCaptureResponse); + + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->once()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $this->getFixtures('capturePaymentFixtures.json'), + array('http_code' => 200) + )); + + $capturePaymentRequest = CreateCaptureRequest::builder()->setAmount(10)->build(); + + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->capturePayment($capturePaymentRequest, '1ddd77af-0bd7-500d-895b-c475c55fdefc'); + + $this->assertTrue($response instanceof CreateCaptureResponse); + + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->any()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + '{"type":"error","code":"request_accepted","retry_after":123}', + array('http_code' => 202) + )); + + try { + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->capturePayment($capturePaymentRequest, '1ddd77af-0bd7-500d-895b-c475c55fdefc', 123); + self::fail('Exception not thrown'); + } catch (ApiException $e) { + self::assertInstanceOf('YooKassa\Common\Exceptions\ResponseProcessingException', $e); + } + + try { + $apiClient->capturePayment($capturePaymentRequest, null, 123); + } catch (InvalidArgumentException $e) { + // it's ok + return; + } + self::fail('Exception not thrown'); + } + + /** + * @dataProvider errorResponseDataProvider + * @param $httpCode + * @param $errorResponse + * @param $requiredException + * @throws Exception + */ + public function testInvalidCapturePayment($httpCode, $errorResponse, $requiredException) + { + $capturePaymentRequest = CreateCaptureRequest::builder()->setAmount(10)->build(); + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->once()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $errorResponse, + array('http_code' => $httpCode) + )); + + $apiClient = new Client(); + $apiClient->setApiClient($curlClientStub)->setAuth('shopId', 'shopPassword'); + try { + $apiClient->capturePayment($capturePaymentRequest, '1ddd77af-0bd7-500d-895b-c475c55fdefc', 123); + } catch (ApiException $e) { + self::assertInstanceOf($requiredException, $e); + return; + } + self::fail('Exception not thrown'); + } + + /** + * @dataProvider paymentInfoDataProvider + * @param mixed $paymentId + * @param string|null $exceptionClassName + */ + public function testPaymentIdCapturePayment($paymentId, $exceptionClassName = null) + { + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($exceptionClassName === null ? self::once() : self::never()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $this->getFixtures('capturePaymentFixtures.json'), + array('http_code' => 200) + )); + + $capturePaymentRequest = array( + 'amount' => array( + 'value' => 123, + 'currency' => 'EUR', + ) + ); + + if ($exceptionClassName !== null) { + $this->setExpectedException($exceptionClassName); + } + + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->capturePayment($capturePaymentRequest, $paymentId, 123); + + self::assertTrue($response instanceof CreateCaptureResponse); + } + + /** + * @dataProvider paymentInfoDataProvider + * @param mixed $paymentId + * @param string $exceptionClassName + */ + public function testCancelPayment($paymentId, $exceptionClassName = null) + { + $invalid = $exceptionClassName !== null; + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($invalid ? self::never() : self::once()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $this->getFixtures('cancelPaymentFixtures.json'), + array('http_code' => 200) + )); + + if ($invalid) { + $this->setExpectedException($exceptionClassName); + } + + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->cancelPayment($paymentId, 123); + + $this->assertTrue($response instanceof CancelResponse); + } + + /** + * @dataProvider errorResponseDataProvider + * @param $httpCode + * @param $errorResponse + * @param $requiredException + */ + public function testInvalidCancelPayment($httpCode, $errorResponse, $requiredException) + { + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->any()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $errorResponse, + array('http_code' => $httpCode) + )); + + $apiClient = new Client(); + $apiClient->setApiClient($curlClientStub)->setAuth('shopId', 'shopPassword'); + try { + $apiClient->cancelPayment(Random::str(36)); + } catch (ApiException $e) { + self::assertInstanceOf($requiredException, $e); + return; + } + self::fail('Exception not thrown'); + } + + /** + * @dataProvider refundsDataProvider + * @param mixed $refundsRequest + */ + public function testGetRefunds($refundsRequest) + { + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects(self::once()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $this->getFixtures('refundsInfoFixtures.json'), + array('http_code' => 200) + )); + + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->getRefunds($refundsRequest); + + $this->assertTrue($response instanceof RefundsResponse); + } + + public function refundsDataProvider() + { + return array( + array(null), + array(RefundsRequest::builder()->build()), + array(array( + 'account_id' => 123, + )), + ); + } + + /** + * @dataProvider errorResponseDataProvider + * @param $httpCode + * @param $errorResponse + * @param $requiredException + */ + public function testInvalidGetRefunds($httpCode, $errorResponse, $requiredException) + { + $refundsRequest = RefundsRequest::builder()->build(); + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->once()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $errorResponse, + array('http_code' => $httpCode) + )); + + $apiClient = new Client(); + $apiClient->setApiClient($curlClientStub)->setAuth('shopId', 'shopPassword'); + try { + $apiClient->getRefunds($refundsRequest); + } catch (ApiException $e) { + self::assertInstanceOf($requiredException, $e); + return; + } + self::fail('Exception not thrown'); + } + + public function testCreateRefund() + { + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->once()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $this->getFixtures('createRefundFixtures.json'), + array('http_code' => 200) + )); + + $refundRequest = CreateRefundRequest::builder()->setPaymentId('1ddd77af-0bd7-500d-895b-c475c55fdefc')->setAmount(123)->build(); + + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->createRefund($refundRequest, 123); + + $this->assertTrue($response instanceof CreateRefundResponse); + + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->once()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $this->getFixtures('createRefundFixtures.json'), + array('http_code' => 200) + )); + + $refundRequest = array( + 'payment_id' => '1ddd77af-0bd7-500d-895b-c475c55fdefc', + 'amount' => array( + 'value' => 321, + 'currency' => 'RUB', + ) + ); + + $apiClient = new Client(); + + $response = $apiClient + ->setMaxRequestAttempts(2) + ->setRetryTimeout(1000) + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->createRefund($refundRequest); + + $this->assertTrue($response instanceof CreateRefundResponse); + + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->any()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + '{"type":"error","code":"request_accepted","retry_after":1800}', + array('http_code' => 202) + )); + + try { + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->createRefund($refundRequest, 123); + } catch (ApiException $e) { + self::assertInstanceOf('YooKassa\Common\Exceptions\ResponseProcessingException', $e); + return; + } + + self::fail('Exception not thrown'); + } + + /** + * @dataProvider errorResponseDataProvider + * @param $httpCode + * @param $errorResponse + * @param $requiredException + * @throws Exception + */ + public function testInvalidCreateRefund($httpCode, $errorResponse, $requiredException) + { + $refundRequest = CreateRefundRequest::builder()->setPaymentId('1ddd77af-0bd7-500d-895b-c475c55fdefc')->setAmount(123)->build(); + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->once()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $errorResponse, + array('http_code' => $httpCode) + )); + + $apiClient = new Client(); + $apiClient->setApiClient($curlClientStub)->setAuth('shopId', 'shopPassword'); + try { + $apiClient->createRefund($refundRequest, 123); + } catch (ApiException $e) { + self::assertInstanceOf($requiredException, $e); + return; + } + self::fail('Exception not thrown'); + } + + /** + * @dataProvider paymentInfoDataProvider + * + * @param mixed $refundId + * @param string $exceptionClassName + * @throws ApiException + * @throws BadApiRequestException + * @throws ForbiddenException + * @throws InternalServerError + * @throws NotFoundException + * @throws ResponseProcessingException + * @throws TooManyRequestsException + * @throws UnauthorizedException + */ + public function testRefundInfo($refundId, $exceptionClassName = null) + { + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($exceptionClassName === null ? self::once() : self::never()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $this->getFixtures('refundInfoFixtures.json'), + array('http_code' => 200) + )); + + if ($exceptionClassName !== null) { + $this->setExpectedException($exceptionClassName); + } + + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->getRefundInfo($refundId); + + $this->assertTrue($response instanceof RefundResponse); + + try { + $apiClient->getRefundInfo(null); + } catch (InvalidArgumentException $e) { + // it's ok + return; + } + self::fail('Exception not thrown'); + } + + /** + * @dataProvider errorResponseDataProvider + * @param $httpCode + * @param $errorResponse + * @param $requiredException + * @throws Exception + */ + public function testInvalidRefundInfo($httpCode, $errorResponse, $requiredException) + { + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->once()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $errorResponse, + array('http_code' => $httpCode) + )); + + $apiClient = new Client(); + $apiClient->setApiClient($curlClientStub)->setAuth('shopId', 'shopPassword'); + try { + $apiClient->getRefundInfo(Random::str(36)); + } catch (ApiException $e) { + self::assertInstanceOf($requiredException, $e); + return; + } + self::fail('Exception not thrown'); + } + + public function testApiException() + { + $payment = CreatePaymentRequest::builder() + ->setAmount(123) + ->setPaymentToken(Random::str(36)) + ->build(); + + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->any()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + 'unknown response here', + array('http_code' => 444) + )); + $this->setExpectedException('YooKassa\Common\Exceptions\ApiException'); + + $apiClient = new Client(); + $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->createPayment($payment, 123); + } + + public function testBadRequestException() + { + $payment = CreatePaymentRequest::builder() + ->setAmount(123) + ->setPaymentToken(Random::str(36)) + ->build(); + + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->any()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + '{"description": "error_msg", "code": "error_code", "parameter_name": "parameter_name"}', + array('http_code' => 400) + )); + $this->setExpectedException('YooKassa\Common\Exceptions\BadApiRequestException'); + + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->createPayment($payment, 123); + } + + public function testTechnicalErrorException() + { + $payment = CreatePaymentRequest::builder() + ->setAmount(123) + ->setPaymentToken(Random::str(36)) + ->build(); + + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->any()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + '{"description": "error_msg", "code": "error_code"}', + array('http_code' => 500) + )); + $this->setExpectedException('YooKassa\Common\Exceptions\InternalServerError'); + + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->createPayment($payment, 123); + } + + public function testUnauthorizedException() + { + $payment = CreatePaymentRequest::builder() + ->setAmount(123) + ->setPaymentToken(Random::str(36)) + ->build(); + + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->any()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + '{"description": "error_msg"}', + array('http_code' => 401) + )); + $this->setExpectedException('YooKassa\Common\Exceptions\UnauthorizedException'); + + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->createPayment($payment, 123); + } + + public function testForbiddenException() + { + $payment = CreatePaymentRequest::builder() + ->setAmount(123) + ->setPaymentToken(Random::str(36)) + ->build(); + + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->any()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + '{"description": "error_msg","error_code": "error_code", "parameter_name": "parameter_name", "operation_name": "operation_name"}', + array('http_code' => 403) + )); + $this->setExpectedException('YooKassa\Common\Exceptions\ForbiddenException'); + + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->createPayment($payment, 123); + } + + public function testNotFoundException() + { + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->any()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + '{"description": "error_msg","error_code": "error_code", "parameter_name": "parameter_name", "operation_name": "operation_name"}', + array('http_code' => 404) + )); + $this->setExpectedException('YooKassa\Common\Exceptions\NotFoundException'); + + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->getPaymentInfo(Random::str(36)); + } + + public function testToManyRequestsException() + { + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->any()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + '{"description": "error_msg","error_code": "error_code", "parameter_name": "parameter_name", "operation_name": "operation_name"}', + array('http_code' => 429) + )); + $this->setExpectedException('YooKassa\Common\Exceptions\TooManyRequestsException'); + + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->getPaymentInfo(Random::str(36)); + } + + public function testAnotherExceptions() + { + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->any()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + '{}', + array('http_code' => 322) + )); + + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->getPaymentInfo(Random::str(36)); + + self::assertNull($response); + + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->any()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + '{}', + array('http_code' => 402) + )); + + $apiClient = new Client(); + + $this->setExpectedException('YooKassa\Common\Exceptions\ApiException'); + + $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->getPaymentInfo(Random::str(36)); + + } + + public function testConfig() + { + $apiClient = new Client(); + $apiClient->setConfig(array( + 'url' => 'test' + )); + + $this->assertEquals(array('url' => 'test'), $apiClient->getConfig()); + } + + public function testSetLogger() + { + $wrapped = new ArrayLogger(); + $logger = new LoggerWrapper($wrapped); + + $apiClient = new Client(); + $apiClient->setLogger($logger); + + $clientMock = $this->getMockBuilder('YooKassa\Client\ApiClientInterface') + ->setMethods(array('setLogger', 'setConfig', 'call', 'setShopId', 'getUserAgent', 'setBearerToken', 'setShopPassword')) + ->disableOriginalConstructor() + ->getMock(); + $expectedLoggers = array(); + $clientMock->expects(self::exactly(3))->method('setLogger')->willReturnCallback(function ($logger) use(&$expectedLoggers) { + $expectedLoggers[] = $logger; + }); + $clientMock->expects(self::once())->method('setConfig')->willReturn($clientMock); + + $apiClient->setApiClient($clientMock); + self::assertSame($expectedLoggers[0], $logger); + + $apiClient->setLogger($wrapped); + $apiClient->setLogger(function ($level, $log, $context = array()) use ($wrapped) { + $wrapped->log($level, $log, $context); + }); + } + + public function testDecodeInvalidData() + { + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects(self::any()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + '{"invalid":"json"', + array('http_code' => 200) + )); + $this->setExpectedException('YooKassa\Common\Exceptions\JsonException'); + + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->getPaymentInfo(Random::str(36)); + } + + public function testEncodeInvalidData() + { + $instance = new TestClient(); + + if (version_compare(PHP_VERSION, '5.5') >= 0) { + $value = array('test' => 'test', 'val' => null); + $value['val'] = &$value; + try { + $instance->encode($value); + self::fail('Exception not thrown'); + } catch (JsonException $e) { + self::assertEquals(JSON_ERROR_RECURSION, $e->getCode()); + self::assertEquals('Failed serialize json. Unknown error', $e->getMessage()); + } + + $value = array('test' => iconv('utf-8', 'windows-1251', 'абвгдеёжз')); + try { + $instance->encode($value); + self::fail('Exception not thrown'); + } catch (JsonException $e) { + self::assertEquals(JSON_ERROR_UTF8, $e->getCode()); + self::assertEquals('Failed serialize json. Malformed UTF-8 characters, possibly incorrectly encoded', + $e->getMessage()); + } + } else { + $value = array('test' => iconv('utf-8', 'windows-1251', 'абвгдеёжз')); + $decoded = json_decode(json_encode($value), true); + self::assertNotSame($decoded, $value); + } + } + + public function testCreatePaymentErrors() { + $payment = CreatePaymentRequest::builder() + ->setAmount(123) + ->setPaymentToken(Random::str(36)) + ->build(); + + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->once()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $this->getFixtures('createPaymentErrorsGeneralFixtures.json'), + array('http_code' => 200) + )); + + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->createPayment($payment); + + self::assertSame($curlClientStub, $apiClient->getApiClient()); + self::assertTrue($response instanceof CreatePaymentResponse); + self::assertEquals("canceled", $response->getStatus()); + self::assertEquals("general_decline", $response->getCancellationDetails()->getReason()); + } + + /** + * @throws ApiException + * @throws BadApiRequestException + * @throws ForbiddenException + * @throws InternalServerError + * @throws NotFoundException + * @throws ResponseProcessingException + * @throws TooManyRequestsException + * @throws UnauthorizedException + * @throws ApiConnectionException + * @throws AuthorizeException + */ + public function testCreateReceipt() + { + // Create Receipt via object + $receipt = $this->createReceiptViaObject(); + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->once()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $this->getFixtures('createReceiptFixtures.json'), + array('http_code' => 200) + )); + + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->createReceipt($receipt); + + self::assertSame($curlClientStub, $apiClient->getApiClient()); + self::assertTrue($response instanceof AbstractReceiptResponse); + + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->once()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + $this->getFixtures('createReceiptFixtures.json'), + array('http_code' => 200) + )); + + // Create Receipt via array + $receipt = $this->createReceiptViaArray(); + $apiClient = new Client(); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->createReceipt($receipt, 123); + + self::assertSame($curlClientStub, $apiClient->getApiClient()); + self::assertTrue($response instanceof AbstractReceiptResponse); + + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->any()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + '{"type":"error","code":"request_accepted","retry_after":1800}', + array('http_code' => 202) + )); + + try { + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->createReceipt($receipt, 123); + self::fail('Исключение не было выброшено'); + } catch (ApiException $e) { + self::assertInstanceOf('YooKassa\Common\Exceptions\ResponseProcessingException', $e); + return; + } + + $curlClientStub = $this->getCurlClientStub(); + $curlClientStub + ->expects($this->any()) + ->method('sendRequest') + ->willReturn(array( + array('Header-Name' => 'HeaderValue'), + '{"type":"error","code":"request_accepted"}', + array('http_code' => 202) + )); + + try { + $apiClient->setRetryTimeout(0); + $response = $apiClient + ->setApiClient($curlClientStub) + ->setAuth('shopId', 'shopPassword') + ->createReceipt($receipt, 123); + self::fail('Исключение не было выброшено'); + } catch (ResponseProcessingException $e) { + self::assertEquals(Client::DEFAULT_DELAY, $e->retryAfter); + return; + } + } + + /** + * @return array + */ + private function createReceiptViaArray() + { + return array( + 'customer' => array( + 'full_name' => 'Иванов Иван Иванович', + 'inn' => '6321341814', + 'email' => 'johndoe@yoomoney.ru', + 'phone' => '79000000000' + ), + 'items' => array( + array( + 'description' => 'string', + 'quantity' => 1, + 'amount' => array( + 'value' => '10.00', + 'currency' => 'RUB' + ), + 'vat_code' => 1, + 'payment_subject' => 'commodity', + 'payment_mode' => 'full_prepayment', + 'product_code' => '00 00 00 01 00 21 FA 41 00 23 05 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12 00 AB 00', + 'country_of_origin_code' => 'RU', + 'customs_declaration_number' => '10714040/140917/0090376', + 'excise' => '20.00' + ) + ), + 'tax_system_code' => 1, + 'type' => 'payment', + 'send' => true, + 'settlements' => array( + array( + 'type' => 'cashless', + 'amount' => array( + 'value' => '10.00', + 'currency' => 'RUB' + ) + ) + ), + 'payment_id' => '1da5c87d-0984-50e8-a7f3-8de646dd9ec9' + ); + } + + /** + * @return CreatePostReceiptRequest + */ + private function createReceiptViaObject() + { + $customer = new ReceiptCustomer(array( + 'full_name' => 'Иванов Иван Иванович', + 'inn' => '6321341814', + 'email' => 'johndoe@yoomoney.ru', + 'phone' => '79000000000' + )); + $settlement = new Settlement(array( + 'type' => 'cashless', + 'amount' => array( + 'value' => '10.00', + 'currency' => 'RUB' + ) + )); + $receiptItem = new ReceiptItem(array( + 'description' => 'string', + 'quantity' => 1, + 'amount' => array( + 'value' => '10.00', + 'currency' => 'RUB' + ), + 'vat_code' => 1, + 'payment_subject' => 'commodity', + 'payment_mode' => 'full_prepayment', + 'product_code' => '00 00 00 01 00 21 FA 41 00 23 05 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12 00 AB 00', + 'country_of_origin_code' => 'RU', + 'customs_declaration_number' => '10714040/140917/0090376', + 'excise' => '20.00' + )); + + return CreatePostReceiptRequest::builder() + ->setCustomer($customer) + ->setType(ReceiptType::PAYMENT) + ->setObjectId('1da5c87d-0984-50e8-a7f3-8de646dd9ec9') + ->setSend(true) + ->setSettlements(array($settlement)) + ->setOnBehalfOf('545665') + ->setItems(array($receiptItem)) + ->build(); + } + + /** + * @return PHPUnit_Framework_MockObject_MockObject + */ + public function getCurlClientStub() + { + $clientStub = $this->getMockBuilder('YooKassa\Client\CurlClient') + ->setMethods(array('sendRequest')) + ->getMock(); + + return $clientStub; + } + + public function errorResponseDataProvider() + { + return array( + array(NotFoundException::HTTP_CODE, '{}', 'YooKassa\Common\Exceptions\NotFoundException'), + array(BadApiRequestException::HTTP_CODE, '{}', 'YooKassa\Common\Exceptions\BadApiRequestException'), + array(BadApiRequestException::HTTP_CODE, '{}', 'YooKassa\Common\Exceptions\BadApiRequestException'), + array(ForbiddenException::HTTP_CODE, '{}', 'YooKassa\Common\Exceptions\ForbiddenException'), + array(UnauthorizedException::HTTP_CODE, '{}', 'YooKassa\Common\Exceptions\UnauthorizedException'), + array(TooManyRequestsException::HTTP_CODE, '{}', 'YooKassa\Common\Exceptions\TooManyRequestsException'), + ); + } + + /** + * @return bool|string + */ + private function getFixtures($fileName) + { + return file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . 'fixtures' . DIRECTORY_SEPARATOR . $fileName); + } +} + +class ArrayLogger +{ + private $lastLog; + + public function log($level, $message, $context) + { + $this->lastLog = array($level, $message, $context); + } + + public function getLastLog() + { + return $this->lastLog; + } +} + +class TestClient extends Client +{ + public function encode($data) + { + $refl = new ReflectionMethod($this, 'encodeData'); + $refl->setAccessible(true); + return $refl->invoke($this, $data); + } +} \ No newline at end of file diff --git a/tests/Client/CurlClientTest.php b/tests/Client/CurlClientTest.php new file mode 100644 index 00000000..82675858 --- /dev/null +++ b/tests/Client/CurlClientTest.php @@ -0,0 +1,91 @@ +setConnectionTimeout(10); + $this->assertEquals(10, $client->getConnectionTimeout()); + } + + public function testTimeout() + { + $client = new CurlClient(); + $client->setTimeout(10); + $this->assertEquals(10, $client->getTimeout()); + } + + public function testProxy() + { + $client = new CurlClient(); + $client->setProxy('proxy_url:8889'); + $this->assertEquals('proxy_url:8889', $client->getProxy()); + } + + /** + * @dataProvider curlErrorCodeProvider + * @expectedException \YooKassa\Common\Exceptions\ApiConnectionException + */ + public function testHandleCurlError($error, $errn) + { + $client = new CurlClient(); + $reflector = new \ReflectionClass('\YooKassa\Client\CurlClient'); + $method = $reflector->getMethod('handleCurlError'); + $method->setAccessible(true); + $method->invokeArgs($client, array($error, $errn)); + } + + public function testConfig() + { + $config = array('url' => 'test:url'); + $client = new CurlClient(); + $client->setConfig($config); + $this->assertEquals($config, $client->getConfig()); + } + + public function testCloseConnection() + { + $wrapped = new \Tests\YooKassa\Client\ArrayLogger(); + $logger = new \YooKassa\Common\LoggerWrapper($wrapped); + $curlClientMock = $this->getMockBuilder('YooKassa\Client\CurlClient') + ->setMethods(array('closeCurlConnection', 'sendRequest')) + ->getMock(); + $curlClientMock->setLogger($logger); + $curlClientMock->setConfig(array('url' => 'test:url')); + $curlClientMock->setKeepAlive(false); + $curlClientMock->setShopId(123); + $curlClientMock->setShopPassword(234); + $curlClientMock->expects($this->once())->method('sendRequest')->willReturn(array( + array('Header-Name' => 'HeaderValue'), + '{body:sample}', + array('http_code' => 200), + )); + $curlClientMock->expects($this->once())->method('closeCurlConnection'); + $curlClientMock->call('', HttpVerb::HEAD, array('queryParam' => 'value'), 'testBodyValue', + array('testHeader' => 'testValue')); + } + + public function testAuthorizeException() + { + $this->setExpectedException('YooKassa\Common\Exceptions\AuthorizeException'); + $client = new CurlClient(); + $client->call('', HttpVerb::HEAD, array('queryParam' => 'value'), array('httpBody' => 'testValue'), + array('testHeader' => 'testValue')); + } + + public function curlErrorCodeProvider() + { + return array( + array('error message', CURLE_SSL_CACERT), + array('error message', CURLE_COULDNT_CONNECT), + array('error message', 0), + ); + } +} diff --git a/tests/Client/UserAgentTest.php b/tests/Client/UserAgentTest.php new file mode 100644 index 00000000..b7532ec2 --- /dev/null +++ b/tests/Client/UserAgentTest.php @@ -0,0 +1,122 @@ +getMethod('setOs'); + $method->setAccessible(true); + $method->invokeArgs($agent, array('name' => 'CentOS', 'version' => '6.7')); + $method = $reflector->getMethod('setPhp'); + $method->setAccessible(true); + $method->invokeArgs($agent, array('name' => 'PHP', 'version' => '5.4.45')); + $method = $reflector->getMethod('setSdk'); + $method->setAccessible(true); + $method->invokeArgs($agent, array('name' => 'YooKassa.PHP', 'version' => '1.4.1')); + $agent->setCms('Wordpress','2.0.4'); + $agent->setModule('Woocommerce','1.2.3'); + $this->assertEquals('CentOS/6.7 PHP/5.4.45 Wordpress/2.0.4 Woocommerce/1.2.3 YooKassa.PHP/1.4.1', $agent->getHeaderString()); + } + + /** + * @throws ReflectionException + */ + public function testSetGetOs() + { + $agent = new UserAgent(); + $reflector = new ReflectionClass('\YooKassa\Client\UserAgent'); + $method = $reflector->getMethod('setOs'); + $method->setAccessible(true); + $method->invokeArgs($agent, array('name' => 'CentOS', 'version' => '6.7')); + $this->assertEquals('CentOS/6.7', $agent->getOs()); + } + + /** + * @throws ReflectionException + */ + public function testSetGetPhp() + { + $agent = new UserAgent(); + $reflector = new ReflectionClass('\YooKassa\Client\UserAgent'); + $method = $reflector->getMethod('setPhp'); + $method->setAccessible(true); + $method->invokeArgs($agent, array('name' => 'PHP', 'version' => '5.4.45')); + $this->assertEquals('PHP/5.4.45', $agent->getPhp()); + } + + public function testSetGetFramework() + { + $agent = new UserAgent(); + $agent->setFramework('Yii', '2.4.1'); + $this->assertEquals('Yii/2.4.1', $agent->getFramework()); + } + + public function testSetGetCms() + { + $agent = new UserAgent(); + $agent->setCms('Wordpress', '2.0.4'); + $this->assertEquals('Wordpress/2.0.4', $agent->getCms()); + } + + public function testSetGetModule() + { + $agent = new UserAgent(); + $agent->setModule('Woocommerce', '1.2.3'); + $this->assertEquals('Woocommerce/1.2.3', $agent->getModule()); + } + + /** + * @throws ReflectionException + */ + public function testSetGetSdk() + { + $agent = new UserAgent(); + $reflector = new ReflectionClass('\YooKassa\Client\UserAgent'); + $method = $reflector->getMethod('setSdk'); + $method->setAccessible(true); + $method->invokeArgs($agent, array('name' => 'YooKassa.PHP', 'version' => '1.4.1')); + $this->assertEquals('YooKassa.PHP/1.4.1', $agent->getSdk()); + } + + /** + * @dataProvider validVersionDataProvider + * @param $input + * @param $output + */ + public function testCreateVersion($input, $output) + { + $agent = new UserAgent(); + $this->assertEquals($agent->createVersion($input['name'], $input['version']), $output); + } + + public function validVersionDataProvider() + { + return array( + array( + array('name' => 'PHP ', 'version' => '1.2.3 '), + 'PHP/1.2.3' + ), + array( + array('name' => 'Ubuntu GNU/Linux', 'version' => ' 14.04'), + 'Ubuntu.GNU.Linux/14.04' + ), + array( + array('name' => 'YooKassa PHP', 'version' => '1/4.3'), + 'YooKassa.PHP/1.4.3' + ), + ); + } +} diff --git a/tests/Client/fixtures/cancelPaymentFixtures.json b/tests/Client/fixtures/cancelPaymentFixtures.json new file mode 100644 index 00000000..b4e05256 --- /dev/null +++ b/tests/Client/fixtures/cancelPaymentFixtures.json @@ -0,0 +1,35 @@ +{ + "id": "1da5c87d-0984-50e8-a7f3-8de646dd9ec9", + "status": "succeeded", + "error": { + "code": "insufficient_funds", + "description": "Съешь еще этих мягких французских булок" + }, + "recipient": { + "account_id": "123", + "gateway_id": "456" + }, + "amount": { + "value": "10.00", + "currency": "RUB" + }, + "payment_method": { + "id": "1da5c87d-0984-50e8-a7f3-8de646dd9ec9", + "saved": true, + "title": "Основная карта", + "type": "qiwi" + }, + "created_at": "2015-11-19T17:05:07+03:00", + "captured_at": "2015-11-19T17:05:31+03:00", + "confirmation": { + "type": "redirect" + }, + "refunded_amount": { + "value": "10.00", + "currency": "RUB" + }, + "paid": true, + "refundable": true, + "receipt_registration": "succeeded", + "metadata": {} +} \ No newline at end of file diff --git a/tests/Client/fixtures/capturePaymentFixtures.json b/tests/Client/fixtures/capturePaymentFixtures.json new file mode 100644 index 00000000..680973ad --- /dev/null +++ b/tests/Client/fixtures/capturePaymentFixtures.json @@ -0,0 +1,39 @@ +{ + "id": "1da5c87d-0984-50e8-a7f3-8de646dd9ec9", + "status": "succeeded", + "error": { + "code": "insufficient_funds", + "description": "Съешь еще этих мягких французских булок" + }, + "recipient": { + "account_id": "123", + "gateway_id": "456" + }, + "amount": { + "value": "10.00", + "currency": "RUB" + }, + "payment_method": { + "id": "1da5c87d-0984-50e8-a7f3-8de646dd9ec9", + "saved": true, + "title": "Основная карта", + "type": "bank_card", + "last4": "3563", + "expiry_year": "2023", + "expiry_month": "05", + "card_type": "MasterCard" + }, + "created_at": "2015-11-19T17:05:07+03:00", + "captured_at": "2015-11-19T17:05:31+03:00", + "confirmation": { + "type": "embedded" + }, + "refunded_amount": { + "value": "10.00", + "currency": "RUB" + }, + "paid": true, + "refundable": true, + "receipt_registration": "succeeded", + "metadata": {} +} \ No newline at end of file diff --git a/tests/Client/fixtures/createPaymentErrorsGeneralFixtures.json b/tests/Client/fixtures/createPaymentErrorsGeneralFixtures.json new file mode 100644 index 00000000..8a9ff3c3 --- /dev/null +++ b/tests/Client/fixtures/createPaymentErrorsGeneralFixtures.json @@ -0,0 +1,34 @@ +{ + "id": "1da5c87d-0984-50e8-a7f3-8de646dd9ec9", + "status": "canceled", + "paid": false, + "refundable": false, + "amount": { + "value": "20.00", + "currency": "RUB" + }, + "created_at": "2018-07-17T11:14:53.131Z", + "metadata": {}, + "payment_method": { + "type": "bank_card", + "id": "1da5c87d-0984-50e8-a7f3-8de646dd9ec9", + "saved": false, + "card": { + "first6": "111111", + "last4": "1026", + "expiry_month": "12", + "expiry_year": "2022", + "card_type": "Unknown" + }, + "title": "Bank card *1026" + }, + "recipient": { + "account_id": "123", + "gateway_id": "456" + }, + "test": true, + "cancellation_details": { + "party": "yoo_money", + "reason": "general_decline" + } +} \ No newline at end of file diff --git a/tests/Client/fixtures/createPaymentFixtures.json b/tests/Client/fixtures/createPaymentFixtures.json new file mode 100644 index 00000000..8e9f60e1 --- /dev/null +++ b/tests/Client/fixtures/createPaymentFixtures.json @@ -0,0 +1,39 @@ +{ + "id": "1da5c87d-0984-50e8-a7f3-8de646dd9ec9", + "status": "succeeded", + "error": { + "code": "insufficient_funds", + "description": "Съешь еще этих мягких французских булок" + }, + "recipient": { + "account_id": "123", + "gateway_id": "456" + }, + "amount": { + "value": "10.00", + "currency": "RUB" + }, + "created_at": "2015-11-19T17:05:07+03:00", + "captured_at": "2015-11-19T17:05:31+03:00", + "payment_method": { + "type": "yoo_money", + "phone": "89990110101", + "account_number": "123456789123" + }, + "confirmation": { + "type": "redirect", + "locale": "ru_RU", + "enforce": true, + "return_url": "string", + "confirmation_url": "string" + }, + "refunded_amount": { + "value": "10.00", + "currency": "RUB" + }, + "paid": true, + "refundable": true, + "test": true, + "receipt_registration": "succeeded", + "metadata": {} +} \ No newline at end of file diff --git a/tests/Client/fixtures/createReceiptFixtures.json b/tests/Client/fixtures/createReceiptFixtures.json new file mode 100644 index 00000000..9c9adc84 --- /dev/null +++ b/tests/Client/fixtures/createReceiptFixtures.json @@ -0,0 +1,49 @@ +{ + "id": "rt_1da5c87d-0984-50e8-a7f3-8de646dd9ec9", + "type": "payment", + "payment_id": "215d8da0-000f-50be-b000-0003308c89be", + "status": "pending", + "items": [ + { + "description": "Мобильный телефон Хувей", + "quantity": "1.00", + "amount": { + "value": "14000.00", + "currency": "RUB" + }, + "vat_code": "2", + "payment_mode": "full_payment", + "payment_subject": "commodity", + "country_of_origin_code": "CN" + }, + { + "description": "Переносное зарядное устройство Хувей", + "quantity": "1.00", + "amount": { + "value": "1000.00", + "currency": "RUB" + }, + "vat_code": "2", + "payment_mode": "full_payment", + "payment_subject": "commodity", + "country_of_origin_code": "CN" + } + ], + "settlements": [ + { + "type": "prepayment", + "amount": { + "value": "8000.00", + "currency": "RUB" + } + }, + { + "type": "prepayment", + "amount": { + "value": "7000.00", + "currency": "RUB" + } + } + ], + "tax_system_code": 1 +} \ No newline at end of file diff --git a/tests/Client/fixtures/createRefundFixtures.json b/tests/Client/fixtures/createRefundFixtures.json new file mode 100644 index 00000000..7bb2abb4 --- /dev/null +++ b/tests/Client/fixtures/createRefundFixtures.json @@ -0,0 +1,17 @@ +{ + "id": "1ddd77af-0bd7-500d-895b-c475c55fdefc", + "payment_id": "1da5c87d-0984-50e8-a7f3-8de646dd9ec9", + "status": "succeeded", + "error": { + "code": "authorization_rejected", + "description": "Съешь еще этих мягких французских булок" + }, + "created_at": "2015-11-19T17:05:07+03:00", + "authorized_at": "2015-11-19T17:05:31+03:00", + "amount": { + "value": "10.00", + "currency": "RUB" + }, + "receipt_registered": "succeeded", + "description": "string" +} \ No newline at end of file diff --git a/tests/Client/fixtures/getPaymentsFixtures.json b/tests/Client/fixtures/getPaymentsFixtures.json new file mode 100644 index 00000000..261044ee --- /dev/null +++ b/tests/Client/fixtures/getPaymentsFixtures.json @@ -0,0 +1,52 @@ +{ + "items": [ + { + "id": "1da5c87d-0984-50e8-a7f3-8de646dd9ec9", + "status": "succeeded", + "error": { + "code": "insufficient_funds", + "description": "Съешь еще этих мягких французских булок" + }, + "recipient": { + "account_id": "123", + "gateway_id": "456" + }, + "amount": { + "value": "10.00", + "currency": "RUB" + }, + "reference_id": "719505144571", + "created_at": "2015-11-19T17:05:07+03:00", + "captured_at": "2015-11-19T17:05:31+03:00", + "payment_method": { + "type": "yoo_money", + "phone": "79990110101", + "account_number": "123456789123" + }, + "confirmation": { + "type": "redirect", + "enforce": true, + "return_url": "string", + "confirmation_url": "string" + }, + "charge": { + "value": "10.00", + "currency": "RUB" + }, + "income": { + "value": "10.00", + "currency": "RUB" + }, + "refunded_amount": { + "value": "10.00", + "currency": "RUB" + }, + "paid": true, + "refundable": true, + "test": true, + "receipt_registration": "succeeded", + "metadata": {} + } + ], + "next_page": "01234567890ABCDEF" +} \ No newline at end of file diff --git a/tests/Client/fixtures/paymentInfoFixtures.json b/tests/Client/fixtures/paymentInfoFixtures.json new file mode 100644 index 00000000..5ab54741 --- /dev/null +++ b/tests/Client/fixtures/paymentInfoFixtures.json @@ -0,0 +1,36 @@ +{ + "id": "1da5c87d-0984-50e8-a7f3-8de646dd9ec9", + "status": "succeeded", + "error": { + "code": "insufficient_funds", + "description": "Съешь еще этих мягких французских булок" + }, + "recipient": { + "account_id": "123", + "gateway_id": "456" + }, + "amount": { + "value": "10.00", + "currency": "RUB" + }, + "payment_method": { + "id": "1da5c87d-0984-50e8-a7f3-8de646dd9ec9", + "saved": true, + "title": "Основная карта", + "type": "qiwi" + }, + "created_at": "2015-11-19T17:05:07+03:00", + "captured_at": "2015-11-19T17:05:31+03:00", + "confirmation": { + "type": "external" + }, + "refunded_amount": { + "value": "10.00", + "currency": "RUB" + }, + "paid": true, + "refundable": true, + "test": true, + "receipt_registration": "succeeded", + "metadata": {} +} \ No newline at end of file diff --git a/tests/Client/fixtures/paymentOptionsFixtures.json b/tests/Client/fixtures/paymentOptionsFixtures.json new file mode 100644 index 00000000..ee06a0e6 --- /dev/null +++ b/tests/Client/fixtures/paymentOptionsFixtures.json @@ -0,0 +1,19 @@ +{ + "items": [ + { + "payment_method_type": "yoo_money", + "confirmation_types": [ + "redirect" + ], + "charge": { + "value": "10.00", + "currency": "RUB" + }, + "fee": { + "value": "10.00", + "currency": "RUB" + }, + "extra_fee": true + } + ] +} \ No newline at end of file diff --git a/tests/Client/fixtures/refundInfoFixtures.json b/tests/Client/fixtures/refundInfoFixtures.json new file mode 100644 index 00000000..7bb2abb4 --- /dev/null +++ b/tests/Client/fixtures/refundInfoFixtures.json @@ -0,0 +1,17 @@ +{ + "id": "1ddd77af-0bd7-500d-895b-c475c55fdefc", + "payment_id": "1da5c87d-0984-50e8-a7f3-8de646dd9ec9", + "status": "succeeded", + "error": { + "code": "authorization_rejected", + "description": "Съешь еще этих мягких французских булок" + }, + "created_at": "2015-11-19T17:05:07+03:00", + "authorized_at": "2015-11-19T17:05:31+03:00", + "amount": { + "value": "10.00", + "currency": "RUB" + }, + "receipt_registered": "succeeded", + "description": "string" +} \ No newline at end of file diff --git a/tests/Client/fixtures/refundsInfoFixtures.json b/tests/Client/fixtures/refundsInfoFixtures.json new file mode 100644 index 00000000..06f7d5ac --- /dev/null +++ b/tests/Client/fixtures/refundsInfoFixtures.json @@ -0,0 +1,27 @@ +{ + "items": [ + { + "id": "1ddd77af-0bd7-500d-895b-c475c55fdefc", + "payment_id": "1da5c87d-0984-50e8-a7f3-8de646dd9ec9", + "status": "succeeded", + "error": { + "code": "authorization_rejected", + "description": "Съешь еще этих мягких французских булок" + }, + "created_at": "2015-11-19T17:05:07+03:00", + "authorized_at": "2015-11-19T17:05:31+03:00", + "amount": { + "value": "10.00", + "currency": "RUB" + }, + "receipt_registered": "succeeded", + "description": "string", + "requestor": { + "type": "RequestorThirdPartyService", + "client_id": "12345", + "client_name": "test" + } + } + ], + "next_page": "01234567890ABCDEF" +} \ No newline at end of file diff --git a/tests/Common/AbstractEnumTest.php b/tests/Common/AbstractEnumTest.php new file mode 100644 index 00000000..90ff1aab --- /dev/null +++ b/tests/Common/AbstractEnumTest.php @@ -0,0 +1,67 @@ + true, + self::ENUM_VALUE_2 => true, + self::ENUM_DISABLED_VALUE_1 => false, + self::ENUM_DISABLED_VALUE_2 => false, + ); +} \ No newline at end of file diff --git a/tests/Common/AbstractObjectTest.php b/tests/Common/AbstractObjectTest.php new file mode 100644 index 00000000..45e801fc --- /dev/null +++ b/tests/Common/AbstractObjectTest.php @@ -0,0 +1,236 @@ +getTestInstance(); + if ($exists) { + self::assertTrue($instance->offsetExists($value)); + self::assertTrue(isset($instance[$value])); + self::assertTrue(isset($instance->{$value})); + } else { + self::assertFalse($instance->offsetExists($value)); + self::assertFalse(isset($instance[$value])); + self::assertFalse(isset($instance->{$value})); + + $instance->offsetSet($value, $value); + self::assertTrue($instance->offsetExists($value)); + self::assertTrue(isset($instance[$value])); + self::assertTrue(isset($instance->{$value})); + } + } + + /** + * @dataProvider offsetDataProvider + * @param $value + */ + public function testOffsetGet($value) + { + $instance = $this->getTestInstance(); + + $tmp = $instance->offsetGet($value); + self::assertNull($tmp); + $tmp = $instance[$value]; + self::assertNull($tmp); + $tmp = $instance->{$value}; + self::assertNull($tmp); + + $instance->offsetSet($value, $value); + + $tmp = $instance->offsetGet($value); + self::assertEquals($value, $tmp); + $tmp = $instance[$value]; + self::assertEquals($value, $tmp); + $tmp = $instance->{$value}; + self::assertEquals($value, $tmp); + } + + /** + * @dataProvider offsetDataProvider + * @param $value + * @param $exists + */ + public function testOffsetUnset($value, $exists) + { + $instance = $this->getTestInstance(); + if ($exists) { + self::assertTrue($instance->offsetExists($value)); + $instance->offsetUnset($value); + self::assertTrue($instance->offsetExists($value)); + unset($instance[$value]); + self::assertTrue($instance->offsetExists($value)); + unset($instance->{$value}); + self::assertTrue($instance->offsetExists($value)); + } else { + self::assertFalse($instance->offsetExists($value)); + $instance->offsetUnset($value); + self::assertFalse($instance->offsetExists($value)); + unset($instance[$value]); + self::assertFalse($instance->offsetExists($value)); + unset($instance->{$value}); + self::assertFalse($instance->offsetExists($value)); + + $instance->{$value} = $value; + self::assertTrue($instance->offsetExists($value)); + $instance->offsetUnset($value); + self::assertFalse($instance->offsetExists($value)); + + $instance->{$value} = $value; + self::assertTrue($instance->offsetExists($value)); + unset($instance[$value]); + self::assertFalse($instance->offsetExists($value)); + + $instance->{$value} = $value; + self::assertTrue($instance->offsetExists($value)); + unset($instance->{$value}); + self::assertFalse($instance->offsetExists($value)); + } + } + + public function offsetDataProvider() + { + return array( + array('property', true), + array('propertyCamelCase', true), + array('property_camel_case', true), + array('Property', true), + array('PropertyCamelCase', true), + array('Property_Camel_Case', true), + array('not_exists', false), + ); + } + + public function testJsonSerialize() + { + $instance = $this->getTestInstance(); + + $data = $instance->jsonSerialize(); + $expected = array(); + self::assertEquals($expected, $data); + + $instance->setProperty('propertyValue'); + $data = $instance->jsonSerialize(); + $expected = array( + 'property' => 'propertyValue', + ); + self::assertEquals($expected, $data); + + $instance->setPropertyCamelCase($this->getTestInstance()); + $data = $instance->jsonSerialize(); + $expected = array( + 'property' => 'propertyValue', + 'property_camel_case' => array(), + ); + self::assertEquals($expected, $data); + + $instance->getPropertyCamelCase()->setProperty(array('test', 1, 2, 3)); + $data = $instance->jsonSerialize(); + $expected = array( + 'property' => 'propertyValue', + 'property_camel_case' => array( + 'property' => array('test', 1, 2, 3), + ), + ); + self::assertEquals($expected, $data); + + $date = new \DateTime(); + $instance->getPropertyCamelCase()->setPropertyCamelCase($date); + $data = $instance->jsonSerialize(); + $expected = array( + 'property' => 'propertyValue', + 'property_camel_case' => array( + 'property' => array('test', 1, 2, 3), + 'property_camel_case' => $date->format(DATE_ATOM), + ), + ); + self::assertEquals($expected, $data); + + $instance->getPropertyCamelCase()->unknown_obj = $this->getTestInstance(); + $data = $instance->jsonSerialize(); + $expected = array( + 'property' => 'propertyValue', + 'property_camel_case' => array( + 'property' => array('test', 1, 2, 3), + 'property_camel_case' => $date->format(DATE_ATOM), + 'unknown_obj' => array(), + ), + ); + self::assertEquals($expected, $data); + + $instance->unknown_property = true; + $data = $instance->jsonSerialize(); + $expected['unknown_property'] = true; + self::assertEquals($expected, $data); + + $instance->unknown_array = array(false); + $data = $instance->jsonSerialize(); + $expected['unknown_array'] = array(false); + self::assertEquals($expected, $data); + + $instance->unknown_date = $date; + $data = $instance->jsonSerialize(); + $expected['unknown_date'] = $date->format(DATE_ATOM); + self::assertEquals($expected, $data); + + $obj = new \stdClass(); + $obj->test = 'test1'; + $instance->unknown_obj = $obj; + $data = $instance->jsonSerialize(); + $expected['unknown_obj'] = $obj; + self::assertEquals($expected, $data); + + $obj = new \stdClass(); + $obj->test = 'test2'; + $instance->property_camel_case = $obj; + $data = $instance->jsonSerialize(); + $expected['property_camel_case'] = $obj; + self::assertEquals($expected, $data); + + $instance->property_camel_case = null; + $data = $instance->jsonSerialize(); + unset($expected['property_camel_case']); + self::assertEquals($expected, $data); + } +} + +class TestAbstractObject extends AbstractObject +{ + private $_property; + private $_anotherProperty; + + public function getProperty() + { + return $this->_property; + } + + public function setProperty($value) + { + $this->_property = $value; + } + + public function getPropertyCamelCase() + { + return $this->_anotherProperty; + } + + public function setPropertyCamelCase($value) + { + $this->_anotherProperty = $value; + } +} \ No newline at end of file diff --git a/tests/Common/AbstractRequestBuilderTest.php b/tests/Common/AbstractRequestBuilderTest.php new file mode 100644 index 00000000..c25f6cf9 --- /dev/null +++ b/tests/Common/AbstractRequestBuilderTest.php @@ -0,0 +1,139 @@ +build(array()); + } catch (InvalidRequestException $e) { + $request = $builder->build(array( + 'isValid' => true, + )); + self::assertTrue($request->isValid()); + + $mess = 'test message'; + try { + $builder->build(array( + 'throwException' => new \Exception($mess), + )); + } catch (\Exception $e) { + self::assertEquals($mess, $e->getPrevious()->getMessage()); + return; + } + self::fail('Exception not thrown in setThrowException method'); + return; + } + self::fail('Exception not thrown in build method'); + } + + public function testSetOptions() + { + $builder = new TestAbstractRequestBuilder(); + + $builder->setOptions(array()); + try { + $builder->build(); + } catch (InvalidRequestException $e) { + $builder->setOptions(array( + 'is_valid' => true, + )); + self::assertTrue($builder->build()->isValid()); + + try { + $builder->setOptions('test'); + } catch (\Exception $e) { + self::assertTrue($e instanceof \InvalidArgumentException); + return; + } + self::fail('Exception not thrown in setOptions method'); + return; + } + self::fail('Exception not thrown in build method'); + } +} + +class TestAbstractRequestBuilder extends AbstractRequestBuilder +{ + /** + * Инициализирует пустой запрос + * @return TestAbstractRequestClass Инстанс запроса который будем собирать + */ + protected function initCurrentObject() + { + return new TestAbstractRequestClass(); + } + + public function setIsValid($value) + { + $this->currentObject->setIsValid($value); + return $this; + } + + /** + * @param \Exception $e + * @return TestAbstractRequestBuilder + * @throws \Exception + */ + public function setThrowException(\Exception $e) + { + $this->currentObject->setThrowException($e); + return $this; + } +} + +class TestAbstractRequestClass extends AbstractRequest +{ + private $valid = false; + + /** + * @var \Exception|null + */ + private $exception = null; + + /** + * @param \Exception $e + * @throws \Exception + */ + public function setThrowException(\Exception $e) + { + $this->exception = $e; + } + + /** + * @param bool $value + */ + public function setIsValid($value) + { + $this->valid = $value ? true : false; + } + + /** + * @return bool + */ + public function isValid() + { + return $this->valid; + } + + /** + * Валидирует текущий запрос, проверяет все ли нужные свойства установлены + * @return bool True если запрос валиден, false если нет + */ + public function validate() + { + if ($this->exception !== null) { + $this->setValidationError($this->exception->getMessage()); + throw $this->exception; + } + return $this->valid; + } +} \ No newline at end of file diff --git a/tests/Common/Exceptions/AbstractApiRequestExceptionTest.php b/tests/Common/Exceptions/AbstractApiRequestExceptionTest.php new file mode 100644 index 00000000..aef0bfab --- /dev/null +++ b/tests/Common/Exceptions/AbstractApiRequestExceptionTest.php @@ -0,0 +1,178 @@ +getTestInstance('', 0, array(), $body); + $tmp = json_decode($body, true); + if (empty($tmp['description'])) { + self::assertEquals('', $instance->getMessage()); + } else { + self::assertEquals($tmp['description'] . '.', $instance->getMessage()); + } + } + + public function descriptionDataProvider() + { + return array( + array('{}'), + array('{"description":"test"}'), + array('{"description":"У попа была собака"}'), + ); + } + + /** + * @dataProvider codeDataProvider + * @param string $body + */ + public function testCode($body) + { + $instance = $this->getTestInstance('', 0, array(), $body); + $tmp = json_decode($body, true); + if (empty($tmp['code'])) { + self::assertEquals('', $instance->getMessage()); + } else { + self::assertEquals('Error code: ' . $tmp['code'] . '.', $instance->getMessage()); + } + } + + public function codeDataProvider() + { + return array( + array('{}'), + array('{"code":"123"}'), + array('{"code":"server_error"}'), + ); + } + + /** + * @dataProvider parameterDataProvider + * @param string $body + */ + public function testParameter($body) + { + $instance = $this->getTestInstance('', 0, array(), $body); + $tmp = json_decode($body, true); + if (empty($tmp['parameter'])) { + self::assertEquals('', $instance->getMessage()); + } else { + self::assertEquals('Parameter name: ' . $tmp['parameter'] . '.', $instance->getMessage()); + } + } + + public function parameterDataProvider() + { + return array( + array('{}'), + array('{"parameter":"parameter_name"}'), + array('{"parameter":null}'), + ); + } + + /** + * @dataProvider retryAfterDataProvider + * @param string $body + */ + public function testRetryAfter($body) + { + $instance = $this->getTestInstance('', 0, array(), $body); + $tmp = json_decode($body, true); + if (empty($tmp['retry_after'])) { + self::assertNull($instance->retryAfter); + } else { + self::assertEquals($tmp['retry_after'], $instance->retryAfter); + } + } + + public function retryAfterDataProvider() + { + return array( + array('{}'), + array('{"retry_after":-20}'), + array('{"retry_after":123}'), + ); + } + + /** + * @dataProvider typeDataProvider + * @param string $body + */ + public function testType($body) + { + $instance = $this->getTestInstance('', 0, array(), $body); + $tmp = json_decode($body, true); + if (empty($tmp['type'])) { + self::assertNull($instance->type); + } else { + self::assertEquals($tmp['type'], $instance->type); + } + } + + public function typeDataProvider() + { + return array( + array('{}'), + array('{"type":"server_error"}'), + array('{"type":"error"}'), + ); + } + + /** + * @dataProvider messageDataProvider + * @param $body + */ + public function testMessage($body) + { + $instance = $this->getTestInstance('', 0, array(), $body); + + $tmp = json_decode($body, true); + $message = ''; + if (!empty($tmp['description'])) { + $message = $tmp['description'] . '. '; + } + if (!empty($tmp['code'])) { + $message .= 'Error code: ' . $tmp['code'] . '. '; + } + if (!empty($tmp['parameter'])) { + $message .= 'Parameter name: ' . $tmp['parameter'] . '. '; + } + self::assertEquals(trim($message), $instance->getMessage()); + + if (empty($tmp['retry_after'])) { + self::assertNull($instance->retryAfter); + } else { + self::assertEquals($tmp['retry_after'], $instance->retryAfter); + } + if (empty($tmp['type'])) { + self::assertNull($instance->type); + } else { + self::assertEquals($tmp['type'], $instance->type); + } + } + + public function messageDataProvider() + { + return array( + array('{}'), + array('{"code":"server_error","description":"Internal server error"}'), + array('{"code":"server_error","description":"Invalid parameter value","parameter":"shop_id"}'), + array('{"code":"server_error","description":"Invalid parameter value","parameter":"shop_id","type":"test"}'), + array('{"code":"server_error","description":"Invalid parameter value","parameter":"shop_id","retry_after":333}'), + ); + } + + abstract public function expectedHttpCode(); + + public function testExceptionCode() + { + $instance = $this->getTestInstance(); + self::assertEquals($this->expectedHttpCode(), $instance->getCode()); + } +} diff --git a/tests/Common/Exceptions/ApiExceptionTest.php b/tests/Common/Exceptions/ApiExceptionTest.php new file mode 100644 index 00000000..b1efc55b --- /dev/null +++ b/tests/Common/Exceptions/ApiExceptionTest.php @@ -0,0 +1,74 @@ +getTestInstance('', 0, $headers); + self::assertEquals($headers, $instance->getResponseHeaders()); + } + + public function responseHeadersDataProvider() + { + return array( + array( + array(), + ), + array( + array('HTTP/1.1 200 Ok'), + ), + array( + array( + 'HTTP/1.1 200 Ok', + 'Content-length: 0', + ), + ), + array( + array( + 'HTTP/1.1 200 Ok', + 'Content-length: 0', + 'Connection: close', + ), + ), + ); + } + + /** + * @dataProvider responseBodyDataProvider + * @param string $body + */ + public function testGetResponseBody($body) + { + $instance = $this->getTestInstance('', 0, array(), $body); + self::assertEquals($body, $instance->getResponseBody()); + } + + public function responseBodyDataProvider() + { + return array( + array( + '', + ), + array( + '{"success":true}', + ), + array( + '', + ), + ); + } +} diff --git a/tests/Common/Exceptions/AuthorizeExceptionTest.php b/tests/Common/Exceptions/AuthorizeExceptionTest.php new file mode 100644 index 00000000..a1fb5c4f --- /dev/null +++ b/tests/Common/Exceptions/AuthorizeExceptionTest.php @@ -0,0 +1,13 @@ +getTestInstance($name); + + self::assertEquals($excepted, $instance->getMessage()); + } + + public function messageDataProvider() + { + return array( + array("json", "json extension is not loaded!"), + array("curl", "curl extension is not loaded!"), + array("gd", "gd extension is not loaded!"), + ); + } +} \ No newline at end of file diff --git a/tests/Common/Exceptions/ForbiddenExceptionTest.php b/tests/Common/Exceptions/ForbiddenExceptionTest.php new file mode 100644 index 00000000..5a574df3 --- /dev/null +++ b/tests/Common/Exceptions/ForbiddenExceptionTest.php @@ -0,0 +1,18 @@ +getTestInstance('', $property); + self::assertEquals((string)$property, $instance->getProperty()); + } + + public function validPropertyDataProvider() + { + return array( + array(''), + array('property'), + array(new StringObject('property')), + ); + } +} diff --git a/tests/Common/Exceptions/InvalidPropertyValueExceptionTest.php b/tests/Common/Exceptions/InvalidPropertyValueExceptionTest.php new file mode 100644 index 00000000..e8e205b3 --- /dev/null +++ b/tests/Common/Exceptions/InvalidPropertyValueExceptionTest.php @@ -0,0 +1,39 @@ +getTestInstance('', '', $value); + if ($value !== null) { + self::assertEquals($value, $instance->getValue()); + } else { + self::assertNull($instance->getValue()); + } + } + + public function validValueDataProvider() + { + return array( + array(null), + array(''), + array('value'), + array(array('test')), + array(new \stdClass()), + array(new \DateTime()), + ); + } +} diff --git a/tests/Common/Exceptions/InvalidPropertyValueTypeExceptionTest.php b/tests/Common/Exceptions/InvalidPropertyValueTypeExceptionTest.php new file mode 100644 index 00000000..db74b3e3 --- /dev/null +++ b/tests/Common/Exceptions/InvalidPropertyValueTypeExceptionTest.php @@ -0,0 +1,49 @@ +getTestInstance('', '', $value); + self::assertEquals($type, $instance->getType()); + } + + public function validTypeDataProvider() + { + return array( + array(null, 'null'), + array('', 'string'), + array('value', 'string'), + array(array('test'), 'array'), + array(new \stdClass(), 'stdClass'), + array(new \DateTime(), 'DateTime'), + array(new InvalidPropertyException(), 'YooKassa\\Common\\Exceptions\\InvalidPropertyException'), + array(fopen(__FILE__, 'r'), 'resource'), + array(true, 'boolean'), + array(false, 'boolean'), + array(0, 'integer'), + array(0.01, 'double'), + ); + } +} diff --git a/tests/Common/Exceptions/InvalidRequestExceptionTest.php b/tests/Common/Exceptions/InvalidRequestExceptionTest.php new file mode 100644 index 00000000..c1e2baae --- /dev/null +++ b/tests/Common/Exceptions/InvalidRequestExceptionTest.php @@ -0,0 +1,39 @@ +getRequestObject()); + $message = 'Failed to build request "' . get_class($requestObject) . '": ""'; + self::assertEquals($message, $instance->getMessage()); + } else { + self::assertNull($instance->getRequestObject()); + self::assertEquals($requestObject, $instance->getMessage()); + } + } + + public function requestObjectDataProvider() + { + return array( + array(''), + array('test'), + array(new PaymentsRequest()), + array(new CreatePaymentRequest()), + ); + } +} diff --git a/tests/Common/Exceptions/JsonExceptionTest.php b/tests/Common/Exceptions/JsonExceptionTest.php new file mode 100644 index 00000000..ecf11b58 --- /dev/null +++ b/tests/Common/Exceptions/JsonExceptionTest.php @@ -0,0 +1,36 @@ +getMessage()); + } + + public function messageDataProvider() + { + $result = array(); + foreach (JsonException::$errorLabels as $code => $message) { + $result[] = array($message, $code); + } + $result[] = array('Test error', -1); + return $result; + } +} diff --git a/tests/Common/Exceptions/NotFoundExceptionTest.php b/tests/Common/Exceptions/NotFoundExceptionTest.php new file mode 100644 index 00000000..978f7d49 --- /dev/null +++ b/tests/Common/Exceptions/NotFoundExceptionTest.php @@ -0,0 +1,18 @@ +getTestInstance('', 0, array(), $body); + $tmp = json_decode($body, true); + if (empty($tmp['description'])) { + self::assertEquals('', $instance->getMessage()); + } else { + self::assertEquals($tmp['description'].'.', $instance->getMessage()); + } + } + + public function descriptionDataProvider() + { + return array( + array('{}'), + array('{"description":"test"}'), + array('{"description":"У попа была собака"}'), + ); + } + + /** + * @dataProvider retryAfterDataProvider + * @param string $body + */ + public function testRetryAfter($body) + { + $instance = $this->getTestInstance('', 0, array(), $body); + $tmp = json_decode($body, true); + if (empty($tmp['retry_after'])) { + self::assertNull($instance->retryAfter); + } else { + self::assertEquals($tmp['retry_after'], $instance->retryAfter); + } + } + + public function retryAfterDataProvider() + { + return array( + array('{}'), + array('{"retry_after":-20}'), + array('{"retry_after":123}'), + ); + } + + /** + * @dataProvider typeDataProvider + * @param string $body + */ + public function testType($body) + { + $instance = $this->getTestInstance('', 0, array(), $body); + $tmp = json_decode($body, true); + if (empty($tmp['type'])) { + self::assertNull($instance->type); + } else { + self::assertEquals($tmp['type'], $instance->type); + } + } + + public function typeDataProvider() + { + return array( + array('{}'), + array('{"type":"server_error"}'), + array('{"type":"error"}'), + ); + } + + /** + * @dataProvider messageDataProvider + * @param $body + */ + public function testMessage($body) + { + $instance = $this->getTestInstance('', 0, array(), $body); + + $tmp = json_decode($body, true); + $message = ''; + if (!empty($tmp['description'])) { + $message = $tmp['description'].'.'; + } + self::assertEquals($message, $instance->getMessage()); + + if (empty($tmp['retry_after'])) { + self::assertNull($instance->retryAfter); + } else { + self::assertEquals($tmp['retry_after'], $instance->retryAfter); + } + if (empty($tmp['type'])) { + self::assertNull($instance->type); + } else { + self::assertEquals($tmp['type'], $instance->type); + } + } + + public function messageDataProvider() + { + return array( + array('{}'), + array('{"code":"server_error","description":"Internal server error"}'), + array('{"code":"server_error","description":"Invalid parameter value","parameter":"shop_id"}'), + array('{"code":"server_error","description":"Invalid parameter value","parameter":"shop_id","type":"test"}'), + array('{"code":"server_error","description":"Invalid parameter value","parameter":"shop_id","retry_after":333}'), + ); + } + + public function testExceptionCode() + { + $instance = $this->getTestInstance(); + self::assertEquals($this->expectedHttpCode(), $instance->getCode()); + } +} diff --git a/tests/Common/Exceptions/TooManyRequestsExceptionTest.php b/tests/Common/Exceptions/TooManyRequestsExceptionTest.php new file mode 100644 index 00000000..54e9c9c6 --- /dev/null +++ b/tests/Common/Exceptions/TooManyRequestsExceptionTest.php @@ -0,0 +1,18 @@ +isInterface()); + if (version_compare('5.4', PHP_VERSION) < 0) { + self::assertTrue($reflection->isInternal()); + } else { + self::assertTrue($reflection->isUserDefined()); + } + } +} \ No newline at end of file diff --git a/tests/Common/LoggerWrapperTest.php b/tests/Common/LoggerWrapperTest.php new file mode 100644 index 00000000..1aead0c7 --- /dev/null +++ b/tests/Common/LoggerWrapperTest.php @@ -0,0 +1,125 @@ +log($level, $message, $context); + $expected = array($level, $message, $context); + self::assertEquals($expected, $wrapped->getLastLog()); + + $wrapped = new ArrayLogger(); + $instance = new LoggerWrapper(function ($level, $message, $context) use($wrapped) { + $wrapped->log($level, $message, $context); + }); + $instance->log($level, $message, $context); + $expected = array($level, $message, $context); + self::assertEquals($expected, $wrapped->getLastLog()); + } + + /** + * @dataProvider validLoggerDataProvider + * @param string $notUsed + * @param string $message + * @param array $context + */ + public function testLogMethods($notUsed, $message, $context) + { + $methodsMap = array( + LogLevel::EMERGENCY => 'emergency', + LogLevel::ALERT => 'alert', + LogLevel::CRITICAL => 'critical', + LogLevel::ERROR => 'error', + LogLevel::WARNING => 'warning', + LogLevel::NOTICE => 'notice', + LogLevel::INFO => 'info', + LogLevel::DEBUG => 'debug', + ); + + $wrapped = new ArrayLogger(); + $instance = new LoggerWrapper($wrapped); + foreach ($methodsMap as $level => $method) { + $instance->{$method} ($message, $context); + $expected = array($level, $message, $context); + self::assertEquals($expected, $wrapped->getLastLog()); + } + } + + public function validLoggerDataProvider() + { + return array( + array(LogLevel::EMERGENCY, Random::str(10, 20), array(Random::str(10, 20))), + array(LogLevel::ALERT, Random::str(10, 20), array(Random::str(10, 20))), + array(LogLevel::CRITICAL, Random::str(10, 20), array(Random::str(10, 20))), + array(LogLevel::ERROR, Random::str(10, 20), array(Random::str(10, 20))), + array(LogLevel::WARNING, Random::str(10, 20), array(Random::str(10, 20))), + array(LogLevel::NOTICE, Random::str(10, 20), array(Random::str(10, 20))), + array(LogLevel::INFO, Random::str(10, 20), array(Random::str(10, 20))), + array(LogLevel::DEBUG, Random::str(10, 20), array(Random::str(10, 20))), + ); + } +} + +class ArrayLogger +{ + private $lastLog; + + public function log($level, $message, $context) + { + $this->lastLog = array($level, $message, $context); + } + + public function getLastLog() + { + return $this->lastLog; + } +} \ No newline at end of file diff --git a/tests/Helpers/Config/ConfigurationLoaderTest.php b/tests/Helpers/Config/ConfigurationLoaderTest.php new file mode 100644 index 00000000..9a5b19c6 --- /dev/null +++ b/tests/Helpers/Config/ConfigurationLoaderTest.php @@ -0,0 +1,33 @@ +load($fileName); + if (empty($fileName)) { + $fileName = __DIR__ . DIRECTORY_SEPARATOR . ".." . DIRECTORY_SEPARATOR . ".." . DIRECTORY_SEPARATOR . ".." . DIRECTORY_SEPARATOR . "lib" . DIRECTORY_SEPARATOR . "configuration.json"; + } + $data = file_get_contents($fileName); + self::assertEquals(json_decode($data, true), $loader->getConfig()); + } + + public function validDataProvider() + { + return array( + array(null), + array(''), + array(__DIR__ . DIRECTORY_SEPARATOR . 'test_config.json'), + ); + } +} \ No newline at end of file diff --git a/tests/Helpers/Config/test_config.json b/tests/Helpers/Config/test_config.json new file mode 100644 index 00000000..ea338742 --- /dev/null +++ b/tests/Helpers/Config/test_config.json @@ -0,0 +1,4 @@ +{ + "test":"test", + "array":[1,2,3,4] +} \ No newline at end of file diff --git a/tests/Helpers/RandomTest.php b/tests/Helpers/RandomTest.php new file mode 100644 index 00000000..eba79923 --- /dev/null +++ b/tests/Helpers/RandomTest.php @@ -0,0 +1,192 @@ +assertEquals($expected, RawHeadersParser::parse($rawHeaders)); + } + + public function headersDataProvider() + { + return array( + array( + 'Server: nginx + Date: Thu, 03 Aug 2017 16:04:35 GMT + Content-Type: text/html + Content-Length: 178 + Connection: keep-alive + Location: https://insales-dev.yamoney.ru/', + array( + 'Server' => 'nginx', + 'Date' => 'Thu, 03 Aug 2017 16:04:35 GMT', + 'Content-Type' => 'text/html', + 'Content-Length' => '178', + 'Connection' => 'keep-alive', + 'Location' => 'https://insales-dev.yamoney.ru/' + ), + ), + array( + "HTTP/1.1 200 Ok\r\n" . + "Server: nginx\r\n" . + "Date: Thu, 03 Aug 2017 16:04:35 GMT\r\n" . + "Content-Type: text/html\r\n" . + "Content-Length: 178\r\n" . + "Array-Header: value1\r\n" . + "Connection: keep-alive\r\n" . + "Array-Header: value2\r\n" . + "Location: https://insales-dev.yamoney.ru/\r\n" . + "\r\n" . + "Content-Length: 132", + array( + 0 => 'HTTP/1.1 200 Ok', + 'Server' => 'nginx', + 'Date' => 'Thu, 03 Aug 2017 16:04:35 GMT', + 'Content-Type' => 'text/html', + 'Content-Length' => '178', + 'Array-Header' => array( + 'value1', 'value2' + ), + 'Connection' => 'keep-alive', + 'Location' => 'https://insales-dev.yamoney.ru/' + ), + ), + array( + "HTTP/1.1 200 Ok\r\n" . + "Server: nginx\r\n" . + "\tversion 1.3.4\r\n" . + "Date: Thu, 03 Aug 2017 16:04:35 GMT\r\n" . + "Content-Type: text/html\r\n" . + "Content-Length: 178\r\n" . + "Array-Header: value1\r\n" . + "Connection: keep-alive\r\n" . + "Array-Header: value2\r\n" . + "Location: https://insales-dev.yamoney.ru/\r\n" . + "Array-Header: value3\r\n" . + "\r\n" . + "Content-Length: 132", + array( + 0 => 'HTTP/1.1 200 Ok', + 'Server' => "nginx\r\n\tversion 1.3.4", + 'Date' => 'Thu, 03 Aug 2017 16:04:35 GMT', + 'Content-Type' => 'text/html', + 'Content-Length' => '178', + 'Array-Header' => array( + 'value1', 'value2', 'value3', + ), + 'Connection' => 'keep-alive', + 'Location' => 'https://insales-dev.yamoney.ru/' + ), + ), + ); + } +} \ No newline at end of file diff --git a/tests/Helpers/StringObjectTest.php b/tests/Helpers/StringObjectTest.php new file mode 100644 index 00000000..7277b7d1 --- /dev/null +++ b/tests/Helpers/StringObjectTest.php @@ -0,0 +1,27 @@ +__toString()); + } + + public function dataProvider() + { + return array( + array(''), + array('value'), + ); + } +} \ No newline at end of file diff --git a/tests/Helpers/TypeCastTest.php b/tests/Helpers/TypeCastTest.php new file mode 100644 index 00000000..adb84aec --- /dev/null +++ b/tests/Helpers/TypeCastTest.php @@ -0,0 +1,151 @@ +getTimestamp(), $instance->getTimestamp()); + self::assertNotSame($value, $instance); + } else { + self::assertEquals($expected, $instance->getTimestamp()); + } + } else { + self::assertNull($instance); + } + } + + public function canCastToStringDataProvider() + { + return array( + array('', true), + array('test_string', true), + array(0, true), + array(1, true), + array(-1, true), + array(0.0, true), + array(-0.001, true), + array(0.001, true), + array(true, false), + array(false, false), + array(null, false), + array(array(), false), + array(new \stdClass(), false), + array(fopen(__FILE__, 'r'), false), + array(new StringObject('test'), true), + ); + } + + public function canCastToEnumStringDataProvider() + { + return array( + array('', false), + array('test_string', true), + array(0, false), + array(1, false), + array(-1, false), + array(0.0, false), + array(-0.001, false), + array(0.001, false), + array(true, false), + array(false, false), + array(null, false), + array(array(), false), + array(new \stdClass(), false), + array(fopen(__FILE__, 'r'), false), + array(new StringObject('test'), true), + ); + } + + public function canCastToDateTimeDataProvider() + { + return array( + array('', false), + array('test_string', true), + array(0, true), + array(1, true), + array(-1, false), + array(0.0, true), + array(-0.001, false), + array(0.001, true), + array(true, false), + array(false, false), + array(null, false), + array(array(), false), + array(new \stdClass(), false), + array(fopen(__FILE__, 'r'), false), + array(new StringObject('test'), true), + array(new \DateTime(), true), + ); + } + + public function castToDateTimeDataProvider() + { + $result = array(); + + $time = time(); + $result[] = array($time, $time, true); + $result[] = array(date(DATE_ATOM, $time), $time, true); + $result[] = array(new \DateTime(date(DATE_ATOM, $time)), $time, true); + $result[] = array('3234-234-23', $time, false); + $result[] = array(array(), $time, false); + + return $result; + } +} \ No newline at end of file diff --git a/tests/Helpers/UUIDTest.php b/tests/Helpers/UUIDTest.php new file mode 100644 index 00000000..5f34d3dd --- /dev/null +++ b/tests/Helpers/UUIDTest.php @@ -0,0 +1,16 @@ +notEmpty()); + + $airline->setBookingReference($data['booking_reference']); + $airline->setTicketNumber($data['ticket_number']); + $airline->setPassengers($data['passengers']); + $airline->setLegs($data['legs']); + + self::assertEquals($airline->getBookingReference(), $data['booking_reference']); + self::assertEquals($airline->getTicketNumber(), $data['ticket_number']); + self::assertTrue(is_array($airline->getPassengers())); + self::assertTrue(is_array($airline->getLegs())); + + foreach ($airline->getLegs() as $leg) { + self::assertTrue($leg instanceof LegInterface); + } + + foreach ($airline->getPassengers() as $passenger) { + self::assertTrue($passenger instanceof PassengerInterface); + } + + self::assertTrue($airline->notEmpty()); + } + + /** + * @dataProvider validDataProvider + * + * @param $data + */ + public function testFromArrayInstantiate($data) + { + $airline = new Airline(); + $airline->fromArray($data); + + self::assertEquals($airline->getBookingReference(), $data['booking_reference']); + self::assertEquals($airline->getTicketNumber(), $data['ticket_number']); + self::assertTrue(is_array($airline->getPassengers())); + self::assertTrue(is_array($airline->getLegs())); + + foreach ($airline->getLegs() as $leg) { + self::assertTrue($leg instanceof LegInterface); + } + + foreach ($airline->getPassengers() as $passenger) { + self::assertTrue($passenger instanceof PassengerInterface); + } + + self::assertTrue($airline->notEmpty()); + } + + + /** + * @dataProvider exceptionDataProvider + */ + public function testAirlinePassengersDataValidate($data) + { + $airline = new Airline(); + + $this->setExpectedException($data['exception']); + + $airline->setPassengers($data['value']); + } + + /** + * @dataProvider exceptionDataProvider + */ + public function testAirlineLegsDataValidate($data) + { + $airline = new Airline(); + + $this->setExpectedException($data['exception']); + + $airline->setLegs($data['value']); + } + + /** + * @dataProvider stringsExceptionDataProvider + */ + public function testBookingReferenceValidate($data) + { + $airline = new Airline(); + + $this->setExpectedException($data['exception']); + + $airline->setBookingReference($data['value']); + } + + /** + * @dataProvider stringsExceptionDataProvider + */ + public function testTicketNumberValidate($data) + { + $airline = new Airline(); + + $this->setExpectedException($data['exception']); + + $airline->setTicketNumber($data['value']); + } + + public function validDataProvider() + { + $passenger = new Passenger(); + $passenger->setFirstName("SERGEI"); + $passenger->setLastName("IVANOV"); + + $leg = new Leg(); + $leg->setDepartureAirport('LED'); + $leg->setDestinationAirport("AMS"); + $leg->setDepartureDate("2018-06-20"); + + return array( + array( + array( + "booking_reference" => "IIIKRV", + "ticket_number" => '12342123413', + "passengers" => array( + array( + "first_name" => "SERGEI", + "last_name" => "IVANOV", + ), + ), + "legs" => array( + array( + "departure_airport" => "LED", + "destination_airport" => "AMS", + "departure_date" => "2018-06-20", + ), + ), + ), + ), + array( + array( + "booking_reference" => "", + "ticket_number" => '', + "passengers" => array( + $passenger, + ), + "legs" => array( + $leg, + ), + ), + ), + ); + } + + public function exceptionDataProvider() + { + return array( + array( + array( + "exception" => 'YooKassa\Common\Exceptions\EmptyPropertyValueException', + "value" => '', + ), + ), + array( + array( + "exception" => 'YooKassa\Common\Exceptions\EmptyPropertyValueException', + "value" => null, + ), + ), + array( + array( + "exception" => 'YooKassa\Common\Exceptions\InvalidPropertyValueTypeException', + "value" => new \stdClass(), + ), + ), + array( + array( + "exception" => 'YooKassa\Common\Exceptions\InvalidPropertyValueTypeException', + "value" => array(1, 2, 3), + ), + ), + ); + } + + public function stringsExceptionDataProvider() + { + return array( + array( + array( + "exception" => 'YooKassa\Common\Exceptions\InvalidPropertyValueTypeException', + "value" => array(), + ), + ), + array( + array( + "exception" => 'YooKassa\Common\Exceptions\InvalidPropertyValueException', + "value" => 'stringThatGreaterThanNeededCharsLongAndActuallyNotValidAtAll123', + ), + ), + ); + } +} diff --git a/tests/Model/AuthorizationDetailsTest.php b/tests/Model/AuthorizationDetailsTest.php new file mode 100644 index 00000000..cff3ff3e --- /dev/null +++ b/tests/Model/AuthorizationDetailsTest.php @@ -0,0 +1,152 @@ +getRrn()); + self::assertEquals($authCode, $instance->getAuthCode()); + } + + /** + * @dataProvider validDataProvider + * + * @param $rrn + * @param $authCode + */ + public function testGetSetRrn($rrn = null, $authCode = null) + { + $instance = self::getInstance($rrn, $authCode); + self::assertEquals($rrn, $instance->getRrn()); + + $instance = self::getInstance(); + $instance->setRrn($rrn); + self::assertEquals($rrn, $instance->getRrn()); + self::assertEquals($rrn, $instance->rrn); + } + + /** + * @dataProvider validDataProvider + * + * @param null $rrn + * @param null $authCode + */ + public function testGetSetAuthCode($rrn = null, $authCode = null) + { + $instance = self::getInstance($rrn, $authCode); + self::assertEquals($authCode, $instance->getAuthCode()); + + $instance = self::getInstance(); + $instance->setAuthCode($authCode); + self::assertEquals($authCode, $instance->getAuthCode()); + self::assertEquals($authCode, $instance->authCode); + } + + /** + * @dataProvider invalidValueDataProvider + * @param mixed $value + * @param string $exceptionClassName + */ + public function testSetInvalidRrn($value, $exceptionClassName) + { + $instance = self::getInstance(); + try { + $instance->setRrn($value); + } catch (\Exception $e) { + self::assertInstanceOf($exceptionClassName, $e); + } + } + + /** + * @dataProvider invalidValueDataProvider + * @param mixed $value + * @param string $exceptionClassName + */ + public function testSetterInvalidAuthCode($value, $exceptionClassName) + { + $instance = self::getInstance(); + try { + $instance->setAuthCode($value); + } catch (\Exception $e) { + self::assertInstanceOf($exceptionClassName, $e); + } + } + + /** + * @return array + * @throws \Exception + */ + public function validDataProvider() + { + $result = array( + array( + 'rrn' => null, + 'authCode' => null, + ), + array( + 'rrn' => '', + 'authCode' => '', + ), + array( + 'rrn' => Random::str(32), + 'authCode' => Random::str(32), + ), + ); + + return $result; + } + + public function invalidValueDataProvider() + { + $exceptionNamespace = 'YooKassa\\Common\\Exceptions\\'; + return array( + array(array(), $exceptionNamespace.'InvalidPropertyValueTypeException'), + array(fopen(__FILE__, 'r'), $exceptionNamespace.'InvalidPropertyValueTypeException'), + array(-1, $exceptionNamespace.'InvalidPropertyValueTypeException'), + array(-0.01, $exceptionNamespace.'InvalidPropertyValueTypeException'), + array(0.0, $exceptionNamespace.'InvalidPropertyValueTypeException'), + array(true, $exceptionNamespace.'InvalidPropertyValueTypeException'), + array(false, $exceptionNamespace.'InvalidPropertyValueTypeException'), + ); + } + + /** + * @dataProvider validDataProvider + * + * @param null $rrn + * @param null $authCode + */ + public function testJsonSerialize($rrn = null, $authCode = null) + { + $instance = new AuthorizationDetails($rrn, $authCode); + $expected = array( + 'rrn' => $rrn, + 'auth_code' => $authCode, + ); + self::assertEquals($expected, $instance->jsonSerialize()); + } +} diff --git a/tests/Model/CancellationDetailsTest.php b/tests/Model/CancellationDetailsTest.php new file mode 100644 index 00000000..ae7cadc2 --- /dev/null +++ b/tests/Model/CancellationDetailsTest.php @@ -0,0 +1,148 @@ +getParty()); + self::assertEquals($reason, $instance->getReason()); + } + + /** + * @dataProvider validDataProvider + * + * @param $party + * @param $reason + */ + public function testGetSetParty($party = null, $reason = null) + { + $instance = self::getInstance($party, $reason); + self::assertEquals($party, $instance->getParty()); + + $instance = self::getInstance(); + $instance->setParty($party); + self::assertEquals($party, $instance->getParty()); + self::assertEquals($party, $instance->party); + } + + /** + * @dataProvider validDataProvider + * + * @param null $party + * @param null $reason + */ + public function testGetSetReason($party = null, $reason = null) + { + $instance = self::getInstance($party, $reason); + self::assertEquals($reason, $instance->getReason()); + + $instance = self::getInstance(); + $instance->setReason($reason); + self::assertEquals($reason, $instance->getReason()); + self::assertEquals($reason, $instance->reason); + } + + /** + * @dataProvider invalidValueDataProvider + * @param mixed $value + * @param string $exceptionClassName + */ + public function testSetInvalidParty($value, $exceptionClassName) + { + $instance = self::getInstance(); + try { + $instance->setParty($value); + } catch (\Exception $e) { + self::assertInstanceOf($exceptionClassName, $e); + } + } + + /** + * @dataProvider invalidValueDataProvider + * @param mixed $value + * @param string $exceptionClassName + */ + public function testSetterInvalidReason($value, $exceptionClassName) + { + $instance = self::getInstance(); + try { + $instance->reason = $value; + } catch (\Exception $e) { + self::assertInstanceOf($exceptionClassName, $e); + } + } + + /** + * @return array + */ + public function validDataProvider() + { + $result = array(); + $cancellationDetailsParties = CancellationDetailsPartyCode::getValidValues(); + $countCancellationDetailsParties = count($cancellationDetailsParties); + $cancellationDetailsReasons = CancellationDetailsReasonCode::getValidValues(); + $countCancellationDetailsReasons = count($cancellationDetailsReasons); + for ($i = 0; $i < 20; $i++) { + $result[] = array( + 'party' => $cancellationDetailsParties[$i % $countCancellationDetailsParties], + 'reason' => $cancellationDetailsReasons[$i % $countCancellationDetailsReasons] + ); + } + return $result; + + } + + public function invalidValueDataProvider() + { + $exceptionNamespace = 'YooKassa\\Common\\Exceptions\\'; + return array( + array(null, $exceptionNamespace.'EmptyPropertyValueException'), + array('', $exceptionNamespace.'EmptyPropertyValueException'), + array(array(), $exceptionNamespace.'InvalidPropertyValueTypeException'), + array(fopen(__FILE__, 'r'), $exceptionNamespace.'InvalidPropertyValueTypeException'), + array(true, $exceptionNamespace.'InvalidPropertyValueTypeException'), + array(false, $exceptionNamespace.'InvalidPropertyValueTypeException'), + ); + } + + /** + * @dataProvider validDataProvider + * + * @param null $party + * @param null $reason + */ + public function testJsonSerialize($party = null, $reason = null) + { + $instance = new CancellationDetails($party, $reason); + $expected = array( + 'party' => $party, + 'reason' => $reason, + ); + self::assertEquals($expected, $instance->jsonSerialize()); + } +} diff --git a/tests/Model/Confirmation/AbstractConfirmationTest.php b/tests/Model/Confirmation/AbstractConfirmationTest.php new file mode 100644 index 00000000..e886f36e --- /dev/null +++ b/tests/Model/Confirmation/AbstractConfirmationTest.php @@ -0,0 +1,63 @@ +getTestInstance(); + self::assertEquals($this->getExpectedType(), $instance->getType()); + } + + /** + * @dataProvider invalidTypeDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testInvalidType($value) + { + new TestConfirmation($value); + } + + /** + * @return array + * @throws \Exception + */ + public function invalidTypeDataProvider() + { + return array( + array(''), + array(null), + array(Random::str(40)), + array(0), + array(array()), + array(new \stdClass()), + ); + } +} + +class TestConfirmation extends AbstractConfirmation +{ + public function __construct($type) + { + $this->_setType($type); + } +} diff --git a/tests/Model/Confirmation/ConfirmationCodeVerificationTest.php b/tests/Model/Confirmation/ConfirmationCodeVerificationTest.php new file mode 100644 index 00000000..bc1c2d8a --- /dev/null +++ b/tests/Model/Confirmation/ConfirmationCodeVerificationTest.php @@ -0,0 +1,25 @@ +getTestInstance(); + + self::assertNull($instance->getConfirmationToken()); + self::assertNull($instance->confirmationToken); + + $instance->setConfirmationToken($value); + if ($value === null || $value === '') { + self::assertNull($instance->getConfirmationToken()); + self::assertNull($instance->confirmationToken); + } else { + self::assertEquals($value, $instance->getConfirmationToken()); + self::assertEquals($value, $instance->confirmationToken); + } + + $instance = $this->getTestInstance(); + $instance->confirmationToken = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getConfirmationToken()); + self::assertNull($instance->confirmationToken); + } else { + self::assertEquals($value, $instance->getConfirmationToken()); + self::assertEquals($value, $instance->confirmationToken); + } + } + + public function validConfirmationTokenDataProvider() + { + return array( + array(null), + array(''), + array('ct-2454fc2d-000f-5000-9000-12a816bfbb35'), + ); + } +} \ No newline at end of file diff --git a/tests/Model/Confirmation/ConfirmationExternalTest.php b/tests/Model/Confirmation/ConfirmationExternalTest.php new file mode 100644 index 00000000..2849f313 --- /dev/null +++ b/tests/Model/Confirmation/ConfirmationExternalTest.php @@ -0,0 +1,26 @@ +getTestInstance(); + $confirmation = $instance->factory($type); + self::assertNotNull($confirmation); + self::assertTrue($confirmation instanceof AbstractConfirmation); + self::assertEquals($type, $confirmation->getType()); + } + + /** + * @dataProvider invalidTypeDataProvider + * @expectedException \InvalidArgumentException + * @param $type + */ + public function testInvalidFactory($type) + { + $instance = $this->getTestInstance(); + $instance->factory($type); + } + + /** + * @dataProvider validArrayDataProvider + * @param array $options + */ + public function testFactoryFromArray($options) + { + $instance = $this->getTestInstance(); + $confirmation = $instance->factoryFromArray($options); + self::assertNotNull($confirmation); + self::assertTrue($confirmation instanceof AbstractConfirmation); + + foreach ($options as $property => $value) { + self::assertEquals($confirmation->{$property}, $value); + } + + $type = $options['type']; + unset($options['type']); + $confirmation = $instance->factoryFromArray($options, $type); + self::assertNotNull($confirmation); + self::assertTrue($confirmation instanceof AbstractConfirmation); + + self::assertEquals($type, $confirmation->getType()); + foreach ($options as $property => $value) { + self::assertEquals($confirmation->{$property}, $value); + } + } + + /** + * @dataProvider invalidDataArrayDataProvider + * @expectedException \InvalidArgumentException + * @param $options + */ + public function testInvalidFactoryFromArray($options) + { + $instance = $this->getTestInstance(); + $instance->factoryFromArray($options); + } + + public function validTypeDataProvider() + { + $result = array(); + foreach (ConfirmationType::getValidValues() as $value) { + $result[] = array($value); + } + return $result; + } + + public function invalidTypeDataProvider() + { + return array( + array(''), + array(null), + array(0), + array(1), + array(-1), + array('5'), + array(array()), + array(new \stdClass()), + array(Random::str(10)), + ); + } + + public function validArrayDataProvider() + { + $result = array( + array( + array( + 'type' => ConfirmationType::REDIRECT, + 'enforce' => false, + 'returnUrl' => Random::str(10), + 'confirmationUrl' => Random::str(10), + ), + ), + array( + array( + 'type' => ConfirmationType::REDIRECT, + 'enforce' => true, + 'returnUrl' => Random::str(10), + ), + ), + array( + array( + 'type' => ConfirmationType::REDIRECT, + 'returnUrl' => Random::str(10), + 'confirmationUrl' => Random::str(10), + ), + ), + array( + array( + 'type' => ConfirmationType::REDIRECT, + 'confirmationUrl' => Random::str(10), + ), + ), + array( + array( + 'type' => ConfirmationType::REDIRECT, + 'returnUrl' => Random::str(10), + ), + ), + array( + array( + 'type' => ConfirmationType::REDIRECT, + 'enforce' => true, + ), + ), + array( + array( + 'type' => ConfirmationType::REDIRECT, + ), + ), + array( + array( + 'type' => ConfirmationType::QR, + 'confirmation_data' => Random::str(30), + ), + ), + ); + foreach (ConfirmationType::getValidValues() as $value) { + $result[] = array(array('type' => $value)); + } + return $result; + } + + public function invalidDataArrayDataProvider() + { + return array( + array(array()), + array(array('type' => 'test')), + ); + } +} \ No newline at end of file diff --git a/tests/Model/Confirmation/ConfirmationQrTest.php b/tests/Model/Confirmation/ConfirmationQrTest.php new file mode 100644 index 00000000..e86f8315 --- /dev/null +++ b/tests/Model/Confirmation/ConfirmationQrTest.php @@ -0,0 +1,152 @@ +getTestInstance(); + + self::assertNull($instance->getConfirmationData()); + self::assertNull($instance->confirmationData); + self::assertNull($instance->confirmation_data); + + $instance->setConfirmationData($value); + if ($value === null || $value === '') { + self::assertNull($instance->getConfirmationData()); + self::assertNull($instance->confirmationData); + self::assertNull($instance->confirmation_data); + } else { + self::assertEquals($value, $instance->getConfirmationData()); + self::assertEquals($value, $instance->confirmationData); + self::assertEquals($value, $instance->confirmation_data); + } + + $instance->setConfirmationData(null); + self::assertNull($instance->getConfirmationData()); + self::assertNull($instance->confirmationData); + self::assertNull($instance->confirmation_data); + + $instance->confirmationData = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getConfirmationData()); + self::assertNull($instance->confirmationData); + self::assertNull($instance->confirmation_data); + } else { + self::assertEquals($value, $instance->getConfirmationData()); + self::assertEquals($value, $instance->confirmationData); + self::assertEquals($value, $instance->confirmation_data); + } + + $instance->confirmation_data = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getConfirmationData()); + self::assertNull($instance->confirmationData); + self::assertNull($instance->confirmation_data); + } else { + self::assertEquals($value, $instance->getConfirmationData()); + self::assertEquals($value, $instance->confirmationData); + self::assertEquals($value, $instance->confirmation_data); + } + } + + /** + * @dataProvider invalidUrlDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidConfirmationData($value) + { + $instance = $this->getTestInstance(); + $instance->setConfirmationData($value); + } + + /** + * @dataProvider invalidUrlDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidConfirmationData($value) + { + $instance = $this->getTestInstance(); + $instance->confirmationData = $value; + } + + /** + * @dataProvider invalidUrlDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidConfirmation_data($value) + { + $instance = $this->getTestInstance(); + $instance->confirmation_data = $value; + } + + public function validEnforceDataProvider() + { + return array( + array(true), + array(false), + array(null), + array(''), + array(0), + array(1), + array(100), + ); + } + + public function invalidEnforceDataProvider() + { + return array( + array('true'), + array('false'), + array(array()), + array(new \stdClass()), + ); + } + + public function validUrlDataProvider() + { + return array( + array('wechat://pay/testurl?pr=xXxXxX'), + array('http://test.ru'), + array(null), + array(''), + ); + } + + public function invalidUrlDataProvider() + { + return array( + array(true), + array(false), + array(array()), + array(new \stdClass()), + ); + } +} \ No newline at end of file diff --git a/tests/Model/Confirmation/ConfirmationRedirectTest.php b/tests/Model/Confirmation/ConfirmationRedirectTest.php new file mode 100644 index 00000000..00a80b0e --- /dev/null +++ b/tests/Model/Confirmation/ConfirmationRedirectTest.php @@ -0,0 +1,288 @@ +getTestInstance(); + + self::assertNull($instance->getEnforce()); + self::assertNull($instance->enforce); + + $instance->setEnforce($value); + if ($value === null || $value === '') { + self::assertNull($instance->getEnforce()); + self::assertNull($instance->enforce); + } else { + self::assertEquals((bool)$value, $instance->getEnforce()); + self::assertEquals((bool)$value, $instance->enforce); + } + + $instance = $this->getTestInstance(); + $instance->enforce = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getEnforce()); + self::assertNull($instance->enforce); + } else { + self::assertEquals((bool)$value, $instance->getEnforce()); + self::assertEquals((bool)$value, $instance->enforce); + } + } + + /** + * @dataProvider invalidEnforceDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidEnforce($value) + { + $instance = $this->getTestInstance(); + $instance->setEnforce($value); + } + + /** + * @dataProvider invalidEnforceDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidEnforce($value) + { + $instance = $this->getTestInstance(); + $instance->enforce = $value; + } + + /** + * @dataProvider validUrlDataProvider + * @param $value + */ + public function testGetSetReturnUrl($value) + { + $instance = $this->getTestInstance(); + + self::assertNull($instance->getReturnUrl()); + self::assertNull($instance->returnUrl); + self::assertNull($instance->return_url); + + $instance->setReturnUrl($value); + if ($value === null || $value === '') { + self::assertNull($instance->getReturnUrl()); + self::assertNull($instance->returnUrl); + self::assertNull($instance->return_url); + } else { + self::assertEquals($value, $instance->getReturnUrl()); + self::assertEquals($value, $instance->returnUrl); + self::assertEquals($value, $instance->return_url); + } + + $instance->setReturnUrl(null); + self::assertNull($instance->getReturnUrl()); + self::assertNull($instance->returnUrl); + self::assertNull($instance->return_url); + + $instance->returnUrl = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getReturnUrl()); + self::assertNull($instance->returnUrl); + self::assertNull($instance->return_url); + } else { + self::assertEquals($value, $instance->getReturnUrl()); + self::assertEquals($value, $instance->returnUrl); + self::assertEquals($value, $instance->return_url); + } + + $instance->return_url = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getReturnUrl()); + self::assertNull($instance->returnUrl); + self::assertNull($instance->return_url); + } else { + self::assertEquals($value, $instance->getReturnUrl()); + self::assertEquals($value, $instance->returnUrl); + self::assertEquals($value, $instance->return_url); + } + } + + /** + * @dataProvider invalidUrlDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidReturnUrl($value) + { + $instance = $this->getTestInstance(); + $instance->setReturnUrl($value); + } + + /** + * @dataProvider invalidUrlDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidReturnUrl($value) + { + $instance = $this->getTestInstance(); + $instance->returnUrl = $value; + } + + /** + * @dataProvider invalidUrlDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidReturn_url($value) + { + $instance = $this->getTestInstance(); + $instance->return_url = $value; + } + + /** + * @dataProvider validUrlDataProvider + * @param $value + */ + public function testGetSetConfirmationUrl($value) + { + $instance = $this->getTestInstance(); + + self::assertNull($instance->getConfirmationUrl()); + self::assertNull($instance->confirmationUrl); + self::assertNull($instance->confirmation_url); + + $instance->setConfirmationUrl($value); + if ($value === null || $value === '') { + self::assertNull($instance->getConfirmationUrl()); + self::assertNull($instance->confirmationUrl); + self::assertNull($instance->confirmation_url); + } else { + self::assertEquals($value, $instance->getConfirmationUrl()); + self::assertEquals($value, $instance->confirmationUrl); + self::assertEquals($value, $instance->confirmation_url); + } + + $instance->setConfirmationUrl(null); + self::assertNull($instance->getConfirmationUrl()); + self::assertNull($instance->confirmationUrl); + self::assertNull($instance->confirmation_url); + + $instance->confirmationUrl = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getConfirmationUrl()); + self::assertNull($instance->confirmationUrl); + self::assertNull($instance->confirmation_url); + } else { + self::assertEquals($value, $instance->getConfirmationUrl()); + self::assertEquals($value, $instance->confirmationUrl); + self::assertEquals($value, $instance->confirmation_url); + } + + $instance->confirmation_url = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getConfirmationUrl()); + self::assertNull($instance->confirmationUrl); + self::assertNull($instance->confirmation_url); + } else { + self::assertEquals($value, $instance->getConfirmationUrl()); + self::assertEquals($value, $instance->confirmationUrl); + self::assertEquals($value, $instance->confirmation_url); + } + } + + /** + * @dataProvider invalidUrlDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidConfirmationUrl($value) + { + $instance = $this->getTestInstance(); + $instance->setConfirmationUrl($value); + } + + /** + * @dataProvider invalidUrlDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidConfirmationUrl($value) + { + $instance = $this->getTestInstance(); + $instance->confirmationUrl = $value; + } + + /** + * @dataProvider invalidUrlDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidConfirmation_url($value) + { + $instance = $this->getTestInstance(); + $instance->confirmation_url = $value; + } + + public function validEnforceDataProvider() + { + return array( + array(true), + array(false), + array(null), + array(''), + array(0), + array(1), + array(100), + ); + } + + public function invalidEnforceDataProvider() + { + return array( + array('true'), + array('false'), + array(array()), + array(new \stdClass()), + ); + } + + public function validUrlDataProvider() + { + return array( + array('http://test.ru'), + array(null), + array(''), + ); + } + + public function invalidUrlDataProvider() + { + return array( + array(true), + array(false), + array(array()), + array(new \stdClass()), + ); + } +} \ No newline at end of file diff --git a/tests/Model/ConfirmationAttributes/AbstractConfirmationAttributesTest.php b/tests/Model/ConfirmationAttributes/AbstractConfirmationAttributesTest.php new file mode 100644 index 00000000..e5f7e4f8 --- /dev/null +++ b/tests/Model/ConfirmationAttributes/AbstractConfirmationAttributesTest.php @@ -0,0 +1,122 @@ +getTestInstance(); + self::assertEquals($this->getExpectedType(), $instance->getType()); + } + + /** + * @dataProvider invalidTypeDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testInvalidType($value) + { + new TestConfirmation($value); + } + + public function invalidTypeDataProvider() + { + return array( + array(''), + array(null), + array(Random::str(40)), + array(0), + array(array()), + array(new \stdClass()), + ); + } + + + /** + * @dataProvider validLocaleDataProvider + * + * @param $value + */ + public function testSetterLocale($value) + { + $instance = $this->getTestInstance(); + $instance->setLocale($value); + self::assertEquals((string)$value, $instance->getLocale()); + } + + /** + * @return array + * @throws \Exception + */ + public function validLocaleDataProvider() + { + return array( + array(''), + array(null), + array( + Random::str(2, 2, 'abcdefghijklmnopqrtuvwxyz') + . '_' . + Random::str(2, 2, 'ABCDEFGHIJKLMNOPQRTUVWXYZ') + ), + array('ru_RU'), + array('en_US'), + ); + } + + /** + * @dataProvider invalidLocaleDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidLocale($value) + { + $this->getTestInstance()->setLocale($value); + } + + /** + * @return array + * @throws \Exception + */ + public function invalidLocaleDataProvider() + { + return array( + array(Random::str(4)), + array(Random::str(6)), + array(0), + array(array()), + array(new \stdClass()), + array( + Random::str(2, 2, 'ABCDEFGHIJKLMNOPQRTUVWXYZ') + . '_' . + Random::str(2, 2, 'abcdefghijklmnopqrtuvwxyz') + ), + ); + } +} + +class TestConfirmation extends AbstractConfirmationAttributes +{ + public function __construct($type) + { + $this->_setType($type); + } +} \ No newline at end of file diff --git a/tests/Model/ConfirmationAttributes/ConfirmationAttributesCodeVerificationTest.php b/tests/Model/ConfirmationAttributes/ConfirmationAttributesCodeVerificationTest.php new file mode 100644 index 00000000..9156f4fc --- /dev/null +++ b/tests/Model/ConfirmationAttributes/ConfirmationAttributesCodeVerificationTest.php @@ -0,0 +1,25 @@ +getTestInstance(); + $confirmation = $instance->factory($type); + self::assertNotNull($confirmation); + self::assertTrue($confirmation instanceof AbstractConfirmationAttributes); + self::assertEquals($type, $confirmation->getType()); + } + + /** + * @dataProvider invalidTypeDataProvider + * @expectedException \InvalidArgumentException + * @param $type + */ + public function testInvalidFactory($type) + { + $instance = $this->getTestInstance(); + $instance->factory($type); + } + + /** + * @dataProvider validArrayDataProvider + * @param array $options + */ + public function testFactoryFromArray($options) + { + $instance = $this->getTestInstance(); + $confirmation = $instance->factoryFromArray($options); + self::assertNotNull($confirmation); + self::assertTrue($confirmation instanceof AbstractConfirmationAttributes); + + foreach ($options as $property => $value) { + self::assertEquals($confirmation->{$property}, $value); + } + + $type = $options['type']; + unset($options['type']); + $confirmation = $instance->factoryFromArray($options, $type); + self::assertNotNull($confirmation); + self::assertTrue($confirmation instanceof AbstractConfirmationAttributes); + + self::assertEquals($type, $confirmation->getType()); + foreach ($options as $property => $value) { + self::assertEquals($confirmation->{$property}, $value); + } + } + + /** + * @dataProvider invalidDataArrayDataProvider + * @expectedException \InvalidArgumentException + * @param $options + */ + public function testInvalidFactoryFromArray($options) + { + $instance = $this->getTestInstance(); + $instance->factoryFromArray($options); + } + + public function validTypeDataProvider() + { + $result = array(); + foreach (ConfirmationType::getValidValues() as $value) { + $result[] = array($value); + } + return $result; + } + + public function invalidTypeDataProvider() + { + return array( + array(''), + array(null), + array(0), + array(1), + array(-1), + array('5'), + array(array()), + array(new \stdClass()), + array(Random::str(10)), + ); + } + + public function validArrayDataProvider() + { + $result = array( + array( + array( + 'type' => ConfirmationType::REDIRECT, + 'enforce' => false, + 'returnUrl' => Random::str(10), + ), + ), + array( + array( + 'type' => ConfirmationType::REDIRECT, + 'enforce' => true, + ), + ), + array( + array( + 'type' => ConfirmationType::REDIRECT, + 'returnUrl' => Random::str(10), + ), + ), + array( + array( + 'type' => ConfirmationType::REDIRECT, + ), + ), + ); + foreach (ConfirmationType::getValidValues() as $value) { + $result[] = array(array('type' => $value)); + } + return $result; + } + + public function invalidDataArrayDataProvider() + { + return array( + array(array()), + array(array('type' => 'test')), + ); + } +} \ No newline at end of file diff --git a/tests/Model/ConfirmationAttributes/ConfirmationAttributesQrTest.php b/tests/Model/ConfirmationAttributes/ConfirmationAttributesQrTest.php new file mode 100644 index 00000000..61178b03 --- /dev/null +++ b/tests/Model/ConfirmationAttributes/ConfirmationAttributesQrTest.php @@ -0,0 +1,25 @@ +getTestInstance(); + + self::assertNull($instance->getEnforce()); + self::assertNull($instance->enforce); + + $instance->setEnforce($value); + if ($value === null || $value === '') { + self::assertNull($instance->getEnforce()); + self::assertNull($instance->enforce); + } else { + self::assertEquals((bool)$value, $instance->getEnforce()); + self::assertEquals((bool)$value, $instance->enforce); + } + + $instance = $this->getTestInstance(); + $instance->enforce = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getEnforce()); + self::assertNull($instance->enforce); + } else { + self::assertEquals((bool)$value, $instance->getEnforce()); + self::assertEquals((bool)$value, $instance->enforce); + } + } + + /** + * @dataProvider invalidEnforceDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidEnforce($value) + { + $instance = $this->getTestInstance(); + $instance->setEnforce($value); + } + + /** + * @dataProvider invalidEnforceDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidEnforce($value) + { + $instance = $this->getTestInstance(); + $instance->enforce = $value; + } + + /** + * @dataProvider validUrlDataProvider + * @param $value + */ + public function testGetSetReturnUrl($value) + { + $instance = $this->getTestInstance(); + + self::assertNull($instance->getReturnUrl()); + self::assertNull($instance->returnUrl); + self::assertNull($instance->return_url); + + $instance->setReturnUrl($value); + if ($value === null || $value === '') { + self::assertNull($instance->getReturnUrl()); + self::assertNull($instance->returnUrl); + self::assertNull($instance->return_url); + } else { + self::assertEquals($value, $instance->getReturnUrl()); + self::assertEquals($value, $instance->returnUrl); + self::assertEquals($value, $instance->return_url); + } + + $instance->setReturnUrl(null); + self::assertNull($instance->getReturnUrl()); + self::assertNull($instance->returnUrl); + self::assertNull($instance->return_url); + + $instance->returnUrl = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getReturnUrl()); + self::assertNull($instance->returnUrl); + self::assertNull($instance->return_url); + } else { + self::assertEquals($value, $instance->getReturnUrl()); + self::assertEquals($value, $instance->returnUrl); + self::assertEquals($value, $instance->return_url); + } + + $instance->setReturnUrl(null); + self::assertNull($instance->getReturnUrl()); + self::assertNull($instance->returnUrl); + self::assertNull($instance->return_url); + + $instance->return_url = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getReturnUrl()); + self::assertNull($instance->returnUrl); + self::assertNull($instance->return_url); + } else { + self::assertEquals($value, $instance->getReturnUrl()); + self::assertEquals($value, $instance->returnUrl); + self::assertEquals($value, $instance->return_url); + } + } + + /** + * @dataProvider invalidUrlDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidReturnUrl($value) + { + $instance = $this->getTestInstance(); + $instance->setReturnUrl($value); + } + + /** + * @dataProvider invalidUrlDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidReturnUrl($value) + { + $instance = $this->getTestInstance(); + $instance->returnUrl = $value; + } + + /** + * @dataProvider invalidUrlDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidReturn_url($value) + { + $instance = $this->getTestInstance(); + $instance->return_url = $value; + } + + public function validEnforceDataProvider() + { + return array( + array(true), + array(false), + array(null), + array(''), + array(0), + array(1), + array(100), + ); + } + + public function invalidEnforceDataProvider() + { + return array( + array('true'), + array('false'), + array(array()), + array(new \stdClass()), + ); + } + + public function validUrlDataProvider() + { + return array( + array('http://test.ru'), + array(null), + array(''), + ); + } + + public function invalidUrlDataProvider() + { + return array( + array(true), + array(false), + array(array()), + array(new \stdClass()), + ); + } +} \ No newline at end of file diff --git a/tests/Model/LegTest.php b/tests/Model/LegTest.php new file mode 100644 index 00000000..29e85920 --- /dev/null +++ b/tests/Model/LegTest.php @@ -0,0 +1,109 @@ +setDepartureAirport($data["departure_airport"]); + $leg->setDestinationAirport($data["destination_airport"]); + $leg->setDepartureDate($data["departure_date"]); + + self::assertEquals($data["departure_airport"], $leg->getDepartureAirport()); + self::assertEquals($data["destination_airport"], $leg->getDestinationAirport()); + self::assertEquals($data["departure_date"], $leg->getDepartureDate()); + + } + + /** + * @dataProvider invalidDataProvider + * + * @param $data + */ + public function testDepartureAirportValidate($data) + { + $leg = new Leg(); + + $this->setExpectedException($data['exception']); + + $leg->setDepartureAirport($data['value']); + } + + /** + * @dataProvider invalidDataProvider + * + * @param $data + */ + public function testDestinationAirportValidate($data) + { + $leg = new Leg(); + + $this->setExpectedException($data['exception']); + + $leg->setDestinationAirport($data['value']); + } + + /** + * @dataProvider invalidDataProvider + * + * @param $data + */ + public function testDepartureDateValidate($data) + { + $leg = new Leg(); + + $this->setExpectedException($data['exception']); + + $leg->setDepartureDate($data['value']); + } + + public function validDataProvider() + { + return array( + array( + array( + "departure_airport" => "LED", + "destination_airport" => "AMS", + "departure_date" => "2018-06-20", + ), + ), + array( + array( + "departure_airport" => "UGR", + "destination_airport" => "IVA", + "departure_date" => "2018-06-21", + ), + ), + ); + } + + public function invalidDataProvider() + { + return array( + array( + array( + "exception" => 'YooKassa\Common\Exceptions\InvalidPropertyValueTypeException', + "value" => array(), + ), + ), + array( + array( + "exception" => 'YooKassa\Common\Exceptions\InvalidPropertyValueException', + "value" => 'stringThatGreaterThanNeededCharsLongAndActuallyNotValidAtAll123', + ), + ), + ); + } +} \ No newline at end of file diff --git a/tests/Model/MetadataTest.php b/tests/Model/MetadataTest.php new file mode 100644 index 00000000..e1103a25 --- /dev/null +++ b/tests/Model/MetadataTest.php @@ -0,0 +1,89 @@ + $value) { + $instance->offsetSet($key, $value); + } + self::assertEquals($source, $instance->toArray()); + } + + /** + * @dataProvider dataProvider + * @param array $source + */ + public function testCount($source) + { + $instance = new Metadata(); + $count = 0; + self::assertEquals($count, $instance->count()); + foreach ($source as $key => $value) { + $instance->offsetSet($key, $value); + $count++; + self::assertEquals($count, $instance->count()); + } + } + + /** + * @dataProvider dataProvider + * @param array $source + */ + public function testGetIterator($source) + { + $instance = new Metadata(); + foreach ($source as $key => $value) { + $instance->offsetSet($key, $value); + } + + $iterator = $instance->getIterator(); + $tmp = $source; + for ($iterator->rewind(); $iterator->valid(); $iterator->next()) { + self::assertArrayHasKey($iterator->key(), $source); + self::assertEquals($source[$iterator->key()], $iterator->current()); + unset($tmp[$iterator->key()]); + } + self::assertEquals(0, count($tmp)); + + $tmp = $source; + foreach ($instance as $key => $value) { + self::assertArrayHasKey($key, $source); + self::assertEquals($source[$key], $value); + unset($tmp[$key]); + } + self::assertEquals(0, count($tmp)); + } + + public function dataProvider() + { + return array( + array( + array('testKey' => 'testValue'), + ), + array( + array( + 'testKey1' => 'testValue1', + 'testKey2' => 'testValue2', + ), + ), + array( + array( + 'testKey1' => 'testValue1', + 'testKey2' => 'testValue2', + 'testKey3' => 'testValue3', + ), + ), + ); + } +} \ No newline at end of file diff --git a/tests/Model/MonetaryAmountTest.php b/tests/Model/MonetaryAmountTest.php new file mode 100644 index 00000000..b973db55 --- /dev/null +++ b/tests/Model/MonetaryAmountTest.php @@ -0,0 +1,335 @@ +getValue()); + self::assertEquals(self::DEFAULT_CURRENCY, $instance->getCurrency()); + + $instance = new MonetaryAmount($value, $currency); + + self::assertEquals(number_format($value, 2, '.', ''), $instance->getValue()); + self::assertEquals(strtoupper($currency), $instance->getCurrency()); + } + + /** + * @dataProvider validValueDataProvider + * + * @param $value + */ + public function testGetSetValue($value) + { + $expected = number_format($value, 2, '.', ''); + + $instance = self::getInstance(); + self::assertEquals(self::DEFAULT_VALUE, $instance->getValue()); + self::assertEquals(self::DEFAULT_VALUE, $instance->value); + $instance->setValue($value); + self::assertEquals($expected, $instance->getValue()); + self::assertEquals($expected, $instance->value); + + $instance = self::getInstance(); + $instance->value = $value; + self::assertEquals($expected, $instance->getValue()); + self::assertEquals($expected, $instance->value); + } + + /** + * @dataProvider invalidValueDataProvider + * @param mixed $value + * @param string $exceptionClassName + */ + public function testSetInvalidValue($value, $exceptionClassName) + { + $instance = self::getInstance(); + try { + $instance->setValue($value); + } catch (\Exception $e) { + self::assertInstanceOf($exceptionClassName, $e); + } + } + + /** + * @dataProvider invalidValueDataProvider + * @param mixed $value + * @param string $exceptionClassName + */ + public function testSetterInvalidValue($value, $exceptionClassName) + { + $instance = self::getInstance(); + try { + $instance->value = $value; + } catch (\Exception $e) { + self::assertInstanceOf($exceptionClassName, $e); + } + } + + /** + * @dataProvider validCurrencyDataProvider + * @param string $currency + */ + public function testGetSetCurrency($currency) + { + $instance = self::getInstance(); + + self::assertEquals(self::DEFAULT_CURRENCY, $instance->getCurrency()); + self::assertEquals(self::DEFAULT_CURRENCY, $instance->currency); + $instance->setCurrency($currency); + self::assertEquals(strtoupper($currency), $instance->getCurrency()); + self::assertEquals(strtoupper($currency), $instance->currency); + } + + /** + * @dataProvider invalidCurrencyDataProvider + * @param string $currency + * @param string $exceptionClassName + */ + public function testSetInvalidCurrency($currency, $exceptionClassName) + { + $instance = self::getInstance(); + try { + $instance->setCurrency($currency); + } catch (\Exception $e) { + self::assertInstanceOf($exceptionClassName, $e); + } + } + + /** + * @dataProvider invalidCurrencyDataProvider + * @param string $currency + * @param string $exceptionClassName + */ + public function testSetterInvalidCurrency($currency, $exceptionClassName) + { + $instance = self::getInstance(); + try { + $instance->currency = $currency; + } catch (\Exception $e) { + self::assertInstanceOf($exceptionClassName, $e); + } + } + + public function validDataProvider() + { + $result = $this->validValueDataProvider(); + foreach ($this->validCurrencyDataProvider() as $index => $tmp) { + if (isset($result[$index])) { + $result[$index][] = $tmp[0]; + } + } + return $result; + } + + public function validValueDataProvider() + { + $result = array( + array(0.01), + array(0.1), + array(0.11), + array(0.1111), + array(0.1166), + array('0.01'), + array(1), + array('1'), + ); + for ($i = 0; $i < 10; $i++) { + $result[] = array(Random::float(0, 9999999)); + } + return $result; + } + + public function validCurrencyDataProvider() + { + $result = array(); + foreach (CurrencyCode::getValidValues() as $value) { + $result[] = array($value); + $result[] = array(strtolower($value[0]) . $value[1] . $value[2]); + $result[] = array($value[0] . strtolower($value[1]) . $value[2]); + $result[] = array($value[0] . $value[1] . strtolower($value[2])); + $result[] = array(strtolower($value[0]) . strtolower($value[1]) . $value[2]); + $result[] = array(strtolower($value[0]) . $value[1] . strtolower($value[2])); + $result[] = array(strtolower($value)); + } + return $result; + } + + public function invalidValueDataProvider() + { + $exceptionNamespace = 'YooKassa\\Common\\Exceptions\\'; + return array( + array(null, $exceptionNamespace . 'EmptyPropertyValueException'), + array('', $exceptionNamespace . 'EmptyPropertyValueException'), + array(array(), $exceptionNamespace . 'InvalidPropertyValueTypeException'), + array(fopen(__FILE__, 'r'), $exceptionNamespace . 'InvalidPropertyValueTypeException'), + array('invalid_value', $exceptionNamespace . 'InvalidPropertyValueTypeException'), + array(-1, $exceptionNamespace . 'InvalidPropertyValueException'), + array(-0.01, $exceptionNamespace . 'InvalidPropertyValueException'), + array(0.0, $exceptionNamespace . 'InvalidPropertyValueException'), + array(0, $exceptionNamespace . 'InvalidPropertyValueException'), + array(0.001, $exceptionNamespace . 'InvalidPropertyValueException'), + array(true, $exceptionNamespace . 'InvalidPropertyValueTypeException'), + array(false, $exceptionNamespace . 'InvalidPropertyValueTypeException'), + ); + } + + public function invalidCurrencyDataProvider() + { + $exceptionNamespace = 'YooKassa\\Common\\Exceptions\\'; + return array( + array(null, $exceptionNamespace . 'EmptyPropertyValueException'), + array('', $exceptionNamespace . 'EmptyPropertyValueException'), + array(array(), $exceptionNamespace . 'InvalidPropertyValueTypeException'), + array(fopen(__FILE__, 'r'), $exceptionNamespace . 'InvalidPropertyValueTypeException'), + array('invalid_value', $exceptionNamespace . 'InvalidPropertyValueException'), + array('III', $exceptionNamespace . 'InvalidPropertyValueException'), + array(-0.01, $exceptionNamespace . 'InvalidPropertyValueTypeException'), + array(0.0, $exceptionNamespace . 'InvalidPropertyValueTypeException'), + array(0, $exceptionNamespace . 'InvalidPropertyValueTypeException'), + array(0.01, $exceptionNamespace . 'InvalidPropertyValueTypeException'), + array(true, $exceptionNamespace . 'InvalidPropertyValueTypeException'), + array(false, $exceptionNamespace . 'InvalidPropertyValueTypeException'), + ); + } + + /** + * @dataProvider validMultiplyDataProvider + * @param $source + * @param $coefficient + * @param $expected + */ + public function testMultiply($source, $coefficient, $expected) + { + $instance = new MonetaryAmount($source); + $instance->multiply($coefficient); + self::assertEquals($expected, $instance->getIntegerValue()); + } + + public function validMultiplyDataProvider() + { + return array( + array(1, 0.5, 50), + array(1.01, 0.5, 51), + array(1.00, 0.01, 1), + array(0.99, 0.01, 1), + ); + } + + /** + * @dataProvider invalidMultiplyDataProvider + * @expectedException \InvalidArgumentException + * @param $source + * @param $coefficient + */ + public function testInvalidMultiply($source, $coefficient) + { + $instance = new MonetaryAmount($source); + $instance->multiply($coefficient); + } + + public function invalidMultiplyDataProvider() + { + return array( + array(1, null), + array(1.01, ''), + array(1.00, true), + array(0.99, false), + array(0.99, array()), + array(0.99, new \stdClass()), + array(0.99, 'test'), + array(0.99, -1.0), + array(0.99, -0.0), + array(0.99, -0.00001), + array(0.99, 0.000001), + ); + } + + /** + * @dataProvider validIncreaseDataProvider + * @param $source + * @param $amount + * @param $expected + */ + public function testIncrease($source, $amount, $expected) + { + $instance = new MonetaryAmount($source); + $instance->increase($amount); + self::assertEquals($expected, $instance->getIntegerValue()); + } + + public function validIncreaseDataProvider() + { + return array( + array(1, 0.5, 150), + array(1.01, -0.5, 51), + array(1.00, -0.001, 100), + array(0.99, 0.01, 100), + ); + } + + /** + * @dataProvider invalidIncreaseDataProvider + * @expectedException \InvalidArgumentException + * @param $source + * @param $amount + */ + public function testInvalidIncrease($source, $amount) + { + $instance = new MonetaryAmount($source); + $instance->increase($amount); + } + + public function invalidIncreaseDataProvider() + { + return array( + array(1, null), + array(1.01, ''), + array(1.00, true), + array(0.99, false), + array(0.99, array()), + array(0.99, new \stdClass()), + array(0.99, 'test'), + array(0.99, -1.0), + array(0.99, -0.99), + ); + } + + /** + * @dataProvider validDataProvider + * + * @param $value + * @param $currency + */ + public function testJsonSerialize($value, $currency) + { + $instance = new MonetaryAmount($value, $currency); + $expected = array( + 'value' => number_format($value, 2, '.', ''), + 'currency' => strtoupper($currency), + ); + self::assertEquals($expected, $instance->jsonSerialize()); + } +} diff --git a/tests/Model/Notification/AbstractNotificationTest.php b/tests/Model/Notification/AbstractNotificationTest.php new file mode 100644 index 00000000..b6a01a68 --- /dev/null +++ b/tests/Model/Notification/AbstractNotificationTest.php @@ -0,0 +1,146 @@ +getTestInstance($value); + self::assertEquals($this->getExpectedType(), $instance->getType()); + } + + /** + * @dataProvider invalidConstructorTypeDataProvider + * @expectedException \InvalidArgumentException + * @param array $source + */ + public function testInvalidTypeInConstructor(array $source) + { + $this->getTestInstance($source); + } + + /** + * @dataProvider validDataProvider + * @param array $value + */ + public function testGetEvent(array $value) + { + $instance = $this->getTestInstance($value); + self::assertEquals($this->getExpectedEvent(), $instance->getEvent()); + } + + /** + * @dataProvider invalidConstructorEventDataProvider + * @expectedException \InvalidArgumentException + * @param array $source + */ + public function testInvalidEventInConstructor(array $source) + { + $this->getTestInstance($source); + } + + /** + * @dataProvider invalidTypeDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testInvalidType($value) + { + new TestNotification($value, $this->getExpectedEvent()); + } + + /** + * @dataProvider invalidEventDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testInvalidEvent($value) + { + new TestNotification($this->getExpectedType(), $value); + } + + public function invalidConstructorTypeDataProvider() + { + return array( + array(array('event' => $this->getExpectedEvent(), 'type' => 'test')), + array(array('event' => $this->getExpectedEvent(), 'type' => null)), + array(array('event' => $this->getExpectedEvent(), 'type' => '')), + array(array('event' => $this->getExpectedEvent(), 'type' => 1)), + array(array('event' => $this->getExpectedEvent(), 'type' => array())), + ); + } + + public function invalidConstructorEventDataProvider() + { + return array( + array(array('type' => $this->getExpectedType(), 'event' => 'test')), + array(array('type' => $this->getExpectedType(), 'event' => null)), + array(array('type' => $this->getExpectedType(), 'event' => '')), + array(array('type' => $this->getExpectedType(), 'event' => 1)), + array(array('type' => $this->getExpectedType(), 'event' => array())), + ); + } + + public function invalidTypeDataProvider() + { + return array( + array(''), + array(null), + array(Random::str(40)), + array(0), + array(array()), + array(new \stdClass()), + ); + } + + public function invalidEventDataProvider() + { + return array( + array(''), + array(null), + array(Random::str(40)), + array(0), + array(array()), + array(new \stdClass()), + ); + } +} + +class TestNotification extends AbstractNotification +{ + public function __construct($type, $event) + { + $this->_setType($type); + $this->_setEvent($event); + } +} \ No newline at end of file diff --git a/tests/Model/Notification/NotificationCanceledTest.php b/tests/Model/Notification/NotificationCanceledTest.php new file mode 100644 index 00000000..b60ffc30 --- /dev/null +++ b/tests/Model/Notification/NotificationCanceledTest.php @@ -0,0 +1,117 @@ +getTestInstance($value); + self::assertTrue($instance->getObject() instanceof PaymentInterface); + self::assertEquals($value['object']['id'], $instance->getObject()->getId()); + } + + /** + * @return array + * @throws \Exception + */ + public function validDataProvider() + { + $result = array(); + $statuses = PaymentStatus::getValidValues(); + $receiptRegistrations = ReceiptRegistrationStatus::getValidValues(); + + $confirmations = array( + array( + 'type' => ConfirmationType::REDIRECT, + 'confirmation_url' => Random::str(10), + 'return_url' => Random::str(10), + 'enforce' => false, + ), + array( + 'type' => ConfirmationType::EXTERNAL, + ), + ); + + for ($i = 0; $i < 10; $i++) { + $payment = array( + 'id' => Random::str(36), + 'status' => Random::value($statuses), + 'recipient' => array( + 'account_id' => Random::str(1, 64, '0123456789'), + 'gateway_id' => Random::str(1, 256), + ), + 'amount' => array( + 'value' => Random::float(0.01, 1000000.0), + 'currency' => Random::value(CurrencyCode::getValidValues()), + ), + 'payment_method' => array( + 'type' => PaymentMethodType::QIWI, + ), + 'created_at' => date(DATE_ATOM, Random::int(1, time())), + 'captured_at' => date(DATE_ATOM, Random::int(1, time())), + 'confirmation' => Random::value($confirmations), + 'refunded' => array( + 'value' => Random::float(0.01, 1000000.0), + 'currency' => Random::value(CurrencyCode::getValidValues()), + ), + 'paid' => $i % 2 ? true : false, + 'refundable' => $i % 2 ? true : false, + 'receipt_registration' => Random::value($receiptRegistrations), + 'metadata' => array( + 'value' => Random::float(0.01, 1000000.0), + 'currency' => Random::str(1, 256), + ), + ); + $result[] = array( + array( + 'type' => $this->getExpectedType(), + 'event' => $this->getExpectedEvent(), + 'object' => $payment, + ), + ); + } + return $result; + } +} diff --git a/tests/Model/Notification/NotificationFactoryTest.php b/tests/Model/Notification/NotificationFactoryTest.php new file mode 100644 index 00000000..eafff556 --- /dev/null +++ b/tests/Model/Notification/NotificationFactoryTest.php @@ -0,0 +1,214 @@ +getTestInstance(); + $instance->factory($options); + } + + /** + * @dataProvider validArrayDataProvider + * @param array $options + */ + public function testFactory($options) + { + $instance = $this->getTestInstance(); + $event = $options['event']; + $notification = $instance->factory($options); + self::assertNotNull($notification); + self::assertTrue($notification instanceof AbstractNotification); + + self::assertEquals($event, $notification->getEvent()); + foreach ($options as $property => $value) { + if ($property !== 'object') { + self::assertEquals($notification->{$property}, $value); + } else { + $this->assertObject($event, $notification->{$property}, $value); + } + } + } + + /** + * @return array + * @throws \Exception + */ + public function validArrayDataProvider() + { + $result = array(); + + for ($i = 0; $i < 12; $i++) { + $eventType = Random::value(NotificationEventType::getEnabledValues()); + switch($eventType) { + case NotificationEventType::REFUND_SUCCEEDED: + $notification = $this->getRefundNotification(); + break; + default: + $notification = $this->getPaymentNotification($eventType); + } + + $result[] = $notification; + } + + return $result; + } + + public function invalidDataArrayDataProvider() + { + return array( + array(array()), + array(array('type' => 'test')), + array(array('event' => 'test')), + ); + } + + private function getRefundNotification() + { + $statuses = RefundStatus::getValidValues(); + $receiptRegistrations = ReceiptRegistrationStatus::getValidValues(); + + $refund = array( + 'id' => Random::str(36), + 'payment_id' => Random::str(36), + 'status' => Random::value($statuses), + 'amount' => array( + 'value' => Random::float(0.01, 1000000.0), + 'currency' => Random::value(CurrencyCode::getValidValues()), + ), + 'created_at' => date(DATE_ATOM, Random::int(1, time())), + 'receipt_registration' => Random::value($receiptRegistrations), + 'description' => Random::str(1, 128), + ); + + return array( + array( + 'type' => $this->getExpectedType(), + 'event' => NotificationEventType::REFUND_SUCCEEDED, + 'object' => $refund, + ), + ); + } + + private function getPaymentNotification($type) + { + $statuses = PaymentStatus::getValidValues(); + $receiptRegistrations = ReceiptRegistrationStatus::getValidValues(); + + $trueFalse = Random::bool(); + $confirmations = array( + array( + 'type' => ConfirmationType::REDIRECT, + 'confirmation_url' => Random::str(10), + 'return_url' => Random::str(10), + 'enforce' => false, + ), + array( + 'type' => ConfirmationType::EXTERNAL, + ), + ); + + $payment = array( + 'id' => Random::str(36), + 'status' => Random::value($statuses), + 'recipient' => array( + 'account_id' => Random::str(1, 64, '0123456789'), + 'gateway_id' => Random::str(1, 256), + ), + 'amount' => array( + 'value' => Random::float(0.01, 1000000.0), + 'currency' => Random::value(CurrencyCode::getValidValues()), + ), + 'payment_method' => array( + 'type' => PaymentMethodType::QIWI, + ), + 'created_at' => date(DATE_ATOM, Random::int(1, time())), + 'captured_at' => date(DATE_ATOM, Random::int(1, time())), + 'confirmation' => Random::value($confirmations), + 'refunded' => array( + 'value' => Random::float(0.01, 1000000.0), + 'currency' => Random::value(CurrencyCode::getValidValues()), + ), + 'paid' => $trueFalse, + 'refundable' => $trueFalse, + 'receipt_registration' => Random::value($receiptRegistrations), + 'metadata' => array( + 'value' => Random::float(0.01, 1000000.0), + 'currency' => Random::str(1, 256), + ), + ); + + return array( + array( + 'type' => $this->getExpectedType(), + 'event' => $type, + 'object' => $payment, + ), + ); + } + + /** + * @return string + */ + protected function getExpectedType() + { + return NotificationType::NOTIFICATION; + } + + /** + * @return mixed + * @throws \Exception + */ + protected function getExpectedEvent() + { + return Random::value(NotificationEventType::getEnabledValues()); + } + + private function assertObject($event, $object, $value) + { + self::assertNotNull($object); + switch ($event) { + case NotificationEventType::REFUND_SUCCEEDED: + self::assertTrue($object instanceof RefundResponse); + self::assertEquals($object, new RefundResponse($value)); + break; + case NotificationEventType::PAYMENT_SUCCEEDED: + case NotificationEventType::PAYMENT_WAITING_FOR_CAPTURE: + case NotificationEventType::PAYMENT_CANCELED: + self::assertTrue($object instanceof PaymentResponse); + self::assertEquals($object, new PaymentResponse($value)); + break; + } + } + +} \ No newline at end of file diff --git a/tests/Model/Notification/NotificationRefundSucceededTest.php b/tests/Model/Notification/NotificationRefundSucceededTest.php new file mode 100644 index 00000000..6be06b5c --- /dev/null +++ b/tests/Model/Notification/NotificationRefundSucceededTest.php @@ -0,0 +1,90 @@ +getTestInstance($value); + self::assertTrue($instance->getObject() instanceof RefundInterface); + self::assertEquals($value['object']['id'], $instance->getObject()->getId()); + } + + /** + * @return array + * @throws \Exception + */ + public function validDataProvider() + { + $result = array(); + $statuses = RefundStatus::getValidValues(); + $receiptRegistrations = ReceiptRegistrationStatus::getValidValues(); + + for ($i = 0; $i < 10; $i++) { + $refund = array( + 'id' => Random::str(36), + 'payment_id' => Random::str(36), + 'status' => Random::value($statuses), + 'amount' => array( + 'value' => Random::float(0.01, 1000000.0), + 'currency' => Random::value(CurrencyCode::getValidValues()), + ), + 'created_at' => date(DATE_ATOM, Random::int(1, time())), + 'receipt_registration' => Random::value($receiptRegistrations), + 'description' => Random::str(1, 128), + ); + $result[] = array( + array( + 'type' => $this->getExpectedType(), + 'event' => $this->getExpectedEvent(), + 'object' => $refund, + ), + ); + } + + return $result; + } +} diff --git a/tests/Model/Notification/NotificationSucceededTest.php b/tests/Model/Notification/NotificationSucceededTest.php new file mode 100644 index 00000000..90340bd0 --- /dev/null +++ b/tests/Model/Notification/NotificationSucceededTest.php @@ -0,0 +1,117 @@ +getTestInstance($value); + self::assertTrue($instance->getObject() instanceof PaymentInterface); + self::assertEquals($value['object']['id'], $instance->getObject()->getId()); + } + + /** + * @return array + * @throws \Exception + */ + public function validDataProvider() + { + $result = array(); + $statuses = PaymentStatus::getValidValues(); + $receiptRegistrations = ReceiptRegistrationStatus::getValidValues(); + + $confirmations = array( + array( + 'type' => ConfirmationType::REDIRECT, + 'confirmation_url' => Random::str(10), + 'return_url' => Random::str(10), + 'enforce' => false, + ), + array( + 'type' => ConfirmationType::EXTERNAL, + ), + ); + + for ($i = 0; $i < 10; $i++) { + $payment = array( + 'id' => Random::str(36), + 'status' => Random::value($statuses), + 'recipient' => array( + 'account_id' => Random::str(1, 64, '0123456789'), + 'gateway_id' => Random::str(1, 256), + ), + 'amount' => array( + 'value' => Random::float(0.01, 1000000.0), + 'currency' => Random::value(CurrencyCode::getValidValues()), + ), + 'payment_method' => array( + 'type' => PaymentMethodType::QIWI, + ), + 'created_at' => date(DATE_ATOM, Random::int(1, time())), + 'captured_at' => date(DATE_ATOM, Random::int(1, time())), + 'confirmation' => Random::value($confirmations), + 'refunded' => array( + 'value' => Random::float(0.01, 1000000.0), + 'currency' => Random::value(CurrencyCode::getValidValues()), + ), + 'paid' => $i % 2 ? true : false, + 'refundable' => $i % 2 ? true : false, + 'receipt_registration' => Random::value($receiptRegistrations), + 'metadata' => array( + 'value' => Random::float(0.01, 1000000.0), + 'currency' => Random::str(1, 256), + ), + ); + $result[] = array( + array( + 'type' => $this->getExpectedType(), + 'event' => $this->getExpectedEvent(), + 'object' => $payment, + ), + ); + } + return $result; + } +} \ No newline at end of file diff --git a/tests/Model/Notification/NotificationWaitingForCaptureTest.php b/tests/Model/Notification/NotificationWaitingForCaptureTest.php new file mode 100644 index 00000000..acadf86a --- /dev/null +++ b/tests/Model/Notification/NotificationWaitingForCaptureTest.php @@ -0,0 +1,113 @@ +getTestInstance($value); + self::assertTrue($instance->getObject() instanceof PaymentInterface); + self::assertEquals($value['object']['id'], $instance->getObject()->getId()); + } + + public function validDataProvider() + { + $result = array(); + $statuses = PaymentStatus::getValidValues(); + $receiptRegistrations = ReceiptRegistrationStatus::getValidValues(); + + $confirmations = array( + array( + 'type' => ConfirmationType::REDIRECT, + 'confirmation_url' => Random::str(10), + 'return_url' => Random::str(10), + 'enforce' => false, + ), + array( + 'type' => ConfirmationType::EXTERNAL, + ), + ); + + for ($i = 0; $i < 10; $i++) { + $payment = array( + 'id' => Random::str(36), + 'status' => Random::value($statuses), + 'recipient' => array( + 'account_id' => Random::str(1, 64, '0123456789'), + 'gateway_id' => Random::str(1, 256), + ), + 'amount' => array( + 'value' => Random::float(0.01, 1000000.0), + 'currency' => Random::value(CurrencyCode::getValidValues()), + ), + 'payment_method' => array( + 'type' => PaymentMethodType::QIWI, + ), + 'created_at' => date(DATE_ATOM, Random::int(1, time())), + 'captured_at' => date(DATE_ATOM, Random::int(1, time())), + 'confirmation' => Random::value($confirmations), + 'refunded' => array( + 'value' => Random::float(0.01, 1000000.0), + 'currency' => Random::value(CurrencyCode::getValidValues()), + ), + 'paid' => $i % 2 ? true : false, + 'refundable' => $i % 2 ? true : false, + 'receipt_registration' => Random::value($receiptRegistrations), + 'metadata' => array( + 'value' => Random::float(0.01, 1000000.0), + 'currency' => Random::str(1, 256), + ), + ); + $result[] = array( + array( + 'type' => $this->getExpectedType(), + 'event' => $this->getExpectedEvent(), + 'object' => $payment, + ), + ); + } + return $result; + } +} \ No newline at end of file diff --git a/tests/Model/PassengerTest.php b/tests/Model/PassengerTest.php new file mode 100644 index 00000000..75f19293 --- /dev/null +++ b/tests/Model/PassengerTest.php @@ -0,0 +1,134 @@ +setFirstName($name); + self::assertEquals($name, $instance->getFirstName()); + self::assertEquals($name, $instance->firstName); + self::assertEquals($name, $instance->first_name); + } + + /** + * @dataProvider validDataProvider + * + * @param $name + */ + public function testGetSetLastName($name) + { + $instance = self::getInstance(); + $instance->setLastName($name); + self::assertEquals($name, $instance->getLastName()); + self::assertEquals($name, $instance->lastName); + self::assertEquals($name, $instance->last_name); + } + + /** + * @dataProvider invalidValueDataProvider + * @param mixed $value + * @param string $exceptionClassName + */ + public function testSetInvalidFirstName($value, $exceptionClassName) + { + $instance = self::getInstance(); + try { + $instance->setFirstName($value); + } catch (\Exception $e) { + self::assertInstanceOf($exceptionClassName, $e); + } + } + + /** + * @dataProvider invalidValueDataProvider + * @param mixed $value + * @param string $exceptionClassName + */ + public function testSetterInvalidLastName($value, $exceptionClassName) + { + $instance = self::getInstance(); + try { + $instance->setLastName($value); + } catch (\Exception $e) { + self::assertInstanceOf($exceptionClassName, $e); + } + } + + /** + * @return array + * @throws \Exception + */ + public function validDataProvider() + { + $alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + return array( + array( + 'firstName' => Random::str(1, null, $alphabet), + 'lastName' => Random::str(1, null, $alphabet), + ), + array( + 'firstName' => Random::str(64, null, $alphabet), + 'lastName' => Random::str(64, null, $alphabet), + ) + ); + } + + /** + * @return array + * @throws \Exception + */ + public function invalidValueDataProvider() + { + $exceptionNamespace = 'YooKassa\\Common\\Exceptions\\'; + return array( + array(null, $exceptionNamespace.'InvalidPropertyValueTypeException'), + array('', $exceptionNamespace.'InvalidPropertyValueTypeException'), + array(array(), $exceptionNamespace.'InvalidPropertyValueTypeException'), + array(fopen(__FILE__, 'r'), $exceptionNamespace.'InvalidPropertyValueTypeException'), + array(Random::str(65), $exceptionNamespace.'InvalidPropertyValueException'), + array(-1, $exceptionNamespace.'InvalidPropertyValueTypeException'), + array(-0.01, $exceptionNamespace.'InvalidPropertyValueTypeException'), + array(0.0, $exceptionNamespace.'InvalidPropertyValueTypeException'), + array(true, $exceptionNamespace.'InvalidPropertyValueTypeException'), + array(false, $exceptionNamespace.'InvalidPropertyValueTypeException'), + ); + } + + /** + * @dataProvider validDataProvider + * + * @param string $firstName + * @param string $lastName + */ + public function testJsonSerialize($firstName, $lastName) + { + $instance = self::getInstance(); + $instance->setFirstName($firstName); + $instance->setLastName($lastName); + + $expected = array( + 'first_name' => $firstName, + 'last_name' => $lastName, + ); + self::assertEquals($expected, $instance->jsonSerialize()); + } +} diff --git a/tests/Model/PaymentData/AbstractPaymentDataApplePayTest.php b/tests/Model/PaymentData/AbstractPaymentDataApplePayTest.php new file mode 100644 index 00000000..f06b892c --- /dev/null +++ b/tests/Model/PaymentData/AbstractPaymentDataApplePayTest.php @@ -0,0 +1,115 @@ +getTestInstance(); + + self::assertNull($instance->getPaymentData()); + self::assertNull($instance->paymentData); + self::assertNull($instance->payment_data); + + $instance->setPaymentData($value); + if ($value === null || $value === '') { + self::assertNull($instance->getPaymentData()); + self::assertNull($instance->paymentData); + self::assertNull($instance->payment_data); + } else { + self::assertEquals($value, $instance->getPaymentData()); + self::assertEquals($value, $instance->paymentData); + self::assertEquals($value, $instance->payment_data); + } + + $instance = $this->getTestInstance(); + $instance->paymentData = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getPaymentData()); + self::assertNull($instance->paymentData); + self::assertNull($instance->payment_data); + } else { + self::assertEquals($value, $instance->getPaymentData()); + self::assertEquals($value, $instance->paymentData); + self::assertEquals($value, $instance->payment_data); + } + + $instance = $this->getTestInstance(); + $instance->payment_data = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getPaymentData()); + self::assertNull($instance->paymentData); + self::assertNull($instance->payment_data); + } else { + self::assertEquals($value, $instance->getPaymentData()); + self::assertEquals($value, $instance->paymentData); + self::assertEquals($value, $instance->payment_data); + } + } + + /** + * @dataProvider invalidPaymentDataDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidPaymentData($value) + { + /** @var PaymentDataApplePay $instance */ + $instance = $this->getTestInstance(); + $instance->setPaymentData($value); + } + + /** + * @dataProvider invalidPaymentDataDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidPaymentData($value) + { + /** @var PaymentDataApplePay $instance */ + $instance = $this->getTestInstance(); + $instance->paymentData = $value; + } + + /** + * @dataProvider invalidPaymentDataDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidPayment_data($value) + { + /** @var PaymentDataApplePay $instance */ + $instance = $this->getTestInstance(); + $instance->payment_data = $value; + } + + public function validPaymentDataDataProvider() + { + return array( + array('http://test.ru'), + array(Random::str(256)), + array(Random::str(1024)), + ); + } + + public function invalidPaymentDataDataProvider() + { + return array( + array(null), + array(''), + array(true), + array(false), + array(array()), + array(new \stdClass()), + ); + } +} diff --git a/tests/Model/PaymentData/AbstractPaymentDataGooglePayTest.php b/tests/Model/PaymentData/AbstractPaymentDataGooglePayTest.php new file mode 100644 index 00000000..5f687554 --- /dev/null +++ b/tests/Model/PaymentData/AbstractPaymentDataGooglePayTest.php @@ -0,0 +1,93 @@ +getTestInstance(); + + self::assertNull($instance->getPaymentMethodToken()); + + $instance->setPaymentMethodToken($data); + self::assertEquals($data, $instance->getPaymentMethodToken()); + + + $instance = $this->getTestInstance(); + $instance->paymentMethodToken = $data; + self::assertEquals($data, $instance->getPaymentMethodToken()); + } + + /** + * @dataProvider validPaymentDataDataProvider + * @param string $data + */ + public function testGetSetGoogleTransactionId($data) + { + /** @var PaymentDataGooglePay $instance */ + $instance = $this->getTestInstance(); + + self::assertNull($instance->getGoogleTransactionId()); + + $instance->setGoogleTransactionId($data); + self::assertEquals($data, $instance->getGoogleTransactionId()); + + $instance = $this->getTestInstance(); + $instance->googleTransactionId = $data; + self::assertEquals($data, $instance->getGoogleTransactionId()); + } + + /** + * @dataProvider invalidPaymentDataDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $data + */ + public function testSetPaymentMethodToken($data) + { + /** @var PaymentDataGooglePay $instance */ + $instance = $this->getTestInstance(); + $instance->setPaymentMethodToken($data); + } + + + /** + * @dataProvider invalidPaymentDataDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $data + */ + public function testSetGoogleTransactionId($data) + { + /** @var PaymentDataGooglePay $instance */ + $instance = $this->getTestInstance(); + $instance->setGoogleTransactionId($data); + } + + public function validPaymentDataDataProvider() + { + return array( + array(Random::str(256)), + array(Random::str(1024)), + ); + } + + public function invalidPaymentDataDataProvider() + { + return array( + array(null), + array(''), + array(true), + array(false), + array(array()), + array(new \stdClass()), + ); + } +} diff --git a/tests/Model/PaymentData/AbstractPaymentDataPhoneTest.php b/tests/Model/PaymentData/AbstractPaymentDataPhoneTest.php new file mode 100644 index 00000000..bcd78e0b --- /dev/null +++ b/tests/Model/PaymentData/AbstractPaymentDataPhoneTest.php @@ -0,0 +1,85 @@ +getTestInstance(); + + self::assertNull($instance->getPhone()); + self::assertNull($instance->phone); + + $instance->setPhone($value); + self::assertEquals($value, $instance->getPhone()); + self::assertEquals($value, $instance->phone); + + $instance = $this->getTestInstance(); + $instance->phone = $value; + self::assertEquals($value, $instance->getPhone()); + self::assertEquals($value, $instance->phone); + } + + /** + * @dataProvider invalidPhoneDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidPhone($value) + { + /** @var PaymentDataMobileBalance $instance */ + $instance = $this->getTestInstance(); + $instance->setPhone($value); + } + + /** + * @dataProvider invalidPhoneDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidPhone($value) + { + /** @var PaymentDataMobileBalance $instance */ + $instance = $this->getTestInstance(); + $instance->phone = $value; + } + + public function validPhoneDataProvider() + { + return array( + array('0123'), + array('45678'), + array('901234'), + array('5678901'), + array('23456789'), + array('012345678'), + array('9012345678'), + array('90123456789'), + array('012345678901'), + array('5678901234567'), + array('89012345678901'), + array('234567890123456'), + ); + } + + public function invalidPhoneDataProvider() + { + return array( + array(null), + array(''), + array(true), + array(false), + array(array()), + array(new \stdClass()), + array('2345678901234567'), + ); + } +} \ No newline at end of file diff --git a/tests/Model/PaymentData/AbstractPaymentDataTest.php b/tests/Model/PaymentData/AbstractPaymentDataTest.php new file mode 100644 index 00000000..e27fa2c0 --- /dev/null +++ b/tests/Model/PaymentData/AbstractPaymentDataTest.php @@ -0,0 +1,59 @@ +getTestInstance(); + self::assertEquals($this->getExpectedType(), $instance->getType()); + } + + /** + * @dataProvider invalidTypeDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testInvalidType($value) + { + new TestPaymentData($value); + } + + public function invalidTypeDataProvider() + { + return array( + array(''), + array(null), + array(Random::str(40)), + array(0), + array(array()), + array(new \stdClass()), + ); + } +} + +class TestPaymentData extends AbstractPaymentData +{ + public function __construct($type) + { + $this->_setType($type); + } +} \ No newline at end of file diff --git a/tests/Model/PaymentData/B2b/Sberbank/VatDataTest.php b/tests/Model/PaymentData/B2b/Sberbank/VatDataTest.php new file mode 100644 index 00000000..46cb8c28 --- /dev/null +++ b/tests/Model/PaymentData/B2b/Sberbank/VatDataTest.php @@ -0,0 +1,287 @@ +getType()); + self::assertEquals($value['rate'], $instance->getRate()); + self::assertEquals($value['amount']->getValue(), $instance->getAmount()->getValue()); + + } + + /** + * @dataProvider validTypeDataProvider + * @param string $value + */ + public function testGetSetType($value) + { + $this->getAndSetTest($value, 'type'); + } + + /** + * @dataProvider invalidTypeDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidType($value) + { + $this->getTestInstance()->setType($value); + } + + /** + * @return array + * @throws \Exception + */ + public function validConstructDataProvider() + { + $result = array( + array( + array( + 'type' => VatDataType::CALCULATED, + 'rate' => VatDataRate::RATE_18, + 'amount' => new MonetaryAmount(Random::int(1, 1000)) + ), + ), + ); + + return $result; + } + + /** + * @return array + * @throws \Exception + */ + public function validTypeDataProvider() + { + $result = array( + array(VatDataType::CALCULATED), + array(VatDataType::UNTAXED), + ); + + return $result; + } + + /** + * @return array + * @throws \Exception + */ + public function invalidTypeDataProvider() + { + return array( + array(''), + array(null), + array(0), + array(1), + array(-1), + array(array()), + array(new \stdClass()), + array(Random::str(20)), + ); + } + + /** + * @dataProvider validRateDataProvider + * @param string $value + */ + public function testGetSetRate($value) + { + $this->getAndSetTest($value, 'rate'); + } + + /** + * @dataProvider invalidRateDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidRate($value) + { + $this->getTestInstance()->setRate($value); + } + + /** + * @return array + * @throws \Exception + */ + public function validRateDataProvider() + { + $result = array( + array(VatDataRate::RATE_7), + array(VatDataRate::RATE_10), + array(VatDataRate::RATE_18), + array(VatDataRate::RATE_20), + ); + + return $result; + } + + /** + * @return array + * @throws \Exception + */ + public function invalidRateDataProvider() + { + return array( + array(''), + array(null), + array(0), + array(1), + array(-1), + array(array()), + array(new \stdClass()), + array(Random::str(20)), + ); + } + + /** + * @dataProvider validDataProvider + * @param array $value + */ + public function testGetSetAmount($value) + { + $instance = $this->getTestInstance(); + + self::assertNull($instance->getAmount()); + self::assertNull($instance->amount); + + $instance->setAmount($value); + if (is_array($value)) { + self::assertSame($value['value'], (int)$instance->getAmount()->getValue()); + self::assertSame($value['currency'], $instance->amount->getCurrency()); + } else { + self::assertSame($value, $instance->getAmount()); + self::assertSame($value, $instance->amount); + } + + $instance = $this->getTestInstance(); + + $instance->amount = $value; + if (is_array($value)) { + self::assertSame($value['value'], (int)$instance->getAmount()->getValue()); + self::assertSame($value['currency'], $instance->amount->getCurrency()); + } else { + self::assertSame($value, $instance->getAmount()); + self::assertSame($value, $instance->amount); + } + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidAmount($value) + { + self::setExpectedException('InvalidArgumentException'); + $instance = $this->getTestInstance(); + $instance->setAmount($value); + } + + /** + * @return array + * @throws \Exception + */ + public function validDataProvider() + { + $result = array( + array(null), + array( + array( + 'value' => Random::int(1, 1000), + 'currency' => CurrencyCode::EUR, + ) + ), + array(new MonetaryAmount(Random::int(1, 10000), CurrencyCode::RUB)) + ); + + return $result; + } + + /** + * @return array + * @throws \Exception + */ + public function invalidDataProvider() + { + return array( + array(''), + array(0), + array(1), + array(-1), + //array(array()), + array(new \stdClass()), + array(Random::str(20)), + ); + } + + /** + * @param $value + * @param string $property + * @param null $snakeCase + */ + protected function getAndSetTest($value, $property, $snakeCase = null) + { + $getter = 'get'.ucfirst($property); + $setter = 'set'.ucfirst($property); + + $instance = $this->getTestInstance(); + + self::assertNull($instance->{$getter}()); + self::assertNull($instance->{$property}); + if ($snakeCase !== null) { + self::assertNull($instance->{$snakeCase}); + } + + $instance->{$setter}($value); + + self::assertEquals($value, $instance->{$getter}()); + self::assertEquals($value, $instance->{$property}); + if ($snakeCase !== null) { + self::assertEquals($value, $instance->{$snakeCase}); + } + + $instance = $this->getTestInstance(); + + $instance->{$property} = $value; + + self::assertEquals($value, $instance->{$getter}()); + self::assertEquals($value, $instance->{$property}); + if ($snakeCase !== null) { + self::assertEquals($value, $instance->{$snakeCase}); + } + + if ($snakeCase !== null) { + $instance = $this->getTestInstance(); + + $instance->{$snakeCase} = $value; + + self::assertEquals($value, $instance->{$getter}()); + self::assertEquals($value, $instance->{$property}); + self::assertEquals($value, $instance->{$snakeCase}); + } + } +} \ No newline at end of file diff --git a/tests/Model/PaymentData/PaymentDataAlfabankTest.php b/tests/Model/PaymentData/PaymentDataAlfabankTest.php new file mode 100644 index 00000000..9ff685e5 --- /dev/null +++ b/tests/Model/PaymentData/PaymentDataAlfabankTest.php @@ -0,0 +1,90 @@ +getTestInstance(); + + self::assertNull($instance->getLogin()); + self::assertNull($instance->login); + + $instance->setLogin($value); + self::assertEquals($value, $instance->getLogin()); + self::assertEquals($value, $instance->login); + + $instance = $this->getTestInstance(); + $instance->login = $value; + self::assertEquals($value, $instance->getLogin()); + self::assertEquals($value, $instance->login); + } + + /** + * @dataProvider invalidLoginDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidLogin($value) + { + $instance = $this->getTestInstance(); + $instance->setLogin($value); + } + + /** + * @dataProvider invalidLoginDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidLogin($value) + { + $instance = $this->getTestInstance(); + $instance->login = $value; + } + + public function validLoginDataProvider() + { + return array( + array('123'), + array(Random::str(256)), + array(Random::str(1024)), + ); + } + + public function invalidLoginDataProvider() + { + return array( + array(null), + array(''), + array(true), + array(false), + array(array()), + array(new \stdClass()), + ); + } +} \ No newline at end of file diff --git a/tests/Model/PaymentData/PaymentDataApplePayTest.php b/tests/Model/PaymentData/PaymentDataApplePayTest.php new file mode 100644 index 00000000..46c31d0e --- /dev/null +++ b/tests/Model/PaymentData/PaymentDataApplePayTest.php @@ -0,0 +1,25 @@ +getTestInstance(); + + self::assertNull($instance->getPaymentPurpose()); + self::assertNull($instance->paymentPurpose); + + $instance->setPaymentPurpose($value); + + self::assertEquals($value, $instance->getPaymentPurpose()); + self::assertEquals($value, $instance->paymentPurpose); + } + + /** + * @dataProvider invalidPaymentPurposeDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidPaymentPurpose($value) + { + $this->getTestInstance()->setPaymentPurpose($value); + } + + /** + * @return array + * @throws \Exception + */ + public function validPaymentPurposeDataProvider() + { + return array( + array(Random::str(16)), + ); + } + + /** + * @return array + * @throws \Exception + */ + public function invalidPaymentPurposeDataProvider() + { + return array( + array(''), + array(true), + array(new \stdClass()), + array(Random::str(211)), + ); + } + + + /** + * @dataProvider validVatDataDataProvider + * @param mixed $value + */ + public function testGetSetVatData($value) + { + $instance = $this->getTestInstance(); + + self::assertNull($instance->getPaymentPurpose()); + self::assertNull($instance->paymentPurpose); + + $instance->setVatData($value); + + if (is_array($value)) { + self::assertEquals($value['type'], $instance->getVatData()->getType()); + self::assertEquals($value['type'], $instance->vatData->getType()); + if (isset($value['rate'])) { + self::assertEquals($value['rate'], $instance->getVatData()->getRate()); + self::assertEquals($value['rate'], $instance->vatData->getRate()); + } + if (isset($value['amount'])) { + if (is_array($value['amount'])) { + self::assertEquals($value['amount']['value'], + (int)$instance->getVatData()->getAmount()->getValue()); + self::assertEquals($value['amount']['currency'], $instance->vatData->getAmount()->getCurrency()); + } else { + self::assertEquals($value['amount'], $instance->getVatData()->getAmount()); + self::assertEquals($value['amount'], $instance->vatData->getAmount()); + } + } + } else { + self::assertEquals($value, $instance->getVatData()); + self::assertEquals($value, $instance->vatData); + } + } + + /** + * @dataProvider invalidVatDataDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidVatData($value) + { + $this->getTestInstance()->setVatData($value); + } + + /** + * @return array + * @throws \Exception + */ + public function validVatDataDataProvider() + { + return array( + array(null), + array(new VatData(VatDataType::UNTAXED)), + array(new VatData(VatDataType::CALCULATED, VatDataRate::RATE_7, new MonetaryAmount(Random::int(1, 10000)))), + array( + array( + 'type' => VatDataType::UNTAXED, + ) + ), + array( + array( + 'type' => VatDataType::CALCULATED, + 'rate' => VatDataRate::RATE_10, + 'amount' => new MonetaryAmount(Random::int(1, 10000), CurrencyCode::EUR), + ) + ), + array( + array( + 'type' => VatDataType::MIXED, + 'amount' => new MonetaryAmount(Random::int(1, 10000), CurrencyCode::EUR), + ) + ), + array( + array( + 'type' => VatDataType::CALCULATED, + 'rate' => VatDataRate::RATE_20, + 'amount' => array( + 'value' => Random::int(1, 10000), + 'currency' => CurrencyCode::USD, + ), + ) + ), + ); + } + + /** + * @return array + * @throws \Exception + */ + public function invalidVatDataDataProvider() + { + return array( + array(0), + array(1), + array(-1), + array(''), + array(true), + array(new \stdClass()), + array( + array( + 'type' => VatDataType::CALCULATED, + 'rate' => VatDataRate::RATE_10, + 'amount' => Random::str(10), + ) + ), + + ); + } +} \ No newline at end of file diff --git a/tests/Model/PaymentData/PaymentDataBankCardCardTest.php b/tests/Model/PaymentData/PaymentDataBankCardCardTest.php new file mode 100644 index 00000000..beb3f74d --- /dev/null +++ b/tests/Model/PaymentData/PaymentDataBankCardCardTest.php @@ -0,0 +1,384 @@ +getAndSetTest($value, 'number'); + } + + /** + * @dataProvider invalidNumberDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidNumber($value) + { + $this->getTestInstance()->setNumber($value); + } + + /** + * @dataProvider invalidNumberDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidNumber($value) + { + $this->getTestInstance()->number = $value; + } + + /** + * @dataProvider validExpiryYearDataProvider + * @param $value + */ + public function testGetSetExpiryYear($value) + { + $this->getAndSetTest($value, 'expiryYear', 'expiry_year'); + } + + /** + * @dataProvider invalidYearDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidYear($value) + { + $this->getTestInstance()->setExpiryYear($value); + } + + /** + * @dataProvider invalidYearDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidYear($value) + { + $this->getTestInstance()->expiryYear = $value; + } + + /** + * @dataProvider invalidYearDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalid_year($value) + { + $this->getTestInstance()->expiry_year = $value; + } + + /** + * @dataProvider invalidMonthDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidMonth($value) + { + $this->getTestInstance()->expiryMonth = $value; + } + + /** + * @dataProvider invalidMonthDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalid_month($value) + { + $this->getTestInstance()->expiry_month = $value; + } + + /** + * @dataProvider validExpiryMonthDataProvider + * @param $value + */ + public function testGetSetExpiryMonth($value) + { + $this->getAndSetTest($value, 'expiryMonth', 'expiry_month'); + } + + /** + * @dataProvider invalidMonthDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidMonth($value) + { + $this->getTestInstance()->setExpiryMonth($value); + } + + /** + * @dataProvider validCscDataProvider + * @param $value + */ + public function testGetSetCsc($value) + { + $this->getAndSetTest($value, 'csc'); + } + + /** + * @dataProvider invalidCscDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidCsc($value) + { + $this->getTestInstance()->setCsc($value); + } + + /** + * @dataProvider invalidCscDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidCsc($value) + { + $this->getTestInstance()->csc = $value; + } + + /** + * @dataProvider validCardholderDataProvider + * @param $value + */ + public function testGetSetCardholder($value) + { + $this->getAndSetTest($value, 'cardholder'); + } + + /** + * @dataProvider invalidCardholderDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidCardholder($value) + { + $this->getTestInstance()->setCardholder($value); + } + + /** + * @dataProvider invalidCardholderDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidCardholder($value) + { + $this->getTestInstance()->cardholder = $value; + } + + /** + * @return array + */ + public function validNumberDataProvider() + { + $result = array(); + for ($i = 0; $i < 3; $i++) { + $result[] = array(Random::str(16, '0123456789')); + $result[] = array(Random::str(17, '0123456789')); + $result[] = array(Random::str(18, '0123456789')); + $result[] = array(Random::str(19, '0123456789')); + } + return $result; + } + + /** + * @return array + */ + public function validExpiryYearDataProvider() + { + $result = array(); + for ($i = 0; $i < 10; $i++) { + $result[] = array(Random::int(2000, 2200)); + } + return $result; + } + + /** + * @return array + */ + public function validExpiryMonthDataProvider() + { + return array( + array('01'), + array('02'), + array('03'), + array('04'), + array('05'), + array('06'), + array('07'), + array('08'), + array('09'), + array('10'), + array('11'), + array('12'), + ); + } + + public function validCscDataProvider() + { + $result = array(); + for ($i = 0; $i < 10; $i++) { + $result[] = array(Random::str(3, 4, '0123456789')); + } + return $result; + } + + public function validCardholderDataProvider() + { + $values = 'abcdefghijklmnopqrstuvwxyz'; + $values .= strtoupper($values) . ' '; + $result = array( + array(Random::str(1, $values)), + array(Random::str(26, $values)), + ); + for ($i = 0; $i < 10; $i++) { + $result[] = array(Random::str(1, 26, $values)); + } + return $result; + } + + public function invalidNumberDataProvider() + { + return array( + array(''), + array(null), + array(0), + array(1), + array(-1), + array(array()), + array(new \stdClass()), + array(Random::str(15, '0123456789')), + array(Random::str(20, '0123456789')), + ); + } + + public function invalidYearDataProvider() + { + return array( + array(''), + array(null), + array(0), + array(1), + array(-1), + array('5'), + array(array()), + array(new \stdClass()), + array(Random::str(1, '0123456789')), + array(Random::str(2, '0123456789')), + array(Random::str(3, '0123456789')), + array(Random::str(5, '0123456789')), + ); + } + + public function invalidMonthDataProvider() + { + return array( + array(''), + array(null), + array(0), + array(1), + array(-1), + array('5'), + array(array()), + array(new \stdClass()), + array(Random::str(1, '0123456789')), + array(Random::str(3, '0123456789')), + array('13'), + array('16'), + ); + } + + public function invalidCscDataProvider() + { + return array( + array(''), + array(null), + array(0), + array(1), + array(-1), + array('5'), + array(array()), + array(new \stdClass()), + array(Random::str(1, '0123456789')), + array(Random::str(2, '0123456789')), + array(Random::str(5, '0123456789')), + array(Random::str(6, '0123456789')), + ); + } + + public function invalidCardholderDataProvider() + { + $values = 'abcdefghijklmnopqrstuvwxyz'; + $values .= strtoupper($values) . ' '; + $result = array( + array(''), + array(null), + array(0), + array(1), + array(-1), + array('5'), + array(array()), + array(new \stdClass()), + array(Random::str(1, '0123456789')), + array(Random::str(2, '0123456789')), + array(Random::str(5, '0123456789')), + array(Random::str(6, '0123456789')), + array(Random::str(27, $values)), + ); + return $result; + } + + protected function getAndSetTest($value, $property, $snakeCase = null) + { + $getter = 'get' . ucfirst($property); + $setter = 'set' . ucfirst($property); + + $instance = $this->getTestInstance(); + + self::assertNull($instance->{$getter}()); + self::assertNull($instance->{$property}); + if ($snakeCase !== null) { + self::assertNull($instance->{$snakeCase}); + } + + $instance->{$setter}($value); + + self::assertEquals($value, $instance->{$getter}()); + self::assertEquals($value, $instance->{$property}); + if ($snakeCase !== null) { + self::assertEquals($value, $instance->{$snakeCase}); + } + + $instance = $this->getTestInstance(); + + $instance->{$property} = $value; + + self::assertEquals($value, $instance->{$getter}()); + self::assertEquals($value, $instance->{$property}); + if ($snakeCase !== null) { + self::assertEquals($value, $instance->{$snakeCase}); + } + + if ($snakeCase !== null) { + $instance = $this->getTestInstance(); + + $instance->{$snakeCase} = $value; + + self::assertEquals($value, $instance->{$getter}()); + self::assertEquals($value, $instance->{$property}); + self::assertEquals($value, $instance->{$snakeCase}); + } + } +} \ No newline at end of file diff --git a/tests/Model/PaymentData/PaymentDataBankCardTest.php b/tests/Model/PaymentData/PaymentDataBankCardTest.php new file mode 100644 index 00000000..9666eca6 --- /dev/null +++ b/tests/Model/PaymentData/PaymentDataBankCardTest.php @@ -0,0 +1,119 @@ +getTestInstance(); + + self::assertNull($instance->getCard()); + self::assertNull($instance->card); + + $instance->setCard($value); + if ($value === null || $value === '' || $value === array()) { + self::assertNull($instance->getCard()); + self::assertNull($instance->card); + } else { + if (is_array($value)) { + $expected = new PaymentDataBankCardCard(); + foreach ($value as $property => $val) { + $expected->offsetSet($property, $val); + } + } else { + $expected = $value; + } + self::assertEquals($expected, $instance->getCard()); + self::assertEquals($expected, $instance->card); + } + + $instance = $this->getTestInstance(); + $instance->card = $value; + if ($value === null || $value === '' || $value === array()) { + self::assertNull($instance->getCard()); + self::assertNull($instance->card); + } else { + if (is_array($value)) { + $expected = new PaymentDataBankCardCard(); + foreach ($value as $property => $val) { + $expected->offsetSet($property, $val); + } + } else { + $expected = $value; + } + self::assertEquals($expected, $instance->getCard()); + self::assertEquals($expected, $instance->card); + } + } + + /** + * @dataProvider invalidCardDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidCard($value) + { + $this->getTestInstance()->setCard($value); + } + + /** + * @dataProvider invalidCardDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidCard($value) + { + $this->getTestInstance()->card = $value; + } + + public function validCardDataProvider() + { + return array( + array(null), + array(new PaymentDataBankCardCard()), + array(array()), + array(''), + array(array( + 'number' => Random::str(16, '0123456789'), + )), + ); + } + + public function invalidCardDataProvider() + { + return array( + array(0), + array(1), + array(-1), + array('5'), + array(true), + array(new \stdClass()), + ); + } +} \ No newline at end of file diff --git a/tests/Model/PaymentData/PaymentDataCashTest.php b/tests/Model/PaymentData/PaymentDataCashTest.php new file mode 100644 index 00000000..4cf25eb2 --- /dev/null +++ b/tests/Model/PaymentData/PaymentDataCashTest.php @@ -0,0 +1,56 @@ +getTestInstance(); + $paymentData = $instance->factory($type); + self::assertNotNull($paymentData); + self::assertTrue($paymentData instanceof AbstractPaymentData); + self::assertEquals($type, $paymentData->getType()); + } + + /** + * @dataProvider invalidTypeDataProvider + * @expectedException \InvalidArgumentException + * @param $type + */ + public function testInvalidFactory($type) + { + $instance = $this->getTestInstance(); + $instance->factory($type); + } + + /** + * @dataProvider validArrayDataProvider + * @param array $options + */ + public function testFactoryFromArray($options) + { + $instance = $this->getTestInstance(); + $paymentData = $instance->factoryFromArray($options); + self::assertNotNull($paymentData); + self::assertTrue($paymentData instanceof AbstractPaymentData); + + foreach ($options as $property => $value) { + self::assertEquals($paymentData->{$property}, $value); + } + + $type = $options['type']; + unset($options['type']); + $paymentData = $instance->factoryFromArray($options, $type); + self::assertNotNull($paymentData); + self::assertTrue($paymentData instanceof AbstractPaymentData); + + self::assertEquals($type, $paymentData->getType()); + foreach ($options as $property => $value) { + self::assertEquals($paymentData->{$property}, $value); + } + } + + /** + * @dataProvider invalidDataArrayDataProvider + * @expectedException \InvalidArgumentException + * @param $options + */ + public function testInvalidFactoryFromArray($options) + { + $instance = $this->getTestInstance(); + $instance->factoryFromArray($options); + } + + public function validTypeDataProvider() + { + $result = array(); + foreach (PaymentMethodType::getEnabledValues() as $value) { + $result[] = array($value); + } + return $result; + } + + public function invalidTypeDataProvider() + { + return array( + array(''), + array(null), + array(0), + array(1), + array(-1), + array('5'), + array(array()), + array(new \stdClass()), + array(Random::str(10)), + ); + } + + public function validArrayDataProvider() + { + $result = array( + array( + array( + 'type' => PaymentMethodType::ALFABANK, + 'login' => Random::str(10, 20), + ), + ), + array( + array( + 'type' => PaymentMethodType::GOOGLE_PAY, + 'paymentMethodToken' => Random::str(10, 20), + 'googleTransactionId' => Random::str(10, 20), + ), + ), + array( + array( + 'type' => PaymentMethodType::APPLE_PAY, + 'paymentData' => Random::str(10, 20), + ), + ), + array( + array( + 'type' => PaymentMethodType::BANK_CARD, + 'card' => new PaymentDataBankCardCard(), + ), + ), + array( + array( + 'type' => PaymentMethodType::CASH, + 'phone' => Random::str(4, 15, '0123456789'), + ), + ), + array( + array( + 'type' => PaymentMethodType::MOBILE_BALANCE, + 'phone' => Random::str(4, 15, '0123456789'), + ), + ), + array( + array( + 'type' => PaymentMethodType::SBERBANK, + 'phone' => Random::str(4, 15, '0123456789'), + ), + ), + array( + array( + 'type' => PaymentMethodType::YOO_MONEY, + ), + ), + array( + array( + 'type' => PaymentMethodType::INSTALLMENTS, + ), + ), + array( + array( + 'type' => PaymentMethodType::TINKOFF_BANK, + ), + ), + ); + foreach (PaymentMethodType::getEnabledValues() as $value) { + $result[] = array(array('type' => $value)); + } + return $result; + } + + public function invalidDataArrayDataProvider() + { + return array( + array(array()), + array(array('type' => 'test')), + ); + } +} \ No newline at end of file diff --git a/tests/Model/PaymentData/PaymentDataGooglePayTest.php b/tests/Model/PaymentData/PaymentDataGooglePayTest.php new file mode 100644 index 00000000..20e357dd --- /dev/null +++ b/tests/Model/PaymentData/PaymentDataGooglePayTest.php @@ -0,0 +1,25 @@ +getTestInstance(); + + self::assertNull($instance->getPhone()); + self::assertNull($instance->phone); + + $instance->setPhone($value); + self::assertEquals($value, $instance->getPhone()); + self::assertEquals($value, $instance->phone); + + $instance = $this->getTestInstance(); + $instance->phone = $value; + self::assertEquals($value, $instance->getPhone()); + self::assertEquals($value, $instance->phone); + } + + /** + * @dataProvider invalidPhoneDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidPhone($value) + { + /** @var PaymentMethodMobileBalance $instance */ + $instance = $this->getTestInstance(); + $instance->setPhone($value); + } + + /** + * @dataProvider invalidPhoneDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidPhone($value) + { + /** @var PaymentMethodMobileBalance $instance */ + $instance = $this->getTestInstance(); + $instance->phone = $value; + } + + public function validPhoneDataProvider() + { + return array( + array('0123'), + array('45678'), + array('901234'), + array('5678901'), + array('23456789'), + array('012345678'), + array('9012345678'), + array('90123456789'), + array('012345678901'), + array('5678901234567'), + array('89012345678901'), + array('234567890123456'), + ); + } + + public function invalidPhoneDataProvider() + { + return array( + array(null), + array(''), + array(true), + array(false), + array(array()), + array(new \stdClass()), + array('2345678901234567'), + ); + } +} diff --git a/tests/Model/PaymentMethod/AbstractPaymentMethodTest.php b/tests/Model/PaymentMethod/AbstractPaymentMethodTest.php new file mode 100644 index 00000000..1b21a74a --- /dev/null +++ b/tests/Model/PaymentMethod/AbstractPaymentMethodTest.php @@ -0,0 +1,276 @@ +getTestInstance(); + self::assertEquals($this->getExpectedType(), $instance->getType()); + } + + /** + * @dataProvider invalidTypeDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testInvalidType($value) + { + new TestPaymentData($value); + } + + /** + * @dataProvider validSavedDataProvider + * @param bool $value + */ + public function testGetSetSaved($value) + { + $instance = $this->getTestInstance(); + + self::assertFalse($instance->getSaved()); + self::assertFalse($instance->saved); + + $instance->setSaved($value); + if ($value) { + self::assertTrue($instance->getSaved()); + self::assertTrue($instance->saved); + } else { + self::assertFalse($instance->getSaved()); + self::assertFalse($instance->saved); + } + + $instance = $this->getTestInstance(); + $instance->saved = $value; + if ($value) { + self::assertTrue($instance->getSaved()); + self::assertTrue($instance->saved); + } else { + self::assertFalse($instance->getSaved()); + self::assertFalse($instance->saved); + } + } + + /** + * @dataProvider invalidSavedDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidSaved($value) + { + $this->getTestInstance()->setSaved($value); + } + + /** + * @dataProvider invalidSavedDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidSaved($value) + { + $this->getTestInstance()->saved = $value; + } + + /** + * @dataProvider validIdDataProvider + * @param bool $value + */ + public function testGetSetId($value) + { + $instance = $this->getTestInstance(); + + self::assertNull($instance->getId()); + self::assertNull($instance->id); + + $instance->setId($value); + if ($value === null || $value === '') { + self::assertNull($instance->getId()); + self::assertNull($instance->id); + } else { + self::assertEquals($value, $instance->getId()); + self::assertEquals($value, $instance->id); + } + + $instance = $this->getTestInstance(); + $instance->id = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getId()); + self::assertNull($instance->id); + } else { + self::assertEquals($value, $instance->getId()); + self::assertEquals($value, $instance->id); + } + } + + /** + * @dataProvider invalidIdDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidId($value) + { + $this->getTestInstance()->setId($value); + } + + /** + * @dataProvider invalidIdDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidId($value) + { + $this->getTestInstance()->id = $value; + } + + /** + * @dataProvider validTitleDataProvider + * @param bool $value + */ + public function testGetSetTitle($value) + { + $instance = $this->getTestInstance(); + + self::assertNull($instance->getTitle()); + self::assertNull($instance->title); + + $instance->setTitle($value); + if ($value === null || $value === '') { + self::assertNull($instance->getTitle()); + self::assertNull($instance->title); + } else { + self::assertEquals($value, $instance->getTitle()); + self::assertEquals($value, $instance->title); + } + + $instance = $this->getTestInstance(); + $instance->title = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getTitle()); + self::assertNull($instance->title); + } else { + self::assertEquals($value, $instance->getTitle()); + self::assertEquals($value, $instance->title); + } + } + + /** + * @dataProvider invalidTitleDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidTitle($value) + { + $this->getTestInstance()->setTitle($value); + } + + /** + * @dataProvider invalidIdDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidTitle($value) + { + $this->getTestInstance()->title = $value; + } + + public function invalidTypeDataProvider() + { + return array( + array(''), + array(null), + array(Random::str(40)), + array(0), + array(array()), + array(new \stdClass()), + ); + } + + public function validSavedDataProvider() + { + return array( + array(true), + array(false), + array(0), + array(1), + ); + } + + public function invalidSavedDataProvider() + { + return array( + array(null), + array(''), + array(array()), + array(new \stdClass()), + ); + } + + public function validIdDataProvider() + { + return array( + array(null), + array(''), + array(Random::str(1)), + array(Random::str(2)), + array(Random::str(10)), + array(Random::str(100)), + ); + } + + public function invalidIdDataProvider() + { + return array( + array(array()), + array(new \stdClass()), + array(true), + array(false), + ); + } + + public function validTitleDataProvider() + { + return array( + array(null), + array(''), + array(Random::str(1)), + array(Random::str(2)), + array(Random::str(10)), + array(Random::str(100)), + ); + } + + public function invalidTitleDataProvider() + { + return array( + array(array()), + array(new \stdClass()), + array(true), + array(false), + ); + } +} + +class TestPaymentData extends AbstractPaymentMethod +{ + public function __construct($type) + { + $this->_setType($type); + } +} \ No newline at end of file diff --git a/tests/Model/PaymentMethod/B2b/Sberbank/PayerBankDetailsTest.php b/tests/Model/PaymentMethod/B2b/Sberbank/PayerBankDetailsTest.php new file mode 100644 index 00000000..f83fb3d0 --- /dev/null +++ b/tests/Model/PaymentMethod/B2b/Sberbank/PayerBankDetailsTest.php @@ -0,0 +1,157 @@ +getAndSetTest($value, 'fullName'); + } + + /** + * @dataProvider validStringDataProvider + * @param string $value + */ + public function testGetSetShortName($value) + { + $this->getAndSetTest($value, 'shortName'); + } + + /** + * @dataProvider validStringDataProvider + * @param string $value + */ + public function testGetSetAddress($value) + { + $this->getAndSetTest($value, 'address'); + } + + /** + * @dataProvider validStringDataProvider + * @param string $value + */ + public function testGetSetInn($value) + { + $this->getAndSetTest($value, 'inn'); + } + + /** + * @dataProvider validStringDataProvider + * @param string $value + */ + public function testGetSetKpp($value) + { + $this->getAndSetTest($value, 'kpp'); + } + + /** + * @dataProvider validStringDataProvider + * @param string $value + */ + public function testGetSetBankName($value) + { + $this->getAndSetTest($value, 'bankName'); + } + + /** + * @dataProvider validStringDataProvider + * @param string $value + */ + public function testGetSetBankBranch($value) + { + $this->getAndSetTest($value, 'bankBranch'); + } + + /** + * @dataProvider validStringDataProvider + * @param string $value + */ + public function testGetSetBankBik($value) + { + $this->getAndSetTest($value, 'bankBik'); + } + + /** + * @dataProvider validStringDataProvider + * @param string $value + */ + public function testGetSetAccount($value) + { + $this->getAndSetTest($value, 'account'); + } + + /** + * @return array + * @throws \Exception + */ + public function validStringDataProvider() + { + $result = array(array(Random::str(10))); + + return $result; + } + + /** + * @param $value + * @param string $property + * @param null $snakeCase + */ + protected function getAndSetTest($value, $property, $snakeCase = null) + { + $getter = 'get'.ucfirst($property); + $setter = 'set'.ucfirst($property); + + $instance = $this->getTestInstance(); + + self::assertNull($instance->{$getter}()); + self::assertNull($instance->{$property}); + if ($snakeCase !== null) { + self::assertNull($instance->{$snakeCase}); + } + + $instance->{$setter}($value); + + self::assertEquals($value, $instance->{$getter}()); + self::assertEquals($value, $instance->{$property}); + if ($snakeCase !== null) { + self::assertEquals($value, $instance->{$snakeCase}); + } + + $instance = $this->getTestInstance(); + + $instance->{$property} = $value; + + self::assertEquals($value, $instance->{$getter}()); + self::assertEquals($value, $instance->{$property}); + if ($snakeCase !== null) { + self::assertEquals($value, $instance->{$snakeCase}); + } + + if ($snakeCase !== null) { + $instance = $this->getTestInstance(); + + $instance->{$snakeCase} = $value; + + self::assertEquals($value, $instance->{$getter}()); + self::assertEquals($value, $instance->{$property}); + self::assertEquals($value, $instance->{$snakeCase}); + } + } +} \ No newline at end of file diff --git a/tests/Model/PaymentMethod/PaymentMethodAlfaBankTest.php b/tests/Model/PaymentMethod/PaymentMethodAlfaBankTest.php new file mode 100644 index 00000000..e137f7b5 --- /dev/null +++ b/tests/Model/PaymentMethod/PaymentMethodAlfaBankTest.php @@ -0,0 +1,90 @@ +getTestInstance(); + + self::assertNull($instance->getLogin()); + self::assertNull($instance->login); + + $instance->setLogin($value); + self::assertEquals($value, $instance->getLogin()); + self::assertEquals($value, $instance->login); + + $instance = $this->getTestInstance(); + $instance->login = $value; + self::assertEquals($value, $instance->getLogin()); + self::assertEquals($value, $instance->login); + } + + /** + * @dataProvider invalidLoginDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidLogin($value) + { + $instance = $this->getTestInstance(); + $instance->setLogin($value); + } + + /** + * @dataProvider invalidLoginDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidLogin($value) + { + $instance = $this->getTestInstance(); + $instance->login = $value; + } + + public function validLoginDataProvider() + { + return array( + array(null), + array(''), + array('123'), + array(Random::str(256)), + array(Random::str(1024)), + ); + } + + public function invalidLoginDataProvider() + { + return array( + array(true), + array(false), + array(array()), + array(new \stdClass()), + ); + } +} \ No newline at end of file diff --git a/tests/Model/PaymentMethod/PaymentMethodApplePayTest.php b/tests/Model/PaymentMethod/PaymentMethodApplePayTest.php new file mode 100644 index 00000000..cf008e2b --- /dev/null +++ b/tests/Model/PaymentMethod/PaymentMethodApplePayTest.php @@ -0,0 +1,25 @@ +getAndSetTest($value, 'last4'); + } + + /** + * @dataProvider invalidLast4DataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidNumber($value) + { + $this->getTestInstance()->setLast4($value); + } + + /** + * @dataProvider invalidLast4DataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidNumber($value) + { + $this->getTestInstance()->last4 = $value; + } + + /** + * @dataProvider validFirst6DataProvider + * @param string $value + */ + public function testGetSetFirst6($value) + { + $this->getAndSetTest($value, 'first6'); + } + + /** + * @dataProvider invalidFirst6DataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetFirst6InvalidNumber($value) + { + $this->getTestInstance()->setFirst6($value); + } + + /** + * @dataProvider invalidFirst6DataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterFirst6InvalidNumber($value) + { + $this->getTestInstance()->first6 = $value; + } + + /** + * @dataProvider validExpiryYearDataProvider + * @param $value + */ + public function testGetSetExpiryYear($value) + { + $this->getAndSetTest($value, 'expiryYear', 'expiry_year'); + } + + /** + * @dataProvider invalidYearDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidYear($value) + { + $this->getTestInstance()->setExpiryYear($value); + } + + /** + * @dataProvider invalidYearDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidYear($value) + { + $this->getTestInstance()->expiryYear = $value; + } + + /** + * @dataProvider invalidYearDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalid_year($value) + { + $this->getTestInstance()->expiry_year = $value; + } + + /** + * @dataProvider invalidMonthDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidMonth($value) + { + $this->getTestInstance()->expiryMonth = $value; + } + + /** + * @dataProvider invalidMonthDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalid_month($value) + { + $this->getTestInstance()->expiry_month = $value; + } + + /** + * @dataProvider validExpiryMonthDataProvider + * @param $value + */ + public function testGetSetExpiryMonth($value) + { + $this->getAndSetTest($value, 'expiryMonth', 'expiry_month'); + } + + /** + * @dataProvider invalidMonthDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidMonth($value) + { + $this->getTestInstance()->setExpiryMonth($value); + } + + /** + * @dataProvider validCardTypeDataProvider + * @param $value + */ + public function testGetSetCardType($value) + { + $this->getAndSetTest($value, 'cardType', 'card_type'); + } + + /** + * @dataProvider validIssuerCountryDataProvider + * @param $value + */ + public function testGetSetIssuerCountry($value) + { + $this->getAndSetTest($value, 'issuerCountry', 'issuer_country'); + } + + /** + * @dataProvider validIssuerNameDataProvider + * @param $value + */ + public function testGetSetIssuerName($value) + { + $this->getAndSetTest($value, 'issuerName', 'issuer_name'); + } + + /** + * @dataProvider validSourceDataProvider + * @param $value + */ + public function testGetSetSource($value) + { + $this->getAndSetTest($value, 'source', 'source'); + } + + /** + * @dataProvider invalidCardTypeDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidCardType($value) + { + $this->getTestInstance()->setCardType($value); + } + + /** + * @dataProvider invalidCardTypeDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidCardType($value) + { + $this->getTestInstance()->cardType = $value; + } + + /** + * @dataProvider invalidCardTypeDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidCard_type($value) + { + $this->getTestInstance()->card_type = $value; + } + + /** + * @dataProvider invalidIssuerCountryDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidIssuerCountry($value) + { + $this->getTestInstance()->setIssuerCountry($value); + } + + /** + * @dataProvider invalidIssuerCountryDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidIssuerCountry($value) + { + $this->getTestInstance()->issuerCountry = $value; + } + + /** + * @dataProvider invalidIssuerCountryDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidIssuer_country($value) + { + $this->getTestInstance()->issuer_country = $value; + } + + /** + * @dataProvider invalidIssuerNameDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidIssuerName($value) + { + $this->getTestInstance()->setIssuerName($value); + } + + /** + * @dataProvider invalidIssuerNameDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidIssuerName($value) + { + $this->getTestInstance()->issuerName = $value; + } + + /** + * @dataProvider invalidIssuerNameDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidIssuer_name($value) + { + $this->getTestInstance()->issuer_name = $value; + } + + /** + * @dataProvider invalidSourceDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidSource($value) + { + $this->getTestInstance()->setSource($value); + } + + /** + * @dataProvider invalidSourceDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidSource($value) + { + $this->getTestInstance()->source = $value; + } + + /** + * @return array + */ + public function validLast4DataProvider() + { + $result = array(); + for ($i = 0; $i < 10; $i++) { + $result[] = array(Random::str(4, '0123456789')); + } + return $result; + } + + /** + * @return array + */ + public function validFirst6DataProvider() + { + $result = array(); + for ($i = 0; $i < 10; $i++) { + $result[] = array(Random::str(6, '0123456789')); + } + return $result; + } + + /** + * @return array + */ + public function validExpiryYearDataProvider() + { + $result = array(); + for ($i = 0; $i < 10; $i++) { + $result[] = array(Random::int(2000, 2200)); + } + return $result; + } + + /** + * @return array + */ + public function validExpiryMonthDataProvider() + { + return array( + array('01'), + array('02'), + array('03'), + array('04'), + array('05'), + array('06'), + array('07'), + array('08'), + array('09'), + array('10'), + array('11'), + array('12'), + ); + } + + public function validCardTypeDataProvider() + { + $result = array(); + for ($i = 0; $i < 10; $i++) { + $result[] = array(Random::str(3, 35)); + } + + return $result; + } + + public function validIssuerCountryDataProvider() + { + return array( + array('RU'), + array('EN'), + array('UK'), + array('AU'), + array(null), + array(''), + ); + } + + public function validIssuerNameDataProvider() + { + $result = array(); + for ($i = 0; $i < 10; $i++) { + $result[] = array(Random::str(3, 35)); + } + $result[] = array(""); + $result[] = array(null); + + return $result; + } + + public function validSourceDataProvider() + { + $result = array(); + foreach (BankCardSource::getValidValues() as $value) { + $result[] = array($value); + } + $result[] = array(""); + $result[] = array(null); + + return $result; + } + + public function invalidLast4DataProvider() + { + return array( + array(''), + array(null), + array(0), + array(1), + array(-1), + array(array()), + array(new \stdClass()), + array(Random::str(3, '0123456789')), + array(Random::str(5, '0123456789')), + ); + } + + public function invalidFirst6DataProvider() + { + return array( + array(''), + array(null), + array(0), + array(1), + array(-1), + array(array()), + array(new \stdClass()), + array(Random::str(3, '0123456789')), + array(Random::str(5, '0123456789')), + ); + } + + public function invalidYearDataProvider() + { + return array( + array(''), + array(null), + array(0), + array(1), + array(-1), + array('5'), + array(array()), + array(new \stdClass()), + array(Random::str(1, '0123456789')), + array(Random::str(2, '0123456789')), + array(Random::str(3, '0123456789')), + ); + } + + public function invalidMonthDataProvider() + { + return array( + array(''), + array(null), + array(0), + array(1), + array(-1), + array('5'), + array(array()), + array(new \stdClass()), + array(Random::str(1, '0123456789')), + array(Random::str(3, '0123456789')), + array('13'), + array('16'), + ); + } + + public function invalidCardTypeDataProvider() + { + return array( + array(''), + array(null), + array(true), + array(false), + array(array()), + array(new \stdClass()), + ); + } + + public function invalidIssuerCountryDataProvider() + { + return array( + array(Random::str(3, 4)), + array(true), + array(false), + array(array()), + array(new \stdClass()), + ); + } + + public function invalidIssuerNameDataProvider() + { + return array( + array(true), + array(false), + array(array()), + array(new \stdClass()), + ); + } + + public function invalidSourceDataProvider() + { + return array( + array(Random::str(3, 6)), + array(Random::int(1, 2)), + array(true), + array(false), + array(array()), + array(new \stdClass()), + ); + } + + protected function getAndSetTest($value, $property, $snakeCase = null) + { + $getter = 'get' . ucfirst($property); + $setter = 'set' . ucfirst($property); + + $instance = $this->getTestInstance(); + + self::assertNull($instance->{$getter}()); + self::assertNull($instance->{$property}); + if ($snakeCase !== null) { + self::assertNull($instance->{$snakeCase}); + } + + $instance->{$setter}($value); + + self::assertEquals($value, $instance->{$getter}()); + self::assertEquals($value, $instance->{$property}); + if ($snakeCase !== null) { + self::assertEquals($value, $instance->{$snakeCase}); + } + + $instance = $this->getTestInstance(); + + $instance->{$property} = $value; + + self::assertEquals($value, $instance->{$getter}()); + self::assertEquals($value, $instance->{$property}); + if ($snakeCase !== null) { + self::assertEquals($value, $instance->{$snakeCase}); + } + + if ($snakeCase !== null) { + $instance = $this->getTestInstance(); + + $instance->{$snakeCase} = $value; + + self::assertEquals($value, $instance->{$getter}()); + self::assertEquals($value, $instance->{$property}); + self::assertEquals($value, $instance->{$snakeCase}); + } + } +} \ No newline at end of file diff --git a/tests/Model/PaymentMethod/PaymentMethodCashTest.php b/tests/Model/PaymentMethod/PaymentMethodCashTest.php new file mode 100644 index 00000000..1cc819b5 --- /dev/null +++ b/tests/Model/PaymentMethod/PaymentMethodCashTest.php @@ -0,0 +1,25 @@ +getTestInstance(); + $paymentData = $instance->factory($type); + self::assertNotNull($paymentData); + self::assertTrue($paymentData instanceof AbstractPaymentMethod); + self::assertEquals($type, $paymentData->getType()); + } + + /** + * @dataProvider invalidTypeDataProvider + * @expectedException \InvalidArgumentException + * @param $type + */ + public function testInvalidFactory($type) + { + $instance = $this->getTestInstance(); + $instance->factory($type); + } + + /** + * @dataProvider validArrayDataProvider + * @param array $options + */ + public function testFactoryFromArray($options) + { + $instance = $this->getTestInstance(); + + $optionsMap = array( + 'card_type' => 'cardType', + 'expiry_month' => 'expiryMonth', + 'expiry_year' => 'expiryYear', + 'account_number' => 'accountNumber', + ); + + $paymentData = $instance->factoryFromArray($options); + self::assertNotNull($paymentData); + self::assertTrue($paymentData instanceof AbstractPaymentMethod); + + foreach ($options as $property => $value) { + if (array_key_exists($property, $optionsMap)) { + $property = $optionsMap[$property]; + } + self::assertEquals($paymentData->{$property}, $value); + } + + $type = $options['type']; + unset($options['type']); + $paymentData = $instance->factoryFromArray($options, $type); + self::assertNotNull($paymentData); + self::assertTrue($paymentData instanceof AbstractPaymentMethod); + + self::assertEquals($type, $paymentData->getType()); + foreach ($options as $property => $value) { + if (array_key_exists($property, $optionsMap)) { + $property = $optionsMap[$property]; + } + self::assertEquals($paymentData->{$property}, $value); + } + } + + /** + * @dataProvider invalidDataArrayDataProvider + * @expectedException \InvalidArgumentException + * @param $options + */ + public function testInvalidFactoryFromArray($options) + { + $instance = $this->getTestInstance(); + $instance->factoryFromArray($options); + } + + public function validTypeDataProvider() + { + $result = array(); + foreach (PaymentMethodType::getValidValues() as $value) { + $result[] = array($value); + } + return $result; + } + + public function invalidTypeDataProvider() + { + return array( + array(''), + array(null), + array(0), + array(1), + array(-1), + array('5'), + array(array()), + array(new \stdClass()), + array(Random::str(10)), + ); + } + + public function validArrayDataProvider() + { + $result = array( + array( + array( + 'type' => PaymentMethodType::ALFABANK, + 'login' => Random::str(10, 20), + 'id' => Random::str(1, 64), + 'saved' => Random::int() % 2 ? true : false, + 'title' => Random::str(10, 20), + ), + ), + array( + array( + 'type' => PaymentMethodType::GOOGLE_PAY, + 'id' => Random::str(1, 64), + 'saved' => Random::int() % 2 ? true : false, + 'title' => Random::str(10, 20), + ), + ), + array( + array( + 'type' => PaymentMethodType::APPLE_PAY, + 'id' => Random::str(1, 64), + 'saved' => Random::int() % 2 ? true : false, + 'title' => Random::str(10, 20), + ), + ), + array( + array( + 'type' => PaymentMethodType::BANK_CARD, + 'id' => Random::str(1, 64), + 'saved' => Random::int() % 2 ? true : false, + 'title' => Random::str(10, 20), + 'last4' => Random::str(4, '0123456789'), + 'first6' => Random::str(6, '0123456789'), + 'expiryYear' => Random::int(2000, 2200), + 'expiryMonth' => Random::value(array('01','02','03','04','05','06','07','08','09','10','11','12')), + 'cardType' => Random::str(3, 10), + ), + ), + array( + array( + 'type' => PaymentMethodType::BANK_CARD, + 'id' => Random::str(1, 64), + 'saved' => Random::int() % 2 ? true : false, + 'title' => Random::str(10, 20), + 'last4' => Random::str(4, '0123456789'), + 'first6' => Random::str(6, '0123456789'), + 'expiry_year' => Random::int(2000, 2200), + 'expiry_month' => Random::value(array('01','02','03','04','05','06','07','08','09','10','11','12')), + 'card_type' => Random::str(3, 10), + ), + ), + array( + array( + 'type' => PaymentMethodType::CASH, + 'id' => Random::str(1, 64), + 'saved' => Random::int() % 2 ? true : false, + 'title' => Random::str(10, 20), + ), + ), + array( + array( + 'type' => PaymentMethodType::MOBILE_BALANCE, + 'id' => Random::str(1, 64), + 'saved' => Random::int() % 2 ? true : false, + 'title' => Random::str(10, 20), + 'phone' => Random::str(4, 15, '0123456789'), + ), + ), + array( + array( + 'type' => PaymentMethodType::SBERBANK, + 'phone' => Random::str(4, 15, '0123456789'), + 'id' => Random::str(1, 64), + 'saved' => Random::int() % 2 ? true : false, + 'title' => Random::str(10, 20), + ), + ), + array( + array( + 'type' => PaymentMethodType::YOO_MONEY, + 'accountNumber' => Random::str(31, '0123456789'), + 'id' => Random::str(1, 64), + 'saved' => Random::int() % 2 ? true : false, + 'title' => Random::str(10, 20), + ), + ), + array( + array( + 'type' => PaymentMethodType::YOO_MONEY, + 'account_number' => Random::str(31, '0123456789'), + 'id' => Random::str(1, 64), + 'saved' => Random::int() % 2 ? true : false, + 'title' => Random::str(10, 20), + ), + ), + array( + array( + 'type' => PaymentMethodType::INSTALLMENTS, + 'id' => Random::str(1, 64), + 'saved' => true, + 'title' => Random::str(10, 20), + ), + ), + array( + array( + 'type' => PaymentMethodType::B2B_SBERBANK, + 'id' => Random::str(1, 64), + 'saved' => false, + ), + ), + array( + array( + 'type' => PaymentMethodType::TINKOFF_BANK, + 'id' => Random::str(1, 64), + 'saved' => false, + ), + ), + ); + foreach (PaymentMethodType::getValidValues() as $value) { + $result[] = array(array('type' => $value)); + } + return $result; + } + + public function invalidDataArrayDataProvider() + { + return array( + array(array()), + array(array('type' => 'test')), + ); + } +} \ No newline at end of file diff --git a/tests/Model/PaymentMethod/PaymentMethodGooglePayTest.php b/tests/Model/PaymentMethod/PaymentMethodGooglePayTest.php new file mode 100644 index 00000000..b41f79e9 --- /dev/null +++ b/tests/Model/PaymentMethod/PaymentMethodGooglePayTest.php @@ -0,0 +1,25 @@ +getTestInstance(); + + self::assertNull($instance->getAccountNumber()); + self::assertNull($instance->accountNumber); + self::assertNull($instance->account_number); + + $instance->setAccountNumber($value); + self::assertEquals($value, $instance->getAccountNumber()); + self::assertEquals($value, $instance->accountNumber); + self::assertEquals($value, $instance->account_number); + + $instance = $this->getTestInstance(); + $instance->accountNumber = $value; + self::assertEquals($value, $instance->getAccountNumber()); + self::assertEquals($value, $instance->accountNumber); + self::assertEquals($value, $instance->account_number); + + $instance = $this->getTestInstance(); + $instance->account_number = $value; + self::assertEquals($value, $instance->getAccountNumber()); + self::assertEquals($value, $instance->accountNumber); + self::assertEquals($value, $instance->account_number); + } + + /** + * @dataProvider invalidAccountNumberDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidAccountNumber($value) + { + $instance = $this->getTestInstance(); + $instance->setAccountNumber($value); + } + + /** + * @dataProvider invalidAccountNumberDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidAccountNumber($value) + { + $instance = $this->getTestInstance(); + $instance->accountNumber = $value; + } + + /** + * @dataProvider invalidAccountNumberDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidAccount_number($value) + { + $instance = $this->getTestInstance(); + $instance->account_number = $value; + } + + public function validAccountNumberDataProvider() + { + return array( + array(Random::str(11, '0123456789')), + array(Random::str(12, '0123456789')), + array(Random::str(13, '0123456789')), + array(Random::str(31, '0123456789')), + array(Random::str(32, '0123456789')), + array(Random::str(33, '0123456789')), + ); + } + + public function invalidAccountNumberDataProvider() + { + return array( + array(null), + array(''), + array(true), + array(false), + array(array()), + array(new \stdClass()), + array(Random::str(10, '0123456789')), + array(Random::str(34, '0123456789')), + ); + } +} \ No newline at end of file diff --git a/tests/Model/PaymentTest.php b/tests/Model/PaymentTest.php new file mode 100644 index 00000000..e8ae424e --- /dev/null +++ b/tests/Model/PaymentTest.php @@ -0,0 +1,996 @@ +getId()); + self::assertNull($instance->id); + + $instance->setId($options['id']); + self::assertEquals($options['id'], $instance->getId()); + self::assertEquals($options['id'], $instance->id); + + $instance = new Payment(); + $instance->id = $options['id']; + self::assertEquals($options['id'], $instance->getId()); + self::assertEquals($options['id'], $instance->id); + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidId($value) + { + $instance = new Payment(); + $instance->setId($value['id']); + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidId($value) + { + $instance = new Payment(); + $instance->id = $value['id']; + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetSetStatus($options) + { + $instance = new Payment(); + + self::assertNull($instance->getStatus()); + self::assertNull($instance->status); + + $instance->setStatus($options['status']); + self::assertEquals($options['status'], $instance->getStatus()); + self::assertEquals($options['status'], $instance->status); + + $instance = new Payment(); + $instance->status = $options['status']; + self::assertEquals($options['status'], $instance->getStatus()); + self::assertEquals($options['status'], $instance->status); + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidStatus($value) + { + $instance = new Payment(); + $instance->setStatus($value['status']); + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidStatus($value) + { + $instance = new Payment(); + $instance->status = $value['status']; + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetSetRecipient($options) + { + $instance = new Payment(); + + self::assertNull($instance->getRecipient()); + self::assertNull($instance->recipient); + + $instance->setRecipient($options['recipient']); + self::assertSame($options['recipient'], $instance->getRecipient()); + self::assertSame($options['recipient'], $instance->recipient); + + $instance = new Payment(); + $instance->recipient = $options['recipient']; + self::assertSame($options['recipient'], $instance->getRecipient()); + self::assertSame($options['recipient'], $instance->recipient); + } + + /** + * @dataProvider invalidDataProvider + * @param $value + */ + public function testSetInvalidRecipient($value) + { + if (class_exists('TypeError')) { + self::setExpectedException('TypeError'); + $instance = new Payment(); + $instance->setRecipient($value['recipient']); + } + } + + /** + * @dataProvider invalidDataProvider + * @param $value + */ + public function testSetterInvalidRecipient($value) + { + if (class_exists('TypeError')) { + self::setExpectedException('TypeError'); + $instance = new Payment(); + $instance->recipient = $value['recipient']; + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetSetAmount($options) + { + $instance = new Payment(); + + self::assertNull($instance->getAmount()); + self::assertNull($instance->amount); + + $instance->setAmount($options['amount']); + self::assertSame($options['amount'], $instance->getAmount()); + self::assertSame($options['amount'], $instance->amount); + + $instance = new Payment(); + $instance->amount = $options['amount']; + self::assertSame($options['amount'], $instance->getAmount()); + self::assertSame($options['amount'], $instance->amount); + } + + /** + * @dataProvider invalidDataProvider + * @param $value + */ + public function testSetInvalidAmount($value) + { + if (class_exists('TypeError')) { + self::setExpectedException('TypeError'); + $instance = new Payment(); + $instance->setAmount($value['amount']); + } + } + + /** + * @dataProvider invalidDataProvider + * @param $value + */ + public function testSetterInvalidAmount($value) + { + if (class_exists('TypeError')) { + self::setExpectedException('TypeError'); + $instance = new Payment(); + $instance->amount = $value['amount']; + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetSetPaymentMethod($options) + { + $instance = new Payment(); + + self::assertNull($instance->getPaymentMethod()); + self::assertNull($instance->paymentMethod); + self::assertNull($instance->payment_method); + + $instance->setPaymentMethod($options['payment_method']); + self::assertSame($options['payment_method'], $instance->getPaymentMethod()); + self::assertSame($options['payment_method'], $instance->paymentMethod); + self::assertSame($options['payment_method'], $instance->payment_method); + + $instance = new Payment(); + $instance->paymentMethod = $options['payment_method']; + self::assertSame($options['payment_method'], $instance->getPaymentMethod()); + self::assertSame($options['payment_method'], $instance->paymentMethod); + self::assertSame($options['payment_method'], $instance->payment_method); + + $instance = new Payment(); + $instance->payment_method = $options['payment_method']; + self::assertSame($options['payment_method'], $instance->getPaymentMethod()); + self::assertSame($options['payment_method'], $instance->paymentMethod); + self::assertSame($options['payment_method'], $instance->payment_method); + } + + /** + * @dataProvider invalidDataProvider + * @param $value + */ + public function testSetInvalidPaymentMethod($value) + { + if (class_exists('TypeError')) { + self::setExpectedException('TypeError'); + $instance = new Payment(); + $instance->setPaymentMethod($value['payment_method']); + } + } + + /** + * @dataProvider invalidDataProvider + * @param $value + */ + public function testSetterInvalidPaymentMethod($value) + { + if (class_exists('TypeError')) { + self::setExpectedException('TypeError'); + $instance = new Payment(); + $instance->paymentMethod = $value['payment_method']; + } + } + + /** + * @dataProvider invalidDataProvider + * @param $value + */ + public function testSetterInvalidPayment_method($value) + { + if (class_exists('TypeError')) { + self::setExpectedException('TypeError'); + $instance = new Payment(); + $instance->payment_method = $value['payment_method']; + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetSetCreatedAt($options) + { + $instance = new Payment(); + + self::assertNull($instance->getCreatedAt()); + self::assertNull($instance->createdAt); + self::assertNull($instance->created_at); + + $instance->setCreatedAt($options['created_at']); + self::assertSame($options['created_at'], $instance->getCreatedAt()->format(DATE_ATOM)); + self::assertSame($options['created_at'], $instance->createdAt->format(DATE_ATOM)); + self::assertSame($options['created_at'], $instance->created_at->format(DATE_ATOM)); + + $instance = new Payment(); + $instance->createdAt = $options['created_at']; + self::assertSame($options['created_at'], $instance->getCreatedAt()->format(DATE_ATOM)); + self::assertSame($options['created_at'], $instance->createdAt->format(DATE_ATOM)); + self::assertSame($options['created_at'], $instance->created_at->format(DATE_ATOM)); + + $instance = new Payment(); + $instance->created_at = $options['created_at']; + self::assertSame($options['created_at'], $instance->getCreatedAt()->format(DATE_ATOM)); + self::assertSame($options['created_at'], $instance->createdAt->format(DATE_ATOM)); + self::assertSame($options['created_at'], $instance->created_at->format(DATE_ATOM)); + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidCreatedAt($value) + { + $instance = new Payment(); + $instance->setCreatedAt($value['created_at']); + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidCreatedAt($value) + { + $instance = new Payment(); + $instance->createdAt = $value['created_at']; + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidCreated_at($value) + { + $instance = new Payment(); + $instance->created_at = $value['created_at']; + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetSetCapturedAt($options) + { + $instance = new Payment(); + + self::assertNull($instance->getCapturedAt()); + self::assertNull($instance->capturedAt); + self::assertNull($instance->captured_at); + + $instance->setCapturedAt($options['captured_at']); + if ($options['captured_at'] === null || $options['captured_at'] === '') { + self::assertNull($instance->getCapturedAt()); + self::assertNull($instance->capturedAt); + self::assertNull($instance->captured_at); + } else { + self::assertSame($options['captured_at'], $instance->getCapturedAt()->format(DATE_ATOM)); + self::assertSame($options['captured_at'], $instance->capturedAt->format(DATE_ATOM)); + self::assertSame($options['captured_at'], $instance->captured_at->format(DATE_ATOM)); + } + + $instance = new Payment(); + $instance->capturedAt = $options['captured_at']; + if ($options['captured_at'] === null || $options['captured_at'] === '') { + self::assertNull($instance->getCapturedAt()); + self::assertNull($instance->capturedAt); + self::assertNull($instance->captured_at); + } else { + self::assertSame($options['captured_at'], $instance->getCapturedAt()->format(DATE_ATOM)); + self::assertSame($options['captured_at'], $instance->capturedAt->format(DATE_ATOM)); + self::assertSame($options['captured_at'], $instance->captured_at->format(DATE_ATOM)); + } + + $instance = new Payment(); + $instance->captured_at = $options['captured_at']; + if ($options['captured_at'] === null || $options['captured_at'] === '') { + self::assertNull($instance->getCapturedAt()); + self::assertNull($instance->capturedAt); + self::assertNull($instance->captured_at); + } else { + self::assertSame($options['captured_at'], $instance->getCapturedAt()->format(DATE_ATOM)); + self::assertSame($options['captured_at'], $instance->capturedAt->format(DATE_ATOM)); + self::assertSame($options['captured_at'], $instance->captured_at->format(DATE_ATOM)); + } + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidCapturedAt($value) + { + $instance = new Payment(); + $instance->setCapturedAt($value['captured_at']); + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidCapturedAt($value) + { + $instance = new Payment(); + $instance->capturedAt = $value['captured_at']; + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidCaptured_at($value) + { + $instance = new Payment(); + $instance->captured_at = $value['captured_at']; + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetSetConfirmation($options) + { + $instance = new Payment(); + + self::assertNull($instance->getConfirmation()); + self::assertNull($instance->confirmation); + + $instance->setConfirmation($options['confirmation']); + self::assertSame($options['confirmation'], $instance->getConfirmation()); + self::assertSame($options['confirmation'], $instance->confirmation); + + $instance = new Payment(); + $instance->confirmation = $options['confirmation']; + self::assertSame($options['confirmation'], $instance->getConfirmation()); + self::assertSame($options['confirmation'], $instance->confirmation); + } + + /** + * @dataProvider invalidDataProvider + * @param $value + */ + public function testSetInvalidConfirmation($value) + { + if (class_exists('TypeError')) { + self::setExpectedException('TypeError'); + $instance = new Payment(); + $instance->setConfirmation($value['confirmation']); + } + } + + /** + * @dataProvider invalidDataProvider + * @param $value + */ + public function testSetterInvalidConfirmation($value) + { + if (class_exists('TypeError')) { + self::setExpectedException('TypeError'); + $instance = new Payment(); + $instance->confirmation = $value['confirmation']; + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetSetRefundedAmount($options) + { + $instance = new Payment(); + + self::assertNull($instance->getRefundedAmount()); + self::assertNull($instance->refundedAmount); + self::assertNull($instance->refunded_amount); + + $instance->setRefundedAmount($options['refunded_amount']); + self::assertSame($options['refunded_amount'], $instance->getRefundedAmount()); + self::assertSame($options['refunded_amount'], $instance->refundedAmount); + self::assertSame($options['refunded_amount'], $instance->refunded_amount); + + $instance = new Payment(); + $instance->refundedAmount = $options['refunded_amount']; + self::assertSame($options['refunded_amount'], $instance->getRefundedAmount()); + self::assertSame($options['refunded_amount'], $instance->refundedAmount); + self::assertSame($options['refunded_amount'], $instance->refunded_amount); + + $instance = new Payment(); + $instance->refunded_amount = $options['refunded_amount']; + self::assertSame($options['refunded_amount'], $instance->getRefundedAmount()); + self::assertSame($options['refunded_amount'], $instance->refundedAmount); + self::assertSame($options['refunded_amount'], $instance->refunded_amount); + } + + /** + * @dataProvider invalidDataProvider + * @param $value + */ + public function testSetInvalidRefundedAmount($value) + { + if (class_exists('TypeError')) { + self::setExpectedException('TypeError'); + $instance = new Payment(); + $instance->setRefundedAmount($value['refunded_amount']); + } + } + + /** + * @dataProvider invalidDataProvider + * @param $value + */ + public function testSetterInvalidRefundedAmount($value) + { + if (class_exists('TypeError')) { + self::setExpectedException('TypeError'); + $instance = new Payment(); + $instance->refundedAmount = $value['refunded_amount']; + } + } + + /** + * @dataProvider invalidDataProvider + * @param $value + */ + public function testSetterInvalidRefunded_amount($value) + { + if (class_exists('TypeError')) { + self::setExpectedException('TypeError'); + $instance = new Payment(); + $instance->refunded_amount = $value['refunded_amount']; + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetSetPaid($options) + { + $instance = new Payment(); + + self::assertNull($instance->getPaid()); + self::assertNull($instance->paid); + + $instance->setPaid($options['paid']); + self::assertSame($options['paid'], $instance->getPaid()); + self::assertSame($options['paid'], $instance->paid); + + $instance = new Payment(); + $instance->paid = $options['paid']; + self::assertSame($options['paid'], $instance->getPaid()); + self::assertSame($options['paid'], $instance->paid); + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidPaid($value) + { + $instance = new Payment(); + $instance->setPaid($value['paid']); + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidPaid($value) + { + $instance = new Payment(); + $instance->paid = $value['paid']; + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetSetRefundable($options) + { + $instance = new Payment(); + + self::assertNull($instance->getRefundable()); + self::assertNull($instance->refundable); + + $instance->setRefundable($options['refundable']); + self::assertSame($options['refundable'], $instance->getRefundable()); + self::assertSame($options['refundable'], $instance->refundable); + + $instance = new Payment(); + $instance->refundable = $options['refundable']; + self::assertSame($options['refundable'], $instance->getRefundable()); + self::assertSame($options['refundable'], $instance->refundable); + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidRefundable($value) + { + $instance = new Payment(); + $instance->setRefundable($value['refundable']); + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidRefundable($value) + { + $instance = new Payment(); + $instance->refundable = $value['refundable']; + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetSetReceiptRegistration($options) + { + $instance = new Payment(); + + self::assertNull($instance->getReceiptRegistration()); + self::assertNull($instance->receiptRegistration); + self::assertNull($instance->receipt_registration); + + $instance->setReceiptRegistration($options['receipt_registration']); + if ($options['receipt_registration'] === null || $options['receipt_registration'] === '') { + self::assertNull($instance->getReceiptRegistration()); + self::assertNull($instance->receiptRegistration); + self::assertNull($instance->receipt_registration); + } else { + self::assertSame($options['receipt_registration'], $instance->getReceiptRegistration()); + self::assertSame($options['receipt_registration'], $instance->receiptRegistration); + self::assertSame($options['receipt_registration'], $instance->receipt_registration); + } + + + $instance = new Payment(); + $instance->receiptRegistration = $options['receipt_registration']; + if ($options['receipt_registration'] === null || $options['receipt_registration'] === '') { + self::assertNull($instance->getReceiptRegistration()); + self::assertNull($instance->receiptRegistration); + self::assertNull($instance->receipt_registration); + } else { + self::assertSame($options['receipt_registration'], $instance->getReceiptRegistration()); + self::assertSame($options['receipt_registration'], $instance->receiptRegistration); + self::assertSame($options['receipt_registration'], $instance->receipt_registration); + } + + $instance = new Payment(); + $instance->receipt_registration = $options['receipt_registration']; + if ($options['receipt_registration'] === null || $options['receipt_registration'] === '') { + self::assertNull($instance->getReceiptRegistration()); + self::assertNull($instance->receiptRegistration); + self::assertNull($instance->receipt_registration); + } else { + self::assertSame($options['receipt_registration'], $instance->getReceiptRegistration()); + self::assertSame($options['receipt_registration'], $instance->receiptRegistration); + self::assertSame($options['receipt_registration'], $instance->receipt_registration); + } + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidReceiptRegistration($value) + { + $instance = new Payment(); + $instance->setReceiptRegistration($value['receipt_registration']); + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidReceiptRegistration($value) + { + $instance = new Payment(); + $instance->receiptRegistration = $value['receipt_registration']; + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidReceipt_registration($value) + { + $instance = new Payment(); + $instance->receipt_registration = $value['receipt_registration']; + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetSetMetadata($options) + { + $instance = new Payment(); + + self::assertNull($instance->getMetadata()); + self::assertNull($instance->metadata); + + $instance->setMetadata($options['metadata']); + self::assertSame($options['metadata'], $instance->getMetadata()); + self::assertSame($options['metadata'], $instance->metadata); + + $instance = new Payment(); + $instance->metadata = $options['metadata']; + self::assertSame($options['metadata'], $instance->getMetadata()); + self::assertSame($options['metadata'], $instance->metadata); + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetSetTransfers($options) + { + $instance = new Payment(); + + self::assertEmpty($instance->getTransfers()); + self::assertEmpty($instance->transfers); + + $instance->setTransfers($options['transfers']); + self::assertSame($options['transfers'], $instance->getTransfers()); + self::assertSame($options['transfers'], $instance->transfers); + + $instance = new Payment(); + $instance->transfers = $options['transfers']; + self::assertSame($options['transfers'], $instance->getTransfers()); + self::assertSame($options['transfers'], $instance->transfers); + } + + public function validDataProvider() + { + $result = array(); + $cancellationDetailsParties = CancellationDetailsPartyCode::getValidValues(); + $countCancellationDetailsParties = count($cancellationDetailsParties); + $cancellationDetailsReasons = CancellationDetailsReasonCode::getValidValues(); + $countCancellationDetailsReasons = count($cancellationDetailsReasons); + for ($i = 0; $i < 20; $i++) { + $payment = array( + 'id' => Random::str(36), + 'status' => Random::value(PaymentStatus::getValidValues()), + 'recipient' => new Recipient(), + 'amount' => new MonetaryAmount(Random::int(1, 10000), 'RUB'), + 'description' => ($i == 0 ? null : ($i == 1 ? '' : ($i == 2 ? Random::str(Payment::MAX_LENGTH_DESCRIPTION) + : Random::str(1, Payment::MAX_LENGTH_DESCRIPTION)))), + 'payment_method' => new PaymentMethodQiwi(), + 'reference_id' => ($i == 0 ? null : ($i == 1 ? '' : Random::str(10, 20, 'abcdef0123456789'))), + 'created_at' => date(DATE_ATOM, mt_rand(1, time())), + 'captured_at' => ($i == 0 ? null : ($i == 1 ? '' : date(DATE_ATOM, mt_rand(1, time())))), + 'expires_at' => ($i == 0 ? null : ($i == 1 ? '' : date(DATE_ATOM, mt_rand(1, time())))), + 'confirmation' => new ConfirmationRedirect(), + 'charge' => new MonetaryAmount(), + 'income' => new MonetaryAmount(), + 'refunded_amount' => new MonetaryAmount(), + 'paid' => $i % 2 ? true : false, + 'refundable' => $i % 2 ? true : false, + 'receipt_registration' => $i == 0 ? null : ($i == 1 ? '' : Random::value(ReceiptRegistrationStatus::getValidValues())), + 'metadata' => new Metadata(), + 'cancellation_details' => new CancellationDetails( + $cancellationDetailsParties[$i % $countCancellationDetailsParties], + $cancellationDetailsReasons[$i % $countCancellationDetailsReasons] + ), + 'transfers' => array( + new Transfer(array( + 'account_id' => Random::str(36), + 'amount' => new MonetaryAmount(Random::int(1, 1000), 'RUB'), + 'platform_fee_amount' => new MonetaryAmount(Random::int(1, 1000), 'RUB'), + )), + ) + ); + $result[] = array($payment); + } + return $result; + } + + public function invalidDataProvider() + { + $result = array( + array( + array( + 'id' => null, + 'status' => null, + 'recipient' => null, + 'amount' => null, + 'payment_method' => null, + 'reference_id' => Random::str(65), + 'confirmation' => null, + 'charge' => null, + 'income' => null, + 'refunded_amount' => null, + 'paid' => null, + 'refundable' => null, + 'created_at' => null, + 'captured_at' => array(), + 'receipt_registration' => array(), + ) + ), + array( + array( + 'id' => '', + 'status' => '', + 'recipient' => '', + 'amount' => '', + 'payment_method' => '', + 'reference_id' => array(), + 'confirmation' => '', + 'charge' => '', + 'income' => '', + 'refunded_amount' => '', + 'paid' => '', + 'refundable' => '', + 'created_at' => array(), + 'captured_at' => '23423-234-234', + 'receipt_registration' => new \stdClass(), + ), + ), + ); + for ($i = 0; $i < 10; $i++) { + $payment = array( + 'id' => Random::str($i < 5 ? mt_rand(1, 35) : mt_rand(37, 64)), + 'status' => Random::str(1, 35), + 'recipient' => 'test', + 'amount' => 'test', + 'payment_method' => 'test', + 'reference_id' => Random::str(66, 128), + 'confirmation' => 'test', + 'charge' => 'test', + 'income' => 'test', + 'refunded_amount' => 'test', + 'paid' => $i == 0 ? array() : new \stdClass(), + 'refundable' => $i == 0 ? array() : new \stdClass(), + 'created_at' => $i == 0 ? '23423-234-32' : -Random::int(), + 'captured_at' => -Random::int(), + 'receipt_registration' => $i == 0 ? true : Random::str(5), + ); + $result[] = array($payment); + } + return $result; + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetSetExpiresAt($options) + { + $instance = new Payment(); + + self::assertNull($instance->getExpiresAt()); + self::assertNull($instance->expiresAt); + self::assertNull($instance->expires_at); + + $instance->setExpiresAt($options['expires_at']); + if ($options['expires_at'] === null || $options['expires_at'] === '') { + self::assertNull($instance->getExpiresAt()); + self::assertNull($instance->expiresAt); + self::assertNull($instance->expires_at); + } else { + self::assertSame($options['expires_at'], $instance->getExpiresAt()->format(DATE_ATOM)); + self::assertSame($options['expires_at'], $instance->expiresAt->format(DATE_ATOM)); + self::assertSame($options['expires_at'], $instance->expires_at->format(DATE_ATOM)); + } + + $instance = new Payment(); + $instance->expiresAt = $options['expires_at']; + if ($options['expires_at'] === null || $options['expires_at'] === '') { + self::assertNull($instance->getExpiresAt()); + self::assertNull($instance->expiresAt); + self::assertNull($instance->expires_at); + } else { + self::assertSame($options['expires_at'], $instance->getExpiresAt()->format(DATE_ATOM)); + self::assertSame($options['expires_at'], $instance->expiresAt->format(DATE_ATOM)); + self::assertSame($options['expires_at'], $instance->expires_at->format(DATE_ATOM)); + } + + $instance = new Payment(); + $instance->expires_at = $options['expires_at']; + if ($options['expires_at'] === null || $options['expires_at'] === '') { + self::assertNull($instance->getExpiresAt()); + self::assertNull($instance->expiresAt); + self::assertNull($instance->expires_at); + } else { + self::assertSame($options['expires_at'], $instance->getExpiresAt()->format(DATE_ATOM)); + self::assertSame($options['expires_at'], $instance->expiresAt->format(DATE_ATOM)); + self::assertSame($options['expires_at'], $instance->expires_at->format(DATE_ATOM)); + } + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidExpiresAt($value) + { + $instance = new Payment(); + $instance->setExpiresAt($value['captured_at']); + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidExpiresAt($value) + { + $instance = new Payment(); + $instance->expiresAt = $value['captured_at']; + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidExpires_at($value) + { + $instance = new Payment(); + $instance->expires_at = $value['captured_at']; + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSetDescription($options) + { + $instance = new Payment(); + $instance->setDescription($options['description']); + + if (empty($options['description']) && ($options['description'] !== '0')) { + self::assertNull($instance->getDescription()); + } else { + self::assertEquals($options['description'], $instance->getDescription()); + } + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testSetInvalidTypeDescription() + { + $instance = new Payment(); + $instance->setDescription(true); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testSetInvalidLengthDescription() + { + $instance = new Payment(); + $description = Random::str(Payment::MAX_LENGTH_DESCRIPTION + 1); + $instance->setDescription($description); + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetSetCancellationDetails($options) + { + $instance = new Payment(); + + self::assertNull($instance->getCancellationDetails()); + self::assertNull($instance->cancellationDetails); + self::assertNull($instance->cancellation_details); + + $instance->setCancellationDetails($options['cancellation_details']); + self::assertSame($options['cancellation_details'], $instance->getCancellationDetails()); + self::assertSame($options['cancellation_details'], $instance->cancellationDetails); + self::assertSame($options['cancellation_details'], $instance->cancellation_details); + + $instance = new Payment(); + $instance->cancellationDetails = $options['cancellation_details']; + self::assertSame($options['cancellation_details'], $instance->getCancellationDetails()); + self::assertSame($options['cancellation_details'], $instance->cancellationDetails); + self::assertSame($options['cancellation_details'], $instance->cancellation_details); + + $instance = new Payment(); + $instance->cancellation_details = $options['cancellation_details']; + self::assertSame($options['cancellation_details'], $instance->getCancellationDetails()); + self::assertSame($options['cancellation_details'], $instance->cancellationDetails); + self::assertSame($options['cancellation_details'], $instance->cancellation_details); + } +} \ No newline at end of file diff --git a/tests/Model/ReceiptCustomerTest.php b/tests/Model/ReceiptCustomerTest.php new file mode 100644 index 00000000..829bf839 --- /dev/null +++ b/tests/Model/ReceiptCustomerTest.php @@ -0,0 +1,509 @@ +getPhone()); + self::assertNull($instance->phone); + + $value = !empty($options['customer']['phone']) + ? $options['customer']['phone'] + : (!empty($options['phone']) ? $options['phone'] : null); + + $instance->setPhone($value); + if ($value === null || $value === '') { + self::assertNull($instance->getPhone()); + self::assertNull($instance->phone); + } else { + self::assertEquals($value, $instance->getPhone()); + self::assertEquals($value, $instance->phone); + } + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSetterPhone($options) + { + $instance = new ReceiptCustomer(); + + self::assertNull($instance->getPhone()); + self::assertNull($instance->phone); + + $value = !empty($options['customer']['phone']) + ? $options['customer']['phone'] + : (!empty($options['phone']) ? $options['phone'] : null); + + $instance->phone = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getPhone()); + self::assertNull($instance->phone); + } else { + self::assertEquals($value, $instance->getPhone()); + self::assertEquals($value, $instance->phone); + } + } + + /** + * @dataProvider invalidPhoneProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidPhone($value) + { + $instance = new ReceiptCustomer(); + $instance->setPhone($value); + } + + public function invalidPhoneProvider() + { + return array( + array(new \stdClass()), + array(array()), + array(true), + array(false), + ); + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testGetSetEmail($options) + { + $instance = new ReceiptCustomer(); + + self::assertNull($instance->getEmail()); + self::assertNull($instance->email); + + $value = !empty($options['customer']['email']) + ? $options['customer']['email'] + : (!empty($options['email']) ? $options['email'] : null); + + $instance->setEmail($value); + if ($value === null || $value === '') { + self::assertNull($instance->getEmail()); + self::assertNull($instance->email); + } else { + self::assertEquals($value, $instance->getEmail()); + self::assertEquals($value, $instance->email); + } + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSetterEmail($options) + { + $instance = new ReceiptCustomer(); + + self::assertNull($instance->getEmail()); + self::assertNull($instance->email); + + $value = !empty($options['customer']['email']) + ? $options['customer']['email'] + : (!empty($options['email']) ? $options['email'] : null); + + $instance->email = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getEmail()); + self::assertNull($instance->email); + } else { + self::assertEquals($value, $instance->getEmail()); + self::assertEquals($value, $instance->email); + } + } + + /** + * @dataProvider validFullNameProvider + * @param $value + */ + public function testGetSetFullName($value) + { + $instance = new ReceiptCustomer(); + + self::assertNull($instance->getFullName()); + self::assertNull($instance->fullName); + self::assertNull($instance->full_name); + + $instance->setFullName($value); + if ($value === null || $value === '') { + self::assertNull($instance->getFullName()); + self::assertNull($instance->fullName); + self::assertNull($instance->full_name); + } else { + self::assertEquals($value, $instance->getFullName()); + self::assertEquals($value, $instance->fullName); + self::assertEquals($value, $instance->full_name); + } + } + + /** + * @dataProvider validFullNameProvider + * @param $value + */ + public function testSetterFullName($value) + { + $instance = new ReceiptCustomer(); + + self::assertNull($instance->getFullName()); + self::assertNull($instance->fullName); + self::assertNull($instance->full_name); + + $instance->fullName = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getFullName()); + self::assertNull($instance->fullName); + self::assertNull($instance->full_name); + } else { + self::assertEquals($value, $instance->getFullName()); + self::assertEquals($value, $instance->fullName); + self::assertEquals($value, $instance->full_name); + } + } + + /** + * @dataProvider validFullNameProvider + * @param $value + */ + public function testSetterFull_name($value) + { + $instance = new ReceiptCustomer(); + + self::assertNull($instance->getFullName()); + self::assertNull($instance->fullName); + self::assertNull($instance->full_name); + + $instance->full_name = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getFullName()); + self::assertNull($instance->fullName); + self::assertNull($instance->full_name); + } else { + self::assertEquals($value, $instance->getFullName()); + self::assertEquals($value, $instance->fullName); + self::assertEquals($value, $instance->full_name); + } + } + + public function validFullNameProvider() + { + return array( + array(null), + array(''), + array(Random::str(1)), + array(Random::str(null, 256)), + array(Random::str(256)), + ); + } + + /** + * @dataProvider invalidFullNameProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidFullName($value) + { + $instance = new ReceiptCustomer(); + $instance->setFullName($value); + } + + public function invalidFullNameProvider() + { + return array( + array(new \stdClass()), + array(array()), + array(true), + array(false), + array(Random::str(257)), + ); + } + + /** + * @dataProvider validInnProvider + * @param $value + */ + public function testGetSetInn($value) + { + $instance = new ReceiptCustomer(); + + self::assertNull($instance->getInn()); + self::assertNull($instance->inn); + + $instance->setInn($value); + if ($value === null || $value === '') { + self::assertNull($instance->getInn()); + self::assertNull($instance->inn); + } else { + self::assertEquals($value, $instance->getInn()); + self::assertEquals($value, $instance->inn); + } + } + + /** + * @dataProvider validInnProvider + * @param $options + */ + public function testSetterInn($options) + { + $instance = new ReceiptCustomer(); + + self::assertNull($instance->getInn()); + self::assertNull($instance->inn); + + $instance->inn = $options; + if ($options === null || $options === '') { + self::assertNull($instance->getInn()); + self::assertNull($instance->inn); + } else { + self::assertEquals($options, $instance->getInn()); + self::assertEquals($options, $instance->inn); + } + } + + public function validInnProvider() + { + return array( + array(null), + array(''), + array('1234567890'), + array('123456789012'), + array(Random::str(10, 10, '1234567890')), + array(Random::str(12, 12, '1234567890')), + ); + } + + /** + * @dataProvider invalidInnProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidInn($value) + { + $instance = new ReceiptCustomer(); + $instance->setInn($value); + } + + + public function invalidInnProvider() + { + return array( + array(new \stdClass()), + array(array()), + array(true), + array(false), + array('123456789'), + array('12345678901'), + array('1234567890123'), + array(Random::str(1)), + array(Random::str(10, 10, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')), + array(Random::str(12, 12, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')), + array(Random::str(13, 13, '1234567890')), + ); + } + + public function validDataProvider() + { + $result = array( + array( + array( + 'customer' => array(), + ), + ), + array( + array( + 'customer' => array(), + 'phone' => Random::str(10, 10, '1234567890'), + 'email' => uniqid() . '@' . uniqid(), + ), + ), + array( + array( + 'customer' => array( + 'phone' => Random::str(10, 10, '1234567890'), + 'email' => uniqid() . '@' . uniqid(), + ), + ), + ), + array( + array( + 'customer' => array( + 'full_name' => Random::str(1, 256), + 'inn' => Random::str(12, 12, '1234567890'), + ), + 'phone' => Random::str(10, 10, '1234567890'), + 'email' => uniqid() . '@' . uniqid(), + ), + ), + array( + array( + 'customer' => array( + 'full_name' => Random::str(1, 256), + 'phone' => Random::str(10, 10, '1234567890'), + 'email' => uniqid() . '@' . uniqid(), + 'inn' => Random::str(10, 10, '1234567890'), + ), + ), + ), + ); + + return $result; + } + + + /** + * @dataProvider fromArrayDataProvider + * @param array $source + * @param ReceiptCustomer $expected + */ + public function testCustomerFromArray($source, $expected) + { + $receipt = new Receipt(); + $receipt->fromArray($source); + + if (!empty($expected)) { + foreach ($expected->jsonSerialize() as $property => $value) { + self::assertEquals($value, $expected->offsetGet($property)); + } + } else { + self::assertEquals(true, $receipt->getCustomer()->isEmpty()); + } + } + + public function fromArrayDataProvider() + { + $customer = new ReceiptCustomer(); + $customer->setFullName('John Doe'); + $customer->setEmail('johndoe@yoomoney.ru'); + $customer->setPhone('79000000000'); + $customer->setInn('6321341814'); + + return array( + + array( + array(), + null, + ), + + array( + array( + 'customer' => array( + 'fullName' => 'John Doe', + 'email' => 'johndoe@yoomoney.ru', + 'phone' => '79000000000', + 'inn' => '6321341814', + ), + ), + + $customer + ), + + array( + array( + 'customer' => array( + 'full_name' => 'John Doe', + 'inn' => '6321341814', + 'email' => 'johndoe@yoomoney.ru', + 'phone' => '79000000000', + ), + ), + + $customer + ), + + array( + array( + 'customer' => array( + 'fullName' => 'John Doe', + 'inn' => '6321341814', + ), + 'email' => 'johndoe@yoomoney.ru', + 'phone' => '79000000000', + ), + + $customer + ), + + array( + array( + 'customer' => array( + 'full_name' => 'John Doe', + 'inn' => '6321341814', + 'email' => 'johndoe@yoomoney.ru', + ), + 'phone' => '79000000000', + ), + + $customer + ), + array( + array( + 'customer' => array( + 'fullName' => 'John Doe', + 'inn' => '6321341814', + 'phone' => '79000000000', + ), + 'email' => 'johndoe@yoomoney.ru', + ), + + $customer + ), + array( + array( + 'customer' => array( + 'full_name' => 'John Doe', + 'inn' => '6321341814', + 'phone' => '79000000000', + 'email' => 'johndoe@yoomoney.ru', + ), + 'email' => 'johndoeOld@yoomoney.ru', + ), + + $customer + ), + array( + array( + 'customer' => array( + 'fullName' => 'John Doe', + 'inn' => '6321341814', + 'phone' => '79000000000', + 'email' => 'johndoe@yoomoney.ru', + ), + 'phone' => '79111111111', + ), + + $customer + ), + array( + array( + 'customer' => array( + 'full_name' => 'John Doe', + 'inn' => '6321341814', + 'phone' => '79000000000', + 'email' => 'johndoe@yoomoney.ru', + ), + 'phone' => '79111111111', + 'email' => 'johndoeOld@yoomoney.ru', + ), + + $customer + ), + ); + } +} \ No newline at end of file diff --git a/tests/Model/ReceiptItemTest.php b/tests/Model/ReceiptItemTest.php new file mode 100644 index 00000000..753cc286 --- /dev/null +++ b/tests/Model/ReceiptItemTest.php @@ -0,0 +1,1206 @@ +getTestInstance(); + self::assertNull($instance->getDescription()); + self::assertNull($instance->description); + $instance->setDescription($value); + self::assertEquals((string)$value, $instance->getDescription()); + self::assertEquals((string)$value, $instance->description); + } + + /** + * @dataProvider validDescriptionDataProvider + * + * @param $value + */ + public function testSetterDescription($value) + { + $instance = $this->getTestInstance(); + $instance->description = $value; + self::assertEquals((string)$value, $instance->getDescription()); + self::assertEquals((string)$value, $instance->description); + } + + public function validDescriptionDataProvider() + { + return array( + array(Random::str(1)), + array(Random::str(2, 31)), + array(Random::str(32)), + array(new StringObject(Random::str(64))), + array(123), + array(45.3), + ); + } + + /** + * @dataProvider invalidDescriptionDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidDescription($value) + { + $this->getTestInstance()->setDescription($value); + } + + /** + * @dataProvider invalidDescriptionDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetterInvalidDescription($value) + { + $this->getTestInstance()->description = $value; + } + + public function invalidDescriptionDataProvider() + { + return array( + array(null), + array(''), + array(new StringObject('')), + array(true), + array(false), + array(new \stdClass()), + array(array()), + ); + } + + /** + * @dataProvider validQuantityDataProvider + * + * @param $value + */ + public function testGetSetQuantity($value) + { + $instance = $this->getTestInstance(); + + self::assertNull($instance->getQuantity()); + self::assertNull($instance->quantity); + $instance->setQuantity($value); + self::assertEquals((float)$value, $instance->getQuantity()); + self::assertEquals((float)$value, $instance->quantity); + } + + /** + * @dataProvider validQuantityDataProvider + * + * @param $value + */ + public function testSetterQuantity($value) + { + $instance = $this->getTestInstance(); + + $instance->quantity = $value; + self::assertEquals((float)$value, $instance->getQuantity()); + self::assertEquals((float)$value, $instance->quantity); + } + + public function validQuantityDataProvider() + { + return array( + array(1), + array(1.3), + array(0.001), + array(10000.001), + array('3.1415'), + array(Random::float(0.001, 9999.999)), + array(Random::int(1, 9999)), + ); + } + + /** + * @dataProvider invalidQuantityDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidQuantity($value) + { + $this->getTestInstance()->setQuantity($value); + } + + /** + * @dataProvider invalidQuantityDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetterInvalidQuantity($value) + { + $this->getTestInstance()->quantity = $value; + } + + public function invalidQuantityDataProvider() + { + return array( + array(null), + array(''), + array(0.0), + array(Random::float(-100, -0.001)), + array(array()), + array(new \stdClass()), + ); + } + + /** + * @dataProvider validVatCodeDataProvider + * + * @param $value + */ + public function testGetSetVatCode($value) + { + $instance = $this->getTestInstance(); + + self::assertNull($instance->getVatCode()); + self::assertNull($instance->vatCode); + self::assertNull($instance->vat_code); + $instance->setVatCode($value); + if ($value === null || $value === '') { + self::assertNull($instance->getVatCode()); + self::assertNull($instance->vatCode); + self::assertNull($instance->vat_code); + } else { + self::assertEquals((int)$value, $instance->getVatCode()); + self::assertEquals((int)$value, $instance->vatCode); + self::assertEquals((int)$value, $instance->vat_code); + } + } + + /** + * @dataProvider validVatCodeDataProvider + * + * @param $value + */ + public function testSetterVatCode($value) + { + $instance = $this->getTestInstance(); + + $instance->vatCode = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getVatCode()); + self::assertNull($instance->vatCode); + self::assertNull($instance->vat_code); + } else { + self::assertEquals((int)$value, $instance->getVatCode()); + self::assertEquals((int)$value, $instance->vatCode); + self::assertEquals((int)$value, $instance->vat_code); + } + } + + /** + * @dataProvider validDataAgent + * @param $value + */ + public function testSetAgentType($value) + { + $instance = $this->getTestInstance(); + self::assertNull($instance->getAgentType()); + $instance->setAgentType($value); + self::assertSame($value, $instance->getAgentType()); + } + + public function validDataAgent() + { + $values = array(); + for ($i = 0; $i < 5; $i++) { + $values[] = array(Random::value(AgentType::getValidValues())); + } + return $values; + } + + /** + * @dataProvider validDataSupplier + * @param $value + */ + public function testSetSupplier($value) + { + $instance = $this->getTestInstance(); + self::assertNull($instance->getSupplier()); + $instance->setSupplier($value); + if (is_array($value)) { + $value = new Supplier($value); + } + self::assertEquals($value, $instance->getSupplier()); + } + + /** + * @return array[] + * @throws \Exception + */ + public function validDataSupplier() + { + $validData = array( + array( + array( + 'name' => Random::str(1, 100), + 'phone' => '79000000000', + 'inn' => '1000000000', + ), + ), + ); + for ($i = 0; $i < 3; $i++) { + $supplier = array( + new Supplier( + array( + 'name' => Random::str(1, 100), + 'phone' => '79000000000', + 'inn' => '1000000000', + ) + ) + ); + $validData[] = $supplier; + } + return $validData; + } + /** + * @dataProvider validVatCodeDataProvider + * + * @param $value + */ + public function testSetterVat_code($value) + { + $instance = $this->getTestInstance(); + + $instance->vat_code = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getVatCode()); + self::assertNull($instance->vatCode); + self::assertNull($instance->vat_code); + } else { + self::assertEquals((int)$value, $instance->getVatCode()); + self::assertEquals((int)$value, $instance->vatCode); + self::assertEquals((int)$value, $instance->vat_code); + } + } + + /** + * @dataProvider validPaymentSubjectDataProvider + * + * @param $value + */ + public function testSetterPayment_subject($value) + { + $instance = $this->getTestInstance(); + + $instance->payment_subject = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getPaymentSubject()); + self::assertNull($instance->payment_subject); + self::assertNull($instance->paymentSubject); + } else { + self::assertContains($instance->getPaymentSubject(), PaymentSubject::getValidValues()); + self::assertContains($instance->payment_subject, PaymentSubject::getValidValues()); + self::assertContains($instance->paymentSubject, PaymentSubject::getValidValues()); + } + } + + /** + * @dataProvider validPaymentSubjectDataProvider + * + * @param $value + */ + public function testSetterPaymentSubject($value) + { + $instance = $this->getTestInstance(); + + $instance->paymentSubject = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getPaymentSubject()); + self::assertNull($instance->payment_subject); + self::assertNull($instance->paymentSubject); + } else { + self::assertContains($instance->getPaymentSubject(), PaymentSubject::getValidValues()); + self::assertContains($instance->payment_subject, PaymentSubject::getValidValues()); + self::assertContains($instance->paymentSubject, PaymentSubject::getValidValues()); + } + } + + /** + * @dataProvider validPaymentModeDataProvider + * + * @param $value + */ + public function testSetterPayment_mode($value) + { + $instance = $this->getTestInstance(); + + $instance->payment_mode = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getPaymentMode()); + self::assertNull($instance->payment_mode); + self::assertNull($instance->paymentMode); + } else { + self::assertContains($instance->getPaymentMode(), PaymentMode::getValidValues()); + self::assertContains($instance->payment_mode, PaymentMode::getValidValues()); + self::assertContains($instance->paymentMode, PaymentMode::getValidValues()); + } + } + + /** + * @dataProvider validPaymentModeDataProvider + * + * @param $value + */ + public function testSetterPaymentMode($value) + { + $instance = $this->getTestInstance(); + + $instance->paymentMode = $value; + if ($value === null || $value === '') { + self::assertNull($instance->getPaymentMode()); + self::assertNull($instance->payment_mode); + self::assertNull($instance->paymentMode); + } else { + self::assertContains($instance->getPaymentMode(), PaymentMode::getValidValues()); + self::assertContains($instance->payment_mode, PaymentMode::getValidValues()); + self::assertContains($instance->paymentMode, PaymentMode::getValidValues()); + } + } + + public function validVatCodeDataProvider() + { + return array( + array(null), + array(''), + array(1), + array(2), + array(3), + array(4), + array(5), + array(6), + ); + } + + public function validPaymentSubjectDataProvider() + { + return array( + array(null), + array(''), + array(PaymentSubject::ANOTHER), + array(PaymentSubject::AGENT_COMMISSION), + array(PaymentSubject::PAYMENT), + array(PaymentSubject::GAMBLING_PRIZE), + array(PaymentSubject::GAMBLING_BET), + array(PaymentSubject::COMPOSITE), + array(PaymentSubject::INTELLECTUAL_ACTIVITY), + array(PaymentSubject::LOTTERY_PRIZE), + array(PaymentSubject::LOTTERY), + array(PaymentSubject::SERVICE), + array(PaymentSubject::JOB), + array(PaymentSubject::EXCISE), + array(PaymentSubject::COMMODITY), + ); + } + + public function validPaymentModeDataProvider() + { + return array( + array(null), + array(''), + array(PaymentMode::ADVANCE), + array(PaymentMode::CREDIT), + array(PaymentMode::CREDIT_PAYMENT), + array(PaymentMode::FULL_PAYMENT), + array(PaymentMode::FULL_PREPAYMENT), + array(PaymentMode::PARTIAL_PAYMENT), + array(PaymentMode::PARTIAL_PREPAYMENT), + ); + } + + /** + * @dataProvider invalidVatCodeDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidVatCode($value) + { + $this->getTestInstance()->setVatCode($value); + } + + /** + * @dataProvider invalidVatCodeDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetterInvalidVatCode($value) + { + $this->getTestInstance()->vatCode = $value; + } + + /** + * @dataProvider invalidVatCodeDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetterInvalidVat_code($value) + { + $this->getTestInstance()->vat_code = $value; + } + + public function invalidVatCodeDataProvider() + { + return array( + array(true), + array(false), + array(array()), + array(new \stdClass()), + array(0), + array(7), + array(Random::int(-100, -1)), + array(Random::int(8, 100)), + ); + } + + /** + * @dataProvider validPriceDataProvider + * + * @param AmountInterface $value + */ + public function testGetSetPrice($value) + { + $instance = $this->getTestInstance(); + + self::assertNull($instance->getPrice()); + self::assertNull($instance->price); + $instance->setPrice($value); + self::assertSame($value, $instance->getPrice()); + self::assertSame($value, $instance->price); + } + + /** + * @dataProvider validPriceDataProvider + * + * @param AmountInterface $value + */ + public function testSetterPrice($value) + { + $instance = $this->getTestInstance(); + $instance->price = $value; + self::assertSame($value, $instance->getPrice()); + self::assertSame($value, $instance->price); + } + + public function validPriceDataProvider() + { + return array( + array( + new ReceiptItemAmount( + Random::int(1, 100), + Random::value(CurrencyCode::getValidValues()) + ), + ), + array( + new ReceiptItemAmount(), + ), + ); + } + + /** + * @dataProvider invalidPriceDataProvider + * + * @param $value + */ + public function testSetInvalidPrice($value) + { + if (class_exists('TypeError')) { + self::setExpectedException('TypeError'); + $this->getTestInstance()->setPrice($value); + } + } + + /** + * @dataProvider invalidPriceDataProvider + * + * @param $value + */ + public function testSetterInvalidPrice($value) + { + if (class_exists('TypeError')) { + self::setExpectedException('TypeError'); + $this->getTestInstance()->price = $value; + } + } + + public function invalidPriceDataProvider() + { + $result = array( + array(null), + array(''), + array(1.0), + array(1), + array(true), + array(false), + array(array()), + array(new \stdClass()), + ); + + return $result; + } + + /** + * @dataProvider validIsShippingDataProvider + * + * @param $value + */ + public function testGetSetIsShipping($value) + { + $instance = $this->getTestInstance(); + + self::assertFalse($instance->isShipping()); + $instance->setIsShipping($value); + if ($value) { + self::assertTrue($instance->isShipping()); + } else { + self::assertFalse($instance->isShipping()); + } + } + + /** + * @dataProvider validIsShippingDataProvider + * + * @param $value + */ + public function testSetterIsShipping($value) + { + $instance = $this->getTestInstance(); + + $instance->isShipping = $value; + if ($value) { + self::assertTrue($instance->isShipping()); + } else { + self::assertFalse($instance->isShipping()); + } + } + + /** + * @return array + */ + public function validIsShippingDataProvider() + { + return array( + array(true), + array(false), + array(0), + array(1), + array(2), + array(null), + array(''), + ); + } + + /** + * @expectedException \InvalidArgumentException + * @dataProvider invalidIsShippingDataProvider + * + * @param mixed $value + */ + public function testInvalidSetIsShipping($value) + { + $this->getTestInstance()->setIsShipping($value); + } + + /** + * @expectedException \InvalidArgumentException + * @dataProvider invalidIsShippingDataProvider + * + * @param mixed $value + */ + public function testInvalidSetterIsShipping($value) + { + $this->getTestInstance()->isShipping = $value; + } + + public function invalidIsShippingDataProvider() + { + return array( + array(array()), + array('true'), + array('false'), + array(new \stdClass()), + ); + } + + /** + * @dataProvider validApplyDiscountCoefficientDataProvider + * + * @param $baseValue + * @param $coefficient + * @param $expected + */ + public function testApplyDiscountCoefficient($baseValue, $coefficient, $expected) + { + $instance = $this->getTestInstance(); + + $instance->setPrice(new ReceiptItemAmount($baseValue)); + $instance->applyDiscountCoefficient($coefficient); + self::assertEquals($expected, $instance->getPrice()->getIntegerValue()); + } + + public function validApplyDiscountCoefficientDataProvider() + { + return array( + array(1, 1, 100), + array(1.01, 1, 101), + array(1.01, 0.5, 51), + array(1.01, 0.4, 40), + array(1.00, 0.5, 50), + array(1.00, 0.333333333, 33), + array(2.00, 0.333333333, 67), + ); + } + + /** + * @dataProvider invalidApplyDiscountCoefficientDataProvider + * @expectedException \InvalidArgumentException + * + * @param mixed $coefficient + */ + public function testInvalidApplyDiscountCoefficient($coefficient) + { + $instance = $this->getTestInstance(); + + $instance->setPrice(new ReceiptItemAmount(Random::int(100))); + $instance->applyDiscountCoefficient($coefficient); + } + + public function invalidApplyDiscountCoefficientDataProvider() + { + return array( + array(null), + array(''), + array('test'), + array(array()), + array(new \stdClass()), + array(-1.4), + array(-0.01), + array(-0.0001), + array(0.0), + array(true), + array(false), + ); + } + + /** + * @dataProvider validAmountDataProvider + * + * @param $price + * @param $quantity + */ + public function testGetAmount($price, $quantity) + { + $instance = $this->getTestInstance(); + $instance->setPrice(new ReceiptItemAmount($price)); + $instance->setQuantity($quantity); + $expected = (int)round($price * 100.0 * $quantity); + self::assertEquals($expected, $instance->getAmount()); + } + + public function validAmountDataProvider() + { + return array( + array(1, 1), + array(1.01, 1.01), + ); + } + + /** + * @dataProvider validIncreasePriceDataProvider + * + * @param float $price + * @param float $value + * @param int $expected + */ + public function testIncreasePrice($price, $value, $expected) + { + $instance = $this->getTestInstance(); + $instance->setPrice(new ReceiptItemAmount($price)); + $instance->increasePrice($value); + self::assertEquals($expected, $instance->getPrice()->getIntegerValue()); + } + + public function validIncreasePriceDataProvider() + { + return array( + array(1, 1, 200), + array(1.01, 3.03, 404), + array(1.01, -0.01, 100), + ); + } + + /** + * @dataProvider invalidIncreasePriceDataProvider + * @expectedException \InvalidArgumentException + * + * @param float $price + * @param float $value + */ + public function testInvalidIncreasePrice($price, $value) + { + $instance = $this->getTestInstance(); + $instance->setPrice(new ReceiptItemAmount($price)); + $instance->increasePrice($value); + } + + public function invalidIncreasePriceDataProvider() + { + return array( + array(1, -1), + array(1.01, -1.01), + array(1.01, -1.02), + array(1.01, null), + array(1.01, false), + array(1.01, true), + array(1.01, ''), + array(1.01, 'test'), + array(1.01, array()), + array(1.01, new \stdClass()), + ); + } + + /** + * @dataProvider validFetchItemDataProvider + * + * @param $price + * @param $quantity + * @param $fetch + */ + public function testFetchItem($price, $quantity, $fetch) + { + $instance = $this->getTestInstance(); + $instance->setPrice(new ReceiptItemAmount($price)); + $instance->setQuantity($quantity); + + $fetched = $instance->fetchItem($fetch); + self::assertTrue($fetched instanceof ReceiptItem); + self::assertNotSame($fetched->getPrice(), $instance->getPrice()); + self::assertEquals($fetch, $fetched->getQuantity()); + self::assertEquals($quantity - $fetch, $instance->getQuantity()); + self::assertEquals($price, $instance->getPrice()->getValue()); + self::assertEquals($price, $fetched->getPrice()->getValue()); + } + + public function validFetchItemDataProvider() + { + return array( + array(1, 2, 1), + array(1.01, 2, 1.5), + array(1.01, 2, 1.99), + array(1.01, 2, 1.9999), + ); + } + + /** + * @dataProvider invalidFetchItemDataProvider + * @expectedException \InvalidArgumentException + * + * @param $quantity + * @param $fetch + */ + public function testInvalidFetchItem($quantity, $fetch) + { + $instance = $this->getTestInstance(); + $instance->setPrice(new ReceiptItemAmount(Random::int(1, 100))); + $instance->setQuantity($quantity); + $instance->fetchItem($fetch); + + } + + public function invalidFetchItemDataProvider() + { + return array( + array(1, 1), + array(1.01, 1.01), + array(1.01, 1.02), + array(1, null), + array(1, ''), + array(1, 0.0), + array(1, -12.3), + array(1, array()), + array(1, new \stdClass()), + array(1, 'test'), + ); + } + + //////////////////////////////////////////////////////////////// + + /** + * @dataProvider validProductCodeDataProvider + * + * @param $value + */ + public function testGetSetProductCode($value) + { + $instance = $this->getTestInstance(); + self::assertNull($instance->getProductCode()); + self::assertNull($instance->productCode); + self::assertNull($instance->product_code); + $instance->setProductCode($value); + self::assertEquals((string)$value, $instance->getProductCode()); + self::assertEquals((string)$value, $instance->productCode); + self::assertEquals((string)$value, $instance->product_code); + } + + /** + * @dataProvider validProductCodeDataProvider + * + * @param $value + */ + public function testGetSetProduct_code($value) + { + $instance = $this->getTestInstance(); + $instance->product_code = $value; + self::assertEquals((string)$value, $instance->getProductCode()); + self::assertEquals((string)$value, $instance->productCode); + self::assertEquals((string)$value, $instance->product_code); + } + + /** + * @dataProvider validProductCodeDataProvider + * + * @param $value + */ + public function testSetterProductCode($value) + { + $instance = $this->getTestInstance(); + $instance->productCode = $value; + self::assertEquals((string)$value, $instance->getProductCode()); + self::assertEquals((string)$value, $instance->productCode); + self::assertEquals((string)$value, $instance->product_code); + } + + public function validProductCodeDataProvider() + { + return array( + array(null), + array(''), + array(Random::str(2, 96, '0123456789ABCDEF ')), + ); + } + + /** + * @dataProvider invalidProductCodeDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidProductCode($value) + { + $this->getTestInstance()->setProductCode($value); + } + + /** + * @dataProvider invalidProductCodeDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetterInvalidProductCode($value) + { + $this->getTestInstance()->productCode = $value; + } + + public function invalidProductCodeDataProvider() + { + return array( + array(new StringObject('')), + array(true), + array(false), + array(new \stdClass()), + array(array()), + array(Random::str(2, 96, 'GHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+-=`~?><:"\'')), + ); + } + + //////////////////////////////////////////////////////////////// + + /** + * @dataProvider validCountryOfOriginCodeDataProvider + * + * @param $value + */ + public function testGetSetCountryOfOriginCode($value) + { + $instance = $this->getTestInstance(); + self::assertNull($instance->getCountryOfOriginCode()); + self::assertNull($instance->countryOfOriginCode); + self::assertNull($instance->country_of_origin_code); + $instance->setCountryOfOriginCode($value); + self::assertEquals((string)$value, $instance->getCountryOfOriginCode()); + self::assertEquals((string)$value, $instance->countryOfOriginCode); + self::assertEquals((string)$value, $instance->country_of_origin_code); + } + + /** + * @dataProvider validCountryOfOriginCodeDataProvider + * + * @param $value + */ + public function testSetterCountryOfOrigin_code($value) + { + $instance = $this->getTestInstance(); + $instance->country_of_origin_code = $value; + self::assertEquals((string)$value, $instance->getCountryOfOriginCode()); + self::assertEquals((string)$value, $instance->countryOfOriginCode); + self::assertEquals((string)$value, $instance->country_of_origin_code); + } + + /** + * @dataProvider validCountryOfOriginCodeDataProvider + * + * @param $value + */ + public function testSetterCountryOfOriginCode($value) + { + $instance = $this->getTestInstance(); + $instance->countryOfOriginCode = $value; + self::assertEquals((string)$value, $instance->getCountryOfOriginCode()); + self::assertEquals((string)$value, $instance->countryOfOriginCode); + self::assertEquals((string)$value, $instance->country_of_origin_code); + } + + public function validCountryOfOriginCodeDataProvider() + { + return array( + array(null), + array(''), + array(Random::str(2, 2, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')), + ); + } + + /** + * @dataProvider invalidCountryOfOriginCodeDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidCountryOfOriginCode($value) + { + $this->getTestInstance()->setCountryOfOriginCode($value); + } + + /** + * @dataProvider invalidCountryOfOriginCodeDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetterInvalidCountryOfOriginCode($value) + { + $this->getTestInstance()->countryOfOriginCode = $value; + } + + public function invalidCountryOfOriginCodeDataProvider() + { + return array( + array(new StringObject('')), + array(true), + array(false), + array(new \stdClass()), + array(array()), + array(Random::int()), + array(Random::str(1, 1)), + array(Random::str(3, null, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')), + array(Random::str(2, 2, '0123456789!@#$%^&*()_+-=`~?><:"\' ')), + ); + } + + /** + * @dataProvider validCustomsDeclarationNumberDataProvider + * + * @param $value + */ + public function testGetSetCustomsDeclarationNumber($value) + { + $instance = $this->getTestInstance(); + self::assertNull($instance->getCustomsDeclarationNumber()); + self::assertNull($instance->customsDeclarationNumber); + self::assertNull($instance->customs_declaration_number); + $instance->setCustomsDeclarationNumber($value); + self::assertEquals((string)$value, $instance->getCustomsDeclarationNumber()); + self::assertEquals((string)$value, $instance->customsDeclarationNumber); + self::assertEquals((string)$value, $instance->customs_declaration_number); + } + + /** + * @dataProvider validCustomsDeclarationNumberDataProvider + * + * @param $value + */ + public function testSetterCustomsDeclaration_number($value) + { + $instance = $this->getTestInstance(); + $instance->customsDeclarationNumber = $value; + self::assertEquals((string)$value, $instance->getCustomsDeclarationNumber()); + self::assertEquals((string)$value, $instance->customsDeclarationNumber); + self::assertEquals((string)$value, $instance->customs_declaration_number); + } + + /** + * @dataProvider validCustomsDeclarationNumberDataProvider + * + * @param $value + */ + public function testSetterCustomsDeclarationNumber($value) + { + $instance = $this->getTestInstance(); + $instance->customsDeclarationNumber = $value; + self::assertEquals((string)$value, $instance->getCustomsDeclarationNumber()); + self::assertEquals((string)$value, $instance->customsDeclarationNumber); + self::assertEquals((string)$value, $instance->customs_declaration_number); + } + + public function validCustomsDeclarationNumberDataProvider() + { + return array( + array(null), + array(''), + array(Random::str(1)), + array(Random::str(2, 31)), + array(Random::str(32)), + ); + } + + /** + * @dataProvider invalidCustomsDeclarationNumberDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidCustomsDeclarationNumber($value) + { + $this->getTestInstance()->setCustomsDeclarationNumber($value); + } + + /** + * @dataProvider invalidCustomsDeclarationNumberDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetterInvalidCustomsDeclarationNumber($value) + { + $this->getTestInstance()->customsDeclarationNumber = $value; + } + + public function invalidCustomsDeclarationNumberDataProvider() + { + return array( + array(true), + array(false), + array(new \stdClass()), + array(array()), + array(Random::str(33, 64)), + ); + } + + /** + * @dataProvider validExciseDataProvider + * + * @param $value + */ + public function testGetSetExcise($value) + { + $instance = $this->getTestInstance(); + + self::assertNull($instance->getExcise()); + self::assertNull($instance->excise); + $instance->setExcise($value); + self::assertEquals((float)$value, $instance->getExcise()); + self::assertEquals((float)$value, $instance->excise); + } + + /** + * @dataProvider validExciseDataProvider + * + * @param $value + */ + public function testSetterExcise($value) + { + $instance = $this->getTestInstance(); + + $instance->excise = $value; + self::assertEquals((float)$value, $instance->getExcise()); + self::assertEquals((float)$value, $instance->excise); + } + + public function validExciseDataProvider() + { + return array( + array(null), + array(''), + array(1), + array(1.3), + array(0.001), + array(10000.001), + array('3.1415'), + array(Random::float(0.001, 9999.999)), + array(Random::int(1, 9999)), + ); + } + + /** + * @dataProvider invalidExciseDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidExcise($value) + { + $this->getTestInstance()->setExcise($value); + } + + /** + * @dataProvider invalidExciseDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetterInvalidExcise($value) + { + $this->getTestInstance()->excise = $value; + } + + public function invalidExciseDataProvider() + { + return array( + array(0.0), + array(Random::float(-100, -0.001)), + array(array()), + array(new \stdClass()), + ); + } +} \ No newline at end of file diff --git a/tests/Model/ReceiptTest.php b/tests/Model/ReceiptTest.php new file mode 100644 index 00000000..bd0aaf9a --- /dev/null +++ b/tests/Model/ReceiptTest.php @@ -0,0 +1,734 @@ +getItems()); + self::assertTrue(is_array($instance->getItems())); + self::assertEmpty($instance->getItems()); + + self::assertNotNull($instance->items); + self::assertTrue(is_array($instance->items)); + self::assertEmpty($instance->items); + + $item = new ReceiptItem(); + $instance->addItem($item); + $items = $instance->getItems(); + self::assertTrue(count($items) === 1); + foreach ($items as $tmp) { + self::assertSame($item, $tmp); + } + + $instance->setItems(array()); + self::assertNotNull($instance->getItems()); + self::assertTrue(is_array($instance->getItems())); + self::assertEmpty($instance->getItems()); + + $instance->setItems($items); + self::assertTrue(count($items) === 1); + foreach ($items as $tmp) { + self::assertSame($item, $tmp); + } + } + + /** + * @dataProvider invalidItemsProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidItems($value) + { + $instance = new Receipt(); + $instance->setItems($value); + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testGetSetTaxSystemCode($options) + { + $instance = new Receipt(); + + self::assertNull($instance->getTaxSystemCode()); + self::assertNull($instance->taxSystemCode); + self::assertNull($instance->tax_system_code); + + $instance->setTaxSystemCode($options['tax_system_code']); + self::assertEquals($options['tax_system_code'], $instance->getTaxSystemCode()); + self::assertEquals($options['tax_system_code'], $instance->taxSystemCode); + self::assertEquals($options['tax_system_code'], $instance->tax_system_code); + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSetterTaxSystemCode($options) + { + $instance = new Receipt(); + + self::assertNull($instance->getTaxSystemCode()); + self::assertNull($instance->taxSystemCode); + self::assertNull($instance->tax_system_code); + + $instance->taxSystemCode = $options['tax_system_code']; + self::assertEquals($options['tax_system_code'], $instance->getTaxSystemCode()); + self::assertEquals($options['tax_system_code'], $instance->taxSystemCode); + self::assertEquals($options['tax_system_code'], $instance->tax_system_code); + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSetterTax_system_code($options) + { + $instance = new Receipt(); + + self::assertNull($instance->getTaxSystemCode()); + self::assertNull($instance->taxSystemCode); + self::assertNull($instance->tax_system_code); + + $instance->tax_system_code = $options['tax_system_code']; + self::assertEquals($options['tax_system_code'], $instance->getTaxSystemCode()); + self::assertEquals($options['tax_system_code'], $instance->taxSystemCode); + self::assertEquals($options['tax_system_code'], $instance->tax_system_code); + } + + /** + * @dataProvider invalidTaxSystemIdProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidTaxSystemCode($value) + { + $instance = new Receipt(); + $instance->setTaxSystemCode($value); + } + + /** + * + */ + public function testNotEmpty() + { + $instance = new Receipt(); + + self::assertFalse($instance->notEmpty()); + $instance->addItem(new ReceiptItem()); + self::assertTrue($instance->notEmpty()); + $instance->setItems(array()); + self::assertFalse($instance->notEmpty()); + } + + public function validDataProvider() + { + $result = array( + array( + array( + 'items' => array(), + 'tax_system_code' => null, + 'customer' => array( + 'phone' => '', + 'email' => '', + ), + ), + ), + array( + array( + 'items' => array(), + 'tax_system_code' => '', + 'customer' => array( + 'phone' => '', + 'email' => '', + ), + ), + ), + array( + array( + 'items' => array(), + 'customer' => array( + 'phone' => '', + 'email' => '', + ), + 'tax_system_code' => '', + ), + ), + array( + array( + 'items' => array(), + 'customer' => array( + 'phone' => '', + 'email' => '', + ), + 'tax_system_code' => '', + ), + ), + array( + array( + 'items' => array(), + 'customer' => array( + 'phone' => '', + 'email' => '', + ), + 'tax_system_code' => '', + ), + ), + ); + for ($i = 1; $i < 6; $i++) { + $receipt = array( + 'items' => array(), + 'tax_system_code' => $i, + 'phone' => Random::str(10, 10, '1234567890'), + 'email' => uniqid() . '@' . uniqid(), + ); + $result[] = array($receipt); + } + return $result; + } + + public function invalidItemsProvider() + { + return array( + array(null), + array(new \stdClass()), + array('invalid_value'), + array(''), + array(0), + array(1), + array(true), + array(false), + array(1.43), + array( + array( + array( + 'description' => 'text', + 'quantity' => 1, + 'amount' => array( + 'value' => 1, + 'currency' => 'RUB', + ), + 'vat_code' => 1, + ), + ), + ), + array( + array(new \stdClass()), + ), + ); + } + + public function invalidTaxSystemIdProvider() + { + return array( + array(new \stdClass()), + array('invalid_value'), + array(0), + array(3234), + array(true), + array(false), + array(0.43), + ); + } + + public function invalidPhoneProvider() + { + return array( + array(new \stdClass()), + array(array()), + array(true), + array(false), + ); + } + + public function testGetAmountValue() + { + $receipt = new Receipt(); + self::assertEquals(0, $receipt->getAmountValue()); + + $item = new ReceiptItem(); + $item->setPrice(new MonetaryAmount(Random::float(0.01, 99.99))); + $item->setQuantity(Random::float(0.0001, 99.99)); + $receipt->addItem($item); + + $expected = (int)round($item->getPrice()->getIntegerValue() * $item->getQuantity()); + self::assertEquals($expected, $receipt->getAmountValue()); + self::assertEquals($expected, $receipt->getAmountValue(false)); + self::assertEquals(0, $receipt->getShippingAmountValue()); + + $item = new ReceiptItem(); + $item->setPrice(new MonetaryAmount(Random::float(0.01, 99.99))); + $item->setQuantity(Random::float(0.0001, 99.99)); + $receipt->addItem($item); + + $expected += (int)round($item->getPrice()->getIntegerValue() * $item->getQuantity()); + self::assertEquals($expected, $receipt->getAmountValue()); + self::assertEquals($expected, $receipt->getAmountValue(false)); + self::assertEquals(0, $receipt->getShippingAmountValue()); + + $item = new ReceiptItem(); + $item->setPrice(new MonetaryAmount(Random::float(0.01, 99.99))); + $item->setQuantity(Random::float(0.0001, 99.99)); + $item->setIsShipping(true); + $receipt->addItem($item); + + $shipping = $expected; + $expected += (int)round($item->getPrice()->getIntegerValue() * $item->getQuantity()); + + self::assertEquals($expected, $receipt->getAmountValue()); + self::assertEquals($shipping, $receipt->getAmountValue(false)); + self::assertEquals($expected - $shipping, $receipt->getShippingAmountValue()); + + $item = new ReceiptItem(); + $item->setPrice(new MonetaryAmount(Random::float(0.01, 99.99))); + $item->setQuantity(Random::float(0.0001, 99.99)); + $item->setIsShipping(true); + $receipt->addItem($item); + + $expected += (int)round($item->getPrice()->getIntegerValue() * $item->getQuantity()); + + self::assertEquals($expected, $receipt->getAmountValue()); + self::assertEquals($shipping, $receipt->getAmountValue(false)); + self::assertEquals($expected - $shipping, $receipt->getShippingAmountValue()); + + $item = new ReceiptItem(); + $item->setPrice(new MonetaryAmount(Random::float(0.01, 99.99))); + $item->setQuantity(Random::float(0.0001, 99.99)); + $receipt->addItem($item); + + $shipping += (int)round($item->getPrice()->getIntegerValue() * $item->getQuantity()); + $expected += (int)round($item->getPrice()->getIntegerValue() * $item->getQuantity()); + self::assertEquals($expected, $receipt->getAmountValue()); + self::assertEquals($shipping, $receipt->getAmountValue(false)); + self::assertEquals($expected - $shipping, $receipt->getShippingAmountValue()); + } + + /** + * @dataProvider validNormalizationDataProvider + * @param $items + * @param $amount + * @param $expected + */ + public function testNormalize($items, $amount, $expected, $withShipping = false) + { + $receipt = new Receipt(); + foreach ($items as $itemInfo) { + $item = new ReceiptItem(); + $item->setPrice(new MonetaryAmount($itemInfo['price'])); + if (!empty($itemInfo['quantity'])) { + $item->setQuantity($itemInfo['quantity']); + } else { + $item->setQuantity(1); + } + if (!empty($itemInfo['shipping'])) { + $item->setIsShipping(true); + } + $receipt->addItem($item); + } + $receipt->normalize(new MonetaryAmount($amount), $withShipping); + + self::assertEquals(count($expected), count($receipt->getItems())); + $expectedAmount = 0; + foreach ($receipt->getItems() as $index => $item) { + self::assertEquals($expected[$index]['price'], $item->getPrice()->getIntegerValue()); + self::assertEquals($expected[$index]['quantity'], $item->getQuantity()); + + $expectedAmount += $item->getAmount(); + } + self::assertEquals($expectedAmount, $amount * 100); + } + + public function validNormalizationDataProvider() + { + return array( + array( + array( + array('price' => 10.0), + ), + 9.0, + array( + array('price' => 900, 'quantity' => 1.0), + ) + ), + array( + array( + array('price' => 10.0), + array('price' => 20.0), + ), + 29.0, + array( + array('price' => 967, 'quantity' => 1.0), + array('price' => 1933, 'quantity' => 1.0), + ) + ), + array( + array( + array('price' => 10.0, 'quantity' => 1), + array('price' => 20.0, 'quantity' => 3), + ), + 29.0, + array( + array('price' => 413, 'quantity' => 1.0), + array('price' => 829, 'quantity' => 3.0), + ) + ), + array( + array( + array('price' => 50.0, 'quantity' => 3), + array('price' => 20.0, 'quantity' => 3), + ), + 100.0, + array( + array('price' => 2381, 'quantity' => 2.0), + array('price' => 2382, 'quantity' => 1.0), + array('price' => 952, 'quantity' => 3.0), + ) + ), + array( + array( + array('price' => 10.0, 'shipping' => true), + array('price' => 50.0, 'quantity' => 3), + array('price' => 10.0, 'shipping' => true), + array('price' => 20.0, 'quantity' => 3), + ), + 120.0, + array( + array('price' => 1000, 'quantity' => 1.0), + array('price' => 2381, 'quantity' => 2.0), + array('price' => 2382, 'quantity' => 1.0), + array('price' => 1000, 'quantity' => 1.0), + array('price' => 952, 'quantity' => 3.0), + ) + ), + array( + array( + array('price' => 50.0, 'quantity' => 1, 'shipping' => 1), + array('price' => 50.0, 'quantity' => 2), + array('price' => 20.0, 'quantity' => 3), + ), + 100.0, + array( + array('price' => 2381, 'quantity' => 1.0), + array('price' => 2381, 'quantity' => 1.0), + array('price' => 2382, 'quantity' => 1.0), + array('price' => 952, 'quantity' => 3.0), + ), + true + ), + array( + array( + array('price' => 50.0, 'quantity' => 1, 'shipping' => 1), + ), + 49.0, + array( + array('price' => 4900, 'quantity' => 1.0), + ), + true + ), + array( + array( + array('price' => 100.0, 'quantity' => 0.5), + array('price' => 100.0, 'quantity' => 0.4), + ), + 98.0, + array( + array('price' => 10889, 'quantity' => 0.25), + array('price' => 10888, 'quantity' => 0.25), + array('price' => 10889, 'quantity' => 0.4), + ), + true + ), + array( + array( + array('price' => 10, 'quantity' => 1), + array('price' => 300, 'quantity' => 1, 'shipping' => 1), + ), + 10.0, + array( + array('price' => 32, 'quantity' => 1), + array('price' => 968, 'quantity' => 1, 'shipping' => 1), + ), + true + ), + array( + array( + array('price' => 10, 'quantity' => 1), + array('price' => 300, 'quantity' => 1, 'shipping' => 1), + ), + 10.0, + array( + array('price' => 32, 'quantity' => 1), + array('price' => 968, 'quantity' => 1, 'shipping' => 1), + ), + false + ), + array( + array( + array('price' => 0.01, 'quantity' => 1), + array('price' => 0.02, 'quantity' => 1), + array('price' => 0.03, 'quantity' => 1), + array('price' => 300, 'quantity' => 1, 'shipping' => 1), + ), + 0.06, + array( + array('price' => 1, 'quantity' => 1), + array('price' => 1, 'quantity' => 1), + array('price' => 1, 'quantity' => 1), + array('price' => 3, 'quantity' => 1, 'shipping' => 1), + ), + false + ), + array( + array( + array('price' => 0.01, 'quantity' => 7), + array('price' => 0.02, 'quantity' => 11), + array('price' => 0.03, 'quantity' => 13), + array('price' => 300, 'quantity' => 1, 'shipping' => 1), + ), + 0.60, + array( + array('price' => 1, 'quantity' => 7), + array('price' => 1, 'quantity' => 11), + array('price' => 1, 'quantity' => 13), + array('price' => 29, 'quantity' => 1, 'shipping' => 1), + ), + false + ), + array( + array( + array('price' => 0.01, 'quantity' => 7), + array('price' => 0.02, 'quantity' => 11), + array('price' => 10, 'quantity' => 1), + array('price' => 300, 'quantity' => 1, 'shipping' => 1), + ), + 10.29, + array( + array('price' => 1, 'quantity' => 7), + array('price' => 1, 'quantity' => 11), + array('price' => 33, 'quantity' => 1), + array('price' => 978, 'quantity' => 1, 'shipping' => 1), + ), + false + ), + ); + } + + /** + * @dataProvider fromArrayDataProvider + * @param array $source + * @param array $expected + */ + public function testFromArray($source, $expected) + { + $receipt = new Receipt(); + $receipt->fromArray($source); + + if (!empty($expected)) { + foreach ($expected as $property => $value) { + self::assertEquals($value, $receipt->offsetGet($property)); + } + } else { + self::assertEquals(array(), $receipt->getItems()); + } + } + + public function fromArrayDataProvider() + { + $receiptItem = new ReceiptItem(); + $receiptItem->setDescription('test'); + $receiptItem->setQuantity(322); + $receiptItem->setVatCode(4); + $receiptItem->setPrice(new ReceiptItemAmount(5, 'USD')); + + return array( + array( + array(), + array(), + ), + + array( + array( + 'taxSystemCode' => 2, + 'customer' => array( + 'phone' => '1234567890', + 'email' => 'test@tset', + ), + 'items' => array( + new ReceiptItem(), + ), + ), + array( + 'tax_system_code' => 2, + 'customer' => new ReceiptCustomer(array( + 'phone' => '1234567890', + 'email' => 'test@tset', + )), + 'items' => array( + new ReceiptItem(), + ), + ), + ), + + array( + array( + 'tax_system_code' => 3, + 'customer' => array( + 'phone' => '1234567890', + 'email' => 'test@tset', + ), + 'items' => array( + array( + 'description' => 'test', + 'quantity' => 322, + 'amount' => array( + 'value' => 5, + 'currency' => 'USD', + ), + 'vat_code' => 4, + ), + new ReceiptItem(), + array( + 'description' => 'test', + 'quantity' => 322, + 'amount' => array( + 'value' => 5, + 'currency' => 'USD', + ), + 'vat_code' => 4, + ), + ), + ), + array( + 'taxSystemCode' => 3, + 'customer' => new ReceiptCustomer(array( + 'phone' => '1234567890', + 'email' => 'test@tset', + )), + 'items' => array( + $receiptItem, + new ReceiptItem(), + $receiptItem, + ), + ), + ), + ); + } + + /** + * @dataProvider fromArrayCustomerDataProvider + * @param array $source + * @param array $expected + */ + public function testCustomerFromArray($source, $expected) + { + $receipt = new Receipt(); + $receipt->fromArray($source); + + if (!empty($expected)) { + foreach ($expected as $property => $value) { + self::assertEquals($value, $receipt->offsetGet($property)); + } + } else { + self::assertEquals(true, $receipt->getCustomer()->isEmpty()); + } + } + + public function fromArrayCustomerDataProvider() + { + $customer = new ReceiptCustomer(); + $customer->setFullName('John Doe'); + $customer->setEmail('johndoe@yoomoney.ru'); + $customer->setPhone('79000000000'); + $customer->setInn('6321341814'); + + return array( + + array( + array(), + array(), + ), + + array( + array( + 'customer' => array( + 'fullName' => 'John Doe', + 'email' => 'johndoe@yoomoney.ru', + 'phone' => '79000000000', + 'inn' => '6321341814', + ), + ), + array( + 'customer' => $customer + ), + ), + + array( + array( + 'customer' => array( + 'full_name' => 'John Doe', + 'inn' => '6321341814', + 'email' => 'johndoe@yoomoney.ru', + 'phone' => '79000000000', + ), + ), + array( + 'customer' => $customer + ), + ), + + array( + array( + 'customer' => array( + 'full_name' => 'John Doe', + 'inn' => '6321341814', + 'email' => 'johndoe@yoomoney.ru', + 'phone' => '79000000000', + ), + ), + array( + 'customer' => $customer + ), + ), + + array( + array( + 'customer' => array( + 'full_name' => 'John Doe', + 'inn' => '6321341814', + 'email' => 'johndoe@yoomoney.ru', + 'phone' => '79000000000', + ), + ), + array( + 'customer' => $customer + ), + ), + array( + array( + 'customer' => array( + 'full_name' => 'John Doe', + 'inn' => '6321341814', + 'email' => 'johndoe@yoomoney.ru', + 'phone' => '79000000000', + ), + ), + array( + 'customer' => $customer + ), + ), + ); + } +} \ No newline at end of file diff --git a/tests/Model/RecipientTest.php b/tests/Model/RecipientTest.php new file mode 100644 index 00000000..9848765f --- /dev/null +++ b/tests/Model/RecipientTest.php @@ -0,0 +1,161 @@ +getAccountId()); + self::assertEquals(null, $instance->accountId); + self::assertEquals(null, $instance->account_id); + $instance->setAccountId($value); + self::assertEquals((string)$value, $instance->getAccountId()); + self::assertEquals((string)$value, $instance->accountId); + self::assertEquals((string)$value, $instance->account_id); + + $instance = new Recipient(); + $instance->accountId = $value; + self::assertEquals((string)$value, $instance->getAccountId()); + self::assertEquals((string)$value, $instance->accountId); + self::assertEquals((string)$value, $instance->account_id); + + $instance = new Recipient(); + $instance->account_id = $value; + self::assertEquals((string)$value, $instance->getAccountId()); + self::assertEquals((string)$value, $instance->accountId); + self::assertEquals((string)$value, $instance->account_id); + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidAccountId($value) + { + $instance = new Recipient(); + $instance->setAccountId($value); + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidAccountId($value) + { + $instance = new Recipient(); + $instance->accountId = $value; + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidAccount_id($value) + { + $instance = new Recipient(); + $instance->account_id = $value; + } + + /** + * @dataProvider validDataProvider + * + * @param $value + */ + public function testGetSetGatewayId($value) + { + $instance = new Recipient(); + + self::assertEquals(null, $instance->getGatewayId()); + self::assertEquals(null, $instance->gatewayId); + self::assertEquals(null, $instance->gateway_id); + $instance->setGatewayId($value); + self::assertEquals((string)$value, $instance->getGatewayId()); + self::assertEquals((string)$value, $instance->gatewayId); + self::assertEquals((string)$value, $instance->gateway_id); + + $instance = new Recipient(); + $instance->gatewayId = $value; + self::assertEquals((string)$value, $instance->getGatewayId()); + self::assertEquals((string)$value, $instance->gatewayId); + self::assertEquals((string)$value, $instance->gateway_id); + + $instance = new Recipient(); + $instance->gateway_id = $value; + self::assertEquals((string)$value, $instance->getGatewayId()); + self::assertEquals((string)$value, $instance->gatewayId); + self::assertEquals((string)$value, $instance->gateway_id); + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidGatewayId($value) + { + $instance = new Recipient(); + $instance->setGatewayId($value); + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidGatewayId($value) + { + $instance = new Recipient(); + $instance->gatewayId = $value; + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidGateway_id($value) + { + $instance = new Recipient(); + $instance->gateway_id = $value; + } + + public function validDataProvider() + { + $result = array( + array(Random::str(1)), + array(Random::str(2, 64)), + array(new StringObject(Random::str(1, 32))), + array(0), + array(123), + ); + return $result; + } + + public function invalidDataProvider() + { + return array( + array(null), + array(''), + array(true), + array(false), + array(array()), + array(new \stdClass()), + ); + } +} \ No newline at end of file diff --git a/tests/Model/RefundTest.php b/tests/Model/RefundTest.php new file mode 100644 index 00000000..2d6a615a --- /dev/null +++ b/tests/Model/RefundTest.php @@ -0,0 +1,598 @@ +getId()); + self::assertNull($instance->id); + + $instance->setId($value); + self::assertEquals((string)$value, $instance->getId()); + self::assertEquals((string)$value, $instance->id); + + $instance = new Refund(); + $instance->id = $value; + self::assertEquals((string)$value, $instance->getId()); + self::assertEquals((string)$value, $instance->id); + } + + public function validIdDataProvider() + { + $values = 'abcdefghijklmnopqrstuvwxyz'; + $values .= strtoupper($values) . '0123456789._-+'; + + return array( + array(Random::str(36, $values)), + array(Random::str(36, $values)), + array(new StringObject(Random::str(36, $values))), + array(new StringObject(Random::str(36, $values))), + ); + } + + /** + * @dataProvider invalidIdDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidId($value) + { + $instance = new Refund(); + $instance->setId($value); + } + + /** + * @dataProvider invalidIdDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidId($value) + { + $instance = new Refund(); + $instance->id = $value; + } + + /** + * @return array + */ + public function invalidIdDataProvider() + { + return array( + array(''), + array(null), + array(array()), + array(Random::str(1,35)), + array(Random::str(1)), + array(Random::str(35)), + array(Random::str(37,48)), + array(Random::str(37)), + array(new \stdClass()), + array(1), + array(0), + array(-1), + array(true), + array(false), + ); + } + + /** + * @dataProvider validSources + * @param $value + */ + public function testSetSources($value) + { + $instance = new CreateRefundRequest(); + $instance->setSources($value); + if (is_array($value)) { + $value = array(new Source($value[0])); + } + self::assertEquals($value, $instance->getSources()); + } + + /** + * @return array[] + * @throws \Exception + */ + public function validSources() + { + $sources = array(); + for($i = 0; $i < 10; $i++) { + $sources[$i][] = array( + 'account_id' => (string)Random::int(11111111, 99999999), + 'amount' => array( + 'value' => sprintf('%.2f', round(Random::float(0.1, 99.99), 2)), + 'currency' => Random::value(CurrencyCode::getValidValues()) + ), + 'platform_fee_amount' => array( + 'value' => sprintf('%.2f', round(Random::float(0.1, 99.99), 2)), + 'currency' => Random::value(CurrencyCode::getValidValues()) + ), + ); + } + $sources[$i][] = array(new Source($sources[0])); + + return array($sources); + } + + /** + * @dataProvider validIdDataProvider + * @param string $value + */ + public function testGetSetPaymentId($value) + { + $instance = new Refund(); + + self::assertNull($instance->getPaymentId()); + self::assertNull($instance->paymentId); + self::assertNull($instance->payment_id); + + $instance->setPaymentId($value); + self::assertEquals((string)$value, $instance->getPaymentId()); + self::assertEquals((string)$value, $instance->paymentId); + self::assertEquals((string)$value, $instance->payment_id); + + $instance = new Refund(); + $instance->paymentId = $value; + self::assertEquals((string)$value, $instance->getPaymentId()); + self::assertEquals((string)$value, $instance->paymentId); + self::assertEquals((string)$value, $instance->payment_id); + + $instance = new Refund(); + $instance->payment_id = $value; + self::assertEquals((string)$value, $instance->getPaymentId()); + self::assertEquals((string)$value, $instance->paymentId); + self::assertEquals((string)$value, $instance->payment_id); + } + + /** + * @dataProvider invalidIdDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidPaymentId($value) + { + $instance = new Refund(); + $instance->setPaymentId($value); + } + + /** + * @dataProvider invalidIdDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidPaymentId($value) + { + $instance = new Refund(); + $instance->paymentId = $value; + } + + /** + * @dataProvider invalidIdDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidPayment_id($value) + { + $instance = new Refund(); + $instance->payment_id = $value; + } + + /** + * @dataProvider validStatusDataProvider + * @param string $value + */ + public function testGetSetStatus($value) + { + $instance = new Refund(); + + self::assertNull($instance->getStatus()); + self::assertNull($instance->status); + + $instance->setStatus($value); + self::assertEquals((string)$value, $instance->getStatus()); + self::assertEquals((string)$value, $instance->status); + + $instance = new Refund(); + $instance->status = $value; + self::assertEquals((string)$value, $instance->getStatus()); + self::assertEquals((string)$value, $instance->status); + } + + /** + * @return array + */ + public function validStatusDataProvider() + { + $result = array(); + foreach (RefundStatus::getValidValues() as $value) { + $result[] = array($value); + $result[] = array(new StringObject($value)); + } + return $result; + } + + /** + * @dataProvider invalidIdDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidStatus($value) + { + $instance = new Refund(); + $instance->setStatus($value); + } + + /** + * @dataProvider invalidIdDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidStatus($value) + { + $instance = new Refund(); + $instance->status = $value; + } + + /** + * @dataProvider validCreatedAtDataProvider + * @param mixed $value + */ + public function testGetSetCreatedAt($value) + { + $instance = new Refund(); + + if (is_numeric($value)) { + $expected = $value; + } elseif ($value instanceof \DateTime) { + $expected = $value->getTimestamp(); + } else { + $expected = strtotime((string)$value); + } + + self::assertNull($instance->getCreatedAt()); + self::assertNull($instance->createdAt); + self::assertNull($instance->created_at); + + $instance->setCreatedAt($value); + self::assertSame($expected, $instance->getCreatedAt()->getTimestamp()); + self::assertSame($expected, $instance->createdAt->getTimestamp()); + self::assertSame($expected, $instance->created_at->getTimestamp()); + + $instance = new Refund(); + $instance->createdAt = $value; + self::assertSame($expected, $instance->getCreatedAt()->getTimestamp()); + self::assertSame($expected, $instance->createdAt->getTimestamp()); + self::assertSame($expected, $instance->created_at->getTimestamp()); + + $instance = new Refund(); + $instance->created_at = $value; + self::assertSame($expected, $instance->getCreatedAt()->getTimestamp()); + self::assertSame($expected, $instance->createdAt->getTimestamp()); + self::assertSame($expected, $instance->created_at->getTimestamp()); + } + + /** + * @return array + */ + public function validCreatedAtDataProvider() + { + return array( + array(new \DateTime()), + array(new \DateTime(date(DATE_ATOM, Random::int(1, time())))), + array(time()), + array(Random::int(1, time())), + array(date(DATE_ATOM)), + array(date(DATE_ATOM, Random::int(1, time()))), + array(new StringObject(date(DATE_ATOM))), + array(new StringObject(date(DATE_ATOM, Random::int(1, time())))), + ); + } + + /** + * @dataProvider invalidCreatedAtDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidCreatedAt($value) + { + $instance = new Refund(); + $instance->setCreatedAt($value); + } + + /** + * @dataProvider invalidCreatedAtDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidCreatedAt($value) + { + $instance = new Refund(); + $instance->createdAt = $value; + } + + /** + * @dataProvider invalidCreatedAtDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidCreated_at($value) + { + $instance = new Refund(); + $instance->created_at = $value; + } + + /** + * @return array + */ + public function invalidCreatedAtDataProvider() + { + return array( + array(null), + array(''), + array(array()), + array(new \stdClass()), + array('test'), + ); + } + + /** + * @dataProvider validAmountDataProvider + * @param AmountInterface $value + */ + public function testGetSetAmount($value) + { + $instance = new Refund(); + + self::assertNull($instance->getAmount()); + self::assertNull($instance->amount); + + $instance->setAmount($value); + self::assertSame($value, $instance->getAmount()); + self::assertSame($value, $instance->amount); + + $instance = new Refund(); + $instance->amount = $value; + self::assertSame($value, $instance->getAmount()); + self::assertSame($value, $instance->amount); + } + + /** + * @return array + */ + public function validAmountDataProvider() + { + return array( + array(new MonetaryAmount(1)), + array(new MonetaryAmount(Random::float(0.01, 9999999.99))), + ); + } + + /** + * @dataProvider invalidAmountDataProvider + * @param mixed $value + */ + public function testSetInvalidAmount($value) + { + if ($value instanceof AmountInterface) { + self::setExpectedException('InvalidArgumentException'); + $instance = new Refund(); + $instance->setAmount($value); + } elseif (class_exists('TypeError')) { + self::setExpectedException('TypeError'); + $instance = new Refund(); + $instance->setAmount($value); + } + } + + /** + * @dataProvider invalidAmountDataProvider + * @param mixed $value + */ + public function testSetterInvalidAmount($value) + { + if ($value instanceof AmountInterface) { + self::setExpectedException('InvalidArgumentException'); + $instance = new Refund(); + $instance->amount = $value; + } elseif (class_exists('TypeError')) { + self::setExpectedException('TypeError'); + $instance = new Refund(); + $instance->amount = $value; + } + } + + /** + * @return array + */ + public function invalidAmountDataProvider() + { + return array( + array(''), + array(null), + array(true), + array(false), + array(new MonetaryAmount()), + array(array()), + array(1), + array(new \stdClass()), + ); + } + + /** + * @dataProvider validReceiptRegisteredDataProvider + * @param string $value + */ + public function testGetSetReceiptRegistered($value) + { + $instance = new Refund(); + + self::assertNull($instance->getReceiptRegistration()); + self::assertNull($instance->receiptRegistration); + self::assertNull($instance->receipt_registration); + + $instance->setReceiptRegistration($value); + self::assertEquals((string)$value, $instance->getReceiptRegistration()); + self::assertEquals((string)$value, $instance->receiptRegistration); + self::assertEquals((string)$value, $instance->receipt_registration); + + $instance = new Refund(); + $instance->receiptRegistration = $value; + self::assertEquals((string)$value, $instance->getReceiptRegistration()); + self::assertEquals((string)$value, $instance->receiptRegistration); + self::assertEquals((string)$value, $instance->receipt_registration); + + $instance = new Refund(); + $instance->receipt_registration = $value; + self::assertEquals((string)$value, $instance->getReceiptRegistration()); + self::assertEquals((string)$value, $instance->receiptRegistration); + self::assertEquals((string)$value, $instance->receipt_registration); + } + + /** + * @return array + */ + public function validReceiptRegisteredDataProvider() + { + $result = array(); + foreach (ReceiptRegistrationStatus::getValidValues() as $value) { + $result[] = array($value); + $result[] = array(new StringObject($value)); + } + return $result; + } + + /** + * @dataProvider invalidReceiptRegisteredDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidReceiptRegistered($value) + { + $instance = new Refund(); + $instance->setReceiptRegistration($value); + } + + /** + * @dataProvider invalidReceiptRegisteredDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidReceiptRegistration($value) + { + $instance = new Refund(); + $instance->receiptRegistration = $value; + } + + /** + * @dataProvider invalidReceiptRegisteredDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidReceipt_registration($value) + { + $instance = new Refund(); + $instance->receipt_registration = $value; + } + + /** + * @return array + */ + public function invalidReceiptRegisteredDataProvider() + { + return array( + array(''), + array(null), + array(true), + array(false), + array(array()), + array(new \stdClass()), + array(Random::str(1,10)), + array(new StringObject(Random::str(1,10))), + ); + } + + /** + * @dataProvider validCommentDataProvider + * @param string $value + */ + public function testGetSetDescription($value) + { + $instance = new Refund(); + + self::assertNull($instance->getDescription()); + self::assertNull($instance->description); + + $instance->setDescription($value); + self::assertEquals((string)$value, $instance->getDescription()); + self::assertEquals((string)$value, $instance->description); + + $instance = new Refund(); + $instance->description = $value; + self::assertEquals((string)$value, $instance->getDescription()); + self::assertEquals((string)$value, $instance->description); + } + + public function validCommentDataProvider() + { + return array( + array(Random::str(1, 249)), + array(new StringObject(Random::str(1, 249))), + array(Random::str(250)), + array(new StringObject(Random::str(250))), + ); + } + + /** + * @dataProvider invalidCommentDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidComment($value) + { + $instance = new Refund(); + $instance->setDescription($value); + } + + /** + * @dataProvider invalidCommentDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidComment($value) + { + $instance = new Refund(); + $instance->description = $value; + } + + public function invalidCommentDataProvider() + { + return array( + array(null), + array(''), + array(array()), + array(true), + array(false), + array(new \stdClass()), + ); + } +} \ No newline at end of file diff --git a/tests/Model/SettlementTest.php b/tests/Model/SettlementTest.php new file mode 100644 index 00000000..e7ad5315 --- /dev/null +++ b/tests/Model/SettlementTest.php @@ -0,0 +1,195 @@ +getTestInstance(); + + self::assertNull($instance->getType()); + self::assertNull($instance->getAmount()); + self::assertNull($instance->type); + self::assertNull($instance->amount); + + $instance->fromArray($value); + + self::assertSame($value['type'], $instance->getType()); + self::assertSame($value['type'], $instance->type); + self::assertSame($value['amount'], $instance->getAmount()->jsonSerialize()); + self::assertSame($value['amount'], $instance->amount->jsonSerialize()); + + self::assertSame($value, $instance->jsonSerialize()); + } + + /** + * @dataProvider validDataProvider + * + * @param array $value + */ + public function testGetSetType($value) + { + $instance = $this->getTestInstance(); + + self::assertNull($instance->getType()); + self::assertNull($instance->type); + $instance->setType($value['type']); + self::assertSame($value['type'], $instance->getType()); + self::assertSame($value['type'], $instance->type); + } + + /** + * @dataProvider invalidTypeDataProvider + * + * @expectedException \InvalidArgumentException + * @expectedException EmptyPropertyValueException + * + * @param $value + */ + public function testSetInvalidType($value) + { + $this->getTestInstance()->setType($value); + } + + /** + * @return array + * @throws \Exception + */ + public function validDataProvider() + { + $result = array(); + for ($i = 0; $i < 10; $i++) { + $result[] = array( + 'type' => Random::value(SettlementType::getValidValues()), + 'amount' => array( + 'value' => sprintf('%.2f', round(Random::float(0.1, 99.99), 2)), + 'currency' => Random::value(CurrencyCode::getValidValues()) + ) + ); + } + return array($result); + } + + /** + * @dataProvider validAmountDataProvider + * + * @param AmountInterface $value + */ + public function testGetSetAmount($value) + { + $instance = $this->getTestInstance(); + + self::assertNull($instance->getAmount()); + self::assertNull($instance->amount); + $instance->setAmount($value); + self::assertSame($value, $instance->getAmount()); + self::assertSame($value, $instance->amount); + } + + /** + * @dataProvider validAmountDataProvider + * + * @param AmountInterface $value + */ + public function testSetterAmount($value) + { + $instance = $this->getTestInstance(); + $instance->amount = $value; + self::assertSame($value, $instance->getAmount()); + self::assertSame($value, $instance->amount); + } + + public function validAmountDataProvider() + { + return array( + array( + new MonetaryAmount( + Random::int(1, 100), + Random::value(CurrencyCode::getValidValues()) + ), + ), + array( + new MonetaryAmount(), + ), + ); + } + + /** + * @dataProvider invalidAmountDataProvider + * + * @expectedException \InvalidArgumentException + * @expectedException EmptyPropertyValueException + * + * @param $value + */ + public function testSetInvalidAmount($value) + { + $this->getTestInstance()->setAmount($value); + } + + /** + * @dataProvider invalidAmountDataProvider + * + * @expectedException \InvalidArgumentException + * @expectedException EmptyPropertyValueException + * + * @param $value + */ + public function testSetterInvalidAmount($value) + { + $this->getTestInstance()->amount = $value; + } + + public function invalidAmountDataProvider() + { + $result = array( + array(null), + array(''), + array(1.0), + array(1), + array(true), + array(false), + array(new \stdClass()), + ); + + return $result; + } + + public function invalidTypeDataProvider() + { + $result = array( + array(null), + array(''), + array(1.0), + array(1), + array(true), + array(false), + array(array()), + array(new \stdClass()), + array(Random::str(1, 10)), + ); + + return $result; + } + +} \ No newline at end of file diff --git a/tests/Model/SourceTest.php b/tests/Model/SourceTest.php new file mode 100644 index 00000000..8c3ee613 --- /dev/null +++ b/tests/Model/SourceTest.php @@ -0,0 +1,279 @@ +getTestInstance(); + + self::assertNull($instance->getAmount()); + self::assertNull($instance->getPlatformFeeAmount()); + self::assertNull($instance->getAccountId()); + self::assertNull($instance->amount); + self::assertNull($instance->platform_fee_amount); + self::assertNull($instance->accountId); + + $instance->fromArray($value); + + self::assertSame($value['account_id'], $instance->getAccountId()); + self::assertSame($value['account_id'], $instance->accountId); + self::assertSame($value['amount'], $instance->getAmount()->jsonSerialize()); + self::assertSame($value['amount'], $instance->amount->jsonSerialize()); + self::assertSame($value['platform_fee_amount'], $instance->getPlatformFeeAmount()->jsonSerialize()); + self::assertSame($value['platform_fee_amount'], $instance->platform_fee_amount->jsonSerialize()); + + self::assertSame($value, $instance->jsonSerialize()); + } + + /** + * @dataProvider validDataProvider + * + * @param array $value + */ + public function testGetSetAccountId($value) + { + $instance = $this->getTestInstance(); + + self::assertNull($instance->getAccountId()); + self::assertNull($instance->accountId); + $instance->setAccountId($value['account_id']); + self::assertSame($value['account_id'], $instance->getAccountId()); + self::assertSame($value['account_id'], $instance->accountId); + } + + /** + * @dataProvider validDataProvider + * + * @param AmountInterface $value + */ + public function testSetterAccountId($value) + { + $instance = $this->getTestInstance(); + $instance->accountId = $value['account_id']; + self::assertSame($value['account_id'], $instance->getAccountId()); + self::assertSame($value['account_id'], $instance->accountId); + } + + /** + * @return array + * @throws \Exception + */ + public function validDataProvider() + { + $result = array(); + for ($i = 0; $i < 10; $i++) { + $result[] = array( + 'account_id' => (string)Random::int(11111111, 99999999), + 'amount' => array( + 'value' => sprintf('%.2f', round(Random::float(0.1, 99.99), 2)), + 'currency' => Random::value(CurrencyCode::getValidValues()) + ), + 'platform_fee_amount' => array( + 'value' => sprintf('%.2f', round(Random::float(0.1, 99.99), 2)), + 'currency' => Random::value(CurrencyCode::getValidValues()) + ) + ); + } + return array($result); + } + + /** + * @dataProvider invalidAccountIdProvider + * + * @expectedException \InvalidArgumentException + * + * @param mixed $value + */ + public function testGetSetInvalidAccountId($value) + { + $this->getTestInstance()->setAccountId($value); + } + + /** + * @dataProvider invalidAccountIdProvider + * + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetterInvalidAccountId($value) + { + $this->getTestInstance()->accountId = $value; + } + + /** + * @return array + */ + public function invalidAccountIdProvider() + { + return array( + array(null), + array(''), + array(array()), + array(new \stdClass()), + ); + } + + /** + * @dataProvider validAmountDataProvider + * + * @param $value + */ + public function testGetSetAmount($value) + { + $instance = $this->getTestInstance(); + + self::assertNull($instance->getAmount()); + self::assertNull($instance->amount); + $instance->setAmount($value); + self::assertSame($value, $instance->getAmount()); + self::assertSame($value, $instance->amount); + } + + /** + * @dataProvider validAmountDataProvider + * + * @param AmountInterface $value + */ + public function testSetterAmount($value) + { + $instance = $this->getTestInstance(); + $instance->amount = $value; + self::assertSame($value, $instance->getAmount()); + self::assertSame($value, $instance->amount); + } + + /** + * @dataProvider validAmountDataProvider + * + * @param $value + */ + public function testGetSetPlatformFeeAmount($value) + { + $instance = $this->getTestInstance(); + + self::assertNull($instance->getPlatformFeeAmount()); + self::assertNull($instance->platform_fee_amount); + $instance->setPlatformFeeAmount($value); + self::assertSame($value, $instance->getPlatformFeeAmount()); + self::assertSame($value, $instance->platform_fee_amount); + } + + /** + * @dataProvider validAmountDataProvider + * + * @param AmountInterface $value + */ + public function testSetterPlatformFeeAmount($value) + { + $instance = $this->getTestInstance(); + $instance->platform_fee_amount = $value; + self::assertSame($value, $instance->getPlatformFeeAmount()); + self::assertSame($value, $instance->platform_fee_amount); + } + + /** + * @return \YooKassa\Model\MonetaryAmount[][] + * @throws \Exception + */ + public function validAmountDataProvider() + { + return array( + array( + new MonetaryAmount( + Random::int(1, 100), + Random::value(CurrencyCode::getValidValues()) + ), + ), + array( + new MonetaryAmount(), + ), + ); + } + + /** + * @dataProvider invalidAmountDataProvider + * + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidAmount($value) + { + $this->getTestInstance()->setAmount($value); + } + + /** + * @dataProvider invalidAmountDataProvider + * + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetterInvalidAmount($value) + { + $this->getTestInstance()->amount = $value; + } + + /** + * @dataProvider invalidAmountDataProvider + * + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidPlatformFeeAmount($value) + { + $this->getTestInstance()->setPlatformFeeAmount($value); + } + + /** + * @dataProvider invalidAmountDataProvider + * + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetterInvalidPlatformFeeAmount($value) + { + $this->getTestInstance()->platform_fee_amount = $value; + } + + /** + * @return array + */ + public function invalidAmountDataProvider() + { + return array( + array(null), + array(''), + array(1.0), + array(1), + array(true), + array(false), + array(new \stdClass()), + ); + } +} \ No newline at end of file diff --git a/tests/Model/TransferTest.php b/tests/Model/TransferTest.php new file mode 100644 index 00000000..04c0d859 --- /dev/null +++ b/tests/Model/TransferTest.php @@ -0,0 +1,363 @@ +getTestInstance(); + + self::assertNull($instance->getAmount()); + self::assertNull($instance->getPlatformFeeAmount()); + self::assertNull($instance->getAccountId()); + self::assertNull($instance->getStatus()); + self::assertNull($instance->amount); + self::assertNull($instance->platform_fee_amount); + self::assertNull($instance->accountId); + self::assertNull($instance->status); + + $instance->fromArray($value); + + self::assertSame($value['account_id'], $instance->getAccountId()); + self::assertSame($value['account_id'], $instance->accountId); + self::assertSame($value['amount'], $instance->getAmount()->jsonSerialize()); + self::assertSame($value['amount'], $instance->amount->jsonSerialize()); + self::assertSame($value['platform_fee_amount'], $instance->getPlatformFeeAmount()->jsonSerialize()); + self::assertSame($value['platform_fee_amount'], $instance->platform_fee_amount->jsonSerialize()); + self::assertSame($value['status'], $instance->getStatus()); + self::assertSame($value['status'], $instance->status); + + self::assertSame($value, $instance->jsonSerialize()); + } + + /** + * @dataProvider validDataProvider + * + * @param array $value + */ + public function testGetSetAccountId($value) + { + $instance = $this->getTestInstance(); + + self::assertNull($instance->getAccountId()); + self::assertNull($instance->accountId); + $instance->setAccountId($value['account_id']); + self::assertSame($value['account_id'], $instance->getAccountId()); + self::assertSame($value['account_id'], $instance->accountId); + } + + /** + * @dataProvider validDataProvider + * + * @param AmountInterface $value + */ + public function testSetterAccountId($value) + { + $instance = $this->getTestInstance(); + $instance->accountId = $value['account_id']; + self::assertSame($value['account_id'], $instance->getAccountId()); + self::assertSame($value['account_id'], $instance->accountId); + } + + /** + * @return array + * @throws \Exception + */ + public function validDataProvider() + { + $result = array(); + for ($i = 0; $i < 10; $i++) { + $result[] = array( + 'account_id' => (string)Random::int(11111111, 99999999), + 'amount' => array( + 'value' => sprintf('%.2f', round(Random::float(0.1, 99.99), 2)), + 'currency' => Random::value(CurrencyCode::getValidValues()) + ), + 'platform_fee_amount' => array( + 'value' => sprintf('%.2f', round(Random::float(0.1, 99.99), 2)), + 'currency' => Random::value(CurrencyCode::getValidValues()) + ), + 'status' => Random::value(TransferStatus::getValidValues()) + ); + } + return array($result); + } + + /** + * @dataProvider invalidAccountIdProvider + * + * @expectedException \InvalidArgumentException + * + * @param mixed $value + */ + public function testGetSetInvalidAccountId($value) + { + $this->getTestInstance()->setAccountId($value); + } + + /** + * @dataProvider invalidAccountIdProvider + * + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetterInvalidAccountId($value) + { + $this->getTestInstance()->accountId = $value; + } + + /** + * @return array + */ + public function invalidAccountIdProvider() + { + return array( + array(null), + array(''), + array(array()), + array(new \stdClass()), + ); + } + + /** + * @dataProvider validAmountDataProvider + * + * @param $value + */ + public function testGetSetAmount($value) + { + $instance = $this->getTestInstance(); + + self::assertNull($instance->getAmount()); + self::assertNull($instance->amount); + $instance->setAmount($value); + self::assertSame($value, $instance->getAmount()); + self::assertSame($value, $instance->amount); + } + + /** + * @dataProvider validAmountDataProvider + * + * @param AmountInterface $value + */ + public function testSetterAmount($value) + { + $instance = $this->getTestInstance(); + $instance->amount = $value; + self::assertSame($value, $instance->getAmount()); + self::assertSame($value, $instance->amount); + } + + /** + * @dataProvider validAmountDataProvider + * + * @param $value + */ + public function testGetSetPlatformFeeAmount($value) + { + $instance = $this->getTestInstance(); + + self::assertNull($instance->getPlatformFeeAmount()); + self::assertNull($instance->platform_fee_amount); + $instance->setPlatformFeeAmount($value); + self::assertSame($value, $instance->getPlatformFeeAmount()); + self::assertSame($value, $instance->platform_fee_amount); + } + + /** + * @dataProvider validAmountDataProvider + * + * @param AmountInterface $value + */ + public function testSetterPlatformFeeAmount($value) + { + $instance = $this->getTestInstance(); + $instance->platform_fee_amount = $value; + self::assertSame($value, $instance->getPlatformFeeAmount()); + self::assertSame($value, $instance->platform_fee_amount); + } + + /** + * @return \YooKassa\Model\MonetaryAmount[][] + * @throws \Exception + */ + public function validAmountDataProvider() + { + return array( + array( + new MonetaryAmount( + Random::int(1, 100), + Random::value(CurrencyCode::getValidValues()) + ), + ), + array( + new MonetaryAmount(), + ), + ); + } + + /** + * @dataProvider invalidAmountDataProvider + * + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidAmount($value) + { + $this->getTestInstance()->setAmount($value); + } + + /** + * @dataProvider invalidAmountDataProvider + * + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetterInvalidAmount($value) + { + $this->getTestInstance()->amount = $value; + } + + /** + * @dataProvider invalidAmountDataProvider + * + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidPlatformFeeAmount($value) + { + $this->getTestInstance()->setPlatformFeeAmount($value); + } + + /** + * @dataProvider invalidAmountDataProvider + * + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetterInvalidPlatformFeeAmount($value) + { + $this->getTestInstance()->platform_fee_amount = $value; + } + + /** + * @return array + */ + public function invalidAmountDataProvider() + { + return array( + array(null), + array(''), + array(1.0), + array(1), + array(true), + array(false), + array(new \stdClass()), + ); + } + + /** + * @dataProvider validStatusProvider + * + * @param $value + */ + public function testSetStatus($value) + { + $instance = $this->getTestInstance(); + self::assertNull($instance->getStatus()); + $instance->setStatus($value); + self::assertEquals($value, $instance->getStatus()); + } + + /** + * @dataProvider validStatusProvider + * + * @param $value + */ + public function testSetterStatus($value) + { + $instance = $this->getTestInstance(); + self::assertNull($instance->status); + $instance->status = $value; + self::assertEquals($value, $instance->status); + self::assertEquals($value, $instance->getStatus()); + } + + /** + * @return array[] + */ + public function validStatusProvider() + { + return array( + array(TransferStatus::SUCCEEDED), + array(TransferStatus::CANCELED), + array(TransferStatus::WAITING_FOR_CAPTURE), + array(TransferStatus::PENDING), + ); + } + + /** + * @dataProvider invalidStatusProvider + * + * @expectedException \InvalidArgumentException + * + * @param mixed $value + */ + public function testGetSetInvalidStatus($value) + { + $this->getTestInstance()->setStatus($value); + } + + /** + * @dataProvider invalidStatusProvider + * + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetterInvalidStatus($value) + { + $this->getTestInstance()->status = $value; + } + + /** + * @return array + * @throws \Exception + */ + public function invalidStatusProvider() + { + return array( + array(null), + array(''), + array(Random::str(15, 100)), + array(new \stdClass()), + ); + } +} \ No newline at end of file diff --git a/tests/Model/Webhook/WebhookTest.php b/tests/Model/Webhook/WebhookTest.php new file mode 100644 index 00000000..67188554 --- /dev/null +++ b/tests/Model/Webhook/WebhookTest.php @@ -0,0 +1,71 @@ +setId($data['id']); + $webhook->setUrl($data['url']); + $webhook->setEvent($data['event']); + + self::assertEquals($webhook->getId(), $data['id']); + self::assertEquals($webhook->getUrl(), $data['url']); + self::assertEquals($webhook->getEvent(), $data['event']); + } + + /** + * @dataProvider validDataProvider + * + * @param $data + */ + public function testWebhookConstructorInstantiate($data) + { + $webhook = new Webhook($data); + + self::assertEquals($webhook->getId(), $data['id']); + self::assertEquals($webhook->getUrl(), $data['url']); + self::assertEquals($webhook->getEvent(), $data['event']); + } + + /** + * @return array + */ + public function validDataProvider() + { + return array( + array( + array( + "id" => Random::str(20), + "event" => NotificationEventType::REFUND_SUCCEEDED, + "url" => Random::str(20), + ), + ), + array( + array( + "id" => Random::str(20), + "event" => NotificationEventType::PAYMENT_SUCCEEDED, + "url" => Random::str(20), + ), + ), + array( + array( + "id" => Random::str(20), + "event" => NotificationEventType::PAYMENT_WAITING_FOR_CAPTURE, + "url" => Random::str(20), + ), + ), + ); + } +} \ No newline at end of file diff --git a/tests/Request/Payments/AbstractPaymentResponseTest.php b/tests/Request/Payments/AbstractPaymentResponseTest.php new file mode 100644 index 00000000..aff36e33 --- /dev/null +++ b/tests/Request/Payments/AbstractPaymentResponseTest.php @@ -0,0 +1,409 @@ +getTestInstance($options); + self::assertEquals($options['id'], $instance->getId()); + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetStatus($options) + { + $instance = $this->getTestInstance($options); + self::assertEquals($options['status'], $instance->getStatus()); + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetRecipient($options) + { + $instance = $this->getTestInstance($options); + if (empty($options['recipient'])) { + self::assertNull($instance->getRecipient()); + } else { + if (!empty($options['recipient']['account_id'])) { + self::assertEquals($options['recipient']['account_id'], $instance->getRecipient()->getAccountId()); + } + if (!empty($options['recipient']['gateway_id'])) { + self::assertEquals($options['recipient']['gateway_id'], $instance->getRecipient()->getGatewayId()); + } + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetAmount($options) + { + $instance = $this->getTestInstance($options); + self::assertEquals(number_format($options['amount']['value'], 2, '.', ''), $instance->getAmount()->getValue()); + self::assertEquals($options['amount']['currency'], $instance->getAmount()->getCurrency()); + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetPaymentMethod($options) + { + $instance = $this->getTestInstance($options); + if (empty($options['payment_method'])) { + self::assertNull($instance->getPaymentMethod()); + } else { + self::assertEquals($options['payment_method']['type'], $instance->getPaymentMethod()->getType()); + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetCreatedAt($options) + { + $instance = $this->getTestInstance($options); + if (empty($options['created_at'])) { + self::assertNull($instance->getCreatedAt()); + } else { + self::assertEquals($options['created_at'], $instance->getCreatedAt()->format(DATE_ATOM)); + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetCapturedAt($options) + { + $instance = $this->getTestInstance($options); + if (empty($options['captured_at'])) { + self::assertNull($instance->getCapturedAt()); + } else { + self::assertEquals($options['captured_at'], $instance->getCapturedAt()->format(DATE_ATOM)); + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetConfirmation($options) + { + $instance = $this->getTestInstance($options); + if (empty($options['confirmation'])) { + self::assertNull($instance->getConfirmation()); + } else { + self::assertEquals($options['confirmation']['type'], $instance->getConfirmation()->getType()); + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetRefundedAmount($options) + { + $instance = $this->getTestInstance($options); + if (empty($options['refunded_amount'])) { + self::assertNull($instance->getRefundedAmount()); + } else { + self::assertEquals(number_format($options['refunded_amount']['value'], 2, '.', ''), $instance->getRefundedAmount()->getValue()); + self::assertEquals((string)$options['refunded_amount']['currency'], $instance->getRefundedAmount()->getCurrency()); + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetPaid($options) + { + $instance = $this->getTestInstance($options); + if (empty($options['paid'])) { + self::assertFalse($instance->getPaid()); + } else { + self::assertEquals($options['paid'], $instance->getPaid()); + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetRefundable($options) + { + $instance = $this->getTestInstance($options); + if (empty($options['refundable'])) { + self::assertFalse($instance->getRefundable()); + } else { + self::assertEquals($options['refundable'], $instance->getRefundable()); + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetTest($options) + { + $instance = $this->getTestInstance($options); + if (empty($options['test'])) { + self::assertNull($instance->getTest()); + } else { + self::assertEquals($options['test'], $instance->getTest()); + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetReceiptRegistration($options) + { + $instance = $this->getTestInstance($options); + if (empty($options['receipt_registration'])) { + self::assertNull($instance->getReceiptRegistration()); + } else { + self::assertEquals($options['receipt_registration'], $instance->getReceiptRegistration()); + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetMetadata($options) + { + $instance = $this->getTestInstance($options); + if (empty($options['metadata'])) { + self::assertNull($instance->getMetadata()); + } else { + self::assertEquals($options['metadata'], $instance->getMetadata()->toArray()); + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetTransfers($options) + { + $instance = $this->getTestInstance($options); + if (empty($options['transfers'])) { + self::assertEmpty($instance->getMetadata()); + } else { + foreach ($instance->getTransfers() as $transfer) { + self::assertInstanceOf('\YooKassa\Model\Transfer', $transfer); + } + } + } + + public function validDataProvider() + { + $result = array(); + $statuses = PaymentStatus::getValidValues(); + $receiptRegistrations = ReceiptRegistrationStatus::getValidValues(); + + $confirmations = array( + array( + 'type' => ConfirmationType::REDIRECT, + 'confirmation_url' => Random::str(10), + 'return_url' => Random::str(10), + 'enforce' => false, + ), + array( + 'type' => ConfirmationType::EXTERNAL, + ), + ); + + for ($i = 0; $i < 10; $i++) { + $payment = array( + 'id' => Random::str(36), + 'status' => Random::value($statuses), + 'description' => Random::str(128), + 'recipient' => array( + 'account_id' => Random::str(1, 64, '0123456789'), + 'gateway_id' => Random::str(1, 256), + ), + 'amount' => array( + 'value' => Random::float(0.01, 1000000.0), + 'currency' => Random::value(CurrencyCode::getEnabledValues()), + ), + 'payment_method' => array( + 'type' => Random::value(PaymentMethodType::getEnabledValues()), + ), + 'created_at' => date(DATE_ATOM, Random::int(1, time())), + 'captured_at' => date(DATE_ATOM, Random::int(1, time())), + 'expires_at' => date(DATE_ATOM, Random::int(1, time())), + 'confirmation' => Random::value($confirmations), + 'refunded_amount' => array( + 'value' => Random::float(0.01, 1000000.0), + 'currency' => Random::value(CurrencyCode::getValidValues()), + ), + 'paid' => $i % 2 ? true : false, + 'refundable' => $i % 2 ? true : false, + 'test' => $i % 2 ? true : false, + 'receipt_registration' => Random::value($receiptRegistrations), + 'metadata' => array( + 'value' => Random::float(0.01, 1000000.0), + 'currency' => Random::str(1, 256), + ), + 'requestor' => array( + 'type' => 'RequestorMarchant', + 'account_id' => Random::int(100000, 999999), + ), + 'authorization_details' => array( + 'rrn' => Random::str(10), + 'auth_code' => Random::str(10), + ), + 'transfers' => array( + new Transfer(array( + 'account_id' => Random::str(36), + 'amount' => new MonetaryAmount(Random::int(1, 1000), 'RUB'), + 'platform_fee_amount' => new MonetaryAmount(Random::int(1, 1000), 'RUB'), + 'status' => Random::value(TransferStatus::getValidValues()), + )), + ) + ); + $result[] = array($payment); + } + + $trueFalse = Random::bool(); + $result[] = array( + array( + 'id' => Random::str(36), + 'status' => Random::value($statuses), + 'description' => Random::str(128), + 'recipient' => array( + 'account_id' => Random::str(1, 64, '0123456789'), + 'gateway_id' => Random::str(1, 256), + ), + 'amount' => array( + 'value' => Random::float(0.01, 1000000.0), + 'currency' => Random::value(CurrencyCode::getValidValues()), + ), + 'payment_method' => array( + 'type' => PaymentMethodType::WECHAT, + ), + 'created_at' => date(DATE_ATOM, Random::int(1, time())), + 'captured_at' => date(DATE_ATOM, Random::int(1, time())), + 'expires_at' => date(DATE_ATOM, Random::int(1, time())), + 'requestor' => array( + 'type' => 'RequestorThirdPartyService', + 'client_id' => Random::int(100000, 999999), + 'client_name' => Random::str(1, 50), + ), + 'confirmation' => array( + 'type' => 'qr', + 'confirmation_data' => 'weixin://wxpay/bizpayurl?pr=SqTE9cX' + ), + 'paid' => $trueFalse, + 'refundable' => $trueFalse, + 'test' => $trueFalse, + 'metadata' => array(), + 'transfers' => array( + new Transfer(array( + 'account_id' => Random::str(36), + 'amount' => new MonetaryAmount(Random::int(1, 1000), 'RUB'), + 'platform_fee_amount' => new MonetaryAmount(Random::int(1, 1000), 'RUB'), + 'status' => Random::value(TransferStatus::getValidValues()), + )), + ) + ) + ); + + return $result; + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetCancellationDetails($options) + { + $instance = $this->getTestInstance($options); + if (empty($options['cancellation_details'])) { + self::assertNull($instance->getCancellationDetails()); + } else { + self::assertEquals( + $options['cancellation_details']['party'], + $instance->getCancellationDetails()->getParty() + ); + self::assertEquals( + $options['cancellation_details']['reason'], + $instance->getCancellationDetails()->getReason() + ); + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetAuthorizationDetails($options) + { + $instance = $this->getTestInstance($options); + if (empty($options['authorization_details'])) { + self::assertNull($instance->getAuthorizationDetails()); + } else { + self::assertEquals( + $options['authorization_details']['rrn'], + $instance->getAuthorizationDetails()->getRrn() + ); + self::assertEquals( + $options['authorization_details']['auth_code'], + $instance->getAuthorizationDetails()->getAuthCode() + ); + } + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testGetRequestor($options) + { + $instance = $this->getTestInstance($options); + + if ($options['requestor']['type'] === 'RequestorThirdPartyService') { + self::assertEquals($options['requestor']['type'], $instance->getRequestor()->getType()); + self::assertEquals($options['requestor']['client_id'], $instance->getRequestor()->getClientId()); + self::assertEquals($options['requestor']['client_name'], $instance->getRequestor()->getClientName()); + } else { + self::assertEquals($options['requestor']['type'], $instance->getRequestor()->getType()); + self::assertEquals($options['requestor']['account_id'], $instance->getRequestor()->getAccountId()); + } + } + +} diff --git a/tests/Request/Payments/CreatePaymentRequestBuilderTest.php b/tests/Request/Payments/CreatePaymentRequestBuilderTest.php new file mode 100644 index 00000000..0db5cd68 --- /dev/null +++ b/tests/Request/Payments/CreatePaymentRequestBuilderTest.php @@ -0,0 +1,1028 @@ +build($this->getRequiredData()); + self::assertNull($instance->getRecipient()); + + $builder->setAccountId($options['accountId']); + $instance = $builder->build($this->getRequiredData('accountId')); + + if ($options['accountId'] === null || $options['accountId'] === '') { + self::assertNull($instance->getRecipient()); + } else { + self::assertNotNull($instance->getRecipient()); + self::assertEquals($options['accountId'], $instance->getRecipient()->getAccountId()); + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws Exception + */ + public function testSetProductGroupId($options) + { + $builder = new CreatePaymentRequestBuilder(); + + $instance = $builder->build($this->getRequiredData()); + self::assertNull($instance->getRecipient()); + + $builder->setGatewayId($options['gatewayId']); + $instance = $builder->build($this->getRequiredData('gatewayId')); + + if (empty($options['gatewayId'])) { + self::assertNull($instance->getRecipient()); + } else { + self::assertNotNull($instance->getRecipient()); + self::assertEquals($options['gatewayId'], $instance->getRecipient()->getGatewayId()); + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws Exception + */ + public function testSetAmount($options) + { + $builder = new CreatePaymentRequestBuilder(); + + $instance = $builder->build($this->getRequiredData()); + self::assertNotNull($instance->getAmount()); + + $builder->setAmount($options['amount']); + $instance = $builder->build($this->getRequiredData('amount')); + + if ($options['amount'] instanceof AmountInterface) { + self::assertEquals($options['amount']->getValue(), $instance->getAmount()->getValue()); + } else { + self::assertEquals($options['amount'], $instance->getAmount()->getValue()); + } + + $builder->setAmount(10000)->setAmount($options['amount']); + $instance = $builder->build($this->getRequiredData('amount')); + + if ($options['amount'] instanceof AmountInterface) { + self::assertEquals($options['amount']->getValue(), $instance->getAmount()->getValue()); + } else { + self::assertEquals($options['amount'], $instance->getAmount()->getValue()); + } + + if (!($options['amount'] instanceof AmountInterface)) { + $builder->setAmount(array( + 'value' => $options['amount'], + 'currency' => 'EUR', + )); + $instance = $builder->build($this->getRequiredData('amount')); + self::assertEquals($options['amount'], $instance->getAmount()->getValue()); + } + } + + /** + * @expectedException InvalidArgumentException + * @dataProvider invalidAmountDataProvider + * + * @param $value + */ + public function testSetInvalidAmount($value) + { + $builder = new CreatePaymentRequestBuilder(); + $builder->setAmount($value); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws Exception + */ + public function testSetCurrency($options) + { + $builder = new CreatePaymentRequestBuilder(); + + $instance = $builder->build($this->getRequiredData()); + self::assertNotNull($instance->getAmount()); + self::assertEquals(CurrencyCode::RUB, $instance->getAmount()->getCurrency()); + + $builder->setReceiptItems($options['receiptItems']); + $builder->setCurrency($options['currency']); + $builder->setReceiptEmail($options['receiptEmail']); + $instance = $builder->build($this->getRequiredData()); + + self::assertEquals($options['currency'], $instance->getAmount()->getCurrency()); + if (!empty($options['receiptItems'])) { + foreach ($instance->getReceipt()->getItems() as $item) { + self::assertEquals($options['currency'], $item->getPrice()->getCurrency()); + } + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws Exception + */ + public function testSetReceiptItems($options) + { + $builder = new CreatePaymentRequestBuilder(); + + $builder->setReceiptItems($options['receiptItems']); + $builder->setReceiptEmail($options['receiptEmail']); + $instance = $builder->build($this->getRequiredData()); + + if (empty($options['receiptItems'])) { + self::assertNull($instance->getReceipt()); + } else { + self::assertNotNull($instance->getReceipt()); + self::assertEquals(count($options['receiptItems']), count($instance->getReceipt()->getItems())); + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws Exception + */ + public function testAddReceiptItems($options) + { + $builder = new CreatePaymentRequestBuilder(); + + foreach ($options['receiptItems'] as $item) { + if ($item instanceof ReceiptItem) { + $builder->addReceiptItem( + $item->getDescription(), $item->getPrice()->getValue(), $item->getQuantity(), $item->getVatCode(), + $item->getPaymentMode(), $item->getPaymentSubject() + ); + } else { + $builder->addReceiptItem($item['title'], $item['price'], $item['quantity'], $item['vatCode'], + $item['paymentMode'], $item['paymentSubject']); + } + } + $builder->setReceiptEmail($options['receiptEmail']); + $instance = $builder->build($this->getRequiredData()); + + if (empty($options['receiptItems'])) { + self::assertNull($instance->getReceipt()); + } else { + self::assertNotNull($instance->getReceipt()); + self::assertEquals(count($options['receiptItems']), count($instance->getReceipt()->getItems())); + foreach ($instance->getReceipt()->getItems() as $item) { + self::assertFalse($item->isShipping()); + } + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws Exception + */ + public function testAddReceiptShipping($options) + { + $builder = new CreatePaymentRequestBuilder(); + + foreach ($options['receiptItems'] as $item) { + if ($item instanceof ReceiptItem) { + $builder->addReceiptShipping( + $item->getDescription(), $item->getPrice()->getValue(), $item->getVatCode() + ); + } else { + $builder->addReceiptShipping($item['title'], $item['price'], $item['vatCode']); + } + } + $builder->setReceiptEmail($options['receiptEmail']); + $instance = $builder->build($this->getRequiredData()); + + if (empty($options['receiptItems'])) { + self::assertNull($instance->getReceipt()); + } else { + self::assertNotNull($instance->getReceipt()); + self::assertEquals(count($options['receiptItems']), count($instance->getReceipt()->getItems())); + foreach ($instance->getReceipt()->getItems() as $item) { + self::assertTrue($item->isShipping()); + } + } + } + + /** + * @dataProvider invalidItemsDataProvider + * @expectedException InvalidArgumentException + * + * @param $items + */ + public function testSetInvalidReceiptItems($items) + { + $builder = new CreatePaymentRequestBuilder(); + $builder->setReceiptItems($items); + } + + public function invalidItemsDataProvider() + { + return array( + array( + array( + array( + 'price' => 1, + 'quantity' => 1.4, + 'vatCode' => 3, + ), + ), + ), + array( + array( + array( + 'title' => 'test', + 'quantity' => 1.4, + 'vatCode' => 3, + ), + ), + ), + array( + array( + array( + 'description' => 'test', + 'quantity' => 1.4, + 'vatCode' => 3, + ), + ), + ), + array( + array( + array( + 'title' => 'test', + 'price' => 123, + 'quantity' => 1.4, + 'vatCode' => 7, + ), + ), + ), + array( + array( + array( + 'description' => 'test', + 'price' => 123, + 'quantity' => -1.4, + ), + ), + ), + array( + array( + array( + 'title' => 'test', + 'price' => 1, + 'vatCode' => 7, + ), + ), + ), + ); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws Exception + */ + public function testSetReceiptEmail($options) + { + $builder = new CreatePaymentRequestBuilder(); + + $builder->setReceiptItems($options['receiptItems']); + $builder->setReceiptEmail($options['receiptEmail']); + $instance = $builder->build($this->getRequiredData()); + + if (empty($options['receiptItems'])) { + self::assertNull($instance->getReceipt()); + } else { + self::assertNotNull($instance->getReceipt()); + self::assertEquals($options['receiptEmail'], $instance->getReceipt()->getCustomer()->getEmail()); + } + } + + /** + * @dataProvider invalidEmailDataProvider + * @expectedException InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidEmail($value) + { + $builder = new CreatePaymentRequestBuilder(); + $builder->setReceiptEmail($value); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws Exception + */ + public function testSetReceiptPhone($options) + { + $builder = new CreatePaymentRequestBuilder(); + + $builder->setReceiptItems($options['receiptItems']); + $builder->setReceiptEmail($options['receiptEmail']); + $builder->setReceiptPhone($options['receiptPhone']); + $instance = $builder->build($this->getRequiredData()); + + if (empty($options['receiptItems'])) { + self::assertNull($instance->getReceipt()); + } else { + self::assertNotNull($instance->getReceipt()); + self::assertEquals($options['receiptPhone'], $instance->getReceipt()->getCustomer()->getPhone()); + } + } + + /** + * @dataProvider invalidPhoneDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidPhone($value) + { + $builder = new CreatePaymentRequestBuilder(); + $builder->setReceiptPhone($value); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws Exception + */ + public function testSetReceiptTaxSystemCode($options) + { + $builder = new CreatePaymentRequestBuilder(); + + $builder->setReceiptItems($options['receiptItems']); + $builder->setReceiptEmail($options['receiptEmail']); + $builder->setTaxSystemCode($options['taxSystemCode']); + $instance = $builder->build($this->getRequiredData()); + + if (empty($options['receiptItems'])) { + self::assertNull($instance->getReceipt()); + } else { + self::assertNotNull($instance->getReceipt()); + self::assertEquals($options['taxSystemCode'], $instance->getReceipt()->getTaxSystemCode()); + } + } + + /** + * @dataProvider invalidVatIdDataProvider + * @expectedException InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidTaxSystemId($value) + { + $builder = new CreatePaymentRequestBuilder(); + $builder->setTaxSystemCode($value); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws Exception + */ + public function testSetPaymentToken($options) + { + $builder = new CreatePaymentRequestBuilder(); + + $instance = $builder->build($this->getRequiredData(null, 'paymentMethodId')); + self::assertNull($instance->getPaymentToken()); + self::assertNull($instance->paymentToken); + self::assertNull($instance->payment_token); + + if (empty($options['paymentToken'])) { + $buildData = $this->getRequiredData(null, 'paymentMethodId'); + } else { + $buildData = $this->getRequiredData('paymentToken'); + } + + $builder->setPaymentToken($options['paymentToken']); + $instance = $builder->build($buildData); + + if (empty($options['paymentToken'])) { + self::assertNull($instance->getPaymentToken()); + self::assertNull($instance->paymentToken); + self::assertNull($instance->payment_token); + } else { + self::assertEquals($options['paymentToken'], $instance->getPaymentToken()); + self::assertEquals($options['paymentToken'], $instance->paymentToken); + self::assertEquals($options['paymentToken'], $instance->payment_token); + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws Exception + */ + public function testSetPaymentMethodId($options) + { + $builder = new CreatePaymentRequestBuilder(); + + $instance = $builder->build($this->getRequiredData()); + self::assertNull($instance->getPaymentMethodId()); + + $builder->setPaymentMethodId($options['paymentMethodId']); + $instance = $builder->build($this->getRequiredData(empty($options['paymentMethodId']) ? null : 'paymentToken')); + + if (empty($options['paymentMethodId'])) { + self::assertNull($instance->getPaymentMethodId()); + } else { + self::assertEquals($options['paymentMethodId'], $instance->getPaymentMethodId()); + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws Exception + */ + public function testSetPaymentData($options) + { + $builder = new CreatePaymentRequestBuilder(); + + $instance = $builder->build($this->getRequiredData()); + self::assertNull($instance->getPaymentMethodData()); + + $builder->setPaymentMethodData($options['paymentMethodData']); + $instance = $builder->build($this->getRequiredData(empty($options['paymentMethodId']) ? null : 'paymentToken')); + + if (empty($options['paymentMethodData'])) { + self::assertNull($instance->getPaymentMethodData()); + } else { + if (is_object($options['paymentMethodData'])) { + self::assertSame($options['paymentMethodData'], $instance->getPaymentMethodData()); + } elseif (is_string($options['paymentMethodData'])) { + self::assertEquals($options['paymentMethodData'], $instance->getPaymentMethodData()->getType()); + } else { + self::assertEquals($options['paymentMethodData']['type'], $instance->getPaymentMethodData()->getType()); + } + } + + if (is_array($options['paymentMethodData'])) { + $builder = new CreatePaymentRequestBuilder(); + $builder->build($this->getRequiredData()); + $builder->setPaymentMethodData($options['paymentMethodData']['type'], $options['paymentMethodData']); + $instance = $builder->build($this->getRequiredData(empty($options['paymentMethodId']) ? null : 'paymentToken')); + self::assertEquals($options['paymentMethodData']['type'], $instance->getPaymentMethodData()->getType()); + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws Exception + */ + public function testSetConfirmationAttributes($options) + { + $builder = new CreatePaymentRequestBuilder(); + + $instance = $builder->build($this->getRequiredData()); + self::assertNull($instance->getConfirmation()); + + $builder->setConfirmation($options['confirmation']); + $instance = $builder->build($this->getRequiredData()); + + if (empty($options['confirmation'])) { + self::assertNull($instance->getConfirmation()); + } else { + if (is_object($options['confirmation'])) { + self::assertSame($options['confirmation'], $instance->getConfirmation()); + } elseif (is_string($options['confirmation'])) { + self::assertEquals($options['confirmation'], $instance->getConfirmation()->getType()); + } else { + self::assertEquals($options['confirmation']['type'], $instance->getConfirmation()->getType()); + self::assertEquals($options['confirmation']['locale'], $instance->getConfirmation()->getLocale()); + } + } + + if (is_array($options['confirmation'])) { + $builder = new CreatePaymentRequestBuilder(); + $builder->build($this->getRequiredData()); + $builder->setConfirmation($options['confirmation']['type'], $options['confirmation']); + $instance = $builder->build($this->getRequiredData()); + self::assertEquals($options['confirmation']['type'], $instance->getConfirmation()->getType()); + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws Exception + */ + public function testSetCreateRecurring($options) + { + $builder = new CreatePaymentRequestBuilder(); + + $instance = $builder->build($this->getRequiredData()); + self::assertNull($instance->getSavePaymentMethod()); + + $builder->setSavePaymentMethod($options['savePaymentMethod']); + $instance = $builder->build($this->getRequiredData()); + + if ($options['savePaymentMethod'] === null || $options['savePaymentMethod'] === '') { + self::assertNull($instance->getSavePaymentMethod()); + } else { + self::assertEquals($options['savePaymentMethod'], $instance->getSavePaymentMethod()); + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws Exception + */ + public function testSetCapture($options) + { + $builder = new CreatePaymentRequestBuilder(); + + $instance = $builder->build($this->getRequiredData()); + self::assertNull($instance->getCapture()); + + $builder->setCapture($options['capture']); + $instance = $builder->build($this->getRequiredData()); + + if ($options['capture'] === null || $options['capture'] === '') { + self::assertNull($instance->getCapture()); + } else { + self::assertEquals($options['capture'], $instance->getCapture()); + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws Exception + */ + public function testSetClientIp($options) + { + $builder = new CreatePaymentRequestBuilder(); + + $instance = $builder->build($this->getRequiredData()); + self::assertNull($instance->getClientIp()); + + $builder->setClientIp($options['clientIp']); + $instance = $builder->build($this->getRequiredData()); + + if (empty($options['clientIp'])) { + self::assertNull($instance->getClientIp()); + } else { + self::assertEquals($options['clientIp'], $instance->getClientIp()); + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws Exception + */ + public function testSetMetadata($options) + { + $builder = new CreatePaymentRequestBuilder(); + + $instance = $builder->build($this->getRequiredData()); + self::assertNull($instance->getMetadata()); + + $builder->setMetadata($options['metadata']); + $instance = $builder->build($this->getRequiredData()); + + if (empty($options['metadata'])) { + self::assertNull($instance->getMetadata()); + } else { + self::assertEquals($options['metadata'], $instance->getMetadata()->toArray()); + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws Exception + */ + public function testSetRecipient($options) + { + $recipient = new Recipient(); + $recipient->setAccountId($options['accountId']); + $recipient->setGatewayId($options['gatewayId']); + + $builder = new CreatePaymentRequestBuilder(); + $builder->setRecipient($recipient); + $instance = $builder->build($this->getRequiredData()); + + self::assertEquals($recipient, $instance->getRecipient()); + + $builder = new CreatePaymentRequestBuilder(); + $builder->setRecipient(array( + 'account_id' => $options['accountId'], + 'gateway_id' => $options['gatewayId'], + )); + $instance = $builder->build($this->getRequiredData()); + + self::assertEquals($recipient, $instance->getRecipient()); + } + + /** + * @dataProvider invalidRecipientDataProvider + * @expectedException InvalidArgumentException + * + * @param mixed $value + */ + public function testSetInvalidRecipient($value) + { + $builder = new CreatePaymentRequestBuilder(); + $builder->setRecipient($value); + } + + public function invalidRecipientDataProvider() + { + return array( + array(null), + array(true), + array(false), + array(1), + array(1.1), + array('test'), + array(new \stdClass()), + ); + } + + /** + * @throws Exception + */ + public function testSetReceipt() + { + $receipt = array( + 'tax_system_code' => Random::int(1, 6), + 'customer' => array( + 'email' => Random::str(10), + 'phone' => Random::str(4, 15, '0123456789'), + ), + 'items' => array( + array( + 'description' => 'test', + 'quantity' => 123, + 'amount' => array( + 'value' => 321, + 'currency' => 'USD', + ), + 'vat_code' => Random::int(1, 6), + 'payment_subject' => PaymentSubject::COMMODITY, + 'payment_mode' => PaymentMode::PARTIAL_PREPAYMENT, + ), + ), + ); + + $builder = new CreatePaymentRequestBuilder(); + $builder->setReceipt($receipt); + $instance = $builder->build($this->getRequiredData()); + + self::assertEquals($receipt['tax_system_code'], $instance->getReceipt()->getTaxSystemCode()); + self::assertEquals($receipt['customer']['email'], $instance->getReceipt()->getCustomer()->getEmail()); + self::assertEquals($receipt['customer']['phone'], $instance->getReceipt()->getCustomer()->getPhone()); + self::assertEquals(1, count($instance->getReceipt()->getItems())); + + $receipt = $instance->getReceipt(); + + $builder = new CreatePaymentRequestBuilder(); + $builder->setReceipt($instance->getReceipt()); + $instance = $builder->build($this->getRequiredData()); + + self::assertEquals($receipt['tax_system_code'], $instance->getReceipt()->getTaxSystemCode()); + self::assertEquals($receipt['customer']['email'], $instance->getReceipt()->getCustomer()->getEmail()); + self::assertEquals($receipt['customer']['phone'], $instance->getReceipt()->getCustomer()->getPhone()); + self::assertEquals(1, count($instance->getReceipt()->getItems())); + } + + /** + * @dataProvider invalidReceiptDataProvider + * @expectedException InvalidArgumentException + * + * @param mixed $value + */ + public function testSetInvalidReceipt($value) + { + $builder = new CreatePaymentRequestBuilder(); + $builder->setReceipt($value); + } + + public function invalidReceiptDataProvider() + { + return array( + array(null), + array(true), + array(false), + array(1), + array(1.1), + array('test'), + array(new \stdClass()), + ); + } + + /** + * @return array + * @throws Exception + */ + public function validDataProvider() + { + $receiptItem = new ReceiptItem(); + $receiptItem->setPrice(new MonetaryAmount(1)); + $receiptItem->setQuantity(1); + $receiptItem->setDescription('test'); + $receiptItem->setVatCode(3); + $result = array( + array( + array( + 'accountId' => Random::str(1, 32), + 'gatewayId' => Random::str(1, 32), + 'recipient' => null, + 'description' => null, + 'amount' => new MonetaryAmount(Random::int(1, 1000)), + 'currency' => Random::value(CurrencyCode::getValidValues()), + 'receiptItems' => array(), + 'paymentToken' => null, + 'paymentMethodId' => null, + 'paymentMethodData' => null, + 'confirmation' => null, + 'savePaymentMethod' => null, + 'capture' => null, + 'clientIp' => null, + 'metadata' => null, + 'receiptEmail' => null, + 'receiptPhone' => null, + 'taxSystemCode' => null, + ), + ), + array( + array( + 'accountId' => Random::str(1, 32), + 'gatewayId' => Random::str(1, 32), + 'recipient' => null, + 'description' => '', + 'amount' => new MonetaryAmount(Random::int(1, 1000)), + 'currency' => Random::value(CurrencyCode::getValidValues()), + 'receiptItems' => array( + array( + 'title' => 'test', + 'quantity' => mt_rand(1, 100), + 'price' => mt_rand(1, 100), + 'vatCode' => mt_rand(1, 6), + 'paymentMode' => PaymentMode::CREDIT_PAYMENT, + 'paymentSubject' => PaymentSubject::ANOTHER, + ), + $receiptItem, + ), + 'referenceId' => '', + 'paymentToken' => '', + 'paymentMethodId' => '', + 'paymentMethodData' => '', + 'confirmation' => '', + 'savePaymentMethod' => '', + 'capture' => '', + 'clientIp' => '', + 'metadata' => array(), + 'receiptEmail' => Random::str(10, 32), + 'receiptPhone' => '', + 'taxSystemCode' => '', + ), + ), + ); + $paymentMethodData = array( + new PaymentDataQiwi(), + PaymentMethodType::BANK_CARD, + array( + 'type' => PaymentMethodType::BANK_CARD, + ), + ); + $confirmationStatuses = array( + new ConfirmationAttributesExternal(), + ConfirmationType::EXTERNAL, + array( + 'type' => ConfirmationType::EXTERNAL, + 'locale' => 'en_US', + ), + array( + 'type' => ConfirmationType::QR, + 'locale' => 'ru_RU', + ), + ); + for ($i = 0; $i < 10; $i++) { + $request = array( + 'accountId' => uniqid(), + 'gatewayId' => uniqid(), + 'recipient' => new Recipient(), + 'description' => uniqid(), + 'amount' => mt_rand(1, 100000), + 'currency' => CurrencyCode::RUB, + 'receiptItems' => array(), + 'referenceId' => uniqid(), + 'paymentToken' => uniqid(), + 'paymentMethodId' => uniqid(), + 'paymentMethodData' => isset($paymentMethodData[$i]) ? $paymentMethodData[$i] : null, + 'confirmation' => isset($confirmationStatuses[$i]) ? $confirmationStatuses[$i] : null, + 'savePaymentMethod' => mt_rand(0, 1) ? true : false, + 'capture' => mt_rand(0, 1) ? true : false, + 'clientIp' => long2ip(mt_rand(0, pow(2, 32))), + 'metadata' => array('test' => 'test'), + 'receiptEmail' => Random::str(10), + 'receiptPhone' => Random::str(10, '0123456789'), + 'taxSystemCode' => Random::int(1, 6), + ); + $result[] = array($request); + } + + return $result; + } + + /** + * @return array + */ + public function invalidAmountDataProvider() + { + return array( + array(-1), + array(true), + array(false), + array(new \stdClass()), + array(0), + ); + } + + /** + * @return array + */ + public function invalidEmailDataProvider() + { + return array( + array(array()), + array(true), + array(false), + array(new \stdClass()), + ); + } + + /** + * @return array + * @throws Exception + */ + public function invalidPhoneDataProvider() + { + return array( + array(new \stdClass()), + array(array()), + array(true), + array(false), + ); + } + + /** + * @return array + * @throws Exception + */ + public function invalidVatIdDataProvider() + { + return array( + array(array()), + array(true), + array(false), + array(new \stdClass()), + array(0), + array(7), + array(Random::int(-100, -1)), + array(Random::int(7, 100)), + ); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws Exception + */ + public function testSetDescription($options) + { + $builder = new CreatePaymentRequestBuilder(); + + $builder->setDescription($options['description']); + $instance = $builder->build($this->getRequiredData()); + + if (empty($options['description'])) { + self::assertNull($instance->getDescription()); + } else { + self::assertEquals($options['description'], $instance->getDescription()); + } + } + + /** + * @expectedException InvalidArgumentException + */ + public function testSetInvalidTypeDescription() + { + $builder = new CreatePaymentRequestBuilder(); + $builder->setDescription(true); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testSetInvalidLengthDescription() + { + $builder = new CreatePaymentRequestBuilder(); + $description = Random::str(Payment::MAX_LENGTH_DESCRIPTION + 1); + $builder->setDescription($description); + } + + /** + * @dataProvider invalidVatIdDataProvider + * @expectedException InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidAirline($value) + { + if (is_array($value)) { + throw new \InvalidArgumentException(); + } + $builder = new CreatePaymentRequestBuilder(); + $builder->setAirline($value); + } +} \ No newline at end of file diff --git a/tests/Request/Payments/CreatePaymentRequestSerializerTest.php b/tests/Request/Payments/CreatePaymentRequestSerializerTest.php new file mode 100644 index 00000000..24e0e09e --- /dev/null +++ b/tests/Request/Payments/CreatePaymentRequestSerializerTest.php @@ -0,0 +1,357 @@ + 'paymentToken', + 'payment_method_id' => 'paymentMethodId', + 'client_ip' => 'clientIp', + ); + + /** + * @dataProvider validDataProvider + * + * @param $options + */ + public function testSerialize($options) + { + $serializer = new CreatePaymentRequestSerializer(); + $instance = CreatePaymentRequest::builder()->build($options); + $data = $serializer->serialize($instance); + + $expected = array( + 'amount' => array( + 'value' => $options['amount'], + 'currency' => isset($options['currency']) ? $options['currency'] : CurrencyCode::RUB, + ), + ); + foreach ($this->fieldMap as $mapped => $field) { + if (isset($options[$field])) { + $value = $options[$field]; + if (!empty($value)) { + $expected[$mapped] = $value instanceof \DateTime ? $value->format(DATE_ATOM) : $value; + } + } + } + if (!empty($options['accountId']) && !empty($options['gatewayId'])) { + $expected['recipient'] = array( + 'account_id' => $options['accountId'], + 'gateway_id' => $options['gatewayId'], + ); + } + if (!empty($options['confirmation'])) { + $expected['confirmation'] = array( + 'type' => $options['confirmation']->getType(), + ); + if ($locale = $options['confirmation']->getLocale()) { + $expected['confirmation']['locale'] = $locale; + } + if ($options['confirmation']->getType() === ConfirmationType::REDIRECT) { + $expected['confirmation']['enforce'] = $options['confirmation']->enforce; + $expected['confirmation']['return_url'] = $options['confirmation']->returnUrl; + } + } + if (!empty($options['paymentMethodData'])) { + $expected['payment_method_data'] = array( + 'type' => $options['paymentMethodData']->getType(), + ); + switch ($options['paymentMethodData']['type']) { + case PaymentMethodType::ALFABANK: + $expected['payment_method_data']['login'] = $options['paymentMethodData']->getLogin(); + break; + case PaymentMethodType::APPLE_PAY: + $expected['payment_method_data']['payment_data'] = $options['paymentMethodData']->getPaymentData(); + break; + case PaymentMethodType::GOOGLE_PAY: + $expected['payment_method_data']['payment_method_token'] = $options['paymentMethodData']->getPaymentMethodToken(); + $expected['payment_method_data']['google_transaction_id'] = $options['paymentMethodData']->getGoogleTransactionId(); + break; + case PaymentMethodType::BANK_CARD: + $expected['payment_method_data']['card'] = array( + 'number' => $options['paymentMethodData']->getCard()->getNumber(), + 'expiry_year' => $options['paymentMethodData']->getCard()->getExpiryYear(), + 'expiry_month' => $options['paymentMethodData']->getCard()->getExpiryMonth(), + 'csc' => $options['paymentMethodData']->getCard()->getCsc(), + 'cardholder' => $options['paymentMethodData']->getCard()->getCardholder(), + ); + break; + case PaymentMethodType::MOBILE_BALANCE: + case PaymentMethodType::CASH: + $expected['payment_method_data']['phone'] = $options['paymentMethodData']->getPhone(); + break; + case PaymentMethodType::SBERBANK: + $expected['payment_method_data']['phone'] = $options['paymentMethodData']->getPhone(); + break; + case PaymentMethodType::B2B_SBERBANK: + /** @var PaymentDataB2bSberbank $paymentMethodData */ + $paymentMethodData = $options['paymentMethodData']; + $expected['payment_method_data']['payment_purpose'] = $paymentMethodData->getPaymentPurpose(); + $expected['payment_method_data']['vat_data'] = array( + 'type' => $paymentMethodData->getVatData()->getType(), + 'rate' => $paymentMethodData->getVatData()->getRate(), + 'amount' => array( + 'value' => $paymentMethodData->getVatData()->getAmount()->getValue(), + 'currency' => $paymentMethodData->getVatData()->getAmount()->getCurrency(), + ), + ); + break; + } + } + if (!empty($options['metadata'])) { + $expected['metadata'] = array(); + foreach ($options['metadata'] as $key => $value) { + $expected['metadata'][$key] = $value; + } + } + if (!empty($options['receipt']['items'])) { + foreach ($options['receipt']['items'] as $item) { + $itemArray = $item; + + if (!empty($item['payment_subject'])) { + $itemArray['payment_subject'] = $item['payment_subject']; + } + if (!empty($item['payment_mode'])) { + $itemArray['payment_mode'] = $item['payment_mode']; + } + $expected['receipt']['items'][] = $itemArray; + } + if (!empty($options['receipt']['customer'])) { + $expected['receipt']['customer'] = $options['receipt']['customer']; + } + if (!empty($options['receipt']['tax_system_code'])) { + $expected['receipt']['tax_system_code'] = $options['receipt']['tax_system_code']; + } + } + + if (array_key_exists('capture', $options)) { + $expected['capture'] = (bool)$options['capture']; + } + if (array_key_exists('savePaymentMethod', $options)) { + $expected['save_payment_method'] = (bool)$options['savePaymentMethod']; + } + if (!empty($options['description'])) { + $expected['description'] = $options['description']; + } + + if (!empty($options['airline'])) { + $expected['airline'] = array( + 'booking_reference' => $options['airline']['booking_reference'], + 'ticket_number' => $options['airline']['ticket_number'], + 'passengers' => array_map(function ($passenger) { + return array( + 'first_name' => $passenger['first_name'], + 'last_name' => $passenger['last_name'], + ); + }, $options['airline']['passengers']), + 'legs' => array_map(function ($leg) { + return array( + 'departure_airport' => $leg['departure_airport'], + 'destination_airport' => $leg['destination_airport'], + 'departure_date' => $leg['departure_date'], + ); + }, $options['airline']['legs']), + ); + } + + self::assertEquals($expected, $data); + } + + /** + * @return array + * @throws \Exception + */ + public function validDataProvider() + { + $airline = new Airline(); + $airline->setBookingReference(Random::str(10)); + $airline->setTicketNumber(Random::int(10)); + $leg = new Leg(); + $leg->setDepartureAirport(Random::str(3, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')); + $leg->setDestinationAirport(Random::str(3, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')); + $leg->setDepartureDate("2018-12-31"); + $airline->setLegs(array($leg)); + $passenger = new Passenger(); + $passenger->setFirstName(Random::str(10)); + $passenger->setLastName(Random::str(10)); + $airline->setPassengers(array($passenger)); + + $result = array( + array( + array( + 'amount' => mt_rand(10, 100000), + 'paymentToken' => Random::str(36), + 'receipt' => array( + 'items' => array( + array( + 'description' => Random::str(10), + 'quantity' => (float)Random::int(1, 10), + 'amount' => array( + 'value' => (float)Random::int(100, 100), + 'currency' => CurrencyCode::RUB, + ), + 'vat_code' => Random::int(1, 6), + 'payment_subject' => PaymentSubject::COMMODITY, + 'payment_mode' => PaymentMode::PARTIAL_PREPAYMENT, + ) + ), + 'customer' => array( + 'email' => Random::str(10), + ), + 'tax_system_code' => Random::int(1, 6), + ), + 'description' => Random::str(10), + 'airline' => array( + 'booking_reference' => Random::str(10), + 'ticket_number' => Random::int(10), + 'passengers' => array( + array( + 'first_name' => Random::str(10, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), + 'last_name' => Random::str(10, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), + ), + ), + 'legs' => array( + array( + 'departure_airport' => Random::str(3, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), + 'destination_airport' => Random::str(3, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), + 'departure_date' => "2020-01-01", + ), + ), + ), + ), + ), + ); + $confirmations = array( + new ConfirmationAttributesExternal(), + new ConfirmationAttributesRedirect(), + ); + $paymentData = array( + new PaymentDataAlfabank(), + new PaymentDataApplePay(), + new PaymentDataGooglePay(), + new PaymentDataBankCard(), + new PaymentDataMobileBalance(), + new PaymentDataQiwi(), + new PaymentDataSberbank(), + new PaymentDataWebmoney(), + new PaymentDataYooMoney(), + new PaymentDataInstallments(), + new PaymentDataB2bSberbank(), + ); + $paymentData[0]->setLogin(Random::str(10)); + + $paymentData[1]->setPaymentData(Random::str(10)); + $paymentData[2]->setPaymentMethodToken(Random::str(10)); + $paymentData[2]->setGoogleTransactionId(Random::str(10)); + + $card = new PaymentDataBankCardCard(); + $card->setNumber(Random::str(16, '0123456789')); + $card->setExpiryYear(Random::int(2000, 2200)); + $card->setExpiryMonth(Random::value(array('01', '02', '03', '04', '05', '06', '07', '08', '09', '11', '12'))); + $card->setCsc(Random::str(4, '0123456789')); + $card->setCardholder(Random::str(26, 'abcdefghijklmnopqrstuvwxyz')); + $paymentData[3]->setCard($card); + $paymentData[4]->setPhone(Random::str(14, '0123456789')); + + $paymentData[6]->setPhone(Random::str(14, '0123456789')); + + /** @var PaymentDataB2bSberbank $paymentData [10] */ + $paymentDataB2bSberbank = new PaymentDataB2bSberbank(); + $paymentDataB2bSberbank->setPaymentPurpose(Random::str(10)); + $paymentDataB2bSberbank->setVatData(array( + 'type' => VatDataType::CALCULATED, + 'rate' => VatDataRate::RATE_10, + 'amount' => array( + 'value' => Random::int(1, 10000), + 'currency' => CurrencyCode::USD, + ), + )); + $paymentData[10] = $paymentDataB2bSberbank; + + $confirmations[0]->setLocale('en_US'); + $confirmations[1]->setEnforce(true); + $confirmations[1]->setReturnUrl(Random::str(10)); + foreach ($paymentData as $i => $paymentMethodData) { + $request = array( + 'accountId' => uniqid(), + 'gatewayId' => uniqid(), + 'amount' => mt_rand(0, 100000), + 'currency' => CurrencyCode::RUB, + 'referenceId' => uniqid(), + 'paymentMethodData' => $paymentData[$i], + 'confirmation' => Random::value($confirmations), + 'savePaymentMethod' => Random::bool(), + 'capture' => mt_rand(0, 1) ? true : false, + 'clientIp' => long2ip(mt_rand(0, pow(2, 32))), + 'metadata' => array('test' => uniqid()), + 'receipt' => array( + 'items' => $this->getReceiptItem($i + 1), + 'customer' => array( + 'email' => Random::str(10), + 'phone' => Random::str(12, '0123456789'), + ), + 'tax_system_code' => Random::int(1, 6), + ), + 'airline' => $airline, + ); + $result[] = array($request); + } + + return $result; + } + + /** + * @param $count + * @return array + * @throws \Exception + */ + private function getReceiptItem($count) + { + $result = array(); + for ($i = 0; $i < $count; $i++) { + $result[] = array( + 'description' => Random::str(10), + 'quantity' => (float)Random::float(1, 100), + 'amount' => array( + 'value' => (float)Random::int(1, 100), + 'currency' => CurrencyCode::RUB, + ), + 'vat_code' => Random::int(1, 6), + 'payment_subject' => PaymentSubject::COMMODITY, + 'payment_mode' => PaymentMode::PARTIAL_PREPAYMENT, + ); + } + + return $result; + } +} \ No newline at end of file diff --git a/tests/Request/Payments/CreatePaymentRequestTest.php b/tests/Request/Payments/CreatePaymentRequestTest.php new file mode 100644 index 00000000..03bfd045 --- /dev/null +++ b/tests/Request/Payments/CreatePaymentRequestTest.php @@ -0,0 +1,837 @@ +hasRecipient()); + self::assertNull($instance->getRecipient()); + self::assertNull($instance->recipient); + + $instance->setRecipient($options['recipient']); + if (empty($options['recipient'])) { + self::assertFalse($instance->hasRecipient()); + self::assertNull($instance->getRecipient()); + self::assertNull($instance->recipient); + } else { + self::assertTrue($instance->hasRecipient()); + self::assertSame($options['recipient'], $instance->getRecipient()); + self::assertSame($options['recipient'], $instance->recipient); + } + + $instance->setRecipient(null); + self::assertFalse($instance->hasRecipient()); + self::assertNull($instance->getRecipient()); + self::assertNull($instance->recipient); + + $instance->recipient = $options['recipient']; + if (empty($options['recipient'])) { + self::assertFalse($instance->hasRecipient()); + self::assertNull($instance->getRecipient()); + self::assertNull($instance->recipient); + } else { + self::assertTrue($instance->hasRecipient()); + self::assertSame($options['recipient'], $instance->getRecipient()); + self::assertSame($options['recipient'], $instance->recipient); + } + } + + /** + * @dataProvider invalidRecipientDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidRecipient($value) + { + $instance = new CreatePaymentRequest(); + $instance->setRecipient($value); + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testAmount($options) + { + $instance = new CreatePaymentRequest(); + + self::assertNull($instance->getAmount()); + self::assertNull($instance->amount); + + $instance->setAmount($options['amount']); + + self::assertSame($options['amount'], $instance->getAmount()); + self::assertSame($options['amount'], $instance->amount); + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testPaymentToken($options) + { + $instance = new CreatePaymentRequest(); + + self::assertFalse($instance->hasPaymentToken()); + self::assertNull($instance->getPaymentToken()); + self::assertNull($instance->paymentToken); + + $instance->setPaymentToken($options['paymentToken']); + if (empty($options['paymentToken'])) { + self::assertFalse($instance->hasPaymentToken()); + self::assertNull($instance->getPaymentToken()); + self::assertNull($instance->paymentToken); + self::assertNull($instance->payment_token); + } else { + self::assertTrue($instance->hasPaymentToken()); + self::assertSame($options['paymentToken'], $instance->getPaymentToken()); + self::assertSame($options['paymentToken'], $instance->paymentToken); + self::assertSame($options['paymentToken'], $instance->payment_token); + } + + $instance->setPaymentToken(null); + self::assertFalse($instance->hasPaymentToken()); + self::assertNull($instance->getPaymentToken()); + self::assertNull($instance->paymentToken); + + $instance->paymentToken = $options['paymentToken']; + if (empty($options['paymentToken'])) { + self::assertFalse($instance->hasPaymentToken()); + self::assertNull($instance->getPaymentToken()); + self::assertNull($instance->paymentToken); + self::assertNull($instance->payment_token); + } else { + self::assertTrue($instance->hasPaymentToken()); + self::assertSame($options['paymentToken'], $instance->getPaymentToken()); + self::assertSame($options['paymentToken'], $instance->paymentToken); + self::assertSame($options['paymentToken'], $instance->payment_token); + } + + $instance->paymentToken = null; + self::assertFalse($instance->hasPaymentToken()); + self::assertNull($instance->getPaymentToken()); + self::assertNull($instance->paymentToken); + + $instance->payment_token = $options['paymentToken']; + if (empty($options['paymentToken'])) { + self::assertFalse($instance->hasPaymentToken()); + self::assertNull($instance->getPaymentToken()); + self::assertNull($instance->paymentToken); + self::assertNull($instance->payment_token); + } else { + self::assertTrue($instance->hasPaymentToken()); + self::assertSame($options['paymentToken'], $instance->getPaymentToken()); + self::assertSame($options['paymentToken'], $instance->paymentToken); + self::assertSame($options['paymentToken'], $instance->payment_token); + } + } + + /** + * @dataProvider invalidPaymentTokenDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidPaymentToken($value) + { + $instance = new CreatePaymentRequest(); + $instance->setPaymentToken($value); + } + + /** + * @dataProvider invalidPaymentTokenDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidPaymentToken($value) + { + $instance = new CreatePaymentRequest(); + $instance->paymentToken = $value; + } + + /** + * @dataProvider invalidPaymentTokenDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidPayment_token($value) + { + $instance = new CreatePaymentRequest(); + $instance->payment_token = $value; + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testPaymentMethodId($options) + { + $instance = new CreatePaymentRequest(); + + self::assertFalse($instance->hasPaymentMethodId()); + self::assertNull($instance->getPaymentMethodId()); + self::assertNull($instance->paymentMethodId); + self::assertNull($instance->payment_method_id); + + $instance->setPaymentMethodId($options['paymentMethodId']); + if (empty($options['paymentMethodId'])) { + self::assertFalse($instance->hasPaymentMethodId()); + self::assertNull($instance->getPaymentMethodId()); + self::assertNull($instance->paymentMethodId); + self::assertNull($instance->payment_method_id); + } else { + self::assertTrue($instance->hasPaymentMethodId()); + self::assertSame($options['paymentMethodId'], $instance->getPaymentMethodId()); + self::assertSame($options['paymentMethodId'], $instance->paymentMethodId); + self::assertSame($options['paymentMethodId'], $instance->payment_method_id); + } + + $instance->setPaymentMethodId(null); + self::assertFalse($instance->hasPaymentMethodId()); + self::assertNull($instance->getPaymentMethodId()); + self::assertNull($instance->paymentMethodId); + + $instance->paymentMethodId = $options['paymentMethodId']; + if (empty($options['paymentMethodId'])) { + self::assertFalse($instance->hasPaymentMethodId()); + self::assertNull($instance->getPaymentMethodId()); + self::assertNull($instance->paymentMethodId); + self::assertNull($instance->payment_method_id); + } else { + self::assertTrue($instance->hasPaymentMethodId()); + self::assertSame($options['paymentMethodId'], $instance->getPaymentMethodId()); + self::assertSame($options['paymentMethodId'], $instance->paymentMethodId); + self::assertSame($options['paymentMethodId'], $instance->payment_method_id); + } + + $instance->setPaymentMethodId(null); + self::assertFalse($instance->hasPaymentMethodId()); + self::assertNull($instance->getPaymentMethodId()); + self::assertNull($instance->paymentMethodId); + + $instance->payment_method_id = $options['paymentMethodId']; + if (empty($options['paymentMethodId'])) { + self::assertFalse($instance->hasPaymentMethodId()); + self::assertNull($instance->getPaymentMethodId()); + self::assertNull($instance->paymentMethodId); + self::assertNull($instance->payment_method_id); + } else { + self::assertTrue($instance->hasPaymentMethodId()); + self::assertSame($options['paymentMethodId'], $instance->getPaymentMethodId()); + self::assertSame($options['paymentMethodId'], $instance->paymentMethodId); + self::assertSame($options['paymentMethodId'], $instance->payment_method_id); + } + } + + /** + * @dataProvider invalidPaymentMethodIdDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidPaymentMethodId($value) + { + $instance = new CreatePaymentRequest(); + $instance->setPaymentMethodId($value); + } + + /** + * @dataProvider invalidPaymentMethodIdDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidPaymentMethodId($value) + { + $instance = new CreatePaymentRequest(); + $instance->paymentMethodId = $value; + } + + /** + * @dataProvider invalidPaymentMethodIdDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidPayment_method_id($value) + { + $instance = new CreatePaymentRequest(); + $instance->payment_method_id = $value; + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testPaymentData($options) + { + $instance = new CreatePaymentRequest(); + + self::assertFalse($instance->hasPaymentMethodData()); + self::assertNull($instance->getPaymentMethodData()); + self::assertNull($instance->paymentMethodData); + + $instance->setPaymentMethodData($options['paymentMethodData']); + if (empty($options['paymentMethodData'])) { + self::assertFalse($instance->hasPaymentMethodData()); + self::assertNull($instance->getPaymentMethodData()); + self::assertNull($instance->paymentMethodData); + } else { + self::assertTrue($instance->hasPaymentMethodData()); + self::assertSame($options['paymentMethodData'], $instance->getPaymentMethodData()); + self::assertSame($options['paymentMethodData'], $instance->paymentMethodData); + } + + $instance->setPaymentMethodData(null); + self::assertFalse($instance->hasPaymentMethodData()); + self::assertNull($instance->getPaymentMethodData()); + self::assertNull($instance->paymentMethodData); + + $instance->paymentMethodData = $options['paymentMethodData']; + if (empty($options['paymentMethodData'])) { + self::assertFalse($instance->hasPaymentMethodData()); + self::assertNull($instance->getPaymentMethodData()); + self::assertNull($instance->paymentMethodData); + } else { + self::assertTrue($instance->hasPaymentMethodData()); + self::assertSame($options['paymentMethodData'], $instance->getPaymentMethodData()); + self::assertSame($options['paymentMethodData'], $instance->paymentMethodData); + } + } + + /** + * @dataProvider invalidPaymentDataDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidPaymentData($value) + { + $instance = new CreatePaymentRequest(); + $instance->setPaymentMethodData($value); + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testConfirmationAttributes($options) + { + $instance = new CreatePaymentRequest(); + + self::assertFalse($instance->hasConfirmation()); + self::assertNull($instance->getConfirmation()); + self::assertNull($instance->confirmation); + + $instance->setConfirmation($options['confirmation']); + if (empty($options['confirmation'])) { + self::assertFalse($instance->hasConfirmation()); + self::assertNull($instance->getConfirmation()); + self::assertNull($instance->confirmation); + } else { + self::assertTrue($instance->hasConfirmation()); + self::assertSame($options['confirmation'], $instance->getConfirmation()); + self::assertSame($options['confirmation'], $instance->confirmation); + } + + $instance->setConfirmation(null); + self::assertFalse($instance->hasConfirmation()); + self::assertNull($instance->getConfirmation()); + self::assertNull($instance->confirmation); + + $instance->confirmation = $options['confirmation']; + if (empty($options['confirmation'])) { + self::assertFalse($instance->hasConfirmation()); + self::assertNull($instance->getConfirmation()); + self::assertNull($instance->confirmation); + } else { + self::assertTrue($instance->hasConfirmation()); + self::assertSame($options['confirmation'], $instance->getConfirmation()); + self::assertSame($options['confirmation'], $instance->confirmation); + } + } + + /** + * @dataProvider invalidConfirmationAttributesDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidConfirmationAttributes($value) + { + $instance = new CreatePaymentRequest(); + $instance->setConfirmation($value); + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testCreateRecurring($options) + { + $instance = new CreatePaymentRequest(); + + self::assertFalse($instance->hasSavePaymentMethod()); + self::assertNull($instance->getSavePaymentMethod()); + self::assertNull($instance->savePaymentMethod); + + $instance->setSavePaymentMethod($options['savePaymentMethod']); + if ($options['savePaymentMethod'] === null || $options['savePaymentMethod'] === '') { + self::assertFalse($instance->hasSavePaymentMethod()); + self::assertNull($instance->getSavePaymentMethod()); + self::assertNull($instance->savePaymentMethod); + } else { + self::assertTrue($instance->hasSavePaymentMethod()); + self::assertSame($options['savePaymentMethod'], $instance->getSavePaymentMethod()); + self::assertSame($options['savePaymentMethod'], $instance->savePaymentMethod); + } + + $instance->setSavePaymentMethod(null); + self::assertFalse($instance->hasSavePaymentMethod()); + self::assertNull($instance->getSavePaymentMethod()); + self::assertNull($instance->savePaymentMethod); + + $instance->savePaymentMethod = $options['savePaymentMethod']; + if ($options['savePaymentMethod'] === null || $options['savePaymentMethod'] === '') { + self::assertFalse($instance->hasSavePaymentMethod()); + self::assertNull($instance->getSavePaymentMethod()); + self::assertNull($instance->savePaymentMethod); + } else { + self::assertTrue($instance->hasSavePaymentMethod()); + self::assertSame($options['savePaymentMethod'], $instance->getSavePaymentMethod()); + self::assertSame($options['savePaymentMethod'], $instance->savePaymentMethod); + } + } + + /** + * @dataProvider invalidBooleanDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidCreateRecurring($value) + { + $instance = new CreatePaymentRequest(); + $instance->setSavePaymentMethod($value); + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testCapture($options) + { + $instance = new CreatePaymentRequest(); + + self::assertFalse($instance->hasCapture()); + self::assertNull($instance->getCapture()); + self::assertNull($instance->capture); + + $instance->setCapture($options['capture']); + if ($options['capture'] === null || $options['capture'] === '') { + self::assertFalse($instance->hasCapture()); + self::assertNull($instance->getCapture()); + self::assertNull($instance->capture); + } else { + self::assertTrue($instance->hasCapture()); + self::assertSame($options['capture'], $instance->getCapture()); + self::assertSame($options['capture'], $instance->capture); + } + + $instance->setCapture(null); + self::assertFalse($instance->hasCapture()); + self::assertNull($instance->getCapture()); + self::assertNull($instance->capture); + + $instance->capture = $options['capture']; + if ($options['capture'] === null || $options['capture'] === '') { + self::assertFalse($instance->hasCapture()); + self::assertNull($instance->getCapture()); + self::assertNull($instance->capture); + } else { + self::assertTrue($instance->hasCapture()); + self::assertSame($options['capture'], $instance->getCapture()); + self::assertSame($options['capture'], $instance->capture); + } + } + + /** + * @dataProvider invalidBooleanDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidCapture($value) + { + $instance = new CreatePaymentRequest(); + $instance->setCapture($value); + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testClientIp($options) + { + $instance = new CreatePaymentRequest(); + + self::assertFalse($instance->hasClientIp()); + self::assertNull($instance->getClientIp()); + self::assertNull($instance->clientIp); + + $instance->setClientIp($options['clientIp']); + if (empty($options['clientIp'])) { + self::assertFalse($instance->hasClientIp()); + self::assertNull($instance->getClientIp()); + self::assertNull($instance->clientIp); + } else { + self::assertTrue($instance->hasClientIp()); + self::assertSame($options['clientIp'], $instance->getClientIp()); + self::assertSame($options['clientIp'], $instance->clientIp); + } + + $instance->setClientIp(null); + self::assertFalse($instance->hasClientIp()); + self::assertNull($instance->getClientIp()); + self::assertNull($instance->clientIp); + + $instance->clientIp = $options['clientIp']; + if (empty($options['clientIp'])) { + self::assertFalse($instance->hasClientIp()); + self::assertNull($instance->getClientIp()); + self::assertNull($instance->clientIp); + } else { + self::assertTrue($instance->hasClientIp()); + self::assertSame($options['clientIp'], $instance->getClientIp()); + self::assertSame($options['clientIp'], $instance->clientIp); + } + } + + /** + * @dataProvider invalidClientIpDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidClientIp($value) + { + $instance = new CreatePaymentRequest(); + $instance->setClientIp($value); + } + + public function invalidClientIpDataProvider() + { + return array( + array(array()), + array(new \stdClass()), + array(true), + array(false), + ); + } + + /** + * @dataProvider validTransfers + * @param $value + */ + public function testSetTransfer($value) + { + $instance = new CreatePaymentRequest(); + $instance->setTransfers($value); + if (is_array($value)) { + $value = array(new Transfer($value[0])); + } + self::assertEquals($value, $instance->getTransfers()); + } + + /** + * @return array[] + * @throws \Exception + */ + public function validTransfers() + { + $transfers = array(); + for($i = 0; $i < 10; $i++) { + $transfers[$i][] = array( + 'account_id' => (string)Random::int(11111111, 99999999), + 'amount' => array( + 'value' => sprintf('%.2f', round(Random::float(0.1, 99.99), 2)), + 'currency' => Random::value(CurrencyCode::getValidValues()) + ), + 'platform_fee_amount' => array( + 'value' => sprintf('%.2f', round(Random::float(0.1, 99.99), 2)), + 'currency' => Random::value(CurrencyCode::getValidValues()) + ) + ); + } + $transfers[$i][] = array(new Transfer($transfers[0])); + + return array($transfers); + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testMetadata($options) + { + $instance = new CreatePaymentRequest(); + + self::assertFalse($instance->hasMetadata()); + self::assertNull($instance->getMetadata()); + self::assertNull($instance->metadata); + + $expected = $options['metadata']; + if ($expected instanceof Metadata) { + $expected = $expected->toArray(); + } + + $instance->setMetadata($options['metadata']); + if (empty($options['metadata'])) { + self::assertFalse($instance->hasMetadata()); + self::assertNull($instance->getMetadata()); + self::assertNull($instance->metadata); + } else { + self::assertTrue($instance->hasMetadata()); + self::assertSame($expected, $instance->getMetadata()->toArray()); + self::assertSame($expected, $instance->metadata->toArray()); + } + + $instance->setMetadata(null); + self::assertFalse($instance->hasMetadata()); + self::assertNull($instance->getMetadata()); + self::assertNull($instance->metadata); + + $instance->metadata = $options['metadata']; + if (empty($options['metadata'])) { + self::assertFalse($instance->hasMetadata()); + self::assertNull($instance->getMetadata()); + self::assertNull($instance->metadata); + } else { + self::assertTrue($instance->hasMetadata()); + self::assertSame($expected, $instance->getMetadata()->toArray()); + self::assertSame($expected, $instance->metadata->toArray()); + } + } + + public function testValidate() + { + $instance = new CreatePaymentRequest(); + + self::assertFalse($instance->validate()); + + $amount = new MonetaryAmount(); + $instance->setAmount($amount); + self::assertFalse($instance->validate()); + + $instance->setAmount(new MonetaryAmount(10)); + self::assertTrue($instance->validate()); + + $instance->setPaymentToken(Random::str(10)); + self::assertTrue($instance->validate()); + $instance->setPaymentMethodId(Random::str(10)); + self::assertFalse($instance->validate()); + $instance->setPaymentMethodId(null); + self::assertTrue($instance->validate()); + $instance->setPaymentMethodData(new PaymentDataQiwi()); + self::assertFalse($instance->validate()); + $instance->setPaymentToken(null); + self::assertTrue($instance->validate()); + $instance->setPaymentMethodId(Random::str(10)); + self::assertFalse($instance->validate()); + $instance->setPaymentMethodId(null); + self::assertTrue($instance->validate()); + + $receipt = new Receipt(); + $instance->setReceipt($receipt); + $item = new ReceiptItem(); + $item->setPrice(new MonetaryAmount(10)); + $item->setDescription('test'); + $receipt->addItem($item); + self::assertFalse($instance->validate()); + $receipt->getCustomer()->setPhone('123123'); + self::assertTrue($instance->validate()); + $item->setVatCode(3); + self::assertTrue($instance->validate()); + $receipt->setTaxSystemCode(4); + self::assertTrue($instance->validate()); + + self::assertNotNull($instance->getReceipt()); + $instance->removeReceipt(); + self::assertTrue($instance->validate()); + self::assertNull($instance->getReceipt()); + + $instance->setAmount(new MonetaryAmount()); + self::assertFalse($instance->validate()); + } + + public function testBuilder() + { + $builder = CreatePaymentRequest::builder(); + self::assertTrue($builder instanceof CreatePaymentRequestBuilder); + } + + /** + * @dataProvider invalidMetadataDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidMetadata($value) + { + $instance = new CreatePaymentRequest(); + $instance->setMetadata($value); + } + + public function validDataProvider() + { + $metadata = new Metadata(); + $metadata->test = 'test'; + $result = array( + array( + array( + 'recipient' => null, + 'amount' => new MonetaryAmount(Random::int(1, 1000000)), + 'referenceId' => null, + 'paymentToken' => null, + 'paymentMethodId' => null, + 'paymentMethodData' => null, + 'confirmation' => null, + 'savePaymentMethod' => null, + 'capture' => null, + 'clientIp' => null, + 'metadata' => null, + ), + ), + array( + array( + 'recipient' => null, + 'amount' => new MonetaryAmount(Random::int(1, 1000000)), + 'referenceId' => '', + 'paymentToken' => '', + 'paymentMethodId' => '', + 'paymentMethodData' => '', + 'confirmation' => '', + 'savePaymentMethod' => '', + 'capture' => '', + 'clientIp' => '', + 'metadata' => array(), + ), + ), + ); + for ($i = 0; $i < 10; $i++) { + $request = array( + 'recipient' => new Recipient(), + 'amount' => new MonetaryAmount(Random::int(1, 1000000)), + 'referenceId' => uniqid(), + 'paymentToken' => uniqid(), + 'paymentMethodId' => uniqid(), + 'paymentMethodData' => new PaymentDataQiwi(), + 'confirmation' => new ConfirmationAttributesExternal(), + 'savePaymentMethod' => mt_rand(0, 1) ? true : false, + 'capture' => mt_rand(0, 1) ? true : false, + 'clientIp' => long2ip(mt_rand(0, pow(2, 32))), + 'metadata' => $i == 0 ? $metadata : array('test' => 'test'), + ); + $result[] = array($request); + } + return $result; + } + + public function invalidRecipientDataProvider() + { + return array( + array(false), + array(true), + array(1), + array(Random::str(10)), + array(new \stdClass()), + ); + } + + public function invalidReferenceIdDataProvider() + { + return array( + array(false), + array(true), + array(new \stdClass()), + array(array()), + array(Random::str(32)), + ); + } + + public function invalidPaymentTokenDataProvider() + { + return array( + array(false), + array(true), + array(new \stdClass()), + array(array()), + array(Random::str(CreatePaymentRequest::MAX_LENGTH_PAYMENT_TOKEN + 1)), + ); + } + + public function invalidPaymentMethodIdDataProvider() + { + return array( + array(false), + array(true), + array(new \stdClass()), + array(array()), + ); + } + + public function invalidPaymentDataDataProvider() + { + return array( + array(array()), + array(false), + array(true), + array(1), + array(Random::str(10)), + array(new \stdClass()), + ); + } + + public function invalidConfirmationAttributesDataProvider() + { + return array( + array(array()), + array(false), + array(true), + array(1), + array(Random::str(10)), + array(new \stdClass()), + ); + } + + public function invalidMetadataDataProvider() + { + return array( + array(false), + array(true), + array(1), + array(Random::str(10)), + ); + } + + public function invalidBooleanDataProvider() + { + return array( + array(array()), + array(new \stdClass()), + array('test'), + ); + } +} \ No newline at end of file diff --git a/tests/Request/Payments/CreatePaymentResponseTest.php b/tests/Request/Payments/CreatePaymentResponseTest.php new file mode 100644 index 00000000..957d0677 --- /dev/null +++ b/tests/Request/Payments/CreatePaymentResponseTest.php @@ -0,0 +1,13 @@ +setAmount($options['amount']); + $instance = $builder->build(); + + if (empty($options['amount'])) { + self::assertNull($instance->getAmount()); + } else { + self::assertNotNull($instance->getAmount()); + self::assertEquals($options['amount'], $instance->getAmount()->getValue()); + } + } + + /** + * @dataProvider validAmountDataProvider + * + * @param AmountInterface $amount + */ + public function testSetAmount($amount) + { + $builder = new CreateCaptureRequestBuilder(); + + $builder->setAmount($amount); + $instance = $builder->build(); + + self::assertNotNull($instance->getAmount()); + self::assertEquals($amount->getValue(), $instance->getAmount()->getValue()); + self::assertEquals($amount->getCurrency(), $instance->getAmount()->getCurrency()); + + $builder->setAmount(array( + 'value' => $amount->getValue(), + 'currency' => $amount->getCurrency(), + )); + $instance = $builder->build(); + + self::assertNotNull($instance->getAmount()); + self::assertEquals($amount->getValue(), $instance->getAmount()->getValue()); + self::assertEquals($amount->getCurrency(), $instance->getAmount()->getCurrency()); + } + + /** + * @dataProvider invalidAmountDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidAmount($value) + { + $builder = new CreateCaptureRequestBuilder(); + $builder->setAmount($value); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + */ + public function testSetAmountCurrency($options) + { + $builder = new CreateCaptureRequestBuilder(); + + $builder->setCurrency($options['currency']); + $instance = $builder->build(array('amount' => mt_rand(1, 100))); + + self::assertNotNull($instance->getAmount()); + self::assertEquals($options['currency'], $instance->getAmount()->getCurrency()); + } + + /** + * @dataProvider invalidCurrencyDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidCurrency($value) + { + $builder = new CreateCaptureRequestBuilder(); + $builder->setCurrency($value); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + */ + public function testSetReceiptItems($options) + { + $builder = new CreateCaptureRequestBuilder(); + + $builder->setReceiptItems($options['receiptItems']); + $builder->setReceiptEmail($options['receiptEmail']); + $instance = $builder->build(); + + if (empty($options['receiptItems'])) { + self::assertNull($instance->getReceipt()); + } else { + self::assertNotNull($instance->getReceipt()); + self::assertEquals(count($options['receiptItems']), count($instance->getReceipt()->getItems())); + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + */ + public function testAddReceiptItems($options) + { + $builder = new CreateCaptureRequestBuilder(); + + foreach ($options['receiptItems'] as $item) { + if ($item instanceof ReceiptItem) { + $builder->addReceiptItem( + $item->getDescription(), $item->getPrice()->getValue(), $item->getQuantity(), $item->getVatCode() + ); + } else { + $builder->addReceiptItem($item['title'], $item['price'], $item['quantity'], $item['vatCode']); + } + } + $builder->setReceiptEmail($options['receiptEmail']); + $instance = $builder->build(); + + if (empty($options['receiptItems'])) { + self::assertNull($instance->getReceipt()); + } else { + self::assertNotNull($instance->getReceipt()); + self::assertEquals(count($options['receiptItems']), count($instance->getReceipt()->getItems())); + foreach ($instance->getReceipt()->getItems() as $item) { + self::assertFalse($item->isShipping()); + } + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + */ + public function testAddReceiptShipping($options) + { + $builder = new CreateCaptureRequestBuilder(); + + foreach ($options['receiptItems'] as $item) { + if ($item instanceof ReceiptItem) { + $builder->addReceiptShipping( + $item->getDescription(), $item->getPrice()->getValue(), $item->getVatCode() + ); + } else { + $builder->addReceiptShipping($item['title'], $item['price'], $item['vatCode']); + } + } + $builder->setReceiptEmail($options['receiptEmail']); + $instance = $builder->build(); + + if (empty($options['receiptItems'])) { + self::assertNull($instance->getReceipt()); + } else { + self::assertNotNull($instance->getReceipt()); + self::assertEquals(count($options['receiptItems']), count($instance->getReceipt()->getItems())); + foreach ($instance->getReceipt()->getItems() as $item) { + self::assertTrue($item->isShipping()); + } + } + } + + /** + * @dataProvider invalidItemsDataProvider + * @expectedException \InvalidArgumentException + * + * @param $items + */ + public function testSetInvalidReceiptItems($items) + { + $builder = new CreateCaptureRequestBuilder(); + $builder->setReceiptItems($items); + } + + public function invalidItemsDataProvider() + { + return array( + array( + array( + array( + 'price' => 1, + 'quantity' => 1.4, + 'vatCode' => 3, + ), + ), + ), + array( + array( + array( + 'title' => 'test', + 'quantity' => 1.4, + 'vatCode' => 3, + ), + ), + ), + array( + array( + array( + 'description' => 'test', + 'quantity' => 1.4, + 'vatCode' => 3, + ), + ), + ), + array( + array( + array( + 'title' => 'test', + 'price' => 123, + 'quantity' => 1.4, + 'vatCode' => 7, + ), + ), + ), + array( + array( + array( + 'description' => 'test', + 'price' => 123, + 'quantity' => -1.4, + ), + ), + ), + ); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + */ + public function testSetReceiptEmail($options) + { + $builder = new CreateCaptureRequestBuilder(); + + $builder->setReceiptItems($options['receiptItems']); + $builder->setReceiptEmail($options['receiptEmail']); + $instance = $builder->build(); + + if (empty($options['receiptItems'])) { + self::assertNull($instance->getReceipt()); + } else { + self::assertNotNull($instance->getReceipt()); + self::assertEquals($options['receiptEmail'], $instance->getReceipt()->getCustomer()->getEmail()); + } + } + + /** + * @dataProvider invalidEmailDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidEmail($value) + { + $builder = new CreateCaptureRequestBuilder(); + $builder->setReceiptEmail($value); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + */ + public function testSetReceiptPhone($options) + { + $builder = new CreateCaptureRequestBuilder(); + + $builder->setReceiptItems($options['receiptItems']); + $builder->setReceiptEmail($options['receiptEmail']); + $builder->setReceiptPhone($options['receiptPhone']); + $instance = $builder->build(); + + if (empty($options['receiptItems'])) { + self::assertNull($instance->getReceipt()); + } else { + self::assertNotNull($instance->getReceipt()); + self::assertEquals($options['receiptPhone'], $instance->getReceipt()->getCustomer()->getPhone()); + } + } + + /** + * @dataProvider invalidPhoneDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidPhone($value) + { + $builder = new CreateCaptureRequestBuilder(); + $builder->setReceiptPhone($value); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + */ + public function testSetReceiptTaxSystemCode($options) + { + $builder = new CreateCaptureRequestBuilder(); + + $builder->setReceiptItems($options['receiptItems']); + $builder->setReceiptEmail($options['receiptEmail']); + $builder->setTaxSystemCode($options['taxSystemCode']); + $instance = $builder->build(); + + if (empty($options['receiptItems'])) { + self::assertNull($instance->getReceipt()); + } else { + self::assertNotNull($instance->getReceipt()); + self::assertEquals($options['taxSystemCode'], $instance->getReceipt()->getTaxSystemCode()); + } + } + + /** + * @dataProvider invalidVatIdDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidTaxSystemId($value) + { + $builder = new CreateCaptureRequestBuilder(); + $builder->setTaxSystemCode($value); + } + + public function testSetReceipt() + { + $receipt = array( + 'tax_system_code' => Random::int(1, 6), + 'customer' => array( + 'email' => Random::str(10), + 'phone' => Random::str(4, 15, '0123456789'), + ), + 'items' => array( + array( + 'description' => 'test', + 'quantity' => 123, + 'amount' => array( + 'value' => 321, + 'currency' => 'USD', + ), + 'vat_code' => Random::int(1, 6), + 'payment_subject' => PaymentSubject::COMMODITY, + 'payment_mode' => PaymentMode::PARTIAL_PREPAYMENT, + ), + ), + ); + + $builder = new CreateCaptureRequestBuilder(); + $builder->setReceipt($receipt); + $instance = $builder->build(); + + self::assertEquals($receipt['tax_system_code'], $instance->getReceipt()->getTaxSystemCode()); + self::assertEquals($receipt['customer']['email'], $instance->getReceipt()->getCustomer()->getEmail()); + self::assertEquals($receipt['customer']['phone'], $instance->getReceipt()->getCustomer()->getPhone()); + self::assertEquals(1, count($instance->getReceipt()->getItems())); + + $receipt = $instance->getReceipt(); + + $builder = new CreateCaptureRequestBuilder(); + $builder->setReceipt($instance->getReceipt()); + $instance = $builder->build(); + + self::assertEquals($receipt['tax_system_code'], $instance->getReceipt()->getTaxSystemCode()); + self::assertEquals($receipt['customer']['email'], $instance->getReceipt()->getCustomer()->getEmail()); + self::assertEquals($receipt['customer']['phone'], $instance->getReceipt()->getCustomer()->getPhone()); + self::assertEquals(1, count($instance->getReceipt()->getItems())); + } + + /** + * @dataProvider invalidReceiptDataProvider + * @expectedException \InvalidArgumentException + * + * @param mixed $value + */ + public function testSetInvalidReceipt($value) + { + $builder = new CreateCaptureRequestBuilder(); + $builder->setReceipt($value); + } + + public function invalidReceiptDataProvider() + { + return array( + array(null), + array(true), + array(false), + array(1), + array(1.1), + array('test'), + array(new \stdClass()), + ); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + */ + public function testBuild($options) + { + $builder = new CreateCaptureRequestBuilder(); + $instance = $builder->build($options); + if (!empty($options['amount'])) { + self::assertNotNull($instance->getAmount()); + self::assertEquals($options['amount'], $instance->getAmount()->getValue()); + self::assertEquals($options['currency'], $instance->getAmount()->getCurrency()); + } else { + self::assertNull($instance->getAmount()); + } + } + + public function validDataProvider() + { + $receiptItem = new ReceiptItem(); + $receiptItem->setPrice(new MonetaryAmount(1)); + $receiptItem->setQuantity(1); + $receiptItem->setDescription('test'); + $receiptItem->setVatCode(3); + + $result = array( + array( + array( + 'amount' => null, + 'currency' => Random::value(CurrencyCode::getValidValues()), + 'receiptItems' => array( + array( + 'title' => 'test', + 'quantity' => mt_rand(1, 100), + 'price' => mt_rand(1, 100), + 'vatCode' => mt_rand(1, 6), + ), + $receiptItem, + ), + 'receiptEmail' => Random::str(32), + 'receiptPhone' => null, + 'taxSystemCode' => null, + ), + ), + ); + for ($i = 0; $i < 10; $i++) { + $request = array( + 'receiptItems' => array(), + 'amount' => Random::int(1, 1000000), + 'currency' => Random::value(CurrencyCode::getValidValues()), + 'receiptEmail' => null, + 'receiptPhone' => Random::str(10, '0123456789'), + 'taxSystemCode' => Random::int(1, 6), + ); + $result[] = array($request); + } + + return $result; + } + + public function validAmountDataProvider() + { + return array( + array(new MonetaryAmount(Random::int(1, 1000000))), + array(new MonetaryAmount(Random::int(1, 1000000)), Random::value(CurrencyCode::getValidValues())), + ); + } + + public function invalidAmountDataProvider() + { + return array( + array(-1), + array(Random::str(10)), + array(new \stdClass()), + array(true), + array(false), + ); + } + + public function invalidCurrencyDataProvider() + { + return array( + array(array()), + array(null), + array(''), + array(-1), + array(new \stdClass()), + array(Random::str(10)), + array(true), + array(false), + ); + } + + public function invalidEmailDataProvider() + { + return array( + array(array()), + array(true), + array(false), + array(new \stdClass()), + ); + } + + public function invalidPhoneDataProvider() + { + return array( + array(new \stdClass()), + array(array()), + array(true), + array(false), + ); + } + + public function invalidVatIdDataProvider() + { + return array( + array(array()), + array(true), + array(false), + array(new \stdClass()), + array(0), + array(7), + array(Random::int(-100, -1)), + array(Random::int(7, 100)), + ); + } +} \ No newline at end of file diff --git a/tests/Request/Payments/Payment/CreateCaptureRequestSerializerTest.php b/tests/Request/Payments/Payment/CreateCaptureRequestSerializerTest.php new file mode 100644 index 00000000..86d21d83 --- /dev/null +++ b/tests/Request/Payments/Payment/CreateCaptureRequestSerializerTest.php @@ -0,0 +1,138 @@ +serialize(CreateCaptureRequest::builder()->build($options)); + + $expected = array(); + if (isset($options['amount'])) { + $expected = array( + 'amount' => $options['amount'], + ); + } + if (!empty($options['receiptItems'])) { + foreach ($options['receiptItems'] as $item) { + $itemArray = array( + 'description' => $item['title'], + 'quantity' => $item['quantity'], + 'amount' => array( + 'value' => $item['price'], + 'currency' => isset($options['currency']) ? $options['currency'] : CurrencyCode::RUB, + ), + 'vat_code' => $item['vatCode'], + ); + + if (!empty($item['payment_subject'])) { + $itemArray['payment_subject'] = $options['payment_subject']; + } + if (!empty($item['payment_mode'])) { + $itemArray['payment_mode'] = $options['payment_mode']; + } + $expected['receipt']['items'][] = $itemArray; + } + if (!empty($options['receiptEmail'])) { + $expected['receipt']['customer']['email'] = $options['receiptEmail']; + } + if (!empty($options['receiptEmail'])) { + $expected['receipt']['customer']['email'] = $options['receiptEmail']; + } + if (!empty($options['taxSystemCode'])) { + $expected['receipt']['tax_system_code'] = $options['taxSystemCode']; + } + } elseif (!empty($options['receipt'])) { + $expected['receipt'] = $options['receipt']; + if (!empty($expected['receipt']['phone'])) { + $expected['receipt']['customer']['phone'] = $expected['receipt']['phone']; + unset($expected['receipt']['phone']); + } + if (!empty($expected['receipt']['email'])) { + $expected['receipt']['customer']['email'] = $expected['receipt']['email']; + unset($expected['receipt']['email']); + } + } + self::assertEquals($expected, $data); + } + + public function validDataProvider() + { + $currencies = CurrencyCode::getValidValues(); + + $result = array( + array( + array() + ), + array( + array( + 'receiptItems' => array( + array( + 'title' => Random::str(10), + 'quantity' => round(Random::float(0.01, 10.00), 2), + 'price' => round(Random::float(10.00, 100.00), 2), + 'vatCode' => Random::int(1, 6), + ), + ), + 'receiptEmail' => Random::str(10), + 'taxSystemCode' => Random::int(1, 6), + ) + ), + array( + array( + 'receipt' => array( + 'items' => array( + array( + 'description' => Random::str(10), + 'quantity' => round(Random::float(0.01, 10.00), 2), + 'amount' => array( + 'value' => round(Random::float(10.00, 100.00), 2), + 'currency' => $currencies[mt_rand(0, count($currencies) - 1)], + ), + 'vat_code' => Random::int(1, 6), + ), + array( + 'description' => Random::str(10), + 'amount' => array( + 'value' => round(Random::float(10.00, 100.00), 2), + 'currency' => $currencies[mt_rand(0, count($currencies) - 1)], + ), + 'quantity' => round(Random::float(0.01, 10.00), 2), + 'vat_code' => Random::int(1, 6), + ), + ), + 'customer' => array( + 'phone' => Random::str(12, '0123456789'), + 'email' => Random::str(10 ), + ), + 'tax_system_code' => Random::int(1, 6), + ), + ), + ), + ); + for ($i = 0; $i < 10; $i++) { + $request = array( + 'amount' => array( + 'value' => (float)mt_rand(1, 1000000), + 'currency' => $currencies[mt_rand(0, count($currencies) - 1)], + ), + ); + $result[] = array($request); + } + return $result; + } +} \ No newline at end of file diff --git a/tests/Request/Payments/Payment/CreateCaptureRequestTest.php b/tests/Request/Payments/Payment/CreateCaptureRequestTest.php new file mode 100644 index 00000000..2f58ec7b --- /dev/null +++ b/tests/Request/Payments/Payment/CreateCaptureRequestTest.php @@ -0,0 +1,94 @@ +hasAmount()); + self::assertNull($instance->getAmount()); + self::assertNull($instance->amount); + + $instance->setAmount($options['amount']); + self::assertTrue($instance->hasAmount()); + self::assertSame($options['amount'], $instance->getAmount()); + self::assertSame($options['amount'], $instance->amount); + + $instance = new CreateCaptureRequest(); + self::assertFalse($instance->hasAmount()); + self::assertNull($instance->getAmount()); + self::assertNull($instance->amount); + + $instance->amount = $options['amount']; + self::assertTrue($instance->hasAmount()); + self::assertSame($options['amount'], $instance->getAmount()); + self::assertSame($options['amount'], $instance->amount); + } + + public function testValidate() + { + $instance = new CreateCaptureRequest(); + + self::assertTrue($instance->validate()); + $amount = new MonetaryAmount(); + $instance->setAmount($amount); + self::assertFalse($instance->validate()); + $amount->setValue(1); + self::assertTrue($instance->validate()); + + $receipt = new Receipt(); + $instance->setReceipt($receipt); + $item = new ReceiptItem(); + $item->setPrice(new MonetaryAmount(10)); + $item->setDescription('test'); + $receipt->addItem($item); + self::assertFalse($instance->validate()); + $receipt->getCustomer()->setPhone('123123'); + self::assertTrue($instance->validate()); + $item->setVatCode(3); + self::assertTrue($instance->validate()); + $receipt->setTaxSystemCode(4); + self::assertTrue($instance->validate()); + + self::assertNotNull($instance->getReceipt()); + $instance->removeReceipt(); + self::assertTrue($instance->validate()); + self::assertNull($instance->getReceipt()); + + $instance->setAmount(new MonetaryAmount()); + self::assertFalse($instance->validate()); + } + + public function testBuilder() + { + $builder = CreateCaptureRequest::builder(); + self::assertTrue($builder instanceof CreateCaptureRequestBuilder); + } + + public function validDataProvider() + { + $result = array(); + $currencies = CurrencyCode::getValidValues(); + for ($i = 0; $i < 10; $i++) { + $request = array( + 'amount' => new MonetaryAmount(mt_rand(1, 1000000), $currencies[mt_rand(0, count($currencies) - 1)]) + ); + $result[] = array($request); + } + return $result; + } +} \ No newline at end of file diff --git a/tests/Request/Payments/Payment/CreateCaptureResponseTest.php b/tests/Request/Payments/Payment/CreateCaptureResponseTest.php new file mode 100644 index 00000000..020e91cc --- /dev/null +++ b/tests/Request/Payments/Payment/CreateCaptureResponseTest.php @@ -0,0 +1,14 @@ +build(); + self::assertNull($instance->getCursor()); + + $builder->setCursor($options['cursor']); + $instance = $builder->build(); + if (empty($options['cursor'])) { + self::assertNull($instance->getCursor()); + } else { + self::assertEquals($options['cursor'], $instance->getCursor()); + } + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSetCreatedAtGte($options) + { + $builder = new PaymentsRequestBuilder(); + + $instance = $builder->build(); + self::assertNull($instance->getCreatedAtGte()); + + $builder->setCreatedAtGte($options['createdAtGte']); + $instance = $builder->build(); + if (empty($options['createdAtGte'])) { + self::assertNull($instance->getCreatedAtGte()); + } else { + self::assertEquals($options['createdAtGte'], $instance->getCreatedAtGte()->format(DATE_ATOM)); + } + } + + /** + * @dataProvider validDataProvider + * @param $options + * @throws \Exception + */ + public function testSetCreatedGt($options) + { + $builder = new PaymentsRequestBuilder(); + + $instance = $builder->build(); + self::assertNull($instance->getCreatedAtGt()); + + $builder->setCreatedAtGt($options['createdAtGt']); + $instance = $builder->build(); + if (empty($options['createdAtGt'])) { + self::assertNull($instance->getCreatedAtGt()); + } else { + self::assertEquals($options['createdAtGt'], $instance->getCreatedAtGt()->format(DATE_ATOM)); + } + } + + /** + * @dataProvider validDataProvider + * @param $options + * @throws \Exception + */ + public function testSetCreatedLte($options) + { + $builder = new PaymentsRequestBuilder(); + + $instance = $builder->build(); + self::assertNull($instance->getCreatedAtLte()); + + $builder->setCreatedAtLte($options['createdAtLte']); + $instance = $builder->build(); + if (empty($options['createdAtLte'])) { + self::assertNull($instance->getCreatedAtLte()); + } else { + self::assertEquals($options['createdAtLte'], $instance->getCreatedAtLte()->format(DATE_ATOM)); + } + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSetCreatedLt($options) + { + $builder = new PaymentsRequestBuilder(); + + $instance = $builder->build(); + self::assertNull($instance->getCreatedAtLt()); + + $builder->setCreatedAtLt($options['createdAtLt']); + $instance = $builder->build(); + if (empty($options['createdAtLt'])) { + self::assertNull($instance->getCreatedAtLt()); + } else { + self::assertEquals($options['createdAtLt'], $instance->getCreatedAtLt()->format(DATE_ATOM)); + } + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSetCapturedAtGte($options) + { + $builder = new PaymentsRequestBuilder(); + + $instance = $builder->build(); + self::assertNull($instance->getCapturedAtGte()); + + $builder->setCapturedAtGte($options['capturedAtGte']); + $instance = $builder->build(); + if (empty($options['capturedAtGte'])) { + self::assertNull($instance->getCapturedAtGte()); + } else { + self::assertEquals($options['capturedAtGte'], $instance->getCapturedAtGte()->format(DATE_ATOM)); + } + } + + /** + * @dataProvider validDataProvider + * @param $options + * @throws \Exception + */ + public function testSetCapturedGt($options) + { + $builder = new PaymentsRequestBuilder(); + + $instance = $builder->build(); + self::assertNull($instance->getCapturedAtGt()); + + $builder->setCapturedAtGt($options['capturedAtGt']); + $instance = $builder->build(); + if (empty($options['capturedAtGt'])) { + self::assertNull($instance->getCapturedAtGt()); + } else { + self::assertEquals($options['capturedAtGt'], $instance->getCapturedAtGt()->format(DATE_ATOM)); + } + } + + /** + * @dataProvider validDataProvider + * @param $options + * @throws \Exception + */ + public function testSetCapturedLte($options) + { + $builder = new PaymentsRequestBuilder(); + + $instance = $builder->build(); + self::assertNull($instance->getCapturedAtLte()); + + $builder->setCapturedAtLte($options['capturedAtLte']); + $instance = $builder->build(); + if (empty($options['capturedAtLte'])) { + self::assertNull($instance->getCapturedAtLte()); + } else { + self::assertEquals($options['capturedAtLte'], $instance->getCapturedAtLte()->format(DATE_ATOM)); + } + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSetCapturedLt($options) + { + $builder = new PaymentsRequestBuilder(); + + $instance = $builder->build(); + self::assertNull($instance->getCapturedAtLt()); + + $builder->setCapturedAtLt($options['capturedAtLt']); + $instance = $builder->build(); + if (empty($options['capturedAtLt'])) { + self::assertNull($instance->getCapturedAtLt()); + } else { + self::assertEquals($options['capturedAtLt'], $instance->getCapturedAtLt()->format(DATE_ATOM)); + } + } + + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSetPaymentMethod($options) + { + $builder = new PaymentsRequestBuilder(); + + $instance = $builder->build(); + self::assertNull($instance->getPaymentMethod()); + + $builder->setPaymentMethod($options['paymentMethod']); + $instance = $builder->build(); + if (empty($options['paymentMethod'])) { + self::assertNull($instance->getPaymentMethod()); + } else { + self::assertEquals($options['paymentMethod'], $instance->getPaymentMethod()); + } + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSetLimit($options) + { + $builder = new PaymentsRequestBuilder(); + + $instance = $builder->build(); + self::assertNull($instance->getLimit()); + + $builder->setLimit($options['limit']); + $instance = $builder->build(); + if (is_null($options['limit'])) { + self::assertNull($instance->getLimit()); + } else { + self::assertEquals($options['limit'], $instance->getLimit()); + } + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSetStatus($options) + { + $builder = new PaymentsRequestBuilder(); + + $instance = $builder->build(); + self::assertNull($instance->getStatus()); + + $builder->setStatus($options['status']); + $instance = $builder->build(); + if (empty($options['status'])) { + self::assertNull($instance->getStatus()); + } else { + self::assertEquals($options['status'], $instance->getStatus()); + } + } + + public function validDataProvider() + { + $result = array( + array( + array( + 'createdAtGte' => null, + 'createdAtGt' => null, + 'createdAtLte' => null, + 'createdAtLt' => null, + 'capturedAtGte' => null, + 'capturedAtGt' => null, + 'capturedAtLte' => null, + 'capturedAtLt' => null, + 'paymentMethod' => null, + 'status' => null, + 'limit' => null, + 'cursor' => null, + ), + ), + array( + array( + 'createdAtGte' => '', + 'createdAtGt' => '', + 'createdAtLte' => '', + 'createdAtLt' => '', + 'capturedAtGte' => '', + 'capturedAtGt' => '', + 'capturedAtLte' => '', + 'capturedAtLt' => '', + 'paymentMethod' => '', + 'status' => '', + 'limit' => 0, + 'cursor' => '', + ), + ), + ); + $statuses = PaymentStatus::getValidValues(); + $methods = PaymentMethodType::getValidValues(); + for ($i = 0; $i < 10; $i++) { + $request = array( + 'createdAtGte' => date(DATE_ATOM, mt_rand(1, time())), + 'createdAtGt' => date(DATE_ATOM, mt_rand(1, time())), + 'createdAtLte' => date(DATE_ATOM, mt_rand(1, time())), + 'createdAtLt' => date(DATE_ATOM, mt_rand(1, time())), + 'capturedAtGte' => date(DATE_ATOM, mt_rand(1, time())), + 'capturedAtGt' => date(DATE_ATOM, mt_rand(1, time())), + 'capturedAtLte' => date(DATE_ATOM, mt_rand(1, time())), + 'capturedAtLt' => date(DATE_ATOM, mt_rand(1, time())), + 'paymentMethod' => $methods[mt_rand(0, count($methods) - 1)], + 'status' => $statuses[mt_rand(0, count($statuses) - 1)], + 'limit' => mt_rand(1, 100), + 'cursor' => $this->randomString(mt_rand(1, 30)), + ); + $result[] = array($request); + } + return $result; + } + + private function randomString($length, $any = true) + { + static $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-+_.'; + + $result = ''; + for ($i = 0; $i < $length; $i++) { + if ($any) { + $char = chr(mt_rand(32, 126)); + } else { + $rnd = mt_rand(0, strlen($chars) - 1); + $char = substr($chars, $rnd, 1); + } + $result .= $char; + } + return $result; + } +} \ No newline at end of file diff --git a/tests/Request/Payments/PaymentsRequestSerializerTest.php b/tests/Request/Payments/PaymentsRequestSerializerTest.php new file mode 100644 index 00000000..8d44eaa7 --- /dev/null +++ b/tests/Request/Payments/PaymentsRequestSerializerTest.php @@ -0,0 +1,110 @@ + 'created_at.gte', + 'createdAtGt' => 'created_at.gt', + 'createdAtLte' => 'created_at.lte', + 'createdAtLt' => 'created_at.lt', + 'capturedAtGte' => 'captured_at.gte', + 'capturedAtGt' => 'captured_at.gt', + 'capturedAtLte' => 'captured_at.lte', + 'capturedAtLt' => 'captured_at.lt', + 'status' => 'status', + 'paymentMethod' => 'payment_method', + 'limit' => 'limit', + 'cursor' => 'cursor', + ); + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSerialize($options) + { + $serializer = new PaymentsRequestSerializer(); + $data = $serializer->serialize(PaymentsRequest::builder()->build($options)); + + $expected = array(); + foreach ($this->fieldMap as $field => $mapped) { + if (isset($options[$field])) { + $value = $options[$field]; + if (!empty($value)) { + $expected[$mapped] = $value instanceof \DateTime ? $value->format(DATE_ATOM) : $value; + } + } + } + self::assertEquals($expected, $data); + } + + public function validDataProvider() + { + $result = array( + array( + array(), + ), + array( + array( + 'createdAtGte' => '', + 'createdAtGt' => '', + 'createdAtLte' => '', + 'createdAtLt' => '', + 'capturedAtGte' => '', + 'capturedAtGt' => '', + 'capturedAtLte' => '', + 'capturedAtLt' => '', + 'paymentMethod' => '', + 'status' => '', + 'limit' => 0, + 'cursor' => '', + ), + ), + ); + $statuses = PaymentStatus::getValidValues(); + $methods = PaymentMethodType::getValidValues(); + for ($i = 0; $i < 10; $i++) { + $request = array( + 'createdAtGte' => date(DATE_ATOM, mt_rand(1, time())), + 'createdAtGt' => date(DATE_ATOM, mt_rand(1, time())), + 'createdAtLte' => date(DATE_ATOM, mt_rand(1, time())), + 'createdAtLt' => date(DATE_ATOM, mt_rand(1, time())), + 'capturedAtGte' => date(DATE_ATOM, mt_rand(1, time())), + 'capturedAtGt' => date(DATE_ATOM, mt_rand(1, time())), + 'capturedAtLte' => date(DATE_ATOM, mt_rand(1, time())), + 'capturedAtLt' => date(DATE_ATOM, mt_rand(1, time())), + 'paymentMethod' => $methods[mt_rand(0, count($methods) - 1)], + 'status' => $statuses[mt_rand(0, count($statuses) - 1)], + 'limit' => mt_rand(1, 100), + 'cursor' => $this->randomString(mt_rand(1, 30)), + ); + $result[] = array($request); + } + return $result; + } + + private function randomString($length, $any = true) + { + static $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-+_.'; + + $result = ''; + for ($i = 0; $i < $length; $i++) { + if ($any) { + $char = chr(mt_rand(32, 126)); + } else { + $rnd = mt_rand(0, strlen($chars) - 1); + $char = substr($chars, $rnd, 1); + } + $result .= $char; + } + return $result; + } +} \ No newline at end of file diff --git a/tests/Request/Payments/PaymentsRequestTest.php b/tests/Request/Payments/PaymentsRequestTest.php new file mode 100644 index 00000000..65a81fea --- /dev/null +++ b/tests/Request/Payments/PaymentsRequestTest.php @@ -0,0 +1,410 @@ +getterAndSetterTest($value, 'cursor', $value === null ? '' : (string)$value); + } + + /** + * @dataProvider invalidPageDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidCursor($value) + { + $this->getTestInstance()->setCursor($value); + } + + /** + * @dataProvider validPaymentMethodDataProvider + * @param $value + */ + public function testPaymentMethod($value) + { + $this->getterAndSetterTest($value, 'paymentMethod', $value); + } + + /** + * @dataProvider invalidPaymentMethodDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidPaymentMethod($value) + { + $this->getTestInstance()->setPaymentMethod($value); + } + + /** + * @dataProvider validDateDataProvider + * @param $value + */ + public function testDateMethods($value) + { + $properties = array( + 'createdAtGte', + 'createdAtGt', + 'createdAtLte', + 'createdAtLt', + 'capturedAtGte', + 'capturedAtGt', + 'capturedAtLte', + 'capturedAtLt', + ); + $expected = null; + if ($value instanceof \DateTime) { + $expected = $value->format(DATE_ATOM); + } elseif (is_numeric($value)) { + $expected = date(DATE_ATOM, $value); + } else { + $expected = $value; + } + foreach ($properties as $property) { + $this->getterAndSetterTest($value, $property, empty($expected) ? null : new \DateTime($expected)); + } + } + + /** + * @dataProvider invalidDateDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidCreatedAtGte($value) + { + $this->getTestInstance()->setCreatedAtGte($value); + } + + /** + * @dataProvider invalidDateDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidCreatedAtGt($value) + { + $this->getTestInstance()->setCreatedAtGt($value); + } + + /** + * @dataProvider invalidDateDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidCreatedAtLte($value) + { + $this->getTestInstance()->setCreatedAtLte($value); + } + + /** + * @dataProvider invalidDateDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidCreatedAtLt($value) + { + $this->getTestInstance()->setCreatedAtLt($value); + } + + /** + * @dataProvider invalidDateDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidCapturedAtGte($value) + { + $this->getTestInstance()->setCapturedAtGte($value); + } + + /** + * @dataProvider invalidDateDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidCapturedAtGt($value) + { + $this->getTestInstance()->setCapturedAtGt($value); + } + + /** + * @dataProvider invalidDateDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidCapturedAtLte($value) + { + $this->getTestInstance()->setCapturedAtLte($value); + } + + /** + * @dataProvider invalidDateDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidCapturedAtLt($value) + { + $this->getTestInstance()->setCapturedAtLt($value); + } + + + /** + * @dataProvider validLimitDataProvider + * @param $value + */ + public function testLimit($value) + { + $this->getterAndSetterTest($value, 'limit', $value); + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidLimit($value) + { + $this->getTestInstance()->setLimit($value); + } + + /** + * @dataProvider validStatusDataProvider + * @param $value + */ + public function testStatus($value) + { + $this->getterAndSetterTest($value, 'status', $value === null ? '' : (string)$value); + } + + /** + * @dataProvider invalidDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidStatus($value) + { + $this->getTestInstance()->setStatus($value); + } + + public function testValidate() + { + $instance = new PaymentsRequest(); + self::assertTrue($instance->validate()); + } + + public function testBuilder() + { + $builder = PaymentsRequest::builder(); + self::assertTrue($builder instanceof PaymentsRequestBuilder); + } + + public function validNetPageDataProvider() + { + return array( + array(''), + array(null), + array(Random::str(1)), + array(Random::str(2, 64)), + array(new StringObject(Random::str(1))), + array(new StringObject(Random::str(2, 64))), + ); + } + + public function validPaymentMethodDataProvider() + { + $result = array( + array(null), + array(''), + ); + foreach (PaymentMethodType::getValidValues() as $value) { + $result[] = array($value); + $result[] = array(new StringObject($value)); + } + return $result; + } + + public function validIdDataProvider() + { + return array( + array(null), + array(''), + array('123'), + array(Random::str(1, 64)), + array(new StringObject(Random::str(1, 64))), + ); + } + + public function validDateDataProvider() + { + return array( + array(null), + array(''), + array(Random::int(0, time())), + array(date(DATE_ATOM, Random::int(0, time()))), + array(new \DateTime()), + ); + } + + public function validStatusDataProvider() + { + $result = array( + array(null), + array(''), + ); + foreach (PaymentStatus::getValidValues() as $value) { + $result[] = array($value); + $result[] = array(new StringObject($value)); + } + return $result; + } + + public function validLimitDataProvider() + { + return array( + array(null), + array(Random::int(1, PaymentsRequest::MAX_LIMIT_VALUE)), + ); + } + + public function invalidIdDataProvider() + { + return array( + array(array()), + array(new \stdClass()), + array(true), + array(false), + ); + } + + public function invalidDataProvider() + { + $result = array( + array(array()), + array(new \stdClass()), + array(Random::str(10)), + array(Random::bytes(10)), + array(-1), + array(PaymentsRequest::MAX_LIMIT_VALUE + 1), + ); + return $result; + } + + public function invalidPaymentMethodDataProvider() + { + return array( + array(true), + array(false), + array(array()), + array(new \stdClass()), + array(Random::str(35)), + array(Random::str(37)), + array(new StringObject(Random::str(10))), + ); + } + + public function invalidDateDataProvider() + { + return array( + array(true), + array(false), + array(array()), + array(new \stdClass()), + array(Random::str(35)), + array(Random::str(37)), + array(new StringObject(Random::str(10))), + array(-123), + ); + } + + public function invalidPageDataProvider() + { + return array( + array(array()), + array(new \stdClass()), + array(true), + array(false), + ); + } + + private function getterAndSetterTest($value, $property, $expected, $testHas = true) + { + $getter = 'get'.ucfirst($property); + $setter = 'set'.ucfirst($property); + $has = 'has'.ucfirst($property); + + $instance = $this->getTestInstance(); + + if ($testHas) { + self::assertFalse($instance->{$has}()); + } + self::assertNull($instance->{$getter}()); + self::assertNull($instance->{$property}); + + $instance->{$setter}($value); + if ($value === null || $value === '') { + if ($testHas) { + self::assertFalse($instance->{$has}()); + } + self::assertNull($instance->{$getter}()); + self::assertNull($instance->{$property}); + } else { + if ($testHas) { + self::assertTrue($instance->{$has}()); + } + if ($expected instanceof \DateTime) { + self::assertEquals($expected->getTimestamp(), $instance->{$getter}()->getTimestamp()); + self::assertEquals($expected->getTimestamp(), $instance->{$property}->getTimestamp()); + } else { + self::assertEquals($expected, $instance->{$getter}()); + self::assertEquals($expected, $instance->{$property}); + } + } + + $instance->{$setter}(null); + if ($testHas) { + self::assertFalse($instance->{$has}()); + } + self::assertNull($instance->{$getter}()); + self::assertNull($instance->{$property}); + + $instance->{$property} = $value; + if ($value === null || $value === '') { + if ($testHas) { + self::assertFalse($instance->{$has}()); + } + self::assertNull($instance->{$getter}()); + self::assertNull($instance->{$property}); + } else { + if ($testHas) { + self::assertTrue($instance->{$has}()); + } + if ($expected instanceof \DateTime) { + self::assertEquals($expected->getTimestamp(), $instance->{$getter}()->getTimestamp()); + self::assertEquals($expected->getTimestamp(), $instance->{$property}->getTimestamp()); + } else { + self::assertEquals($expected, $instance->{$getter}()); + self::assertEquals($expected, $instance->{$property}); + } + } + } +} \ No newline at end of file diff --git a/tests/Request/Payments/PaymentsResponseTest.php b/tests/Request/Payments/PaymentsResponseTest.php new file mode 100644 index 00000000..432d8a4f --- /dev/null +++ b/tests/Request/Payments/PaymentsResponseTest.php @@ -0,0 +1,204 @@ +getItems())); + foreach ($instance->getItems() as $index => $item) { + self::assertTrue($item instanceof PaymentInterface); + self::assertArrayHasKey($index, $options['items']); + self::assertEquals($options['items'][$index]['id'], $item->getId()); + self::assertEquals($options['items'][$index]['status'], $item->getStatus()); + self::assertEquals($options['items'][$index]['amount']['value'], $item->getAmount()->getValue()); + self::assertEquals($options['items'][$index]['amount']['currency'], $item->getAmount()->getCurrency()); + self::assertEquals($options['items'][$index]['created_at'], $item->getCreatedAt()->format(DATE_ATOM)); + self::assertEquals($options['items'][$index]['payment_method']['type'], $item->getPaymentMethod()->getType()); + self::assertEquals($options['items'][$index]['paid'], $item->getPaid()); + self::assertEquals($options['items'][$index]['refundable'], $item->getRefundable()); + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetNextCursor($options) + { + $instance = new PaymentsResponse($options); + if (empty($options['next_cursor'])) { + self::assertNull($instance->getNextCursor()); + } else { + self::assertEquals($options['next_cursor'], $instance->getNextCursor()); + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testHasNext($options) + { + $instance = new PaymentsResponse($options); + if (empty($options['next_cursor'])) { + self::assertFalse($instance->hasNextCursor()); + } else { + self::assertTrue($instance->hasNextCursor()); + } + } + + public function validDataProvider() + { + return array( + array( + array( + 'items' => array(), + ), + ), + array( + array( + 'items' => array( + array( + 'id' => Random::str(36), + 'status' => PaymentStatus::SUCCEEDED, + 'amount' => array( + 'value' => Random::int(1, 100000), + 'currency' => CurrencyCode::EUR, + ), + 'description' => Random::str(20), + 'created_at' => date(DATE_ATOM), + 'payment_method' => array( + 'type' => PaymentMethodType::QIWI, + ), + 'paid' => false, + 'refundable' => false, + ) + ), + 'next_cursor' => uniqid(), + ), + ), + array( + array( + 'items' => array( + array( + 'id' => Random::str(36), + 'status' => PaymentStatus::SUCCEEDED, + 'amount' => array( + 'value' => Random::int(1, 100000), + 'currency' => CurrencyCode::EUR, + ), + 'created_at' => date(DATE_ATOM), + 'payment_method' => array( + 'type' => PaymentMethodType::QIWI, + ), + 'paid' => true, + 'refundable' => true, + 'confirmation' => array( + 'type' => ConfirmationType::EXTERNAL, + ), + ), + array( + 'id' => Random::str(36), + 'status' => PaymentStatus::SUCCEEDED, + 'amount' => array( + 'value' => Random::int(1, 100000), + 'currency' => CurrencyCode::EUR, + ), + 'description' => Random::str(20), + 'created_at' => date(DATE_ATOM), + 'payment_method' => array( + 'type' => PaymentMethodType::QIWI, + ), + 'paid' => false, + 'refundable' => false, + 'recipient' => array( + 'account_id' => uniqid(), + 'gateway_id' => uniqid(), + ), + 'reference_id' => uniqid(), + 'captured_at' => date(DATE_ATOM), + 'charge' => array('value' => Random::int(1, 100000), 'currency' => CurrencyCode::RUB), + 'income' => array('value' => Random::int(1, 100000), 'currency' => CurrencyCode::USD), + 'refunded' => array('value' => Random::int(1, 100000), 'currency' => CurrencyCode::EUR), + 'metadata' => array('test_key' => 'test_value'), + 'cancellation_details' => array('party' => CancellationDetailsPartyCode::PAYMENT_NETWORK, 'reason' => CancellationDetailsReasonCode::INVALID_CSC), + 'authorization_details' => array('rrn' => Random::str(20), 'auth_code' => Random::str(20)), + 'refunded_amount' => array('value' => Random::int(1, 100000), 'currency' => CurrencyCode::RUB), + 'confirmation' => array( + 'type' => ConfirmationType::EXTERNAL, + ), + 'receipt_registration' => ReceiptRegistrationStatus::PENDING, + ), + ), + 'next_cursor' => uniqid(), + ), + ), + array( + array( + 'items' => array( + array( + 'id' => Random::str(36), + 'status' => PaymentStatus::SUCCEEDED, + 'amount' => array( + 'value' => Random::int(1, 100000), + 'currency' => CurrencyCode::EUR, + ), + 'description' => Random::str(20), + 'created_at' => date(DATE_ATOM), + 'payment_method' => array( + 'type' => PaymentMethodType::QIWI, + ), + 'paid' => true, + 'refundable' => true, + 'confirmation' => array( + 'type' => ConfirmationType::REDIRECT, + 'confirmation_url' => Random::str(10), + 'return_url' => Random::str(10), + 'enforce' => false, + ), + ), + array( + 'id' => Random::str(36), + 'status' => PaymentStatus::SUCCEEDED, + 'amount' => array( + 'value' => Random::int(1, 100000), + 'currency' => CurrencyCode::EUR, + ), + 'description' => Random::str(20), + 'created_at' => date(DATE_ATOM), + 'payment_method' => array( + 'type' => PaymentMethodType::QIWI, + ), + 'paid' => true, + 'refundable' => true, + 'confirmation' => array( + 'type' => ConfirmationType::REDIRECT, + 'confirmation_url' => Random::str(10), + ), + ), + ), + 'next_cursor' => uniqid(), + ), + ), + ); + } +} \ No newline at end of file diff --git a/tests/Request/Receipts/AbstractReceiptResponseTest.php b/tests/Request/Receipts/AbstractReceiptResponseTest.php new file mode 100644 index 00000000..14783d5a --- /dev/null +++ b/tests/Request/Receipts/AbstractReceiptResponseTest.php @@ -0,0 +1,183 @@ +getTestInstance($options); + self::assertEquals($options['id'], $instance->getId()); + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetType($options) + { + $instance = $this->getTestInstance($options); + self::assertEquals($options['type'], $instance->getType()); + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetStatus($options) + { + $instance = $this->getTestInstance($options); + if (empty($options['status'])) { + self::assertFalse($instance->getStatus()); + } else { + self::assertEquals($options['status'], $instance->getStatus()); + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetTaxSystemCode($options) + { + $instance = $this->getTestInstance($options); + if (empty($options['tax_system_code'])) { + self::assertFalse($instance->getTaxSystemCode()); + } else { + self::assertEquals($options['tax_system_code'], $instance->getTaxSystemCode()); + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetItems($options) + { + $instance = $this->getTestInstance($options); + + self::assertEquals(count($options['items']), count($instance->getItems())); + + foreach ($instance->getItems() as $index => $item) { + self::assertTrue($item instanceof ReceiptResponseItemInterface); + self::assertArrayHasKey($index, $options['items']); + self::assertEquals($options['items'][$index]['description'], $item->getDescription()); + self::assertEquals($options['items'][$index]['amount']['value'], $item->getPrice()->getValue()); + self::assertEquals($options['items'][$index]['amount']['currency'], $item->getPrice()->getCurrency()); + self::assertEquals($options['items'][$index]['quantity'], $item->getQuantity()); + self::assertEquals($options['items'][$index]['vat_code'], $item->getVatCode()); + } + } + + public function validDataProvider() + { + return array($this->generateReceipts($this->type)); + } + + private function generateReceipts($type) + { + $return = array(); + $count = Random::int(1, 10); + + for ($i=0; $i < $count; $i++) { + $return[] = $this->generateReceipt($type); + } + + return $return; + } + + private function generateReceipt($type) + { + $receipt = array( + 'id' => Random::str(39), + 'type' => $type, + 'status' => Random::value(array('pending', 'succeeded', 'canceled')), + 'items' => $this->generateItems(), + 'settlements' => $this->generateSettlements(), + 'tax_system_code' => Random::int(1 ,6), + ); + + $receipt = $this->addSpecificProperties($receipt); + + return $receipt; + } + + private function generateItems() + { + $return = array(); + $count = Random::int(1, 10); + + for ($i=0; $i < $count; $i++) { + $return[] = $this->generateItem(); + } + + return $return; + } + + private function generateItem() + { + return array( + 'description' => Random::str(1, 128), + 'amount' => array( + 'value' => round(Random::float(1.00, 100.00), 2), + 'currency' => 'RUB', + ), + 'quantity' => round(Random::float(0.001, 99.999), 3), + 'vat_code' => Random::int(1 ,6), + ); + } + + private function generateSettlements() + { + $return = array(); + $count = Random::int(1, 10); + + for ($i=0; $i < $count; $i++) { + $return[] = $this->generateSettlement(); + } + + return $return; + } + + private function generateSettlement() + { + return array( + 'description' => Random::str(1, 128), + 'amount' => array( + 'value' => round(Random::float(1.00, 100.00), 2), + 'currency' => 'RUB', + ), + 'quantity' => round(Random::float(0.001, 99.999), 3), + 'vat_code' => Random::int(1 ,6), + ); + } +} diff --git a/tests/Request/Receipts/CreatePostReceiptRequestBuilderTest.php b/tests/Request/Receipts/CreatePostReceiptRequestBuilderTest.php new file mode 100644 index 00000000..b6a1a9a8 --- /dev/null +++ b/tests/Request/Receipts/CreatePostReceiptRequestBuilderTest.php @@ -0,0 +1,329 @@ +build($options); + + if (empty($options['items'])) { + self::assertNull($instance->getItems()); + } else { + self::assertNotNull($instance->getItems()); + self::assertEquals(count($options['items']), count($instance->getItems())); + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + */ + public function testSetSettlements($options) + { + $builder = new CreatePostReceiptRequestBuilder(); + $instance = $builder->build($options); + + if (empty($options['settlements'])) { + self::assertNull($instance->getSettlements()); + } else { + self::assertNotNull($instance->getSettlements()); + self::assertEquals(count($options['settlements']), count($instance->getSettlements())); + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws \Exception + */ + public function testSetCustomer($options) + { + $builder = new CreatePostReceiptRequestBuilder(); + $instance = $builder->build($options); + + if (empty($options['customer'])) { + self::assertNull($instance->getCustomer()); + } else { + self::assertNotNull($instance->getCustomer()); + self::assertEquals($options['customer'], $instance->getCustomer()->jsonSerialize()); + } + } + + /** + * @dataProvider invalidCustomerDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidCustomer($value) + { + $builder = new CreatePostReceiptRequestBuilder(); + $builder->setCustomer($value); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + */ + public function testSetType($options) + { + $builder = new CreatePostReceiptRequestBuilder(); + + $instance = $builder->build($options); + + if (empty($options['type'])) { + self::assertNull($instance->getType()); + } else { + self::assertNotNull($instance->getType()); + self::assertEquals($options['type'], $instance->getType()); + } + } + + /** + * @dataProvider invalidVatIdDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidType($value) + { + $builder = new CreatePostReceiptRequestBuilder(); + $builder->setType($value); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + */ + public function testSetSend($options) + { + $builder = new CreatePostReceiptRequestBuilder(); + + $instance = $builder->build($options); + + if (empty($options['send'])) { + self::assertNull($instance->getSend()); + } else { + self::assertNotNull($instance->getSend()); + self::assertEquals($options['send'], $instance->getSend()); + } + } + + /** + * @dataProvider invalidBooleanDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidSend($value) + { + $builder = new CreatePostReceiptRequestBuilder(); + $builder->setType($value); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + */ + public function testSetTaxSystemCode($options) + { + $builder = new CreatePostReceiptRequestBuilder(); + + $instance = $builder->build($options); + + if (empty($options['tax_system_code'])) { + self::assertNull($instance->getTaxSystemCode()); + } else { + self::assertNotNull($instance->getTaxSystemCode()); + self::assertEquals($options['tax_system_code'], $instance->getTaxSystemCode()); + } + } + + /** + * @dataProvider invalidVatIdDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidTaxSystemId($value) + { + $builder = new CreatePostReceiptRequestBuilder(); + $builder->setTaxSystemCode($value); + } + + /** + * @dataProvider validDataProvider + * @param $value + */ + public function testSetOnBehalfOf($options) + { + $builder = new CreatePostReceiptRequestBuilder(); + $instance = $builder->build($options); + + if (empty($options['on_behalf_of'])) { + self::assertNull($instance->getOnBehalfOf()); + } else { + self::assertNotNull($instance->getOnBehalfOf()); + self::assertEquals($options['on_behalf_of'], $instance->getOnBehalfOf()); + } + } + + public function validDataProvider() + { + $type = Random::value(ReceiptType::getValidValues()); + $result = array( + array( + array( + 'customer' => array( + 'full_name' => Random::str(128), + 'email' => Random::str(128), + 'phone' => Random::str(4, 12, '1234567890'), + 'inn' => '1234567890', + ), + 'items' => array( + array( + 'description' => Random::str(128), + 'quantity' => Random::int(1, 10), + 'amount' => array( + 'value' => round(Random::float(0.1, 99.99), 2), + 'currency' => Random::value(CurrencyCode::getValidValues()) + ), + 'vat_code' => Random::int(1, 6), + 'payment_subject' => Random::value(PaymentSubject::getValidValues()), + 'payment_mode' => Random::value(PaymentMode::getValidValues()), + 'product_code' => Random::str(2, 96, '1234567890ABCDEF '), + 'country_of_origin_code' => 'RU', + 'customs_declaration_number' => Random::str(32), + 'excise' => Random::float(0.0, 99.99), + ) + ), + 'tax_system_code' => Random::int(1, 6), + 'type' => $type, + 'send' => true, + 'settlements' => array( + array( + 'type' => Random::value(SettlementType::getValidValues()), + 'amount' => array( + 'value' => round(Random::float(0.1, 99.99), 2), + 'currency' => Random::value(CurrencyCode::getValidValues()) + ) + ) + ), + $type . '_id' => uniqid() + ), + ), + ); + for ($i = 0; $i < 10; $i++) { + $type = Random::value(ReceiptType::getValidValues()); + $request = array( + 'customer' => array( + 'full_name' => Random::str(128), + 'email' => Random::str(128), + 'phone' => Random::str(4, 12, '1234567890'), + 'inn' => '1234567890', + ), + 'items' => array( + array( + 'description' => Random::str(128), + 'quantity' => Random::int(1, 10), + 'amount' => array( + 'value' => round(Random::float(0.1, 99.99), 2), + 'currency' => Random::value(CurrencyCode::getValidValues()) + ), + 'vat_code' => Random::int(1, 6), + 'payment_subject' => Random::value(PaymentSubject::getValidValues()), + 'payment_mode' => Random::value(PaymentMode::getValidValues()), + 'product_code' => Random::str(2, 96, '0123456789ABCDEF '), + 'country_of_origin_code' => 'RU', + 'customs_declaration_number' => Random::str(32), + 'excise' => round(Random::float(0.0, 99.99), 2), + ) + ), + 'tax_system_code' => Random::int(1, 6), + 'type' => $type, + 'send' => true, + 'on_behalf_of' => Random::int(99999, 999999), + 'settlements' => array( + array( + 'type' => Random::value(SettlementType::getValidValues()), + 'amount' => array( + 'value' => round(Random::float(0.1, 99.99), 2), + 'currency' => Random::value(CurrencyCode::getValidValues()) + ) + ) + ), + $type . '_id' => uniqid() + ); + $result[] = array($request); + } + return $result; + } + + public function invalidAmountDataProvider() + { + return array( + array(-1), + array(true), + array(false), + array(new \stdClass()), + array(0), + ); + } + + public function invalidCustomerDataProvider() + { + return array( + array(true), + array(false), + array(Random::str(1, 100)), + ); + } + + public function invalidVatIdDataProvider() + { + return array( + array(array()), + array(true), + array(false), + array(new \stdClass()), + array(0), + array(7), + array(Random::int(-100, -1)), + array(Random::int(7, 100)), + ); + } + + + public function invalidBooleanDataProvider() + { + return array( + array(array()), + array(new \stdClass()), + array('test'), + ); + } + +} \ No newline at end of file diff --git a/tests/Request/Receipts/CreatePostReceiptRequestSerializerTest.php b/tests/Request/Receipts/CreatePostReceiptRequestSerializerTest.php new file mode 100644 index 00000000..096e0c58 --- /dev/null +++ b/tests/Request/Receipts/CreatePostReceiptRequestSerializerTest.php @@ -0,0 +1,183 @@ +build($options); + $data = $serializer->serialize($instance); + + $expected = array( + 'type' => $options['type'], + 'send' => $options['send'], + ); + + if (!empty($options['customer'])) { + $expected['customer'] = $options['customer']; + } + if (!empty($options['tax_system_code'])) { + $expected['tax_system_code'] = $options['tax_system_code']; + } + if (!empty($options['items'])) { + foreach ($options['items'] as $item) { + $itemArray = $item; + + if (!empty($item['payment_subject'])) { + $itemArray['payment_subject'] = $item['payment_subject']; + } + if (!empty($item['payment_mode'])) { + $itemArray['payment_mode'] = $item['payment_mode']; + } + if (!empty($item['vat_code'])) { + $itemArray['vat_code'] = $item['vat_code']; + } + if (!empty($item['product_code'])) { + $itemArray['product_code'] = $item['product_code']; + } + $expected['items'][] = $itemArray; + } + } + + if (!empty($options['settlements'])) { + foreach ($options['settlements'] as $item) { + $itemArray = $item; + $expected['settlements'][] = $itemArray; + } + } + + if (!empty($options['payment_id'])) { + $expected['payment_id'] = $options['payment_id']; + } + if (!empty($options['refund_id'])) { + $expected['refund_id'] = $options['refund_id']; + } + + self::assertEquals($expected, $data); + } + + public function validDataProvider() + { + $result = array( + array( + array( + 'type' => 'payment', + 'send' => true, + 'customer' => array( + 'email' => Random::str(10), + ), + 'items' => array( + array( + 'description' => Random::str(10), + 'quantity' => (float)Random::int(1, 10), + 'amount' => array( + 'value' => round(Random::float(1, 100), 2), + 'currency' => CurrencyCode::RUB, + ), + 'vat_code' => Random::int(1, 6), + 'payment_subject' => PaymentSubject::COMMODITY, + 'payment_mode' => PaymentMode::PARTIAL_PREPAYMENT, + ) + ), + 'settlements' => array( + array( + 'type' => Random::value(SettlementType::getValidValues()), + 'amount' => array( + 'value' => round(Random::float(0.1, 99.99), 2), + 'currency' => Random::value(CurrencyCode::getValidValues()) + ) + ) + ), + 'payment_id' => uniqid(), + 'tax_system_code' => Random::int(1, 6), + ), + ), + ); + + for ($i = 0; $i < 10; $i++) { + $type = Random::value(array(ReceiptType::PAYMENT, ReceiptType::REFUND)); + $request = array( + 'items' => $this->getReceiptItems($i + 1), + 'customer' => array( + 'email' => Random::str(10), + 'phone' => Random::str(12, '0123456789'), + ), + 'tax_system_code' => Random::int(1, 6), + 'type' => $type, + 'send' => true, + 'settlements' => $this->getSettlements($i + 1), + $type . '_id' => uniqid() + ); + $result[] = array($request); + } + + return $result; + } + + /** + * @param int $count + * @return array + * @throws \Exception + */ + private function getReceiptItems($count) + { + $result = array(); + for ($i = 0; $i < $count; $i++) { + $result[] = array( + 'description' => Random::str(10), + 'quantity' => (float)Random::float(1, 100), + 'amount' => array( + 'value' => (float)Random::int(1, 100), + 'currency' => CurrencyCode::RUB, + ), + 'vat_code' => Random::int(1, 6), + 'payment_subject' => Random::value(PaymentSubject::getValidValues()), + 'payment_mode' => Random::value(PaymentMode::getValidValues()), + 'product_code' => Random::str(96, 96, '0123456789ABCDEF '), + 'country_of_origin_code' => 'RU', + 'customs_declaration_number' => Random::str(32), + 'excise' => Random::float(0.0, 99.99), + ); + } + + return $result; + } + + /** + * @param int $count + * @return array + * @throws \Exception + */ + private function getSettlements($count) + { + $result = array(); + for ($i = 0; $i < $count; $i++) { + $result[] = array( + 'type' => Random::value(SettlementType::getValidValues()), + 'amount' => array( + 'value' => round(Random::float(0.1, 99.99), 2), + 'currency' => Random::value(CurrencyCode::getValidValues()) + ) + ); + } + + return $result; + } +} \ No newline at end of file diff --git a/tests/Request/Receipts/CreatePostReceiptRequestTest.php b/tests/Request/Receipts/CreatePostReceiptRequestTest.php new file mode 100644 index 00000000..fb03eb24 --- /dev/null +++ b/tests/Request/Receipts/CreatePostReceiptRequestTest.php @@ -0,0 +1,314 @@ +hasCustomer()); + self::assertNull($instance->getCustomer()); + self::assertNull($instance->customer); + + $instance->setCustomer($options['customer']); + if (empty($options['customer'])) { + self::assertFalse($instance->hasCustomer()); + self::assertNull($instance->getCustomer()); + self::assertNull($instance->customer); + } else { + self::assertTrue($instance->hasCustomer()); + self::assertSame($options['customer'], $instance->getCustomer()->jsonSerialize()); + self::assertSame($options['customer'], $instance->customer->jsonSerialize()); + } + + $instance->customer = $options['customer']; + if (empty($options['customer'])) { + self::assertFalse($instance->hasCustomer()); + self::assertNull($instance->getCustomer()); + self::assertNull($instance->customer); + } else { + self::assertTrue($instance->hasCustomer()); + self::assertSame($options['customer'], $instance->getCustomer()->jsonSerialize()); + self::assertSame($options['customer'], $instance->customer->jsonSerialize()); + } + } + + /** + * @dataProvider invalidCustomerDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidCustomer($value) + { + $instance = new CreatePostReceiptRequest(); + $instance->setCustomer($value); + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testType($options) + { + $instance = new CreatePostReceiptRequest(); + + self::assertNull($instance->getType()); + self::assertNull($instance->type); + + $instance->setType($options['type']); + + self::assertSame($options['type'], $instance->getType()); + self::assertSame($options['type'], $instance->type); + } + + /** + * @dataProvider invalidTypeDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidType($value) + { + $instance = new CreatePostReceiptRequest(); + $instance->setType($value); + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSend($options) + { + $instance = new CreatePostReceiptRequest(); + + self::assertTrue($instance->getSend()); + self::assertTrue($instance->send); + + $instance->setSend($options['send']); + + self::assertSame($options['send'], $instance->getSend()); + self::assertSame($options['send'], $instance->send); + } + + /** + * @dataProvider invalidBooleanDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidSend($value) + { + $instance = new CreatePostReceiptRequest(); + $instance->setType($value); + } + + public function testValidate() + { + $instance = new CreatePostReceiptRequest(); + + self::assertFalse($instance->validate()); + + $instance->setCustomer(new ReceiptCustomer()); + self::assertFalse($instance->validate()); + + $instance->setCustomer(new ReceiptCustomer(array('email' => 'johndoe@email.com'))); + self::assertFalse($instance->validate()); + + $instance->setType(ReceiptType::REFUND); + self::assertFalse($instance->validate()); + + $instance->setType(ReceiptType::PAYMENT); + self::assertFalse($instance->validate()); + + $instance->setSend(false); + self::assertFalse($instance->validate()); + + $instance->setSend(true); + self::assertFalse($instance->validate()); + + $instance->setObjectId(uniqid()); + self::assertFalse($instance->validate()); + + $instance->setItems(array()); + self::assertFalse($instance->validate()); + + $instance->setSettlements(array()); + self::assertFalse($instance->validate()); + + $instance->setItems(array( + new ReceiptItem(array( + 'description' => 'description', + 'amount' => array( + 'value' => 10, + 'currency' => 'RUB', + ), + 'quantity' => 1, + 'vat_code' => 1 + )) + )); + self::assertFalse($instance->validate()); + + $instance->setSettlements(array( + new Settlement(array( + 'type' => SettlementType::PREPAYMENT, + 'amount' => new ReceiptItemAmount(10, 'RUB'))) + ) + ); + self::assertTrue($instance->validate()); + } + + public function testBuilder() + { + $builder = CreatePaymentRequest::builder(); + self::assertTrue($builder instanceof CreatePaymentRequestBuilder); + } + + /** + * @return array + * @throws \Exception + */ + public function validDataProvider() + { + $type = Random::value(ReceiptType::getValidValues()); + $result = array( + + array( + array( + 'customer' => array( + 'full_name' => Random::str(128), + 'email' => Random::str(128), + 'phone' => Random::str(4, 12, '1234567890'), + 'inn' => '1234567890', + ), + 'items' => array( + array( + 'description' => Random::str(128), + 'quantity' => Random::int(1, 10), + 'amount' => array( + 'value' => Random::float(0.1, 99.99), + 'currency' => Random::value(CurrencyCode::getValidValues()) + ), + 'vat_code' => Random::int(1, 6), + 'payment_subject' => Random::value(PaymentSubject::getValidValues()), + 'payment_mode' => Random::value(PaymentMode::getValidValues()), + 'product_code' => Random::str(128), + 'country_of_origin_code' => 'RU', + 'customs_declaration_number' => Random::str(128), + 'excise' => Random::float(0.0, 99.99), + ) + ), + 'tax_system_code' => Random::int(1, 6), + 'type' => $type, + 'send' => true, + 'settlements' => array( + array( + 'type' => Random::value(SettlementType::getValidValues()), + 'amount' => array( + 'value' => Random::float(0.1, 99.99), + 'currency' => Random::value(CurrencyCode::getValidValues()) + ) + ) + ), + $type . '_id' => uniqid() + ), + ), + ); + for ($i = 0; $i < 10; $i++) { + $type = Random::value(ReceiptType::getValidValues()); + $request = array( + 'customer' => array( + 'full_name' => Random::str(128), + 'email' => Random::str(128), + 'phone' => Random::str(4, 12, '1234567890'), + 'inn' => '1234567890', + ), + 'items' => array( + array( + 'description' => Random::str(128), + 'quantity' => Random::int(1, 10), + 'amount' => array( + 'value' => Random::float(0.1, 99.99), + 'currency' => Random::value(CurrencyCode::getValidValues()) + ), + 'vat_code' => Random::int(1, 6), + 'payment_subject' => Random::value(PaymentSubject::getValidValues()), + 'payment_mode' => Random::value(PaymentMode::getValidValues()), + 'product_code' => Random::str(128), + 'country_of_origin_code' => 'RU', + 'customs_declaration_number' => Random::str(128), + 'excise' => Random::float(0.0, 99.99), + ) + ), + 'tax_system_code' => Random::int(1, 6), + 'type' => $type, + 'send' => true, + 'settlements' => array( + array( + 'type' => Random::value(SettlementType::getValidValues()), + 'amount' => array( + 'value' => Random::float(0.1, 99.99), + 'currency' => Random::value(CurrencyCode::getValidValues()) + ) + ) + ), + $type . '_id' => uniqid() + ); + $result[] = array($request); + } + return $result; + } + + public function invalidCustomerDataProvider() + { + return array( + array(false), + array(true), + array(1), + array(Random::str(10)), + array(new \stdClass()), + ); + } + + public function invalidTypeDataProvider() + { + return array( + array(false), + array(true), + array(1), + array(Random::str(10)), + array(new \stdClass()), + ); + } + + public function invalidBooleanDataProvider() + { + return array( + array(array()), + array(new \stdClass()), + array('test'), + ); + } +} \ No newline at end of file diff --git a/tests/Request/Receipts/PaymentReceiptResponseTest.php b/tests/Request/Receipts/PaymentReceiptResponseTest.php new file mode 100644 index 00000000..ca0612c8 --- /dev/null +++ b/tests/Request/Receipts/PaymentReceiptResponseTest.php @@ -0,0 +1,33 @@ +getTestInstance($options); + self::assertEquals($options['payment_id'], $instance->getPaymentId()); + } + +} \ No newline at end of file diff --git a/tests/Request/Receipts/ReceiptsResponseTest.php b/tests/Request/Receipts/ReceiptsResponseTest.php new file mode 100644 index 00000000..6e0c6a13 --- /dev/null +++ b/tests/Request/Receipts/ReceiptsResponseTest.php @@ -0,0 +1,133 @@ +getType()); + } + + /** + * @dataProvider validDataProvider + * @param array $options + * @throws \Exception + */ + public function testGetItems($options) + { + $instance = new ReceiptsResponse($options); + + self::assertEquals(count($options['items']), count($instance->getItems())); + + foreach ($instance->getItems() as $index => $item) { + self::assertTrue($item instanceof ReceiptResponseInterface); + self::assertArrayHasKey($index, $options['items']); + self::assertEquals($options['items'][$index]['id'], $item->getId()); + self::assertEquals($options['items'][$index]['type'], $item->getType()); + self::assertEquals($options['items'][$index]['tax_system_code'], $item->getTaxSystemCode()); + self::assertEquals($options['items'][$index]['status'], $item->getStatus()); + + self::assertEquals(count($options['items'][$index]['items']), count($item->getItems())); + } + } + + public function validDataProvider() + { + return array( + array( + array( + 'type' => 'list', + 'items' => $this->generateReceipts(), + ), + ), + ); + } + + private function generateReceipts() + { + $return = array(); + $count = Random::int(1, 10); + + for ($i=0; $i < $count; $i++) { + $return[] = $this->generateReceipt(); + } + + return $return; + } + + private function generateReceipt() + { $type = Random::value(ReceiptType::getEnabledValues()); + return array( + 'id' => Random::str(39), + 'type' => $type, + 'status' => Random::value(array('pending', 'succeeded', 'canceled')), + 'items' => $this->generateItems(), + 'settlements' => $this->generateItems(), + 'tax_system_code' => Random::int(1 ,6), + $type . '_id' => UUID::v4(), + ); + } + + private function generateItems() + { + $return = array(); + $count = Random::int(1, 10); + + for ($i=0; $i < $count; $i++) { + $return[] = $this->generateItem(); + } + + return $return; + } + + private function generateItem() + { + return array( + 'description' => Random::str(1, 128), + 'amount' => array( + 'value' => round(Random::float(1.00, 100.00), 2), + 'currency' => 'RUB', + ), + 'quantity' => round(Random::float(0.001, 99.999), 3), + 'vat_code' => Random::int(1 ,6), + ); + } + + private function generateSettlements() + { + $return = array(); + $count = Random::int(1, 10); + + for ($i=0; $i < $count; $i++) { + $return[] = $this->generateSettlement(); + } + + return $return; + } + + private function generateSettlement() + { + return array( + 'type' => Random::value(SettlementType::getValidValues()), + 'amount' => array( + 'value' => round(Random::float(1.00, 100.00), 2), + 'currency' => 'RUB', + ), + ); + } +} diff --git a/tests/Request/Receipts/RefundReceiptResponseTest.php b/tests/Request/Receipts/RefundReceiptResponseTest.php new file mode 100644 index 00000000..42c3ff1c --- /dev/null +++ b/tests/Request/Receipts/RefundReceiptResponseTest.php @@ -0,0 +1,32 @@ +getTestInstance($options); + self::assertEquals($options['refund_id'], $instance->getRefundId()); + } +} \ No newline at end of file diff --git a/tests/Request/Refunds/AbstractRefundResponseTest.php b/tests/Request/Refunds/AbstractRefundResponseTest.php new file mode 100644 index 00000000..7c13c1cf --- /dev/null +++ b/tests/Request/Refunds/AbstractRefundResponseTest.php @@ -0,0 +1,148 @@ +getTestInstance($options); + self::assertEquals($options['id'], $instance->getId()); + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetPaymentId($options) + { + $instance = $this->getTestInstance($options); + self::assertEquals($options['payment_id'], $instance->getPaymentId()); + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetStatus($options) + { + $instance = $this->getTestInstance($options); + self::assertEquals($options['status'], $instance->getStatus()); + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetCreatedAt($options) + { + $instance = $this->getTestInstance($options); + self::assertTrue($instance->getCreatedAt() instanceof \DateTime); + self::assertEquals($options['created_at'], $instance->getCreatedAt()->format(DATE_ATOM)); + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetAmount($options) + { + $instance = $this->getTestInstance($options); + self::assertTrue($instance->getAmount() instanceof AmountInterface); + self::assertEquals($options['amount']['value'], $instance->getAmount()->getValue()); + self::assertEquals($options['amount']['currency'], $instance->getAmount()->getCurrency()); + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetReceiptRegistered($options) + { + $instance = $this->getTestInstance($options); + if (empty($options['receipt_registration'])) { + self::assertNull($instance->getReceiptRegistration()); + } else { + self::assertEquals($options['receipt_registration'], $instance->getReceiptRegistration()); + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetComment($options) + { + $instance = $this->getTestInstance($options); + if (empty($options['description'])) { + self::assertNull($instance->getDescription()); + } else { + self::assertEquals($options['description'], $instance->getDescription()); + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetSources($options) + { + $instance = $this->getTestInstance($options); + if (empty($options['sources'])) { + self::assertEmpty($instance->getSources()); + } else { + foreach ($instance->getSources() as $sources) { + self::assertInstanceOf('\YooKassa\Model\Source', $sources); + } + } + } + + public function validDataProvider() + { + $result = array(); + for ($i = 0; $i < 10; $i++) { + $payment = array( + 'id' => Random::str(36), + 'payment_id' => Random::str(36), + 'status' => Random::value(RefundStatus::getValidValues()), + 'created_at' => date(DATE_ATOM, mt_rand(1, time())), + 'authorized_at' => date(DATE_ATOM, mt_rand(1, time())), + 'amount' => array( + 'value' => mt_rand(100, 100000), + 'currency' => Random::value(CurrencyCode::getValidValues()), + ), + 'receipt_registration' => Random::value(ReceiptRegistrationStatus::getValidValues()), + 'description' => uniqid(), + 'sources' => array( + new Source(array( + 'account_id' => Random::str(36), + 'amount' => new MonetaryAmount(Random::int(1, 1000), 'RUB'), + 'platform_fee_amount' => new MonetaryAmount(Random::int(1, 1000), 'RUB'), + )), + ) + ); + $result[] = array($payment); + } + return $result; + } +} \ No newline at end of file diff --git a/tests/Request/Refunds/CreateRefundRequestBuilderTest.php b/tests/Request/Refunds/CreateRefundRequestBuilderTest.php new file mode 100644 index 00000000..64d881a3 --- /dev/null +++ b/tests/Request/Refunds/CreateRefundRequestBuilderTest.php @@ -0,0 +1,612 @@ +build(array('amountValue' => mt_rand(1, 100))); + } catch (\RuntimeException $e) { + $builder->setPaymentId($options['paymentId']); + $instance = $builder->build(array('amount' => mt_rand(1, 100))); + self::assertEquals($options['paymentId'], $instance->getPaymentId()); + + return; + } + self::fail('Exception not thrown'); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws \Exception + */ + public function testSetAmountValue($options) + { + $builder = new CreateRefundRequestBuilder(); + try { + $builder->build(array('paymentId' => Random::str(36))); + } catch (\RuntimeException $e) { + $builder->setAmount($options['amount']); + $instance = $builder->build(array('paymentId' => Random::str(36))); + if ($options['amount'] instanceof AmountInterface) { + self::assertEquals($options['amount']->getValue(), $instance->getAmount()->getValue()); + } else { + self::assertEquals($options['amount'], $instance->getAmount()->getValue()); + } + + + if ($options['amount'] instanceof AmountInterface) { + $builder->setAmount(array( + 'value' => $options['amount']->getValue(), + 'currency' => 'USD', + )); + $instance = $builder->build(array('paymentId' => Random::str(36))); + self::assertEquals($options['amount']->getValue(), $instance->getAmount()->getValue()); + } else { + $builder->setAmount(array( + 'value' => $options['amount'], + 'currency' => 'USD', + )); + $instance = $builder->build(array('paymentId' => Random::str(36))); + self::assertEquals($options['amount'], $instance->getAmount()->getValue()); + } + + return; + } + self::fail('Exception not thrown'); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws \Exception + */ + public function testSetAmountCurrency($options) + { + $builder = new CreateRefundRequestBuilder(); + + $builder->setCurrency($options['currency']); + $instance = $builder->build(array( + 'paymentId' => Random::str(36), + 'amount' => mt_rand(1, 100), + )); + self::assertEquals($options['currency'], $instance->getAmount()->getCurrency()); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws \Exception + */ + public function testSetComment($options) + { + $builder = new CreateRefundRequestBuilder(); + $instance = $builder->build(array( + 'paymentId' => Random::str(36), + 'amount' => mt_rand(1, 100), + )); + self::assertNull($instance->getDescription()); + + $builder->setDescription($options['description']); + $instance = $builder->build(array( + 'paymentId' => Random::str(36), + 'amount' => mt_rand(1, 100), + )); + if (empty($options['description'])) { + self::assertNull($instance->getDescription()); + } else { + self::assertEquals($options['description'], $instance->getDescription()); + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + */ + public function testBuild($options) + { + $builder = new CreateRefundRequestBuilder(); + $instance = $builder->build($options); + + self::assertEquals($options['paymentId'], $instance->getPaymentId()); + if ($options['amount'] instanceof AmountInterface) { + self::assertEquals($options['amount']->getValue(), $instance->getAmount()->getValue()); + } else { + self::assertEquals($options['amount'], $instance->getAmount()->getValue()); + } + self::assertEquals($options['currency'], $instance->getAmount()->getCurrency()); + if (empty($options['description'])) { + self::assertNull($instance->getDescription()); + } else { + self::assertEquals($options['description'], $instance->getDescription()); + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws \Exception + */ + public function testSetReceiptItems($options) + { + $builder = new CreateRefundRequestBuilder(); + + $builder->setReceiptItems($options['receiptItems']); + $builder->setReceiptEmail($options['receiptEmail']); + $instance = $builder->build($this->getRequiredData()); + + if (empty($options['receiptItems'])) { + self::assertNull($instance->getReceipt()); + } else { + self::assertNotNull($instance->getReceipt()); + self::assertEquals(count($options['receiptItems']), count($instance->getReceipt()->getItems())); + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws \Exception + */ + public function testAddReceiptItems($options) + { + $builder = new CreateRefundRequestBuilder(); + + foreach ($options['receiptItems'] as $item) { + if ($item instanceof ReceiptItem) { + $builder->addReceiptItem( + $item->getDescription(), $item->getPrice()->getValue(), $item->getQuantity(), $item->getVatCode() + ); + } else { + $builder->addReceiptItem($item['title'], $item['price'], $item['quantity'], $item['vatCode']); + } + } + $builder->setReceiptEmail($options['receiptEmail']); + $instance = $builder->build($this->getRequiredData()); + + if (empty($options['receiptItems'])) { + self::assertNull($instance->getReceipt()); + } else { + self::assertNotNull($instance->getReceipt()); + self::assertEquals(count($options['receiptItems']), count($instance->getReceipt()->getItems())); + foreach ($instance->getReceipt()->getItems() as $item) { + self::assertFalse($item->isShipping()); + } + } + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws \Exception + */ + public function testAddReceiptShipping($options) + { + $builder = new CreateRefundRequestBuilder(); + + foreach ($options['receiptItems'] as $item) { + if ($item instanceof ReceiptItem) { + $builder->addReceiptShipping( + $item->getDescription(), $item->getPrice()->getValue(), $item->getVatCode() + ); + } else { + $builder->addReceiptShipping($item['title'], $item['price'], $item['vatCode']); + } + } + $builder->setReceiptEmail($options['receiptEmail']); + $instance = $builder->build($this->getRequiredData()); + + if (empty($options['receiptItems'])) { + self::assertNull($instance->getReceipt()); + } else { + self::assertNotNull($instance->getReceipt()); + self::assertEquals(count($options['receiptItems']), count($instance->getReceipt()->getItems())); + foreach ($instance->getReceipt()->getItems() as $item) { + self::assertTrue($item->isShipping()); + } + } + } + + /** + * @dataProvider invalidItemsDataProvider + * @expectedException \InvalidArgumentException + * + * @param $items + */ + public function testSetInvalidReceiptItems($items) + { + $builder = new CreateRefundRequestBuilder(); + $builder->setReceiptItems($items); + } + + /** + * @throws \Exception + */ + public function testSetReceipt() + { + $receipt = array( + 'tax_system_code' => Random::int(1, 6), + 'customer' => array( + 'email' => Random::str(10), + 'phone' => Random::str(4, 15, '0123456789'), + ), + 'items' => array( + array( + 'description' => 'test', + 'quantity' => 123, + 'amount' => array( + 'value' => 321, + 'currency' => 'USD', + ), + 'vat_code' => Random::int(1, 6), + 'payment_subject' => PaymentSubject::COMMODITY, + 'payment_mode' => PaymentMode::PARTIAL_PREPAYMENT, + ), + ), + ); + + $builder = new CreateRefundRequestBuilder(); + $builder->setReceipt($receipt); + $instance = $builder->build($this->getRequiredData()); + + self::assertEquals($receipt['tax_system_code'], $instance->getReceipt()->getTaxSystemCode()); + self::assertEquals($receipt['customer']['email'], $instance->getReceipt()->getCustomer()->getEmail()); + self::assertEquals($receipt['customer']['phone'], $instance->getReceipt()->getCustomer()->getPhone()); + self::assertEquals(1, count($instance->getReceipt()->getItems())); + + $receipt = $instance->getReceipt(); + + $builder = new CreateRefundRequestBuilder(); + $builder->setReceipt($instance->getReceipt()); + $instance = $builder->build($this->getRequiredData()); + + self::assertEquals($receipt['tax_system_code'], $instance->getReceipt()->getTaxSystemCode()); + self::assertEquals($receipt['customer']['email'], $instance->getReceipt()->getCustomer()->getEmail()); + self::assertEquals($receipt['customer']['phone'], $instance->getReceipt()->getCustomer()->getPhone()); + self::assertEquals(1, count($instance->getReceipt()->getItems())); + } + + /** + * @dataProvider invalidReceiptDataProvider + * @expectedException \InvalidArgumentException + * + * @param mixed $value + */ + public function testSetInvalidReceipt($value) + { + $builder = new CreateRefundRequestBuilder(); + $builder->setReceipt($value); + } + + /** + * @return array + */ + public function invalidReceiptDataProvider() + { + return array( + array(null), + array(true), + array(false), + array(1), + array(1.1), + array('test'), + array(new \stdClass()), + ); + } + + /** + * @return array + */ + public function invalidItemsDataProvider() + { + return array( + array( + array( + array( + 'price' => 1, + 'quantity' => 1.4, + 'vatCode' => 3, + ), + ), + ), + array( + array( + array( + 'title' => 'test', + 'quantity' => 1.4, + 'vatCode' => 3, + ), + ), + ), + array( + array( + array( + 'description' => 'test', + 'quantity' => 1.4, + 'vatCode' => 3, + ), + ), + ), + array( + array( + array( + 'title' => 'test', + 'price' => 123, + 'quantity' => 1.4, + 'vatCode' => 7, + ), + ), + ), + array( + array( + array( + 'description' => 'test', + 'price' => 123, + 'quantity' => -1.4, + ), + ), + ), + array( + array( + array( + 'title' => 'test', + 'price' => 1, + 'vatCode' => 7, + ), + ), + ), + ); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws \Exception + */ + public function testSetReceiptEmail($options) + { + $builder = new CreateRefundRequestBuilder(); + + $builder->setReceiptItems($options['receiptItems']); + $builder->setReceiptEmail($options['receiptEmail']); + $instance = $builder->build($this->getRequiredData()); + + if (empty($options['receiptItems'])) { + self::assertNull($instance->getReceipt()); + } else { + self::assertNotNull($instance->getReceipt()); + self::assertEquals($options['receiptEmail'], $instance->getReceipt()->getCustomer()->getEmail()); + } + } + + /** + * @dataProvider invalidEmailDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidEmail($value) + { + $builder = new CreateRefundRequestBuilder(); + $builder->setReceiptEmail($value); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws \Exception + */ + public function testSetReceiptPhone($options) + { + $builder = new CreateRefundRequestBuilder(); + + $builder->setReceiptItems($options['receiptItems']); + $builder->setReceiptEmail($options['receiptEmail']); + $builder->setReceiptPhone($options['receiptPhone']); + $instance = $builder->build($this->getRequiredData()); + + if (empty($options['receiptItems'])) { + self::assertNull($instance->getReceipt()); + } else { + self::assertNotNull($instance->getReceipt()); + self::assertEquals($options['receiptPhone'], $instance->getReceipt()->getCustomer()->getPhone()); + } + } + + /** + * @dataProvider invalidPhoneDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidPhone($value) + { + $builder = new CreateRefundRequestBuilder(); + $builder->setReceiptPhone($value); + } + + /** + * @dataProvider validDataProvider + * + * @param $options + * @throws \Exception + */ + public function testSetReceiptTaxSystemCode($options) + { + $builder = new CreateRefundRequestBuilder(); + + $builder->setReceiptItems($options['receiptItems']); + $builder->setReceiptEmail($options['receiptEmail']); + $builder->setTaxSystemCode($options['taxSystemCode']); + $instance = $builder->build($this->getRequiredData()); + + if (empty($options['receiptItems'])) { + self::assertNull($instance->getReceipt()); + } else { + self::assertNotNull($instance->getReceipt()); + self::assertEquals($options['taxSystemCode'], $instance->getReceipt()->getTaxSystemCode()); + } + } + + /** + * @dataProvider invalidVatIdDataProvider + * @expectedException \InvalidArgumentException + * + * @param $value + */ + public function testSetInvalidTaxSystemId($value) + { + $builder = new CreateRefundRequestBuilder(); + $builder->setTaxSystemCode($value); + } + + + /** + * @return array + * @throws \Exception + */ + public function validDataProvider() + { + $result = array( + array( + array( + 'paymentId' => Random::str(36), + 'amount' => mt_rand(1, 999999), + 'currency' => Random::value(CurrencyCode::getValidValues()), + 'description' => null, + 'receiptItems' => array(), + 'receiptEmail' => null, + 'receiptPhone' => null, + 'taxSystemCode' => Random::int(1, 6), + ), + ), + array( + array( + 'paymentId' => Random::str(36), + 'amount' => new MonetaryAmount( + Random::int(1, 999999), + Random::value(CurrencyCode::getValidValues()) + ), + 'currency' => Random::value(CurrencyCode::getValidValues()), + 'description' => '', + 'receiptItems' => array(), + 'receiptEmail' => '', + 'receiptPhone' => '', + 'taxSystemCode' => Random::int(1, 6), + ), + ), + ); + $items = array( + new ReceiptItem(), + array( + 'title' => 'test', + 'price' => Random::int(1, 999999), + 'quantity' => Random::int(1, 9999), + 'vatCode' => Random::int(1, 6), + ), + ); + $items[0]->setDescription('test1'); + $items[0]->setQuantity(Random::int(1, 9999)); + $items[0]->setPrice(new MonetaryAmount(Random::int(1, 999999))); + $items[0]->setVatCode(Random::int(1, 6)); + for ($i = 0; $i < 10; $i++) { + $request = array( + 'paymentId' => Random::str(36), + 'amount' => mt_rand(1, 999999), + 'currency' => Random::value(CurrencyCode::getValidValues()), + 'description' => uniqid(), + 'receiptItems' => $items, + 'receiptEmail' => uniqid(), + 'receiptPhone' => Random::str(4, 15, '0123456789'), + 'taxSystemCode' => Random::int(1, 6), + ); + $result[] = array($request); + } + + return $result; + } + + /** + * @return array + * @throws \Exception + */ + private function getRequiredData() + { + return array( + 'paymentId' => Random::str(36), + 'amount' => mt_rand(1, 100), + ); + } + + /** + * @return array + */ + public function invalidEmailDataProvider() + { + return array( + array(array()), + array(true), + array(false), + array(new \stdClass()), + ); + } + + /** + * @return array + */ + public function invalidPhoneDataProvider() + { + return array( + array(new \stdClass()), + array(array()), + array(true), + array(false), + ); + } + + /** + * @return array + * @throws \Exception + */ + public function invalidVatIdDataProvider() + { + return array( + array(array()), + array(true), + array(false), + array(new \stdClass()), + array(0), + array(7), + array(Random::int(-100, -1)), + array(Random::int(7, 100)), + ); + } +} \ No newline at end of file diff --git a/tests/Request/Refunds/CreateRefundRequestSerializerTest.php b/tests/Request/Refunds/CreateRefundRequestSerializerTest.php new file mode 100644 index 00000000..47921630 --- /dev/null +++ b/tests/Request/Refunds/CreateRefundRequestSerializerTest.php @@ -0,0 +1,137 @@ +serialize(CreateRefundRequest::builder()->build($options)); + + $expected = array( + 'payment_id' => $options['paymentId'], + 'amount' => array( + 'value' => $options['amount'], + 'currency' => $options['currency'], + ), + ); + if (!empty($options['description'])) { + $expected['description'] = $options['description']; + } + + if (!empty($options['receiptItems'])) { + foreach ($options['receiptItems'] as $item) { + $expected['receipt']['items'][] = array( + 'description' => $item['title'], + 'quantity' => empty($item['quantity']) ? 1 : $item['quantity'], + 'amount' => array( + 'value' => $item['price'], + 'currency' => isset($options['currency']) ? $options['currency'] : CurrencyCode::RUB, + ), + 'vat_code' => $item['vatCode'], + ); + } + } + if (!empty($options['receiptEmail'])) { + $expected['receipt']['customer']['email'] = $options['receiptEmail']; + } + if (!empty($options['receiptPhone'])) { + $expected['receipt']['customer']['phone'] = $options['receiptPhone']; + } + if (!empty($options['taxSystemCode'])) { + $expected['receipt']['tax_system_code'] = $options['taxSystemCode']; + } + + self::assertEquals($expected, $data); + } + + public function validDataProvider() + { + $currencies = CurrencyCode::getValidValues(); + $result = array( + array( + array( + 'paymentId' => $this->randomString(36), + 'amount' => mt_rand(1, 999999), + 'currency' => $currencies[mt_rand(0, count($currencies) - 1)], + 'description' => null, + 'receiptItems' => array(), + ), + ), + array( + array( + 'paymentId' => $this->randomString(36), + 'amount' => mt_rand(1, 999999), + 'currency' => $currencies[mt_rand(0, count($currencies) - 1)], + 'description' => '', + 'receiptItems' => array( + array( + 'title' => Random::str(10), + 'quantity' => Random::int(1, 10), + 'price' => Random::int(100, 100), + 'vatCode' => Random::int(1, 6), + ), + ), + 'receiptEmail' => Random::str(10), + 'taxSystemCode' => Random::int(1, 6), + ), + ), + ); + for ($i = 0; $i < 10; $i++) { + $request = array( + 'paymentId' => $this->randomString(36), + 'amount' => mt_rand(1, 999999), + 'currency' => $currencies[mt_rand(0, count($currencies) - 1)], + 'description' => uniqid(), + 'receiptItems' => $this->getReceipt($i + 1), + 'receiptEmail' => Random::str(10), + 'receiptPhone' => Random::str(12, '0123456789'), + 'taxSystemCode' => Random::int(1, 6), + ); + $result[] = array($request); + } + return $result; + } + + private function randomString($length, $any = true) + { + static $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-+_.'; + + $result = ''; + for ($i = 0; $i < $length; $i++) { + if ($any) { + $char = chr(mt_rand(32, 126)); + } else { + $rnd = mt_rand(0, strlen($chars) - 1); + $char = substr($chars, $rnd, 1); + } + $result .= $char; + } + return $result; + } + + private function getReceipt($count) + { + $result = array(); + for ($i = 0; $i < $count; $i++) { + $result[] = array( + 'title' => Random::str(10), + 'quantity' => Random::float(1, 100), + 'price' => Random::int(1, 100), + 'vatCode' => Random::int(1, 6), + ); + } + return $result; + } +} \ No newline at end of file diff --git a/tests/Request/Refunds/CreateRefundRequestTest.php b/tests/Request/Refunds/CreateRefundRequestTest.php new file mode 100644 index 00000000..903b9bb9 --- /dev/null +++ b/tests/Request/Refunds/CreateRefundRequestTest.php @@ -0,0 +1,270 @@ +getPaymentId()); + self::assertNull($instance->paymentId); + + $instance->setPaymentId($options['paymentId']); + + self::assertEquals($options['paymentId'], $instance->getPaymentId()); + self::assertEquals($options['paymentId'], $instance->paymentId); + + $instance = new CreateRefundRequest(); + + self::assertNull($instance->getPaymentId()); + self::assertNull($instance->paymentId); + + $instance->paymentId = $options['paymentId']; + + self::assertEquals($options['paymentId'], $instance->getPaymentId()); + self::assertEquals($options['paymentId'], $instance->paymentId); + } + + /** + * @dataProvider invalidPaymentIdDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidPaymentId($value) + { + $instance = new CreateRefundRequest(); + $instance->setPaymentId($value); + } + + /** + * @dataProvider invalidPaymentIdDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidPaymentId($value) + { + $instance = new CreateRefundRequest(); + $instance->paymentId = $value; + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testAmount($options) + { + $instance = new CreateRefundRequest(); + + self::assertNull($instance->getAmount()); + self::assertNull($instance->amount, $instance->getAmount()); + + $instance->setAmount($options['amount']); + + self::assertEquals($options['amount']->getValue(), $instance->getAmount()->getValue()); + self::assertEquals($options['amount']->getValue(), $instance->amount->getValue()); + self::assertEquals($options['amount']->getCurrency(), $instance->getAmount()->getCurrency()); + self::assertEquals($options['amount']->getCurrency(), $instance->amount->getCurrency()); + + $instance = new CreateRefundRequest(); + + $instance->amount = $options['amount']; + + self::assertEquals($options['amount']->getValue(), $instance->getAmount()->getValue()); + self::assertEquals($options['amount']->getValue(), $instance->amount->getValue()); + self::assertEquals($options['amount']->getCurrency(), $instance->getAmount()->getCurrency()); + self::assertEquals($options['amount']->getCurrency(), $instance->amount->getCurrency()); + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testComment($options) + { + $instance = new CreateRefundRequest(); + + self::assertFalse($instance->hasDescription()); + self::assertNull($instance->getDescription()); + self::assertNull($instance->description); + + $instance->setDescription($options['description']); + if (empty($options['description'])) { + self::assertFalse($instance->hasDescription()); + self::assertNull($instance->getDescription()); + self::assertNull($instance->description); + } else { + self::assertTrue($instance->hasDescription()); + self::assertEquals($options['description'], $instance->getDescription()); + self::assertEquals($options['description'], $instance->description); + } + + $instance->setDescription(''); + self::assertFalse($instance->hasDescription()); + self::assertNull($instance->getDescription()); + self::assertNull($instance->description); + + $instance->description = $options['description']; + if (empty($options['description'])) { + self::assertFalse($instance->hasDescription()); + self::assertNull($instance->getDescription()); + self::assertNull($instance->description); + } else { + self::assertTrue($instance->hasDescription()); + self::assertEquals($options['description'], $instance->getDescription()); + self::assertEquals($options['description'], $instance->description); + } + } + + /** + * @dataProvider invalidCommentDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidComment($value) + { + $instance = new CreateRefundRequest(); + $instance->setDescription($value); + } + + /** + * @dataProvider invalidCommentDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidComment($value) + { + $instance = new CreateRefundRequest(); + $instance->description = $value; + } + + public function testValidate() + { + $instance = new CreateRefundRequest(); + + self::assertFalse($instance->validate()); + $instance->setAmount(new MonetaryAmount()); + self::assertFalse($instance->validate()); + $instance->setAmount(new MonetaryAmount(Random::int(1, 100000))); + self::assertFalse($instance->validate()); + $instance->setPaymentId(Random::str(36)); + self::assertTrue($instance->validate()); + + $receipt = new Receipt(); + $instance->setReceipt($receipt); + $item = new ReceiptItem(); + $item->setPrice(new MonetaryAmount(10)); + $item->setDescription('test'); + $receipt->addItem($item); + self::assertFalse($instance->validate()); + $receipt->getCustomer()->setPhone('123123'); + self::assertTrue($instance->validate()); + $item->setVatCode(3); + self::assertTrue($instance->validate()); + $receipt->setTaxSystemCode(4); + self::assertTrue($instance->validate()); + } + + /** + * @dataProvider invalidReceiptDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidReceipt($value) + { + $instance = new CreateRefundRequest(); + $instance->setReceipt($value); + } + + /** + * @dataProvider invalidReceiptDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidReceipt($value) + { + $instance = new CreateRefundRequest(); + $instance->receipt = $value; + } + + public function invalidReceiptDataProvider() + { + return array( + array(''), + array(1), + array('test'), + array(true), + array(false), + array(new \stdClass()), + ); + } + + public function testBuilder() + { + $builder = CreateRefundRequest::builder(); + self::assertTrue($builder instanceof CreateRefundRequestBuilder); + } + + public function validDataProvider() + { + $result = array( + array( + array( + 'paymentId' => Random::str(36), + 'amount' => new MonetaryAmount(mt_rand(1, 100)), + 'description' => null, + ) + ), + array( + array( + 'paymentId' => Random::str(36), + 'amount' => new MonetaryAmount(mt_rand(1, 100)), + 'description' => '', + ) + ) + ); + for ($i = 0; $i < 10; $i++) { + $request = array( + 'paymentId' => Random::str(36), + 'amount' => new MonetaryAmount(mt_rand(1, 100)), + 'description' => uniqid(), + ); + $result[] = array($request); + } + return $result; + } + + public function invalidPaymentIdDataProvider() + { + return array( + array(''), + array(null), + array(array()), + array(1), + array(new \stdClass()), + array(Random::str(35)), + array(Random::str(37)), + ); + } + + public function invalidCommentDataProvider() + { + return array( + array(array()), + array(new \stdClass()), + ); + } +} \ No newline at end of file diff --git a/tests/Request/Refunds/CreateRefundResponseTest.php b/tests/Request/Refunds/CreateRefundResponseTest.php new file mode 100644 index 00000000..6dbdf676 --- /dev/null +++ b/tests/Request/Refunds/CreateRefundResponseTest.php @@ -0,0 +1,17 @@ +build(); + self::assertNull($instance->getPaymentId()); + + $builder->setPaymentId($options['paymentId']); + $instance = $builder->build(); + if (empty($options['paymentId'])) { + self::assertNull($instance->getPaymentId()); + } else { + self::assertEquals($options['paymentId'], $instance->getPaymentId()); + } + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSetCreateAtGte($options) + { + $builder = new RefundsRequestBuilder(); + + $instance = $builder->build(); + self::assertNull($instance->getCreatedAtGte()); + + $builder->setCreatedAtGte($options['createAtGte']); + $instance = $builder->build(); + if (empty($options['createAtGte'])) { + self::assertNull($instance->getCreatedAtGte()); + } else { + self::assertEquals($options['createAtGte'], $instance->getCreatedAtGte()->format(DATE_ATOM)); + } + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSetCreateAtGt($options) + { + $builder = new RefundsRequestBuilder(); + + $instance = $builder->build(); + self::assertNull($instance->getCreatedAtGt()); + + $builder->setCreatedAtGt($options['createAtGt']); + $instance = $builder->build(); + if (empty($options['createAtGt'])) { + self::assertNull($instance->getCreatedAtGt()); + } else { + self::assertEquals($options['createAtGt'], $instance->getCreatedAtGt()->format(DATE_ATOM)); + } + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSetCreateAtLte($options) + { + $builder = new RefundsRequestBuilder(); + + $instance = $builder->build(); + self::assertNull($instance->getCreatedAtLte()); + + $builder->setCreatedAtLte($options['createAtLte']); + $instance = $builder->build(); + if (empty($options['createAtLte'])) { + self::assertNull($instance->getCreatedAtLte()); + } else { + self::assertEquals($options['createAtLte'], $instance->getCreatedAtLte()->format(DATE_ATOM)); + } + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSetCreateAtLt($options) + { + $builder = new RefundsRequestBuilder(); + + $instance = $builder->build(); + self::assertNull($instance->getCreatedAtLt()); + + $builder->setCreatedAtLt($options['createAtLt']); + $instance = $builder->build(); + if (empty($options['createAtLt'])) { + self::assertNull($instance->getCreatedAtLt()); + } else { + self::assertEquals($options['createAtLt'], $instance->getCreatedAtLt()->format(DATE_ATOM)); + } + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSetStatus($options) + { + $builder = new RefundsRequestBuilder(); + + $instance = $builder->build(); + self::assertNull($instance->getStatus()); + + $builder->setStatus($options['status']); + $instance = $builder->build(); + if (empty($options['status'])) { + self::assertNull($instance->getStatus()); + } else { + self::assertEquals($options['status'], $instance->getStatus()); + } + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSetCursor($options) + { + $builder = new RefundsRequestBuilder(); + + $instance = $builder->build(); + self::assertNull($instance->getCursor()); + + $builder->setCursor($options['cursor']); + $instance = $builder->build(); + if (empty($options['cursor'])) { + self::assertNull($instance->getCursor()); + } else { + self::assertEquals($options['cursor'], $instance->getCursor()); + } + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSetLimit($options) + { + $builder = new RefundsRequestBuilder(); + + $instance = $builder->build(); + self::assertNull($instance->getLimit()); + + $builder->setLimit($options['limit']); + $instance = $builder->build(); + if (empty($options['limit'])) { + self::assertNull($instance->getLimit()); + } else { + self::assertEquals($options['limit'], $instance->getLimit()); + } + } + + public function validDataProvider() + { + $result = array( + array( + array( + 'paymentId' => null, + 'createAtGte' => null, + 'createAtGt' => null, + 'createAtLte' => null, + 'createAtLt' => null, + 'status' => null, + 'cursor' => null, + 'limit' => 1, + ), + ), + array( + array( + 'paymentId' => '', + 'createAtGte' => '', + 'createAtGt' => '', + 'createAtLte' => '', + 'createAtLt' => '', + 'status' => '', + 'cursor' => '', + 'limit' => null, + ), + ), + ); + $statuses = RefundStatus::getValidValues(); + for ($i = 0; $i < 10; $i++) { + $request = array( + 'paymentId' => $this->randomString(36), + 'createAtGte' => date(DATE_ATOM, mt_rand(1, time())), + 'createAtGt' => date(DATE_ATOM, mt_rand(1, time())), + 'createAtLte' => date(DATE_ATOM, mt_rand(1, time())), + 'createAtLt' => date(DATE_ATOM, mt_rand(1, time())), + 'status' => $statuses[mt_rand(0, count($statuses) - 1)], + 'cursor' => uniqid(), + 'limit' => mt_rand(1, RefundsRequest::MAX_LIMIT_VALUE), + ); + $result[] = array($request); + } + return $result; + } + + private function randomString($length, $any = true) + { + static $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-+_.'; + + $result = ''; + for ($i = 0; $i < $length; $i++) { + if ($any) { + $char = chr(mt_rand(32, 126)); + } else { + $rnd = mt_rand(0, strlen($chars) - 1); + $char = substr($chars, $rnd, 1); + } + $result .= $char; + } + return $result; + } +} \ No newline at end of file diff --git a/tests/Request/Refunds/RefundsRequestSerializerTest.php b/tests/Request/Refunds/RefundsRequestSerializerTest.php new file mode 100644 index 00000000..d19fd019 --- /dev/null +++ b/tests/Request/Refunds/RefundsRequestSerializerTest.php @@ -0,0 +1,98 @@ + 'payment_id', + 'createdAtGte' => 'created_at.gte', + 'createdAtGt' => 'created_at.gt', + 'createdAtLte' => 'created_at.lte', + 'createdAtLt' => 'created_at.lt', + 'status' => 'status', + 'cursor' => 'cursor', + 'limit' => 'limit', + ); + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testSerialize($options) + { + $serializer = new RefundsRequestSerializer(); + $data = $serializer->serialize(RefundsRequest::builder()->build($options)); + + $expected = array(); + foreach ($this->fieldMap as $field => $mapped) { + if (isset($options[$field])) { + $value = $options[$field]; + if (!empty($value)) { + $expected[$mapped] = $value instanceof \DateTime ? $value->format(DATE_ATOM) : $value; + } + } + } + self::assertEquals($expected, $data); + } + + public function validDataProvider() + { + $result = array( + array( + array( + 'accountId' => uniqid(), + ), + ), + array( + array( + 'paymentId' => '', + 'createAtGte' => '', + 'createAtGt' => '', + 'createAtLte' => '', + 'createAtLt' => '', + 'status' => '', + 'cursor' => '', + 'limit' => '', + ), + ), + ); + $statuses = RefundStatus::getValidValues(); + for ($i = 0; $i < 10; $i++) { + $request = array( + 'paymentId' => $this->randomString(36), + 'createAtGte' => date(DATE_ATOM, mt_rand(1, time())), + 'createAtGt' => date(DATE_ATOM, mt_rand(1, time())), + 'createAtLte' => date(DATE_ATOM, mt_rand(1, time())), + 'createAtLt' => date(DATE_ATOM, mt_rand(1, time())), + 'status' => $statuses[mt_rand(0, count($statuses) - 1)], + 'cursor' => uniqid(), + 'limit' => mt_rand(1, RefundsRequest::MAX_LIMIT_VALUE), + ); + $result[] = array($request); + } + return $result; + } + + private function randomString($length, $any = true) + { + static $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-+_.'; + + $result = ''; + for ($i = 0; $i < $length; $i++) { + if ($any) { + $char = chr(mt_rand(32, 126)); + } else { + $rnd = mt_rand(0, strlen($chars) - 1); + $char = substr($chars, $rnd, 1); + } + $result .= $char; + } + return $result; + } +} \ No newline at end of file diff --git a/tests/Request/Refunds/RefundsRequestTest.php b/tests/Request/Refunds/RefundsRequestTest.php new file mode 100644 index 00000000..15db4c02 --- /dev/null +++ b/tests/Request/Refunds/RefundsRequestTest.php @@ -0,0 +1,639 @@ +hasPaymentId()); + self::assertNull($instance->getPaymentId()); + self::assertNull($instance->paymentId); + + $instance->setPaymentId($options['payment_id']); + if (empty($options['payment_id'])) { + self::assertFalse($instance->hasPaymentId()); + self::assertNull($instance->getPaymentId()); + self::assertNull($instance->paymentId); + } else { + self::assertTrue($instance->hasPaymentId()); + self::assertEquals($options['payment_id'], $instance->getPaymentId()); + self::assertEquals($options['payment_id'], $instance->paymentId); + } + + $instance->setPaymentId(''); + self::assertFalse($instance->hasPaymentId()); + self::assertNull($instance->getPaymentId()); + self::assertNull($instance->paymentId); + + $instance->paymentId = $options['payment_id']; + if (empty($options['payment_id'])) { + self::assertFalse($instance->hasPaymentId()); + self::assertNull($instance->getPaymentId()); + self::assertNull($instance->paymentId); + } else { + self::assertTrue($instance->hasPaymentId()); + self::assertEquals($options['payment_id'], $instance->getPaymentId()); + self::assertEquals($options['payment_id'], $instance->paymentId); + } + } + + /** + * @dataProvider invalidPaymentIdDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidPaymentId($value) + { + $instance = new RefundsRequest(); + $instance->setPaymentId($value); + } + + /** + * @dataProvider invalidPaymentIdDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidPaymentId($value) + { + $instance = new RefundsRequest(); + $instance->paymentId = $value; + } + + /** + * @return array + */ + public function validStringDataProvider() + { + return array( + array(array()), + array(true), + array(false), + array(new \stdClass()), + ); + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testCreateGte($options) + { + $instance = new RefundsRequest(); + + self::assertFalse($instance->hasCreatedAtGte()); + self::assertNull($instance->getCreatedAtGte()); + self::assertNull($instance->createdAtGte); + + $instance->setCreatedAtGte($options['created_at_gte']); + if (empty($options['created_at_gte'])) { + self::assertFalse($instance->hasCreatedAtGte()); + self::assertNull($instance->getCreatedAtGte()); + self::assertNull($instance->createdAtGte); + } else { + self::assertTrue($instance->hasCreatedAtGte()); + self::assertEquals($options['created_at_gte'], $instance->getCreatedAtGte()->format(DATE_ATOM)); + self::assertEquals($options['created_at_gte'], $instance->createdAtGte->format(DATE_ATOM)); + } + + $instance->setCreatedAtGte(''); + self::assertFalse($instance->hasCreatedAtGte()); + self::assertNull($instance->getCreatedAtGte()); + self::assertNull($instance->createdAtGte); + + $instance->createdAtGte = $options['created_at_gte']; + if (empty($options['created_at_gte'])) { + self::assertFalse($instance->hasCreatedAtGte()); + self::assertNull($instance->getCreatedAtGte()); + self::assertNull($instance->createdAtGte); + } else { + self::assertTrue($instance->hasCreatedAtGte()); + self::assertEquals($options['created_at_gte'], $instance->getCreatedAtGte()->format(DATE_ATOM)); + self::assertEquals($options['created_at_gte'], $instance->createdAtGte->format(DATE_ATOM)); + } + } + + /** + * @dataProvider invalidDateDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidCreatedGte($value) + { + $instance = new RefundsRequest(); + $instance->setCreatedAtGte($value); + } + + /** + * @dataProvider invalidDateDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidCreatedGte($value) + { + $instance = new RefundsRequest(); + $instance->createdAtGte = $value; + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testCreateGt($options) + { + $instance = new RefundsRequest(); + + self::assertFalse($instance->hasCreatedAtGt()); + self::assertNull($instance->getCreatedAtGt()); + self::assertNull($instance->createdAtGt); + + $instance->setCreatedAtGt($options['created_at_gt']); + if (empty($options['created_at_gt'])) { + self::assertFalse($instance->hasCreatedAtGte()); + self::assertNull($instance->getCreatedAtGte()); + self::assertNull($instance->createdAtGte); + } else { + self::assertTrue($instance->hasCreatedAtGt()); + self::assertEquals($options['created_at_gt'], $instance->getCreatedAtGt()->format(DATE_ATOM)); + self::assertEquals($options['created_at_gt'], $instance->createdAtGt->format(DATE_ATOM)); + } + + $instance->setCreatedAtGt(''); + self::assertFalse($instance->hasCreatedAtGt()); + self::assertNull($instance->getCreatedAtGt()); + self::assertNull($instance->createdAtGt); + + $instance->createdAtGt = $options['created_at_gt']; + if (empty($options['created_at_gt'])) { + self::assertFalse($instance->hasCreatedAtGt()); + self::assertNull($instance->getCreatedAtGt()); + self::assertNull($instance->createdAtGt); + } else { + self::assertTrue($instance->hasCreatedAtGt()); + self::assertEquals($options['created_at_gt'], $instance->getCreatedAtGt()->format(DATE_ATOM)); + self::assertEquals($options['created_at_gt'], $instance->createdAtGt->format(DATE_ATOM)); + } + } + + /** + * @dataProvider invalidDateDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidCreatedGt($value) + { + $instance = new RefundsRequest(); + $instance->setCreatedAtGt($value); + } + + /** + * @dataProvider invalidDateDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidCreatedGt($value) + { + $instance = new RefundsRequest(); + $instance->createdAtGt = $value; + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testCreateLte($options) + { + $instance = new RefundsRequest(); + + self::assertFalse($instance->hasCreatedAtLte()); + self::assertNull($instance->getCreatedAtLte()); + self::assertNull($instance->createdAtLte); + + $instance->setCreatedAtLte($options['created_at_lte']); + if (empty($options['created_at_lte'])) { + self::assertFalse($instance->hasCreatedAtLte()); + self::assertNull($instance->getCreatedAtLte()); + self::assertNull($instance->createdAtLte); + } else { + self::assertTrue($instance->hasCreatedAtLte()); + self::assertEquals($options['created_at_lte'], $instance->getCreatedAtLte()->format(DATE_ATOM)); + self::assertEquals($options['created_at_lte'], $instance->createdAtLte->format(DATE_ATOM)); + } + + $instance->setCreatedAtLte(''); + self::assertFalse($instance->hasCreatedAtLte()); + self::assertNull($instance->getCreatedAtLte()); + self::assertNull($instance->createdAtLte); + + $instance->createdAtLte = $options['created_at_lte']; + if (empty($options['created_at_lte'])) { + self::assertFalse($instance->hasCreatedAtLte()); + self::assertNull($instance->getCreatedAtLte()); + self::assertNull($instance->createdAtLte); + } else { + self::assertTrue($instance->hasCreatedAtLte()); + self::assertEquals($options['created_at_lte'], $instance->getCreatedAtLte()->format(DATE_ATOM)); + self::assertEquals($options['created_at_lte'], $instance->createdAtLte->format(DATE_ATOM)); + } + } + + /** + * @dataProvider invalidDateDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidCreatedLte($value) + { + $instance = new RefundsRequest(); + $instance->setCreatedAtLte($value); + } + + /** + * @dataProvider invalidDateDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidCreatedLte($value) + { + $instance = new RefundsRequest(); + $instance->createdAtLte = $value; + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testCreateLt($options) + { + $instance = new RefundsRequest(); + + self::assertFalse($instance->hasCreatedAtLt()); + self::assertNull($instance->getCreatedAtLt()); + self::assertNull($instance->createdAtLt); + + $instance->setCreatedAtLt($options['created_at_lt']); + if (empty($options['created_at_lt'])) { + self::assertFalse($instance->hasCreatedAtLt()); + self::assertNull($instance->getCreatedAtLt()); + self::assertNull($instance->createdAtLt); + } else { + self::assertTrue($instance->hasCreatedAtLt()); + self::assertEquals($options['created_at_lt'], $instance->getCreatedAtLt()->format(DATE_ATOM)); + self::assertEquals($options['created_at_lt'], $instance->createdAtLt->format(DATE_ATOM)); + } + + $instance->setCreatedAtLt(''); + self::assertFalse($instance->hasCreatedAtLt()); + self::assertNull($instance->getCreatedAtLt()); + self::assertNull($instance->createdAtLt); + + $instance->createdAtLt = $options['created_at_lt']; + if (empty($options['created_at_lt'])) { + self::assertFalse($instance->hasCreatedAtLt()); + self::assertNull($instance->getCreatedAtLt()); + self::assertNull($instance->createdAtLt); + } else { + self::assertTrue($instance->hasCreatedAtLt()); + self::assertEquals($options['created_at_lt'], $instance->getCreatedAtLt()->format(DATE_ATOM)); + self::assertEquals($options['created_at_lt'], $instance->createdAtLt->format(DATE_ATOM)); + } + } + + /** + * @dataProvider invalidDateDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetInvalidCreatedLt($value) + { + $instance = new RefundsRequest(); + $instance->setCreatedAtLt($value); + } + + /** + * @dataProvider invalidDateDataProvider + * @expectedException \InvalidArgumentException + * @param mixed $value + */ + public function testSetterInvalidCreatedLt($value) + { + $instance = new RefundsRequest(); + $instance->createdAtLt = $value; + } + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testStatus($options) + { + $instance = new RefundsRequest(); + + self::assertFalse($instance->hasStatus()); + self::assertNull($instance->getStatus()); + self::assertNull($instance->status); + + $instance->setStatus($options['status']); + if (empty($options['status'])) { + self::assertFalse($instance->hasStatus()); + self::assertNull($instance->getStatus()); + self::assertNull($instance->status); + } else { + self::assertTrue($instance->hasStatus()); + self::assertEquals($options['status'], $instance->getStatus()); + self::assertEquals($options['status'], $instance->status); + } + + $instance->setStatus(''); + self::assertFalse($instance->hasStatus()); + self::assertNull($instance->getStatus()); + self::assertNull($instance->status); + + $instance->status = $options['status']; + if (empty($options['status'])) { + self::assertFalse($instance->hasStatus()); + self::assertNull($instance->getStatus()); + self::assertNull($instance->status); + } else { + self::assertTrue($instance->hasStatus()); + self::assertEquals($options['status'], $instance->getStatus()); + self::assertEquals($options['status'], $instance->status); + } + } + + /** + * @dataProvider invalidStatusDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidStatus($value) + { + $instance = new RefundsRequest(); + $instance->setStatus($value); + } + + /** + * @dataProvider invalidStatusDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidStatus($value) + { + $instance = new RefundsRequest(); + $instance->status = $value; + self::assertEquals($value, $instance->status); + } + + /** + * @dataProvider validLimitDataProvider + * @param $value + */ + public function testLimit($value) + { + $instance = new RefundsRequest(); + $instance->limit = $value; + self::assertEquals($value, $instance->limit); + } + + /** + * @dataProvider invalidLimitDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidLimit($value) + { + $instance = new RefundsRequest(); + $instance->setLimit($value); + } + + + /** + * @dataProvider validDataProvider + * @param $options + */ + public function testCursor($options) + { + $instance = new RefundsRequest(); + + self::assertFalse($instance->hasCursor()); + self::assertNull($instance->getCursor()); + self::assertNull($instance->cursor); + + $instance->setCursor($options['cursor']); + if (empty($options['cursor'])) { + self::assertFalse($instance->hasCursor()); + self::assertNull($instance->getCursor()); + self::assertNull($instance->cursor); + } else { + self::assertTrue($instance->hasCursor()); + self::assertEquals($options['cursor'], $instance->getCursor()); + self::assertEquals($options['cursor'], $instance->cursor); + } + + $instance->setCursor(''); + self::assertFalse($instance->hasCursor()); + self::assertNull($instance->getCursor()); + self::assertNull($instance->cursor); + + $instance->cursor = $options['cursor']; + if (empty($options['cursor'])) { + self::assertFalse($instance->hasCursor()); + self::assertNull($instance->getCursor()); + self::assertNull($instance->cursor); + } else { + self::assertTrue($instance->hasCursor()); + self::assertEquals($options['cursor'], $instance->getCursor()); + self::assertEquals($options['cursor'], $instance->cursor); + } + } + + /** + * @dataProvider invalidNextCursorDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetInvalidCursor($value) + { + $instance = new RefundsRequest(); + $instance->setCursor($value); + } + + /** + * @dataProvider invalidNextCursorDataProvider + * @expectedException \InvalidArgumentException + * @param $value + */ + public function testSetterInvalidCursor($value) + { + $instance = new RefundsRequest(); + $instance->cursor = $value; + } + + public function testValidate() + { + $instance = new RefundsRequest(); + + self::assertTrue($instance->validate()); + } + + public function testBuilder() + { + $builder = RefundsRequest::builder(); + self::assertTrue($builder instanceof RefundsRequestBuilder); + } + + public function validDataProvider() + { + $result = array( + array( + array( + 'created_at_gte' => null, + 'created_at_gt' => null, + 'created_at_lte' => null, + 'created_at_lt' => null, + 'status' => null, + 'payment_id' => null, + 'limit' => null, + 'cursor' => null, + ), + ), + array( + array( + 'created_at_gte' => '', + 'created_at_gt' => '', + 'created_at_lte' => '', + 'created_at_lt' => '', + 'status' => '', + 'payment_id' => '', + 'limit' => '', + 'cursor' => '', + ), + ), + ); + $statuses = RefundStatus::getValidValues(); + for ($i = 0; $i < 10; $i++) { + $request = array( + 'created_at_gte' => date(DATE_ATOM, mt_rand(1, time())), + 'created_at_gt' => date(DATE_ATOM, mt_rand(1, time())), + 'created_at_lte' => date(DATE_ATOM, mt_rand(1, time())), + 'created_at_lt' => date(DATE_ATOM, mt_rand(1, time())), + 'status' => $statuses[mt_rand(0, count($statuses) - 1)], + 'payment_id' => $this->randomString(36), + 'limit' => mt_rand(0, RefundsRequest::MAX_LIMIT_VALUE), + 'cursor' => uniqid(), + ); + $result[] = array($request); + } + return $result; + } + + public function invalidStatusDataProvider() + { + return array( + array(true), + array(false), + array(array()), + array(new \stdClass()), + array(Random::str(1, 10)), + array(new StringObject(Random::str(1, 10))), + ); + } + + public function validLimitDataProvider() + { + return array( + array(null), + array(Random::int(1, RefundsRequest::MAX_LIMIT_VALUE)), + ); + } + + public function invalidLimitDataProvider() + { + return array( + array(array()), + array(new \stdClass()), + array(-1), + array(RefundsRequest::MAX_LIMIT_VALUE + 1), + ); + } + + public function invalidDataProvider() + { + $result = array( + array(array()), + array(new \stdClass()), + array(Random::str(10)), + array(Random::bytes(10)), + array(-1), + array(RefundsRequest::MAX_LIMIT_VALUE + 1), + ); + return $result; + } + + public function invalidNextCursorDataProvider() + { + return array( + array(true), + array(false), + array(array()), + array(new \stdClass()), + ); + } + + public function invalidPaymentIdDataProvider() + { + return array( + array(true), + array(false), + array(array()), + array(new \stdClass()), + array(Random::str(35)), + array(Random::str(37)), + array(new StringObject(Random::str(10))), + ); + } + + public function invalidDateDataProvider() + { + return array( + array(true), + array(false), + array(array()), + array(new \stdClass()), + array(Random::str(35)), + array(Random::str(37)), + array(new StringObject(Random::str(10))), + array(-123), + ); + } + + private function randomString($length, $any = true) + { + static $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-+_.'; + + $result = ''; + for ($i = 0; $i < $length; $i++) { + if ($any) { + $char = chr(mt_rand(32, 126)); + } else { + $rnd = mt_rand(0, strlen($chars) - 1); + $char = substr($chars, $rnd, 1); + } + $result .= $char; + } + return $result; + } +} \ No newline at end of file diff --git a/tests/Request/Refunds/RefundsResponseTest.php b/tests/Request/Refunds/RefundsResponseTest.php new file mode 100644 index 00000000..5bc83184 --- /dev/null +++ b/tests/Request/Refunds/RefundsResponseTest.php @@ -0,0 +1,120 @@ +getItems())); + foreach ($instance->getItems() as $index => $item) { + self::assertTrue($item instanceof RefundInterface); + self::assertArrayHasKey($index, $options['items']); + self::assertEquals($options['items'][$index]['id'], $item->getId()); + self::assertEquals($options['items'][$index]['payment_id'], $item->getPaymentId()); + self::assertEquals($options['items'][$index]['status'], $item->getStatus()); + self::assertEquals($options['items'][$index]['amount']['value'], $item->getAmount()->getValue()); + self::assertEquals($options['items'][$index]['amount']['currency'], $item->getAmount()->getCurrency()); + self::assertEquals($options['items'][$index]['created_at'], $item->getCreatedAt()->format(DATE_ATOM)); + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testGetNextCursor($options) + { + $instance = new RefundsResponse($options); + if (empty($options['next_cursor'])) { + self::assertNull($instance->getNextCursor()); + } else { + self::assertEquals($options['next_cursor'], $instance->getNextCursor()); + } + } + + /** + * @dataProvider validDataProvider + * @param array $options + */ + public function testHasNextCursor($options) + { + $instance = new RefundsResponse($options); + if (empty($options['next_cursor'])) { + self::assertFalse($instance->hasNextCursor()); + } else { + self::assertTrue($instance->hasNextCursor()); + } + } + + public function validDataProvider() + { + return array( + array( + array( + 'items' => array(), + ), + ), + array( + array( + 'items' => array( + array( + 'id' => Random::str(36), + 'payment_id' => Random::str(36), + 'status' => RefundStatus::SUCCEEDED, + 'amount' => array( + 'value' => Random::int(1, 100), + 'currency' => Random::value(CurrencyCode::getValidValues()), + ), + 'created_at' => date(DATE_ATOM, Random::int(0, time())), + ) + ), + 'next_cursor' => Random::str(1, 64), + ), + ), + array( + array( + 'items' => array( + array( + 'id' => Random::str(36), + 'payment_id' => Random::str(36), + 'status' => RefundStatus::SUCCEEDED, + 'amount' => array( + 'value' => Random::int(1, 100), + 'currency' => Random::value(CurrencyCode::getValidValues()), + ), + 'created_at' => date(DATE_ATOM), + ), + array( + 'id' => Random::str(36), + 'payment_id' => Random::str(36), + 'status' => RefundStatus::SUCCEEDED, + 'amount' => array( + 'value' => Random::int(1, 100), + 'currency' => Random::value(CurrencyCode::getValidValues()), + ), + 'created_at' => date(DATE_ATOM, Random::int(0, time())), + 'authorized_at' => date(DATE_ATOM, Random::int(0, time())), + 'receipt_registered' => Random::value(ReceiptRegistrationStatus::getValidValues()), + 'description' => Random::str(64, 250), + ), + ), + 'next_cursor' => Random::str(1, 64), + ), + ), + ); + } +} \ No newline at end of file