Download the PHP package nesthus/vipps-php without Composer
On this page you can find all versions of the php package nesthus/vipps-php. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Informations about the package vipps-php
nesthus/vipps-php
Unofficial framework-agnostic PHP SDK for Vipps MobilePay: ePayment, Recurring, Login (OIDC) and Webhooks.
[!IMPORTANT] This is an unofficial SDK. It is not affiliated with, endorsed or supported by Vipps MobilePay AS. Vipps and MobilePay are trademarks of Vipps MobilePay AS. When presenting the payment option to your users, follow the official brand guidelines: https://brand.vippsmobilepay.com/.
Why this SDK
- PSR-18 / PSR-17 — bring your own HTTP client; the SDK never picks one, so your timeout and proxy policy applies.
- PHP 8.3+,
final readonlyDTOs, native enums,declare(strict_types=1)throughout. - No serializer, no annotations, no framework — the only runtime
dependencies are PSR interfaces (plus the
mbstringextension). - No floats for money. Amounts are an
Amountvalue object over integer minor units (øre/cents); float constructors don't exist. - Caller-owned idempotency keys. Every mutating call requires one from you, because a key the SDK generated per call protects nothing — you must persist it before the request so you can replay with the same key.
- Tested webhook signature validation — HMAC verification with recomputed content hashes, constant-time comparison, replay-window enforcement, and leak-free failure reasons.
zaporylie/vipps is the long-standing community alternative and may fit you better; this library exists as a smaller, dependency-light take on the current API generation (ePayment v1, Recurring v3, Webhooks).
Install
The SDK depends only on PSR interfaces, so you also need a PSR-18 client and PSR-17 factories. Guzzle provides all of them:
[!WARNING] Configure timeouts, or a hung call will wedge your worker. Most PSR-18 clients — Guzzle included — wait forever by default, and a payment SDK without deadlines turns one slow upstream call into a stuck process. Construct your client with explicit limits:
Setup
All four credential values come from the merchant portal's developer section, per sales unit and per environment — test keys only work against the test host, which is why the environment lives in the config next to the keys.
Construction is free — everything inside is lazy. Access tokens are fetched and cached automatically on the first authenticated call (see Token caching).
Recurring quick start
Two rules every integrator trips on: the redirect back to your site proves nothing about approval, and Vipps never bills anyone by itself — your scheduler creates every charge.
Also available: listAgreements() (status filter plus optional
pageNumber/pageSize), updateAgreement() (price/text changes),
stopAgreement() (final — a stopped agreement can never be reactivated),
listCharges() (returns a ChargePage; feed its continuationToken back in
to page), getCharge() (use this in webhook and polling flows whenever you
have the agreement id), getChargeById() (lookup by charge id alone —
Vipps intends it for investigating customer claims, not for automation),
cancelCharge(), captureCharge() (for RESERVE_CAPTURE
charges — v3 requires an explicit amount even for a full capture) and
refundCharge(). Charge money totals (captured/refunded/cancelled) live on
Charge->summary.
Pricing models: Pricing::legacy() (fixed price per charge),
Pricing::variable() (user-approved ceiling) and Pricing::flexible()
(currency only — no price approved up front, every charge carries its own
amount; interval: may then be null, since a flexible agreement has no
fixed cadence).
ePayment quick start
One-off payments are reserve-then-capture: AUTHORIZED only holds the
money; capture() moves it, in full or in parts.
The reference is your idempotent identity for the whole payment, distinct
from the per-request idempotency key: creating a second payment with a used
reference is answered with a 409, and that failure is the point — never
generate a fresh reference to "get past" it. Note that a fully captured, even
fully refunded payment still reports AUTHORIZED — money movement is read
from Payment's aggregate amounts and getEvents(), not the state.
Login quick start
A standard OIDC authorization-code flow, discovered at runtime from the well-known document.
[!CAUTION]
idTokenClaims()decodes the id token without verifying the JWT signature. That is safe for exactly one reason: this token arrived over TLS directly from Vipps' token endpoint in a confidential-client code exchange, so its origin is already authenticated by the channel. An id token received from anywhere else — a browser redirect, a mobile app, another service — must not be trusted this way; it could be forged freely. Full JWKS signature verification is a deliberate non-goal of v0.1; if you need to accept tokens from untrusted channels, bring a real JWT library.The claims are not validated either — the SDK performs no OIDC claim checks, so treat them as unvalidated input. If you sent a
noncein theAuthorizationRequest, compare the token'snonceclaim against the value in your session before accepting the login (that binding is what stops a token minted for one session being replayed into another — the SDK has no session, so it cannot do this for you). If your acceptance logic readsiss,aud,exp,iatorazp, validate them per the OIDC spec, §3.1.3.7 before using the claims as identity data.
Webhooks
Register a callback URL per sales unit. Vipps caps how many hooks a sales unit
may hold, so list-and-reuse (all()) rather than re-registering on every
deploy.
Verify every inbound delivery before trusting a byte of it:
No PSR-7? Construct WebhookRequest directly with the method, the path+query
as sent on the wire, the Host header value, the exact raw body bytes
(never re-encoded from a decoded payload — the hash covers bytes, not
meaning), and the three signature headers.
Token caching
Merchant access tokens are fetched and refreshed automatically; you never handle them. The default cache is in-memory — one token per process, which is fine for classic per-request PHP. In long-running or multi-worker setups (queues, Octane, Swoole), share one token through any PSR-16 cache instead of letting every worker mint its own:
If Vipps ever answers 401 on a token that should have been valid (revoked
keys, clock trouble), $vipps->tokens()->forget() drops the cached token so
the next call fetches fresh.
Errors
Everything the SDK throws implements the Nesthus\Vipps\Exceptions\VippsException
marker interface.
Modules never inspect status codes themselves: any non-2xx from Vipps becomes
a VippsApiException at the transport. Its message carries method, path,
status and Vipps' own title/detail — never request headers or bodies, so
credentials can't leak through your exception logs.
Testing your integration
The suite under tests/ doubles as living documentation of every
endpoint's exact wire shape — URL, headers, JSON body — and the pattern is
portable: a queue-and-record PSR-18 fake
(tests/Support/FakeHttpClient.php, ~60
lines, copy it into your own suite) plus Guzzle's PSR-17 HttpFactory. No
HTTP, no mocking framework; the real transport runs down to the PSR-7
boundary.
For end-to-end testing against real infrastructure, use Vipps' apitest
environment: Environment::Test points at https://apitest.vipps.no, a full
sandbox with its own merchant keys (from the test tab of the merchant portal's
developer section) and test users. Test keys never work against production and
vice versa.
Development
No local PHP needed — everything runs in throwaway containers:
CI runs the same three checks (pint, phpstan level max, pest) on PHP 8.3 and 8.4.
Versioning & license
This is a 0.x release: the public API may still move between minor versions — pin accordingly and read CHANGELOG.md before upgrading. Once the surface has survived real-world use, 1.0 freezes it under semantic versioning.
MIT — see LICENSE.
Related: nesthus/vipps-laravel wraps this SDK for Laravel (config, container bindings, facades).
All versions of vipps-php with dependencies
ext-mbstring Version *
psr/clock Version ^1.0
psr/http-client Version ^1.0
psr/http-factory Version ^1.0
psr/http-message Version ^1.1 || ^2.0
psr/simple-cache Version ^2.0 || ^3.0