{"_id":"@abdssamie/adyen-payments","_rev":"2-d752fb7dafa2072d8096e60e372b7c0d","name":"@abdssamie/adyen-payments","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@abdssamie/adyen-payments","version":"0.1.0","keywords":["convex","component"],"license":"Apache-2.0","_id":"@abdssamie/adyen-payments@0.1.0","maintainers":[{"name":"abdessamie","email":"abdessamie.elmoubarki@gmail.com"}],"homepage":"https://github.com/Abdssamie/adyen-payments#readme","bugs":{"url":"https://github.com/Abdssamie/adyen-payments/issues"},"dist":{"shasum":"0294cafe42897fc99b6b941a74bca1f2b5aa43ce","tarball":"https://registry.npmjs.org/@abdssamie/adyen-payments/-/adyen-payments-0.1.0.tgz","fileCount":69,"integrity":"sha512-LcJCE4d9RGbgCi829pipJA6YTAOGfgMT+o8y9gHHxR465nhbSA8aOPbXbITIT7eQ33vheZDkP5AvI9CKBYfEhg==","signatures":[{"sig":"MEUCIFy8YG67vyfcm4Gb/WKUsDBgfwByG3++pImUW4JvjYUTAiEAi4RUd0VgrYxxmU3HydqFAs54y01dpKsLZ/7Nwy0Hg98=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":280439},"type":"module","types":"./dist/client/index.d.ts","module":"./dist/client/index.js","exports":{".":{"types":"./dist/client/index.d.ts","default":"./dist/client/index.js"},"./test":"./src/test.ts","./react":{"types":"./dist/react/index.d.ts","default":"./dist/react/index.js"},"./package.json":"./package.json","./convex.config":{"types":"./dist/component/convex.config.d.ts","default":"./dist/component/convex.config.js"},"./convex.config.js":{"types":"./dist/component/convex.config.d.ts","default":"./dist/component/convex.config.js"},"./_generated/component":{"types":"./dist/component/_generated/component.d.ts"},"./_generated/component.js":{"types":"./dist/component/_generated/component.d.ts"}},"gitHead":"930865bd77c19f07629bbfd4cb6c94ce6b7ed193","scripts":{"dev":"convex dev --start 'npm run dev:build'","lint":"eslint .","test":"vitest run --typecheck","alpha":"npm version prerelease --preid alpha && npm publish --tag alpha && git push --follow-tags","build":"tsc --project ./tsconfig.build.json","predev":"convex init && npm run build:codegen","release":"npm version patch && npm publish && git push --follow-tags","version":"(npm whoami || npm login) && vim -c 'normal o' -c 'normal o## '$npm_package_version CHANGELOG.md && prettier -w CHANGELOG.md && git add CHANGELOG.md","dev:build":"chokidar 'tsconfig*.json' 'src/**/*.ts' -i '**/*.test.ts' -c 'npm run build:codegen' --initial","typecheck":"tsc --noEmit && tsc -p example && tsc -p example/convex","preversion":"npm ci && npm run build:clean && npm run test && npm run lint && npm run typecheck","test:debug":"vitest --inspect-brk --no-file-parallelism","test:watch":"vitest --typecheck --clearScreen false","build:clean":"rm -rf dist *.tsbuildinfo && npm run build:codegen","dev:frontend":"cd example && vite","build:codegen":"npx convex codegen --component-dir ./src/component && npm run build","test:coverage":"vitest run --coverage --coverage.reporter=text"},"_npmUser":{"name":"abdessamie","email":"abdessamie.elmoubarki@gmail.com"},"repository":{"url":"git+https://github.com/Abdssamie/adyen-payments.git","type":"git"},"_npmVersion":"11.13.0","description":"A adyen payments component for Convex.","directories":{},"_nodeVersion":"26.2.0","dependencies":{"better-auth":"^1.6.20","@adyen/adyen-web":"^6.39.0","@adyen/api-library":"^22.0.0","@convex-dev/better-auth":"^0.12.4"},"_hasShrinkwrap":false,"devDependencies":{"vite":"8.0.9","react":"^19.2.5","convex":"^1.41.0","eslint":"9.39.4","vitest":"4.1.4","globals":"^17.5.0","prettier":"3.8.3","react-dom":"^19.2.5","@eslint/js":"9.39.4","pkg-pr-new":"^0.0.66","typescript":"6.0.3","@types/node":"^24.12.2","convex-test":"0.0.49","@types/react":"^19.2.14","chokidar-cli":"3.0.0","@edge-runtime/vm":"^5.0.0","@eslint/eslintrc":"^3.3.5","@types/react-dom":"^19.2.3","typescript-eslint":"8.58.2","eslint-plugin-react":"^7.37.5","@vitejs/plugin-react":"^6.0.2","@convex-dev/eslint-plugin":"^2.0.0","eslint-plugin-react-hooks":"^7.1.1","@typescript/native-preview":"7.0.0-dev.20260614.1","eslint-plugin-react-refresh":"^0.5.2"},"peerDependencies":{"react":"^18.3.1 || ^19.0.0","convex":"^1.36.1"},"_npmOperationalInternal":{"tmp":"tmp/adyen-payments_0.1.0_1782400268226_0.363366306501659","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@abdssamie/adyen-payments","description":"A adyen payments component for Convex.","repository":{"type":"git","url":"git+https://gitlab.com/Abdssamie/adyen-payments.git"},"homepage":"https://gitlab.com/Abdssamie/adyen-payments#readme","bugs":{"url":"https://gitlab.com/Abdssamie/adyen-payments/issues"},"version":"0.1.1","license":"Apache-2.0","keywords":["convex","component"],"type":"module","scripts":{"dev":"convex dev --start 'npm run dev:build'","dev:frontend":"cd example && vite","dev:build":"chokidar 'tsconfig*.json' 'src/**/*.ts' -i '**/*.test.ts' -c 'npm run build:codegen' --initial","predev":"convex init && npm run build:codegen","build":"tsc --project ./tsconfig.build.json","build:codegen":"npx convex codegen --component-dir ./src/component && npm run build","build:clean":"rm -rf dist *.tsbuildinfo && npm run build:codegen","typecheck":"tsc --noEmit && tsc -p example && tsc -p example/convex","lint":"eslint .","test":"vitest run --typecheck","test:watch":"vitest --typecheck --clearScreen false","test:debug":"vitest --inspect-brk --no-file-parallelism","test:coverage":"vitest run --coverage --coverage.reporter=text","preversion":"npm ci && npm run build:clean && npm run test && npm run lint && npm run typecheck","alpha":"npm version prerelease --preid alpha && npm publish --tag alpha && git push --follow-tags","release":"npm version patch && npm publish && git push --follow-tags","version":"(npm whoami || npm login) && vim -c 'normal o' -c 'normal o## '$npm_package_version CHANGELOG.md && prettier -w CHANGELOG.md && git add CHANGELOG.md"},"exports":{"./package.json":"./package.json",".":{"types":"./dist/client/index.d.ts","default":"./dist/client/index.js"},"./react":{"types":"./dist/react/index.d.ts","default":"./dist/react/index.js"},"./test":"./src/test.ts","./_generated/component.js":{"types":"./dist/component/_generated/component.d.ts"},"./_generated/component":{"types":"./dist/component/_generated/component.d.ts"},"./convex.config.js":{"types":"./dist/component/convex.config.d.ts","default":"./dist/component/convex.config.js"},"./convex.config":{"types":"./dist/component/convex.config.d.ts","default":"./dist/component/convex.config.js"}},"peerDependencies":{"convex":"^1.36.1","react":"^18.3.1 || ^19.0.0"},"devDependencies":{"@convex-dev/eslint-plugin":"^2.0.0","@edge-runtime/vm":"^5.0.0","@eslint/eslintrc":"^3.3.5","@eslint/js":"9.39.4","@types/node":"^24.12.2","@types/react":"^19.2.14","@types/react-dom":"^19.2.3","@typescript/native-preview":"7.0.0-dev.20260614.1","@vitejs/plugin-react":"^6.0.2","chokidar-cli":"3.0.0","convex":"^1.41.0","convex-test":"0.0.49","eslint":"9.39.4","eslint-plugin-react":"^7.37.5","eslint-plugin-react-hooks":"^7.1.1","eslint-plugin-react-refresh":"^0.5.2","globals":"^17.5.0","pkg-pr-new":"^0.0.66","prettier":"3.8.3","react":"^19.2.5","react-dom":"^19.2.5","typescript":"6.0.3","typescript-eslint":"8.58.2","vite":"8.0.9","vitest":"4.1.4"},"dependencies":{"@adyen/adyen-web":"^6.39.0","@adyen/api-library":"^22.0.0","@convex-dev/better-auth":"^0.12.4","better-auth":"^1.6.20"},"types":"./dist/client/index.d.ts","module":"./dist/client/index.js","gitHead":"b153c33731a781fb6b9511cb1be6ee1083154d79","_id":"@abdssamie/adyen-payments@0.1.1","_nodeVersion":"24.18.0","_npmVersion":"11.17.0","dist":{"integrity":"sha512-POGrnE8Ti58BiLm6JTdvT5zrP6lj7F71C973Ue83v6jYSiZWgLGs726vIJ9wd/ed0xp0JUOn8B3JhjMp71w+dQ==","shasum":"921e40c03e7dcbaf5bc041a0854fff39e94865e6","tarball":"https://registry.npmjs.org/@abdssamie/adyen-payments/-/adyen-payments-0.1.1.tgz","fileCount":69,"unpackedSize":280459,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@abdssamie%2fadyen-payments@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v0.2"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIFyXzLTNsXiSW2PnrZeT74E/yJS5c7j9oadSRaMrCmH3AiEA/ji5ENC52gqxj5FziSjLBWSBev//nK7EBAVCGyHFRmc="}]},"_npmUser":{"name":"GitLab CI/CD","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"gitlab","oidcConfigId":"oidc:ea135108-280f-44b1-b5fe-27441443c9b1"}},"directories":{},"maintainers":[{"name":"abdessamie","email":"abdessamie.elmoubarki@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/adyen-payments_0.1.1_1782402946552_0.4190258188398621"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-25T15:11:08.017Z","modified":"2026-06-25T15:55:47.068Z","0.1.0":"2026-06-25T15:11:08.380Z","0.1.1":"2026-06-25T15:55:46.681Z"},"bugs":{"url":"https://gitlab.com/Abdssamie/adyen-payments/issues"},"license":"Apache-2.0","homepage":"https://gitlab.com/Abdssamie/adyen-payments#readme","keywords":["convex","component"],"repository":{"type":"git","url":"git+https://gitlab.com/Abdssamie/adyen-payments.git"},"description":"A adyen payments component for Convex.","maintainers":[{"name":"abdessamie","email":"abdessamie.elmoubarki@gmail.com"}],"readme":"# Convex Adyen Payments\n\n[![npm version](https://badge.fury.io/js/@abdssamie%2Fadyen-payments.svg)](https://badge.fury.io/js/@abdssamie%2Fadyen-payments)\n\nA Convex component that integrates your application with **Adyen Payments**. It enables checkout sessions (supporting the Adyen Drop-in & Web Components SDK), secure payment tokenization for recurring billing, and automatic database updates via HMAC-validated webhooks.\n\n---\n\n## 🚀 Installation\n\nInstall the package in your project:\n\n```sh\nnpm install @abdssamie/adyen-payments\n# or\npnpm add @abdssamie/adyen-payments\n```\n\nCreate or update your `convex/convex.config.ts` file to import and use the component:\n\n```ts\n// convex/convex.config.ts\nimport { defineApp } from \"convex/server\";\nimport adyenPayments from \"@abdssamie/adyen-payments/convex.config.js\";\n\nconst app = defineApp();\napp.use(adyenPayments);\n\nexport default app;\n```\n\n---\n\n## 🔑 Environment Variables & Dashboard Configuration\n\nThe component requires the following environment variables. Set them in your Convex dashboard under **Settings** > **Environment Variables** or locally in `.env.local`:\n\n| Environment Variable | Description |\n| :--- | :--- |\n| `ADYEN_API_KEY` | Server-side API key for executing requests (e.g. `AQEy...`). |\n| `ADYEN_MERCHANT_ACCOUNT` | The merchant account code (e.g. `CompanyAccountECOM`). |\n| `ADYEN_ENVIRONMENT` | Set to `TEST` for sandbox testing, or `LIVE` for production. |\n| `ADYEN_HMAC_KEY` | HMAC signature key for validating incoming webhook authenticity. |\n| `APP_URL` | Base URL of your app (e.g. `https://myapp.com` or `http://localhost:3000`). |\n\n### How to Get Your Credentials from the Adyen Customer Area\n\n#### 1. Retrieve the Merchant Account Name\n1. Log in to the [Adyen Customer Area](https://ca-live.adyen.com/ca/ca/login.shtml) (use sandbox for testing, live for production).\n2. Click the account switcher in the top-left corner.\n3. Toggle to your specific **Merchant Account** (which handles payments) rather than the **Company Account** (used for administration).\n4. Copy the unique account name/code. This is your `ADYEN_MERCHANT_ACCOUNT`.\n\n#### 2. Generate an API Key\n1. In the account switcher, select your **Company Account** level.\n2. In the sidebar, navigate to **Developers** > **API credentials**.\n3. Select your integration's web service user (typically starting with `ws@Company.[YourCompanyAccount]`).\n4. Under **Server settings** > **Authentication**, click the **API key** tab.\n5. Click **Generate API key**.\n6. **Important**: Copy this key immediately and store it securely. You cannot view it again once you navigate away. Click **Save changes** at the bottom of the page.\n\n#### 3. Set Up Webhooks & Generate an HMAC Key\n1. Select your specific **Merchant Account** in the switcher.\n2. Go to **Developers** > **Webhooks** in the sidebar.\n3. Click **+ Webhook** on the top-right.\n4. Select **Standard Webhook** and click **Add**.\n5. Set the **Server URL** to your Convex deployment site endpoint (e.g., `https://<your-deployment>.convex.site/adyen/webhooks`).\n6. Scroll down to the **Security** tab and click **Generate** under the HMAC Key section.\n7. Copy the generated HMAC key. This is your `ADYEN_HMAC_KEY`.\n8. Ensure the webhook state is toggled to **Active** and click **Save configuration**.\n\n---\n\n## 💻 Usage\n\nTo use the client, import `AdyenPayments` and initialize it with your registered component:\n\n```ts\nimport { AdyenPayments } from \"@abdssamie/adyen-payments\";\nimport { components } from \"./_generated/api\";\n\nconst adyenClient = new AdyenPayments(components.adyenPayments, {\n  autoCapture: true, // If true (default), capture immediately. Set false for manual capture.\n});\n```\n\n### 1. Initializing Checkout\nCreate an action in your app's `convex/` folder to initialize a payment checkout session. This provides the `sessionId` and configuration payload required by Adyen's frontend Drop-in/Components SDK.\n\n```ts\nimport { action } from \"./_generated/server\";\nimport { v } from \"convex/values\";\n\nexport const startCheckout = action({\n  args: {\n    amount: v.number(), // Value in minor units (e.g., 1000 for $10.00)\n    currency: v.string(), // e.g. \"USD\", \"EUR\"\n    shopperReference: v.string(), // Unique shopper identifier\n  },\n  handler: async (ctx, args) => {\n    const session = await adyenClient.createCheckoutSession(ctx, {\n      amount: args.amount,\n      currency: args.currency,\n      successUrl: `https://myapp.com/checkout/success`,\n      cancelUrl: `https://myapp.com/checkout/cancel`,\n      shopperReference: args.shopperReference,\n    });\n    return session; // Returns { sessionId, sessionData, url? }\n  },\n});\n```\n\n> **Note:** This component supports the Adyen Drop-in and Web Components SDK only. It does not support hosted checkout pages (HPP) or Pay By Link — the `url` field in the session response is optional and `null` for most merchant configurations.\n\n### 2. Charging a Stored Card (Recurring / MIT)\nWhen a shopper pays during checkout and consents to saving their payment details, Adyen stores a token. You can trigger recurring charges from a backend action:\n\n```ts\nexport const chargeRecurring = action({\n  args: {\n    shopperReference: v.string(),\n    recurringDetailReference: v.string(), // The stored card token\n    amount: v.number(),\n    currency: v.string(),\n  },\n  handler: async (ctx, args) => {\n    return await adyenClient.chargeStoredCard(ctx, {\n      shopperReference: args.shopperReference,\n      recurringDetailReference: args.recurringDetailReference,\n      amount: args.amount,\n      currency: args.currency,\n    });\n  },\n});\n```\n\n### 3. Payment Modifications (Manual Capture, Refund, Cancel)\nIf you configure `autoCapture: false` (manual capture), you must manually capture authorizations:\n\n```ts\nexport const capture = action({\n  args: { pspReference: v.string(), amount: v.number(), currency: v.string() },\n  handler: async (ctx, args) => {\n    return await adyenClient.capturePayment(ctx, args);\n  },\n});\n\nexport const refund = action({\n  args: { pspReference: v.string(), amount: v.number(), currency: v.string() },\n  handler: async (ctx, args) => {\n    return await adyenClient.refundPayment(ctx, args);\n  },\n});\n\nexport const cancel = action({\n  args: { pspReference: v.string() },\n  handler: async (ctx, args) => {\n    return await adyenClient.cancelPayment(ctx, args);\n  },\n});\n```\n\n---\n\n## 🔔 Webhook Integration\n\nAdyen webhooks require a Node.js context because signature verification depends on Node-native packages. Define the handler inside a `\"use node\"` file, and map it inside your `http.ts` router.\n\n### 1. Webhook Handler (`convex/adyenWebhooks.ts`)\n```ts\n\"use node\";\n\nimport { internalAction } from \"./_generated/server\";\nimport { components } from \"./_generated/api\";\nimport { createWebhookHandler } from \"@abdssamie/adyen-payments\";\nimport { v } from \"convex/values\";\n\n// Create raw handler with custom hooks if needed\nconst rawHandler = createWebhookHandler(components.adyenPayments, {\n  events: {\n    AUTHORISATION: async (ctx, notification) => {\n      console.log(`Payment authorized for order: ${notification.merchantReference}`);\n    },\n    CAPTURE: async (ctx, notification) => {\n      console.log(`Payment captured: ${notification.pspReference}`);\n    },\n  },\n});\n\nexport const handleWebhook = internalAction({\n  args: { bodyText: v.string(), url: v.string() },\n  handler: async (ctx, args) => {\n    const request = new Request(args.url, {\n      method: \"POST\",\n      body: args.bodyText,\n      headers: { \"Content-Type\": \"application/json\" },\n    });\n\n    const response = await rawHandler(ctx, request);\n    if (!response.ok) {\n      throw new Error(`Webhook error: ${response.status}`);\n    }\n    return await response.text();\n  },\n});\n```\n\n### 2. HTTP Routing (`convex/http.ts`)\n```ts\nimport { httpRouter } from \"convex/server\";\nimport { httpAction } from \"./_generated/server\";\nimport { internal } from \"./_generated/api\";\n\nconst http = httpRouter();\n\nhttp.route({\n  path: \"/adyen/webhooks\",\n  method: \"POST\",\n  handler: httpAction(async (ctx, request) => {\n    const bodyText = await request.text();\n    try {\n      const responseText = await ctx.runAction(\n        internal.adyenWebhooks.handleWebhook,\n        { bodyText, url: request.url }\n      );\n      return new Response(responseText, {\n        status: 200,\n        headers: { \"Content-Type\": \"text/plain\" },\n      });\n    } catch (err) {\n      console.error(\"Webhook processing error:\", err);\n      return new Response(\"Webhook Error\", { status: 400 });\n    }\n  }),\n});\n\nexport default http;\n```\n\n---\n\n## 🛠️ Developing the Component\n\nTo contribute or make changes to the component repository itself, follow these steps to test and compile local changes:\n\n```sh\n# Install dependencies\npnpm install\n\n# Run the dev watcher (recompiles the component and runs example backend)\npnpm dev\n\n# Run unit tests\npnpm test\n\n# Lint files\npnpm lint\n```\n","readmeFilename":"README.md"}