iyzico/iyzipay-php
Official PHP client for iyzico, Turkey's leading payment platform. Offers a simple SDK for processing payments, 3D Secure authentication, refunds, cancellations, stored cards, subscriptions, and marketplace payouts without handling raw API requests.
Architecture fit. iyzico/iyzipay-php is a plain, framework-agnostic PHP SDK — not a Laravel package. It ships no service provider, no facade, no config publishing, and no container bindings. Integration into a Laravel codebase is therefore a wrapper exercise, not a drop-in. The SDK is built around a mutable global Iyzipay\Options object plus static-ish request/model classes (Iyzipay\Request\CreatePaymentRequest, Iyzipay\Model\Payment), and it performs its own cURL-based HTTP. That means it bypasses Laravel's Http client, so you inherit none of the retry, middleware, logging, or mocking hooks the framework provides. For a clean Laravel fit we would own a PaymentGateway contract, a thin IyzicoClient adapter, and typed DTOs on top of the SDK so the rest of the app never touches Iyzipay\* directly.
Integration feasibility. Composer-installable and namespace-clean under PSR-4, so it coexists fine with an existing Laravel app. The main friction is the mutable options object: in a traditional FPM deployment you can configure once per request, but under Octane, queue workers, or any long-lived process, credentials and merchant settings must be set per-invocation or you risk cross-tenant leakage. The SDK also reports failures through response objects (getStatus(), getErrorCode(), getErrorMessage()) rather than exceptions, which is un-idiomatic for Laravel and needs a translating layer before it hits controllers or jobs. Sandbox support exists (sandbox-api.iyzipay.com), which makes smoke-testing feasible in a single sprint.
Technical risk. Highest risks, in order: (1) global state leakage in long-running processes — this is a correctness and potentially a security issue for multi-merchant setups; (2) no exception model, so unhandled "failed but 200" responses silently pass through unless every call site checks status; (3) the 3D Secure flow is redirect- and callback-based, and getting the callback verification, idempotency, and order-state transitions right is where most integration bugs land; (4) PCI scope — card data handling depends on whether we use Hosted Checkout Form vs. direct 3DS, and that decision needs to be explicit; (5) regional lock-in — iyzico's installment rules, currency constraints (TRY), and BDDK regulatory changes are enforced server-side and can change without a library release. The low overall score (18.1) is consistent with a legacy-style SDK: functional, official, but not modern PHP and not something you'd choose for maintainability reasons. It is, however, the vendor's own client, which is a strong argument over a third-party wrapper.
Key questions. Which iyzico products are in scope — Hosted Checkout, direct 3DS, marketplace/split payouts, subscription/recurring, refunds and partial captures? Is Turkey the only market, or is a multi-gateway abstraction required for expansion? Do we ever touch PANs, or is the card form fully hosted by iyzico? Single merchant or multi-tenant with per-seller credentials? What are the reconciliation and settlement-reporting requirements, and is there an SLA we're committing to that iyzico's Turkish-language, business-hours support can actually meet?
Stack fit. Compatible with Laravel 8–11 on PHP 7.4–8.3; the SDK's own HTTP layer and lack of return types mean it will run on modern PHP but won't benefit from strict typing. Recommended shape: config/iyzico.php (keys, base URL, merchant ID, sandbox flag) sourced from env/secrets manager; a IyzicoServiceProvider that binds a singleton IyzicoClient; the client constructs a fresh Options per call rather than reusing one; domain-level PaymentIntent/PaymentResult DTOs; a PaymentGateway interface if multi-gateway is on the roadmap. Keep the SDK types out of controllers and jobs.
Migration path. Introduce the gateway behind an interface and route traffic by currency or market rather than ripping out an existing provider. If there's no gateway today, phase it: sandbox smoke test → single-flow production (one product, one currency) → broaden. Feature-flag at the channel level so a rollback is a config change, not a deploy.
Compatibility. Two concrete constraints. First, the SDK does not use Guzzle or PSR-18, so it can't share Laravel's HTTP client, connection pooling, or Http::fake() in tests — plan on a seam (an interface you mock) rather than trying to intercept its transport. Second, its request/response objects are not designed for serialization, so never queue an Iyzipay\* object; queue your own DTOs and reconstruct the request inside the job.
Sequencing. (1) Config, secrets, sandbox credentials, and a one-off smoke script. (2) IyzicoClient adapter with per-call Options, typed DTOs, and a status-to-exception translator. (3) Idempotency keys and structured logging with correlation IDs on every outbound call. (4) 3DS initiate + callback route with signature/state verification and replay protection. (5) Webhook/callback hardening and order-state machine. (6) Refund/cancel jobs on the queue. (7) Settlement/reconciliation job against iyzico's reporting endpoints.
Maintenance. Small maintainer team and a narrow release cadence; expect to pin a specific version and treat upgrades as deliberate, tested events rather than routine composer update churn. The low score reflects that the codebase isn't going to modernize quickly. Budget for a thin internal fork or a patch set if you need PHP 8.x typing or a transport swap. Bus-factor risk is real but partially offset by the SDK being relatively small and readable.
Support. Official vendor SDK buys you iyzico's merchant support channel, which is Turkish-first and business-hours; there is no library-level SLA, no community Slack, and the GitHub issue tracker is not a reliable escalation path. Escalation for payment failures should go through the merchant account manager, not the repo. Document this explicitly so on-call engineers don't waste time filing issues.
Scaling. All calls are synchronous and blocking. Anything not in the customer's request path — refunds, captures, settlement pulls, retries — belongs on a queue with backoff. In the request path, set aggressive connect/read timeouts and treat timeouts as unknown-state, requiring a status query before retry. Watch for per-merchant rate limits and installment-rule lookups that may need caching. The biggest scaling hazard is the mutable global options under Octane: enforce per-request construction in code review, or you will eventually charge the wrong merchant.
Failure modes. Expect: silent business-logic failures (HTTP 200 with status=failure) if status checks are missed; 3DS callback replays and duplicate order creation without idempotency; stale credentials after rotation because Options was cached; currency or installment mismatches after a regulatory change on iyzico's side; and orphaned payments when the user abandons the 3DS redirect. Each needs a detector — a nightly reconciliation job comparing local orders to iyzico's records is the single highest-value operational control.
Ramp-up. A senior Laravel engineer can reach a working sandbox payment in a day, but the 3DS state machine, error taxonomy, and reconciliation semantics take one to two sprints to get production-safe. The SDK's non-idiomatic request/response style and Turkish/English mixed documentation mean the wrapper abstraction is what makes onboarding tractable — new engineers should learn your PaymentGateway contract, never Iyzipay\*.
How can I help you explore Laravel packages today?