PaymentSheetEvent.fromJson constructor

PaymentSheetEvent.fromJson(
  1. Map<Object?, Object?> value
)

Parses and validates a lifecycle event from the native bridge.

Implementation

factory PaymentSheetEvent.fromJson(Map<Object?, Object?> value) {
  const baseFields = {'type', 'occurredAt', 'flowId', 'sequence'};
  final rawType = value['type'];
  final rawOccurredAt = value['occurredAt'];
  final flowId = value['flowId'];
  final sequence = value['sequence'];
  final type = rawType is String
      ? PaymentSheetEventType.fromWireValue(rawType)
      : null;
  final occurredAt = rawOccurredAt is String
      ? DateTime.tryParse(rawOccurredAt)
      : null;
  if (type == null ||
      occurredAt == null ||
      flowId is! String ||
      !_uuidPattern.hasMatch(flowId) ||
      sequence is! int ||
      sequence < 1) {
    throw const FormatException('Invalid payment sheet lifecycle event');
  }

  final extraFields = switch (type) {
    PaymentSheetEventType.presented || PaymentSheetEventType.ready =>
      const <String>{},
    PaymentSheetEventType.change => const {'complete', 'paymentMethod'},
    PaymentSheetEventType.orderPrepared ||
    PaymentSheetEventType.paymentAttemptStarted ||
    PaymentSheetEventType.paymentProcessing ||
    PaymentSheetEventType.completed =>
      const {'order'},
    PaymentSheetEventType.paymentActionRequired => const {'order', 'action'},
    PaymentSheetEventType.paymentAttemptFailed => const {'order', 'failure'},
    PaymentSheetEventType.canceled => const {'order'},
    PaymentSheetEventType.failed => const {'order', 'failure'},
  };
  _expectFields(value, {...baseFields, ...extraFields});

  final rawOrder = value['order'];
  final rawAction = value['action'];
  final rawFailure = value['failure'];
  final complete = value['complete'];
  final paymentMethod = value['paymentMethod'];
  final order = rawOrder is Map
      ? CheckoutOrder.fromJson(Map<Object?, Object?>.from(rawOrder))
      : null;
  final action = rawAction is Map
      ? CheckoutAction.fromJson(Map<Object?, Object?>.from(rawAction))
      : null;
  final failure = rawFailure is Map
      ? CheckoutFailure.fromJson(Map<Object?, Object?>.from(rawFailure))
      : null;

  final valid = switch (type) {
    PaymentSheetEventType.presented || PaymentSheetEventType.ready => true,
    PaymentSheetEventType.change =>
      complete is bool &&
          (paymentMethod == null || paymentMethod == 'mobile_money'),
    PaymentSheetEventType.orderPrepared ||
    PaymentSheetEventType.paymentAttemptStarted ||
    PaymentSheetEventType.paymentProcessing ||
    PaymentSheetEventType.completed =>
      order != null,
    PaymentSheetEventType.paymentActionRequired =>
      order != null && action != null,
    PaymentSheetEventType.paymentAttemptFailed =>
      order != null && failure != null,
    PaymentSheetEventType.canceled => rawOrder == null || order != null,
    PaymentSheetEventType.failed => failure != null,
  };
  if (!valid ||
      (rawOrder != null && order == null) ||
      (rawAction != null && action == null) ||
      (rawFailure != null && failure == null)) {
    throw const FormatException('Invalid payment sheet lifecycle event');
  }

  return PaymentSheetEvent(
    flowId: flowId,
    sequence: sequence,
    type: type,
    occurredAt: occurredAt,
    order: order,
    action: action,
    failure: failure,
    complete: complete as bool?,
    paymentMethod: paymentMethod as String?,
  );
}