Open
Conversation
Allow passing a custom API base_url for local development while preventing custom URLs in non-dev builds. Client now accepts base_url and resolves it via _resolve_base_url (uses MSP_SDK_BUILD_PROFILE, MSP_SDK_ALLOW_CUSTOM_BASE_URL, MSP_SDK_CUSTOM_BASE_URL); _normalize_base_url validates/normalizes the URL. Sdk forwards base_url to Client. Added unit tests covering default test/live URLs, dev-only custom URL acceptance, env-provided URL, and blocking in release/when flag disabled. README updated with usage and guardrails.
Reject invalid custom base URLs with query strings, fragments, or malformed hosts. Add unit coverage for invalid URL cases and document environment-variable precedence for custom base URLs.
Improve Client._normalize_base_url by rejecting URLs that include path parameters (parsed.params) and standardize the error message to "Invalid base URL.". Update unit tests to expect the new message, add a test ensuring an explicit base_url argument takes precedence over environment settings, and add a test that rejects base URLs containing params.
Use a dedicated E2E_API_KEY, centralize E2E SDK bootstrap in shared fixtures, and keep end-to-end tests isolated from the general SDK environment configuration. Update the E2E documentation and environment example accordingly.
Ensure E2E fixtures remain isolated from local custom-base-url overrides. The E2E SDK factory now temporarily clears MSP_SDK_BUILD_PROFILE, MSP_SDK_ALLOW_CUSTOM_BASE_URL and MSP_SDK_CUSTOM_BASE_URL while instantiating the SDK, then restores previous values. Added a guard to assert the resulting client URL is Client.TEST_URL, so E2E always targets the test environment when using E2E_API_KEY.
Introduce POS and terminal-related functionality and add order cancel support. Added PosManager (get_receipt) with POS receipt models and components; TerminalManager (create/get terminals) with CreateTerminalRequest and Terminal response model; TerminalGroupManager (list terminals by group). Added request/response models for cancelling an order transaction (CancelTransactionRequest, CancelTransaction) and wired cancel_transaction into OrderManager. Exposed new managers via api.paths and Sdk getters. Includes validation, custom response adapters and pager/listing support.
Introduce a credential resolver API and wire scoped auth into the client and managers. Adds src/multisafepay/client/credential_resolver.py (AuthScope, CredentialResolver protocol, ScopedCredentialResolver). Client now accepts an optional CredentialResolver, exposes auth scope constants, and supports an auth_scope argument for endpoint requests; it normalizes scopes, resolves API keys via the resolver, and uses the resolved key in Authorization headers. Updated managers to pass AuthScope for terminal-group and partner-affiliate requests and exported resolver types from client.__init__. The SDK constructor now accepts a credential_resolver to propagate into Client. Terminal-group resolution enforces group_id and falls back to defaults when appropriate.
Introduce SSE event stream support and Cloud POS/terminal examples. Added EventStream parsing (SSE) and EventManager helpers, plus unit tests for both. Updated Order response to normalize legacy/singular event fields (events_token/events_stream_url) and updated OrderManager.create to accept terminal_group_id and pass a terminal-group AuthScope. Made Client and Sdk accept optional api_key (require credential_resolver when missing) and added validation in ScopedCredentialResolver; improved credential resolution for partner and default scopes. Small API tweaks: CreateTerminalRequest default values and param type adjustments. Many example scripts and integration/unit tests added to cover the new functionality.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #54 +/- ##
==========================================
- Coverage 90.81% 88.67% -2.14%
==========================================
Files 147 173 +26
Lines 2579 3187 +608
==========================================
+ Hits 2342 2826 +484
- Misses 237 361 +124 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Contributor
There was a problem hiding this comment.
Pull request overview
This PR expands the Python SDK’s support for Cloud POS workflows by adding scoped credential resolution, event streaming helpers, and new terminal/POS managers, while also improving environment configuration for custom base URLs and E2E testing.
Changes:
- Added
CredentialResolver/AuthScopesupport inClient/Sdkto enable scoped API-key selection (default / partner-affiliate / terminal-group). - Introduced new managers and models for events (SSE), POS receipts, terminals, and terminal groups; updated order responses for legacy/plural events field compatibility.
- Refactored E2E tests to use dedicated
E2E_*environment variables and added extensive unit tests for the new behavior.
Reviewed changes
Copilot reviewed 75 out of 75 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/multisafepay/unit/test_unit_sdk.py | SDK guardrails + resolver wiring tests |
| tests/multisafepay/unit/client/test_unit_credential_resolver.py | Scoped credential resolver unit tests |
| tests/multisafepay/unit/client/test_unit_client.py | Client base URL + auth scope/resolver tests |
| tests/multisafepay/unit/api/path/terminals/response/test_unit_terminal_response.py | Terminal response model tests |
| tests/multisafepay/unit/api/path/terminals/request/test_unit_create_terminal_request.py | CreateTerminalRequest tests |
| tests/multisafepay/unit/api/path/orders/response/test_unit_order_response.py | Order events field compatibility tests |
| tests/multisafepay/unit/api/path/orders/manager/test_unit_order_manager.py | OrderManager terminal-group scope tests |
| tests/multisafepay/unit/api/path/events/test_unit_event_manager.py | EventManager subscription helper tests |
| tests/multisafepay/unit/api/path/events/stream/test_unit_event_stream.py | SSE parsing tests for EventStream |
| tests/multisafepay/integration/api/path/orders/manager/test_integration_order_manager_create.py | Integration-style tests updated for events/auth scope |
| tests/multisafepay/e2e/examples/transport/test_custom_urllib3_transport.py | E2E transport example uses shared E2E fixtures |
| tests/multisafepay/e2e/examples/transport/test_custom_requests_session_transport.py | E2E requests.Session transport fixture refactor |
| tests/multisafepay/e2e/examples/transport/test_custom_httpx_transport.py | E2E httpx transport fixture refactor |
| tests/multisafepay/e2e/examples/transaction_manager/test_get_transactions.py | E2E uses e2e_sdk fixture |
| tests/multisafepay/e2e/examples/recurring_manager/test_recurring.py | E2E uses e2e_sdk fixture |
| tests/multisafepay/e2e/examples/payment_method_manager/test_get_payment_methods.py | E2E uses e2e_sdk fixture |
| tests/multisafepay/e2e/examples/payment_method_manager/test_get_by_gateway_code.py | E2E uses e2e_sdk fixture |
| tests/multisafepay/e2e/examples/order_manager/test_update.py | E2E uses e2e_sdk fixture |
| tests/multisafepay/e2e/examples/order_manager/test_refund.py | E2E uses e2e_sdk fixture |
| tests/multisafepay/e2e/examples/order_manager/test_refund_by_shopping_cart.py | E2E uses e2e_sdk fixture |
| tests/multisafepay/e2e/examples/order_manager/test_refund_by_item.py | E2E uses e2e_sdk fixture |
| tests/multisafepay/e2e/examples/order_manager/test_get_order.py | E2E uses e2e_sdk fixture |
| tests/multisafepay/e2e/examples/order_manager/test_create.py | E2E uses e2e_sdk fixture |
| tests/multisafepay/e2e/examples/order_manager/test_capture.py | E2E uses e2e_sdk fixture |
| tests/multisafepay/e2e/examples/me_manager/test_get_me.py | E2E uses e2e_sdk fixture |
| tests/multisafepay/e2e/examples/issuer_manager/test_get_issuers_by_gateway_code.py | E2E uses e2e_sdk fixture |
| tests/multisafepay/e2e/examples/gateway_manager/test_get_gateways.py | E2E uses e2e_sdk fixture |
| tests/multisafepay/e2e/examples/gateway_manager/test_get_by_code.py | E2E uses e2e_sdk fixture |
| tests/multisafepay/e2e/examples/category_manager/test_get_categories.py | E2E uses e2e_sdk fixture |
| tests/multisafepay/e2e/examples/capture_manager/test_capture_reservation_cancel.py | E2E uses e2e_sdk fixture |
| tests/multisafepay/e2e/examples/auth_manager/test_get_api_token.py | E2E uses e2e_sdk fixture |
| tests/multisafepay/e2e/conftest.py | Adds E2E_API_KEY/E2E_BASE_URL fixtures + validation |
| src/multisafepay/sdk.py | Public SDK surface expanded (events/pos/terminals/groups) |
| src/multisafepay/client/credential_resolver.py | Adds resolver protocol + scoped resolver + AuthScope |
| src/multisafepay/client/client.py | Base URL guardrails + scoped auth header resolution |
| src/multisafepay/client/init.py | Exposes new resolver/public types |
| src/multisafepay/api/paths/terminals/terminal_manager.py | Adds /json/terminals manager |
| src/multisafepay/api/paths/terminals/response/terminal.py | Adds Terminal response model |
| src/multisafepay/api/paths/terminals/response/init.py | Exports terminal response models |
| src/multisafepay/api/paths/terminals/request/create_terminal_request.py | Adds create-terminal request model |
| src/multisafepay/api/paths/terminals/request/init.py | Exports terminal request models |
| src/multisafepay/api/paths/terminals/init.py | Exposes TerminalManager |
| src/multisafepay/api/paths/terminal_groups/terminal_group_manager.py | Adds terminal-group listing manager |
| src/multisafepay/api/paths/terminal_groups/init.py | Exposes TerminalGroupManager |
| src/multisafepay/api/paths/pos/receipt/response/receipt.py | Adds Receipt response model |
| src/multisafepay/api/paths/pos/receipt/response/components/related_transactions.py | Receipt related-transactions component |
| src/multisafepay/api/paths/pos/receipt/response/components/payment.py | Receipt payment component |
| src/multisafepay/api/paths/pos/receipt/response/components/order.py | Receipt order + item/tip component models |
| src/multisafepay/api/paths/pos/receipt/response/components/merchant.py | Receipt merchant component |
| src/multisafepay/api/paths/pos/receipt/response/components/init.py | Exports receipt component models |
| src/multisafepay/api/paths/pos/receipt/response/init.py | Exports receipt response models |
| src/multisafepay/api/paths/pos/receipt/init.py | POS receipt package init |
| src/multisafepay/api/paths/pos/pos_manager.py | Adds POS receipt retrieval manager |
| src/multisafepay/api/paths/pos/init.py | Exposes PosManager |
| src/multisafepay/api/paths/orders/response/order_response.py | Adds plural events fields + normalization |
| src/multisafepay/api/paths/orders/order_manager.py | Adds terminal-group scoping + cancel endpoint |
| src/multisafepay/api/paths/orders/order_id/cancel/response/cancel_transaction.py | Adds cancel-transaction response model |
| src/multisafepay/api/paths/orders/order_id/cancel/response/init.py | Exports cancel response models |
| src/multisafepay/api/paths/orders/order_id/cancel/request/cancel_transaction_request.py | Adds cancel-transaction request model |
| src/multisafepay/api/paths/orders/order_id/cancel/request/init.py | Exports cancel request models |
| src/multisafepay/api/paths/orders/order_id/cancel/init.py | Cancel endpoint package init |
| src/multisafepay/api/paths/events/stream/event_stream.py | Adds SSE stream opener/parser |
| src/multisafepay/api/paths/events/stream/init.py | Exposes EventStream/Event types |
| src/multisafepay/api/paths/events/event_manager.py | Adds event subscription helpers |
| src/multisafepay/api/paths/events/init.py | Exposes EventManager |
| src/multisafepay/api/paths/init.py | Public paths exports include new managers |
| README.md | Documents base URL guardrails + E2E env vars |
| examples/terminal_manager/get_terminals.py | Terminal listing example using resolver |
| examples/terminal_manager/create.py | Terminal creation example |
| examples/terminal_group_manager/get_terminals_by_group.py | Terminal-group listing example |
| examples/pos_manager/get_receipt.py | Cloud POS receipt flow example |
| examples/order_manager/cloud_pos_order.py | Cloud POS order creation example |
| examples/order_manager/cancel.py | Cloud POS cancel flow example |
| examples/event_manager/subscribe_events.py | Cloud POS event subscription example |
| .env.example | Adds E2E/POS/partner env variable examples |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+77
to
+83
| response = self.client.create_get_request( | ||
| endpoint, | ||
| context=context, | ||
| auth_scope=AuthScope( | ||
| scope=Client.AUTH_SCOPE_TERMINAL_GROUP, | ||
| group_id=terminal_group_id, | ||
| ), |
Comment on lines
+347
to
+353
| response = self.client.create_post_request( | ||
| endpoint, | ||
| context=context, | ||
| auth_scope=AuthScope( | ||
| scope=Client.AUTH_SCOPE_TERMINAL_GROUP, | ||
| group_id=terminal_group_id, | ||
| ), |
Comment on lines
+67
to
+70
| def add_group_id( | ||
| self: "CreateTerminalRequest", | ||
| group_id: str, | ||
| ) -> "CreateTerminalRequest": |
Comment on lines
+64
to
+69
| .add_currency("EUR") | ||
| .add_gateway_info( | ||
| { | ||
| "terminal_id": terminal_id, | ||
| }, | ||
| ) |
Comment on lines
+31
to
+37
| def _validate_e2e_base_url(base_url: str) -> str: | ||
| parsed = urlparse(base_url) | ||
| if parsed.scheme != "https" or not parsed.netloc: | ||
| msg = f"{E2E_BASE_URL_ENV} must be a valid https URL" | ||
| raise pytest.UsageError(msg) | ||
|
|
||
| parsed = urlparse(base_url) |
Comment on lines
+263
to
+270
| def _create_endpoint_request( | ||
| self: "Client", | ||
| method: str, | ||
| endpoint: str, | ||
| params: Optional[dict[str, Any]] = None, | ||
| request_body: Optional[dict[str, Any]] = None, | ||
| context: Optional[dict[str, Any]] = None, | ||
| *, |
Comment on lines
+35
to
+45
| id: Optional[str] | ||
| provider: Optional[str] | ||
| name: Optional[str] | ||
| code: Optional[str] | ||
| created: Optional[str] | ||
| last_updated: Optional[str] | ||
| manufacturer_id: Optional[str] | ||
| serial_number: Optional[str] | ||
| active: Optional[bool] | ||
| group_id: Optional[int] | ||
| country: Optional[str] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request introduces several new Cloud POS and terminal management example scripts, improves environment variable configuration. It also adds new API managers to the public SDK interface. These changes collectively make it easier to work with Cloud POS flows, manage terminals and terminal groups, and configure the SDK for various environments.