# paynex (Node.js)

Zero-dependency client for Node 18+. Copy `paynex.js` (+ `paynex.d.ts` for TypeScript) into
your project or `npm install ./paynex-node`.

```js
const express = require('express');
const { Paynex } = require('./paynex');
const px = new Paynex({ baseUrl: 'https://pay.example.com', keyId: process.env.PAYNEX_KEY_ID, secret: process.env.PAYNEX_SECRET });
const app = express();

// 1. your app / website calls this; it returns the checkout URL to open
app.post('/api/pay', express.json(), async (req, res) => {
  const order = await loadOrder(req.body.orderId);
  const p = await px.createPayment({
    amount: order.total, merchant_ref: order.id, description: order.title,
    customer: { name: order.name, email: order.email, phone: order.phone },
    return_url: 'myapp://paynex/return',   // mobile deep link (register "myapp" in store → Domains)
    cancel_url: 'myapp://paynex/cancel',   // or https://… for a website
  }, `${order.id}-${order.total}`);
  res.json({ checkout_url: p.checkout_url, payment_id: p.id });
});

// 2. webhook — raw body is required for the signature
app.post('/paynex/webhook', express.raw({ type: () => true }), Paynex.webhookHandler(process.env.PAYNEX_WEBHOOK_SECRET, async (ev) => {
  if (ev.event !== 'payment.paid') return;
  const p = await px.getPayment(ev.data.id);          // source of truth
  if (p.status === 'paid') await markOrderPaid(p.merchant_ref, p.id); // idempotent by p.id
}));

// 3. the app asks "is my order paid?" after the deep link
app.get('/api/pay/:id', async (req, res) => res.json({ status: (await px.getPayment(req.params.id)).status }));
```
