Updated 9 min readBy Daniel Weber

Integrate Photo Payment with React Native

This guide connects React Native and TypeScript to the native Docutain Photo Payment flow on Android and iOS.

One JavaScript entry point opens the native capture UI, recognizes GiroCode or invoice data locally and returns structured JSON. Your application keeps ownership of mapping, validation, confirmation and transfer authorization.

Targets
Android and iOS
Language
TypeScript
Result
JSON string or rejected Promise
Processing
Local in the native SDK
Jump to the React Native setup

The native workflow behind the TypeScript call

  1. The React Native screen invokes the Docutain bridge from a user action.
  2. The native Android or iOS component presents capture, import and review UI.
  3. Docutain reads a GiroCode when available or extracts fields from invoice text.
  4. The Promise resolves with JSON, resolves with an empty string in the configured edge case, or rejects on cancellation/error.
  5. TypeScript maps the result to the application's payment model before native banking controls continue.

Prepare both native projects

AreaRequirement
AndroidAndroid 5.0+, compileSdk 34+ and Android Gradle Plugin 8.0.2+
iOSiOS 11+ and an NSCameraUsageDescription
LicenseA key matching Android applicationId and iOS CFBundleIdentifier
HardwareRepresentative physical devices with rear-facing cameras

Use emulators for navigation and basic bridge tests only. Camera focus, auto-capture, scan quality and performance need physical devices.

Install and initialize the React Native SDK

1. Add the npm package

npm install @docutain/react-native-docutain-sdk

Complete the package's Android and iOS setup, including the iOS camera-purpose string and the recommended Android memory configuration.

2. Initialize before enabling the feature

import DocutainSDK from '@docutain/react-native-docutain-sdk';

async function initializeDocutain(): Promise<boolean> {
  const initialized = await DocutainSDK.initSDK(
    '<YOUR-LICENSE-KEY>'
  );

  if (!initialized) {
    // Read the SDK error and keep Photo Payment disabled.
    const error: string = await DocutainSDK.getLastError();
    reportInitializationError(error);
  }

  return initialized;
}

Launch Photo Payment and classify the outcome

import DocutainSDK from '@docutain/react-native-docutain-sdk';

type DocutainError = { code?: string; message?: string };

async function startPhotoPayment(): Promise<void> {
  try {
    const paymentData = await DocutainSDK.startPhotoPayment({
      // Customize scan, analysis and theming when required.
    });

    if (paymentData === '') {
      // No data was found. This is reachable when the
      // Empty Result Screen has been disabled.
      showManualEntry();
      return;
    }

    // Decode the JSON, apply app rules and prefill a draft.
    processPaymentData(paymentData);
  } catch (unknownError) {
    const error = unknownError as DocutainError;
    if (error.code === 'CANCELED') {
      return; // Expected user cancellation.
    }
    reportPhotoPaymentError(error);
  }
}

Do not report CANCELED as an application failure. Treat every other rejection as an integration or runtime error and keep sensitive invoice values out of telemetry.

Decode the JSON into a typed payment draft

{
  "Address": {
    "Name1": "Sanitär Krause",
    "Zipcode": "56068",
    "City": "Koblenz",
    "Street": "Musterstraße 17",
    "Bank": [{
      "BIC": "MALADE51KOB",
      "IBAN": "DE58570501200094710328"
    }]
  },
  "Date": "2026-04-17",
  "Amount": "359.44",
  "InvoiceId": "2026-0417",
  "Reference": "Invoice 2026-0417",
  "PaymentState": "ToBePaid",
  "SEPACreditor": "Sanitär Krause"
}

SEPACreditor is the payment recipient. Model fields as optional because invoices differ. The SDK returns only valid IBANs, but the application must still verify the intended recipient, amount and reference and show all payment values before authorization.

Configure analysis, UX and retry behavior

The configuration object exposes analysis, capture behavior, page editing, onboarding, Scan Tips, colors and the Empty Result Screen. Keep defaults during the first quality evaluation and change only requirements that belong to the host app's user journey.

const paymentData = await DocutainSDK.startPhotoPayment({
  analyzeConfig: {
    // Add the optional paid/to-be-paid classification.
    readPaymentState: true,
  },
  // The default Empty Result Screen offers retry and cancel.
});

BIC extraction can be disabled when the payment model does not use it; account for the resulting JSON shape in the mapper. GiroCode and invoice OCR remain one Photo Payment flow, so users do not need to choose a scanner first.

Test JavaScript state and both native implementations

  • Start with the Android and iOS Showcase Apps, then use a trial license in the React Native app.
  • Use the same approved invoice corpus on representative physical Android and iOS devices.
  • Measure field-level correctness and manual corrections for recipient, IBAN, amount and reference.
  • Test paper, screen and file inputs as well as invoices with and without GiroCode.
  • Verify cancellation, empty result, initialization failure, bridge errors and retry/manual entry.
  • Test app backgrounding, repeated launches, navigation teardown and prevention of double taps.
  • Run TalkBack and VoiceOver checks around the native flow and the returned payment form.

Official resources

Technical sources last checked on September 13, 2026.

FREQUENTLY ASKED QUESTIONS

React Native Photo Payment integration




Contact us and receive your quote

Our pricing is tailored to your use case. Let our colleague Harry Beck know how we can help and receive your quote.




Information about how we process your details is available in our Privacy Policy.