# PINs, overrides, alerts and onboarding: 4.23-4.27

Behaviour the specs don't define (simulator choices). Back to the [index](README.md).

PIN Retrieval (4.23):
- A card with no recorded date of birth (the seed card, cards bought
  without `customerInfo.dob`) accepts any well-formed `dob`.
- Wrong values → `103` ("Invalid CVV/expire Date/DOB"), the one code the
  spec has for all three. Missing or malformed ones (`expiryDate` not 4
  digits, `cvv2` not 3, `dob` not 8) → `11`.
- Active (`I`) and inactive (`M`) cards qualify, so a PIN can be read before
  activation. Locked → `CRDLKD`, hot-listed → `CRDBLO`, closed → `CRDCLD`.
- There are no retry limits: wrong guesses don't lock the card.

ATM PIN Verification (4.24):
- The spec has no code for a wrong PIN, so it gets `104` ("Invalid
  EPinBlock"), the same as a block that doesn't decrypt to a format-0 block
  for that card.
- `dob` is checked as in PIN Retrieval: a card with none recorded accepts
  any; a malformed one → `11`.
- The same card statuses qualify as for PIN Retrieval, and there are no
  retry limits either.

ATM PIN Change (4.25):
- The table names the fields `eoldPinBlock` / `enewPinBlock`; the sample
  sends `epinBlockOld` / `epinBlockNew`. Both are accepted.
- A wrong, missing or invalid old block, or a missing or invalid new block,
  → `104`. The spec has no separate codes for these.
- There's no `dob` check, as the request has none. The new PIN may equal
  the old one.
- The same card statuses qualify as for PIN Retrieval.

Assign Override Settings (4.26):
- Campaigns are defined in the real system's portal, so they come from
  `:campaigns` config. Campaigns override fees and limits, which the
  simulator doesn't have, so an assignment is only recorded; nothing else
  changes.
- The spec says one campaign is assigned to one product, so an account
  holds at most one: assigning another replaces it. `N` removes the named
  campaign if the account has it, and succeeds either way, as the sample
  (`flag` `N` on a card with no campaign) does.
- The campaign's dates are inclusive. Before the start → `INCPDT`; after
  the end → `INVCMP`, since the spec has no code for an ended campaign.
- The card must have an open account for `productCode` (`INPDID` /
  `ACCCLD`). Any card status but closed is accepted. A `flag` other than
  `Y` / `N` → `11`.
- The response is `txnRefNo` and the response code only, as the table
  says; errors also echo `proxyNumber`, like other endpoints.

Alert Settings (4.27):
- No SMS or email is ever sent, so settings are only recorded. Each account
  has one setting per `alertType`; setting it again replaces it, and `N`
  removes it (and succeeds if there was none).
- The spec's rules are enforced: `DLY` / `WLY` only for `LOWBAL`, `TXN`
  only for the others, and `MLY` / `YLY` (reserved for future use) refused.
  Anything else, including the sample's `alertType` `aLTSET`, → `11`.
- `alertData` is the threshold in minor units, as the spec's example says
  (`000000000200` is 2 units): 1–12 digits (`11` otherwise). It's required
  only to set a `LOWBAL` alert, and ignored for other types.
- The card must have an open account for `productCode` (`INPDID` /
  `ACCCLD`). Any card status but closed is accepted.

Notification and onboarding:
- The notification response body is invented. QRMiddleLayer only looks at the
  HTTP status (2xx = delivered).
- Onboarding follows Alipay+, which uses the same paths and signing scheme:
  `result.resultCode` / `resultStatus` / `resultMessage`, with HTTP 200 for
  errors too. Errors are `INVALID_SIGNATURE` (missing, malformed or wrong
  signature) and `PARAM_ILLEGAL` (bad body or missing field).
- The signature covers the path without the `/naradaapiservices/yse` prefix,
  which is how QRMiddleLayer's `YspProvider` signs it.
