UNPKG

quick-phonepe

Version:

easy to use phonepe sdk for payment integration

144 lines (125 loc) 5.05 kB
const axios = require('axios'); const crypto = require('crypto'); /** * @typedef {Object} PaymentInstrument * @property {string} type - The type of the payment instrument, e.g., 'PAY_PAGE'. */ /** * @typedef {Object} TransactionData * @property {string} merchantTransactionId - The transaction ID for the merchant. * @property {string} merchantUserId - The user ID for the merchant. * @property {string} name - The name of the user. * @property {number} amount - The transaction amount in paisa (1 INR = 100 paisa). * @property {string} redirectUrl - The URL to redirect after the transaction. * @property {string} redirectMode - The redirect mode, e.g., 'POST'. * @property {string} mobileNumber - The mobile number of the user. * @property {PaymentInstrument} paymentInstrument - The payment instrument details. */ /** * QuickPhonePe class to interact with PhonePe payment gateway. */ class QuickPhonePe { /** * Constructor to initialize the QuickPhonePe instance. * @param {Object} config - The configuration object. * @param {string} config.merchantId - The Merchant ID provided by PhonePe. * @param {string} config.saltKey - The Salt Key provided by PhonePe for hashing. * @param {number} [config.keyIndex=1] - The Key Index for the salt key, default is 1. * @param {("DEV"|"PROD")} [config.mode="DEV"] - The mode of the API, either 'DEV' for sandbox or 'PROD' for production. */ constructor({ merchantId, saltKey, keyIndex = 1, mode = "DEV" }) { this.merchantId = merchantId; this.saltKey = saltKey; this.keyIndex = keyIndex; this.mode = mode; } /** * Get the appropriate URL for the payment link based on the mode. * @returns {string} The URL for the payment link. */ _getPayLink() { const urls = { DEV: "https://api-preprod.phonepe.com/apis/pg-sandbox/pg/v1", PROD: "https://api.phonepe.com/apis/hermes/pg/v1" }; return urls[this.mode.toUpperCase()]; } /** * Generate checksum for the request. * @param {string} payload - The payload to be hashed. * @param {string} endpoint - The endpoint for which the checksum is generated. * @returns {string} The generated checksum. */ _generateChecksum(payload, endpoint) { const stringToHash = `${payload}${endpoint}${this.saltKey}`; const sha256 = crypto.createHash("sha256").update(stringToHash).digest("hex"); return `${sha256}###${this.keyIndex}`; } /** * @param {string} merchantTransactionId */ _generateCheckVerifySum(merchantTransactionId) { const string = `/pg/v1/status/${this.merchantId}/${merchantTransactionId}` + this.saltKey const sha256 = crypto.createHash("sha256").update(string).digest("hex"); const checksum = sha256 + "###" + this.keyIndex; return checksum; } /** * Create a transaction using PhonePe payment gateway. * @param {TransactionData} data - The transaction data. * @returns {Promise<Object>} The response from PhonePe API. * @throws Will throw an error if the request fails. */ async createTransaction(data) { const payload = JSON.stringify({ ...data, merchantId: this.merchantId }); const payloadBase64 = Buffer.from(payload).toString("base64"); const checksum = this._generateChecksum(payloadBase64, "/pg/v1/pay"); const options = { method: "POST", url: `${this._getPayLink()}/pay`, headers: { accept: "application/json", "Content-Type": "application/json", "X-VERIFY": checksum, }, data: { request: payloadBase64, }, }; try { const response = await axios.request(options); return response.data; } catch (error) { throw error; } } /** * Verify the status of a transaction. * @param {string} merchantTransactionId - The transaction ID to verify. * @returns {Promise<Object>} The response from PhonePe API. * @throws Will throw an error if the request fails. */ async verifyTransaction(merchantTransactionId) { const endpoint = `/pg/v1/status/${this.merchantId}/${merchantTransactionId}`; const checksum = this._generateCheckVerifySum(merchantTransactionId); const options = { method: "GET", url: `${this._getPayLink()}${endpoint}`, headers: { accept: "application/json", "Content-Type": "application/json", "X-VERIFY": checksum, "X-MERCHANT-ID": this.merchantId, }, }; try { const response = await axios.request(options); return response.data; } catch (error) { throw error; } } } // Export the QuickPhonePe class module.exports = QuickPhonePe;