### Node.js Express: Complete NETOPIA Payment Flow Source: https://context7.com/mobilpay/node.js/llms.txt An Express.js application demonstrating the full lifecycle of a payment using NETOPIA. It includes routes for initiating payments, redirecting users to the payment gateway, and asynchronously processing IPN callbacks to confirm payment status. Dependencies include express and body-parser. Assumes helper functions `getRequest` and `decodeResponse` are available. ```javascript const express = require('express'); const bodyParser = require('body-parser'); const { getRequest, decodeResponse } = require('./order'); const app = express(); app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); // Step 1: Initiate payment app.get('/payment/initiate/:orderId', (req, res) => { try { const orderId = req.params.orderId; const encrypted = getRequest(orderId); // Generate HTML form that auto-submits to NETOPIA const html = ` Processing Payment...
`; res.send(html); } catch (error) { console.error('Payment initiation failed:', error); res.status(500).json({ error: 'Payment initiation failed' }); } }); // Step 2: Handle IPN callback from NETOPIA app.post('/payment/ipn', async (req, res) => { try { const ipnData = { env_key: req.body.env_key, data: req.body.data, iv: req.body.iv || '', cipher: req.body.cipher || 'aes-256-cbc' }; const result = await decodeResponse(ipnData); const errorCode = result.order.mobilpay.error.$.code; const action = result.order.mobilpay.action; const orderId = result.order.$.id; const amount = result.order.mobilpay.amount; console.log(`IPN received for order ${orderId}: ${action}, code: ${errorCode}`); // Update order status in database based on action if (errorCode === '0') { if (action === 'confirmed') { // Payment successful - mark order as paid console.log(`Order ${orderId} confirmed with amount ${amount}`); // updateOrderStatus(orderId, 'paid'); } else if (action === 'paid_pending') { // Payment pending - wait for confirmation console.log(`Order ${orderId} payment pending`); // updateOrderStatus(orderId, 'pending'); } else if (action === 'canceled') { // Payment canceled by user console.log(`Order ${orderId} canceled`); // updateOrderStatus(orderId, 'canceled'); } } else { // Payment failed console.log(`Order ${orderId} failed with error: ${result.order.mobilpay.error._}`); // updateOrderStatus(orderId, 'failed'); } // Must respond with CRC confirmation to NETOPIA res.set('Content-Type', 'application/xml'); res.send('success'); } catch (error) { console.error('IPN processing error:', error); res.set('Content-Type', 'application/xml'); res.send('error'); } }); // Step 3: Handle user return from payment page app.get('/payment/return', async (req, res) => { // User is redirected here after completing payment on NETOPIA // Note: Don't rely on this for order confirmation - use IPN instead const html = ` Payment Processing

Thank you for your payment!

Your payment is being processed. You will receive a confirmation email shortly.

Return to homepage

`; res.send(html); }); app.listen(3000, () => { console.log('Payment server running on port 3000'); console.log('IPN endpoint: http://localhost:3000/payment/ipn'); }); ``` -------------------------------- ### Build NETOPIA Payment Data Object (JavaScript) Source: https://context7.com/mobilpay/node.js/llms.txt Constructs the payment data structure required by NETOPIA, including order details, currency, and billing/shipping information. This data is then typically converted to XML and encrypted. Returns the payment data object and the encryption algorithm. ```javascript const getPayment = (orderId, amount, currency) => { let date = new Date(); const paymentData = { order: { $: { id: orderId, timestamp: date.getTime(), type: 'card' }, signature: 'XXXX-XXXX-XXXX-XXXX-XXXX', url: { return: 'https://yoursite.com/payment/return', confirm: 'https://yoursite.com/payment/ipn' }, invoice: { $: { currency: currency, amount: amount }, details: 'Order payment for products', contact_info: { billing: { $: { type: 'person' }, first_name: 'John', last_name: 'Doe', address: '123 Main Street', email: 'john.doe@example.com', mobile_phone: '+40712345678' }, shipping: { $: { type: 'person' }, first_name: 'John', last_name: 'Doe', address: '123 Main Street', email: 'john.doe@example.com', mobile_phone: '+40712345678' } } }, ipn_cipher: 'aes-256-cbc' } }; return { data: paymentData, algorithm: 'aes-256-cbc' }; }; // Usage example const orderData = getPayment('ORDER_12345', 250.00, 'RON'); console.log('Payment data structure:', JSON.stringify(orderData, null, 2)); ``` -------------------------------- ### Encrypt Payment Data for NETOPIA with Node.js Source: https://context7.com/mobilpay/node.js/llms.txt Encrypts payment data into XML format using hybrid encryption (AES-256-CBC for data, RSA for key exchange). Requires NETOPIA's public key, payment details, and a cipher algorithm. Outputs encrypted data, initialization vector, and the encrypted symmetric key. ```javascript const crypto = require('crypto'); const { encrypt } = require('./encrypt'); const fs = require('fs'); // Load NETOPIA public key const publicKey = fs.readFileSync('./netopia_public.key').toString(); // Payment data in XML format const paymentXml = ` XXXX-XXXX-XXXX-XXXX-XXXX https://yoursite.com/payment/return https://yoursite.com/payment/confirm
Product purchase
`; // Encrypt the payment data const encrypted = encrypt(publicKey, paymentXml, 'aes-256-cbc'); console.log('Encrypted data:', { iv: encrypted.iv, // Base64 encoded initialization vector envKey: encrypted.envKey, // Base64 encoded encrypted symmetric key envData: encrypted.envData, // Base64 encoded encrypted data cipher: encrypted.cipher // Cipher algorithm used }); // Result structure: // { // iv: 'dGVzdGl2MTIzNDU2Nzg=', // envKey: 'ZW5jcnlwdGVka2V5ZXhhbXBsZQ==', // envData: 'ZW5jcnlwdGVkZGF0YWV4YW1wbGU=', // cipher: 'aes-256-cbc' // } ``` -------------------------------- ### Node.js Card Payment Request Structure Source: https://github.com/mobilpay/node.js/blob/master/README.md This JavaScript code defines the structure for a card payment request to NETOPIA Payments. It includes order details, seller signature, return and confirmation URLs, invoice information, and contact details. All fields are required except for shipping information. ```javascript const data = { order: { $: { id: orderId, timestamp: date.getTime(), type: "card", }, signature: "", url: { return: "", confirm: "", }, invoice: { $: { currency: currency, amount: amount, }, details: "test plata", contact_info: { billing: { $: { type: "person", }, first_name: "Test", last_name: "Test", address: "strada", email: "test@mobilpay.ro", mobile_phone: "mobilePhone", }, shipping: { $: { type: "person", }, first_name: "Test", last_name: "Test", address: "strada", email: "test@mobilpay.ro", mobile_phone: "mobilePhone", }, }, }, ipn_cipher: "aes-256-cbc", }, }; ``` -------------------------------- ### Card Payment Request Source: https://github.com/mobilpay/node.js/blob/master/README.md This endpoint handles card payment requests for NETOPIA integration. It requires a POST request with encrypted payment data. ```APIDOC ## POST / ### Description This endpoint is used to initiate a card payment request to the NETOPIA Payments gateway. All requests must be sent via HTTP POST and include encrypted payment data. ### Method POST ### Endpoint - Live: https://secure.mobilpay.ro - Sandbox: https://sandboxsecure.mobilpay.ro ### Parameters #### Request Body - **order** (object) - Required - The main object containing all payment details. - **$** (object) - Required - Core order attributes. - **id** (string) - Required - Unique identifier for the order. - **timestamp** (number) - Required - Timestamp of the order creation. - **type** (string) - Required - Type of payment, e.g., "card". - **signature** (string) - Required - Your NETOPIA seller account signature. - **url** (object) - Required - URLs for confirmation and return. - **return** (string) - Required - The URL to redirect the user back to after payment. - **confirm** (string) - Required - The URL for Instant Payment Notifications (IPN) about transaction status. - **invoice** (object) - Required - Invoice details. - **$** (object) - Required - Invoice monetary details. - **currency** (string) - Required - Currency code (e.g., "RON"). - **amount** (number) - Required - The payment amount. - **details** (string) - Required - Description of the invoice. - **contact_info** (object) - Required - Contact information for billing and shipping. - **billing** (object) - Required - Billing contact details. - **$** (object) - Required - Billing contact type attributes. - **type** (string) - Required - Type of contact, e.g., "person". - **first_name** (string) - Required - First name of the billing contact. - **last_name** (string) - Required - Last name of the billing contact. - **address** (string) - Required - Billing address. - **email** (string) - Required - Billing email address. - **mobile_phone** (string) - Required - Billing mobile phone number. - **shipping** (object) - Optional - Shipping contact details. If not provided, billing details are used. - **$** (object) - Required - Shipping contact type attributes. - **type** (string) - Required - Type of contact, e.g., "person". - **first_name** (string) - Required - First name of the shipping contact. - **last_name** (string) - Required - Last name of the shipping contact. - **address** (string) - Required - Shipping address. - **email** (string) - Required - Shipping email address. - **mobile_phone** (string) - Required - Shipping mobile phone number. - **ipn_cipher** (string) - Required - The encryption cipher used for IPN, e.g., "aes-256-cbc". ### Request Example ```json { "order": { "$": { "id": "orderId", "timestamp": 1678886400000, "type": "card" }, "signature": "", "url": { "return": "", "confirm": "" }, "invoice": { "$": { "currency": "RON", "amount": "100.50" }, "details": "test plata", "contact_info": { "billing": { "$": { "type": "person" }, "first_name": "Test", "last_name": "Test", "address": "strada", "email": "test@mobilpay.ro", "mobile_phone": "mobilePhone" }, "shipping": { "$": { "type": "person" }, "first_name": "Test", "last_name": "Test", "address": "strada", "email": "test@mobilpay.ro", "mobile_phone": "mobilePhone" } } }, "ipn_cipher": "aes-256-cbc" } } ``` ### Response #### Success Response (200) - **redirect_url** (string) - The URL to redirect the user to for payment processing. #### Response Example ```json { "redirect_url": "https://secure.mobilpay.ro/redirect/payment?token=..." } ``` ``` -------------------------------- ### Generate NETOPIA Payment Request (JavaScript) Source: https://context7.com/mobilpay/node.js/llms.txt Generates a complete payment request including order details and customer information. It encrypts the data and returns an HTML form ready to be posted to NETOPIA's payment gateway. Requires a local 'order' module with a 'getRequest' function. ```javascript const { getRequest } = require('./order'); // Generate payment request for order const orderId = 'ORDER_' + Date.now(); try { const paymentRequest = getRequest(orderId); console.log('Payment request generated:', { orderId: orderId, encryptedData: paymentRequest }); // Post to NETOPIA payment gateway const formHtml = `
`; console.log('Payment form HTML:', formHtml); // Expected output structure: // { // iv: 'randomBase64IV==', // envKey: 'encryptedSymmetricKey==', // envData: 'encryptedPaymentData==', // cipher: 'aes-256-cbc' // } } catch (error) { console.error('Payment request generation failed:', error.message); } ``` -------------------------------- ### Decode NETOPIA IPN Response (JavaScript) Source: https://context7.com/mobilpay/node.js/llms.txt Parses and decrypts the Instant Payment Notification (IPN) callback data received from NETOPIA. It returns a promise that resolves with the payment status, error codes, and other relevant order details. Requires a local 'order' module with a 'decodeResponse' function. ```javascript const { decodeResponse } = require('./order'); // Example IPN POST data received from NETOPIA const ipnCallback = { env_key: 'ZW5jcnlwdGVkU3ltbWV0cmljS2V5RXhhbXBsZQ==', data: 'ZW5jcnlwdGVkUGF5bWVudFJlc3BvbnNlRGF0YQ==', iv: 'cmFuZG9tSW5pdGlhbGl6YXRpb25WZWN0b3I=', cipher: 'aes-256-cbc' }; decodeResponse(ipnCallback) .then(result => { console.log('Payment status:', result.order.mobilpay.action); console.log('Error code:', result.order.mobilpay.error.$.code); console.log('Error message:', result.order.mobilpay.error._); console.log('Amount:', result.order.mobilpay.amount); console.log('Order ID:', result.order.$.id); // Example successful payment response: // { // order: { // $: { id: 'ORDER_12345', timestamp: '1699876543210', type: 'card' }, // mobilpay: { // action: 'confirmed', // error: { $: { code: '0' }, _: 'Approved' }, // amount: '250.00', // customer_info: { // card_number: 'XXXX-XXXX-XXXX-1234' // } // } // } // } // Send response back to NETOPIA if (result.order.mobilpay.error.$.code === '0') { console.log('Payment successful - update order status'); return { statusCode: 200, body: 'success' }; } else { console.log('Payment failed - handle error'); return { statusCode: 200, body: 'error' }; } }) .catch(error => { console.error('Failed to decode IPN response:', error.message); return { statusCode: 500, body: 'error' }; }); ``` -------------------------------- ### Decrypt NETOPIA Payment Response with Node.js Source: https://context7.com/mobilpay/node.js/llms.txt Decrypts Instant Payment Notification (IPN) responses from NETOPIA. It uses the merchant's private key to decrypt the symmetric key and then decrypts the payment data. Requires the merchant's private key and the encrypted IPN data. ```javascript const { decrypt } = require('./encrypt'); const fs = require('fs'); // Load merchant's private key const privateKey = fs.readFileSync('./merchant_private.key').toString(); // Example IPN data received from NETOPIA const ipnData = { iv: 'dGVzdGl2MTIzNDU2Nzg=', envKey: 'ZW5jcnlwdGVka2V5ZXhhbXBsZQ==', data: 'ZW5jcnlwdGVkZGF0YWV4YW1wbGU=', cipher: 'aes-256-cbc' }; try { // Decrypt the response const decryptedXml = decrypt( privateKey, ipnData.iv, ipnData.envKey, ipnData.data, ipnData.cipher ); console.log('Decrypted payment response:', decryptedXml); // Expected XML format: // // // // confirmed // Approved // 100.50 // // XXXX-XXXX-XXXX-1234 // // // } catch (error) { console.error('Decryption failed:', error.message); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.