{"_id":"@cashiaapp/pay-with-cashia","_rev":"2-5e7b132d59656e060a2cb59ef6224483","name":"@cashiaapp/pay-with-cashia","dist-tags":{"latest":"0.1.6"},"versions":{"0.1.5":{"name":"@cashiaapp/pay-with-cashia","version":"0.1.5","keywords":["cashia","payment","button","modal","iframe","framework-agnostic"],"license":"MIT","_id":"@cashiaapp/pay-with-cashia@0.1.5","maintainers":[{"name":"walobwa.ivy","email":"walobwa.ivy@cashia.com"}],"homepage":"https://github.com/CashiaApp/pay-with-cashia#readme","bugs":{"url":"https://github.com/CashiaApp/pay-with-cashia/issues"},"dist":{"shasum":"e563906a83d9d4662ebef5d7f74f7f18736fdaf1","tarball":"https://registry.npmjs.org/@cashiaapp/pay-with-cashia/-/pay-with-cashia-0.1.5.tgz","fileCount":8,"integrity":"sha512-AKlFUwwQtbNUJSOQ0JvfAKY80XPuj0mBf3PaarRc1R8OJTEGIaNX0f/Kl0CNJHfeM9qCv3vLCLNnqoLO0oJrdg==","signatures":[{"sig":"MEQCIAabWFhalT8/w0voVk1x2si9Oy6HEh+grXVYJpng//fAAiApAaQ5YHjEooIgCp5lJ/FmpqnYfQigEZ0TL/DB7FgIeg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":77032},"main":"./dist/index.cjs","types":"./dist/index.d.cts","module":"./dist/index.mjs","exports":{".":{"import":"./dist/index.mjs","require":"./dist/index.cjs"},"./package.json":"./package.json"},"gitHead":"5f9b3ff02f42324db561204a5386eacfcc9f2cb0","scripts":{"dev":"tsdown --watch","build":"tsdown","release":"release-it"},"_npmUser":{"name":"walobwa.ivy","email":"walobwa.ivy@cashia.com"},"release-it":{"github":{"release":true},"$schema":"https://unpkg.com/release-it/schema/release-it.json"},"repository":{"url":"git+https://github.com/CashiaApp/pay-with-cashia.git","type":"git","directory":"packages/pay-with-cashia"},"_npmVersion":"10.9.2","description":"A framework-agnostic Cashia payment button library that opens a payment modal.","directories":{},"_nodeVersion":"22.16.0","publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"tsdown":"^0.21.10","release-it":"^20.2.1","typescript":"^6.0.3","@types/node":"^20.19.43","@typescript/native-preview":"^7.0.0-dev.20260707.2"},"_npmOperationalInternal":{"tmp":"tmp/pay-with-cashia_0.1.5_1788417465903_0.7615939269327756","host":"s3://npm-registry-packages-npm-production"}},"0.1.6":{"name":"@cashiaapp/pay-with-cashia","version":"0.1.6","description":"A framework-agnostic Cashia payment button library that opens a payment modal.","repository":{"type":"git","url":"git+https://github.com/CashiaApp/pay-with-cashia.git","directory":"packages/pay-with-cashia"},"homepage":"https://github.com/CashiaApp/pay-with-cashia#readme","bugs":{"url":"https://github.com/CashiaApp/pay-with-cashia/issues"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"main":"./dist/index.cjs","module":"./dist/index.mjs","types":"./dist/index.d.cts","exports":{".":{"import":"./dist/index.mjs","require":"./dist/index.cjs"},"./package.json":"./package.json"},"scripts":{"build":"tsdown","dev":"tsdown --watch","release":"release-it"},"keywords":["cashia","payment","button","modal","iframe","framework-agnostic"],"license":"MIT","devDependencies":{"@typescript/native-preview":"^7.0.0-dev.20260707.2","@types/node":"^20.19.43","release-it":"^20.2.1","tsdown":"^0.21.10","typescript":"^6.0.3"},"release-it":{"$schema":"https://unpkg.com/release-it/schema/release-it.json","github":{"release":true}},"_id":"@cashiaapp/pay-with-cashia@0.1.6","gitHead":"2a2afdb2c6825e2aaea3027b728002a404ec4210","_nodeVersion":"22.23.2","_npmVersion":"10.9.8","dist":{"integrity":"sha512-mRwpcjVT05aQSAke9n2bG9bDY5nGc1Xt1WrEMELtLPRnMt+ZPNzNk2+uNz3jAwckd/RyJmjwydUFkyxkvvnm0Q==","shasum":"6787a7a8cec4e57850091f5d21fcab73fefaa6b2","tarball":"https://registry.npmjs.org/@cashiaapp/pay-with-cashia/-/pay-with-cashia-0.1.6.tgz","fileCount":8,"unpackedSize":88318,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDgUvu9yQFr8ZlBtYYXQKYlks1bDHF4BxBtNEuGzFHIowIhAJSk28cEJ309f/lAYqQCxN0neaH0jvIo8QgCFSz5Rnle"}]},"_npmUser":{"name":"walobwa.ivy","email":"walobwa.ivy@cashia.com"},"directories":{},"maintainers":[{"name":"walobwa.ivy","email":"walobwa.ivy@cashia.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/pay-with-cashia_0.1.6_1788418961000_0.5492568480875308"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-03T06:37:45.712Z","modified":"2026-09-03T07:02:41.415Z","0.1.5":"2026-09-03T06:37:46.046Z","0.1.6":"2026-09-03T07:02:41.133Z"},"bugs":{"url":"https://github.com/CashiaApp/pay-with-cashia/issues"},"license":"MIT","homepage":"https://github.com/CashiaApp/pay-with-cashia#readme","keywords":["cashia","payment","button","modal","iframe","framework-agnostic"],"repository":{"type":"git","url":"git+https://github.com/CashiaApp/pay-with-cashia.git","directory":"packages/pay-with-cashia"},"description":"A framework-agnostic Cashia payment button library that opens a payment modal.","maintainers":[{"name":"walobwa.ivy","email":"walobwa.ivy@cashia.com"}],"readme":"# Pay with Cashia\n\n`@cashiaapp/pay-with-cashia` adds a Cashia payment button and hosted checkout modal to a website. It is framework-agnostic and can be used through its JavaScript API or as a Web Component.\n\n## How the integration works\n\n1. A customer selects **Pay with Cashia** on your checkout page.\n2. The library calls the `createSession` function supplied by your application.\n3. Your frontend asks your backend to create a payment session.\n4. Your backend authenticates with Cashia and returns the hosted checkout URL.\n5. The library opens that URL in a modal iframe.\n6. Cashia closes the modal when the hosted payment flow finishes or is cancelled.\n\n> [!IMPORTANT]\n> Create Cashia payment sessions on your backend. Never expose Cashia API keys, access tokens, or other credentials in browser code.\n\n## Prerequisites\n\nBefore integrating, obtain the following from Cashia:\n\n- Access to the public `@cashiaapp/pay-with-cashia` npm package\n- Your Cashia API credentials and payment-session API details\n- The hosted checkout URL or environment details for sandbox and production\n- A publicly accessible HTTPS URL for your partner logo\n\nThe library requires a browser DOM. Server-side rendered applications must initialize it on the client.\n\n## Installation\n\nInstall the package from the public npm registry with your package manager:\n\n```bash\nnpm install @cashiaapp/pay-with-cashia\n# or\npnpm add @cashiaapp/pay-with-cashia\n# or\nyarn add @cashiaapp/pay-with-cashia\n```\n\n## Quick start\n\nAdd a container where the payment button should appear:\n\n```html\n<div id=\"cashia-payment\"></div>\n```\n\nCreate the button in browser code:\n\n```ts\nimport { createPaymentButton } from \"@cashiaapp/pay-with-cashia\";\n\nconst paymentButton = createPaymentButton(\"#cashia-payment\", {\n  partnerLogoUrl: \"https://merchant.example/assets/logo.png\",\n  createSession: async () => {\n    // Ask your backend to create the Cashia session so credentials stay server-side.\n    const response = await fetch(\"/api/cashia/payment-sessions\", {\n      method: \"POST\",\n      headers: { \"Content-Type\": \"application/json\" },\n      body: JSON.stringify({\n        orderId: \"order-123\",\n        amount: 500,\n        currency: \"KES\",\n        phoneNumber: \"0712345678\",\n      }),\n    });\n\n    if (!response.ok) {\n      throw new Error(\"Unable to start the Cashia payment\");\n    }\n\n    // Return the absolute hosted checkout URL for the library to open in its modal.\n    const session = (await response.json()) as { url: string };\n    return session.url;\n  },\n});\n```\n\n`createSession` may return a string or a `Promise<string>`. The string must be an absolute Cashia hosted checkout URL, including the session identifier supplied by Cashia. The library adds `parentOrigin` and `partnerLogoUrl` query parameters before opening the URL.\n\nThe request body above is illustrative. Build payment details from your trusted order data and follow the payment-session contract supplied during Cashia onboarding.\n\n### Backend responsibility\n\nYour `/api/cashia/payment-sessions` endpoint should:\n\n1. Authenticate the customer and load the order from trusted server-side data.\n2. Validate the amount, currency, customer, and order status.\n3. Create a payment session with Cashia using server-side credentials.\n4. Return only the absolute hosted checkout URL needed by the library.\n\nFor example, the response consumed by `createSession` is:\n\n```json\n{\n  \"url\": \"https://cashia-checkout.example/pay?sessionId=SESSION_ID\"\n}\n```\n\nThe actual Cashia domain and response fields are environment-specific. Use the values provided during onboarding.\n\n## React and Next.js\n\nInitialize the library in a client component and destroy the handle when the component unmounts. A dynamic import prevents the DOM-dependent library from being evaluated during server rendering.\n\n```tsx\n\"use client\";\n\nimport { useEffect, useRef } from \"react\";\nimport type { PaymentButtonHandle } from \"@cashiaapp/pay-with-cashia\";\n\nexport function CashiaPaymentButton() {\n  const containerRef = useRef<HTMLDivElement>(null);\n\n  useEffect(() => {\n    let handle: PaymentButtonHandle | undefined;\n    let disposed = false;\n\n    void import(\"@cashiaapp/pay-with-cashia\").then(\n      ({ createPaymentButton }) => {\n        if (disposed || !containerRef.current) return;\n\n        handle = createPaymentButton(containerRef.current, {\n          partnerLogoUrl: \"https://merchant.example/assets/logo.png\",\n          createSession: async () => {\n            const response = await fetch(\"/api/cashia/payment-sessions\", {\n              method: \"POST\",\n            });\n\n            if (!response.ok) {\n              throw new Error(\"Unable to start the Cashia payment\");\n            }\n\n            const session = (await response.json()) as { url: string };\n            return session.url;\n          },\n        });\n      },\n    );\n\n    return () => {\n      disposed = true;\n      handle?.destroy();\n    };\n  }, []);\n\n  return <div ref={containerRef} />;\n}\n```\n\n## Web Component\n\nRegister the custom element once, assign its required `createSession` property, and then add it to the page.\n\n```html\n<cashia-payment-button\n  id=\"cashia-payment\"\n  partner-logo-url=\"https://merchant.example/assets/logo.png\"\n></cashia-payment-button>\n\n<script type=\"module\">\n  import { definePaymentButtonElement } from \"@cashiaapp/pay-with-cashia\";\n\n  definePaymentButtonElement();\n\n  const element = document.querySelector(\"#cashia-payment\");\n  element.createSession = async () => {\n    const response = await fetch(\"/api/cashia/payment-sessions\", {\n      method: \"POST\",\n    });\n\n    if (!response.ok) {\n      throw new Error(\"Unable to start the Cashia payment\");\n    }\n\n    const session = await response.json();\n    return session.url;\n  };\n</script>\n```\n\n`definePaymentButtonElement()` is safe to call more than once. Pass a custom tag name if your application requires one:\n\n```ts\ndefinePaymentButtonElement(\"merchant-cashia-payment\");\n```\n\n### Web Component attributes\n\n| Attribute | Description |\n| --- | --- |\n| `partner-logo-url` | Required partner logo URL shown in the hosted checkout |\n| `button-text` | Trigger label; child text is used when this attribute is omitted |\n| `button-class-name` | Space-separated CSS classes added to the button |\n| `logo-url` | Image URL or raw SVG used as the trigger icon |\n| `special-offer-text` | Badge text displayed on the button |\n| `button-background-color` | Trigger background color |\n| `button-text-color` | Trigger text and icon color |\n| `special-offer-background-color` | Badge background color |\n| `special-offer-text-color` | Badge text color |\n\n## Configuration\n\n### `PaymentButtonConfig`\n\n| Property | Type | Required | Default | Description |\n| --- | --- | --- | --- | --- |\n| `createSession` | `() => string \\| Promise<string>` | Yes | - | Creates a session and returns its absolute hosted checkout URL |\n| `partnerLogoUrl` | `string` | Yes | - | Public partner logo URL passed to the hosted checkout |\n| `buttonText` | `string` | No | `\"Pay with Cashia\"` | Trigger button label |\n| `buttonClassName` | `string` | No | - | Space-separated CSS classes added to the trigger button |\n| `buttonLogoUrl` | `string` | No | Cashia logo | Image URL or raw `<svg>...</svg>` markup for the trigger icon |\n| `specialOfferText` | `string` | No | `\"SPECIAL OFFER\"` | Badge text; use an empty string to hide it in the JavaScript API |\n| `buttonBackgroundColor` | `string` | No | `\"#e01864\"` | Trigger background color |\n| `buttonTextColor` | `string` | No | `\"#ffffff\"` | Trigger foreground color |\n| `specialOfferBackgroundColor` | `string` | No | `\"#ffffff\"` | Badge background color |\n| `specialOfferTextColor` | `string` | No | `\"#e01864\"` | Badge text color |\n\nAny valid browser CSS color can be used for the color properties.\n\n### `PaymentButtonHandle`\n\n`createPaymentButton` returns a handle for controlling the integration:\n\n```ts\nconst handle = createPaymentButton(container, config);\n\nawait handle.open();\nhandle.close();\nhandle.update({ buttonText: \"Complete payment\" });\nhandle.destroy();\n```\n\n| Member | Description |\n| --- | --- |\n| `buttonElement` | The generated `HTMLButtonElement` |\n| `open()` | Creates a new session and opens the modal |\n| `close()` | Closes the current modal |\n| `update(config)` | Updates appearance or session configuration at runtime |\n| `destroy()` | Closes the modal and removes the button and its listeners |\n\nCalling `open()` while a session is being created or the modal is already open has no effect. The trigger button is disabled while `createSession` is pending.\n\n## Error handling\n\nWhen a customer clicks the generated button and `createSession` fails, the button dispatches a `payment-button-error` custom event. Use it to display an error in your own interface or send the failure to monitoring.\n\n```ts\npaymentButton.buttonElement.addEventListener(\"payment-button-error\", (event) => {\n  const error = (event as CustomEvent<unknown>).detail;\n  console.error(\"Cashia payment could not be opened\", error);\n});\n```\n\nWhen you call `handle.open()` directly, handle the rejected promise with `try`/`catch`.\n\n## Security and deployment\n\n- Keep Cashia credentials and authoritative payment data on your backend.\n- Use HTTPS for the host page, API endpoint, logo assets, and hosted checkout URL in production.\n- Allow the Cashia hosted checkout origin in your Content Security Policy `frame-src` directive.\n- Allow required logo origins in `img-src` if your Content Security Policy restricts images.\n- Return a newly created or still-valid session URL for each payment attempt.\n- Treat payment completion as authoritative only after server-side verification using the Cashia integration supplied during onboarding. Closing the modal is not proof of payment.\n\nThe library validates modal close messages against the hosted checkout URL's origin. The hosted checkout closes the modal with:\n\n```js\nwindow.parent.postMessage(\n  { type: \"PAYMENT_BUTTON_CLOSE\" },\n  new URLSearchParams(window.location.search).get(\"parentOrigin\"),\n);\n```\n\n## Troubleshooting\n\n### The package cannot be installed\n\nConfirm that your package manager can access `https://registry.npmjs.org`. Remove any `.npmrc` rule that maps the `@cashiaapp` scope to a private registry.\n\n### The button does not appear\n\nEnsure the container exists before calling `createPaymentButton`. In an SSR framework, initialize the library only in browser code.\n\n### The modal does not open\n\nListen for `payment-button-error`, check the session endpoint response, and confirm that `createSession` returns a valid absolute URL rather than a relative path.\n\n### The iframe is blocked\n\nCheck the browser console and your Content Security Policy. The Cashia checkout origin must be allowed by `frame-src`, and your server must not apply a conflicting iframe policy to the hosted checkout.\n\n## Package exports\n\n```ts\nimport {\n  createPaymentButton,\n  definePaymentButtonElement,\n  PaymentButtonElement,\n} from \"@cashiaapp/pay-with-cashia\";\n\nimport type {\n  CloseMessage,\n  CreatePaymentSession,\n  PaymentButtonAppearance,\n  PaymentButtonConfig,\n  PaymentButtonHandle,\n} from \"@cashiaapp/pay-with-cashia\";\n```\n\n## Repository development\n\nThis repository is a pnpm monorepo:\n\n| Path | Purpose |\n| --- | --- |\n| `packages/pay-with-cashia` | Published library |\n| `examples/host-app` | Next.js integration example |\n\nFrom the repository root:\n\n```bash\npnpm install\npnpm build\npnpm dev:package\npnpm dev:host\n```\n\n## Support\n\nContact your Cashia integration representative for credentials, environment URLs, payment-session API details, and production onboarding support.\n\n## License\n\nMIT","readmeFilename":"README.md"}