// Initialize UPI SDK
import 'package:upi_connect/upi.dart';
final upi = UpiConnect();
await upi.init(
merchantId: "sumukh@upi",
currency: "INR",
);
Transaction Channel
MethodChannel('upi/pay')
UPI Connect Plugin
UPI Connect simplifies payment SDK integrations. By providing an open-source, highly performant Flutter package, it wraps native financial SDK layers into an expressive, clean Dart API.
The Problem
Integrating enterprise financial platforms and UPI SDKs into Flutter usually requires extensive native code, leading to unstable payment callbacks and integration friction.
Product Thinking
Fintech developers need a simple, single, unified Dart interface. Every payment state must be type-safe, preventing integration errors that could lead to financial transaction drops.
Engineering Challenges
Creating a reliable, type-safe MethodChannel serialization interface to safely translate native Java/Swift payment data structures into Dart objects.
Key Learnings
Acquired advanced expertise in API library design, standard security protocols, and strict type casting across platform interfaces.
Architectural & Code Decisions
Deep technical breakdowns of individual structural choices and implementation patterns.
Type-Safe Payment Request Interface
Created a declarative MethodChannel handler with precise error codes, preventing compilation crashes caused by mismatched platform types.
// Type-Safe platform invocation layer
class UpiConnect {
static const MethodChannel _channel = MethodChannel('upi_connect/payments');
Future<PaymentResponse> initiatePayment(PaymentRequest req) async {
try {
final Map<dynamic, dynamic>? result = await _channel.invokeMethod(
'initiatePayment',
req.toMap(),
);
if (result == null) throw UpiException('Null payment callback response');
return PaymentResponse.fromMap(result.cast<String, dynamic>());
} on PlatformException catch (e) {
throw UpiException(e.message ?? 'Unknown Native Payment Error', code: e.code);
}
}
}Android Native UPI SDK Wrapper
Developed the Kotlin-side intent handler to launch third-party banking applications and return precise intent result mappings to the Dart interface.
// Kotlin Platform Channel payment dispatcher
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
if (call.method == "initiatePayment") {
val upiUri = call.argument<String>("upiUri")
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(upiUri))
activity?.startActivityForResult(intent, PAYMENT_REQUEST_CODE)
pendingResult = result
} else {
result.notImplemented()
}
}