Skip to main content

Pine Labs Online P3P Client SDK (Python)

Python SDK for Pine Labs Online P3P client integrations. It mirrors p3p-client-sdk, intercepts HTTP 402 Payment Required responses, creates customer-scoped P3P payment credentials, and retries paid requests.

Installation

pip install pinelabs-online-p3p-client-sdk

Import module: pinelabs_p3p_client. Requires Python 3.9 or newer.

Quick Start

from pinelabs_p3p_client import (
    ClientRuntimeContext,
    P3PEnvironment,
    PaymentMethod,
    PineLabsOnlineClient,
    PineLabsOnlineClientConfig,
)

client = PineLabsOnlineClient.create(PineLabsOnlineClientConfig(
    env=P3PEnvironment.SANDBOX,
    clientId="client-client-id",
    clientSecret="client-client-secret",
    merchantId="merchant-id",
))

response = client.get(
    "https://server.example.com/api/premium",
    context=ClientRuntimeContext(
        customerReference="9876543210",
        mobileNumber="9876543210",
        paymentMethod=PaymentMethod.RESERVE_PAY,
    ),
)
print(response.json())
client.close()

Customer identity and payment method are runtime context, not static SDK config. This lets one client instance safely serve many customers and payment choices. paymentMethod is required for automatic 402 handling.

By default, the SDK uses client-credentials customer auth: it exchanges clientId and clientSecret through POST /api/auth/v1/token, then calls POST /mpp/v1/token. merchantId is mandatory and is sent as Merchant-ID for token creation across RESERVE_PAY, OTM, CARD, and CREDIT_EMI. The SDK rejects missing MID during construction, before any network call.

For customer API-token flows, explicitly set customerAuthMode=P3PCustomerAuthMode.CustomerKey and pass customerKey plus mobileNumber in ClientRuntimeContext.

Keep the client SDK instance long-lived in production. Auth tokens are cached per SDK instance.

402 Flow

  1. Your code calls client.get(url, context=...).
  2. The server returns HTTP 402 with WWW-Authenticate: Payment <challenge>.
  3. The SDK decodes the challenge and validates amount, expiry, and accepted payment methods.
  4. The SDK creates a token:
    • default mode: POST /mpp/v1/token with Authorization: Bearer <token>
    • customer-key mode: POST /api/v1/customer/mpp/token with Authorization: Bearer <token> and X-Customer-Key
    • customer.merchant_customer_reference and/or customer.mobile_number
    • challenge_id
    • payment_amount.value in minor units
  5. The SDK retries the server with P3P-Credential: Payment <credential>.
  6. The server captures the payment and may return Payment-Receipt.

Direct Token API

from pinelabs_p3p_client import Amount, CreateTokenOptions, PaymentMethod

token = client.methods.create_token(CreateTokenOptions(
    customerReference="9876543210",
    mobileNumber="9876543210",
    challengeId="ch_...",
    paymentAmount=Amount(value=50000, currency="INR"),
    paymentMethod=PaymentMethod.RESERVE_PAY,
))

The client SDK no longer creates mandates. Mandate/pre-authorization creation is handled by the server SDK.

Customer-key mode remains available:

from pinelabs_p3p_client import P3PCustomerAuthMode

customer_key_client = PineLabsOnlineClient.create(PineLabsOnlineClientConfig(
    env=P3PEnvironment.SANDBOX,
    customerAuthMode=P3PCustomerAuthMode.CustomerKey,
    clientId="client-client-id",
    clientSecret="client-client-secret",
    merchantId="merchant-id",
))

Timeout and retry settings (requestTimeoutMs, maxRetries, initialRetryDelayMs) apply to internal P3P calls only. The protected resource request itself uses the integrator's own HTTP timeout policy.

Environment defaults:

Env URL Timeout Retries Initial retry delay
P3PEnvironment.SANDBOX https://pluraluat.v2.pinepg.in 60000 ms 3 500 ms
P3PEnvironment.PRODUCTION https://api.pluralpay.in 45000 ms 3 500 ms

Supported Methods

  • PaymentMethod.RESERVE_PAY -> "RESERVE_PAY" / UPI ReservePay
  • PaymentMethod.OTM -> "OTM"
  • PaymentMethod.CARD -> "CARD"
  • PaymentMethod.Crypto -> "CRYPTO" (currently rejected by token creation)

CARD

Card payments require an active card pre-authorization on the server side (see the Server SDK's create_pre_authorization). The Client SDK creates the token bound to that pre-auth; the Server SDK's debit call then sends payment_method_reference_id = the pre-auth reference id.

response = client.get(
    "https://server.example.com/api/premium",
    context=ClientRuntimeContext(
        customerReference="9876543210",
        mobileNumber="9876543210",
        paymentMethod=PaymentMethod.CARD,
    ),
)

Error Handling

from pinelabs_p3p_client import P3PChallengeError, P3PError, P3PNetworkError

try:
    response = client.get(url, context=runtime_context)
except P3PChallengeError as err:
    ...
except P3PNetworkError as err:
    ...
except P3PError as err:
    print(err.code, err.http_status, err.details)

Grantex (Delegated Agent Authorization)

Set grantex in config to attach and optionally verify a Grantex grant token on every payment request.

from pinelabs_p3p_client import (
    GRANTEX_SANDBOX_BASE_URL,
    P3PEnvironment,
    PineLabsOnlineClient,
    PineLabsOnlineClientConfig,
)
from pinelabs_p3p_client.types.config import ClientGrantexConfig

client = PineLabsOnlineClient.create(PineLabsOnlineClientConfig(
    env=P3PEnvironment.SANDBOX,
    clientId="...",
    clientSecret="...",
    merchantId="...",
    grantex=ClientGrantexConfig(
        enforceGrant=True,                            # raise before payment if no grant token
        agentId=os.environ.get("GRANTEX_AGENT_ID"),  # optional: assert grant is for this agent
        requiredScopes=["mpp:payment:initiate"],       # optional: assert grant has these scopes
        baseUrl=GRANTEX_SANDBOX_BASE_URL,              # lower/UAT
        # Omit baseUrl for production (https://grantex.pinelabs.com).
        # Set only for self-hosted Grantex:
        # baseUrl="https://my-grantex.company.com",
    ),
))

The JWKS URI is always <baseUrl>/.well-known/jwks.json. The path is constant; only the base URL changes for self-hosted deployments.

Setting JWKS endpoint
baseUrl not set https://grantex.pinelabs.com/.well-known/jwks.json
baseUrl=GRANTEX_SANDBOX_BASE_URL https://grantex.test.pinelabs.com/.well-known/jwks.json
baseUrl="https://my-grantex.co" https://my-grantex.co/.well-known/jwks.json
jwksUri="https://..." That exact URL (takes precedence over baseUrl)

Pass the grant token per request:

response = client.get(
    url,
    context=ClientRuntimeContext(
        mobileNumber="9876543210",
        paymentMethod=PaymentMethod.RESERVE_PAY,
        grantexToken=user_grant_token,   # per-request grant token
    ),
)

License

MIT

Metadata

Release files for pinelabs-online-p3p-client-sdk 1.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pinelabs-online-p3p-client-sdk 1.3.0
File Size Uploaded
pinelabs_online_p3p_client_sdk-1.3.0.tar.gz 28.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pinelabs-online-p3p-client-sdk 1.3.0
File Interpreter ABI Platform
pinelabs_online_p3p_client_sdk-1.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 58.7 kB

Release files / pinelabs_online_p3p_client_sdk-1.3.0.tar.gz

Download URL pinelabs_online_p3p_client_sdk-1.3.0.tar.gz
Size 28.0 kB
Tags Source
SHA-256 checksum
How to use checksums
dbd95611c25761a53d1cc62cbb67292ca2f597a8b4fb3a715ec4cd9145912620
BLAKE2b-256 checksum
How to use checksums
c60e1e1b4b076669ea93749ec110d0510a770601b34e2a9f2f50997732f41e5c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release files / pinelabs_online_p3p_client_sdk-1.3.0-py3-none-any.whl

Download URL pinelabs_online_p3p_client_sdk-1.3.0-py3-none-any.whl
Size 30.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
90ae2fc6c0a9340a145f7735a6610a392901ddccf7d92e8eaabde4ffbb6c723e
BLAKE2b-256 checksum
How to use checksums
183c63d5841b0d973cc43d148a1cfbb4f2fd86643e628bc1d35be72d1f9a684c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.13

Release history Release notifications | RSS feed

This release

1.3.0 This release

2 release files

1.2.0

2 release files

1.1.0

2 release files

1.0.0

2 release files

0.3.0

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.3

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page