Skip to content

Payments Ledger with Paystack Webhook Verification & Double-Entry Reconciliation #41

Description

@meshackyaro

Description

This issue aims to address the implementation of Payments Ledger with Paystack Webhook Verification & Double-Entry Reconciliation.

The core objective is to: Turn the half-built Paystack integration into a trustworthy money path — signature-verified webhooks, an append-only double-entry ledger, an explicit payout state machine, and a reconciliation job that proves the platform's books match the provider's.

By completing this feature, we will ensure that the GuildWorkman protocol maintains its high standards for security, usability, and decentralized logic. This issue requires careful attention to the Backend architecture and adherence to the existing project conventions.

When picking up this issue, please ensure you document any new dependencies or architectural decisions made during development.

Component

Backend (Spring Boot / Java 17)

Difficulty

⚫ Very Hard

Current state

The payment path is currently a shell:

  • controllers/PaymentController.java is entirely commented out — there is no payment endpoint and no webhook receiver at all.
  • services/implmentations/TransactionServiceImpl.java and TransactionHistoryServiceImpl are empty @Service stubs, despite Transaction, TransactionHistory, and TransactionStatus models existing.
  • Payment state today therefore depends on the client calling back after a redirect, which is not a source of truth — a dropped callback silently loses a payment.

Money that can be lost by closing a browser tab is the problem this issue closes. Note that this is the fiat leg; the on-chain leg is tracked separately, and the reconciliation model here must leave room for both.

Tasks

  • Review the existing Spring Boot structure under backend-api/src/main/java
  • Implement the service and REST endpoints for: Payments Ledger with Paystack Webhook Verification & Double-Entry Reconciliation
  • Restore PaymentController as a real controller and add a webhook endpoint that verifies the Paystack x-paystack-signature HMAC over the raw request body, rejecting unverified payloads before any parsing
  • Make webhook handling idempotent by provider event id — Paystack retries, and a retry must never credit twice
  • Implement an append-only double-entry ledger (balanced debit/credit entries, no destructive updates) as the authoritative record, with Transaction/TransactionHistory derived from it
  • Model the payout lifecycle as an explicit state machine with documented legal transitions, covering success, failure, reversal, and refund
  • Implement a scheduled reconciliation job that pulls provider-side state and flags any divergence rather than silently correcting it
  • Ensure the webhook path is reachable without authentication but is protected by signature verification, and account for it explicitly in config/SecurityConfig.java
  • Add or adjust JPA entities, repositories, and schema migrations as needed
  • Write unit and integration tests (Spring Boot Test; MockWebServer for external RPC calls), including forged-signature, replayed-event, and out-of-order-event cases
  • Add caching for Maven dependencies in CI
  • Run ./mvnw verify and ./mvnw test to validate build and coverage

Acceptance Criteria

  • Feature accurately implements the objective: Turn the half-built Paystack integration into a trustworthy money path — signature-verified webhooks, an append-only double-entry ledger, an explicit payout state machine, and a reconciliation job that proves the platform's books match the provider's.
  • A webhook with a missing or forged signature is rejected and never mutates ledger state
  • The same provider event delivered twice produces exactly one ledger effect
  • Every ledger account balances: total debits equal total credits, asserted by test
  • A payment completes correctly even when the client never returns from the redirect
  • Illegal state transitions are rejected rather than silently applied
  • Reconciliation surfaces divergence between platform and provider state as an actionable signal
  • Any PR that introduces failing tests or compilation errors is automatically blocked
  • Endpoints/services are covered by tests including failure and concurrency paths
  • Public API is documented (OpenAPI) and errors follow a consistent response contract
  • Code is properly reviewed and approved by codeowners

Estimated Time

4-6 days

Metadata

Metadata

Assignees

No one assigned

    Labels

    GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial Campaign | FWC26Campaign: Official Campaign | FWC26backendBackend API (Spring Boot) workdifficulty: very hard⚫ Very HardenhancementNew feature or requesthelp wantedExtra attention is neededpriority: high🔴 High priority — core / blocking

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions