### 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.