PhonePe B2B PG SDK
A python library for integrating with PhonePe APIs.
v3.0.0 - Breaking changes
- Retry mechanism removed. The SDK no longer retries any HTTP call (including GET). The
should_retryconstructor parameter has been removed fromStandardCheckoutClient,CustomCheckoutClient, andSubscriptionClient- passing it now raises aTypeError. - Client construction can now raise. The SDK fetches its OAuth token immediately at
construction (a single, non-blocking attempt) instead of waiting for the first API call.
Genuine configuration problems (e.g. invalid credentials) now fail fast and
get_instance(...)/the constructor raises immediately, where previously construction always succeeded regardless of credential validity. See the Quick start note below for details - transient failures do NOT raise or block; they're retried automatically in the background instead. - New: configurable connection pooling/timeouts via
HttpClientConfig(see Connection pool & timeout tuning) and aclose()method on every client to release resources cleanly.
Installation
Requires python 3.9 or later
pip install phonepe-pg-sdk-python
Quick start
To get your keys, please visit the Merchant Onboarding of PhonePe PG: Merchant Onboarding
You will need three things to get started: client-id, client-secret and client-version.
Create an instance of the StandardCheckoutClient class:
from phonepe.sdk.pg.payments.v2.standard_checkout_client import StandardCheckoutClient
from phonepe.sdk.pg.env import Env
client_id = "<YOUR_CLIENT_ID>"
client_secret = "<YOUR_CLIENT_SECRET>"
client_version = 1 # Insert your client version here
env = Env.SANDBOX # Change to Env.PRODUCTION when you go live
standard_phonepe_client = StandardCheckoutClient.get_instance(client_id=client_id,
client_secret=client_secret,
client_version=client_version,
env=env)
Note: Client construction fetches an OAuth token immediately (a single, non-blocking attempt) rather than waiting for the first API call. A genuine configuration problem (e.g. invalid credentials) fails fast and
get_instance(...)/the constructor raises immediately; a transient failure (network blip, 5xx, rate-limiting) does NOT block construction or raise - it's retried automatically in the background instead. Once constructed, the token is kept fresh automatically in the background for the lifetime of the client - see Connection pool & timeout tuning below forclose()and other tunable behavior.
Initiate an order using Checkout Page
To init a pay request, we make a request object using StandardCheckoutPayRequest.build_request build_request.
Code:
from uuid import uuid4
from phonepe.sdk.pg.payments.v2.models.request.standard_checkout_pay_request import StandardCheckoutPayRequest
unique_order_id = str(uuid4())
ui_redirect_url = "https://www.merchant.com/redirect"
amount = 100
standard_pay_request = StandardCheckoutPayRequest.build_request(merchant_order_id=unique_order_id,
amount=amount,
redirect_url=ui_redirect_url)
standard_pay_response = standard_phonepe_client.pay(standard_pay_request)
checkout_page_url = standard_pay_response.redirect_url
The data will be in a StandardCheckoutPayResponse object.
The checkout_page_url you get can be handled by redirecting the user to that url on the front end.
Check status of order
View the state for the order we just initiated.
unique_order_id = "INSERT_YOUR_UNIQUE_ORDER_ID"
order_status_response = standard_phonepe_client.get_order_status(merchant_order_id=unique_order_id)
order_state = order_status_response.state
You will get the data OrderStatusResponse object.
For more details, please visit: https://developer.phonepe.com
Connection pool & timeout tuning
Every client accepts an optional http_client_config argument on both its constructor and get_instance(...), letting
you tune the underlying HTTP connection pool and timeouts per merchant/client instance:
from phonepe.sdk.pg.common.configs.http_client_config import HttpClientConfig
from phonepe.sdk.pg.payments.v2.standard_checkout_client import StandardCheckoutClient
from phonepe.sdk.pg.env import Env
http_client_config = HttpClientConfig(
pool_size=10, # max pooled (kept-alive) connections per host
keep_alive_seconds=60, # proactively recycle connections idle longer than this
connect_timeout_seconds=3, # max time to establish the TCP/TLS connection
read_timeout_seconds=30, # max time to wait for a response once the request is sent
pool_block=True, # wait for a free pooled connection instead of overflowing the pool
)
standard_phonepe_client = StandardCheckoutClient.get_instance(
client_id=client_id,
client_secret=client_secret,
client_version=client_version,
env=env,
http_client_config=http_client_config,
)
If http_client_config is omitted, the SDK uses the defaults shown above (pool_size=10,
keep_alive_seconds=60, connect_timeout_seconds=3, read_timeout_seconds=30,
pool_block=True).
Why these four settings trade off against each other:
pool_sizecaps how many connections are kept alive per host. A merchant sending many concurrent requests benefits from a larger pool so requests don't queue up waiting for a free connection; a merchant sending only the occasional request (e.g. one every several seconds) gains nothing from a large pool - a small value (2-4) is enough, since most of those connections would otherwise sit idle.keep_alive_secondsbounds how long a pooled connection can sit idle before the SDK proactively closes and replaces it with a fresh one, rather than risking handing a request a connection that a server/load balancer has already silently closed while idle (a scenario confirmed via repro testing against PhonePe's production environment). This is enforced both the moment a connection is next reused for a request and independently by a background sweep thread that periodically closes idle connections directly, so staleness is bounded even during a period with no request traffic at all.connect_timeout_seconds/read_timeout_secondsbound how long a single request is allowed to take establishing a connection vs. waiting for a response. A merchant with fast, reliable infrastructure can tighten these to fail faster on genuine problems; a merchant on slower/less reliable infrastructure (or calling latency-sensitive endpoints like autoPay APIs) may need to raiseread_timeout_secondsto avoid timing out on otherwise-successful, just-slow responses.pool_blockdecides what happens when allpool_sizeconnections are already busy and another request needs one. With the defaultTrue, the request waits for one to be released, sopool_sizeis a genuine cap on concurrent connections. WithFalse, the request instead opens an extra connection outside the pool and throws it away immediately after that single request - so a traffic burst pays a fresh TCP/TLS handshake per overflow request andpool_sizeno longer limits anything. Waiting cannot deadlock: every in-flight request releases its slot when it completes or hitsread_timeout_seconds, so that timeout (notconnect_timeout_seconds) bounds how long a request can wait for a slot. If you setpool_block=False, sizepool_sizefor your peak concurrency to keep overflow rare.
Releasing resources with close()
Every client exposes a close() method that releases pooled HTTP connections and stops the
SDK's background threads (token refresh, connection recycling, event publishing).
Calling close() is optional. All of these are daemon threads, so a long-lived server that
creates its client once and never closes it works exactly as before and still exits cleanly.
Call close() only when you want a deterministic, immediate release - short-lived processes
(tests, scripts, serverless invocations), or when you want to discard a client instance:
standard_phonepe_client.close()
close() also removes the instance from the get_instance() cache, so a later get_instance()
call with the same arguments builds a fresh client instead of returning the closed one. It is
safe to call multiple times, and it waits for any in-flight event flush to finish.
License
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Metadata
Release files for phonepe-pg-sdk-python 3.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| phonepe_pg_sdk_python-3.0.1.tar.gz | 104.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| phonepe_pg_sdk_python-3.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 330.1 kB
Release files / phonepe_pg_sdk_python-3.0.1.tar.gz
| Download URL | phonepe_pg_sdk_python-3.0.1.tar.gz |
|---|---|
| Size | 104.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f1c95df38704fdb08264272aac0996479a8af9dc8e974703c78569885f891ec9
|
|
BLAKE2b-256 checksum How to use checksums |
716a80a59487c6455229c848a3b67f281f5b4cac203855dd54fea73ad9ab1c7c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.21
|
Release files / phonepe_pg_sdk_python-3.0.1-py3-none-any.whl
| Download URL | phonepe_pg_sdk_python-3.0.1-py3-none-any.whl |
|---|---|
| Size | 225.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
68374a0aa1839fe017e34709b20eaef0b685ea605d72145a24abd494285a7161
|
|
BLAKE2b-256 checksum How to use checksums |
276522e3d4859daa132e70b29373ab164633afa85323839241097265386f4d66
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.10.21
|