@mgov/webview-sign
v0.2.1
Published
Frontend SDK for the eGov Mobile (Казахстан) WebView signing bridge: CMS/XML signing over the native iOS/Android JS interfaces.
Maintainers
Readme
@mgov/webview-sign
Frontend SDK for signing documents inside the eGov Mobile (Казахстан) WebView via the native ЭЦП bridge. Handles CMS (CMS_SIGN_ONLY / CMS_WITH_DATA) and XML signing, abstracts the iOS/Android differences, and — most importantly — makes the callback impossible to misconfigure.
TypeScript · ESM + CJS · zero dependencies · framework-agnostic.
Why this exists
The native bridge calls back into the page by invoking the function at the path you put into payload.callback (e.g. currentProfile.verifyCMS). The #1 integration failure is a mismatch between three places: the path registered on window, the string in payload.callback, and what actually exists on window. This SDK generates the path once and uses that single value for all three, so they can never drift apart.
It also encodes the real interface locations that aren't obvious from the docs:
- iOS interfaces live under
window.mobapp.iosSignCMS/window.mobapp.iosSignXmlList— notwindow.*. - Android
signDoc(doc)takes a single argument; the callback travels in the payload, not as a second argument.signXmlList(multiDoc, callback)does take the callback as the 2nd arg. - No iOS↔Android fallback: platform is routed strictly from the
platformTypecookie.
Install
npm install @mgov/webview-signUsage
import { egovSign } from '@mgov/webview-sign';
if (!egovSign.isAvailable()) {
// Not inside eGov Mobile — show a QR / desktop flow instead.
}
// CMS signing (PDF, base64)
const result = await egovSign.signCMS(
[
{
id: 1,
nameRu: 'Заявление',
nameKz: 'Өтініш',
nameEn: 'Application',
meta: [{ name: 'ИИН', value: '940622300641' }],
document: { file: { mime: 'application/pdf', data: base64Pdf } },
},
],
'CMS_SIGN_ONLY' // or 'CMS_WITH_DATA'
);
console.log(result.documentsToSign[0].document.file.data); // signed CMS, base64// XML signing
const result = await egovSign.signXML([
{
id: 1,
nameRu: 'Согласие на предоставление данных',
documentXml: '<data><iin>12345678</iin></data>',
},
]);Debugging "nothing happens"
Run this inside the real WebView and log it before filing a bug — it tells you instantly whether the bridge is missing or the callback never fired:
import { getBridgeDiagnostics } from '@mgov/webview-sign';
console.log(JSON.stringify(getBridgeDiagnostics(), null, 2));If every bridge.* is false, the page isn't running inside the app (or the interfaces are named differently in your build). If the bridge is present but the promise times out, the app accepted the call but never invoked the callback — check that your build of the app reads payload.callback as a path.
React (thin wrapper)
import { useCallback, useState } from 'react';
import { egovSign, type CmsDocumentToSign, type SignResult } from '@mgov/webview-sign';
export function useEgovSign() {
const [pending, setPending] = useState(false);
const [error, setError] = useState<Error | null>(null);
const signCMS = useCallback(async (docs: CmsDocumentToSign[]) => {
setPending(true);
setError(null);
try {
return (await egovSign.signCMS(docs)) as SignResult;
} catch (e) {
setError(e as Error);
throw e;
} finally {
setPending(false);
}
}, []);
return { signCMS, pending, error, available: egovSign.isAvailable() };
}API
| Method | Description |
| --- | --- |
| egovSign.isAvailable() | true if inside eGov Mobile (X-Egov-Frame-Type=MOBILE). |
| egovSign.detectEnvironment() | { isEgovMobile, platform, language, appVersion }. |
| egovSign.signCMS(docs, method?, opts?) | Sign with CMS_SIGN_ONLY (default) or CMS_WITH_DATA. |
| egovSign.signXML(docs, opts?) | Sign with the XML method. |
| egovSign.getDiagnostics() | Full bridge snapshot. |
SignOptions: { timeoutMs?: number; version?: number; callbackPath?: string }.
Errors are thrown as EgovSignError with .code: BRIDGE_UNAVAILABLE, NOT_EGOV_MOBILE, TIMEOUT, INVALID_PAYLOAD, UNKNOWN_PLATFORM.
License
MIT
