Download the PHP package getpayin/paylink without Composer
On this page you can find all versions of the php package getpayin/paylink. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download getpayin/paylink
More information about getpayin/paylink
Files in getpayin/paylink
Package paylink
Short Description Official server-side PHP SDK for the PayLink payment integration API (checkouts, payment operations, card tokens, recurring mandates, webhook verification).
License MIT
Homepage https://github.com/GetPayin-Tech/paylink-php
Informations about the package paylink
@getpayin/paylink
Official server-side PHP SDK for the PayLink payment integration API — hosted checkouts, payment operations, card tokens, recurring mandates, and webhook verification.
The SDK signs every request exactly the way the PayLink servers expect, so you never reproduce the HMAC signing rules yourself. It is framework-agnostic (plain PHP, Symfony, Laravel, a queue worker) with no required Composer dependencies beyond ext-curl, ext-json, and PSR-3.
Requirements
- PHP 8.2+
ext-curl,ext-json
Installation
Quick start
Pass 'iframe' => true to enable embedded (iframe) checkout instead of a full-page redirect:
Then embed the returned checkout URL on your page. The <iframe> needs allow="payment *" so Apple Pay and Google Pay work inside the frame, and your page must listen for the completion message — in iframe mode the checkout signals the parent via postMessage instead of redirecting:
The embedding page's origin must exactly match your integration's registered Origin, or the browser blocks framing and the message never arrives.
Request parameters are passed as camelCase arrays; results come back as camelCase arrays.
Using Laravel? Don't construct the client by hand — inject the configured
PaylinkClientfrom the container instead. See Using it inside Laravel.
Payment operations
Card tokenization
For US and CA billing addresses, also pass the state fields the API requires: usState + postalCode (US) or canadaState + postalCode (CA).
Recurring mandates
Idempotency
Retrying a write after a network error or timeout risks performing it twice. To make that safe, pass an idempotencyKey — the SDK sends it as the Idempotency-Key header and the server returns the original result instead of charging, refunding, or creating a second time. Keys are scoped per integration and capped at 64 characters.
| Endpoint | A replay with the same key returns |
|---|---|
invoices->create |
the original invoice and checkoutUrl |
vcc->charge |
the original charge |
cards->charge |
the original charge |
payments->refund |
the original refund |
recurring->create |
the original mandate |
Reusing a key with a different request — for example recurring->create with changed terms, or payments->refund for a different amount — is rejected as a conflict: a PaylinkApiException whose isIdempotencyConflict() is true (HTTP 409). Only the endpoints above honor the header.
Verifying webhooks
Pass the raw request body (or a decoded array) to verify(). It recomputes the signature with your hashToken and compares in constant time, throwing PaylinkSignatureException on a mismatch.
PayLink webhook signatures carry no timestamp, so verification does not protect against replay. Pair it with your own idempotency keyed on
invoice_id.
Error handling
Every failure extends GetPayin\Paylink\Core\Exceptions\PaylinkException:
| Error | When |
|---|---|
PaylinkConfigException |
Invalid client configuration (missing tokens, non-positive timeout). |
PaylinkApiException |
The API returned an error. Carries status, errors, raw, retryAfterMs, and isIdempotencyConflict() (409), isRateLimited() (429), isForbidden() (403 — e.g. card tokenization or recurring payments not enabled). |
PaylinkSignatureException |
A webhook signature did not verify. |
PaylinkConnectionException |
Network failure or timeout (no HTTP response). |
Retries and rate limiting
Every integration endpoint is rate limited server-side, so 429s are an expected condition under burst traffic rather than an edge case. The SDK retries transient failures — 429, 5xx, connection errors, and timeouts — with exponential backoff and full jitter, honoring the server's Retry-After header when present.
A request is only ever replayed when replaying it cannot double-charge:
| Replayed | Not replayed |
|---|---|
All GETs (recurring->status) |
vcc->charge, cards->charge, cards->tokenize |
Any call you pass an idempotencyKey to |
invoices->create, recurring->create without a key |
payments->checkStatus (a pure read) |
recurring->cancel / pause / resume |
So to make a refund safely retryable, pass an idempotency key — otherwise a failed refund surfaces immediately and is yours to handle:
Tune or disable retries per client:
timeoutMs applies to each attempt, so worst-case wall time is roughly (maxRetries + 1) × timeoutMs plus backoff. For requests the SDK will not replay, PaylinkApiException::$retryAfterMs exposes the server's backoff hint (milliseconds) so you can schedule your own retry:
Amounts and precision
Signatures are computed over the exact bytes sent on the wire. To avoid any floating-point ambiguity, pass monetary amounts as strings (e.g. '10.50'). Integers are accepted and stringified, but strings give you full control.
Logging
The SDK logs to any PSR-3 logger you pass — retries at warning, exhausted retries at error, rejected webhooks at warning, and a timed info line per request. Every context array is masked, so a token, secret, signature, or card field never reaches the log. With no logger, output is silently discarded.
In Laravel, point it at a dedicated channel:
Outside Laravel, pass a Monolog logger (or any PSR-3 implementation) the same way.
Using it inside Laravel
The package ships an auto-discovered service provider and a Paylink facade — no manual wiring. Set the credentials in your environment:
Then inject the configured client — constructor injection is the idiomatic way, and the container resolves the singleton from your config:
Method injection (route actions, jobs, listeners) and the facade resolve the same singleton:
The provider binds the client through LaravelHttpTransport (Laravel's HTTP client, so Http::fake() works in tests) and logs to your configured channel. Publish the config to tune it:
Outside auto-discovery (or to run more than one integration), construct the client directly and pass any transport — implement GetPayin\Paylink\Core\Http\Transport to plug in Guzzle, a PSR-18 client, or a fake:
Security
hashTokenis a signing secret. Never ship it to a browser, a mobile app, or a client bundle. It is redacted fromvar_dump()andjson_encode()on the client, but load it from an environment variable or secret manager and never log it.vcc->chargeandcards->tokenizeaccept raw PAN/CVV, which puts your server in PCI scope. Prefer the hosted checkout (invoices->create) or card tokens where possible.
See SECURITY.md for the full security policy and how to report a vulnerability privately.
API reference
The full HTTP API — endpoints, fields, error codes, and test cards — is documented in the PayLink API reference: https://pay.getpayin.com/docs/payment_integration/index.html
Development
See CONTRIBUTING.md — the signing contract and how to keep it in sync with the server.
License
MIT — see LICENSE.
All versions of paylink with dependencies
ext-curl Version *
ext-json Version *
psr/log Version ^1.1 || ^2.0 || ^3.0