Skip to content

Contributing to OwnPay โ€‹

First off - thank you for considering a contribution to OwnPay! ๐ŸŽ‰ Whether it's a bug report, a new payment gateway, a translation, a documentation fix, or a feature, every contribution helps make self-hosted, open-source payment infrastructure better for everyone.

This guide explains how to get involved effectively.


๐Ÿ“œ Code of Conduct โ€‹

This project and everyone participating in it is governed by our Code of Conduct. By participating, you are expected to uphold it. Please report unacceptable behavior to [email protected].


๐Ÿงญ Ways to Contribute โ€‹

  • ๐Ÿ› Report bugs - open a clear, reproducible issue.
  • ๐Ÿ’ก Suggest features - start a discussion or feature request.
  • ๐Ÿ”Œ Build a gateway/plugin - add a payment gateway or add-on (see below).
  • ๐ŸŒ Translate - add or improve a language catalog (see TRANSLATIONS.md).
  • ๐Ÿ“– Improve docs - fix typos, clarify guides, expand examples.
  • ๐Ÿงน Improve code - fix bugs, add tests, refactor with care.

Not sure where to start? Look for issues labelled good first issue or help wanted.


๐Ÿš€ Getting Set Up โ€‹

  1. Fork the repository and clone your fork.
  2. Follow Local Setup to get a local instance running (~2 minutes).
  3. Create a feature branch from dev (the integration branch PRs target):
    bash
    git checkout dev
    git checkout -b feat/short-description

Requirements: PHP 8.3+ (bcmath, json, mbstring, openssl, pdo_mysql, curl), Composer 2, MySQL 8 / MariaDB 10.4+.


๐Ÿ” Development Workflow โ€‹

  1. Make your changes in a focused branch (one logical change per PR).
  2. Add or update tests for any behavior you change.
  3. Run the full local check suite (this is what CI runs):
    bash
    composer test       # PHPUnit - all tests must pass
    composer analyse    # PHPStan - must stay clean at level 9
    composer lint       # Twig + JS + CSS linting
  4. Commit with a clear message and a DCO sign-off (see below).
  5. Push to your fork and open a Pull Request against dev.

โœ… PRs must pass composer test, composer analyse, and composer lint before review. Green checks get reviewed faster.


๐ŸŽฏ Coding Standards โ€‹

OwnPay maintains a high quality bar. Please match the existing code and these rules:

  • Strict types everywhere. Every PHP file starts with declare(strict_types=1); as its first statement (no BOM).
  • PHPStan level 9 must stay green. Don't suppress errors with baselines, @phpstan-ignore, or needless casts - fix the root cause.
  • Money is always bcmath strings, never floats. Financial correctness is non-negotiable.
  • Tenant scoping is mandatory. Never run a scoped query without forTenant() / *Scoped(); use forAllTenants() only for deliberate owner-level views.
  • Build URLs via DomainUrlService (buildCheckoutUrl(), buildCallbackUrl()) - never hardcode a host (white-label domains depend on this).
  • CSRF tokens via SecurityHelpers::csrfToken() - never read $_SESSION directly.
  • Prepared statements only. No string-interpolated SQL, ever.
  • Escape output. Twig autoescaping stays on; never |raw untrusted data.
  • Keep it lean. No new heavyweight dependencies without discussion; prefer the existing first-party utilities.
  • Comments explain why, not what. Document non-obvious decisions.

For the full feature inventory, see the Feature Reference. For the bigger picture, read the Architecture Guide.


๐Ÿ”Œ Contributing a Payment Gateway or Plugin โ€‹

Gateways and add-ons are plugins under modules/:

  1. Create modules/gateways/<slug>/ with a manifest.json (metadata, capabilities, CSP origins, icon).
  2. Add an adapter class implementing OwnPay\Gateway\GatewayAdapterInterface (use the GatewayDefaults trait for no-op defaults).
  3. Declare supportedCurrencies() accurately (return [] for "any currency").
  4. Keep the plugin within the sandbox rules - no exec, shell_exec, eval, raw PDO, etc.
  5. Test the full flow (initiate โ†’ callback โ†’ verify โ†’ refund) locally.

See the gateway developer guide on Gateway Developer Guide for the full contract and examples.


๐ŸŒ Contributing Translations โ€‹

OwnPay has full i18n for both the admin panel and customer checkout. To add or update a language, follow TRANSLATIONS.md - create a dot-notation JSON catalog (keep :placeholders intact) and place core languages in config/languages/.


โœ๏ธ Commit Messages & DCO Sign-Off โ€‹

We use the Developer Certificate of Origin (DCO). By signing off, you certify you have the right to submit the contribution under the project's license.

Add a sign-off line to every commit by using the -s flag:

bash
git commit -s -m "feat(gateway): add Acme Pay adapter"

This appends:

Signed-off-by: Your Name <[email protected]>

Please write clear messages. We encourage Conventional Commits style (feat:, fix:, docs:, refactor:, test:, chore:), though it isn't strictly enforced.


๐Ÿ“ฅ Pull Request Guidelines โ€‹

  • Keep PRs focused - one logical change each. Split large work into reviewable pieces.
  • Fill out the PR description: what changed, why, and how to test it.
  • Link the related issue (e.g. Closes #123).
  • Update documentation and tests alongside code.
  • Be responsive to review feedback - we review with care because this is payment software.
  • Ensure all CI checks are green.

โš–๏ธ Licensing of Contributions โ€‹

OwnPay is licensed under the GNU AGPL-3.0. By submitting a contribution, you agree that your work is licensed under the same AGPL-3.0 license as the project (inbound = outbound), and you certify its origin via your DCO sign-off. No separate CLA is required.


๐Ÿ™ Thank You โ€‹

Every issue, PR, translation, and idea moves OwnPay forward. We're building this in the open, for the community - and we're glad you're here.

Questions about contributing? Reach out at [email protected] or open a discussion.


โค๏ธ Built by the Community, for the Community.