Skip to main content

otp_flutter 0.3.0 copy "otp_flutter: ^0.3.0" to clipboard
otp_flutter: ^0.3.0 copied to clipboard

Phone and email verification for Flutter, over the native otp.com SDKs. Requires iOS 15 and Android API 26.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:otp_flutter/otp_flutter.dart';

void main() {
  runApp(const OtpExampleApp());
}

class OtpExampleApp extends StatelessWidget {
  const OtpExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(home: OtpExampleScreen());
  }
}

/// A menu in front of the bridge, so each call can be made on a device.
///
/// Nothing here is part of the package. It is the app a customer would write, and it uses only
/// what a customer can see.
class OtpExampleScreen extends StatefulWidget {
  const OtpExampleScreen({super.key});

  @override
  State<OtpExampleScreen> createState() => _OtpExampleScreenState();
}

class _OtpExampleScreenState extends State<OtpExampleScreen> {
  // Blank means the SDK's own host, https://api.otp.com. This field exists to point at a local or
  // staging backend instead: an emulator shares the machine's loopback, so it reaches a backend
  // running here, while a physical device needs the machine's address on the network instead.
  final _baseUrlController = TextEditingController();
  final _publishableKeyController = TextEditingController(
    text: 'otp_pk_test_…',
  );
  final _recipientController = TextEditingController(text: '+14155552671');
  final _codeController = TextEditingController();

  PendingOtp? _pending;
  String _outcome = '';

  Future<void> _report(String label, Future<Object?> Function() call) async {
    setState(() => _outcome = '$label…');
    try {
      final result = await call();
      setState(() => _outcome = '$label: $result');
    } on OtpException catch (error) {
      // Every call in the package throws this and nothing else, which is what makes a screen
      // like this able to branch rather than guess.
      setState(() {
        _outcome =
            '$label failed: ${error.kind.name}'
            '${error.type != null ? ' (${error.type})' : ''}'
            '${error.retryAfterSeconds != null ? ', retry after ${error.retryAfterSeconds}s' : ''}'
            '\n${error.message}';
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('otp.com bridge')),
      body: SafeArea(
        child: ListView(
          padding: const EdgeInsets.all(16),
          children: [
            const Text(
              'base url',
              style: TextStyle(fontSize: 12, color: Colors.grey),
            ),
            TextField(
              controller: _baseUrlController,
              decoration: const InputDecoration(
                hintText: 'https://api.otp.com',
              ),
            ),
            const Text(
              'publishable key',
              style: TextStyle(fontSize: 12, color: Colors.grey),
            ),
            TextField(controller: _publishableKeyController),
            const Text(
              'recipient',
              style: TextStyle(fontSize: 12, color: Colors.grey),
            ),
            TextField(controller: _recipientController),
            const SizedBox(height: 8),
            ElevatedButton(
              onPressed: () => _report(
                'configure',
                () => Otp.configure(
                  publishableKey: _publishableKeyController.text,
                  baseUrl: _baseUrlController.text.trim().isEmpty
                      ? null
                      : _baseUrlController.text.trim(),
                ),
              ),
              child: const Text('configure'),
            ),
            const SizedBox(height: 16),
            const Text(
              'Presented screens',
              style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
            ),
            ElevatedButton(
              onPressed: () => _report(
                'verify',
                () => Otp.verify(_recipientController.text, locale: 'en'),
              ),
              child: const Text('verify'),
            ),
            ElevatedButton(
              onPressed: () => _report(
                'verifyCollecting',
                () => Otp.verifyCollecting(RecipientKind.phone, locale: 'en'),
              ),
              child: const Text('verify, collecting a phone number'),
            ),
            ElevatedButton(
              onPressed: () => _report(
                'verifyCollecting',
                () => Otp.verifyCollecting(RecipientKind.email, locale: 'en'),
              ),
              child: const Text('verify, collecting an email address'),
            ),
            ElevatedButton(
              onPressed: () =>
                  _report('resumeInterrupted', () => Otp.resumeInterrupted()),
              child: const Text('resume an interrupted verification'),
            ),
            const SizedBox(height: 16),
            const Text(
              'Your own screen',
              style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
            ),
            ElevatedButton(
              onPressed: () => _report('start', () async {
                final started = await Otp.start(
                  _recipientController.text,
                  locale: 'en',
                );
                setState(() => _pending = started);
                return started;
              }),
              child: const Text('start'),
            ),
            Text(
              'code${_pending != null ? ' (${_pending!.codeLength} digits)' : ''}',
              style: const TextStyle(fontSize: 12, color: Colors.grey),
            ),
            TextField(
              controller: _codeController,
              keyboardType: TextInputType.number,
            ),
            ElevatedButton(
              onPressed: () => _report(
                'submit',
                () => Otp.submit(_pending?.id ?? '', _codeController.text),
              ),
              child: const Text('submit'),
            ),
            ElevatedButton(
              onPressed: () =>
                  _report('resend', () => Otp.resend(_pending?.id ?? '')),
              child: const Text('resend'),
            ),
            ElevatedButton(
              onPressed: () =>
                  _report('resume', () => Otp.resume(_pending?.id ?? '')),
              child: const Text('resume'),
            ),
            ElevatedButton(
              onPressed: () => _report('interrupted', () => Otp.interrupted()),
              child: const Text('what is in flight'),
            ),
            const SizedBox(height: 20),
            Text(
              _outcome,
              style: const TextStyle(fontFamily: 'monospace', fontSize: 12),
            ),
          ],
        ),
      ),
    );
  }
}
2
likes
0
points
432
downloads

Publisher

verified publisherotp.com

Weekly Downloads

Phone and email verification for Flutter, over the native otp.com SDKs. Requires iOS 15 and Android API 26.

Homepage
Repository (GitHub)
View/report issues

Topics

#otp #verification #sms #authentication #whatsapp

License

unknown (license)

Dependencies

flutter, meta

More

Packages that depend on otp_flutter

Packages that implement otp_flutter