Download the PHP package kosovopay/php-sdk without Composer

On this page you can find all versions of the php package kosovopay/php-sdk. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package php-sdk

# KosovoPay PHP SDK **The official, strongly-typed PHP client for the [KosovoPay](https://kosovo.sh) payment API.** ๐Ÿ“– **API reference:** https://pay.kosovo.sh/docs Built on [Saloon v3](https://docs.saloon.dev) ยท PHPStan level max ยท 100% typed request & response objects [![PHP Version](https://img.shields.io/badge/php-%E2%89%A58.2-777BB4)](https://www.php.net/) [![Static Analysis](https://img.shields.io/badge/PHPStan-level%20max-2a2a2a)](https://phpstan.org/) [![Code Style](https://img.shields.io/badge/code%20style-Pint-FF2D20)](https://laravel.com/docs/pint) [![License](https://img.shields.io/badge/license-KosovoPay%201.0-3da639)](LICENSE)

Table of contents


Why this SDK

Typed end to end Every request is a readonly params object; every response is a readonly DTO with enum-typed fields. No associative-array guessing, no stringly-typed statuses.
Forward compatible Unknown enum values โ€” a bank or event type the platform adds after you ship โ€” decode to an Unknown case instead of throwing. Old SDK versions keep working.
Safe by construction Mutating calls carry an idempotency key automatically. Retries use exponential backoff, and a mutating 5xx is never retried without an idempotency key โ€” a network blip can't double-charge a customer.
Typed errors The server error envelope maps to a precise exception class (ValidationException, RateLimitException, PaymentException subclasses, โ€ฆ), each carrying errorCode, errorType, param, requestId and docUrl.
Statically verified PHPStan level max, Pint-clean, 29 tests covering every resource, idempotency, pagination, error mapping and webhook signature verification.

Requirements


Installation

That's it โ€” no service providers, no config publishing. The client is a plain object you construct with your API key.


Authentication & client setup

Authenticate with a secret key from your KosovoPay dashboard. Keys are environment-scoped โ€” sk_test_โ€ฆ for the test sandbox, sk_live_โ€ฆ for production.

The constructor accepts the full configuration surface; every argument after the key is optional and shown here with its default:

Never hard-code a live key. Load it from the environment or your secrets manager:


Quickstart

Create a hosted checkout and redirect the buyer to KosovoPay's payment page:

When the buyer finishes, KosovoPay sends a payment.captured webhook and redirects them to your successUrl.


Core concepts

Minor units

All monetary amounts are integers in the currency's minor unit โ€” cents for EUR/USD, etc. There are no floats anywhere in the money path, which eliminates rounding drift.

Display Pass as
โ‚ฌ49.90 4990
$5.00 500
ยฅ1200 (JPY, zero-decimal) 1200

Use Money::format() to render a minor-unit integer back to a human string.

Hosted vs. direct checkout

The SDK supports two checkout modes via the CheckoutMode enum:

Mode What happens You use
CheckoutMode::Hosted (default) KosovoPay renders the payment page and bank selection. $payment->hostedUrl
CheckoutMode::Direct You pick the bank up front; KosovoPay returns a bank redirect URL. Requires bankCode. $payment->redirectUrl

Idempotency

Every mutating call (payments->create, refunds->create) accepts an optional idempotency key. If you omit it, the SDK generates a ULID automatically, so an in-flight retry never creates a duplicate charge. Supply your own key (e.g. your order ID) to make the operation idempotent across your retries too:

A key is valid for 24 hours. Reusing it with a different payload raises an IdempotencyException.

API versioning

The API is date-versioned. The SDK pins a version via the Kosovopay-Version header (default 2026-06-01) so the response shape never changes underneath you. Upgrade deliberately by bumping apiVersion in the constructor after reading the changelog.


Payments

Create โ€” hosted checkout

Create โ€” direct checkout

You select the bank; KosovoPay returns a redirect straight to it. bankCode is required in this mode.

The params object validates itself on construction. Passing mode: Direct without a bankCode, a non-positive amount, or a non-HTTP(S) successUrl throws InvalidArgumentException before any network call.

Retrieve

List & paginate

payments->all() returns a lazy iterator that transparently walks every page using cursor pagination โ€” you never touch starting_after:

Filter options on ListPaymentsParams: status, bankCode, currency, merchantReference, createdGte, createdLte, limit, startingAfter, endingBefore.

Timeline

A chronological audit trail for a single payment, returned as a typed Collection<TimelineEvent>:

Cancel

Cancelling a payment that is no longer cancelable raises PaymentNotCancelableException.


Refunds

Create

Omit amount for a full refund; pass a value in minor units for a partial refund.

Not every bank supports partial refunds. Check $bank->capabilities->refunds->partial first (see Banks) โ€” a partial refund to an unsupported bank raises PartialRefundUnsupportedException. Refunding more than the remaining balance raises RefundExceedsRemainingException.

Retrieve

List


Banks

Supported banks: BankCode::Procredit, BankCode::Procard, BankCode::Onefor.


Currencies & FX rates

Pair the rate with Money::convert() for exact minor-unit conversion.


Account (me)

Identify the key in use โ€” its team, environment, usable banks and default currency:

keyPrefix is the only key material safe to log โ€” it identifies the key without exposing the secret.


Webhooks

KosovoPay notifies your server of events (a captured payment, a succeeded refund) by POSTing a signed JSON event to your endpoint. Always verify the signature before trusting the payload.

Verifying a webhook

constructEvent() does three things: verifies the HMAC-SHA256 signature in constant time, enforces a 5-minute replay window on the timestamp, and decodes the raw body into a typed Event. The signed payload is "{timestamp}.{raw_body}" โ€” which is why you must verify against the unmodified request body.

The signature header is exposed as a constant if you need it: Webhook::SIGNATURE_HEADER ("Kosovopay-Signature"). Adjust the replay tolerance with the fourth argument: Webhook::constructEvent($payload, $sig, $secret, tolerance: 600).

The decoded Event exposes id, type, created, livemode, apiVersion, the raw object, and previousAttributes. Use $event->asPayment() / $event->asRefund() to hydrate the affected resource into its typed DTO, and $event->createdAt() for a DateTimeImmutable.

Framework integration

Laravel

Symfony

Event types

WebhookEventType Wire value $event->asโ€ฆ()
PaymentCreated payment.created asPayment()
PaymentCaptured payment.captured asPayment()
PaymentFailed payment.failed asPayment()
PaymentCanceled payment.canceled asPayment()
PaymentExpired payment.expired asPayment()
RefundSucceeded refund.succeeded asRefund()
RefundFailed refund.failed asRefund()

Any event type added in the future arrives as WebhookEventType::Unknown โ€” handle it with a default arm rather than a crash.

Managing webhook endpoints

Register, list, rotate, and delete endpoints programmatically:


Helpers

Money formatting & conversion

Local amount validation

Catch amount_below_minimum / amount_step_invalid before a round-trip by checking an amount against a bank's live capabilities:


Error handling

Every non-2xx response is converted into a typed exception. Catch the specific subclass you care about, or the KosovoPayException base for a catch-all. Every exception carries the full error envelope.

Every KosovoPayException exposes:

Property Type Meaning
getMessage() string Human-readable summary
errorCode ?string Stable machine code, e.g. amount_below_minimum
errorType ?string Error family, e.g. validation_error
param ?string The offending request field, when applicable
requestId ?string Correlation id โ€” always include this in support tickets
docUrl ?string Link to the docs for this error
statusCode int HTTP status
retryAfter (RateLimitException only) ?int Seconds to wait before retrying

Exception hierarchy

Resolution order: an exact code match wins; otherwise the error type family is used; otherwise it falls back to ApiException. An unrecognised code from a newer API never crashes the SDK.

Error codes

Code Maps to Notes
missing_key, invalid_key AuthenticationException
invalid_request ValidationException check ->param
resource_missing ValidationException 404
unknown_api_version ValidationException bad Kosovopay-Version
currency_not_supported ValidationException
rate_unavailable ValidationException FX feed down
idempotency_payload_mismatch, idempotency_conflict IdempotencyException
rate_limited RateLimitException honour ->retryAfter
amount_below_minimum AmountBelowMinimumException
amount_step_invalid AmountStepInvalidException
bank_not_enabled BankNotEnabledException
bank_unreachable BankUnreachableException transient โ€” retryable
payment_not_cancelable PaymentNotCancelableException
payment_not_refundable PaymentNotRefundableException
refund_exceeds_remaining RefundExceedsRemainingException
partial_refund_unsupported PartialRefundUnsupportedException
internal_error ApiException

Type reference

Enums

Enum Cases
CheckoutMode Hosted, Direct
BankMode Test, Live
BankCode Procredit, Procard, Onefor, Unknown
CurrencyCode The full ISO 4217 circulating set (155 currencies) โ€” EUR, USD, GBP, JPY, CHF, CNY, AUD, CAD, โ€ฆ ALL, RSD, MKD, plus Unknown. Each case's value is its ISO code.
PaymentStatus Pending, Authorized, Captured, PartiallyRefunded, Refunded, Failed, Canceled, Unknown
RefundStatus Pending, Succeeded, Failed, Unknown
RefundReason RequestedByCustomer, Duplicate, Fraudulent, Other
WebhookEventType PaymentCreated, PaymentCaptured, PaymentFailed, PaymentCanceled, PaymentExpired, RefundSucceeded, RefundFailed, Unknown

Enums marked with Unknown are forward-compatible: any value the platform introduces later decodes to Unknown rather than throwing. Always include a default/Unknown arm when matching on them.

Key response objects

Payment โ€” id, status: PaymentStatus, mode: BankMode, amount, amountCaptured, amountRefunded, currency: CurrencyCode, bankCode: ?BankCode, merchantReference, description, payer: ?Payer, lineItems, metadata, fx: ?Fx, lastError, expires, captured, created, refunds, checkoutMode: ?CheckoutMode, hostedUrl, redirectUrl ยท methods: createdAt(): DateTimeImmutable

Refund โ€” id, payment, amount, status: RefundStatus, reason: ?RefundReason, failureReason, created, succeededAt ยท methods: createdAt(): ?DateTimeImmutable

Bank โ€” code: BankCode, displayName, logoUrl, enabled, modes, capabilities: BankCapabilities BankCapabilities โ€” currencies: list<CurrencyCode>, minAmount, amountStep, refunds: RefundCapability RefundCapability โ€” supported: bool, partial: bool

Currency โ€” code: CurrencyCode, name, symbol, decimals, isDefault Rate โ€” from: CurrencyCode, to: CurrencyCode, rate: string, syncedAt, stale Me โ€” team: Team, mode: BankMode, keyPrefix, enabledBanks: list<BankCode>, defaultCurrency: ?CurrencyCode WebhookEndpoint โ€” id, url, description, enabledEvents: list<WebhookEventType>, status, mode: BankMode, created, secret Event โ€” id, type: WebhookEventType, created, livemode, apiVersion, data, object, previousAttributes ยท methods: asPayment(), asRefund(), createdAt()

Single-page lists (banks, currencies, webhookEndpoints, payment timeline) return a typed Collection<T> implementing Countable and IteratorAggregate โ€” iterate it directly, call ->count(), or grab ->all() / ->data for the array. Paginated lists (payments, refunds) return a lazy iterator instead.


Retries, timeouts & resilience

The connector retries transient failures with exponential backoff, governed by maxRetries (default 3) and an internal 500 ms base interval (โ†’ ~0.5s, 1s, 2s).

Failure Retried?
Network / connection error โœ… always
429 Too Many Requests โœ… always
5xx on a GET/HEAD โœ…
5xx on a mutating call with an idempotency key โœ… (safe โ€” the key dedupes)
5xx on a mutating call without an idempotency key โŒ (could double-charge)
4xx (validation, auth, etc.) โŒ (deterministic โ€” won't change)

Because the SDK auto-attaches an idempotency key to every mutating call, your create operations are retried safely out of the box.

Tune timeouts via the constructor (connectTimeout, requestTimeout).


Testing

The client is backed by a Saloon connector, so you can swap in a MockClient and assert against requests โ€” no network, fully deterministic:


Development

The codebase is held to PHPStan level max with zero suppressions โ€” no @phpstan-ignore, no assert()-to-silence, no blind casts. Decoded JSON is narrowed through a dedicated coercion layer so types are real, not asserted.


Versioning & support


License

KosovoPay License 1.0 โ€” free to use, including commercially, at no charge. Modifying, forking, redistributing, or reverse-engineering the SDK is not permitted; it is maintained solely by KosovoPay. See LICENSE.


All versions of php-sdk with dependencies

PHP Build Version
Package Version
Requires php Version ^8.2
saloonphp/saloon Version ^3.0
saloonphp/pagination-plugin Version ^2.0
symfony/uid Version ^6.0 || ^7.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package kosovopay/php-sdk contains the following files

Loading the files please wait ...