A React component library for signing electronic prescriptions using HIN authentication. This library provides both a usePrescriptionSigning
hook for custom implementations and a PrescriptionSign
component for quick integration. The library intelligently handles session restoration to minimize authentication flows when valid session data exists.
npm install @documedis-components/prescription-sign
import { PrescriptionSign } from '@documedis-components/prescription-sign/react'; function MyApp() { return ( <PrescriptionSign environment="demo" accessToken="your-access-token" chmed="encoded-chmed-data" onSuccess={(signedCHMED) => console.log('Success!', signedCHMED)} onError={(error) => alert(error.userMessage)} // Show user-friendly message /> ); }
Parameter | Type | Required | Description |
---|---|---|---|
environment | 'demo' | 'prod' | ✅ | Environment configuration for the prescription service ('demo' for testing and development, 'prod' for production) |
accessToken | string | ✅ | Authentication token for backend service |
chmed | string | ✅ | Encoded CHMED prescription data |
sessionToken | string | ❌ | Optional existing session token to reuse authentication state |
onSessionTokenUpdate | (token: string) => void | ❌ | Optional callback invoked when the session token is updated |
onSuccess | (signedCHMED: string) => void | ❌ | Optional callback invoked when prescription signing succeeds |
onError | (error: DomainError) => void | ❌ | Optional callback invoked when prescription signing fails |
className | string | ❌ | Additional CSS classes |
For advanced use cases, you can use the usePrescriptionSigning
hook directly to build custom UI components while leveraging the same robust signing logic. The hook accepts configuration parameters similar to the component props, but requires calling start(chmed)
to initiate signing rather than passing chmed
as a parameter.
Parameter | Type | Required | Description |
---|---|---|---|
environment | 'demo' | 'prod' | ✅ | Environment configuration for the prescription service ('demo' for testing and development, 'prod' for production) |
accessToken | string | ✅ | Authentication token for backend service |
sessionToken | string | ❌ | Optional existing session token to reuse authentication state |
onSessionTokenUpdate | (token: string) => void | ❌ | Optional callback invoked when the session token is updated |
onSuccess | (signedCHMED: string) => void | ❌ | Optional callback invoked when prescription signing succeeds |
onError | (error: DomainError) => void | ❌ | Optional callback invoked when prescription signing fails |
Property | Type | Description |
---|---|---|
start | (chmed: string) => void | Initiates the signing process with base64-encoded CHMED prescription data |
interrupt | () => void | Terminates the signing process at any time |
isIdle | boolean | True when ready to start signing (initial state) |
isActive | boolean | True when actively processing (excludes error/success states) |
isError | boolean | True when in error state (persists until retry) |
isSuccess | boolean | True when signing completed successfully |
isSigning | boolean | True during the actual signature operation |
signedCHMED | string | undefined | The signed prescription data (available after success) |
demo
- Demo environment with non-production data (safe for testing and development)prod
- Production environment with real data (for live prescriptions)All errors are instances of DomainError
with three key properties:
code
- Stable error code for programmatic handling (e.g., "POPUP_CLOSED", "INVALID_TOKEN")message
- Technical message for debugging (not for end users)userMessage
- User-friendly message safe to display in UIonError={(error) => { // Show user-friendly message in UI showNotification(error.userMessage); // Handle specific errors programmatically switch (error.code) { case 'POPUP_CLOSED': // User closed the popup, maybe offer to retry break; case 'SESSION_EXPIRED': // Session expired, clear cache and retry clearSession(); break; case 'INVALID_FORMAT': // Invalid prescription data format highlightFormErrors(); break; } // Log technical details for debugging console.error(error.message, error.code); }}
POPUP_CLOSED
- User closed authentication popupPOPUP_BLOCKED
- Browser blocked popup windowSESSION_EXPIRED
- Authentication session expiredINVALID_TOKEN
- Invalid or expired access tokenINVALID_FORMAT
- Malformed prescription dataHIN_ERROR
- HIN service errorAPI_CONNECTION_FAILED
- Network connection failedTIMEOUT
- Operation timed outThe library intelligently optimizes the signing process by checking session state first. This can result in two different flow patterns:
When valid authentication data exists in session, the process can skip the authorization phase while maintaining all security checks:
Events like saml_handle_retrieved_from_session
and oauth_token_retrieved_from_session
indicate the process found valid session data and can skip the authorization phase.
When no valid session data exists, the full OAuth/SAML flow executes:
Events like oauth_flow_initiated
and saml_handle_received
indicate fresh authentication flows are being executed.
<PrescriptionSign environment="demo" accessToken="your-token" chmed="CHMED16A1H4sI..." />
<PrescriptionSign environment="demo" accessToken="your-token" chmed="CHMED16A1H4sI..." onSuccess={(signedCHMED) => { console.log('Prescription signed:', signedCHMED); // Save to database, redirect user, etc. }} onError={(error) => { // Display user-friendly message showNotification(error.userMessage); // Log technical details for debugging console.error('Error code:', error.code, error.message); }} />
import { usePrescriptionSigning } from '@documedis-components/prescription-sign/react'; function CustomSigningButton({ chmed, environment, accessToken }) { const { start, interrupt, isActive, isSuccess, isError, signedCHMED } = usePrescriptionSigning({ environment, accessToken, onSuccess: (signedCHMED) => console.log('Signed!', signedCHMED), onError: (error) => { // You can access error.userMessage for UI display console.error('Error:', error.code, '-', error.userMessage); }, }); if (isSuccess) { return <div>✅ Prescription signed: {signedCHMED?.substring(0, 20)}...</div>; } if (isError) { return <div>❌ Signing failed. <button onClick={() => start(chmed)}>Retry</button></div>; } return ( <div> <button onClick={() => start(chmed)} disabled={isActive} > {isActive ? 'Signing...' : 'Sign Prescription'} </button> {isActive && <button onClick={interrupt}>Cancel</button>} </div> ); }
Try the component below with real CHMED data. Success and error events are displayed in the Event Log below for educational purposes.
This component uses the Documedis design system CSS variables and utility classes. You can customize the appearance by overriding these variables:
:root { --documedis-color-primary: #2d4e9b; --documedis-color-success: #3b9977; --documedis-color-error: #e5232a; --documedis-spacing-md: 1rem; --documedis-border-radius-md: 0.25rem; /* ... and many more */ }