Skip to content

BTI-977 - Add payment method: Point Of Sale#18

Closed
ShuCh3n wants to merge 36 commits into
masterfrom
BTI-977
Closed

BTI-977 - Add payment method: Point Of Sale#18
ShuCh3n wants to merge 36 commits into
masterfrom
BTI-977

Conversation

@ShuCh3n

@ShuCh3n ShuCh3n commented Jul 16, 2026

Copy link
Copy Markdown

No description provided.

buckaroo-shu and others added 30 commits April 15, 2026 10:55
…1.0.0

- Introduce a cleaner inheritance model with `BaseBuilder` and `PaymentBuilder`.
- Decouple transaction execution from builders via a new `TransactionExecutor` service.
- Implement `TransactionContext` to handle follow-up operations (refund, capture, cancel) explicitly instead of relying on internal payload state.
- Standardize method naming to PEP 8 snake_case across all builders and capability mixins.
- Enhance the HTTP client with better error wrapping, logging, and FIPS-compliant MD5 hashing.
- Add GitHub Actions CI, a formal changelog, and modernized packaging metadata for the v1.0.0 release.
Adds comprehensive example scripts for Credit Card, iDEAL, In3, and PayPal. These examples demonstrate standard integration flows, including encrypted card data, Hosted Fields, two-step authorization/capture, recurring payments, and refunds.
Removes the example for paying with a pre-selected bank issuer and renames the generic payment example to `example_pay`. This streamlines the demonstration to focus on the standard flow where Buckaroo handles bank selection.
…mprehensive test suite

- Apply Ruff formatting and linting rules across the entire project for consistency.
- Complete the builder implementation for several payment methods, including iDEAL QR, Payconiq, and SEPA Direct Debit.
- Introduce a robust testing suite comprising unit and feature tests with high coverage.
- Update CI/CD workflows to support Python 3.13 and automate linting/formatting checks.
- Remove redundant transaction service logic in favor of internal builder dispatching.
- Add .gitattributes to ensure consistent line endings across platforms.
- Rename `BuckarooAppConfig` to `BuckarooConfig` and improve configuration handling.
- Transition from snake_case to camelCase for public builder methods (e.g., `payEncrypted`, `cancelAuthorize`) to align with Buckaroo API naming conventions.
- Introduce `TransactionExecutor` to centralize API communication, removing direct HTTP concerns from builders.
- Simplify follow-up operations (refund, capture, cancel) by passing transaction keys directly instead of requiring a `TransactionContext` object.
- Standardize status code grouping and enhance sensitive field masking in logs.
- Refine error messages and validation logic within the builder hierarchy.
- Replaces `.execute()` with `.pay()` for more intuitive transaction initiation in builders and examples.
- Removes the `TransactionContext` model, allowing direct passing of `original_transaction_key` and other parameters for operations like `capture`, `refund`, and `cancelAuthorize`.
- Standardizes method naming from `cancel_authorize` to `cancelAuthorize` to align with camelCase conventions.
BTI-978: add In3 route param for ABN-AMRO Achteraf Betalen
BTI-721: Add Banking service (PaymentOrder payout) to Python SDK
BTI-715: support optional In3 CompanyName & CocNumber params
Klarna no longer returns a reservation number; follow-up actions reference
the prior Reserve through the Buckaroo DataRequestKey service parameter.

- Fix cancelReservation to post to /json/DataRequest with DataRequestKey
  (was posting to /json/transaction with OriginalTransactionKey)
- Add updateReservation and extendReservation DataRequest actions
- Align allowed service parameters and required_fields per action with the
  BPS Klarna docs (operatingCountry mandatory on Reserve; Pay requires an
  invoice)
- Remove AddShippingInfo: the gateway rejects it for the klarna service
  (ActionUnknown); shipping details ride on the Pay request instead
- Refund keeps the base OriginalTransactionKey path

Verified end-to-end against the Buckaroo test gateway: Reserve -> hosted-page
approval -> ExtendReservation -> Pay (captured) -> Refund all succeed.
feat(BTI-584): update Klarna MOR to DataRequestKey flow
- add examples/payperemail.py demoing the PaymentInvitation flow, creds-gated like examples/in3.py
- add feature test asserting the PaymentInvitation action and customer service params reach the wire
feat(BTI-17): add PayPerEmail example and feature test
- add IdinBuilder driving identify/verify/login via the DataRequest endpoint
- register idin in the payment method factory
- add unit and feature tests covering all three actions
- add examples/idin.py demoing the actions with sandbox issuer BANKNL2Y
- document iDIN usage in README
BTI-20: add iDIN verification method (identify, verify, login)
- fix instantRefund() to send OriginalTransactionKey + AmountCredit (refund-shaped body) instead of a Pay-shaped request
- extract shared _build_refund_request_data() helper reused by refund() and instantRefund()
- support partial refunds via refund_amount; raise ValueError when the original transaction key is missing
- strengthen assert_instant_refund_returns_success to assert OriginalTransactionKey + AmountCredit on the wire
- add wire-level and failure-flow tests for iDEAL and Payconiq instant refunds
- add examples/instant_refund.py demoing iDEAL + Payconiq instant refunds
- document instant refunds in README
BTI-21: Instant refunds for iDEAL and Payconiq
Add eMandate as a DataRequest-based solution with five actions:
GetIssuerList, CreateMandate, GetStatus, ModifyMandate, CancelMandate.

- EmandateBuilder (SolutionBuilder) + EmandateB2BBuilder subclass for the
  emandateb2b service code; both registered in SolutionMethodFactory.
- Per-action allowed/required service-parameter validation
  (debtorReference for create; mandateId for status/modify/cancel).
- Reuses PaymentResponse; no bespoke per-action response model.
- Unit + feature tests for every action (success + validation paths),
  runnable examples/emandate.py, and a README eMandate section.

Verified against Buckaroo Plaza test: GetIssuerList succeeds and
CreateMandate is accepted (redirect returned) for both B2C and B2B.
feat(BTI-23): add eMandate solution (B2C + B2B)
Ensures BaseBuilder gracefully handles null HTTP responses from the API client.
ShuCh3n and others added 6 commits July 15, 2026 17:54
refactor: Isolate payment lifecycle methods in PaymentBuilder
```
Moves payment-specific transaction methods (`pay`, `refund`, `partial_refund`,
`pay_remainder`, `cancel`) from `BaseBuilder` to `PaymentBuilder`.

This refactors the builder hierarchy to clearly separate generic builder
functionality from operations specific to payment processing flows.
`BaseBuilder` now exclusively houses common operations like `build` and `capture`,
while `PaymentBuilder` encapsulates all payment lifecycle actions.
```
- add MarketplacesBuilder with split, transfer, refund_supplementary and manual_transfer
- register "marketplaces" solution in SolutionMethodFactory
- add combine() to BaseBuilder so a supplementary service rides in one ServiceList
- add CombinableService model returned by split/refund_supplementary
- split and refund_supplementary combine into a payment/refund; transfer and manual_transfer post standalone DataRequests
- map grouped Marketplace/Seller split params from a single spec dict
- add unit and feature tests asserting the exact wire body per request type
- add examples/marketplaces.py demoing all six request types
- document Split Payments usage in README
BTI-16: add Split Payments (Marketplaces) solution
Introduces support for in-store PIN-based payments processed via physical terminals.

This change adds a `PosBuilder` for initiating POS transactions, including specific handling for its unique characteristics: no redirect flow, immediate pending response, and delivery of the final result (with printable receipt) via push notification.

A new `Channel` field is added to `BaseBuilder` and `PaymentRequest` to accommodate the fixed "Web" channel required for POS payments, which is enforced internally by the `PosBuilder`.
@ShuCh3n ShuCh3n closed this Jul 16, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 09bf6d7245

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

if not txn_key:
raise ValueError("Transaction key is required for cancel")

request_data = self._build_keyed_request('Pay', txn_key)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Build cancel requests with the Cancel action

When a caller uses cancel(original_transaction_key=...), this builds the keyed request with action Pay, so the service sent to Buckaroo is a Pay request referencing the original transaction rather than a cancellation. It also runs Pay-time parameter validation for methods with required Pay parameters before stripping the amounts, so valid cancellation calls can fail unless unrelated payment fields are supplied; this should build the Cancel action instead.

Useful? React with 👍 / 👎.

# Create service list
service_list = ServiceList(services=[service])
# Create service list, appending any services merged in via combine()
service_list = ServiceList(services=[service, *self._combined_services])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add the missing combine API for Marketplaces

Any consumer following the new Marketplaces flow (payments.create_payment(...).combine(mp).pay() / .refund()) currently gets AttributeError because neither BaseBuilder nor PaymentBuilder defines combine; _combined_services is initialized and read here but is never publicly populated. This makes the newly added split and refund-supplementary services unusable through the documented API.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants