Skip to content

Releases: P2Flux/sdk-php

v0.14.0

Choose a tag to compare

@modulout modulout released this 27 Oct 14:46

Added

  • Private payments with Hinkal (live on the P2Flux API since 26 October 2026).
    'private_payment' => 'hinkal' on createPayment() and createPaymentLink() (once and reusable, not subscriptions) adds "Pay
    privately with Hinkal" to the hosted checkout; the answer, resolvePayment() and link terms carry
    private_payment. A verification's accounting.refundable is false for a payment made through a
    privacy service (refund it by hand); link payments in the manage view carry refundable and
    screening. Requests and answers were already passed through unchanged, so 0.13.0 code can use it
    too; this release documents it. (https://p2flux.com/docs/payments.html#private)

0.13.0 - Redirect checkout

Choose a tag to compare

@modulout modulout released this 22 Oct 15:42

Added

  • Redirect checkout. return_url on createPayment() and createPaymentLink(): after paying, the
    hosted checkout sends the buyer back with p2flux_reference, p2flux_tx and p2flux_status in
    the query. Every create answer now carries checkout_url, the hosted page to send the buyer to.
    resolvePayment() and link terms report return_url. An older API leaves both out. Answers were
    already passed through unchanged, so 0.12.0 code sees the new fields too; this release documents
    them. (https://p2flux.com/docs/payments.html#return)

0.12.0 - Optional webhooks

Choose a tag to compare

@modulout modulout released this 15 Oct 11:49

Added

  • Optional webhooks (live on the P2Flux API since 15 October 2026). Add notify_url (a public
    https URL) to createPayment() or createPaymentLink() and P2Flux POSTs payment.paid,
    subscription.charged or subscription.updated there, retrying for about 18 hours. Without it
    nothing changes. The response repeats notify_url only when the payment or link is watched.
    (https://p2flux.com/docs/webhooks.html)
  • handleNotification($body, $expect) - confirms a notification with the API before you fulfil:
    ['reference' => ...] for a payment, ['link_id' => ..., 'manage' => ...] for a link. Returns
    confirmed, a dedupe_key built from the verified payment (never the event id), and throws
    P2FluxException when the answer is not final yet (answer 5xx; it is sent again).

v0.11.1 - paywall refusal handling

Choose a tag to compare

@modulout modulout released this 08 Oct 16:57

Fixed

  • Paywall helper: a refusal from P2Flux (a 429 rate limit above all) is answered with a 402 again -
    never served free through onUnavailable 'free', and never turned into a 503 for every agent
    because somebody flooded junk payment headers. Only an unreachable or failing P2Flux
    (NETWORK_ERROR, INTERNAL_ERROR, RPC_ERROR, RELAYER_NOT_READY, RPC_BUSY) is "unavailable".

v0.11.0 - sanctions screening

Choose a tag to compare

@modulout modulout released this 08 Oct 10:02

Added

  • Sanctions screening (live since 7 October 2026): error codes PAYER_SANCTIONED (action
    STOP_SUBSCRIPTION - stop charging that subscription) and RECIPIENT_SANCTIONED (action
    INVALID_REQUEST - the receiving wallet is on the OFAC list; retrying gives the same answer).
    Nothing was submitted when either is returned. Show buyers a neutral message such as "This wallet
    cannot be used with P2Flux. No transaction was submitted." (https://p2flux.com/docs/errors.html#sanctions)
  • verifyPayment() passes through screening: 'clear' | 'sanctioned' | 'unknown' (documented in the
    return shape).

v0.10.0 - payment links

Choose a tag to compare

@modulout modulout released this 04 Oct 09:50

Added

  • Payment links - createPaymentLink(), paymentLinkStatus(), collectPaymentLink(),
    stopPaymentLink() and, for custom checkouts, openPaymentLink() and subscribePaymentLink(). Invoices paid once, fixed
    prices paid many times, and subscriptions P2Flux collects for you - no server needed.
    (https://p2flux.com/docs/payment-links.html)
  • checkoutLink('link' | 'links', $token) for the buyer's link and the merchant's overview.
  • Error codes INVALID_LINK, LINK_EXPIRED, LINK_UNAVAILABLE, ALREADY_SUBSCRIBED.

v0.9.0

Choose a tag to compare

@modulout modulout released this 03 Oct 14:11

Added

  • checkoutLink($page, $token) — the address that opens a checkout page (pay, subscribe,
    cancel, refund, approve) for a token the API issued, with the token in the fragment.
  • checkoutUrl option — where buyers open the checkout. Defaults to P2Flux's hosted checkout for
    the API in use; set it when you host the checkout yourself
    (https://p2flux.com/docs/self-hosted-checkout.html). Must be https (http only for localhost).

Nothing else changed.

v0.8.0

Choose a tag to compare

@modulout modulout released this 02 Oct 16:33

Added

  • x402 paywall — charge AI agents for a page or an API route without an x402 library:
    P2Flux\Paywall (guard($paymentHeader, $url, $userAgent)), and the two calls under it,
    P2FluxClient::paywallChallenge() and paywallRedeem(). Pay-per-request and prepaid balance; the
    payment is settled before anything is served and serves one response. examples/paywall.php.
  • Usage pricing — Paywall::usage($paymentHeader, $url, $maxPrice, $work) and
    P2FluxClient::paywallVerify(): the agent signs for at most $maxPrice (x402 upto), you charge
    what the request cost (paywallRedeem(..., $amount)).
  • Requests signed as bots (Web Bot Auth) count as agents under agentsOnly (guard(..., ['signed' => true]));
    an agent's prepaid refund request is answered with its receipt.
    Nothing else changed.

v0.7.3

Choose a tag to compare

@modulout modulout released this 07 Sep 14:51

Documentation, examples and PHPDoc. No behaviour changed: every method keeps its name, arguments
and return shape, and no API or payment path was touched.

Added

  • docs/payment-flow.md — the whole merchant lifecycle in one page, including the browser half
    the SDK never sees: the checkout handshake, why p2flux.payment.completed is a claim, and how to
    make the paid transition happen exactly once.
  • docs/recovery.md — recoverPayment(), recoverCharge() and a table of what to do after an
    ambiguous request, per operation. Both other pages now link here instead of repeating it.
  • docs/frameworks/laravel.md and docs/frameworks/symfony.md — the SDK used through the
    container: binding, constructor injection, a create action, a repeat-safe verify action, a renewal
    command and exception mapping. No Laravel package and no Symfony bundle: neither is needed.
  • docs/testing.md — how to test an integration without spending anything: the transport
    contract, a fake transport, a canned response per outcome worth a test, and the Laravel and
    Symfony overrides. The SDK still ships no dev dependencies.
  • docs/production-checklist.md — short, and every line is something that has gone wrong.
  • A recipes section in docs/errors.md — API unreachable, validation, RATE_LIMITED,
    CONCURRENCY_LIMIT, sponsorship unavailable, gas quotes, "it already happened", and who acts.
  • A glossary in docs/getting-started.md — intent, reference, capability, salt, base units.
  • examples/complete-payment-flow/ — a runnable merchant integration: order, checkout
    handshake, repeat-safe verification, recovery fallback. It runs against the canned API, so no
    wallet, USDC or chain is involved. tests/complete-flow.php drives it end to end in composer test.
  • More, smaller examples, one operation each: create-sponsored-payment.php,
    recover-payment.php, subscription-signup.php, charge-subscription.php, recover-charge.php.
    subscription.php is gone; network-fee-in-usdc.php now explains the accounting block.

Changed

  • PHPDoc array shapes on every response a caller reads — createPayment(), verifyPayment(),
    recoverPayment(), recoverCharge(), capabilities(), status(), prepareRefund() and the
    rest — so PhpStorm and PHPStan can see the keys. The shapes are unsealed (...), so a new API
    field never breaks a static analyser. Two methods carried a second docblock that hid the first
    from every IDE; those are merged. No signature changed.
  • The README leads with the first successful integration: install, a five-minute payment, the
    checkout flow, verify before fulfilling, USDC network fees, subscriptions, then links.
  • tests/stub-api.php answers PAYMENT_CONFIRMING for a hash starting 0xc0 and
    TRANSACTION_NOT_FOUND for one starting 0xbad, so the waiting and rejection paths are reachable
    offline.
  • tests/docs.php checks documentation recursively, derives the current version from
    package.json rather than a hard-coded list, and fails on claims this product does not support.

Install

composer require p2flux/sdk-php

v0.7.2

Choose a tag to compare

@modulout modulout released this 07 Sep 13:58

Packaging and documentation only. No behaviour changed: every method keeps its name, arguments
and return shape, and no API or payment path was touched.

Changed

  • The Composer package is p2flux/sdk-php and is published on Packagist, so installation is
    composer require p2flux/sdk-php — no repositories block and no VCS pin. The namespace,
    P2Flux\, and the PSR-4 layout are unchanged; the old name was never published anywhere.
  • composer.json carries production metadata (keywords, homepage, issue/source/docs links) and
    composer test, which runs the whole offline suite.
  • The README is a standalone entry point: install, requirements, a five-minute quickstart,
    configuration, the USDC-network-fee flow, error handling and links to everything else.
  • The integration guide was split into one page per topic — docs/getting-started.md,
    docs/payments.md, docs/network-fee-in-usdc.md, docs/subscriptions.md, docs/refunds.md and
    docs/errors.md. docs/guide.md is now the index.
  • Every example loads vendor/autoload.php and reads its configuration from the environment, and
    fails with the missing variable's name rather than a stack trace. examples/one-time.php is now
    examples/create-payment.php.

Added

  • examples/verify-payment.php — server-side verification and the recoverPayment() fallback.
    P2Flux sends no webhooks; this is the trust boundary, and the documentation now says so plainly.
  • tests/examples.php runs every example against tests/stub-api.php, a canned API on loopback,
    and tests/docs.php checks that every documented class, method, option and snippet still exists
    and parses. Both are offline and part of composer test.
  • .gitattributes keeps the Composer dist archive to the library itself.

Install

composer require p2flux/sdk-php