Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 6 additions & 55 deletions Sample/lib/feature/checkout/checkout_screen.dart
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/src/painting/text_style.dart' as ts;
import 'package:logger/logger.dart';
import 'package:ottu_flutter_checkout/ottu_flutter_checkout.dart';
import 'package:ottu_flutter_checkout_sample/l10n/app_localizations.dart';

const _defaultCheckoutViewHeight = 200;
const _methodCheckoutHeight = "METHOD_CHECKOUT_HEIGHT";
const _methodPaymentSuccessResult = "METHOD_PAYMENT_SUCCESS_RESULT";
const _methodPaymentErrorResult = "METHOD_PAYMENT_ERROR_RESULT";
const _methodPaymentCancelResult = "METHOD_PAYMENT_CANCEL_RESULT";
const _methodChannel = MethodChannel('com.ottu.sample/checkout');

class CheckoutScreen extends StatefulWidget {
const CheckoutScreen({
super.key,
Expand All @@ -29,7 +21,6 @@ class CheckoutScreen extends StatefulWidget {
}

class _CheckoutScreenState extends State<CheckoutScreen> {
final ValueNotifier<int> _checkoutHeight = ValueNotifier<int>(_defaultCheckoutViewHeight);
final ValueNotifier<(String, String)> _checkoutMessage = ValueNotifier<(String, String)>((
"",
"",
Expand All @@ -49,41 +40,6 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
_checkoutMessage.removeListener(_showMessageDialog);
}

@override
void didChangeDependencies() {
super.didChangeDependencies();
_methodChannel.setMethodCallHandler((call) async {
switch (call.method) {
case _methodCheckoutHeight:
{
int height = call.arguments as int;
logger.d("didChangeDependencies, height: $height");
_checkoutHeight.value = height;
}
case _methodPaymentSuccessResult:
{
String message = call.arguments as String;
logger.d("didChangeDependencies, success: $message");
_checkoutMessage.value = ("Success", message);
}

case _methodPaymentCancelResult:
{
String message = call.arguments as String;
logger.d("didChangeDependencies, cancel: $message");
_checkoutMessage.value = ("Cancel", message);
}

case _methodPaymentErrorResult:
{
String message = call.arguments as String;
logger.d("didChangeDependencies, error: $message");
_checkoutMessage.value = ("Error", message);
}
}
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
Expand Down Expand Up @@ -111,17 +67,12 @@ class _CheckoutScreenState extends State<CheckoutScreen> {
//End of Merchant content
Padding(
padding: const EdgeInsets.all(12.0),
child: ValueListenableBuilder<int>(
builder: (BuildContext context, int height, Widget? child) {
return SizedBox(
height: height.toDouble(),
child: OttuCheckoutWidget(
arguments: widget.checkoutArguments,
verifyPayment: _verifyPayment,
),
);
},
valueListenable: _checkoutHeight,
child: OttuCheckoutWidget(
arguments: widget.checkoutArguments,
verifyPayment: _verifyPayment,
successCallback: (message) => _checkoutMessage.value = ("Success", message),
cancelCallback: (message) => _checkoutMessage.value = ("Cancel", message),
errorCallback: (message) => _checkoutMessage.value = ("Error", message),
),
),
const SizedBox(height: 20),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@ private const val METHOD_CHECKOUT_HEIGHT = "METHOD_CHECKOUT_HEIGHT"
private const val METHOD_PAYMENT_SUCCESS_RESULT = "METHOD_PAYMENT_SUCCESS_RESULT"
private const val METHOD_PAYMENT_ERROR_RESULT = "METHOD_PAYMENT_ERROR_RESULT"
private const val METHOD_PAYMENT_CANCEL_RESULT = "METHOD_PAYMENT_CANCEL_RESULT"
private const val METHOD_ON_WIDGET_DETACHED = "METHOD_ON_WIDGET_DETACHED"
private const val METHOD_VERIFY_PAYMENT = "METHOD_VERIFY_PAYMENT"
private const val CHANNEL = "com.ottu.sample/checkout"
private const val CHANNEL_PAYMENT_VERIFY = "com.ottu.sample/checkout/payment/verify"
private const val TAG = "CheckoutView"

private val sessionCoroutineExceptionHandler = CoroutineExceptionHandler { _, t ->
Expand All @@ -67,8 +67,6 @@ internal class CheckoutView(
private val arguments: CheckoutArguments,
) : PlatformView {
private val methodChannel: MethodChannel
private val methodChannelVerifyPayment: MethodChannel

private val checkoutView: FrameLayout = LayoutInflater.from(context)
.inflate(R.layout.fragment_checkout_wrapper_view, null) as FrameLayout

Expand All @@ -80,7 +78,6 @@ internal class CheckoutView(
)
checkoutView.layoutParams = vParams
methodChannel = MethodChannel(messenger, CHANNEL)
methodChannelVerifyPayment = MethodChannel(messenger, CHANNEL_PAYMENT_VERIFY)
}

override fun getView(): View = checkoutView
Expand All @@ -95,6 +92,14 @@ internal class CheckoutView(
override fun onFlutterViewAttached(flutterView: View) {
super.onFlutterViewAttached(flutterView)

methodChannel.setMethodCallHandler { call, _ ->
when (call.method) {
METHOD_ON_WIDGET_DETACHED -> {
Log.d(TAG, "onFlutterViewAttached, handle onWidgetDetached")
}
}
}

Log.i(TAG, "onFlutterViewAttached, isCheckoutInitializing: ${isCheckoutInitializing.get()}")
if (isCheckoutInitializing.getAndSet(true).not()) {
val fa = checkoutView.context as FragmentActivity
Expand Down Expand Up @@ -219,7 +224,7 @@ internal class CheckoutView(

private suspend fun verifyPayment(payload: String?): CardVerificationResult<Nothing> {
val deferredResult = CompletableDeferred<CardVerificationResult<Nothing>>()
methodChannelVerifyPayment.invokeMethod(
methodChannel.invokeMethod(
METHOD_VERIFY_PAYMENT,
payload,
object : MethodChannel.Result {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import ottu_checkout_sdk
//

private let checkoutChannelName = "com.ottu.sample/checkout"
private let checkoutVerifyPaymentChannelName =
"com.ottu.sample/checkout/payment/verify"
private let methodCheckoutHeight = "METHOD_CHECKOUT_HEIGHT"
private let _methodPaymentSuccessResult = "METHOD_PAYMENT_SUCCESS_RESULT"
private let _methodPaymentErrorResult = "METHOD_PAYMENT_ERROR_RESULT"
Expand All @@ -24,7 +22,6 @@ private let _methodVerifyPayment = "METHOD_VERIFY_PAYMENT"
public class CheckoutPlatformView: NSObject, FlutterPlatformView {
private let viewId: Int64
private let channel: FlutterMethodChannel
private let channelVerifyPayment: FlutterMethodChannel
private let _view: CheckoutContainerView
private weak var paymentViewController: UIViewController?
private var checkout: Checkout?
Expand Down Expand Up @@ -58,10 +55,6 @@ public class CheckoutPlatformView: NSObject, FlutterPlatformView {
name: checkoutChannelName,
binaryMessenger: messenger
)
self.channelVerifyPayment = FlutterMethodChannel(
name: checkoutVerifyPaymentChannelName,
binaryMessenger: messenger
)
_view = CheckoutContainerView()
super.init()

Expand Down Expand Up @@ -426,7 +419,7 @@ public class CheckoutPlatformView: NSObject, FlutterPlatformView {
return await withCheckedContinuation { continuation in
Logger.sdk.info("CheckoutPlatformView.verifyPaymentCallback")
DispatchQueue.main.async {
self.channelVerifyPayment.invokeMethod(
self.channel.invokeMethod(
_methodVerifyPayment,
arguments: payload,
result: { [weak self] (result) -> Void in
Expand Down
117 changes: 86 additions & 31 deletions lib/src/checkout_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,70 +6,125 @@ import 'package:flutter/services.dart';
import 'package:ottu_flutter_checkout/ottu_flutter_checkout.dart';

const _checkoutViewType = 'OttuCheckoutWidget';
const _methodCheckoutHeight = "METHOD_CHECKOUT_HEIGHT";
const _methodOnWidgetDetached = "METHOD_ON_WIDGET_DETACHED";
const _methodVerifyPayment = "METHOD_VERIFY_PAYMENT";
const _methodPaymentSuccessResult = "METHOD_PAYMENT_SUCCESS_RESULT";
const _methodPaymentErrorResult = "METHOD_PAYMENT_ERROR_RESULT";
const _methodPaymentCancelResult = "METHOD_PAYMENT_CANCEL_RESULT";
const _methodChannel = MethodChannel('com.ottu.sample/checkout');
const _methodChannelPaymentVerify = MethodChannel('com.ottu.sample/checkout/payment/verify');

const _defaultCheckoutViewHeight = 200;

typedef VerifyPaymentDelegate = Future<CardVerificationResult<void, String>> Function(
String? payload);

class OttuCheckoutWidget extends StatefulWidget {
final CheckoutArguments arguments;
final VerifyPaymentDelegate? _verifyPayment;
final Function(String message)? _successCallback;
final Function(String message)? _cancelCallback;
final Function(String message)? _errorCallback;

const OttuCheckoutWidget(
{super.key, required this.arguments, VerifyPaymentDelegate? verifyPayment})
: _verifyPayment = verifyPayment;
const OttuCheckoutWidget({
super.key,
required this.arguments,
VerifyPaymentDelegate? verifyPayment,
Function(String message)? successCallback,
Function(String message)? cancelCallback,
Function(String message)? errorCallback,
}) : _verifyPayment = verifyPayment,
_successCallback = successCallback,
_cancelCallback = cancelCallback,
_errorCallback = errorCallback;

@override
State<StatefulWidget> createState() => _OttuCheckoutWidgetState();
}

class _OttuCheckoutWidgetState extends State<OttuCheckoutWidget> {
static const StandardMessageCodec _decoder = StandardMessageCodec();
final ValueNotifier<int> _checkoutHeight = ValueNotifier<int>(_defaultCheckoutViewHeight);

@override
void initState() {
super.initState();
_methodChannel.setMethodCallHandler(_handleChannelMethod);
}

@override
void dispose() {
print("OttuCheckoutWidget.dispose()");
if (kDebugMode) {
print("OttuCheckoutWidget.dispose()");
}
_methodChannel.setMethodCallHandler(null);
_methodChannel.invokeMethod(_methodOnWidgetDetached);
super.dispose();
}

@override
void didChangeDependencies() {
_methodChannelPaymentVerify.setMethodCallHandler((call) async {
print("CheckoutWidget, method call: ${call.method}");
switch (call.method) {
case _methodVerifyPayment:
{
final result = await widget._verifyPayment?.call(call.arguments);
Future<dynamic> _handleChannelMethod(call) async {
switch (call.method) {
case _methodCheckoutHeight:
{
int height = call.arguments as int;
_checkoutHeight.value = height;
}
case _methodPaymentSuccessResult:
{
String message = call.arguments as String;
widget._successCallback?.call(message);
}

case _methodPaymentCancelResult:
{
String message = call.arguments as String;
widget._cancelCallback?.call(message);
}

case _methodPaymentErrorResult:
{
String message = call.arguments as String;
widget._errorCallback?.call(message);
}
case _methodVerifyPayment:
{
final result = await widget._verifyPayment?.call(call.arguments);
if (kDebugMode) {
print("CheckoutWidget, verifyPayment, result: ${result.runtimeType}");
switch (result) {
case Success():
return "";
case Failure(:final message):
throw PlatformException(code: _methodVerifyPayment, message: message);
case null:
throw PlatformException(code: _methodVerifyPayment, message: "Unknown error");
}
}
}
});
super.didChangeDependencies();
switch (result) {
case Success():
return "";
case Failure(:final message):
throw PlatformException(code: _methodVerifyPayment, message: message);
case null:
throw PlatformException(code: _methodVerifyPayment, message: "Unknown error");
}
}
}
}

@override
Widget build(BuildContext context) {
final argsMap = widget.arguments.toJson();
final jsonArg = json.encode(argsMap);
final args = {"args": jsonArg};
if (defaultTargetPlatform == TargetPlatform.android) {
return AndroidView(
viewType: _checkoutViewType, creationParams: args, creationParamsCodec: _decoder);
} else {
return UiKitView(
viewType: _checkoutViewType, creationParams: args, creationParamsCodec: _decoder);
}
return ValueListenableBuilder<int>(
valueListenable: _checkoutHeight,
builder: (BuildContext context, int height, Widget? child) {
return SizedBox(
height: height.toDouble(),
child: defaultTargetPlatform == TargetPlatform.android
? AndroidView(
viewType: _checkoutViewType,
creationParams: args,
creationParamsCodec: _decoder)
: defaultTargetPlatform == TargetPlatform.iOS
? UiKitView(
viewType: _checkoutViewType,
creationParams: args,
creationParamsCodec: _decoder)
: SizedBox.shrink());
});
}
}