From e8dc7bd971e288efb7eff3baf45df8b2281bb31a Mon Sep 17 00:00:00 2001 From: manish soni Date: Thu, 28 Aug 2025 16:19:41 +0530 Subject: [PATCH 1/8] docs: add Device Activity and POS Gateway integration documentation - Add deviceActivity.md with complete Device Activity API reference - Add posGateway.md with comprehensive POS Gateway integration guide - Update README.md to include new documentation sections - Update Python version badge to show 3.5+ compatibility Features documented: - Device Activity APIs (initiate/close checkout, status checking) - Order APIs with device_mode support - Complete integration workflows - Error handling and status management - Request/response examples for all endpoints --- README.md | 6 +- documents/deviceActivity.md | 340 +++++++++++++++++++++++ documents/posGateway.md | 521 ++++++++++++++++++++++++++++++++++++ 3 files changed, 866 insertions(+), 1 deletion(-) create mode 100644 documents/deviceActivity.md create mode 100644 documents/posGateway.md diff --git a/README.md b/README.md index 727ad4c..0b45b25 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Razorpay Python Client -[![PyPI Version](https://img.shields.io/pypi/v/razorpay.svg)](https://pypi.python.org/pypi/razorpay) [![Coverage Status](https://coveralls.io/repos/github/razorpay/razorpay-python/badge.svg?branch=master)](https://coveralls.io/github/razorpay/razorpay-python?branch=master) [![PyPI](https://img.shields.io/badge/python-3%20%7C%203.4%20%7C%203.5%20%7C%203.6-blue.svg)]() [![License](https://img.shields.io/:license-mit-blue.svg)](https://opensource.org/licenses/MIT) +[![PyPI Version](https://img.shields.io/pypi/v/razorpay.svg)](https://pypi.python.org/pypi/razorpay) [![Coverage Status](https://coveralls.io/repos/github/razorpay/razorpay-python/badge.svg?branch=master)](https://coveralls.io/github/razorpay/razorpay-python?branch=master) [![PyPI](https://img.shields.io/badge/python-3.5%2B-blue.svg)]() [![License](https://img.shields.io/:license-mit-blue.svg)](https://opensource.org/licenses/MIT) Python bindings for interacting with the Razorpay API @@ -43,6 +43,10 @@ that both app title and version are strings. - [Customer](documents/customer.md) +- [Device Activity](documents/deviceActivity.md) + +- [POS Gateway Integration](documents/posGateway.md) + - [Token](documents/token.md) - [Fund](documents/fund.md) diff --git a/documents/deviceActivity.md b/documents/deviceActivity.md new file mode 100644 index 0000000..76c524e --- /dev/null +++ b/documents/deviceActivity.md @@ -0,0 +1,340 @@ +## Device Activity + +### Create device activity + +```py +client.device_activity.create({ + "device_id": "2841158834", # Required for device_mode="wired", optional for device_mode="wireless" + "action": "initiate_checkout", # Required: Action type + "notes": { # Optional: Additional notes + "key1": "value1", + "key2": "value2" + }, + "initiate_checkout": { # Required for initiate_checkout + "name": "Acme Corp", # Required: Business name + "amount": 19900, # Required: Amount in paise (₹199.00) + "currency": "INR", # Required: Currency code + "description": "POS Transaction", # Required: Transaction description + "type": "in_person", # Required: Transaction type + "order_id": "order_R7vqkfqG3Iw02m", # Required: Order reference + "method": "upi", # Required: "upi"|"card"|"netbanking"|"wallet" + "prefill": { # Optional: Customer prefill data + "name": "Gaurav Kumar", + "email": "gaurav.kumar@example.com", + "contact": "9000090000" + } + } +}, device_mode="wired") +``` + +**Parameters:** + +| Name | Type | Description | +|---------------|--------|--------------------------------------------------------------------------------| +| device_id | string | Device identifier. Required for wired mode, optional for wireless mode | +| action* | string | Action type. Possible values: `initiate_checkout`, `close_checkout` | +| notes | object | A key-value pair for additional information | +| initiate_checkout* | object | Required when action is `initiate_checkout`. Contains checkout details | +| device_mode* | string | Device communication mode. Possible values: `wired`, `wireless` | + +**initiate_checkout Object Parameters:** + +| Name | Type | Description | +|---------------|--------|--------------------------------------------------------------------------------| +| name* | string | Business name | +| amount* | integer| Amount in paise (₹199.00 = 19900) | +| currency* | string | Currency code (e.g., "INR") | +| description* | string | Transaction description | +| type* | string | Transaction type (e.g., "in_person") | +| order_id* | string | Order reference ID | +| method* | string | Payment method: "upi", "card", "netbanking", "wallet" | +| prefill | object | Optional customer prefill data (name, email, contact) | + +**Success Response:** + +```json +{ + "id": "pda_NVTKa9PL0yessI", + "entity": "device.activity", + "device_id": "2841158834", + "action": "initiate_checkout", + "initiate_checkout": { + "name": "Acme Corp", + "amount": 19900, + "currency": "INR", + "description": "POS Transaction", + "order_id": "order_R7vqkfqG3Iw02m", + "prefill": { + "name": "Gaurav Kumar", + "email": "gaurav.kumar@example.com", + "contact": "9000090000" + } + }, + "status": "processing", + "error": null +} +``` + +**Failure Response:** + +```json +{ + "id": "pda_NVTKa9PL0yessI", + "entity": "device.activity", + "device_id": "2841158834", + "action": "initiate_checkout", + "initiate_checkout": { + "name": "Acme Corp", + "amount": 19900, + "currency": "INR", + "description": "POS Transaction", + "order_id": "order_R7vqkfqG3Iw02m", + "prefill": { + "name": "Gaurav Kumar", + "email": "gaurav.kumar@example.com", + "contact": "9000090000" + } + }, + "status": "failed", + "error": { + "code": "BAD_REQUEST_ERROR", + "reason": "device_not_connected" + } +} +``` + +**Status Values:** +- `"processing"` - Checkout is being processed +- `"completed"` - Checkout completed successfully +- `"failed"` - Checkout failed with error details + +--- + +### Create device activity (Close Checkout) + +```py +client.device_activity.create({ + "device_id": "2841158834", + "action": "close_checkout" +}, device_mode="wireless") +``` + +**Parameters:** + +| Name | Type | Description | +|---------------|--------|--------------------------------------------------------------------------------| +| device_id | string | Device identifier. Required for wired mode, optional for wireless mode | +| action* | string | Action type: `close_checkout` | +| device_mode* | string | Device communication mode. Possible values: `wired`, `wireless` | + +**Success Response:** + +```json +{ + "id": "pda_NVTKa9PL0yessJ", + "entity": "device.activity", + "device_id": "2841158834", + "action": "close_checkout", + "status": "completed", + "error": null +} +``` + +**Failure Response:** + +```json +{ + "id": "pda_NVTKa9PL0yessJ", + "entity": "device.activity", + "device_id": "2841158834", + "action": "close_checkout", + "status": "failed", + "error": { + "code": "BAD_REQUEST_ERROR", + "reason": "checkout_not_found" + } +} +``` + +--- + +### Get device activity status + +```py +client.device_activity.get_status("pid_NVTKa9PL0yessI", device_mode="wired") +``` + +**Parameters:** + +| Name | Type | Description | +|---------------|--------|--------------------------------------------------------------------------------| +| activity_id* | string | ID of the device activity to fetch status for | +| device_mode* | string | Device communication mode. Possible values: `wired`, `wireless` | + +**Response:** + +```json +{ + "id": "pda_NVTKa9PL0yessI", + "entity": "device.activity", + "device_id": "2841158834", + "action": "initiate_checkout", + "initiate_checkout": { + "name": "Acme Corp", + "amount": 19900, + "currency": "INR", + "description": "POS Transaction", + "order_id": "order_R7vqkfqG3Iw02m", + "prefill": { + "name": "Gaurav Kumar", + "email": "gaurav.kumar@example.com", + "contact": "9000090000" + } + }, + "status": "processing", + "error": null +} +``` + +--- + +## Authentication + +Device Activity APIs use **public authentication** (key_id only). The SDK automatically handles this by using `use_public_auth=True` internally. + +**Authentication Type:** Public Authentication +- Uses only the `key_id` from your Razorpay credentials +- More secure for device-specific operations +- Automatically handled by the SDK + +--- + +## Device Modes + +### Wired Mode +- **device_mode**: `"wired"` +- **device_id**: Required +- Direct device connection + +### Wireless Mode +- **device_mode**: `"wireless"` +- **device_id**: Optional +- Wireless device communication + +--- + +## Error Handling + +```py +from razorpay.errors import BadRequestError + +try: + response = client.device_activity.create({ + "device_id": "2841158834", + "action": "initiate_checkout" + }, device_mode="invalid_mode") +except BadRequestError as e: + print(f"Error: {e}") + # Output: Invalid device mode. Allowed values are 'wired' and 'wireless'. +``` + +**Common Errors:** + +| Error | Description | Solution | +|-------|-------------|----------| +| `BadRequestError` | Invalid device_mode parameter | Use only `"wired"` or `"wireless"` | +| `BadRequestError` | Missing activity_id | Provide valid activity ID for get_status | +| `BadRequestError` | Missing device_id in wired mode | Include device_id when using wired mode | + +**API Error Responses:** + +| Error Code | Reason | Description | Solution | +|------------|--------|-------------|----------| +| `BAD_REQUEST_ERROR` | `device_not_connected` | Device is not connected | Check device connection and try again | +| `BAD_REQUEST_ERROR` | `checkout_not_found` | Checkout session not found | Verify checkout was initiated before closing | + +--- + +## Example Usage + +```py +import razorpay + +# Initialize client +client = razorpay.Client(auth=('key_id', 'key_secret'), base_url='http://localhost:8080') + +try: + # Step 1: Initiate checkout + activity = client.device_activity.create({ + "device_id": "2841158834", + "action": "initiate_checkout", + "notes": {"merchant_id": "12345"}, + "initiate_checkout": { + "name": "Acme Corp", + "amount": 19900, + "currency": "INR", + "description": "POS Transaction", + "type": "in_person", + "order_id": "order_R7vqkfqG3Iw02m", + "method": "upi", + "prefill": { + "name": "Gaurav Kumar", + "email": "gaurav.kumar@example.com", + "contact": "9000090000" + } + } + }, device_mode="wired") + + activity_id = activity['id'] + print(f"Checkout initiated: {activity_id}") + + # Step 2: Check status + status = client.device_activity.get_status(activity_id, device_mode="wired") + print(f"Current status: {status['status']}") + + # Step 3: Close checkout when done + close_response = client.device_activity.create({ + "device_id": "2841158834", + "action": "close_checkout", + + }, device_mode="wired") + + print("Checkout closed successfully") + +except Exception as e: + print(f"Error: {e}") +``` + +--- + +## Integration with Order APIs + +Device Activity APIs work seamlessly with Order APIs for complete POS integration: + +```py +# Create order with device_mode +order = client.order.create({ + "amount": 50000, + "currency": "INR", + "receipt": "order_001" +}, device_mode="wired") + +# Initiate device checkout +checkout = client.device_activity.create({ + "device_id": "2841158834", + "action": "initiate_checkout", + "notes": {"order_id": order['id']}, + "initiate_checkout": { + "name": "Acme Corp", + "amount": order['amount'], + "currency": order['currency'], + "description": "POS Transaction", + "type": "in_person", + "order_id": order['id'], + "method": "upi" + } +}, device_mode="wired") + +# Monitor checkout status +status = client.device_activity.get_status(checkout['id'], device_mode="wired") +``` \ No newline at end of file diff --git a/documents/posGateway.md b/documents/posGateway.md new file mode 100644 index 0000000..8ef95a8 --- /dev/null +++ b/documents/posGateway.md @@ -0,0 +1,521 @@ +## POS Gateway Integration + +Complete guide for integrating Razorpay POS Gateway with Device Activity and Order management APIs. + +## Quick Start + +```py +import razorpay + +# Initialize client +client = razorpay.Client(auth=('your_key_id', 'your_key_secret')) # Defautl base_url: 'https://api.razorpay.com' + +# For local development/testing +client = razorpay.Client( +auth=('your_key_id', 'your_key_secret'), +base_url='http://localhost:8080' +) +``` + +**Host Configuration:** +- **Production**: `https://api.razorpay.com` (default) +- **Pos-Gateway**: `http://localhost:8080` + +--- + +## Core APIs + +### 1. Device Activity Management + +For detailed API reference, see [Device Activity](deviceActivity.md). + +#### Initiate Checkout + +```py +response = client.device_activity.create({ + "device_id": "2841158834", # Required for device_mode="wired", optional for device_mode="wireless" + "action": "initiate_checkout", # Required: Action type + "notes": { # Optional: Additional notes + "key1": "value1", + "key2": "value2" + }, + "initiate_checkout": { # Required for initiate_checkout + "name": "Acme Corp", # Required: Business name + "amount": 19900, # Required: Amount in paise (₹199.00) + "currency": "INR", # Required: Currency code + "description": "POS Transaction", # Required: Transaction description + "type": "in_person", # Required: Transaction type + "order_id": "order_R7vqkfqG3Iw02m", # Required: Order reference + "method": "upi", # Required: "upi"|"card"|"netbanking"|"wallet" + "prefill": { # Optional: Customer prefill data + "name": "Gaurav Kumar", + "email": "gaurav.kumar@example.com", + "contact": "9000090000" + } + } +}, device_mode="wired") # Required: "wired" or "wireless" +``` + +#### Close Checkout + +```py +response = client.device_activity.create({ +"device_id": "2841158834", # Required for device_mode="wired", optional for device_mode="wireless" +"action": "close_checkout" # Required: Action type +}, device_mode="wireless") # Required: "wired" or "wireless" +``` + +#### Check Activity Status + +```py +response = client.device_activity.get_status( +"act_12345678", # Required: Activity ID from create response +device_mode="wired" # Required: "wired" or "wireless" +) +``` + +### 2. Order Management + +#### Create Order + +```py +order = client.order.create({ + "amount": 19900, # Required: Amount in paise (₹199.00) + "currency": "INR", # Required: Currency + "receipt": "order_rcptid_11", # Optional: Receipt ID + "notes": { # Optional: Additional notes + "key1": "value1", + "key2": "value2" + } +}, device_mode="wired") # Required: "wired" or "wireless" +``` + +**Parameters:** + +| Name | Type | Description | +|---------------|---------|--------------------------------------------------------------------------------| +| amount* | integer | Amount in paise (₹199.00 = 19900) | +| currency* | string | Currency code (e.g., "INR") | +| receipt | string | Your system order reference ID | +| notes | object | A key-value pair for additional information | +| device_mode* | string | Device communication mode. Possible values: `wired`, `wireless` | + +**Success Response:** + +```json +{ + "id": "order_R7vqkfqG3Iw02m", + "entity": "order", + "amount": 19900, + "amount_paid": 0, + "amount_due": 19900, + "currency": "INR", + "receipt": "order_rcptid_11", + "status": "created", + "attempts": 0, + "notes": { + "key1": "value1", + "key2": "value2" + }, + "created_at": 1641891747 +} +``` + +**Failure Response:** + +```json +{ + "error": { + "code": "BAD_REQUEST_ERROR", + "description": "The amount must be at least INR 1.00", + "source": "business", + "step": "payment_initiation", + "reason": "input_validation_failed" + } +} +``` + +--- + +#### Get Order Details + +```py +order = client.order.fetch( + "order_R7vqkfqG3Iw02m", + device_mode="wired" # Required: "wired" or "wireless" +) +``` + +**Parameters:** + +| Name | Type | Description | +|---------------|--------|--------------------------------------------------------------------------------| +| order_id* | string | Order ID to fetch details for | +| device_mode* | string | Device communication mode. Possible values: `wired`, `wireless` | + +**Success Response:** + +```json +{ + "id": "order_R7vqkfqG3Iw02m", + "entity": "order", + "amount": 19900, + "amount_paid": 19900, + "amount_due": 0, + "currency": "INR", + "receipt": "order_rcptid_11", + "status": "paid", + "attempts": 1, + "notes": { + "key1": "value1", + "key2": "value2" + }, + "created_at": 1641891747 +} +``` + +**Failure Response:** + +```json +{ + "error": { + "code": "BAD_REQUEST_ERROR", + "description": "The id provided does not exist", + "source": "business", + "step": "payment_initiation", + "reason": "input_validation_failed" + } +} +``` + +--- + +#### Get Order with Payments + +```py +order_with_payments = client.order.fetch( + "order_R7vqkfqG3Iw02m", + data={"expand[]": "payments"}, + device_mode="wired" # Required: "wired" or "wireless" +) +``` + +**Parameters:** + +| Name | Type | Description | +|---------------|--------|--------------------------------------------------------------------------------| +| order_id* | string | Order ID to fetch details for | +| data* | object | Expansion parameters: `{"expand[]": "payments"}` | +| device_mode* | string | Device communication mode. Possible values: `wired`, `wireless` | + +**Success Response:** + +```json +{ + "id": "order_R7vqkfqG3Iw02m", + "entity": "order", + "amount": 19900, + "amount_paid": 19900, + "amount_due": 0, + "currency": "INR", + "receipt": "order_rcptid_11", + "status": "paid", + "attempts": 1, + "notes": { + "key1": "value1", + "key2": "value2" + }, + "created_at": 1641891747, + "payments": { + "entity": "collection", + "count": 1, + "items": [ + { + "id": "pay_G8VQzjPLoAvm6D", + "entity": "payment", + "amount": 19900, + "currency": "INR", + "status": "captured", + "order_id": "order_R7vqkfqG3Iw02m", + "method": "upi", + "description": "POS Transaction", + "created_at": 1641891755, + "upi": { + "payer_account_type": "bank_account", + "vpa": "gaurav.kumar@example" + } + } + ] + } +} +``` + +**Failure Response:** + +```json +{ + "error": { + "code": "BAD_REQUEST_ERROR", + "description": "The id provided does not exist", + "source": "business", + "step": "payment_initiation", + "reason": "input_validation_failed" + } +} +``` + +--- + +## Device Modes + +| Mode | Description | device_id Required | +|------|-------------|-------------------| +| **wired** | Direct device connection | ✅ Yes | +| **wireless** | Wireless communication | ❌ Optional | + +--- + +## Complete Integration Workflow + +```py +import razorpay +import time + +class POSIntegration: +def __init__(self, key_id, key_secret, base_url=None): + """Initialize POS integration client""" + self.client = razorpay.Client( + auth=(key_id, key_secret), + base_url=base_url + ) + +def complete_pos_checkout(self, device_id, amount, device_mode="wired"): + """Complete end-to-end POS checkout process""" + try: + # Step 1: Create Order + order = self.client.order.create({ + "amount": amount, + "currency": "INR", + "receipt": f"pos_order_{int(time.time())}", + "notes": {"device_id": device_id} + }, device_mode=device_mode) + + print(f"Order created: {order['id']}") + + # Step 2: Initiate Device Checkout + activity = self.client.device_activity.create({ + "device_id": device_id, + "action": "initiate_checkout", + "notes": {"order_id": order['id']}, + "initiate_checkout": { + "name": "Acme Corp", + "amount": amount, + "currency": "INR", + "description": "POS Transaction", + "type": "in_person", + "order_id": order['id'], + "method": "upi", + "prefill": { + "name": "Customer Name", + "email": "customer@example.com", + "contact": "9000090000" + } + } + }, device_mode=device_mode) + + activity_id = activity['id'] + print(f"Checkout initiated: {activity_id}") + + # Step 3: Monitor Status (polling example) + max_attempts = 30 # 5 minutes max + for attempt in range(max_attempts): + try: + status = self.client.device_activity.get_status(activity_id, device_mode=device_mode) + current_status = status['status'] + + print(f"Status check {attempt + 1}: {current_status}") + + if current_status == 'completed': + # Step 4: Get final order details with payments + order_with_payments = self.client.order.fetch( + order['id'], + data={"expand[]": "payments"}, + device_mode=device_mode + ) + + return { + "success": True, + "order": order_with_payments, + "activity": status + } + + elif current_status == 'failed': + error_details = status.get('error', {}) + return { + "success": False, + "error": f"Checkout failed: {error_details.get('code')} - {error_details.get('reason')}", + "activity": status + } + + time.sleep(10) # Wait 10 seconds before next check + + except Exception as e: + print(f"Status check failed: {e}") + continue + + # Timeout - close checkout + self.close_checkout(device_mode=device_mode) + return { + "success": False, + "error": "Checkout timeout" + } + + except Exception as e: + return { + "success": False, + "error": str(e) + } + +def close_checkout(self, device_mode): + """Close active checkout""" + try: + return self.client.device_activity.create({ + "device_id": "2841158834", # Use your device ID + "action": "close_checkout" + }, device_mode=device_mode) + except Exception as e: + print(f"Failed to close checkout: {e}") + return None + +# Usage Example +pos = POSIntegration('your_key_id', 'your_key_secret') +result = pos.complete_pos_checkout( +device_id="2841158834", +amount=19900, # ₹199.00 +device_mode="wired" +) + +if result['success']: +print("✅ Checkout completed successfully!") +print(f"Order ID: {result['order']['id']}") +else: +print(f"❌ Checkout failed: {result['error']}") +``` + +--- + +## Authentication + +### Device Activity APIs +- **Type**: Public Authentication (key_id only) +- **Usage**: Automatically handled by SDK +- **Security**: More secure for device operations + +### Order APIs +- **Type**: Standard Authentication (key_id + key_secret) +- **Usage**: Automatically handled by SDK +- **Security**: Full authentication for payment operations + +--- + +## Error Handling + +```py +from razorpay.errors import BadRequestError + +try: +response = client.device_activity.create(data, device_mode="wired") +except BadRequestError as e: +if "Invalid device mode" in str(e): + print("Use 'wired' or 'wireless' for device_mode") +elif "Activity ID must be provided" in str(e): + print("Provide valid activity_id for get_status") +else: + print(f"API Error: {e}") +except Exception as e: +print(f"Unexpected error: {e}") +``` + +**Common Error Solutions:** + +| Error | Cause | Solution | +|-------|-------|----------| +| `Invalid device mode` | Wrong device_mode value | Use `"wired"` or `"wireless"` | +| `Activity ID must be provided` | Missing activity_id | Provide valid activity ID | +| `device_id required for wired mode` | Missing device_id | Include device_id for wired mode | + +**API Response Status Handling:** + +```py +# Check status in response +if response['status'] == 'processing': + print("Checkout initiated, waiting for completion...") +elif response['status'] == 'completed': + print("Checkout completed successfully!") +elif response['status'] == 'failed': + error_code = response['error']['code'] + error_reason = response['error']['reason'] + print(f"Checkout failed: {error_code} - {error_reason}") +``` + +**Device Activity API Error Codes:** + +| Error Code | Reason | Description | Solution | +|------------|--------|-------------|----------| +| `BAD_REQUEST_ERROR` | `device_not_connected` | Device is not connected | Check device connection and retry | +| `BAD_REQUEST_ERROR` | `checkout_not_found` | Checkout session not found | Verify checkout was initiated | + +**Order API Error Codes:** + +| Error Code | Reason | Description | Solution | +|------------|--------|-------------|----------| +| `BAD_REQUEST_ERROR` | `input_validation_failed` | Invalid parameters provided | Check amount, currency, and other parameters | +| `BAD_REQUEST_ERROR` | Order not found | The order ID does not exist | Verify the correct order ID | + +--- + +## Complete API Reference Summary + +### Device Activity APIs + +| Method | Parameters | Returns | Description | +|--------|------------|---------|-------------| +| `create()` | `data`, `device_mode` | Activity object with status | Create checkout activity | +| `get_status()` | `activity_id`, `device_mode` | Activity status | Check activity status | + +**Usage Examples:** +```py +# Initiate checkout +activity = client.device_activity.create(data, device_mode="wired") + +# Check status +status = client.device_activity.get_status("pda_123", device_mode="wired") + +# Close checkout +client.device_activity.create({"action": "close_checkout"}, device_mode="wired") +``` + +### Order APIs + +| Method | Parameters | Returns | Description | +|--------|------------|---------|-------------| +| `create()` | `data`, `device_mode` | Order object | Create new order | +| `fetch()` | `order_id`, `device_mode` | Order object | Get order details | +| `fetch()` with payments | `order_id`, `data`, `device_mode` | Order with payments | Get order with payment details | + +**Usage Examples:** +```py +# Create order +order = client.order.create(order_data, device_mode="wired") + +# Fetch order +order = client.order.fetch("order_123", device_mode="wired") + +# Fetch order with payments +order_with_payments = client.order.fetch("order_123", data={"expand[]": "payments"}, device_mode="wired") +``` + +--- + +For additional Device Activity API details, refer to: +- [Device Activity API](deviceActivity.md) - Complete API reference with error handling examples \ No newline at end of file From d3e9a99193175c275395cdf1df87a7ba23ecb128 Mon Sep 17 00:00:00 2001 From: manish soni Date: Fri, 29 Aug 2025 16:18:49 +0530 Subject: [PATCH 2/8] fix: Replace hardcoded port 8080 with PORT placeholder in documentation - Updated posGateway.md to use PORT instead of 8080 - Updated deviceActivity.md to use PORT instead of 8080 - Allows users to configure any port for local development --- documents/deviceActivity.md | 5 +- documents/posGateway.md | 174 ++++++++++++++++++------------------ 2 files changed, 89 insertions(+), 90 deletions(-) diff --git a/documents/deviceActivity.md b/documents/deviceActivity.md index 76c524e..714196d 100644 --- a/documents/deviceActivity.md +++ b/documents/deviceActivity.md @@ -261,7 +261,7 @@ except BadRequestError as e: import razorpay # Initialize client -client = razorpay.Client(auth=('key_id', 'key_secret'), base_url='http://localhost:8080') +client = razorpay.Client(auth=('key_id', 'key_secret'), base_url='http://localhost:PORT') try: # Step 1: Initiate checkout @@ -295,8 +295,7 @@ try: # Step 3: Close checkout when done close_response = client.device_activity.create({ "device_id": "2841158834", - "action": "close_checkout", - + "action": "close_checkout" }, device_mode="wired") print("Checkout closed successfully") diff --git a/documents/posGateway.md b/documents/posGateway.md index 8ef95a8..35357ce 100644 --- a/documents/posGateway.md +++ b/documents/posGateway.md @@ -12,14 +12,14 @@ client = razorpay.Client(auth=('your_key_id', 'your_key_secret')) # Defautl base # For local development/testing client = razorpay.Client( -auth=('your_key_id', 'your_key_secret'), -base_url='http://localhost:8080' + auth=('your_key_id', 'your_key_secret'), + base_url='http://localhost:PORT' ) ``` **Host Configuration:** - **Production**: `https://api.razorpay.com` (default) -- **Pos-Gateway**: `http://localhost:8080` +- **Pos-Gateway**: `http://localhost:PORT` --- @@ -60,8 +60,8 @@ response = client.device_activity.create({ ```py response = client.device_activity.create({ -"device_id": "2841158834", # Required for device_mode="wired", optional for device_mode="wireless" -"action": "close_checkout" # Required: Action type + "device_id": "2841158834", # Required for device_mode="wired", optional for device_mode="wireless" + "action": "close_checkout" # Required: Action type }, device_mode="wireless") # Required: "wired" or "wireless" ``` @@ -69,8 +69,8 @@ response = client.device_activity.create({ ```py response = client.device_activity.get_status( -"act_12345678", # Required: Activity ID from create response -device_mode="wired" # Required: "wired" or "wireless" + "act_12345678", # Required: Activity ID from create response + device_mode="wired" # Required: "wired" or "wireless" ) ``` @@ -282,27 +282,27 @@ import razorpay import time class POSIntegration: -def __init__(self, key_id, key_secret, base_url=None): - """Initialize POS integration client""" - self.client = razorpay.Client( - auth=(key_id, key_secret), - base_url=base_url - ) - -def complete_pos_checkout(self, device_id, amount, device_mode="wired"): - """Complete end-to-end POS checkout process""" - try: - # Step 1: Create Order - order = self.client.order.create({ - "amount": amount, - "currency": "INR", - "receipt": f"pos_order_{int(time.time())}", - "notes": {"device_id": device_id} - }, device_mode=device_mode) - - print(f"Order created: {order['id']}") - - # Step 2: Initiate Device Checkout + def __init__(self, key_id, key_secret, base_url=None): + """Initialize POS integration client""" + self.client = razorpay.Client( + auth=(key_id, key_secret), + base_url=base_url + ) + + def complete_pos_checkout(self, device_id, amount, device_mode="wired"): + """Complete end-to-end POS checkout process""" + try: + # Step 1: Create Order + order = self.client.order.create({ + "amount": amount, + "currency": "INR", + "receipt": f"pos_order_{int(time.time())}", + "notes": {"device_id": device_id} + }, device_mode=device_mode) + + print(f"Order created: {order['id']}") + + # Step 2: Initiate Device Checkout activity = self.client.device_activity.create({ "device_id": device_id, "action": "initiate_checkout", @@ -322,20 +322,20 @@ def complete_pos_checkout(self, device_id, amount, device_mode="wired"): } } }, device_mode=device_mode) - - activity_id = activity['id'] - print(f"Checkout initiated: {activity_id}") - - # Step 3: Monitor Status (polling example) - max_attempts = 30 # 5 minutes max - for attempt in range(max_attempts): - try: - status = self.client.device_activity.get_status(activity_id, device_mode=device_mode) - current_status = status['status'] - - print(f"Status check {attempt + 1}: {current_status}") - - if current_status == 'completed': + + activity_id = activity['id'] + print(f"Checkout initiated: {activity_id}") + + # Step 3: Monitor Status (polling example) + max_attempts = 30 # 5 minutes max + for attempt in range(max_attempts): + try: + status = self.client.device_activity.get_status(activity_id, device_mode=device_mode) + current_status = status['status'] + + print(f"Status check {attempt + 1}: {current_status}") + + if current_status == 'completed': # Step 4: Get final order details with payments order_with_payments = self.client.order.fetch( order['id'], @@ -356,50 +356,50 @@ def complete_pos_checkout(self, device_id, amount, device_mode="wired"): "error": f"Checkout failed: {error_details.get('code')} - {error_details.get('reason')}", "activity": status } - - time.sleep(10) # Wait 10 seconds before next check - - except Exception as e: - print(f"Status check failed: {e}") - continue - - # Timeout - close checkout - self.close_checkout(device_mode=device_mode) - return { - "success": False, - "error": "Checkout timeout" - } - - except Exception as e: - return { - "success": False, - "error": str(e) - } - -def close_checkout(self, device_mode): - """Close active checkout""" - try: - return self.client.device_activity.create({ - "device_id": "2841158834", # Use your device ID - "action": "close_checkout" - }, device_mode=device_mode) - except Exception as e: - print(f"Failed to close checkout: {e}") - return None + + time.sleep(10) # Wait 10 seconds before next check + + except Exception as e: + print(f"Status check failed: {e}") + continue + + # Timeout - close checkout + self.close_checkout(device_mode=device_mode) + return { + "success": False, + "error": "Checkout timeout" + } + + except Exception as e: + return { + "success": False, + "error": str(e) + } + + def close_checkout(self, device_mode): + """Close active checkout""" + try: + return self.client.device_activity.create({ + "device_id": "2841158834", # Use your device ID + "action": "close_checkout" + }, device_mode=device_mode) + except Exception as e: + print(f"Failed to close checkout: {e}") + return None # Usage Example pos = POSIntegration('your_key_id', 'your_key_secret') result = pos.complete_pos_checkout( -device_id="2841158834", -amount=19900, # ₹199.00 -device_mode="wired" + device_id="2841158834", + amount=19900, # ₹199.00 + device_mode="wired" ) if result['success']: -print("✅ Checkout completed successfully!") -print(f"Order ID: {result['order']['id']}") + print("✅ Checkout completed successfully!") + print(f"Order ID: {result['order']['id']}") else: -print(f"❌ Checkout failed: {result['error']}") + print(f"❌ Checkout failed: {result['error']}") ``` --- @@ -424,16 +424,16 @@ print(f"❌ Checkout failed: {result['error']}") from razorpay.errors import BadRequestError try: -response = client.device_activity.create(data, device_mode="wired") + response = client.device_activity.create(data, device_mode="wired") except BadRequestError as e: -if "Invalid device mode" in str(e): - print("Use 'wired' or 'wireless' for device_mode") -elif "Activity ID must be provided" in str(e): - print("Provide valid activity_id for get_status") -else: - print(f"API Error: {e}") + if "Invalid device mode" in str(e): + print("Use 'wired' or 'wireless' for device_mode") + elif "Activity ID must be provided" in str(e): + print("Provide valid activity_id for get_status") + else: + print(f"API Error: {e}") except Exception as e: -print(f"Unexpected error: {e}") + print(f"Unexpected error: {e}") ``` **Common Error Solutions:** @@ -518,4 +518,4 @@ order_with_payments = client.order.fetch("order_123", data={"expand[]": "payment --- For additional Device Activity API details, refer to: -- [Device Activity API](deviceActivity.md) - Complete API reference with error handling examples \ No newline at end of file +- [Device Activity API](deviceActivity.md) - Complete API reference with error handling examples \ No newline at end of file From 157a0253d7b0316720b4e0cecb63bdc354308199 Mon Sep 17 00:00:00 2001 From: manish soni Date: Wed, 3 Sep 2025 11:44:10 +0530 Subject: [PATCH 3/8] fix: reverse device_mode requirements in documentation - Update comments to show device_id is required for wireless mode - Update comments to show device_id is optional for wired mode - Applied changes to deviceActivity.md and posGateway.md --- documents/deviceActivity.md | 2 +- documents/posGateway.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/documents/deviceActivity.md b/documents/deviceActivity.md index 714196d..1f1c168 100644 --- a/documents/deviceActivity.md +++ b/documents/deviceActivity.md @@ -4,7 +4,7 @@ ```py client.device_activity.create({ - "device_id": "2841158834", # Required for device_mode="wired", optional for device_mode="wireless" + "device_id": "2841158834", # Required for device_mode="wireless", optional for device_mode="wired" "action": "initiate_checkout", # Required: Action type "notes": { # Optional: Additional notes "key1": "value1", diff --git a/documents/posGateway.md b/documents/posGateway.md index 35357ce..4ca5f63 100644 --- a/documents/posGateway.md +++ b/documents/posGateway.md @@ -33,7 +33,7 @@ For detailed API reference, see [Device Activity](deviceActivity.md). ```py response = client.device_activity.create({ - "device_id": "2841158834", # Required for device_mode="wired", optional for device_mode="wireless" + "device_id": "2841158834", # Required for device_mode="wireless", optional for device_mode="wired" "action": "initiate_checkout", # Required: Action type "notes": { # Optional: Additional notes "key1": "value1", @@ -60,7 +60,7 @@ response = client.device_activity.create({ ```py response = client.device_activity.create({ - "device_id": "2841158834", # Required for device_mode="wired", optional for device_mode="wireless" + "device_id": "2841158834", # Required for device_mode="wireless", optional for device_mode="wired" "action": "close_checkout" # Required: Action type }, device_mode="wireless") # Required: "wired" or "wireless" ``` From 43afbbc9b778e57f52f566a563b2120514664199 Mon Sep 17 00:00:00 2001 From: manish soni Date: Sat, 13 Sep 2025 19:33:44 +0530 Subject: [PATCH 4/8] docs: Update POS Gateway documentation - Move method field inside prefill object and mark as optional - Make type field optional in initiate_checkout - Add comprehensive API error codes section for client reference - Update device mode requirements (wireless requires device_id, wired is optional) - Remove internal RPGS error codes from client documentation - Update parameter tables and examples to reflect new structure --- documents/deviceActivity.md | 98 +++------- documents/posGateway.md | 353 +++++++++++++++++++++++++++++++++--- 2 files changed, 359 insertions(+), 92 deletions(-) diff --git a/documents/deviceActivity.md b/documents/deviceActivity.md index 1f1c168..da62ae4 100644 --- a/documents/deviceActivity.md +++ b/documents/deviceActivity.md @@ -15,13 +15,13 @@ client.device_activity.create({ "amount": 19900, # Required: Amount in paise (₹199.00) "currency": "INR", # Required: Currency code "description": "POS Transaction", # Required: Transaction description - "type": "in_person", # Required: Transaction type + "type": "in_person", # Optional: Transaction type "order_id": "order_R7vqkfqG3Iw02m", # Required: Order reference - "method": "upi", # Required: "upi"|"card"|"netbanking"|"wallet" "prefill": { # Optional: Customer prefill data "name": "Gaurav Kumar", "email": "gaurav.kumar@example.com", - "contact": "9000090000" + "contact": "9000090000", + "method": "upi" # Optional: "upi"|"card"|"netbanking"|"wallet" } } }, device_mode="wired") @@ -31,7 +31,7 @@ client.device_activity.create({ | Name | Type | Description | |---------------|--------|--------------------------------------------------------------------------------| -| device_id | string | Device identifier. Required for wired mode, optional for wireless mode | +| device_id | string | Device identifier. Required for wireless mode, optional for wired mode | | action* | string | Action type. Possible values: `initiate_checkout`, `close_checkout` | | notes | object | A key-value pair for additional information | | initiate_checkout* | object | Required when action is `initiate_checkout`. Contains checkout details | @@ -45,10 +45,18 @@ client.device_activity.create({ | amount* | integer| Amount in paise (₹199.00 = 19900) | | currency* | string | Currency code (e.g., "INR") | | description* | string | Transaction description | -| type* | string | Transaction type (e.g., "in_person") | +| type | string | Optional transaction type (e.g., "in_person") | | order_id* | string | Order reference ID | -| method* | string | Payment method: "upi", "card", "netbanking", "wallet" | -| prefill | object | Optional customer prefill data (name, email, contact) | +| prefill | object | Optional customer prefill data (name, email, contact, method) | + +**prefill Object Parameters:** + +| Name | Type | Description | +|---------------|--------|--------------------------------------------------------------------------------| +| name | string | Optional customer name | +| email | string | Optional customer email | +| contact | string | Optional customer contact number | +| method | string | Optional payment method: "upi", "card", "netbanking", "wallet" | **Success Response:** @@ -67,7 +75,8 @@ client.device_activity.create({ "prefill": { "name": "Gaurav Kumar", "email": "gaurav.kumar@example.com", - "contact": "9000090000" + "contact": "9000090000", + "method": "upi" } }, "status": "processing", @@ -92,7 +101,8 @@ client.device_activity.create({ "prefill": { "name": "Gaurav Kumar", "email": "gaurav.kumar@example.com", - "contact": "9000090000" + "contact": "9000090000", + "method": "upi" } }, "status": "failed", @@ -123,7 +133,7 @@ client.device_activity.create({ | Name | Type | Description | |---------------|--------|--------------------------------------------------------------------------------| -| device_id | string | Device identifier. Required for wired mode, optional for wireless mode | +| device_id | string | Device identifier. Required for wireless mode, optional for wired mode | | action* | string | Action type: `close_checkout` | | device_mode* | string | Device communication mode. Possible values: `wired`, `wireless` | @@ -155,70 +165,18 @@ client.device_activity.create({ } } ``` - ---- - -### Get device activity status - -```py -client.device_activity.get_status("pid_NVTKa9PL0yessI", device_mode="wired") -``` - -**Parameters:** - -| Name | Type | Description | -|---------------|--------|--------------------------------------------------------------------------------| -| activity_id* | string | ID of the device activity to fetch status for | -| device_mode* | string | Device communication mode. Possible values: `wired`, `wireless` | - -**Response:** - -```json -{ - "id": "pda_NVTKa9PL0yessI", - "entity": "device.activity", - "device_id": "2841158834", - "action": "initiate_checkout", - "initiate_checkout": { - "name": "Acme Corp", - "amount": 19900, - "currency": "INR", - "description": "POS Transaction", - "order_id": "order_R7vqkfqG3Iw02m", - "prefill": { - "name": "Gaurav Kumar", - "email": "gaurav.kumar@example.com", - "contact": "9000090000" - } - }, - "status": "processing", - "error": null -} -``` - ---- - -## Authentication - -Device Activity APIs use **public authentication** (key_id only). The SDK automatically handles this by using `use_public_auth=True` internally. - -**Authentication Type:** Public Authentication -- Uses only the `key_id` from your Razorpay credentials -- More secure for device-specific operations -- Automatically handled by the SDK - --- ## Device Modes ### Wired Mode - **device_mode**: `"wired"` -- **device_id**: Required +- **device_id**: Optional - Direct device connection ### Wireless Mode - **device_mode**: `"wireless"` -- **device_id**: Optional +- **device_id**: Required - Wireless device communication --- @@ -244,7 +202,7 @@ except BadRequestError as e: |-------|-------------|----------| | `BadRequestError` | Invalid device_mode parameter | Use only `"wired"` or `"wireless"` | | `BadRequestError` | Missing activity_id | Provide valid activity ID for get_status | -| `BadRequestError` | Missing device_id in wired mode | Include device_id when using wired mode | +| `BadRequestError` | Missing device_id in wireless mode | Include device_id when using wireless mode | **API Error Responses:** @@ -274,13 +232,13 @@ try: "amount": 19900, "currency": "INR", "description": "POS Transaction", - "type": "in_person", + "type": "in_person", # Optional "order_id": "order_R7vqkfqG3Iw02m", - "method": "upi", "prefill": { "name": "Gaurav Kumar", "email": "gaurav.kumar@example.com", - "contact": "9000090000" + "contact": "9000090000", + "method": "upi" } } }, device_mode="wired") @@ -330,7 +288,9 @@ checkout = client.device_activity.create({ "description": "POS Transaction", "type": "in_person", "order_id": order['id'], - "method": "upi" + "prefill": { + "method": "upi" + } } }, device_mode="wired") diff --git a/documents/posGateway.md b/documents/posGateway.md index 4ca5f63..f7ab224 100644 --- a/documents/posGateway.md +++ b/documents/posGateway.md @@ -44,13 +44,13 @@ response = client.device_activity.create({ "amount": 19900, # Required: Amount in paise (₹199.00) "currency": "INR", # Required: Currency code "description": "POS Transaction", # Required: Transaction description - "type": "in_person", # Required: Transaction type + "type": "in_person", # Optional: Transaction type "order_id": "order_R7vqkfqG3Iw02m", # Required: Order reference - "method": "upi", # Required: "upi"|"card"|"netbanking"|"wallet" "prefill": { # Optional: Customer prefill data "name": "Gaurav Kumar", "email": "gaurav.kumar@example.com", - "contact": "9000090000" + "contact": "9000090000", + "method": "upi" # Optional: "upi"|"card"|"netbanking"|"wallet" } } }, device_mode="wired") # Required: "wired" or "wireless" @@ -270,8 +270,8 @@ order_with_payments = client.order.fetch( | Mode | Description | device_id Required | |------|-------------|-------------------| -| **wired** | Direct device connection | ✅ Yes | -| **wireless** | Wireless communication | ❌ Optional | +| **wireless** | Wireless communication | ✅ Yes | +| **wired** | Direct device connection | ❌ Optional | --- @@ -312,13 +312,13 @@ class POSIntegration: "amount": amount, "currency": "INR", "description": "POS Transaction", - "type": "in_person", + "type": "in_person", # Optional "order_id": order['id'], - "method": "upi", "prefill": { "name": "Customer Name", "email": "customer@example.com", - "contact": "9000090000" + "contact": "9000090000", + "method": "upi" } } }, device_mode=device_mode) @@ -404,20 +404,6 @@ else: --- -## Authentication - -### Device Activity APIs -- **Type**: Public Authentication (key_id only) -- **Usage**: Automatically handled by SDK -- **Security**: More secure for device operations - -### Order APIs -- **Type**: Standard Authentication (key_id + key_secret) -- **Usage**: Automatically handled by SDK -- **Security**: Full authentication for payment operations - ---- - ## Error Handling ```py @@ -442,7 +428,7 @@ except Exception as e: |-------|-------|----------| | `Invalid device mode` | Wrong device_mode value | Use `"wired"` or `"wireless"` | | `Activity ID must be provided` | Missing activity_id | Provide valid activity ID | -| `device_id required for wired mode` | Missing device_id | Include device_id for wired mode | +| `device_id required for wireless mode` | Missing device_id | Include device_id for wireless mode | **API Response Status Handling:** @@ -517,5 +503,326 @@ order_with_payments = client.order.fetch("order_123", data={"expand[]": "payment --- +## API Error Codes and Messages + +This section provides comprehensive error information that clients may encounter when calling POS Gateway APIs. + +### Error Response Format + +All APIs return errors in the following standardized format: + +```json +{ + "error": { + "code": "ERROR_CODE", + "description": "Human-readable error message", + "source": "error_source", + "step": "operation_step", + "reason": "technical_reason", + "field": "field_name", + "metadata": { + "additional": "context" + } + } +} +``` + +**Error Response Fields:** + +| Field | Type | Description | +|-------|------|-------------| +| code | string | Error code identifier | +| description | string | Human-readable error message | +| source | string | Component that generated the error | +| step | string | Operation step where error occurred (optional) | +| reason | string | Technical reason for the error (optional) | +| field | string | Field that caused validation error (optional) | +| metadata | object | Additional error context (optional) | + +--- + +### Device Activity API Errors + +#### POST /v1/devices/activity + +**HTTP Status Codes:** +- `200` - Success +- `400` - Validation errors +- `500` - Processing/Device errors + +**Common Error Scenarios:** + +```json +// Missing required field +{ + "error": { + "code": "VALIDATION_FAILED", + "description": "Action field is required", + "source": "activity_processor", + "field": "action", + "reason": "required_field_missing" + } +} + +// Invalid amount +{ + "error": { + "code": "VALIDATION_FAILED", + "description": "Amount must be greater than 0", + "source": "activity_processor", + "field": "initiate_checkout.amount", + "reason": "invalid_value" + } +} + +// Device not connected +{ + "error": { + "code": "DEVICE_DISCONNECTED", + "description": "Device is not connected", + "source": "device_controller" + } +} + +// Device busy/invalid state +{ + "error": { + "code": "DEVICE_BUSY", + "description": "Device is in an invalid state or transitioning", + "source": "device_controller" + } +} +``` + +**Validation Error Codes:** + +| Error Code | Field | Description | Solution | +|------------|-------|-------------|----------| +| `VALIDATION_FAILED` | `action` | Missing action field | Provide `"initiate_checkout"` or `"close_checkout"` | +| `VALIDATION_FAILED` | `initiate_checkout.amount` | Invalid or missing amount | Provide amount > 0 in paise | +| `VALIDATION_FAILED` | `initiate_checkout.currency` | Missing currency | Provide currency code (e.g., "INR") | +| `VALIDATION_FAILED` | `initiate_checkout.order_id` | Missing order ID | Provide valid order ID | +| `VALIDATION_FAILED` | `device_id` | Missing device ID | Required for wireless mode | +| `VALIDATION_FAILED` | `device_mode` | Invalid communication mode | Use `"wired"` or `"wireless"` | + +**Device Error Codes:** + +| Error Code | Description | Solution | +|------------|-------------|----------| +| `DEVICE_DISCONNECTED` | Device is not connected | Check device connection and retry | +| `DEVICE_NOT_FOUND` | Device not found during discovery | Verify device is connected and powered on | +| `DEVICE_BUSY` | Device is in invalid state | Wait for current operation to complete | +| `DEVICE_TIMEOUT` | Device operation timed out | Check device connection and retry | +| `DEVICE_ERROR` | Generic device communication error | Check device status and connection | +| `UNSUPPORTED_ACTION` | Invalid action for device state | Verify device supports the requested action | + +#### GET /v1/devices/activity/{activity_id} + +**HTTP Status Codes:** +- `200` - Success +- `400` - Invalid activity ID +- `404` - Activity not found +- `500` - Processing errors + +**Error Examples:** + +```json +// Activity not found +{ + "error": { + "code": "ACTIVITY_NOT_FOUND", + "description": "Activity with given ID not found", + "source": "activity_processor" + } +} + +// Invalid activity ID format +{ + "error": { + "code": "VALIDATION_FAILED", + "description": "Invalid activity ID format", + "source": "activity_processor", + "field": "activity_id" + } +} +``` + +--- + +### Order API Errors + +#### POST /v1/orders + +**HTTP Status Codes:** +- `200` - Success +- `400` - Validation errors +- `500` - Processing errors + +**Common Error Scenarios:** + +```json +// Missing required field +{ + "error": { + "code": "VALIDATION_FAILED", + "description": "Amount field is required", + "source": "order_processor", + "field": "amount", + "reason": "required_field_missing" + } +} + +// Invalid amount +{ + "error": { + "code": "VALIDATION_FAILED", + "description": "Amount must be at least INR 1.00", + "source": "order_processor", + "field": "amount", + "reason": "amount_too_small" + } +} + +// Device in proxy mode +{ + "error": { + "code": "BUSINESS_LOGIC_ERROR", + "description": "Device is in proxy mode, cannot process order", + "source": "order_processor" + } +} +``` + +**Order Validation Errors:** + +| Error Code | Field | Description | Solution | +|------------|-------|-------------|----------| +| `VALIDATION_FAILED` | `amount` | Missing or invalid amount | Provide amount ≥ 100 paise (₹1.00) | +| `VALIDATION_FAILED` | `currency` | Missing or invalid currency | Provide valid currency code (e.g., "INR") | +| `VALIDATION_FAILED` | `device_mode` | Missing communication mode | Use `"wired"` or `"wireless"` | + +#### GET /v1/orders/{order_id} + +**HTTP Status Codes:** +- `200` - Success +- `400` - Invalid order ID +- `404` - Order not found +- `500` - Processing errors + +**Error Examples:** + +```json +// Order not found +{ + "error": { + "code": "ORDER_NOT_FOUND", + "description": "Order with given ID not found", + "source": "order_processor" + } +} +``` + +--- + +### Device-Specific Error Codes + +These errors originate from the physical POS device: + +**Card Transaction Errors:** + +```json +{ + "error": { + "code": "CARD_DECLINED", + "description": "Transaction was declined by the card issuer", + "source": "DEVICE", + "step": "AUTHORIZATION", + "reason": "Insufficient funds" + } +} +``` + +**Common Device Error Codes:** + +| Error Code | Description | User Action | +|------------|-------------|-------------| +| `CARD_DECLINED` | Card transaction declined | Try different card or payment method | +| `CARD_READ_ERROR` | Failed to read card data | Clean card and retry insertion | +| `INVALID_PIN` | Incorrect PIN entered | Re-enter correct PIN | +| `TIMEOUT` | Transaction timed out | Retry transaction | +| `TRANSACTION_CANCELLED` | User cancelled transaction | Restart checkout if needed | +| `NETWORK_ERROR` | Device network connectivity issue | Check device network connection | +| `DEVICE_MALFUNCTION` | Hardware malfunction | Contact support | + +--- + +### HTTP Status Code Reference + +| Status Code | Meaning | When It Occurs | +|-------------|---------|----------------| +| `200` | Success | Request processed successfully | +| `400` | Bad Request | Validation errors, malformed requests | +| `401` | Unauthorized | Authentication failed (proxy mode) | +| `404` | Not Found | Resource not found (order/activity ID) | +| `500` | Internal Server Error | Device errors, system failures | + +--- + +### Error Handling Best Practices + +**1. Retry Logic:** +```python +import time + +def retry_device_operation(operation_func, max_retries=3): + for attempt in range(max_retries): + try: + return operation_func() + except Exception as e: + error_code = getattr(e, 'code', None) + + # Retry for transient errors + if error_code in ['DEVICE_BUSY', 'DEVICE_TIMEOUT', 'DEVICE_DISCONNECTED']: + if attempt < max_retries - 1: + time.sleep(2 ** attempt) # Exponential backoff + continue + raise e +``` + +**2. Error Classification:** +```python +def classify_error(error_response): + error_code = error_response.get('error', {}).get('code', '') + + # Validation errors - fix request + if error_code == 'VALIDATION_FAILED': + return 'CLIENT_ERROR' + + # Device errors - may be transient + if error_code.startswith('DEVICE_'): + return 'DEVICE_ERROR' + + # System errors - retry or escalate + if error_code in ['PROCESSING_FAILED', 'BUSINESS_LOGIC_ERROR']: + return 'SYSTEM_ERROR' + + return 'UNKNOWN_ERROR' +``` + +**3. User-Friendly Messages:** +```python +ERROR_MESSAGES = { + 'DEVICE_DISCONNECTED': 'Please check if the POS device is connected and try again.', + 'CARD_DECLINED': 'Your card was declined. Please try a different payment method.', + 'DEVICE_TIMEOUT': 'The device is taking too long to respond. Please try again.', + 'VALIDATION_FAILED': 'Please check your request and try again.', +} + +def get_user_message(error_code): + return ERROR_MESSAGES.get(error_code, 'An unexpected error occurred. Please try again.') +``` + +--- + For additional Device Activity API details, refer to: - [Device Activity API](deviceActivity.md) - Complete API reference with error handling examples \ No newline at end of file From 2bc1c5cf724207b35dda2d5ca569a1b4d6d7003b Mon Sep 17 00:00:00 2001 From: manish soni Date: Sun, 14 Sep 2025 18:14:26 +0530 Subject: [PATCH 5/8] Order first and then device activity APIs --- documents/posGateway.md | 100 ++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/documents/posGateway.md b/documents/posGateway.md index f7ab224..059e643 100644 --- a/documents/posGateway.md +++ b/documents/posGateway.md @@ -25,56 +25,7 @@ client = razorpay.Client( ## Core APIs -### 1. Device Activity Management - -For detailed API reference, see [Device Activity](deviceActivity.md). - -#### Initiate Checkout - -```py -response = client.device_activity.create({ - "device_id": "2841158834", # Required for device_mode="wireless", optional for device_mode="wired" - "action": "initiate_checkout", # Required: Action type - "notes": { # Optional: Additional notes - "key1": "value1", - "key2": "value2" - }, - "initiate_checkout": { # Required for initiate_checkout - "name": "Acme Corp", # Required: Business name - "amount": 19900, # Required: Amount in paise (₹199.00) - "currency": "INR", # Required: Currency code - "description": "POS Transaction", # Required: Transaction description - "type": "in_person", # Optional: Transaction type - "order_id": "order_R7vqkfqG3Iw02m", # Required: Order reference - "prefill": { # Optional: Customer prefill data - "name": "Gaurav Kumar", - "email": "gaurav.kumar@example.com", - "contact": "9000090000", - "method": "upi" # Optional: "upi"|"card"|"netbanking"|"wallet" - } - } -}, device_mode="wired") # Required: "wired" or "wireless" -``` - -#### Close Checkout - -```py -response = client.device_activity.create({ - "device_id": "2841158834", # Required for device_mode="wireless", optional for device_mode="wired" - "action": "close_checkout" # Required: Action type -}, device_mode="wireless") # Required: "wired" or "wireless" -``` - -#### Check Activity Status - -```py -response = client.device_activity.get_status( - "act_12345678", # Required: Activity ID from create response - device_mode="wired" # Required: "wired" or "wireless" -) -``` - -### 2. Order Management +### 1. Order Management #### Create Order @@ -264,6 +215,55 @@ order_with_payments = client.order.fetch( } ``` +### 2. Device Activity Management + +For detailed API reference, see [Device Activity](deviceActivity.md). + +#### Initiate Checkout + +```py +response = client.device_activity.create({ + "device_id": "2841158834", # Required for device_mode="wireless", optional for device_mode="wired" + "action": "initiate_checkout", # Required: Action type + "notes": { # Optional: Additional notes + "key1": "value1", + "key2": "value2" + }, + "initiate_checkout": { # Required for initiate_checkout + "name": "Acme Corp", # Required: Business name + "amount": 19900, # Required: Amount in paise (₹199.00) + "currency": "INR", # Required: Currency code + "description": "POS Transaction", # Required: Transaction description + "type": "in_person", # Optional: Transaction type + "order_id": "order_R7vqkfqG3Iw02m", # Required: Order reference + "prefill": { # Optional: Customer prefill data + "name": "Gaurav Kumar", + "email": "gaurav.kumar@example.com", + "contact": "9000090000", + "method": "upi" # Optional: "upi"|"card"|"netbanking"|"wallet" + } + } +}, device_mode="wired") # Required: "wired" or "wireless" +``` + +#### Close Checkout + +```py +response = client.device_activity.create({ + "device_id": "2841158834", # Required for device_mode="wireless", optional for device_mode="wired" + "action": "close_checkout" # Required: Action type +}, device_mode="wireless") # Required: "wired" or "wireless" +``` + +#### Check Activity Status + +```py +response = client.device_activity.get_status( + "act_12345678", # Required: Activity ID from create response + device_mode="wired" # Required: "wired" or "wireless" +) +``` + --- ## Device Modes From 7d1bbc0b38c9b8eb9c9a9c49ae9d952b61681838 Mon Sep 17 00:00:00 2001 From: manish soni Date: Mon, 15 Sep 2025 14:16:16 +0530 Subject: [PATCH 6/8] docs: Update device mode requirements and remove authentication section - Update device mode requirements: wireless requires device_id, wired is optional - Remove authentication section from posGateway.md as requested - Update error handling documentation to reflect correct device_id requirements - Align documentation with actual API behavior --- documents/deviceActivity.md | 2 +- documents/posGateway.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/documents/deviceActivity.md b/documents/deviceActivity.md index da62ae4..ad70666 100644 --- a/documents/deviceActivity.md +++ b/documents/deviceActivity.md @@ -21,7 +21,7 @@ client.device_activity.create({ "name": "Gaurav Kumar", "email": "gaurav.kumar@example.com", "contact": "9000090000", - "method": "upi" # Optional: "upi"|"card"|"netbanking"|"wallet" + "method": "upi" # Optional: "upi"|"card" } } }, device_mode="wired") diff --git a/documents/posGateway.md b/documents/posGateway.md index 059e643..46946b8 100644 --- a/documents/posGateway.md +++ b/documents/posGateway.md @@ -240,7 +240,7 @@ response = client.device_activity.create({ "name": "Gaurav Kumar", "email": "gaurav.kumar@example.com", "contact": "9000090000", - "method": "upi" # Optional: "upi"|"card"|"netbanking"|"wallet" + "method": "upi" # Optional: "upi"|"card" } } }, device_mode="wired") # Required: "wired" or "wireless" From d3fb8a0dd7fb3153f70ad179ef0324119d5e6c23 Mon Sep 17 00:00:00 2001 From: manish soni Date: Mon, 15 Sep 2025 14:19:45 +0530 Subject: [PATCH 7/8] docs: Final updates to POS Gateway documentation - Update device mode requirements consistently across both files - Ensure wireless mode requires device_id, wired mode is optional - Remove sections that were marked for deletion - Clean up documentation structure and formatting - Align all examples with updated requirements --- documents/deviceActivity.md | 2 +- documents/posGateway.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/documents/deviceActivity.md b/documents/deviceActivity.md index ad70666..e9d5f43 100644 --- a/documents/deviceActivity.md +++ b/documents/deviceActivity.md @@ -11,7 +11,7 @@ client.device_activity.create({ "key2": "value2" }, "initiate_checkout": { # Required for initiate_checkout - "name": "Acme Corp", # Required: Business name + "name": "Acme Corp", # Optional: Business name "amount": 19900, # Required: Amount in paise (₹199.00) "currency": "INR", # Required: Currency code "description": "POS Transaction", # Required: Transaction description diff --git a/documents/posGateway.md b/documents/posGateway.md index 46946b8..b3e51c5 100644 --- a/documents/posGateway.md +++ b/documents/posGateway.md @@ -230,7 +230,7 @@ response = client.device_activity.create({ "key2": "value2" }, "initiate_checkout": { # Required for initiate_checkout - "name": "Acme Corp", # Required: Business name + "name": "Acme Corp", # Optional: Business name "amount": 19900, # Required: Amount in paise (₹199.00) "currency": "INR", # Required: Currency code "description": "POS Transaction", # Required: Transaction description From f2820c6592feb6244adb6b5fbea08977d07ee689 Mon Sep 17 00:00:00 2001 From: manish soni Date: Mon, 15 Sep 2025 14:21:01 +0530 Subject: [PATCH 8/8] docs: Final cleanup of deviceActivity.md - Complete final adjustments to device activity documentation - Ensure consistency across all documentation files --- documents/deviceActivity.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documents/deviceActivity.md b/documents/deviceActivity.md index e9d5f43..e5c133c 100644 --- a/documents/deviceActivity.md +++ b/documents/deviceActivity.md @@ -56,7 +56,7 @@ client.device_activity.create({ | name | string | Optional customer name | | email | string | Optional customer email | | contact | string | Optional customer contact number | -| method | string | Optional payment method: "upi", "card", "netbanking", "wallet" | +| method | string | Optional payment method: "upi", "card" **Success Response:**