# Billing Mutuelle de la Corse from an iPhone

> How health professionals bill Mutuelle de la Corse from their iPhone: the camera fills in a patient's number only after reading the same valid number five times, and only the insurer's answer confirms an invoice.

- Context: GoodBarber · Client project
- Published: 2026-06-17 · Updated: 2026-09-29
- Reading time: 7 min
- Canonical: https://lanfranchistephane.dev/articles/mutuelle-de-la-corse/

## System at a glance

1. Scan or type — Carte Vitale photo, or the keyboard
2. Patient — Number checked, birth date added
3. Invoice — Procedure, amount, date, and place
4. Insurer's server — Creates the invoice, or refuses it
5. Confirmation — Receipt to download and share

## At a glance

- Role: iOS engineer who set up the app and built its billing journey: card scanner, patient sheet, billing screen, and the requests that send an invoice and fetch its receipt.
- Challenge: Let the camera save typing without ever filling in a misread number, and never show an invoice as sent before the insurer has created it.
- Outcome: The camera fills in a number only after five matching, valid reads, typing always works, and only the server's answer opens the confirmation.

## What was at stake

### Scanning a card should save typing, never slip in a wrong number.

Mutuelle de la Corse is a health insurer. Its iPhone app lets health professionals bill it for a procedure: identify the patient, choose the procedure, check the amount, and send. GoodBarber built the app for the insurer in UIKit. The app is in French, so its words are quoted here in French, with a translation.

The patient is identified by their social security number, printed on their Carte Vitale (the French health insurance card). The number is 15 characters long. The camera can save typing it, but a camera can misread a digit. And once the professional taps "Valider" (confirm), the app must not say the invoice is sent until the insurer's server has created it.

**My responsibility — the billing journey.** I set up the project and built the card scanner, the patient sheet, the billing screen, the requests that send an invoice and download its receipt, the invoice history, and what happens when a session expires. Teammates built sign-in, two-step authentication, and the confirmation screen, where I added the receipt download. A teammate wrote the check on the social security number; I extended it for the scanner.

## One journey, five steps

The home screen, "Facturer un acte" (bill a procedure), has two buttons: one photographs the patient's Carte Vitale, the other opens manual entry. Both lead to the same patient sheet, then to the same billing screen.

<picture>
  <source media="(max-width: 720px)" srcset="https://lanfranchistephane.dev/articles/mutuelle-de-la-corse/billing-workflow-narrow.svg">
  <img src="https://lanfranchistephane.dev/articles/mutuelle-de-la-corse/billing-workflow.svg" width="960" height="330" loading="lazy" decoding="async" alt="One invoice in five steps: the professional photographs the patient's Carte Vitale or types the number; the patient sheet checks the number and adds the date of birth; the billing screen shows the procedure, amount, date, and place; the insurer's server creates the invoice or refuses it; only then does the confirmation offer the receipt. If the server refuses, the billing screen stays as it was, with every value in place.">
</picture>

## 1. Read the card on the iPhone

The camera needs the professional's permission. If it is refused, an alert offers a button to Settings, and manual entry is still there on the home screen.

The scanner shows a card-shaped frame. Apple's Vision framework reads the text inside that frame only, on the iPhone itself: no picture is saved or sent. For each piece of text, Vision offers up to three guesses. A guess counts only if it has the shape of a social security number and its control key is right. The control key is the last two digits, computed from the thirteen before them, so a single misread digit breaks it.

```pseudo title="When the camera accepts a number"
for each camera frame:
  read the text inside the card frame
  for each of Vision's three best guesses:
    if it is not shaped like a social security number:
      ignore it
    if its control key is right:
      count one more sighting of this number
      after 5 sightings: close the camera and fill in the patient sheet
    if its control key is wrong:
      count one more sighting of this wrong number
      after 5 sightings: stop, and say the number is invalid
```

Five sightings of the same number keep one bad frame from deciding. When a number keeps failing its check, the card or the reading is the problem, so the scanner stops, says the number is invalid, and offers to read the card again or cancel.

People born in Corsica have 2A or 2B in their number, for their department of birth. The check turns these letters into digits before computing the key.

## 2. Check the patient

The patient sheet, "Informations", asks for the date of birth, picked in a calendar, the social security number, and, for twins, their birth rank. After a scan, the number is already filled in, and it can still be corrected. The date of birth is always entered by the professional.

The number is spaced into its usual groups as it is typed. A check mark appears once it passes the check, and leaving the field with a wrong number shows an error under it. "Suivant" (next) stays disabled until the date of birth, the number, and the birth rank, if added, are all valid.

## 3. Review the invoice

The billing screen, "Montant de la facture" (invoice amount), gathers the invoice:

- **The procedure**, picked from the professional's own list. Each professional sets that list in their account, with a price for each procedure. The procedure sent last time is selected first.
- **The amount**, the procedure's price. "Modifier le montant" (change the amount) edits it for this invoice only, up to five digits plus two decimals.
- **The date, time, and place**, filled in automatically: now, and the iPhone's approximate location if the professional allowed it. Otherwise the screen says there is no location.
- **The patient**: number, date of birth, and birth rank, shown for a last look. They cannot be edited here. To change them, the professional goes back and fills in the sheet again.

If the professional's list of procedures is empty, this screen does not open. The app says information is missing and offers to open the account. "Valider" is enabled as soon as a procedure and an amount are set.

## 4. Let the server decide

Tapping "Valider" sends one request, with the session of the signed-in professional. The number goes without its spaces, the birth rank only when there is one, the time of sending, and the place only when the iPhone knows it.

```pseudo title="Send the invoice"
send the invoice with the professional's session
if the server created it:
  remember this procedure for next time
  open the confirmation
if the server rejected the session:
  delete the saved account and invoice history from the iPhone
  go back to sign-in, saying the session has expired
if anything else went wrong:
  show an error, and stay on the billing screen with every value in place
```

Nothing looks like success before the server answers. After an error, the billing screen is exactly as it was, so the professional taps "Valider" again without entering anything twice. The app also checks the session each time it comes back to the foreground.

## 5. Confirm, then hand over the receipt

Only the server's success opens the confirmation: "Merci ! Votre facture a bien été soumise." (Thank you! Your invoice has been submitted.) The server's answer includes a link to the receipt. "Télécharger un justificatif" (download a receipt) fetches that PDF with the professional's session and opens the share sheet, to save it or send it on. The file sits in a temporary folder and is deleted when the professional taps OK to go back home.

On the home screen, "Historique" (history) lists the invoices already sent, a page at a time. A sent invoice cannot be changed in the app. Tapping one offers "Signaler une erreur" (report an error), which prepares an email to the insurer about that invoice.

## When things do not go to plan

| What happens | What the professional sees |
|---|---|
| Camera access is refused | An alert with a button to Settings; manual entry still works |
| The camera cannot read the card | Nothing is filled in; "Annuler" (cancel) goes back to the home screen |
| The server returns an error | An error message; the billing screen keeps every value |
| The session has expired | Back to sign-in, with a message saying so |
| The receipt download fails | An error message; the invoice itself was already created |
| A mistake is found after sending | "Signaler une erreur" prepares an email to the insurer |

## Trade-offs

- **Five matching reads are slower than one.** The camera waits for the same valid number five times, and the date of birth is always entered by hand. In return, a scanned number has been read the same way five times and has passed its check.
- **The check catches a misread, not a mix-up.** A number with a correct key can still belong to someone else, so the patient's details stay on the billing screen for a last look. Correcting them there means going back to the sheet, the one place where they are entered and checked.
- **Nothing is saved before the server has it.** A failed invoice stays on screen, but it is not stored: if the app is closed, it must be entered again. In return, the history only ever shows invoices the insurer has.

## Related

- [One Subscription Flow for Thousands of Apps](https://lanfranchistephane.dev/articles/in-app-purchase-infrastructure/) — GoodBarber · Platform, 6 min read. How GoodBarber apps sell subscriptions: one shared service shows only what Apple can sell, lets the server confirm every purchase, and unlocks the same access on every screen.
- [Asking for Age Before Asking to Track](https://lanfranchistephane.dev/articles/privacy-feature-gates/) — GoodBarber · Platform, 7 min read. How GoodBarber apps ask for a person's age range before any tracking prompt, keep people under 16 away from ad networks, third-party analytics, and location, and check that answer again each time one of them runs.
