Python SDK
This SDK offers simple to use api for integrating PineLabs api in your python applications. It provide several easy methods for creating, fetching orders and calculate EMIs and verify hash.
A step-by-step guide on the usage is available here: Plural by Pinelabs | Youtube
Sample app: Link
Refer to Github: Link
Installation
In order to use this SDK locally from a folder you'll need to copy the sdk
folder in your project and import it in your python file.
from src.pinelabs import Pinelabs
Usage For SDK
Create Instance of PineLabs SDK
Import pinelabs sdk and create object of Pinelabs class. It takes 4 parameters which are as follows:
- merchant_id (string) : Merchant ID provided by PineLabs
- access_code (string) : Merchant Access Code Provided by PineLabs
- secret (string) : Merchant Secret
- is_test (boolean) : If using test mode then set this to
true
const pinelabs = Pinelabs("{merchant_id}", "{access_code}", "{secret}", is_test)
Create Order
This section explains how to create order for payment processing. There are a couple of things required in order to create an order.
Parameters Required & Optional
// Transaction Data ( Mandatory )
const txn_data = {
txn_id: "", // String
callback: "", // String
amount_in_paisa: "1000", // String
}
// Customer Data ( Optional )
const customer_data = {
email_id: "", // String
first_name: "", // String
last_name: "", // String
mobile_no: "", // String
customer_id: "", // String
}
// Billing Data ( Optional )
const billing_data = {
address1: "", // String
address2: "", // String
address3: "", // String
pincode: "", // String
city: "", // String
state: "", // String
country: "", // String
}
// Shipping Data ( Optional )
const shipping_data = {
first_name: "", // String
last_name: "", // String
mobile_no: "", // String
address1: "", // String
address2: "", // String
address3: "", // String
pincode: "", // String
city: "", // String
state: "", // String
country: "", // String
}
// UDF data ( Optional )
const udf_data = {
udf_field_1: "", // String
udf_field_2: "", // String
udf_field_3: "", // String
udf_field_4: "", // String
udf_field_5: "", // String
}
// Payment Modes That Needs To Be Shown ( Mandatory )
const payment_mode = {
netbanking: true, // Boolean
cards: true, // Boolean
emi: true, // Boolean
upi: true, // Boolean
cardless_emi: true, // Boolean
wallet: true, // Boolean
debit_emi: true, // Boolean
prebooking: true, // Boolean
bnpl: true, // Boolean
paybypoints: false, // Boolean
}
// Product Details ( Optional, Required For Multicart )
const product_details = [
{
"product_code": "testSKU1", // String
"product_amount": 500000 // Integer
},
{
"product_code": "testSKU1", // String
"product_amount": 500000 // Integer
}
]
Order Creation
Using the instance of the SDK we created above we will call the .create()
method on the payment
interface for
creating an order with the provided parameters. It takes the following positional arguments
- Transaction Data
- Customer Data
- Billing Data
- Shipping Data
- UDF Data
- Payment Modes
- Product Details
The create()
method returns a promise with the response or else throws an error if something went wrong.
// Create Order
try :
orderCreateResponse = pinelabs.payment.create(txn_data, customer_data, billing_data, shipping_data, udf_data, payment_mode, products_details)
print(orderCreateResponse)
except Exception as e:
print("Exception : " , e)
Success Response
{
"status": true,
"redirect_url": "https://uat.pinepg.in/pinepg/v2/process/payment?token=S01wPSlIH%2bopelRVif7m7e4SgrTRIcKYx25YDYfmgtbPOE%3d",
"token": "S01wPSlIH%2bopelRVif7m7e4SgrTRIcKYx25YDYfmgtbPOE%3d"
}
Failure Response
Exception : DUPLICATE TRANSACTION ID RECEIVED FROM MERCHANT
Fetch Order
Using the instance of the SDK we created above we will call the .fetch()
method on the payment
interface for
fetching
an order details with the provided transaction id and transaction type. It takes the following positional arguments
- Transaction ID
// Fetch Order
try :
orderFetchResponse = pinelabs.payment.fetch("650acb67d3752")
print({"response":orderFetchResponse})
except Exception as e:
print("Exception : " , e)
Success Response
{
"ppc_MerchantID": "106600",
"ppc_MerchantAccessCode": "bcf441be-411b-46a1-aa88-c6e852a7d68c",
"ppc_PinePGTxnStatus": "7",
"ppc_TransactionCompletionDateTime": "20\/09\/2023 04:07:52 PM",
"ppc_UniqueMerchantTxnID": "650acb67d3752",
"ppc_Amount": "1000",
"ppc_TxnResponseCode": "1",
"ppc_TxnResponseMessage": "SUCCESS",
"ppc_PinePGTransactionID": "12069839",
"ppc_CapturedAmount": "1000",
"ppc_RefundedAmount": "0",
"ppc_AcquirerName": "BILLDESK",
"ppc_DIA_SECRET": "D640CFF0FCB8D42B74B1AFD19D97A375DAF174CCBE9555E40CC6236964928896",
"ppc_DIA_SECRET_TYPE": "SHA256",
"ppc_PaymentMode": "3",
"ppc_Parent_TxnStatus": "4",
"ppc_ParentTxnResponseCode": "1",
"ppc_ParentTxnResponseMessage": "SUCCESS",
"ppc_CustomerMobile": "7737291210",
"ppc_UdfField1": "",
"ppc_UdfField2": "",
"ppc_UdfField3": "",
"ppc_UdfField4": "",
"ppc_AcquirerResponseCode": "0300",
"ppc_AcquirerResponseMessage": "NA"
}
Failure Response
Exception : Invalid Data
EMI Calculator
Using the instance of the SDK we created above we will call the .calculate()
method on the emi
interface for
fetching
offers for EMI with the provided product details. It takes the following positional arguments
- Transaction Data
- Product Details
// Emi Calculation
const txn_data = {
amount_in_paisa: "1000",
}
const products_details = [
{
"product_code": "testproduct02",
"product_amount": "10000"
}
];
try :
orderEmiResponse = pinelabs.emi.calculate(txn_data, products_details)
print(orderEmiResponse)
except Exception as e:
print("Exception : " , e)
Success Response
{
"issuer": [
{
"list_emi_tenure": [
{
"offer_scheme": {
"product_details": [
{
"schemes": [],
"product_code": "testproduct02",
"product_amount": 10000,
"subvention_cashback_discount": 0,
"product_discount": 0,
"subvention_cashback_discount_percentage": 0,
"product_discount_percentage": 0,
"subvention_type": 3,
"bank_interest_rate_percentage": 150000,
"bank_interest_rate": 251
}
],
"emi_scheme": {
"scheme_id": 48040,
"program_type": 105,
"is_scheme_valid": true
}
},
"tenure_id": "3",
"tenure_in_month": "3",
"monthly_installment": 3417,
"bank_interest_rate": 150000,
"interest_pay_to_bank": 251,
"total_offerred_discount_cashback_amount": 0,
"loan_amount": 10000,
"auth_amount": 10000
},
{
"offer_scheme": {
"product_details": [
{
"schemes": [],
"product_code": "testproduct02",
"product_amount": 10000,
"subvention_cashback_discount": 0,
"product_discount": 0,
"subvention_cashback_discount_percentage": 0,
"product_discount_percentage": 0,
"subvention_type": 3,
"bank_interest_rate_percentage": 150000,
"bank_interest_rate": 440
}
],
"emi_scheme": {
"scheme_id": 48040,
"program_type": 105,
"is_scheme_valid": true
}
},
"tenure_id": "6",
"tenure_in_month": "6",
"monthly_installment": 1740,
"bank_interest_rate": 150000,
"interest_pay_to_bank": 440,
"total_offerred_discount_cashback_amount": 0,
"loan_amount": 10000,
"auth_amount": 10000
}
],
"issuer_name": "HDFC",
"is_debit_emi_issuer": false
}
],
"response_code": 1,
"response_message": "SUCCESS"
}
Failure Response
Exception : INVALID DATA,MISMATCH_IN_TOTAL_CART_AMOUNT_AND_TOTAL_PRODUCT_AMOUNT
Verify Hash
Using the instance of the SDK we created above we will call the .verify()
method on the hash
interface for
verifying
a hash received in the response of callback and webhooks. It takes the following positional arguments
- Hash Received in Response (
ppc_DIA_SECRET
) - Response Received ( Not including
ppc_DIA_SECRET
andppc_DIA_SECRET_TYPE
)
// Verify Hash
try :
hash = orderResponse["ppc_DIA_SECRET"]
keys_to_remove = ["ppc_DIA_SECRET", "ppc_DIA_SECRET_TYPE"]
for key in keys_to_remove:
orderResponse.pop(key, None)
isVerified = pinelabs.hash.verify(hash, orderResponse)
print(isVerified)
except Exception as e:
print("Exception : " , e)
Integration Best Practices
Best practices to put into effect for a smooth and secure integration with Plural:
- Signature Verification to avoid data tampering: This is a mandatory step to confirm the authenticity of the details returned to you on the return URL for successful payments.
- Convert the response received on the return URL into a string (remove secret and secret_type params)
- Sort the string alphabetically
- Hash the payload with your secret key using SHA256
- Match the generated signature with the one received in the response from Plural
- Check payment status before providing services: Check if the payment status is in the success state .i.e. : ppc_Parent_TxnStatus = 4 and ppc_ParentTxnResponseCode = 1 before providing the services to the customers
- One Inquiry API call (Fetch payment using ppc_UniqueMerchantTxnID) right after the Transaction
- Run Inquiry API periodically for the payments in initiated state
- Webhook Implementation: Implement webhooks to avoid callback failures (drop offs due to connectivity/network issues)
- Payment.captured
- Payment.failed
- TLS Version We support TLS_v_1.2 and above which is strongly recommended. Kindly ensure you are using higher TLS versions to avoid any transaction failures.