React Integration
The mypos-online-checkout/react sub-export provides a PaymentForm component and a usePaymentForm hook for React 18+ applications. It keeps the React dependency out of the core server-side package.
React 18+ required. The sub-export uses React hooks and server/client component patterns compatible with React 18 and Next.js 13+.
Import
import { PaymentForm, usePaymentForm } from 'mypos-online-checkout/react'
const { PaymentForm, usePaymentForm } = require('mypos-online-checkout/react')
PaymentForm Component
PaymentForm renders the hidden signed fields and submits the form to the myPOS checkout URL. Pass the checkoutFields object generated server-side.
'use client'
import { PaymentForm } from 'mypos-online-checkout/react'
interface CheckoutPageProps {
checkoutFields: Record<string, string>
checkoutUrl: string
}
export function CheckoutPage({ checkoutFields, checkoutUrl }: CheckoutPageProps) {
return (
<PaymentForm
checkoutFields={checkoutFields}
checkoutUrl={checkoutUrl}
submitLabel="Pay now"
className="mt-4"
/>
)
}
'use client'
import { PaymentForm } from 'mypos-online-checkout/react'
export function CheckoutPage({ checkoutFields, checkoutUrl }) {
return (
<PaymentForm
checkoutFields={checkoutFields}
checkoutUrl={checkoutUrl}
submitLabel="Pay now"
className="mt-4"
/>
)
}
usePaymentForm Hook
Use usePaymentForm when you need to programmatically trigger form submission or access form state:
'use client'
import { usePaymentForm } from 'mypos-online-checkout/react'
interface ManualCheckoutProps {
checkoutFields: Record<string, string>
checkoutUrl: string
}
export function ManualCheckout({ checkoutFields, checkoutUrl }: ManualCheckoutProps) {
const { formRef, submit, isSubmitting } = usePaymentForm({ checkoutFields, checkoutUrl })
return (
<>
<form ref={formRef} />
<button onClick={submit} disabled={isSubmitting}>
{isSubmitting ? 'Redirecting…' : 'Complete payment'}
</button>
</>
)
}
'use client'
import { usePaymentForm } from 'mypos-online-checkout/react'
export function ManualCheckout({ checkoutFields, checkoutUrl }) {
const { formRef, submit, isSubmitting } = usePaymentForm({ checkoutFields, checkoutUrl })
return (
<>
<form ref={formRef} />
<button onClick={submit} disabled={isSubmitting}>
{isSubmitting ? 'Redirecting…' : 'Complete payment'}
</button>
</>
)
}
Next.js Architecture Pattern
The recommended pattern separates the signed field generation (server) from form rendering (client) and webhook handling (API route):
Server Component — generate signed fields
// app/checkout/page.tsx
import { MyPOSClient } from 'mypos-online-checkout'
import { CheckoutPage } from './CheckoutPage'
const client = new MyPOSClient({ /* config */ })
export default async function Page({ searchParams }: { searchParams: { orderId: string } }) {
const checkoutFields = await client.generateCheckoutFields({
orderId: searchParams.orderId,
amount: 19.99,
currency: 'EUR',
urlOk: 'https://mystore.example/checkout/success',
urlCancel: 'https://mystore.example/checkout/cancel',
urlNotify: 'https://mystore.example/api/payment/notify',
})
return <CheckoutPage checkoutFields={checkoutFields} checkoutUrl={client.checkoutUrl} />
}
Client Component — render form
// app/checkout/CheckoutPage.tsx
'use client'
import { PaymentForm } from 'mypos-online-checkout/react'
export function CheckoutPage({
checkoutFields,
checkoutUrl,
}: {
checkoutFields: Record<string, string>
checkoutUrl: string
}) {
return (
<div>
<h2>Complete your payment</h2>
<PaymentForm checkoutFields={checkoutFields} checkoutUrl={checkoutUrl} submitLabel="Pay €19.99" />
</div>
)
}
API Route — validate webhook
// app/api/payment/notify/route.ts
import { MyPOSClient, MyPOSSignatureError } from 'mypos-online-checkout'
import type { NextRequest } from 'next/server'
const client = new MyPOSClient({ /* config */ })
export async function POST(req: NextRequest) {
const body = await req.text()
const params = Object.fromEntries(new URLSearchParams(body))
try {
const result = await client.validateNotification(params)
if (result.success) {
// Update order status in DB
}
} catch (err) {
if (err instanceof MyPOSSignatureError) {
return new Response('Forbidden', { status: 403 })
}
throw err
}
return new Response('OK', { status: 200 })
}