Skip to content

CryptoOnramp SDK: Example App L0 KYC Setting + Initial Routing Behavior#6198

Merged
mliberatore merged 6 commits into
masterfrom
mliberatore/crypto-onramp-l0-kyc-setting-and-initial-routing
Mar 17, 2026
Merged

CryptoOnramp SDK: Example App L0 KYC Setting + Initial Routing Behavior#6198
mliberatore merged 6 commits into
masterfrom
mliberatore/crypto-onramp-l0-kyc-setting-and-initial-routing

Conversation

@mliberatore

@mliberatore mliberatore commented Mar 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

Note

This builds off of changes in #6191, which should be reviewed first.

Introduces a setting at the root level to enable KYC L0 mode (requires the livemode setting to be on).

  • When on, the KYC info collection that occurs after auth pushes the user into L0 collection mode, which makes the SSN + DOB fields optional. The actual form work is done in CryptoOnramp SDK: Adds Data Collection Modes to KYCInfoView for L0 KYC Support #6191, this just makes use of it.
  • The KYC form now reports back the collected KYC level so the flow coordinator can store it and use that state for advancing to the right step.
  • In L0 mode, the identity verification is skipped during the auth flow.
    • It will later be shown just-in-time on onramp session creation, as will the L1 step-up form, if needed. That work is not a part of this PR.

Here's the setting:

livemode off livemode on, L0 mode off livemode on, L0 mode on

Motivation

https://docs.google.com/document/d/1PAjI3bl3S_h3630TpZ012-wn4k6lQJlFyxaX3cmTRhE/edit?tab=t.0#heading=h.lnqfcyy21mit

Testing

  1. Turned off the simulator checks so that I can test the livemode toggle on the simulator.
  2. Tested the new setting, ensuring it was always disabled when livemode was off, enabled when livemode was on, and that the new setting was properly toggle-able.
  3. With the new setting off, ran through an entire signup -> checkout flow to ensure everything still functioned as it does on master. When completing the KYC submission form, ensured that the value passed back in the completion handler was level1 since all L0 and L1 fields were filled. Also ensured that identity verification occurred right after KYC collection, as expected.
  4. With the new setting on, ran through signup -> wallet selection, including the L0 KYC collection. I ensured that SSN and DOB were optional, I didn't fill them, and ensured that level0 was reported on completion. I also ensured that the identity verification was not shown after KYC collection, as expected.
  5. With the new setting on, ran through signup -> wallet selection again, but this time filled the SSN and DOB fields to ensure that level1 was reported on completion.

Changelog

N/A Example app changes only.

@@ -0,0 +1,44 @@
//
// KYCLevel.swift

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's not clear from this PR alone, note that this differs from the mode introduced in #6191 which is used to configure what fields are shown and which are optional in the KYCInfoView. This represents the full spectrum of a user's possible KYC levels, which also incorporates identity verification, which is not a part of the form.

A real merchant app won't need to juggle this distinction between "the old way" and supporting L0 KYC. A L0 KYC supporting app, instead, would just collect the minimal necessary fields, and during the "step-up" process (not yet introduced in PR) collect additional information if needed. I call this out, as there's no intention to introduce this level model to the SDK itself.

@mliberatore mliberatore requested a review from mats-stripe March 12, 2026 20:05
@mliberatore mliberatore marked this pull request as ready for review March 12, 2026 20:05
@mliberatore mliberatore requested review from a team as code owners March 12, 2026 20:05
Base automatically changed from mliberatore/crypto-onramp-l0-kyc-info-view-modes to master March 17, 2026 19:09
mats-stripe
mats-stripe previously approved these changes Mar 17, 2026
@mliberatore

Copy link
Copy Markdown
Collaborator Author

I‘ll rebase here since the changes from the base branch that were just merged are showing in the diff, and to resolve the conflict.

…nd-initial-routing

# Conflicts:
#	Example/CryptoOnramp Example/CryptoOnramp Example/KYCInfoView.swift
@mliberatore mliberatore requested a review from mats-stripe March 17, 2026 21:12
@mliberatore mliberatore merged commit cb7b1f0 into master Mar 17, 2026
7 checks passed
@mliberatore mliberatore deleted the mliberatore/crypto-onramp-l0-kyc-setting-and-initial-routing branch March 17, 2026 21:17
mliberatore added a commit that referenced this pull request Mar 18, 2026
## Summary

Adds step-up flow logic to the demo app for errors encountered related
to expected L0 KYC-related errors.

When creating an onramp session, we respond to certain error codes
returned from the backend and collect more KYC information as needed.

- L0 → L1: We collected L0 fields from the user after auth, but the
transaction requires L1. We present the KYC form with only SSN and DOB
fields to complete L1.
- L1 → L2: We collected L0 fields from the user after auth, and
potentially later collected L1 fields in the scenario above. However,
the transaction requires L2 (identity document verification). We present
the Identity flow to complete L2.
- L0 → L2: We collected L0 fields from the user after auth, but the
transaction requires L2. We present the KYC form with only SSN and DOB
fields, and then we push the identity flow afterwards to step up to L2.

## Motivation
<!-- Why are you making this change? If it's for fixing a bug, if
possible, please include a code snippet or example project that
demonstrates the issue. -->

https://docs.google.com/document/d/1PAjI3bl3S_h3630TpZ012-wn4k6lQJlFyxaX3cmTRhE/edit?tab=t.0#heading=h.lnqfcyy21mit

## Testing
Tested the step-up flow by disabling the livemode requirement, and
enabling the L0 KYC mode introduced in #6198, then getting to the
payment screen, and attempting to create onramp sessions. Note that
checkout will fail in livemode under these conditions, but starting the
onramp session at least allows us to respond to appropriate errors [when
we provide large transaction $$
amounts](https://lickability.slack.com/archives/C094P3BRBL1/p1773765260079949?thread_ts=1773760441.342059&cid=C094P3BRBL1).

Level 0 → Level 1 step-up, in response to
`crypto_onramp_missing_identity_verification` with L0 fields attached:


https://github.com/user-attachments/assets/10cabb4a-4f56-4bc7-a36e-c2a5d98f049c

Level 1 → Level 2 step-up, in response to
`crypto_onramp_missing_document_verification` with L1 fields attached:


https://github.com/user-attachments/assets/76aebd28-e53a-4092-89da-f6ebd3f7f8db

Level 0 → L2 step-up, in response to
`crypto_onramp_missing_document_verification` with L0 fields attached.
(Note that this scenario is simulated, as the backend is returning
`crypto_onramp_missing_identity_verification` [incorrectly at the
moment](https://lickability.slack.com/archives/C094P3BRBL1/p1773762790424179?thread_ts=1773760441.342059&cid=C094P3BRBL1).
I swapped the error check to force this scenario to test the 2-step
step-up process.):


https://github.com/user-attachments/assets/85685337-e1ae-435e-a69c-2b6fbf75a3f7

## Changelog
<!-- Is this a notable change that affects users? If so, add a line to
`CHANGELOG.md` and prefix the line with one of the following:
    - [Added] for new features.
    - [Changed] for changes in existing functionality.
    - [Deprecated] for soon-to-be removed features.
    - [Removed] for now removed features.
    - [Fixed] for any bug fixes.
    - [Security] in case of vulnerabilities.
-->
N/A, SDK is in Alpha
Twigz added a commit that referenced this pull request Apr 8, 2026
…6230)

## Summary
When a client's `PKPaymentRequest` specifies collection of name `.name`
and or `.postalAddress` in its billing contact fields, this information
is passed back to the caller on success of payment method collection.
This would allow clients to skip L0 KYC collection before a collecting
payment method, and when Apple Paying, they could choose to either
pre-fill a KYC data collection form, or simply call `attachKYCInfo`
passing in the resulting `KycInfo` instance.

This change required:
- New return type (`CollectPaymentMethodResult`) on
`collectPaymentMethod`. This also brings cancelation more in line with
other `*Result` types where cancelation is modeled as one of the
possible enum cases, rather than relying on return type optionality.
This is a breaking change.
- Adding (non-`public`) helper extensions to convert the data collected
by Apple Pay into `KycInfo`.
- Minimally adapting the example app to migrate to the new return type.
The example app _does not_ implement usage of the new `KycInfo` being
returned. More info on that in the Testing section below.
- Minor `README` update.

## Motivation
<!-- Why are you making this change? If it's for fixing a bug, if
possible, please include a code snippet or example project that
demonstrates the issue. -->
I don’t have a PRD for this, but this comes via [request from the crypto
team](https://lickability.slack.com/archives/C094P3BRBL1/p1772727381787439?thread_ts=1772726317.792319&cid=C094P3BRBL1).
To open the link in Stripe Slack, paste/send this Lickability Slack link
to Slackbot and it should convert it.

## Testing
<!-- How was the code tested? Be as specific as possible. -->
<!-- Ignored Tests: Did you newly ignore a test in this PR? If so,
please open an R4 incident so that the test can be re-enabled as soon as
possible-->
Adding the ability to exercise this from the example app requires more
thinking and more work. We currently support `livemode`, a new L0 KYC
Mode introduced in #6198, and to support filling KYC details via Apple
pay, we'd need to skip KYC info collection after auth, so that would
require a new mutually exclusive mode to L0 KYC Mode. I want to avoid
adding heavier conditional logic to accomplish this for the time being,
to keep the example app from becoming too complex as a reference point.

I did test this feature with the example app, however, by applying
temporary changes to the example app to allow for this to be exercised,
which can be seen in commit 43b06aa. To
test, I ran `git revert -n e0a517e` and
fixed conflicts (including the change from `completedWithKycInfo` to
`completed` in `attachKycInfoIfNeeded`. Then:

1. Launched the app and selected L0 KYC Mode from the menu on the sign
in screen.
2. Created a new account and filled out the OTP.
3. Saw that the KYC collection step was skipped.
4. Added a wallet address.
5. Selected a small $ amount from the payment screen.
6. Selected Apple Pay and completed payment (my contact has relevant
billing details).
7. Saw an onramp session creation failure. This is expected as L0 KYC
session creation does not work in testmode.
8. Checked my customer info to confirm that those fields were collected
successfully and I became KYC verified.


https://github.com/user-attachments/assets/a74bb2f8-035c-42cd-91e9-db2d0cd9ebef

1. Ran through the same test again with a large $ amount selected in
step 5 above.
2. After auto-attaching KYC, this triggered KYC step-up from L0 to L2.
3. Filled out just SSN + DOB, and completed ID document verification.
4. Tapped the menu option to fetch and display KYC info to ensure the
name and address appeared appropriately.
5. Checked my customer info to confirm that those fields were collected
successfully and I became KYC verified.


https://github.com/user-attachments/assets/466f3529-1bd7-4620-bed2-1249ad9d6373

## Changelog
<!-- Is this a notable change that affects users? If so, add a line to
`CHANGELOG.md` and prefix the line with one of the following:
    - [Added] for new features.
    - [Changed] for changes in existing functionality.
    - [Deprecated] for soon-to-be removed features.
    - [Removed] for now removed features.
    - [Fixed] for any bug fixes.
    - [Security] in case of vulnerabilities.
-->
N/A, Alpha SDK

---------

Co-authored-by: Andrew Harrison <Twigz@users.noreply.github.com>
Co-authored-by: Twig <aharris.1990@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants