{"_id":"@dalli/chargily-pay","_rev":"3-187ceb8b7828ad2b66e6781ebf8a4812","name":"@dalli/chargily-pay","dist-tags":{"latest":"3.1.1"},"versions":{"3.0.0":{"name":"@dalli/chargily-pay","version":"3.0.0","keywords":["chargily","payment","gateway","e-payment","algeria","edahabia","cib","javascript","typescript"],"author":{"url":"https://github.com/rofazayn","name":"Abderraouf Zine","email":"rofazayn@gmail.com"},"license":"MIT","_id":"@dalli/chargily-pay@3.0.0","maintainers":[{"name":"dalli","email":"aiceberg.gc@gmail.com"}],"homepage":"https://github.com/ramdaniAli/chargily-pay-javascript#readme","bugs":{"url":"https://github.com/ramdaniAli/chargily-pay-javascript/issues"},"dist":{"shasum":"02eb9893a3dae91a5f29ba5dc91c0e6a06da94a5","tarball":"https://registry.npmjs.org/@dalli/chargily-pay/-/chargily-pay-3.0.0.tgz","fileCount":30,"integrity":"sha512-dt/VJbCHjpga1idxeUOnwjH9+MQyE0rJzzikCZjKQqSJgwPiUUTK+lc1OzDQ8+hHuV/AFPN7QcJM8GdDMIaLuA==","signatures":[{"sig":"MEUCIQCj19dDphS7887PnDk5OA4NVC/jzcDt5FMfsmygaeWHuAIgYlEmI71/NMxJv3xbMql9ooP58RqR8yf7KypC5M85eC0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":82015},"main":"lib/index.js","types":"lib/index.d.ts","engines":{"node":">=18.0.0"},"gitHead":"8bbef194432bae8f60aca56074730b1bf7a7691f","scripts":{"dev":"nodemon --exec ts-node ./src/index.ts","lint":"eslint src/ tests/","test":"vitest run","build":"tsc","format":"prettier --write 'src/**/*.ts' 'tests/**/*.ts'","lint:fix":"eslint src/ tests/ --fix","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"dalli","email":"aiceberg.gc@gmail.com"},"repository":{"url":"git+https://github.com/ramdaniAli/chargily-pay-javascript.git","type":"git"},"_npmVersion":"11.6.2","description":"JavaScript Library for Chargily Pay™ Gateway - V2. The easiest and free way to integrate e-payment API through EDAHABIA of Algerie Poste and CIB of SATIM into your JS project.","directories":{},"_nodeVersion":"24.11.0","_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.0.3","vitest":"^4.0.18","nodemon":"^3.1.0","ts-node":"^10.9.2","prettier":"^3.8.1","typescript":"^4.9.5","@types/node":"^18.0.0","eslint-config-prettier":"^10.1.8","@typescript-eslint/parser":"^8.56.1","@typescript-eslint/eslint-plugin":"^8.56.1"},"_npmOperationalInternal":{"tmp":"tmp/chargily-pay_3.0.0_1773025515405_0.9555668842431926","host":"s3://npm-registry-packages-npm-production"}},"3.1.0":{"name":"@dalli/chargily-pay","version":"3.1.0","keywords":["chargily","payment","gateway","e-payment","algeria","edahabia","cib","javascript","typescript"],"author":{"url":"https://github.com/rofazayn","name":"Abderraouf Zine","email":"rofazayn@gmail.com"},"license":"MIT","_id":"@dalli/chargily-pay@3.1.0","maintainers":[{"name":"dalli","email":"aiceberg.gc@gmail.com"}],"homepage":"https://github.com/ramdaniAli/chargily-pay-javascript#readme","bugs":{"url":"https://github.com/ramdaniAli/chargily-pay-javascript/issues"},"dist":{"shasum":"330ed68eac96507bcd67e9194c19fa202f2fa67d","tarball":"https://registry.npmjs.org/@dalli/chargily-pay/-/chargily-pay-3.1.0.tgz","fileCount":39,"integrity":"sha512-f96NDwLLu5LsFVxDsnu6Z7HmdFvZ6PPfMm9melUfQRdHElhpACwddqMp4CMRvOyeQFYU7bD3Iar8j9bP5c1+fw==","signatures":[{"sig":"MEQCIDLjG1+MrJPJTVVfDcU4ZLcU+4X0msHRDf4k6yQM4XHZAiAcUnE3qE/wXJxuF7+asAp2jp7jNe1L7Nv5A+Ko9LEq3Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":86042},"main":"lib/index.js","types":"lib/index.d.ts","engines":{"node":">=18.0.0"},"gitHead":"8c240d77a036165fc444a1ef1861eeda12d0d1c9","scripts":{"dev":"nodemon --exec ts-node ./src/index.ts","lint":"eslint src/ tests/","test":"vitest run","build":"tsc","format":"prettier --write 'src/**/*.ts' 'tests/**/*.ts'","lint:fix":"eslint src/ tests/ --fix","typecheck":"tsc --noEmit","test:watch":"vitest"},"_npmUser":{"name":"dalli","email":"aiceberg.gc@gmail.com"},"repository":{"url":"git+https://github.com/ramdaniAli/chargily-pay-javascript.git","type":"git"},"_npmVersion":"11.6.2","description":"JavaScript Library for Chargily Pay™ Gateway - V2. The easiest and free way to integrate e-payment API through EDAHABIA of Algerie Poste and CIB of SATIM into your JS project.","directories":{},"_nodeVersion":"24.11.0","_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.0.3","vitest":"^4.0.18","nodemon":"^3.1.0","ts-node":"^10.9.2","prettier":"^3.8.1","typescript":"^4.9.5","@types/node":"^18.0.0","eslint-config-prettier":"^10.1.8","@typescript-eslint/parser":"^8.56.1","@typescript-eslint/eslint-plugin":"^8.56.1"},"_npmOperationalInternal":{"tmp":"tmp/chargily-pay_3.1.0_1773025950977_0.9961751351180057","host":"s3://npm-registry-packages-npm-production"}},"3.1.1":{"name":"@dalli/chargily-pay","version":"3.1.1","description":"JavaScript Library for Chargily Pay™ Gateway - V2. The easiest and free way to integrate e-payment API through EDAHABIA of Algerie Poste and CIB of SATIM into your JS project.","main":"lib/index.js","types":"lib/index.d.ts","engines":{"node":">=18.0.0"},"scripts":{"dev":"nodemon --exec ts-node ./src/index.ts","build":"tsc","test":"vitest run","test:watch":"vitest","lint":"eslint src/ tests/","lint:fix":"eslint src/ tests/ --fix","format":"prettier --write 'src/**/*.ts' 'tests/**/*.ts'","typecheck":"tsc --noEmit"},"repository":{"type":"git","url":"git+https://github.com/ramdaniAli/chargily-pay-javascript.git"},"keywords":["chargily","payment","gateway","e-payment","algeria","edahabia","cib","javascript","typescript"],"author":{"name":"Abderraouf Zine","email":"rofazayn@gmail.com","url":"https://github.com/rofazayn"},"license":"MIT","bugs":{"url":"https://github.com/ramdaniAli/chargily-pay-javascript/issues"},"homepage":"https://github.com/ramdaniAli/chargily-pay-javascript#readme","devDependencies":{"@types/node":"^22.0.0","@typescript-eslint/eslint-plugin":"^8.56.1","@typescript-eslint/parser":"^8.56.1","eslint":"^9.39.4","eslint-config-prettier":"^10.1.8","nodemon":"^3.1.0","prettier":"^3.8.1","ts-node":"^10.9.2","typescript":"^4.9.5","vitest":"^2.1.9"},"gitHead":"f4083a6db69d3a3c61feb91e7f2d27a26a223ebd","_id":"@dalli/chargily-pay@3.1.1","_nodeVersion":"24.11.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-UuBdz64ABKIUWl/FKOH6JNSVbTCpQUm7YiE8a/2YvROU0ghNytZTS+rr1RBGHWgZw7k8Q4TN8MHQOOVrz7ukoQ==","shasum":"b8f0e76a43a437defa7f2dd4521a5c75903fbdbd","tarball":"https://registry.npmjs.org/@dalli/chargily-pay/-/chargily-pay-3.1.1.tgz","fileCount":39,"unpackedSize":86365,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIGtX7r8BPCAFihu/9XpwJRJhAMUquAbBZkoKUfWo1xGEAiAxyxk3esWTfJxbAPZcPa7Ai5SsUYL50nAnXvcj1aom5g=="}]},"_npmUser":{"name":"dalli","email":"aiceberg.gc@gmail.com"},"directories":{},"maintainers":[{"name":"dalli","email":"aiceberg.gc@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/chargily-pay_3.1.1_1773027013261_0.27922305893911226"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-09T03:05:15.315Z","modified":"2026-03-09T03:30:15.429Z","3.0.0":"2026-03-09T03:05:15.551Z","3.1.0":"2026-03-09T03:12:31.202Z","3.1.1":"2026-03-09T03:30:15.217Z"},"bugs":{"url":"https://github.com/ramdaniAli/chargily-pay-javascript/issues"},"author":{"name":"Abderraouf Zine","email":"rofazayn@gmail.com","url":"https://github.com/rofazayn"},"license":"MIT","homepage":"https://github.com/ramdaniAli/chargily-pay-javascript#readme","keywords":["chargily","payment","gateway","e-payment","algeria","edahabia","cib","javascript","typescript"],"repository":{"type":"git","url":"git+https://github.com/ramdaniAli/chargily-pay-javascript.git"},"description":"JavaScript Library for Chargily Pay™ Gateway - V2. The easiest and free way to integrate e-payment API through EDAHABIA of Algerie Poste and CIB of SATIM into your JS project.","maintainers":[{"name":"dalli","email":"aiceberg.gc@gmail.com"}],"readme":"# @dalli/chargily-pay\r\n\r\nA robust, production-ready JavaScript/TypeScript SDK for the [Chargily Pay](https://chargily.com/business/pay)™ Gateway V2.\r\n\r\nIntegrate EDAHABIA (Algerie Poste) and CIB (SATIM) payments into your Node.js applications.\r\n\r\n> **Fork of [@chargily/chargily-pay](https://github.com/chargily/chargily-pay-javascript)** with critical bug fixes, resilience features, and developer experience improvements.\r\n\r\n## Features\r\n\r\n- Full TypeScript support with strict types\r\n- Retry with exponential backoff on 429/5xx errors\r\n- Configurable request timeout with AbortController\r\n- Built-in rate limiter (token bucket)\r\n- Idempotency key support for safe retries\r\n- Typed webhook events with signature verification\r\n- Framework-agnostic webhook handler (`parseWebhookEvent`)\r\n- Optional logger interface (compatible with console, winston, pino)\r\n- Pagination support with validation\r\n- Proper error hierarchy (`ChargilyApiError`, `ChargilyNetworkError`)\r\n\r\n## Installation\r\n\r\n```bash\r\nnpm install @dalli/chargily-pay\r\n```\r\n\r\n**Requires Node.js >= 18** (uses native `fetch`).\r\n\r\n## Quick Start\r\n\r\n```ts\r\nimport { ChargilyClient } from '@dalli/chargily-pay';\r\n\r\nconst client = new ChargilyClient({\r\n  api_key: 'YOUR_API_SECRET_KEY',\r\n  mode: 'test', // 'test' or 'live'\r\n});\r\n\r\n// Create a checkout\r\nconst checkout = await client.createCheckout({\r\n  amount: 5000,\r\n  currency: 'dzd',\r\n  success_url: 'https://example.com/success',\r\n});\r\n\r\nconsole.log(checkout.checkout_url); // Redirect your customer here\r\n```\r\n\r\n## Configuration\r\n\r\n```ts\r\nconst client = new ChargilyClient({\r\n  api_key: 'YOUR_API_SECRET_KEY',\r\n  mode: 'test',\r\n\r\n  // Resilience\r\n  timeout: 30000,            // Request timeout in ms (default: 30000)\r\n  maxRetries: 2,             // Retries on 429/5xx (default: 2)\r\n  retryDelay: 1000,          // Base delay for exponential backoff (default: 1000)\r\n\r\n  // Rate limiting\r\n  maxRequestsPerSecond: 5,   // Token bucket rate limit (default: 5, 0 to disable)\r\n\r\n  // Logging\r\n  logger: console,           // Any object with debug/info/warn/error methods\r\n});\r\n```\r\n\r\n## API Reference\r\n\r\n### Customers\r\n\r\n```ts\r\nconst customer = await client.createCustomer({ name: 'Ali', email: 'ali@example.com' });\r\nconst fetched  = await client.getCustomer('customer_id');\r\nconst updated  = await client.updateCustomer('customer_id', { name: 'Ali R.' });\r\nconst deleted  = await client.deleteCustomer('customer_id');\r\nconst list     = await client.listCustomers({ per_page: 20, page: 1 });\r\n```\r\n\r\n### Products\r\n\r\n```ts\r\nconst product = await client.createProduct({ name: 'T-Shirt' });\r\nconst fetched = await client.getProduct('product_id');\r\nconst updated = await client.updateProduct('product_id', { name: 'Premium T-Shirt' });\r\nconst deleted = await client.deleteProduct('product_id');\r\nconst list    = await client.listProducts({ per_page: 10 });\r\n```\r\n\r\n### Prices\r\n\r\n```ts\r\nconst price  = await client.createPrice({ amount: 2500, currency: 'dzd', product_id: 'product_id' });\r\nconst fetched = await client.getPrice('price_id');\r\nconst updated = await client.updatePrice('price_id', { metadata: { size: 'L' } });\r\nconst list    = await client.listPrices({ per_page: 10 });\r\nconst prices  = await client.getProductPrices('product_id');\r\n```\r\n\r\n### Checkouts\r\n\r\n```ts\r\n// With items\r\nconst checkout = await client.createCheckout({\r\n  items: [{ price: 'price_id', quantity: 2 }],\r\n  success_url: 'https://example.com/success',\r\n  failure_url: 'https://example.com/failure',\r\n  webhook_endpoint: 'https://example.com/webhook',\r\n  locale: 'fr',\r\n});\r\n\r\n// With direct amount\r\nconst checkout2 = await client.createCheckout({\r\n  amount: 5000,\r\n  currency: 'dzd',\r\n  success_url: 'https://example.com/success',\r\n});\r\n\r\nconst details = await client.getCheckout('checkout_id');\r\nconst items   = await client.getCheckoutItems('checkout_id');\r\nconst expired = await client.expireCheckout('checkout_id');\r\nconst list    = await client.listCheckouts({ per_page: 10 });\r\n```\r\n\r\n### Payment Links\r\n\r\n```ts\r\nconst link    = await client.createPaymentLink({\r\n  name: 'Summer Sale',\r\n  items: [{ price: 'price_id', quantity: 1, adjustable_quantity: true }],\r\n});\r\nconst fetched = await client.getPaymentLink('link_id');\r\nconst updated = await client.updatePaymentLink('link_id', { name: 'Winter Sale' });\r\nconst items   = await client.getPaymentLinkItems('link_id');\r\nconst list    = await client.listPaymentLinks();\r\n```\r\n\r\n### Balance\r\n\r\n```ts\r\nconst balance = await client.getBalance();\r\nconsole.log(balance.wallets); // [{ currency: 'dzd', balance: 50000, ... }]\r\n```\r\n\r\n### Idempotency\r\n\r\nAll mutation methods accept an optional `RequestOptions` parameter to prevent duplicate operations:\r\n\r\n```ts\r\nconst customer = await client.createCustomer(\r\n  { name: 'Ali' },\r\n  { idempotencyKey: 'unique-request-id-123' }\r\n);\r\n```\r\n\r\n## Webhooks\r\n\r\n### Quick Setup (Recommended)\r\n\r\nUse `parseWebhookEvent` for one-call verify + parse:\r\n\r\n```ts\r\nimport express from 'express';\r\nimport { parseWebhookEvent, isCheckoutPaid } from '@dalli/chargily-pay';\r\n\r\nconst app = express();\r\nconst SECRET = 'YOUR_API_SECRET_KEY';\r\n\r\napp.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {\r\n  try {\r\n    const event = parseWebhookEvent(req.body, req.headers['signature'] as string, SECRET);\r\n\r\n    if (isCheckoutPaid(event)) {\r\n      console.log('Payment received!', event.data.id);\r\n      // Handle successful payment\r\n    }\r\n\r\n    res.sendStatus(200);\r\n  } catch (err) {\r\n    console.error('Webhook error:', err);\r\n    res.sendStatus(400);\r\n  }\r\n});\r\n\r\napp.listen(4000);\r\n```\r\n\r\n### Manual Verification\r\n\r\nFor more control, use `verifySignature` directly:\r\n\r\n```ts\r\nimport { verifySignature } from '@dalli/chargily-pay';\r\n\r\nconst isValid = verifySignature(rawBodyBuffer, signatureHeader, secretKey);\r\n```\r\n\r\n### Webhook Event Types\r\n\r\n```ts\r\nimport {\r\n  WebhookEvent,\r\n  CheckoutWebhookEvent,\r\n  isCheckoutPaid,\r\n  isCheckoutFailed,\r\n} from '@dalli/chargily-pay';\r\n\r\n// Type guards narrow the event type\r\nif (isCheckoutPaid(event)) {\r\n  // event.data is typed as Checkout\r\n  console.log(event.data.amount);\r\n}\r\n```\r\n\r\nAvailable event types: `checkout.paid`, `checkout.failed`, `checkout.expired`, `checkout.canceled`, `checkout.processing`, `checkout.pending`.\r\n\r\n## Error Handling\r\n\r\nThe SDK throws typed errors:\r\n\r\n```ts\r\nimport { ChargilyApiError, ChargilyNetworkError } from '@dalli/chargily-pay';\r\n\r\ntry {\r\n  await client.createCustomer({ name: '' });\r\n} catch (error) {\r\n  if (error instanceof ChargilyApiError) {\r\n    // API returned an error (4xx/5xx)\r\n    console.log(error.status);     // 422\r\n    console.log(error.statusText); // 'Unprocessable Entity'\r\n    console.log(error.body);       // { message: '...', errors: { ... } }\r\n  } else if (error instanceof ChargilyNetworkError) {\r\n    // Network/timeout error\r\n    console.log(error.message);    // 'Request timed out'\r\n    console.log(error.cause);      // Original error\r\n  }\r\n}\r\n```\r\n\r\n## Pagination\r\n\r\nAll list methods support pagination:\r\n\r\n```ts\r\nconst page = await client.listCustomers({ per_page: 20, page: 2 });\r\n\r\nconsole.log(page.data);          // Customer[]\r\nconsole.log(page.current_page);  // 2\r\nconsole.log(page.last_page);     // 5\r\n```\r\n\r\n`per_page` is clamped to 1-50, `page` minimum is 1.\r\n\r\n## Logging\r\n\r\nPass any logger with `debug`, `info`, `warn`, `error` methods:\r\n\r\n```ts\r\n// Use console\r\nconst client = new ChargilyClient({ ..., logger: console });\r\n\r\n// Use winston\r\nimport winston from 'winston';\r\nconst logger = winston.createLogger({ /* ... */ });\r\nconst client = new ChargilyClient({ ..., logger });\r\n\r\n// Use pino\r\nimport pino from 'pino';\r\nconst client = new ChargilyClient({ ..., logger: pino() });\r\n```\r\n\r\nThe SDK logs:\r\n- `debug`: Every request (`GET balance`, `POST customers`)\r\n- `warn`: Retry attempts with delay info\r\n- `error`: API errors with status and body\r\n\r\n## What's Different from @chargily/chargily-pay\r\n\r\n| Issue | Original | This Fork |\r\n|-------|----------|-----------|\r\n| Update methods use POST | POST | PATCH (correct) |\r\n| URL validation | None (accepts `httpmalicious`) | `new URL()` with protocol check |\r\n| `verifySignature` throws | Throws on invalid | Returns `false` |\r\n| Error handling | Generic errors | `ChargilyApiError` / `ChargilyNetworkError` |\r\n| Timeouts | None | AbortController with configurable timeout |\r\n| Retries | None | Exponential backoff on 429/5xx |\r\n| Rate limiting | None | Token bucket (5 req/s default) |\r\n| Pagination | `per_page` only | `per_page` + `page` with validation |\r\n| Webhook DX | Manual verify + parse | `parseWebhookEvent` one-liner |\r\n| TypeScript types | Several incorrect | All fixed and strict |\r\n| Logging | None | Pluggable logger interface |\r\n| Idempotency | None | `RequestOptions` with idempotency key |\r\n| Tests | None | 51 tests with Vitest |\r\n| CI | None | GitHub Actions (Node 18/20/22) |\r\n| Linting | None | ESLint + Prettier |\r\n\r\n## API Documentation\r\n\r\nSee the full Chargily Pay V2 API docs: [dev.chargily.com/pay-v2](https://dev.chargily.com/pay-v2/introduction)\r\n\r\n## Contributing\r\n\r\nWe welcome contributions! See [CONTRIBUTING.md](CONTRIBUTING.md) for setup instructions, coding standards, and workflow guidelines.\r\n\r\nPlease read our [Code of Conduct](CODE_OF_CONDUCT.md) before participating.\r\n\r\n## Changelog\r\n\r\nSee [CHANGELOG.md](CHANGELOG.md) for a detailed history of all changes.\r\n\r\n## License\r\n\r\nMIT\r\n","readmeFilename":"README.md"}