Skip to main content

Verify Users

The Mizuhiki SDK offers a simple and convenient way to complete compliant Electronic Know Your Customer (eKYC) verification in Japan. We provide pre-built UIs you can use to guide your users through the verification process.

Make sure you have already completed the SDK installation steps from our Getting Started guide.

1. Initialize the SDK

Create an SDK instance (mock or production) by passing in your project ID obtained from JSC. You can use this SDK instance to access all Mizuhiki ID functionality.

Required: Replace YOUR_PROJECT_ID with the actual project ID provided by JSC during beta access setup.

import MizuhikiCore
import MizuhikiMock
import Mizuhiki

// Define your app environment with Mizuhiki client
class AppEnvironment: ObservableObject {
// Replace with your actual project ID from JSC
private let mizuhikiProjectId = "YOUR_PROJECT_ID"

lazy var mizuhiki: IdentityClient = {
#if DEBUG
// Use mock environment for development and testing
return MizuhikiMock.makeClient(projectId: mizuhikiProjectId)
#else
// Use production environment for release builds
return Mizuhiki.makeClient(projectId: mizuhikiProjectId)
#endif
}()

// Shared instance for app-wide usage
static let shared = AppEnvironment()
}

// Usage in SwiftUI
struct ContentView: View {
@StateObject private var appEnv = AppEnvironment.shared

var body: some View {
VStack {
Text("Mizuhiki SDK Ready")
// Use appEnv.mizuhiki for all Mizuhiki operations
}
.environmentObject(appEnv)
}
}

Important Notes:

  • 🔑 Project ID: Must match the ID provided in your JSC credentials
  • 🏗️ Environment: Mock for development, Production for release
  • 💾 Instance Management: Create one client instance per app session
  • 🔄 Lifecycle: Client handles connection management automatically

2. Use the built-in Mizuhiki UIs to complete KYC

The Mizuhiki SDK comes with a pre-built UI flow to guide users through the KYC process.

The KYC process includes the following screens:

  1. Introduction screen with explanation of the process
  2. Password entry screen
  3. MyNumber card scanning instructions
  4. NFC scanning in progress
  5. Success screen

User information format

note

After successful KYC, the SDK returns the user's personal information (name, date of birth, address, gender) encrypted as a JWE object.
Send this JWE to your backend for decryption and processing. Do not decrypt user information (PII) in the mobile app.

ParameterTypeRequiredDescriptionExample
addressStringYesResidential address徳島県板野町犬伏9番8
dateOfBirthStringYesDate of birth in western calendar2000-12-25
fullNameStringYesFull name山中 逸穂
genderEnum (female | male | other)YesGendermale
import MizuhikiCore
import MizuhikiUI

struct ContentView: View {
@Environment(\.appEnv) private var appEnv

var body: some View {
VStack {
Button(action: kyc) {
Text("KYC")
.padding(8)
.fontWeight(.semibold)
.frame(maxWidth: .infinity)
}
}
}

@State private var signedUpUser: MizuhikiCore.User?
private func onSignUp() {
MizuhikiUIBridge.present(config: .init(client: appEnv.mizuhiki)) { event in
switch event {
case .didStart:
break
case .didFinish(let result):
self.signedUpUser = result.user
// submit the encrypted JWE to your backend for decryption and storage, see details in the next step
submitEncryptedPii(jwe: result.kycDetails)
case .didCancel:
break
}
}
}
}

3. Forward encrypted user information (JWE) to your backend

When KYC completes, your app receives encrypted user personal information in JWE format.
Pass it directly to your backend API over HTTPS.

// Example payload you send to your backend after successful KYC
struct KycResultPayload: Encodable {
let encryptedPiiJwe: String
}

func submitEncryptedPii(_ jwe: String) async throws {
let payload = KycResultPayload(encryptedPiiJwe: jwe)
// POST payload to your backend over HTTPS
}

4. Decrypt JWE on your backend

Use your private key generated during setup to decrypt the JWE and parse the user information payload.

Node.js example (jose)
import { compactDecrypt, CompactJWEHeaderParameters } from "jose";
import { createPrivateKey } from "node:crypto";

type KycPiiGender = "female" | "male" | "other";

interface KycPii {
// in ""徳島県板野町犬伏9番8" format
address: string;

// in "2000-12-25" basic ISO format
dateOfBirth: string;

// in "山中 逸穂" format
fullName: string;
gender: KycPiiGender;
}

interface DecryptedKycPii {
pii: KycPii;
protectedHeader: CompactJWEHeaderParameters;
}

export async function decryptMizuhikiPii(jwe: string): Promise<DecryptedKycPii> {
const privateKeyPem = process.env.MIZUHIKI_PII_PRIVATE_KEY_PEM;
if (!privateKeyPem) {
throw new Error("Missing MIZUHIKI_PII_PRIVATE_KEY_PEM");
}

const privateKey = createPrivateKey(privateKeyPem);
const { plaintext, protectedHeader } = await compactDecrypt(jwe, privateKey);

const json = new TextDecoder().decode(plaintext);
const pii = JSON.parse(json) as KycPii;

return { pii, protectedHeader };
}

Backend handling requirements:

  • Accept JWE only over TLS (HTTPS).
  • Decrypt only on trusted server infrastructure.
  • Avoid logging raw JWE or decrypted PII.
  • Apply least-privilege access controls to decrypted data.
KYC introduction screenMyNumber card passwordMyNumber card scanning instructionsMyNumber card scanningVerification success

Identity verification flow with the Mizuhiki ID

Next Steps

After completing KYC, you are ready to mint a Mizuhiki Verified SBT to the user's address

Continue to: SBT Minting Guide →

Troubleshooting

Common Issues and Solutions

Issue: NFC Permission Denied

  • Symptoms: App crashes when attempting to scan MyNumber card
  • iOS Solution:
    1. Verify NFC capability is added in Xcode project settings
    2. Check Info.plist contains NFCReaderUsageDescription
    3. Ensure device supports NFC (iPhone 7+ for NFC reading)
  • Android Solution:
    1. Add <uses-permission android:name="android.permission.NFC" /> to AndroidManifest.xml
    2. Verify device has NFC hardware and it's enabled in settings

Issue: Card Not Detected

  • Symptoms: NFC scanning doesn't detect the card
  • Solutions:
    1. Remove card from wallet/case - avoid interference
    2. Hold card steady against device's NFC area for at least 5 seconds
    3. Try different positioning - NFC antenna location varies by device
    4. Ensure card is not damaged or demagnetized

Authentication Issues

Issue: Invalid Project ID

  • Symptoms: Authentication errors during SDK usage ("message": "permission denied: invalid x-project-id")
  • Solution: Verify project ID matches exactly the one provided by JSC (case-sensitive)

Issue: Mock Environment Card Rejection

  • Symptoms: Valid FeliCa card rejected in mock environment
  • Solution:
    1. Confirm using mock SDK version (mizuhiki-adapter-mock)
    2. Use password ABC123 for all mock cards
    3. Verify card is FeliCa or ISO/IEC 14443-4 Type-A compatible

Issue: Production Password Lock

  • Symptoms: MyNumber card becomes unusable after failed attempts
  • Solution:
    1. Visit convenience store (7-Eleven, FamilyMart) with card and ID
    2. Use card reader terminal to unlock with PIN reset procedure
    3. Alternative: Visit city hall for manual unlock process

Integration Issues

Issue: Build Errors with Package Registry

  • Symptoms: Cannot resolve Mizuhiki SDK dependencies
  • iOS Solution:
    # Re-authenticate with package registry
    swift package-registry login https://swift.cloudsmith.io/jsc/mizuhiki/ --token YOUR_TOKEN --no-confirm

    # Clear Xcode derived data
    rm -rf ~/Library/Developer/Xcode/DerivedData
  • Android Solution:
    # Verify environment variable is set
    echo $MIZUHIKI_TOKEN

    # Clean and rebuild project
    ./gradlew clean
    ./gradlew build

Issue: UI Bridge Not Responding

  • Symptoms: KYC UI doesn't appear or callbacks not triggered
  • iOS Solution:
    1. Ensure UI calls are on main thread
    2. Verify MizuhikiUI framework is imported
    3. Check if client instance is properly initialized
  • Android Solution:
    1. Verify context is valid Activity context
    2. Check if UI permissions are granted
    3. Ensure client is created before UI presentation

Getting Help

If you encounter issues not covered here:

  1. Check SDK Version: Ensure you're using the latest SDK version
  2. Contact Support: Email [email protected] with:
    • SDK version and platform (iOS/Android)
    • Environment (mock/production)
    • Complete error messages and stack traces
    • Minimal reproduction code example