安卓应用如何从Firebase服务器生成哈希并集成PAYU支付网关?
Hey there! I’ve been in your exact situation—needing to integrate PayU without a self-hosted server, and Firebase Cloud Functions is the perfect secure solution here. Let’s break this down into actionable, easy-to-follow steps:
1. Prep Your Firebase Environment
First, make sure you have these basics covered:
- A Firebase project set up in the Firebase Console
- The Firebase CLI installed on your machine (
npm install -g firebase-tools) - Cloud Functions enabled for your project
Log into Firebase via the CLI with firebase login, then initialize Functions in your project folder using firebase init functions—pick Node.js as the runtime (it’s the most straightforward for PayU integrations).
2. Write the Hash Generation Cloud Function
PayU requires secure hashes (like payment_hash) to authenticate transactions, and these must be generated server-side (never client-side—exposing your merchant key/salt would be a massive security risk).
Here’s a tested Node.js function that generates the payment hash following PayU’s SHA-512 rules:
const functions = require("firebase-functions"); const crypto = require("crypto"); // Store your PayU merchant key and salt in Firebase Environment Variables (never hardcode!) // Set them via CLI: firebase functions:config:set payu.key="YOUR_MERCHANT_KEY" payu.salt="YOUR_MERCHANT_SALT" const PAYU_KEY = functions.config().payu.key; const PAYU_SALT = functions.config().payu.salt; exports.generatePayuPaymentHash = functions.https.onCall(async (data, context) => { // Validate incoming data to avoid missing required fields const requiredFields = ["txnid", "amount", "productinfo", "firstname", "email"]; const missingFields = requiredFields.filter(field => !data[field]); if (missingFields.length > 0) { throw new functions.https.HttpsError("invalid-argument", `Missing required fields: ${missingFields.join(", ")}`); } // PayU's payment hash format: key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5||||||salt const hashString = `${PAYU_KEY}|${data.txnid}|${data.amount}|${data.productinfo}|${data.firstname}|${data.email}|${data.udf1 || ""}|${data.udf2 || ""}|${data.udf3 || ""}|${data.udf4 || ""}|${data.udf5 || ""}||||||${PAYU_SALT}`; // Generate SHA-512 hash const paymentHash = crypto.createHash("sha512").update(hashString).digest("hex"); return { paymentHash }; });
Critical Notes:
- Never hardcode your merchant key/salt—use Firebase’s environment variables to keep these sensitive values secure.
- This uses a callable function (
onCall) which is super easy to integrate with your Android app via the Firebase SDK.
3. Call the Function from Your Android App
In your Android project, add the Firebase Functions SDK (check Firebase’s docs for the latest dependency version). Then call the function to fetch the hash right before initiating the PayU payment:
// Initialize Firebase Functions val functions = FirebaseFunctions.getInstance() // Create a map with your transaction details (generate a unique txnid for each payment!) val transactionData = hashMapOf( "txnid" to "UNIQUE_TXN_ID_123", "amount" to "299.99", "productinfo" to "Premium Subscription", "firstname" to "Jane Smith", "email" to "jane@example.com", "udf1" to "UserID_456" ) // Trigger the hash generation function functions.getHttpsCallable("generatePayuPaymentHash") .call(transactionData) .addOnSuccessListener { result -> val response = result.data as HashMap<*, *> val paymentHash = response["paymentHash"] as String // Now pass this hash to the PayU SDK along with other transaction data startPayuPayment(paymentHash, transactionData) } .addOnFailureListener { error -> // Handle errors (e.g., network issues, missing fields) Log.e("PayUHashError", "Failed to generate hash", error) }
4. Handle Payment Callback with Another Cloud Function
After the transaction, PayU will send a status callback to a public URL. Create another Cloud Function to receive this callback, verify the response hash, and update your Firebase data (like Firestore or Realtime Database) with the transaction status:
const admin = require("firebase-admin"); admin.initializeApp(); exports.payuCallbackHandler = functions.https.onRequest(async (req, res) => { if (req.method !== "POST") { return res.status(405).send("Method Not Allowed"); } const callbackData = req.body; const receivedHash = callbackData.hash; // Generate verification hash using PayU's rule: salt|status||||||udf5|udf4|udf3|udf2|udf1|email|firstname|productinfo|amount|txnid|key const verifyHashString = `${PAYU_SALT}|${callbackData.status}||||||${callbackData.udf5 || ""}|${callbackData.udf4 || ""}|${callbackData.udf3 || ""}|${callbackData.udf2 || ""}|${callbackData.udf1 || ""}|${callbackData.email}|${callbackData.firstname}|${callbackData.productinfo}|${callbackData.amount}|${callbackData.txnid}|${PAYU_KEY}`; const generatedVerifyHash = crypto.createHash("sha512").update(verifyHashString).digest("hex"); // Validate the hash to ensure the callback is legitimate if (generatedVerifyHash === receivedHash) { // Hash is valid—update transaction status in Firestore await admin.firestore().collection("transactions").doc(callbackData.txnid).set({ status: callbackData.status, amount: callbackData.amount, paymentId: callbackData.paymentId, updatedAt: admin.firestore.FieldValue.serverTimestamp() }); res.status(200).send("SUCCESS"); // Send acknowledgment to PayU } else { res.status(400).send("INVALID_HASH"); // Reject tampered callbacks } });
Deploy this function, then use its public URL (you’ll get it after deploying via the CLI) as the callbackURL parameter in your PayU transaction setup.
5. Final PayU SDK Integration
Once you have the paymentHash, pass all required parameters (including the hash) to the PayU SDK exactly like you did with your previous server setup. The only difference is now the hash comes from your Firebase Cloud Function instead of a custom server.
内容的提问来源于stack exchange,提问作者Vemuri Pavan

