diff --git a/.agents/skills/package-compatibility/SKILL.md b/.agents/skills/package-compatibility/SKILL.md
new file mode 100644
index 0000000..fcb2579
--- /dev/null
+++ b/.agents/skills/package-compatibility/SKILL.md
@@ -0,0 +1,41 @@
+---
+name: package-compatibility
+description: "Use this skill when reviewing Laravel package compatibility across composer constraints, PHP versions, Laravel versions, Testbench versions, dependency stability lanes, Windows CI, or matrix-sensitive code and workflow changes."
+license: MIT
+metadata:
+ author: laravel
+---
+
+# Package Compatibility
+
+## Primary Goal
+
+Keep package code, dependencies, and workflows compatible with the supported Laravel 12/13 and PHP 8.3+ matrix.
+
+## Workflow
+
+1. Read `composer.json` first to determine PHP, Laravel, and Testbench constraints.
+2. Check changed code against Laravel 12/13 APIs and PHP 8.3+ syntax before adopting newer framework or language features.
+3. Review `.github/workflows/tests.yml` for dependency stability lanes, prefer-lowest coverage, prefer-stable coverage, and Windows concerns.
+4. When changing dependencies, confirm constraints still allow the intended Laravel and Testbench versions.
+5. Validate with the smallest local command available, then rely on CI for full OS and dependency matrix coverage.
+
+## References
+
+- `composer.json`
+- `.github/workflows/tests.yml`
+- `phpstan.neon.dist`
+- `tests/`
+- `workbench/`
+
+## Examples
+
+- Review a new Laravel API call by checking whether it exists in Laravel 12 and Laravel 13 before merging it into shared package code.
+- Review a dependency bump by checking Composer constraints, Testbench constraints, prefer-lowest behavior, and Windows path assumptions.
+
+## Anti-Patterns
+
+- Assuming the latest local dependency version represents the whole support matrix.
+- Adding PHP syntax or Laravel APIs that exceed `composer.json` constraints.
+- Ignoring Windows path separators, executable assumptions, or shell-only syntax in tests and workflows.
+- Removing dependency stability lanes because they are slower than a single happy path.
diff --git a/.agents/skills/package-generate-skill/SKILL.md b/.agents/skills/package-generate-skill/SKILL.md
new file mode 100644
index 0000000..5365689
--- /dev/null
+++ b/.agents/skills/package-generate-skill/SKILL.md
@@ -0,0 +1,55 @@
+---
+name: package-generate-skill
+description: "Use this skill when creating or updating the bundled Laravel Boost skill under resources/boost/skills from the package implementation and package documentation. Trigger after public APIs, commands, config, routes, views, publish tags, README content, or examples change."
+license: MIT
+metadata:
+ author: laravel
+---
+
+# Package Generate Skill
+
+## Primary Goal
+
+Keep the package's bundled Boost skill accurate, concise, and focused on helping Laravel applications adopt the package.
+
+## Workflow
+
+1. Inspect the package implementation before editing the Boost skill: service provider, facades, public classes, commands, config, routes, migrations, events, views, publish tags, and tests.
+2. Inspect package documentation: `README.md`, contributing docs, examples, and changelog entries that describe user-facing behavior.
+3. Identify the public integration surface only. Include install, configure, publish, command, route, facade, helper, middleware, event, and testing guidance only when the package actually exposes it.
+4. Update `resources/boost/skills/*/SKILL.md` with practical adoption steps, references, examples, and anti-patterns for Laravel app developers using the package.
+5. Preserve front matter, package metadata, and the Boost skill structure: description, primary goal, workflow, references, examples, and anti-patterns.
+6. Validate that the Boost skill does not describe internals as public API and does not document features that are not implemented.
+
+## Writing Rules
+
+- Write for consumers installing the package in a Laravel application, not for maintainers changing package internals.
+- Prefer short, task-oriented steps over broad explanations.
+- Point to concrete files only when they help the consumer understand package adoption.
+- Keep examples runnable and aligned with documented package names, config keys, commands, and publish tags.
+- Keep the skill small enough for an agent to load and apply quickly.
+
+## References
+
+- `resources/boost/skills/`
+- `src/*ServiceProvider.php`
+- `src/Facades/`
+- `src/Console/Commands/`
+- `config/*.php`
+- `routes/*.php`
+- `database/migrations/`
+- `README.md`
+- `tests/Feature/` and `tests/Unit/`
+
+## Examples
+
+- After adding a new Artisan command, update the Boost skill with when to run it, required options, expected output, and any related config.
+- After adding config and publish tags, update the Boost skill with publish commands and the minimum config keys users need to set.
+- After adding a facade or public class, update the Boost skill with one practical integration example and the test assertion a consuming app should use.
+
+## Anti-Patterns
+
+- Regenerating the Boost skill from documentation alone without checking implementation.
+- Documenting private classes, test helpers, workbench-only routes, or implementation details as consumer API.
+- Adding speculative examples for features the package does not provide.
+- Removing package metadata that consuming agents need to identify and apply the skill.
diff --git a/.agents/skills/package-release/SKILL.md b/.agents/skills/package-release/SKILL.md
new file mode 100644
index 0000000..3179c8b
--- /dev/null
+++ b/.agents/skills/package-release/SKILL.md
@@ -0,0 +1,41 @@
+---
+name: package-release
+description: "Use this skill when preparing Laravel package releases: CHANGELOG.md updates, generated release notes, GitHub release workflows, version checks, tags, release validation, or release automation changes. Never publish autonomously."
+license: MIT
+metadata:
+ author: laravel
+---
+
+# Package Release
+
+## Primary Goal
+
+Prepare a safe package release checklist and implementation without tagging, pushing, or publishing unless the user explicitly approves that action.
+
+## Workflow
+
+1. Review `CHANGELOG.md`, generated release notes config, GitHub release workflows, open diff, and pending package changes.
+2. Validate the release state with `composer test` before recommending a release.
+3. Confirm whether version metadata needs to change; many Laravel packages rely on Git tags rather than a hardcoded package version.
+4. Review tag naming, release branch, and GitHub release workflow behavior before any release command.
+5. Do not tag, push, or publish without explicit user approval.
+
+## References
+
+- `CHANGELOG.md`
+- `.github/release.yml`
+- `.github/workflows/update-changelog.yml`
+- `.github/workflows/tests.yml`
+- `composer.json`
+
+## Examples
+
+- Prepare a release by checking changelog coverage, confirming generated release notes categories, running `composer test`, and drafting the tag command for user approval.
+- Update release notes grouping in `.github/release.yml` when a new label convention is added.
+
+## Anti-Patterns
+
+- Creating tags, pushing branches, or publishing releases without explicit approval.
+- Skipping `composer test` before a release recommendation.
+- Treating generated release notes as a replacement for meaningful `CHANGELOG.md` entries.
+- Changing release workflows without checking the supported matrix in `.github/workflows/tests.yml`.
diff --git a/.agents/skills/package-scaffold/SKILL.md b/.agents/skills/package-scaffold/SKILL.md
new file mode 100644
index 0000000..971c51c
--- /dev/null
+++ b/.agents/skills/package-scaffold/SKILL.md
@@ -0,0 +1,63 @@
+---
+name: package-scaffold
+description: "Use this skill when adding Laravel package capabilities or wiring them through the service provider: commands, migrations, routes, config merges, views, translations, assets, middleware, publish tags, workbench files, or console-only behavior."
+license: MIT
+metadata:
+ author: laravel
+---
+
+# Package Scaffold
+
+## Primary Goal
+
+Add package features in the right place and wire them through the service provider using explicit Laravel APIs, keeping package names, namespaces, config keys, and publish tags consistent.
+
+## Workflow
+
+1. Inspect the existing package structure, sibling examples, README setup notes, and the current service provider before creating files.
+2. Identify whether the request touches commands, migrations, routes, config, views, translations, assets, middleware, tests, README/contributing docs, compatibility, or release flow.
+3. Create the capability files under Laravel-native package paths and use the configured package names, namespaces, publish tags, URLs, and badges consistently.
+4. Wire the capability through the service provider using the patterns in *Provider wiring* below.
+5. Use `package-testing` for coverage, update README or contributing documentation when user-facing behavior changes, use `package-compatibility` for matrix-sensitive changes, and use `package-release` for release tasks.
+6. Add only the files needed for the requested capability and validate with the narrowest relevant command before broader checks.
+
+## Provider Wiring
+
+1. Keep provider wiring in `register()` or `boot()` unless extracting a method makes a real repeated concern clearer.
+2. Put container bindings and `mergeConfigFrom` calls in `register()` when the host app must be able to override configuration.
+3. Put resource loading in boot-time methods with Laravel-native APIs such as `loadRoutesFrom`, `loadViewsFrom`, and `loadTranslationsFrom`.
+4. Guard console-only publishing and command registration with `runningInConsole()` before calling `publishes`, `publishesMigrations`, or `commands`.
+5. Name publish tags with the `simplepay-*` convention so consumers can target individual resource groups.
+6. Add tests for the observable provider behavior: merged config, loaded routes, publish tags, or command registration.
+
+Provider wiring anti-patterns:
+
+- Loading host app state too early during provider registration.
+- Calling `env()` outside config files; use config values after `mergeConfigFrom` instead.
+- Registering web-only concerns unconditionally when the package can run in console contexts.
+- Replacing explicit provider methods with `spatie/laravel-package-tools` by default.
+
+## References
+
+- `src/*ServiceProvider.php`
+- `config/*.php`
+- `routes/*.php`
+- `resources/views/`
+- `lang/`
+- `database/migrations/`
+- `public/`
+- `src/Console/Commands/`
+- `tests/Feature/` and `tests/Unit/`
+
+## Examples
+
+- Add an Artisan command: create the command class under `src/Console/Commands`, register it in the `commands` array inside the `runningInConsole()` guard, add a feature test for observable console output, and document the command if it is user-facing.
+- Add a publishable migration: place the migration in `database/migrations`, wire it through a console-guarded `publishesMigrations` call with a `simplepay-migrations` tag, and test publish behavior with Testbench.
+- Wire a new publish tag by adding a `publishes` map inside the existing console-guarded publishing method and naming the tag with `simplepay-*`.
+
+## Anti-Patterns
+
+- Adding unused files because a package might need them later.
+- Mixing package names, namespaces, config keys, or publish tags.
+- Changing dependencies without approval.
+- Replacing explicit Laravel package code with a helper abstraction when one feature-specific change would do.
diff --git a/.agents/skills/package-testing/SKILL.md b/.agents/skills/package-testing/SKILL.md
new file mode 100644
index 0000000..321dfa5
--- /dev/null
+++ b/.agents/skills/package-testing/SKILL.md
@@ -0,0 +1,43 @@
+---
+name: package-testing
+description: "Use this skill when writing, editing, fixing, or reviewing package tests with Pest 4/5 and Orchestra Testbench, including TDD, feature tests, unit tests, type coverage, arch tests, workbench behavior, commands, routes, config, migrations, and publishable resources."
+license: MIT
+metadata:
+ author: laravel
+---
+
+# Package Testing
+
+## Primary Goal
+
+Prove package behavior with Pest 4/5, Orchestra Testbench, and the local `tests/TestCase.php` setup before or alongside implementation.
+
+## Workflow
+
+1. Start with TDD: write the smallest failing package test for the requested behavior, then implement the smallest change that makes it pass.
+2. Cover happy-path, unhappy-path, and edge-case behavior when the feature has meaningful failure modes.
+3. Prefer focused feature tests for package integration behavior and arch tests for broad constraints.
+4. Use `composer test:unit -- --filter ...` while iterating, `composer test:types` when type-sensitive tests or code changed, and `composer test` before finishing.
+5. Keep real package tests in the suite and remove only throwaway tests that were explicitly created for local scaffolding experiments.
+
+## References
+
+- `tests/TestCase.php`
+- `tests/Pest.php`
+- `tests/Feature/`
+- `tests/Unit/`
+- `tests/ArchTest.php`
+- `composer.json` scripts
+
+## Examples
+
+- Test config merge and config override by asserting default package config, then overriding the host config value in the Testbench app.
+- Test publishable assets, migrations, views, lang files, or config by invoking vendor publish behavior and asserting the target path exists.
+- Test routes with Testbench HTTP requests, commands with Artisan assertions, migrations with a SQLite test database, and workbench behavior after `composer build` when needed.
+
+## Anti-Patterns
+
+- Deleting real package tests because they are inconvenient.
+- Relying only on smoke tests when behavior needs assertions.
+- Testing implementation details when observable package behavior is available.
+- Keeping throwaway scaffolding experiment tests in the package test suite.
diff --git a/.claude b/.claude
new file mode 120000
index 0000000..c0ca468
--- /dev/null
+++ b/.claude
@@ -0,0 +1 @@
+.agents
\ No newline at end of file
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..81162ca
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,15 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = space
+insert_final_newline = true
+trim_trailing_whitespace = true
+
+[*.md]
+trim_trailing_whitespace = false
+
+[*.{yml,yaml,json}]
+indent_size = 2
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..c2b57d0
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,18 @@
+* text=auto eol=lf
+
+/.github export-ignore
+/.gitattributes export-ignore
+/.gitignore export-ignore
+/.editorconfig export-ignore
+/tests export-ignore
+/phpunit.xml.dist export-ignore
+/phpstan.neon.dist export-ignore
+/pint.json export-ignore
+/testbench.yaml export-ignore
+/workbench export-ignore
+/.claude export-ignore
+/.agents export-ignore
+/CLAUDE.md export-ignore
+/AGENTS.md export-ignore
+/art export-ignore
+/official-docs export-ignore
diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
new file mode 100644
index 0000000..a871547
--- /dev/null
+++ b/.github/CONTRIBUTING.md
@@ -0,0 +1,43 @@
+# Contribution Guide
+
+Thank you for considering contributing to SimplePay for Laravel! Please review the following guidelines before submitting a pull request.
+
+For significant changes, please open an issue first so we can discuss the approach.
+
+## Process
+
+1. Fork the project
+2. Create a new branch
+3. Code, test, commit, and push
+4. Open a pull request detailing your changes
+
+## Guidelines
+
+- Ensure the coding style passes by running `composer lint`.
+- Send a coherent commit history, making sure each commit in your pull request is meaningful.
+- You may need to [rebase](https://git-scm.com/book/en/v2/Git-Branching-Rebasing) to avoid merge conflicts.
+- Please remember that we follow [SemVer](http://semver.org/).
+
+## Setup
+
+Clone your fork, then install the dev dependencies:
+
+```bash
+composer install
+```
+
+## Lint
+
+Lint your code:
+
+```bash
+composer lint
+```
+
+## Tests
+
+Run all tests:
+
+```bash
+composer test
+```
diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml
new file mode 100644
index 0000000..2ec89f0
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug.yml
@@ -0,0 +1,69 @@
+name: Bug Report
+description: Report something that is not working as expected.
+title: "[Bug]: "
+labels: ["bug"]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ Thanks for taking the time to report a bug. Please complete the fields below so we can reproduce the issue quickly.
+
+ - type: input
+ id: package-version
+ attributes:
+ label: Package Version
+ description: Provide the package version that you are using.
+ placeholder: 1.0.0
+ validations:
+ required: true
+
+ - type: input
+ id: laravel-version
+ attributes:
+ label: Laravel Version
+ description: Provide the Laravel version that you are using.
+ placeholder: 13.0.0
+ validations:
+ required: true
+
+ - type: input
+ id: php-version
+ attributes:
+ label: PHP Version
+ description: Provide the PHP version that you are using.
+ placeholder: 8.3.0
+ validations:
+ required: true
+
+ - type: input
+ id: operating-system
+ attributes:
+ label: Operating System
+ description: If relevant, provide the operating system and version where this occurs.
+ placeholder: macOS 15.0, Ubuntu 24.04, Windows 11
+ validations:
+ required: false
+
+ - type: textarea
+ id: description
+ attributes:
+ label: Description
+ description: Provide a clear description of the issue you are facing.
+ validations:
+ required: true
+
+ - type: textarea
+ id: steps-to-reproduce
+ attributes:
+ label: Steps To Reproduce
+ description: Provide detailed steps to reproduce the issue. A minimal reproduction repository is helpful when possible.
+ validations:
+ required: true
+
+ - type: textarea
+ id: notes
+ attributes:
+ label: Notes
+ description: Add any other context that might help diagnose the issue.
+ validations:
+ required: false
diff --git a/.github/SECURITY.md b/.github/SECURITY.md
new file mode 100644
index 0000000..670ca0b
--- /dev/null
+++ b/.github/SECURITY.md
@@ -0,0 +1,11 @@
+# Security Policy
+
+**PLEASE DON'T DISCLOSE SECURITY-RELATED ISSUES PUBLICLY, [SEE BELOW](#reporting-a-vulnerability).**
+
+## Supported Versions
+
+Only the latest major version receives security fixes.
+
+## Reporting a Vulnerability
+
+If you discover a security vulnerability within SimplePay for Laravel, please send an email to NETipar at dev@netipar.hu. All security vulnerabilities will be promptly addressed.
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..f090fce
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,18 @@
+# Please see the documentation for all configuration options:
+# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
+
+version: 2
+updates:
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ labels:
+ - "dependencies"
+
+ - package-ecosystem: "composer"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ labels:
+ - "dependencies"
diff --git a/.github/phpstan-windows.neon b/.github/phpstan-windows.neon
new file mode 100644
index 0000000..dda11d0
--- /dev/null
+++ b/.github/phpstan-windows.neon
@@ -0,0 +1,15 @@
+# PHPStan configuration for the Windows CI lane.
+#
+# Larastan boots a Laravel application (via Testbench) in every PHPStan worker,
+# and each boot rewrites the Testbench skeleton's bootstrap/cache/services.php
+# through a write-to-temp-file followed by rename() onto the shared path.
+# POSIX rename() tolerates concurrent writers; Windows does not, and the losing
+# worker dies with "Access is denied (code: 5)". A single process serialises
+# those writes; only the Windows lane pays the speed cost.
+
+includes:
+ - ../phpstan.neon.dist
+
+parameters:
+ parallel:
+ maximumNumberOfProcesses: 1
diff --git a/.github/release.yml b/.github/release.yml
new file mode 100644
index 0000000..fc53f3c
--- /dev/null
+++ b/.github/release.yml
@@ -0,0 +1,27 @@
+changelog:
+ exclude:
+ labels:
+ - skip-changelog
+ - duplicate
+ categories:
+ - title: Breaking Changes
+ labels:
+ - breaking
+ - title: Enhancements
+ labels:
+ - enhancement
+ - title: Bug Fixes
+ labels:
+ - bug
+ - title: Documentation
+ labels:
+ - documentation
+ - title: Dependencies
+ labels:
+ - dependencies
+ - title: Maintenance
+ labels:
+ - maintenance
+ - title: Other Changes
+ labels:
+ - "*"
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 8787bca..f1a3bf6 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -1,66 +1,90 @@
-name: Tests
+name: tests
on:
push:
branches:
- main
+ - '*.x'
pull_request:
- branches:
- - main
-
-jobs:
- pint:
- runs-on: ubuntu-latest
- name: Pint
-
- steps:
- - name: Checkout code
- uses: actions/checkout@v4
-
- - name: Setup PHP
- uses: shivammathur/setup-php@v2
- with:
- php-version: 8.4
- extensions: dom, libxml, simplexml
- coverage: none
- - name: Install dependencies
- run: composer install --prefer-dist --no-interaction
+permissions:
+ contents: read
- - name: Run Pint
- run: vendor/bin/pint --test
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+jobs:
tests:
- runs-on: ubuntu-latest
+ runs-on: ${{ matrix.os }}
strategy:
- fail-fast: true
+ # Let every lane report, so a break shows whether it is matrix-wide or
+ # specific to one PHP/Laravel/stability combination. The concurrency
+ # group above still cancels superseded runs.
+ fail-fast: false
matrix:
- php: [8.2, 8.3, 8.4]
- laravel: [11.*, 12.*]
+ os: [ubuntu-latest, windows-latest]
+ php: [8.3, 8.4, 8.5]
+ laravel: [12.*, 13.*]
+ stability: [prefer-lowest, prefer-stable]
include:
- - laravel: 11.*
- testbench: 9.*
- laravel: 12.*
testbench: 10.*
+ - laravel: 13.*
+ testbench: 11.*
- name: PHP ${{ matrix.php }} - Laravel ${{ matrix.laravel }}
+ name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }}
steps:
- name: Checkout code
- uses: actions/checkout@v4
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup PHP
- uses: shivammathur/setup-php@v2
+ uses: shivammathur/setup-php@eb7c497e18156a6bbabfef1d3a82760b9eda3962 # v2
with:
php-version: ${{ matrix.php }}
- extensions: dom, libxml, simplexml
+ extensions: dom, curl, libxml, mbstring, zip, fileinfo, sqlite, pdo_sqlite, bcmath, intl
+ # setup-php seeds php.ini from php.ini-production, where
+ # variables_order="GPCS" leaves $_ENV empty; the type coverage step
+ # needs it populated, as in a normal local install.
+ ini-values: error_reporting=E_ALL, variables_order=EGPCS
+ tools: composer:v2
coverage: none
- name: Install dependencies
run: |
- composer require "illuminate/support:${{ matrix.laravel }}" "illuminate/http:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --dev --no-interaction --no-update
- composer update --prefer-dist --no-interaction
+ composer require "laravel/framework:${{ matrix.laravel }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update
+ composer update --${{ matrix.stability }} --prefer-dist --no-interaction --no-progress --no-scripts
+ composer run prepare
+
+ - name: PHPStan
+ if: runner.os != 'Windows'
+ run: composer analyse
+
+ # Larastan boots Laravel in every PHPStan worker, and each boot rewrites
+ # the Testbench skeleton's bootstrap/cache/services.php. Concurrent
+ # rename() onto that file fails on Windows, so this lane analyses in a
+ # single process. See .github/phpstan-windows.neon.
+ - name: PHPStan (Windows)
+ if: runner.os == 'Windows'
+ run: vendor/bin/phpstan analyse --configuration=.github/phpstan-windows.neon
+
+ - name: Linter
+ run: composer lint:check
+
+ # pest-plugin-type-coverage 4.x workers share one cache file without a
+ # blocking lock; __PEST_PLUGIN_ENV keeps the analysis in one process.
+ - name: Type Coverage
+ if: runner.os != 'Windows'
+ env:
+ __PEST_PLUGIN_ENV: '1'
+ run: composer test:types
+
+ - name: Test Suite
+ if: runner.os != 'Windows'
+ run: composer test:unit
- - name: Run tests
+ - name: Test Suite (Windows)
+ if: runner.os == 'Windows'
run: vendor/bin/pest
diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml
new file mode 100644
index 0000000..9ba1e4e
--- /dev/null
+++ b/.github/workflows/update-changelog.yml
@@ -0,0 +1,32 @@
+name: Update Changelog
+
+on:
+ release:
+ types: [released]
+
+permissions:
+ contents: write
+
+jobs:
+ update:
+ runs-on: ubuntu-latest
+ timeout-minutes: 5
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
+ with:
+ ref: main
+
+ - name: Update changelog
+ uses: stefanzweifel/changelog-updater-action@a938690fad7edf25368f37e43a1ed1b34303eb36 # v1
+ with:
+ latest-version: ${{ github.event.release.name }}
+ release-notes: ${{ github.event.release.body }}
+
+ - name: Commit updated changelog
+ uses: stefanzweifel/git-auto-commit-action@4a55954c782fc1ea30b9056cd3e7a2b40ca8887d # v7
+ with:
+ branch: main
+ commit_message: Update CHANGELOG
+ file_pattern: CHANGELOG.md
diff --git a/.gitignore b/.gitignore
index 3d0a5b5..d0ee595 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,11 @@
-/vendor/
-/.idea/
+/vendor
+/build
+/.phpunit.cache
+/.phpunit.result.cache
+/coverage
composer.lock
+.phpunit.cache
.phpunit.result.cache
+.DS_Store
+.idea
+.vscode
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..1bad700
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,38 @@
+# SimplePay for Laravel
+
+This repository is a Laravel package. Keep the package focused, idiomatic, and easy for Laravel developers to install, test, and maintain.
+
+## Package Conventions
+
+- Use Laravel-native package APIs and the existing service provider shape before adding abstractions.
+- Keep package names, namespaces, Composer metadata, publish tags, documentation, and examples aligned with `netipar/simplepay`.
+- Add only the files and dependencies needed for the package behavior being implemented.
+- Prefer explicit Laravel package code over helper abstractions unless the extension point is real.
+- Keep tests focused on observable package behavior through public APIs, service provider wiring, commands, routes, published resources, and documentation promises.
+
+## Quick Commands
+
+- Full validation: `composer test`
+- Formatting check: `composer lint:check`
+- Static analysis: `composer analyse`
+- Pest tests: `composer test:unit`
+- Workbench build: `composer build`
+- Workbench server: `composer serve`
+
+## Local Skills
+
+- `package-scaffold`: use when adding package capabilities or wiring them through the service provider, including commands, migrations, routes, config, views, translations, assets, middleware, publish tags, workbench files, and console-only behavior.
+- `package-testing`: use when adding or changing package tests with Pest 4/5 and Orchestra Testbench.
+- `package-release`: use when preparing changelog, release notes, tags, or GitHub release workflow changes.
+- `package-compatibility`: use when reviewing code, dependencies, or CI against the PHP and Laravel support matrix.
+- `package-generate-skill`: use when updating the bundled Boost skill from the package implementation, README, and examples.
+
+## SimplePay Architecture
+
+- The package follows the official SimplePay PHP SDKs (API v2, published at https://simplepay.hu/fejlesztoknek/). `official-docs/` holds the reference PDFs; it is not part of the dist archive.
+- `src/SimplePay.php` sits behind the `SimplePay` facade and exposes the services in `src/Services`: `PaymentService` (start, finish, refund, query, cancel, qvik/EAM, Apple Pay), `CardStorageService` (OneClick `do`, recurring, card and token query/cancel), `AutoPaymentService` (merchant-side card data) and `RtpService` (Request to Pay).
+- Request and response payloads are readonly DTOs in `src/Dto`: `toArray()` builds the API body including `salt` and `sdkVersion`, `fromArray()` maps the response. Enums live in `src/Enums`; `ErrorCode` mirrors the official error code list with Hungarian descriptions.
+- `src/Support/Client.php` signs every request with HMAC-SHA384 (`Support/Signature`), verifies the response signature and throws `SimplePayApiException` when `errorCodes` is not empty; the exception keeps the response body (`getResponseData()`), e.g. the `redirectUrl` of a 3DS challenge (3004).
+- Merchant credentials are configured per currency (`simplepay.merchants`) and resolved by `Support/MerchantResolver`; IPN bodies without `currency` are resolved by their `merchant` field.
+- Routes: `POST simplepay/ipn` (`VerifySimplePaySignature` middleware; `SimplePayWebhookController` dispatches the events in `src/Events`) and `GET simplepay/back` (`SimplePayBackController`, response customisable through the `BackUrlResponse` contract).
+- Consumer documentation is bilingual: keep `examples/en/` and `examples/hu/` in sync with each other and with the README.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f1e4afa..04ba82f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,6 @@
-# Changelog
+# Release Notes
-All notable changes to `netipar/simplepay` will be documented in this file.
+## [Unreleased](https://github.com/NETipar/simplepay/compare/v1.2.0...main)
## v1.2.0 - 2026-04-28
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 120000
index 0000000..47dc3e3
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1 @@
+AGENTS.md
\ No newline at end of file
diff --git a/README.md b/README.md
index ddd0a16..1ff8791 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,8 @@
# SimplePay for Laravel
[](https://packagist.org/packages/netipar/simplepay)
-[](https://github.com/NETipar/simplepay/actions?query=workflow%3ATests+branch%3Amain)
+[](https://github.com/NETipar/simplepay/actions/workflows/tests.yml?query=branch%3Amain)
+[](https://packagist.org/packages/netipar/simplepay)
[](https://packagist.org/packages/netipar/simplepay)
Modern Laravel package for [SimplePay](https://simplepay.hu) online payment integration. Start payments, handle IPN webhooks, manage card storage, process refunds, and more.
@@ -45,8 +46,8 @@ return redirect($response->paymentUrl);
## Requirements
-- PHP 8.2+
-- Laravel 11 or 12
+- PHP 8.3+
+- Laravel 12 or 13
- A [SimplePay](https://simplepay.hu) merchant account
## Installation
@@ -61,6 +62,12 @@ Publish the config file:
php artisan vendor:publish --tag=simplepay-config
```
+Or publish the config file and the logo assets at once:
+
+```bash
+php artisan vendor:publish --tag=simplepay
+```
+
Add your merchant credentials to `.env`:
```
@@ -385,6 +392,23 @@ try {
$e->getErrorCodes(); // [5083]
$e->hasErrorCode(5083); // true
$e->getResolvedCodes(); // [ErrorCode::TokenTimesRequired]
+ $e->getResponseData(); // The full API response body
+}
+```
+
+When a card storage or auto payment requires a 3DS challenge, the API answers with error code `3004`, and the response body holds the `redirectUrl` where the customer has to be sent:
+
+```php
+use Netipar\SimplePay\Enums\ErrorCode;
+
+try {
+ $result = SimplePay::cardStorage()->do($request);
+} catch (SimplePayApiException $e) {
+ if ($e->hasErrorCode(ErrorCode::ThreeDsChallengeRedirect->value)) {
+ return redirect($e->getResponseData()['redirectUrl']);
+ }
+
+ throw $e;
}
```
@@ -468,9 +492,24 @@ This package is built based on the **SimplePay PHP SDK v2.1** (API v2). All API
## Testing
```bash
-composer test
+composer test # PHPStan, Pint check, type coverage and the Pest suite
+composer test:unit # Pest suite only
+composer analyse # PHPStan (Larastan, level 7)
+composer lint # Fix code style with Pint
```
+## Changelog
+
+Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.
+
+## Contributing
+
+Please review the [contributing guide](.github/CONTRIBUTING.md) before opening a pull request.
+
+## Security Vulnerabilities
+
+Please review the [security policy](.github/SECURITY.md) on how to report security vulnerabilities.
+
## Credits
- [NETipar](https://netipar.hu)
diff --git a/composer.json b/composer.json
index f1effd6..bb9bb34 100644
--- a/composer.json
+++ b/composer.json
@@ -1,17 +1,43 @@
{
+ "$schema": "https://getcomposer.org/schema.json",
"name": "netipar/simplepay",
"description": "Modern Laravel package for SimplePay online payment integration",
- "keywords": ["laravel", "simplepay", "payment", "hungary"],
+ "keywords": [
+ "laravel",
+ "netipar",
+ "simplepay",
+ "payment",
+ "hungary"
+ ],
+ "homepage": "https://github.com/NETipar/simplepay",
"license": "MIT",
+ "support": {
+ "issues": "https://github.com/NETipar/simplepay/issues",
+ "source": "https://github.com/NETipar/simplepay",
+ "security": "https://github.com/NETipar/simplepay/security/policy"
+ },
+ "authors": [
+ {
+ "name": "NETipar",
+ "email": "dev@netipar.hu",
+ "homepage": "https://netipar.hu",
+ "role": "Developer"
+ }
+ ],
"require": {
- "php": "^8.2",
- "illuminate/support": "^11.0|^12.0",
- "illuminate/http": "^11.0|^12.0"
+ "php": "^8.3",
+ "illuminate/http": "^12.0||^13.0",
+ "illuminate/support": "^12.0||^13.0"
},
"require-dev": {
- "laravel/pint": "^1.18",
- "orchestra/testbench": "^9.0|^10.0",
- "pestphp/pest": "^3.0"
+ "larastan/larastan": "^3.10",
+ "laravel/pao": "^1.0",
+ "laravel/pint": "^1.29",
+ "orchestra/testbench": "^10.0||^11.0",
+ "pestphp/pest": "^4.6||^5.0",
+ "pestphp/pest-plugin-laravel": "^4.1||^5.0",
+ "pestphp/pest-plugin-type-coverage": "^4.0||^5.0",
+ "phpstan/extension-installer": "^1.4"
},
"autoload": {
"psr-4": {
@@ -20,9 +46,53 @@
},
"autoload-dev": {
"psr-4": {
- "Netipar\\SimplePay\\Tests\\": "tests/"
+ "Netipar\\SimplePay\\Tests\\": "tests/",
+ "Workbench\\App\\": "workbench/app/",
+ "Workbench\\Database\\Factories\\": "workbench/database/factories/",
+ "Workbench\\Database\\Seeders\\": "workbench/database/seeders/"
}
},
+ "scripts": {
+ "post-autoload-dump": [
+ "@clear",
+ "@prepare"
+ ],
+ "prepare": [
+ "@php vendor/bin/testbench package:discover --ansi"
+ ],
+ "build": [
+ "@php vendor/bin/testbench workbench:build --ansi"
+ ],
+ "serve": [
+ "Composer\\Config::disableProcessTimeout",
+ "@build",
+ "@php vendor/bin/testbench serve --ansi"
+ ],
+ "lint": [
+ "vendor/bin/pint --parallel"
+ ],
+ "lint:check": [
+ "vendor/bin/pint --parallel --test"
+ ],
+ "analyse": [
+ "vendor/bin/phpstan analyse"
+ ],
+ "test:types": [
+ "vendor/bin/pest --type-coverage --min=100"
+ ],
+ "test:unit": [
+ "vendor/bin/pest --parallel"
+ ],
+ "test": [
+ "@analyse",
+ "@lint:check",
+ "@test:types",
+ "@test:unit"
+ ],
+ "clear": [
+ "@php vendor/bin/testbench package:purge-skeleton --ansi"
+ ]
+ },
"extra": {
"laravel": {
"providers": [
@@ -33,17 +103,13 @@
}
}
},
- "scripts": {
- "test": "vendor/bin/pest",
- "test-coverage": "vendor/bin/pest --coverage",
- "format": "vendor/bin/pint"
- },
"config": {
"sort-packages": true,
"allow-plugins": {
- "pestphp/pest-plugin": true
+ "pestphp/pest-plugin": true,
+ "phpstan/extension-installer": true
}
},
- "minimum-stability": "dev",
+ "minimum-stability": "stable",
"prefer-stable": true
}
diff --git a/config/simplepay.php b/config/simplepay.php
index b93d1ec..317ca87 100644
--- a/config/simplepay.php
+++ b/config/simplepay.php
@@ -1,5 +1,7 @@
-
-
-
- tests/Unit
-
-
- tests/Feature
-
-
-
-
- src
-
-
-
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
new file mode 100644
index 0000000..e2ecb23
--- /dev/null
+++ b/phpunit.xml.dist
@@ -0,0 +1,34 @@
+
+
+
+
+ tests/ArchTest.php
+
+
+ tests/Feature
+
+
+ tests/Unit
+
+
+
+
+ src
+
+
+
diff --git a/pint.json b/pint.json
index 93061b6..1099652 100644
--- a/pint.json
+++ b/pint.json
@@ -1,3 +1,36 @@
{
- "preset": "laravel"
+ "preset": "laravel",
+ "rules": {
+ "declare_strict_types": true,
+ "no_extra_blank_lines": {
+ "tokens": [
+ "curly_brace_block",
+ "extra",
+ "throw",
+ "use"
+ ]
+ },
+ "blank_line_before_statement": {
+ "statements": [
+ "break",
+ "continue",
+ "declare",
+ "if",
+ "return",
+ "throw",
+ "try"
+ ]
+ },
+ "global_namespace_import": {
+ "import_classes": true
+ },
+ "trailing_comma_in_multiline": {
+ "elements": [
+ "arguments",
+ "arrays",
+ "match",
+ "parameters"
+ ]
+ }
+ }
}
diff --git a/resources/assets/logos/Apple_Pay_Mark_RGB.png b/public/logos/Apple_Pay_Mark_RGB.png
similarity index 100%
rename from resources/assets/logos/Apple_Pay_Mark_RGB.png
rename to public/logos/Apple_Pay_Mark_RGB.png
diff --git a/resources/assets/logos/GPay_logo_color_new.png b/public/logos/GPay_logo_color_new.png
similarity index 100%
rename from resources/assets/logos/GPay_logo_color_new.png
rename to public/logos/GPay_logo_color_new.png
diff --git a/resources/assets/logos/OTPszepkartya_logo_color.png b/public/logos/OTPszepkartya_logo_color.png
similarity index 100%
rename from resources/assets/logos/OTPszepkartya_logo_color.png
rename to public/logos/OTPszepkartya_logo_color.png
diff --git a/resources/assets/logos/amex_logo_bw.png b/public/logos/amex_logo_bw.png
similarity index 100%
rename from resources/assets/logos/amex_logo_bw.png
rename to public/logos/amex_logo_bw.png
diff --git a/resources/assets/logos/amex_logo_color.png b/public/logos/amex_logo_color.png
similarity index 100%
rename from resources/assets/logos/amex_logo_color.png
rename to public/logos/amex_logo_color.png
diff --git a/resources/assets/logos/maestro_logo_bw_new.png b/public/logos/maestro_logo_bw_new.png
similarity index 100%
rename from resources/assets/logos/maestro_logo_bw_new.png
rename to public/logos/maestro_logo_bw_new.png
diff --git a/resources/assets/logos/maestro_logo_color_new.png b/public/logos/maestro_logo_color_new.png
similarity index 100%
rename from resources/assets/logos/maestro_logo_color_new.png
rename to public/logos/maestro_logo_color_new.png
diff --git a/resources/assets/logos/mastercard_logo_bw_new.png b/public/logos/mastercard_logo_bw_new.png
similarity index 100%
rename from resources/assets/logos/mastercard_logo_bw_new.png
rename to public/logos/mastercard_logo_bw_new.png
diff --git a/resources/assets/logos/mastercard_logo_color_new.png b/public/logos/mastercard_logo_color_new.png
similarity index 100%
rename from resources/assets/logos/mastercard_logo_color_new.png
rename to public/logos/mastercard_logo_color_new.png
diff --git a/resources/assets/logos/qvik_logo_color.png b/public/logos/qvik_logo_color.png
similarity index 100%
rename from resources/assets/logos/qvik_logo_color.png
rename to public/logos/qvik_logo_color.png
diff --git a/resources/assets/logos/simplepay_200x50.png b/public/logos/simplepay_200x50.png
similarity index 100%
rename from resources/assets/logos/simplepay_200x50.png
rename to public/logos/simplepay_200x50.png
diff --git a/resources/assets/logos/simplepay_horizontal_01-white.png b/public/logos/simplepay_horizontal_01-white.png
similarity index 100%
rename from resources/assets/logos/simplepay_horizontal_01-white.png
rename to public/logos/simplepay_horizontal_01-white.png
diff --git a/resources/assets/logos/simplepay_horizontal_01.png b/public/logos/simplepay_horizontal_01.png
similarity index 100%
rename from resources/assets/logos/simplepay_horizontal_01.png
rename to public/logos/simplepay_horizontal_01.png
diff --git a/resources/assets/logos/simplepay_horizontal_02-white.png b/public/logos/simplepay_horizontal_02-white.png
similarity index 100%
rename from resources/assets/logos/simplepay_horizontal_02-white.png
rename to public/logos/simplepay_horizontal_02-white.png
diff --git a/resources/assets/logos/simplepay_horizontal_02.png b/public/logos/simplepay_horizontal_02.png
similarity index 100%
rename from resources/assets/logos/simplepay_horizontal_02.png
rename to public/logos/simplepay_horizontal_02.png
diff --git a/resources/assets/logos/simplepay_top-white.png b/public/logos/simplepay_top-white.png
similarity index 100%
rename from resources/assets/logos/simplepay_top-white.png
rename to public/logos/simplepay_top-white.png
diff --git a/resources/assets/logos/simplepay_top.png b/public/logos/simplepay_top.png
similarity index 100%
rename from resources/assets/logos/simplepay_top.png
rename to public/logos/simplepay_top.png
diff --git a/resources/assets/logos/simplepay_vertical-wite.png b/public/logos/simplepay_vertical-wite.png
similarity index 100%
rename from resources/assets/logos/simplepay_vertical-wite.png
rename to public/logos/simplepay_vertical-wite.png
diff --git a/resources/assets/logos/simplepay_vertical.png b/public/logos/simplepay_vertical.png
similarity index 100%
rename from resources/assets/logos/simplepay_vertical.png
rename to public/logos/simplepay_vertical.png
diff --git a/resources/assets/logos/simplepay_w140-white.png b/public/logos/simplepay_w140-white.png
similarity index 100%
rename from resources/assets/logos/simplepay_w140-white.png
rename to public/logos/simplepay_w140-white.png
diff --git a/resources/assets/logos/simplepay_w140.png b/public/logos/simplepay_w140.png
similarity index 100%
rename from resources/assets/logos/simplepay_w140.png
rename to public/logos/simplepay_w140.png
diff --git a/resources/assets/logos/simplepay_w240-white.png b/public/logos/simplepay_w240-white.png
similarity index 100%
rename from resources/assets/logos/simplepay_w240-white.png
rename to public/logos/simplepay_w240-white.png
diff --git a/resources/assets/logos/simplepay_w240.png b/public/logos/simplepay_w240.png
similarity index 100%
rename from resources/assets/logos/simplepay_w240.png
rename to public/logos/simplepay_w240.png
diff --git a/resources/assets/logos/simplepay_w360-white.png b/public/logos/simplepay_w360-white.png
similarity index 100%
rename from resources/assets/logos/simplepay_w360-white.png
rename to public/logos/simplepay_w360-white.png
diff --git a/resources/assets/logos/simplepay_w360.png b/public/logos/simplepay_w360.png
similarity index 100%
rename from resources/assets/logos/simplepay_w360.png
rename to public/logos/simplepay_w360.png
diff --git a/resources/assets/logos/visa_logo_bw.png b/public/logos/visa_logo_bw.png
similarity index 100%
rename from resources/assets/logos/visa_logo_bw.png
rename to public/logos/visa_logo_bw.png
diff --git a/resources/assets/logos/visa_logo_color.png b/public/logos/visa_logo_color.png
similarity index 100%
rename from resources/assets/logos/visa_logo_color.png
rename to public/logos/visa_logo_color.png
diff --git a/resources/assets/variaciok/SimplePay_Logo+MC-Maestro-Visa/simplepay_bankcard_logos_left.png b/public/variaciok/SimplePay_Logo+MC-Maestro-Visa/simplepay_bankcard_logos_left.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo+MC-Maestro-Visa/simplepay_bankcard_logos_left.png
rename to public/variaciok/SimplePay_Logo+MC-Maestro-Visa/simplepay_bankcard_logos_left.png
diff --git a/resources/assets/variaciok/SimplePay_Logo+MC-Maestro-Visa/simplepay_bankcard_logos_top_horizontal.png b/public/variaciok/SimplePay_Logo+MC-Maestro-Visa/simplepay_bankcard_logos_top_horizontal.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo+MC-Maestro-Visa/simplepay_bankcard_logos_top_horizontal.png
rename to public/variaciok/SimplePay_Logo+MC-Maestro-Visa/simplepay_bankcard_logos_top_horizontal.png
diff --git a/resources/assets/variaciok/SimplePay_Logo+Qvik/bankcards_logos_new.png b/public/variaciok/SimplePay_Logo+Qvik/bankcards_logos_new.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo+Qvik/bankcards_logos_new.png
rename to public/variaciok/SimplePay_Logo+Qvik/bankcards_logos_new.png
diff --git a/resources/assets/variaciok/SimplePay_Logo+Qvik/simplepay_bankcard_logos_left_new.png b/public/variaciok/SimplePay_Logo+Qvik/simplepay_bankcard_logos_left_new.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo+Qvik/simplepay_bankcard_logos_left_new.png
rename to public/variaciok/SimplePay_Logo+Qvik/simplepay_bankcard_logos_left_new.png
diff --git a/resources/assets/variaciok/SimplePay_Logo+Qvik/simplepay_bankcard_logos_vertical.png b/public/variaciok/SimplePay_Logo+Qvik/simplepay_bankcard_logos_vertical.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo+Qvik/simplepay_bankcard_logos_vertical.png
rename to public/variaciok/SimplePay_Logo+Qvik/simplepay_bankcard_logos_vertical.png
diff --git a/resources/assets/variaciok/SimplePay_Logo+SZEP/simplepay_bankcard_logos_left_new.png b/public/variaciok/SimplePay_Logo+SZEP/simplepay_bankcard_logos_left_new.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo+SZEP/simplepay_bankcard_logos_left_new.png
rename to public/variaciok/SimplePay_Logo+SZEP/simplepay_bankcard_logos_left_new.png
diff --git a/resources/assets/variaciok/SimplePay_Logo+SZEP/simplepay_bankcard_logos_vertical.png b/public/variaciok/SimplePay_Logo+SZEP/simplepay_bankcard_logos_vertical.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo+SZEP/simplepay_bankcard_logos_vertical.png
rename to public/variaciok/SimplePay_Logo+SZEP/simplepay_bankcard_logos_vertical.png
diff --git a/resources/assets/variaciok/SimplePay_Logo-kartyak_with_Amex/bankcards_logos_new.png b/public/variaciok/SimplePay_Logo-kartyak_with_Amex/bankcards_logos_new.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo-kartyak_with_Amex/bankcards_logos_new.png
rename to public/variaciok/SimplePay_Logo-kartyak_with_Amex/bankcards_logos_new.png
diff --git a/resources/assets/variaciok/SimplePay_Logo-kartyak_with_Amex/simplepay_bankcard_logos_left-hu.png b/public/variaciok/SimplePay_Logo-kartyak_with_Amex/simplepay_bankcard_logos_left-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo-kartyak_with_Amex/simplepay_bankcard_logos_left-hu.png
rename to public/variaciok/SimplePay_Logo-kartyak_with_Amex/simplepay_bankcard_logos_left-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo-kartyak_with_Amex/simplepay_bankcard_logos_left_new-hu.png b/public/variaciok/SimplePay_Logo-kartyak_with_Amex/simplepay_bankcard_logos_left_new-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo-kartyak_with_Amex/simplepay_bankcard_logos_left_new-hu.png
rename to public/variaciok/SimplePay_Logo-kartyak_with_Amex/simplepay_bankcard_logos_left_new-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo-kartyak_with_Amex/simplepay_bankcard_logos_top_horizontal-hu.png b/public/variaciok/SimplePay_Logo-kartyak_with_Amex/simplepay_bankcard_logos_top_horizontal-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo-kartyak_with_Amex/simplepay_bankcard_logos_top_horizontal-hu.png
rename to public/variaciok/SimplePay_Logo-kartyak_with_Amex/simplepay_bankcard_logos_top_horizontal-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo-kartyak_with_Amex/simplepay_bankcard_logos_vertical-hu.png b/public/variaciok/SimplePay_Logo-kartyak_with_Amex/simplepay_bankcard_logos_vertical-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo-kartyak_with_Amex/simplepay_bankcard_logos_vertical-hu.png
rename to public/variaciok/SimplePay_Logo-kartyak_with_Amex/simplepay_bankcard_logos_vertical-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_kartyak_wo_Amex/bankcards_logos_new.png b/public/variaciok/SimplePay_Logo_kartyak_wo_Amex/bankcards_logos_new.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_kartyak_wo_Amex/bankcards_logos_new.png
rename to public/variaciok/SimplePay_Logo_kartyak_wo_Amex/bankcards_logos_new.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_kartyak_wo_Amex/simplepay_bankcard_logos_left-hu.png b/public/variaciok/SimplePay_Logo_kartyak_wo_Amex/simplepay_bankcard_logos_left-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_kartyak_wo_Amex/simplepay_bankcard_logos_left-hu.png
rename to public/variaciok/SimplePay_Logo_kartyak_wo_Amex/simplepay_bankcard_logos_left-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_kartyak_wo_Amex/simplepay_bankcard_logos_left_new-hu.png b/public/variaciok/SimplePay_Logo_kartyak_wo_Amex/simplepay_bankcard_logos_left_new-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_kartyak_wo_Amex/simplepay_bankcard_logos_left_new-hu.png
rename to public/variaciok/SimplePay_Logo_kartyak_wo_Amex/simplepay_bankcard_logos_left_new-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_kartyak_wo_Amex/simplepay_bankcard_logos_top_horizontal-hu.png b/public/variaciok/SimplePay_Logo_kartyak_wo_Amex/simplepay_bankcard_logos_top_horizontal-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_kartyak_wo_Amex/simplepay_bankcard_logos_top_horizontal-hu.png
rename to public/variaciok/SimplePay_Logo_kartyak_wo_Amex/simplepay_bankcard_logos_top_horizontal-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_kartyak_wo_Amex/simplepay_bankcard_logos_top_vertical-hu.png b/public/variaciok/SimplePay_Logo_kartyak_wo_Amex/simplepay_bankcard_logos_top_vertical-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_kartyak_wo_Amex/simplepay_bankcard_logos_top_vertical-hu.png
rename to public/variaciok/SimplePay_Logo_kartyak_wo_Amex/simplepay_bankcard_logos_top_vertical-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_with_Amex+Qvik/bankcards_logos_new.png b/public/variaciok/SimplePay_Logo_with_Amex+Qvik/bankcards_logos_new.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_with_Amex+Qvik/bankcards_logos_new.png
rename to public/variaciok/SimplePay_Logo_with_Amex+Qvik/bankcards_logos_new.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_with_Amex+Qvik/simplepay_bankcard_logos_left-hu.png b/public/variaciok/SimplePay_Logo_with_Amex+Qvik/simplepay_bankcard_logos_left-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_with_Amex+Qvik/simplepay_bankcard_logos_left-hu.png
rename to public/variaciok/SimplePay_Logo_with_Amex+Qvik/simplepay_bankcard_logos_left-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_with_Amex+Qvik/simplepay_bankcard_logos_left_new-hu.png b/public/variaciok/SimplePay_Logo_with_Amex+Qvik/simplepay_bankcard_logos_left_new-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_with_Amex+Qvik/simplepay_bankcard_logos_left_new-hu.png
rename to public/variaciok/SimplePay_Logo_with_Amex+Qvik/simplepay_bankcard_logos_left_new-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_with_Amex+Qvik/simplepay_bankcard_logos_top_horizontal-hu.png b/public/variaciok/SimplePay_Logo_with_Amex+Qvik/simplepay_bankcard_logos_top_horizontal-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_with_Amex+Qvik/simplepay_bankcard_logos_top_horizontal-hu.png
rename to public/variaciok/SimplePay_Logo_with_Amex+Qvik/simplepay_bankcard_logos_top_horizontal-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_with_Amex+Qvik/simplepay_bankcard_logos_top_vertical-hu.png b/public/variaciok/SimplePay_Logo_with_Amex+Qvik/simplepay_bankcard_logos_top_vertical-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_with_Amex+Qvik/simplepay_bankcard_logos_top_vertical-hu.png
rename to public/variaciok/SimplePay_Logo_with_Amex+Qvik/simplepay_bankcard_logos_top_vertical-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_with_Amex/bankcards_logos_new.png b/public/variaciok/SimplePay_Logo_with_Amex/bankcards_logos_new.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_with_Amex/bankcards_logos_new.png
rename to public/variaciok/SimplePay_Logo_with_Amex/bankcards_logos_new.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_with_Amex/simplepay_bankcard_logos_left-hu.png b/public/variaciok/SimplePay_Logo_with_Amex/simplepay_bankcard_logos_left-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_with_Amex/simplepay_bankcard_logos_left-hu.png
rename to public/variaciok/SimplePay_Logo_with_Amex/simplepay_bankcard_logos_left-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_with_Amex/simplepay_bankcard_logos_left_new-hu.png b/public/variaciok/SimplePay_Logo_with_Amex/simplepay_bankcard_logos_left_new-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_with_Amex/simplepay_bankcard_logos_left_new-hu.png
rename to public/variaciok/SimplePay_Logo_with_Amex/simplepay_bankcard_logos_left_new-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_with_Amex/simplepay_bankcard_logos_top_horizontal-hu.png b/public/variaciok/SimplePay_Logo_with_Amex/simplepay_bankcard_logos_top_horizontal-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_with_Amex/simplepay_bankcard_logos_top_horizontal-hu.png
rename to public/variaciok/SimplePay_Logo_with_Amex/simplepay_bankcard_logos_top_horizontal-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_with_Amex/simplepay_bankcard_logos_vertical-hu.png b/public/variaciok/SimplePay_Logo_with_Amex/simplepay_bankcard_logos_vertical-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_with_Amex/simplepay_bankcard_logos_vertical-hu.png
rename to public/variaciok/SimplePay_Logo_with_Amex/simplepay_bankcard_logos_vertical-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_wo_Amex+Qvik/bankcards_logos_new.png b/public/variaciok/SimplePay_Logo_wo_Amex+Qvik/bankcards_logos_new.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_wo_Amex+Qvik/bankcards_logos_new.png
rename to public/variaciok/SimplePay_Logo_wo_Amex+Qvik/bankcards_logos_new.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_wo_Amex+Qvik/simplepay_bankcard_logos_left-hu.png b/public/variaciok/SimplePay_Logo_wo_Amex+Qvik/simplepay_bankcard_logos_left-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_wo_Amex+Qvik/simplepay_bankcard_logos_left-hu.png
rename to public/variaciok/SimplePay_Logo_wo_Amex+Qvik/simplepay_bankcard_logos_left-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_wo_Amex+Qvik/simplepay_bankcard_logos_left_new-hu.png b/public/variaciok/SimplePay_Logo_wo_Amex+Qvik/simplepay_bankcard_logos_left_new-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_wo_Amex+Qvik/simplepay_bankcard_logos_left_new-hu.png
rename to public/variaciok/SimplePay_Logo_wo_Amex+Qvik/simplepay_bankcard_logos_left_new-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_wo_Amex+Qvik/simplepay_bankcard_logos_top_horizontal-hu.png b/public/variaciok/SimplePay_Logo_wo_Amex+Qvik/simplepay_bankcard_logos_top_horizontal-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_wo_Amex+Qvik/simplepay_bankcard_logos_top_horizontal-hu.png
rename to public/variaciok/SimplePay_Logo_wo_Amex+Qvik/simplepay_bankcard_logos_top_horizontal-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_wo_Amex+Qvik/simplepay_bankcard_logos_vertical-hu.png b/public/variaciok/SimplePay_Logo_wo_Amex+Qvik/simplepay_bankcard_logos_vertical-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_wo_Amex+Qvik/simplepay_bankcard_logos_vertical-hu.png
rename to public/variaciok/SimplePay_Logo_wo_Amex+Qvik/simplepay_bankcard_logos_vertical-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_wo_Amex/bankcards_logos_new.png b/public/variaciok/SimplePay_Logo_wo_Amex/bankcards_logos_new.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_wo_Amex/bankcards_logos_new.png
rename to public/variaciok/SimplePay_Logo_wo_Amex/bankcards_logos_new.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_wo_Amex/simplepay_bankcard_logos_left-hu.png b/public/variaciok/SimplePay_Logo_wo_Amex/simplepay_bankcard_logos_left-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_wo_Amex/simplepay_bankcard_logos_left-hu.png
rename to public/variaciok/SimplePay_Logo_wo_Amex/simplepay_bankcard_logos_left-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_wo_Amex/simplepay_bankcard_logos_left_new-hu.png b/public/variaciok/SimplePay_Logo_wo_Amex/simplepay_bankcard_logos_left_new-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_wo_Amex/simplepay_bankcard_logos_left_new-hu.png
rename to public/variaciok/SimplePay_Logo_wo_Amex/simplepay_bankcard_logos_left_new-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_wo_Amex/simplepay_bankcard_logos_top_horizontal-hu.png b/public/variaciok/SimplePay_Logo_wo_Amex/simplepay_bankcard_logos_top_horizontal-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_wo_Amex/simplepay_bankcard_logos_top_horizontal-hu.png
rename to public/variaciok/SimplePay_Logo_wo_Amex/simplepay_bankcard_logos_top_horizontal-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_wo_Amex/simplepay_bankcard_logos_vertical-hu.png b/public/variaciok/SimplePay_Logo_wo_Amex/simplepay_bankcard_logos_vertical-hu.png
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_wo_Amex/simplepay_bankcard_logos_vertical-hu.png
rename to public/variaciok/SimplePay_Logo_wo_Amex/simplepay_bankcard_logos_vertical-hu.png
diff --git a/resources/assets/variaciok/SimplePay_Logo_wo_Amex/szerk/bankcards_logos_new.psd b/public/variaciok/SimplePay_Logo_wo_Amex/szerk/bankcards_logos_new.psd
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_wo_Amex/szerk/bankcards_logos_new.psd
rename to public/variaciok/SimplePay_Logo_wo_Amex/szerk/bankcards_logos_new.psd
diff --git a/resources/assets/variaciok/SimplePay_Logo_wo_Amex/szerk/simplepay_bankcard_logos_left-hu.ai b/public/variaciok/SimplePay_Logo_wo_Amex/szerk/simplepay_bankcard_logos_left-hu.ai
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_wo_Amex/szerk/simplepay_bankcard_logos_left-hu.ai
rename to public/variaciok/SimplePay_Logo_wo_Amex/szerk/simplepay_bankcard_logos_left-hu.ai
diff --git a/resources/assets/variaciok/SimplePay_Logo_wo_Amex/szerk/simplepay_bankcard_logos_left_new-hu.ai b/public/variaciok/SimplePay_Logo_wo_Amex/szerk/simplepay_bankcard_logos_left_new-hu.ai
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_wo_Amex/szerk/simplepay_bankcard_logos_left_new-hu.ai
rename to public/variaciok/SimplePay_Logo_wo_Amex/szerk/simplepay_bankcard_logos_left_new-hu.ai
diff --git a/resources/assets/variaciok/SimplePay_Logo_wo_Amex/szerk/simplepay_bankcard_logos_top_horizontal-hu.ai b/public/variaciok/SimplePay_Logo_wo_Amex/szerk/simplepay_bankcard_logos_top_horizontal-hu.ai
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_wo_Amex/szerk/simplepay_bankcard_logos_top_horizontal-hu.ai
rename to public/variaciok/SimplePay_Logo_wo_Amex/szerk/simplepay_bankcard_logos_top_horizontal-hu.ai
diff --git a/resources/assets/variaciok/SimplePay_Logo_wo_Amex/szerk/simplepay_bankcard_logos_vertical-hu.ai b/public/variaciok/SimplePay_Logo_wo_Amex/szerk/simplepay_bankcard_logos_vertical-hu.ai
similarity index 100%
rename from resources/assets/variaciok/SimplePay_Logo_wo_Amex/szerk/simplepay_bankcard_logos_vertical-hu.ai
rename to public/variaciok/SimplePay_Logo_wo_Amex/szerk/simplepay_bankcard_logos_vertical-hu.ai
diff --git a/resources/boost/skills/simplepay-development/SKILL.md b/resources/boost/skills/simplepay-development/SKILL.md
index a79a687..ea3bf43 100644
--- a/resources/boost/skills/simplepay-development/SKILL.md
+++ b/resources/boost/skills/simplepay-development/SKILL.md
@@ -1,6 +1,9 @@
---
name: simplepay-development
description: Build and integrate SimplePay online payment features using the netipar/simplepay Laravel package, including payment start, IPN webhook handling, back redirects, refunds, two-step payments, card storage (OneClick), recurring payments, auto payments, and Request to Pay (RTP) flows.
+license: MIT
+metadata:
+ author: NETipar
---
# SimplePay Payment Integration Development
diff --git a/routes/simplepay.php b/routes/simplepay.php
index 30308f2..736f1b3 100644
--- a/routes/simplepay.php
+++ b/routes/simplepay.php
@@ -1,5 +1,7 @@
+ */
public function toArray(): array
{
return array_filter([
@@ -28,6 +33,6 @@ public function toArray(): array
'address' => $this->address,
'address2' => $this->address2,
'phone' => $this->phone,
- ], fn ($value) => $value !== null);
+ ], fn (mixed $value): bool => $value !== null);
}
}
diff --git a/src/Dto/ApplePayDoRequest.php b/src/Dto/ApplePayDoRequest.php
index a19af2e..6cc8e61 100644
--- a/src/Dto/ApplePayDoRequest.php
+++ b/src/Dto/ApplePayDoRequest.php
@@ -1,5 +1,7 @@
+ */
public function toArray(): array
{
return [
diff --git a/src/Dto/ApplePayStartRequest.php b/src/Dto/ApplePayStartRequest.php
index 3f0eb7f..defaec9 100644
--- a/src/Dto/ApplePayStartRequest.php
+++ b/src/Dto/ApplePayStartRequest.php
@@ -1,5 +1,7 @@
+ */
public function toArray(): array
{
return [
diff --git a/src/Dto/AutoPaymentRequest.php b/src/Dto/AutoPaymentRequest.php
index 8b60506..96cd241 100644
--- a/src/Dto/AutoPaymentRequest.php
+++ b/src/Dto/AutoPaymentRequest.php
@@ -1,5 +1,7 @@
+ */
public function toArray(): array
{
return array_filter([
@@ -41,6 +46,6 @@ public function toArray(): array
'delivery' => $this->delivery?->toArray(),
'items' => $this->items ? array_map(fn (Item $item) => $item->toArray(), $this->items) : null,
'sdkVersion' => 'netipar-simplepay:laravel',
- ], fn ($value) => $value !== null);
+ ], fn (mixed $value): bool => $value !== null);
}
}
diff --git a/src/Dto/BackResponse.php b/src/Dto/BackResponse.php
index af80854..0c69632 100644
--- a/src/Dto/BackResponse.php
+++ b/src/Dto/BackResponse.php
@@ -1,5 +1,7 @@
+ */
public function toArray(): array
{
return array_filter([
@@ -30,6 +35,6 @@ public function toArray(): array
'timeZone' => $this->timeZone,
'windowSize' => $this->windowSize,
'challengePreference' => $this->challengePreference,
- ], fn ($value) => $value !== null);
+ ], fn (mixed $value): bool => $value !== null);
}
}
diff --git a/src/Dto/CardData.php b/src/Dto/CardData.php
index ed03473..26e206c 100644
--- a/src/Dto/CardData.php
+++ b/src/Dto/CardData.php
@@ -1,5 +1,7 @@
+ */
public function toArray(): array
{
return array_filter([
@@ -18,6 +23,6 @@ public function toArray(): array
'expiry' => $this->expiry,
'cvc' => $this->cvc,
'holder' => $this->cardHolder,
- ], fn ($value) => $value !== null);
+ ], fn (mixed $value): bool => $value !== null);
}
}
diff --git a/src/Dto/CardStorageDoRequest.php b/src/Dto/CardStorageDoRequest.php
index 5e5945d..3e2934a 100644
--- a/src/Dto/CardStorageDoRequest.php
+++ b/src/Dto/CardStorageDoRequest.php
@@ -1,5 +1,7 @@
+ *
* @throws RandomException
*/
public function toArray(): array
@@ -37,6 +41,6 @@ public function toArray(): array
'customerEmail' => $this->customerEmail,
'url' => $this->url,
'items' => $this->items ? array_map(fn (Item $item) => $item->toArray(), $this->items) : null,
- ], fn ($value) => $value !== null);
+ ], fn (mixed $value): bool => $value !== null);
}
}
diff --git a/src/Dto/EamStartRequest.php b/src/Dto/EamStartRequest.php
index 4b91c7d..cbca652 100644
--- a/src/Dto/EamStartRequest.php
+++ b/src/Dto/EamStartRequest.php
@@ -1,5 +1,7 @@
+ *
* @throws RandomException
*/
public function toArray(): array
@@ -33,6 +37,6 @@ public function toArray(): array
'customerEmail' => $this->customerEmail,
'url' => $this->url,
'items' => $this->items ? array_map(fn (Item $item) => $item->toArray(), $this->items) : null,
- ], fn ($value) => $value !== null);
+ ], fn (mixed $value): bool => $value !== null);
}
}
diff --git a/src/Dto/FinishRequest.php b/src/Dto/FinishRequest.php
index add140a..be64627 100644
--- a/src/Dto/FinishRequest.php
+++ b/src/Dto/FinishRequest.php
@@ -1,5 +1,7 @@
+ *
* @throws RandomException
*/
public function toArray(): array
diff --git a/src/Dto/FinishResponse.php b/src/Dto/FinishResponse.php
index 8c8286c..e41c69f 100644
--- a/src/Dto/FinishResponse.php
+++ b/src/Dto/FinishResponse.php
@@ -1,5 +1,7 @@
$data
+ */
public static function fromArray(array $data): self
{
return new self(
diff --git a/src/Dto/IpnMessage.php b/src/Dto/IpnMessage.php
index 01fbfd2..df243a4 100644
--- a/src/Dto/IpnMessage.php
+++ b/src/Dto/IpnMessage.php
@@ -1,5 +1,7 @@
$data
+ */
public static function fromArray(array $data): self
{
return new self(
diff --git a/src/Dto/Item.php b/src/Dto/Item.php
index 76c85be..db73eda 100644
--- a/src/Dto/Item.php
+++ b/src/Dto/Item.php
@@ -1,5 +1,7 @@
+ */
public function toArray(): array
{
return array_filter([
@@ -22,6 +27,6 @@ public function toArray(): array
'amount' => $this->quantity,
'price' => $this->price,
'tax' => $this->tax,
- ], fn ($value) => $value !== null);
+ ], fn (mixed $value): bool => $value !== null);
}
}
diff --git a/src/Dto/PaymentRequest.php b/src/Dto/PaymentRequest.php
index d056265..e585229 100644
--- a/src/Dto/PaymentRequest.php
+++ b/src/Dto/PaymentRequest.php
@@ -1,5 +1,7 @@
$methods
* @param array|null $items
+ * @param array|null $recurring
*/
public function __construct(
public Currency $currency,
@@ -36,6 +39,8 @@ public function __construct(
) {}
/**
+ * @return array
+ *
* @throws RandomException
*/
public function toArray(): array
diff --git a/src/Dto/PaymentResponse.php b/src/Dto/PaymentResponse.php
index 421f245..9c7f2cd 100644
--- a/src/Dto/PaymentResponse.php
+++ b/src/Dto/PaymentResponse.php
@@ -1,5 +1,7 @@
$data
+ */
public static function fromArray(array $data): self
{
return new self(
- transactionId: $data['transactionId'],
+ transactionId: (int) $data['transactionId'],
paymentUrl: $data['paymentUrl'],
timeout: $data['timeout'],
);
diff --git a/src/Dto/QueryResponse.php b/src/Dto/QueryResponse.php
index ee488d9..bf5f677 100644
--- a/src/Dto/QueryResponse.php
+++ b/src/Dto/QueryResponse.php
@@ -1,5 +1,7 @@
$data
+ */
public static function fromArray(array $data): self
{
$transaction = $data['transactions'][0] ?? null;
diff --git a/src/Dto/RecurringRequest.php b/src/Dto/RecurringRequest.php
index 2034eef..81fce12 100644
--- a/src/Dto/RecurringRequest.php
+++ b/src/Dto/RecurringRequest.php
@@ -1,5 +1,7 @@
+ *
* @throws RandomException
*/
public function toArray(): array
@@ -38,6 +42,6 @@ public function toArray(): array
'url' => $this->url,
'type' => $this->type->value,
'items' => $this->items ? array_map(fn (Item $item) => $item->toArray(), $this->items) : null,
- ], fn ($value) => $value !== null);
+ ], fn (mixed $value): bool => $value !== null);
}
}
diff --git a/src/Dto/RefundRequest.php b/src/Dto/RefundRequest.php
index c921f4a..238f0ea 100644
--- a/src/Dto/RefundRequest.php
+++ b/src/Dto/RefundRequest.php
@@ -1,5 +1,7 @@
+ *
* @throws RandomException
*/
public function toArray(): array
diff --git a/src/Dto/RefundResponse.php b/src/Dto/RefundResponse.php
index ae1b4b0..1b28e63 100644
--- a/src/Dto/RefundResponse.php
+++ b/src/Dto/RefundResponse.php
@@ -1,5 +1,7 @@
$data
+ */
public static function fromArray(array $data): self
{
return new self(
diff --git a/src/Dto/RtpDoRequest.php b/src/Dto/RtpDoRequest.php
index 9cf8a5c..341fe70 100644
--- a/src/Dto/RtpDoRequest.php
+++ b/src/Dto/RtpDoRequest.php
@@ -1,5 +1,7 @@
+ *
* @throws RandomException
*/
public function toArray(): array
diff --git a/src/Dto/RtpPayment.php b/src/Dto/RtpPayment.php
index 1641f8e..9f86201 100644
--- a/src/Dto/RtpPayment.php
+++ b/src/Dto/RtpPayment.php
@@ -1,5 +1,7 @@
+ */
public function toArray(): array
{
return [
diff --git a/src/Dto/RtpStartRequest.php b/src/Dto/RtpStartRequest.php
index db5ddde..4fcc6f4 100644
--- a/src/Dto/RtpStartRequest.php
+++ b/src/Dto/RtpStartRequest.php
@@ -1,5 +1,7 @@
+ *
* @throws RandomException
*/
public function toArray(): array
diff --git a/src/Enums/BackEvent.php b/src/Enums/BackEvent.php
index 6e61fc1..e5658ee 100644
--- a/src/Enums/BackEvent.php
+++ b/src/Enums/BackEvent.php
@@ -1,5 +1,7 @@
*/
private array $resolvedCodes;
+ /** @var array */
+ private array $responseData;
+
/**
* @param array $errorCodes
+ * @param array $responseData
*/
public function __construct(array $errorCodes, array $responseData = [])
{
$this->errorCodes = $errorCodes;
+ $this->responseData = $responseData;
$this->resolvedCodes = array_filter(
array_map(fn (int $code) => ErrorCode::tryFrom($code), $errorCodes),
);
@@ -56,4 +63,14 @@ public function hasErrorCode(int $code): bool
{
return in_array($code, $this->errorCodes, true);
}
+
+ /**
+ * The full API response body, e.g. the `redirectUrl` of a 3DS challenge (error code 3004).
+ *
+ * @return array
+ */
+ public function getResponseData(): array
+ {
+ return $this->responseData;
+ }
}
diff --git a/src/Facades/SimplePay.php b/src/Facades/SimplePay.php
index 528320f..aa6da72 100644
--- a/src/Facades/SimplePay.php
+++ b/src/Facades/SimplePay.php
@@ -1,5 +1,7 @@
$data
+ */
private function resolveSecretKey(array $data): ?string
{
if (isset($data['currency'])) {
diff --git a/src/Http/Responses/DefaultBackUrlResponse.php b/src/Http/Responses/DefaultBackUrlResponse.php
index 3da3273..b5541da 100644
--- a/src/Http/Responses/DefaultBackUrlResponse.php
+++ b/src/Http/Responses/DefaultBackUrlResponse.php
@@ -1,5 +1,7 @@
+ *
* @throws ConnectionException
*/
public function auto(AutoPaymentRequest $request): array
diff --git a/src/Services/CardStorageService.php b/src/Services/CardStorageService.php
index cf75456..5b51c00 100644
--- a/src/Services/CardStorageService.php
+++ b/src/Services/CardStorageService.php
@@ -1,5 +1,7 @@
+ *
* @throws RandomException|ConnectionException
*/
public function do(CardStorageDoRequest $request): array
@@ -32,6 +36,8 @@ public function do(CardStorageDoRequest $request): array
}
/**
+ * @return array
+ *
* @throws RandomException|ConnectionException
*/
public function doRecurring(RecurringRequest $request): array
@@ -46,6 +52,8 @@ public function doRecurring(RecurringRequest $request): array
}
/**
+ * @return array
+ *
* @throws RandomException|ConnectionException
*/
public function cardQuery(Currency $currency, string $cardId, bool $history = false): array
@@ -64,6 +72,8 @@ public function cardQuery(Currency $currency, string $cardId, bool $history = fa
}
/**
+ * @return array
+ *
* @throws RandomException|ConnectionException
*/
public function cardCancel(Currency $currency, string $cardId): array
@@ -81,6 +91,8 @@ public function cardCancel(Currency $currency, string $cardId): array
}
/**
+ * @return array
+ *
* @throws RandomException|ConnectionException
*/
public function tokenQuery(Currency $currency, string $token): array
@@ -98,6 +110,8 @@ public function tokenQuery(Currency $currency, string $token): array
}
/**
+ * @return array
+ *
* @throws RandomException|ConnectionException
*/
public function tokenCancel(Currency $currency, string $token): array
diff --git a/src/Services/PaymentService.php b/src/Services/PaymentService.php
index 3815f9f..6e874b3 100644
--- a/src/Services/PaymentService.php
+++ b/src/Services/PaymentService.php
@@ -1,5 +1,7 @@
+ *
* @throws RandomException
* @throws ConnectionException
*/
@@ -62,6 +66,8 @@ public function startEam(EamStartRequest $request): array
}
/**
+ * @return array
+ *
* @throws ConnectionException
*/
public function startApplePay(ApplePayStartRequest $request): array
@@ -76,6 +82,8 @@ public function startApplePay(ApplePayStartRequest $request): array
}
/**
+ * @return array
+ *
* @throws ConnectionException
*/
public function doApplePay(ApplePayDoRequest $request): array
@@ -174,6 +182,8 @@ public function query(Currency $currency, ?int $transactionId = null, ?string $o
}
/**
+ * @return array
+ *
* @throws RandomException
* @throws ConnectionException
*/
diff --git a/src/Services/RtpService.php b/src/Services/RtpService.php
index 1b2cd02..2d0f369 100644
--- a/src/Services/RtpService.php
+++ b/src/Services/RtpService.php
@@ -1,5 +1,7 @@
+ *
* @throws RandomException
* @throws ConnectionException
*/
@@ -47,6 +51,8 @@ public function do(RtpDoRequest $request): array
}
/**
+ * @return array
+ *
* @throws RandomException|ConnectionException
*/
public function query(Currency $currency, ?string $transactionId = null, ?string $orderRef = null): array
@@ -70,6 +76,8 @@ public function query(Currency $currency, ?string $transactionId = null, ?string
}
/**
+ * @return array
+ *
* @throws RandomException|ConnectionException
*/
public function refund(Currency $currency, string $transactionId, float $amount): array
@@ -87,6 +95,8 @@ public function refund(Currency $currency, string $transactionId, float $amount)
}
/**
+ * @return array
+ *
* @throws RandomException|ConnectionException
*/
public function reverse(Currency $currency, string $transactionId): array
diff --git a/src/SimplePay.php b/src/SimplePay.php
index 946c935..2f94470 100644
--- a/src/SimplePay.php
+++ b/src/SimplePay.php
@@ -1,5 +1,7 @@
mergeConfigFrom(__DIR__.'/../config/simplepay.php', 'simplepay');
@@ -20,18 +25,23 @@ public function register(): void
$this->app->singleton(BackUrlResponse::class, DefaultBackUrlResponse::class);
}
+ /**
+ * Bootstrap any application services.
+ */
public function boot(): void
{
- if ($this->app->runningInConsole()) {
- $this->publishes([
- __DIR__.'/../config/simplepay.php' => config_path('simplepay.php'),
- ], 'simplepay-config');
-
- $this->publishes([
- __DIR__.'/../resources/assets' => public_path('vendor/simplepay'),
- ], 'simplepay-assets');
+ $this->loadRoutesFrom(__DIR__.'/../routes/simplepay.php');
+
+ if (! $this->app->runningInConsole()) {
+ return;
}
- $this->loadRoutesFrom(__DIR__.'/../routes/simplepay.php');
+ $this->publishes([
+ __DIR__.'/../config/simplepay.php' => config_path('simplepay.php'),
+ ], ['simplepay', 'simplepay-config']);
+
+ $this->publishes([
+ __DIR__.'/../public' => public_path('vendor/simplepay'),
+ ], ['simplepay', 'simplepay-assets']);
}
}
diff --git a/src/Support/Client.php b/src/Support/Client.php
index 35c20e3..9ec0df8 100644
--- a/src/Support/Client.php
+++ b/src/Support/Client.php
@@ -1,5 +1,7 @@
$data
+ * @return array
+ *
* @throws ConnectionException
*/
public function post(string $endpoint, array $data, string $merchantKey): array
{
$url = $this->buildUrl($endpoint);
- $json = json_encode($data);
+ $json = json_encode($data, JSON_THROW_ON_ERROR);
$signature = Signature::generate($merchantKey, $json);
$this->log('SimplePay request', ['url' => $url, 'data' => $data]);
@@ -36,12 +41,15 @@ public function post(string $endpoint, array $data, string $merchantKey): array
}
/**
+ * @param array $data
+ * @return array
+ *
* @throws ConnectionException
*/
public function postSecurePay(string $endpoint, array $data, string $merchantKey): array
{
$url = $this->buildSecurePayUrl($endpoint);
- $json = json_encode($data);
+ $json = json_encode($data, JSON_THROW_ON_ERROR);
$signature = Signature::generate($merchantKey, $json);
$this->log('SimplePay securepay request', ['url' => $url, 'data' => $data]);
@@ -97,6 +105,9 @@ private function validateResponse(Response $response, string $merchantKey): void
}
}
+ /**
+ * @param array $context
+ */
private function log(string $message, array $context = []): void
{
$channel = config('simplepay.log_channel');
diff --git a/src/Support/MerchantResolver.php b/src/Support/MerchantResolver.php
index ff314cb..9914acf 100644
--- a/src/Support/MerchantResolver.php
+++ b/src/Support/MerchantResolver.php
@@ -1,5 +1,7 @@
preset()->php();
+
+arch()->preset()->security();
+
+arch('it will not use dd(), ddd(), env(), or exit()')
+ ->expect(['dd', 'ddd', 'env', 'exit'])
+ ->each->not->toBeUsed();
+
+arch('the package source declares strict types')
+ ->expect('Netipar\SimplePay')
+ ->toUseStrictTypes();
diff --git a/tests/Feature/ConfigTest.php b/tests/Feature/ConfigTest.php
index 8c80e11..3e94aca 100644
--- a/tests/Feature/ConfigTest.php
+++ b/tests/Feature/ConfigTest.php
@@ -1,5 +1,7 @@
toBeInstanceOf(SimplePay::class)
+ ->and(app(SimplePay::class))->toBe(app(SimplePay::class));
+});
+
+it('registers the IPN and back routes', function () {
+ expect(Route::has('simplepay.ipn'))->toBeTrue()
+ ->and(Route::has('simplepay.back'))->toBeTrue();
+});
+
+it('publishes the config file under its own tag', function () {
+ $paths = ServiceProvider::pathsToPublish(SimplePayServiceProvider::class, 'simplepay-config');
+
+ expect(array_values($paths))->toBe([config_path('simplepay.php')])
+ ->and(array_keys($paths)[0])->toBeFile();
+});
+
+it('publishes the logo assets under its own tag', function () {
+ $paths = ServiceProvider::pathsToPublish(SimplePayServiceProvider::class, 'simplepay-assets');
+
+ expect(array_values($paths))->toBe([public_path('vendor/simplepay')])
+ ->and(array_keys($paths)[0].'/logos/simplepay_200x50.png')->toBeFile();
+});
+
+it('publishes every resource under the package tag', function () {
+ $paths = ServiceProvider::pathsToPublish(SimplePayServiceProvider::class, 'simplepay');
+
+ expect(array_values($paths))->toBe([
+ config_path('simplepay.php'),
+ public_path('vendor/simplepay'),
+ ]);
+});
diff --git a/tests/Pest.php b/tests/Pest.php
index f114f14..28b3657 100644
--- a/tests/Pest.php
+++ b/tests/Pest.php
@@ -1,5 +1,7 @@
in('Unit', 'Feature');
+uses(TestCase::class)->in(__DIR__);
diff --git a/tests/TestCase.php b/tests/TestCase.php
index 1fa3893..deb6d9f 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -1,11 +1,13 @@
Http::response([
+ 'errorCodes' => [3004],
+ 'transactionId' => 123456,
+ 'redirectUrl' => 'https://sandbox.simplepay.hu/3ds/challenge',
+ ]),
+ ]);
+
+ $request = new CardStorageDoRequest(
+ currency: Currency::HUF,
+ transactionId: 123456,
+ cardId: 'card-abc-123',
+ orderRef: 'ORDER-001',
+ total: 1500,
+ customerEmail: 'test@example.com',
+ url: 'https://example.com/back',
+ );
+
+ expect(fn () => createCardStorageService()->do($request))
+ ->toThrow(function (SimplePayApiException $exception) {
+ expect($exception->hasErrorCode(3004))->toBeTrue()
+ ->and($exception->getResponseData())
+ ->toHaveKey('redirectUrl', 'https://sandbox.simplepay.hu/3ds/challenge');
+ });
+});
+
it('sends a do request with items', function () {
Http::fake([
'sandbox.simplepay.hu/payment/v2/do' => Http::response([
diff --git a/tests/Unit/MerchantResolverTest.php b/tests/Unit/MerchantResolverTest.php
index bd0685b..e4d0665 100644
--- a/tests/Unit/MerchantResolverTest.php
+++ b/tests/Unit/MerchantResolverTest.php
@@ -1,5 +1,7 @@
'502272810',
+ 'paymentUrl' => 'https://sandbox.simplepay.hu/pay/rtp/pspHU/abc',
+ 'timeout' => '2026-10-17T12:00:00+02:00',
+ ]);
+
+ expect($response->transactionId)->toBe(502272810);
+});
diff --git a/tests/Unit/PaymentServiceTest.php b/tests/Unit/PaymentServiceTest.php
index 1637a48..4a24f17 100644
--- a/tests/Unit/PaymentServiceTest.php
+++ b/tests/Unit/PaymentServiceTest.php
@@ -1,5 +1,7 @@
*/
+ use HasFactory, Notifiable;
+
+ /**
+ * Get the attributes that should be cast.
+ *
+ * @return array
+ */
+ protected function casts(): array
+ {
+ return [
+ 'email_verified_at' => 'datetime',
+ 'password' => 'hashed',
+ ];
+ }
+}
diff --git a/workbench/app/Providers/WorkbenchServiceProvider.php b/workbench/app/Providers/WorkbenchServiceProvider.php
new file mode 100644
index 0000000..d09c191
--- /dev/null
+++ b/workbench/app/Providers/WorkbenchServiceProvider.php
@@ -0,0 +1,26 @@
+withRouting(
+ web: __DIR__.'/../routes/web.php',
+ commands: __DIR__.'/../routes/console.php',
+ )
+ ->withMiddleware(function (Middleware $middleware): void {
+ //
+ })
+ ->withExceptions(function (Exceptions $exceptions): void {
+ //
+ })->create();
diff --git a/workbench/database/factories/.gitkeep b/workbench/database/factories/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/workbench/database/factories/UserFactory.php b/workbench/database/factories/UserFactory.php
new file mode 100644
index 0000000..6268042
--- /dev/null
+++ b/workbench/database/factories/UserFactory.php
@@ -0,0 +1,54 @@
+
+ */
+class UserFactory extends Factory
+{
+ /**
+ * The current password being used by the factory.
+ */
+ protected static ?string $password;
+
+ /**
+ * The name of the factory's corresponding model.
+ *
+ * @var class-string
+ */
+ protected $model = User::class;
+
+ /**
+ * Define the model's default state.
+ *
+ * @return array
+ */
+ public function definition(): array
+ {
+ return [
+ 'name' => fake()->name(),
+ 'email' => fake()->unique()->safeEmail(),
+ 'email_verified_at' => now(),
+ 'password' => static::$password ??= Hash::make('password'),
+ 'remember_token' => Str::random(10),
+ ];
+ }
+
+ /**
+ * Indicate that the model's email address should be unverified.
+ */
+ public function unverified(): static
+ {
+ return $this->state(fn (array $attributes) => [
+ 'email_verified_at' => null,
+ ]);
+ }
+}
diff --git a/workbench/database/migrations/.gitkeep b/workbench/database/migrations/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/workbench/database/seeders/DatabaseSeeder.php b/workbench/database/seeders/DatabaseSeeder.php
new file mode 100644
index 0000000..4105579
--- /dev/null
+++ b/workbench/database/seeders/DatabaseSeeder.php
@@ -0,0 +1,27 @@
+times(10)->create();
+
+ UserFactory::new()->create([
+ 'name' => 'Test User',
+ 'email' => 'test@example.com',
+ ]);
+ }
+}
diff --git a/workbench/resources/views/.gitkeep b/workbench/resources/views/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/workbench/routes/console.php b/workbench/routes/console.php
new file mode 100644
index 0000000..7b00eec
--- /dev/null
+++ b/workbench/routes/console.php
@@ -0,0 +1,10 @@
+comment(Inspiring::quote());
+// })->purpose('Display an inspiring quote');
diff --git a/workbench/routes/web.php b/workbench/routes/web.php
new file mode 100644
index 0000000..7bceeaf
--- /dev/null
+++ b/workbench/routes/web.php
@@ -0,0 +1,9 @@
+