Mifos Pay Use Cases
Merchant - Use case
PhonePe, Paytm, Google Pay
TABLE OF CONTENTS
- 1 Implementing a Merchant Module in Mifos Mobile Wallet (KMP)
- 1.1 1. Required Features for Merchant Support
- 1.2 2. Merchant Payment Flows and User Journey (Diagrams)
- 1.3 3. Inspiration from Leading Apps (PhonePe, Paytm, Google Pay)
- 1.4 4. Third-Party SDKs and Integrations (QR, UPI, Cards, etc.)
- 1.5 5. Handling Common Payment Instruments in the Merchant Module
- 1.5.1 Razorpay Mobile SDK
- 1.5.2 Stripe Mobile SDK
- 1.5.3 Paytm All-in-One SDK
- 1.5.4 Notes:
- 1.6 6. Developing the Merchant Module in the KMP Repository
- 1.7 7. Recommendations and Next Steps
- 1.8 Loan Feature via Open Banking Integration
- 1.9 Screenshots
- 2 Mifos Pay Wallet Customer Use Cases (Kotlin Multiplatform)
- 2.1 Required Features for Customer
- 2.1.1 User Registration and KYC
- 2.1.2 Secure Login with MFA (PIN + OTP + Biometrics)
- 2.1.3 Account Overview (Balance and Statements)
- 2.1.4 P2P Transfers (Send/Receive)
- 2.1.5 QR Code-Based Payments
- 2.1.6 Bill Payments and Recharges
- 2.1.7 Cashback and Loyalty Tracking
- 2.1.8 Notifications (FCM and SMS)
- 2.1.9 Dispute Reporting and Support Chat
- 2.2 (Optional) Offline Mode and Sync
- 2.3 References
- 2.1 Required Features for Customer
- 3 Mifos Pay KMP – Feature Implementation Analysis
- 3.1 Customer Centric Flows Implementations in KMP
- 3.1.1 UPI Transfers (Send & Receive) (NOT YET IMPLEMENTED)
- 3.1.2 QR Code Payments (Scan & Display)
- 3.1.3 Bill Payments & Recharges(NOT YET IMPLEMENTED)
- 3.1.4 Split Bill / Request to Pay(NOT YET IMPLEMENTED)
- 3.1.5 Cashback & Rewards(NOT YET IMPLEMENTED)
- 3.1.6 Savings & Loans (NOT YET IMPLEMENTED)
- 3.1.7 Insurance Payments (NOT YET IMPLEMENTED)
- 3.1.8 Subscriptions & Auto‑Pay(NOT YET IMPLEMENTED)
- 3.1.9 Offers & Coupons (NOT YET IMPLEMENTED)
- 3.1.10 Social / Referrals (NOT YET IMPLEMENTED)
- 3.1.11 Multi-language UI (NOT YET IMPLEMENTED)
- 3.1.12 Transaction Insights (NOT YET IMPLEMENTED)
- 3.1.13 Advanced Security (PIN, Biometric, OTP)
- 3.1.14 Futuristic Expansions (CBDC, Offline Transfers, Digital ID) (NOT YET IMPLEMENTED)
- 3.1 Customer Centric Flows Implementations in KMP
- 4 Mifos Pay Architecture Suggestions and KMP Context
- 5 Recommendations (Roadmap, Scalability, Compliance)
- 6 Loan Feature in Mifos Pay – Open Banking Solutions in India
- 7 Indian Banks and Loan APIs
- 8 UPI Infrastructure Overview
Implementing a Merchant Module in Mifos Mobile Wallet (KMP)
1. Required Features for Merchant Support
In-Store Merchant Features: Merchants need a range of features to accept payments at physical stores and track their sales. Key capabilities include:
QR Code Payment Acceptance: Ability to generate and display QR codes (both static and dynamic) that customers can scan to pay. A static QR contains the merchant’s payment address (e.g. UPI VPA or wallet ID) for flexible amounts, while a dynamic QR can include a specific amount and invoice details for each transaction medium.com. This allows any UPI app or compatible wallet to scan and initiate payment to the merchant.
Instant Payment Notifications: Real-time alerts for incoming payments, e.g. in-app notifications or sound cues (akin to Paytm’s SoundBox) when a customer payment is received. This assures the merchant that a transaction is successful.
Transaction History & Analytics: A detailed history of payments received, with filters (daily, weekly, etc.), and summary analytics. Merchants should be able to see how much they earned in a day, track trends, and view details of each transaction (payer info, time, amount). For example, Paytm’s merchant dashboard allows viewing key metrics, settlements, and downloading reports business.paytm.com.
Digital Receipts and Invoices: Ability to generate a receipt or invoice for each sale. This could be as simple as a transaction confirmation screen that can be shown or sent to the customer. Invoices might include item details (if entered by the merchant) and the amount due, which the app can convert into a QR or payment request. The Mifos initiative explicitly notes “generate invoices” as a desirable feature for merchant-facing wallets openmf.github.io.
Merchant Profile & Store Details: A section for the merchant to manage their business profile – e.g. store name (to display on the customer’s app when paying), contact information, and possibly a business QR code that can be printed or shared. Top apps like Google Pay for Business let merchants set up their business name and even help customers discover the store or pay via phone numbersupport.google.comsupport.google.com.
Online (Remote) Merchant Features: For merchants selling online or seeking remote payments (without a physical QR scan), the module should support:
Payment Links / “Request to Pay”: The ability to generate a payment link or send a request-to-pay notification to a customer. The merchant enters an amount (and description) and the app produces a link or QR code that can be shared via messaging or displayed on a website. When the customer opens the link, they can choose a payment method (UPI, card, netbanking, etc.) to complete the payment. This is analogous to Paytm’s “Payment Link” feature which collects payments without needing the customer to visit a website or app of the merchant business.paytm.com. Mifos itself highlights “Request to Pay” as a core feature of merchant wallets products.mifos.org, allowing a merchant to prompt a customer’s app to pay a certain amount.
Multi-Mode Online Payments: Support accepting payments via various instruments remotely. This typically involves integration with a payment gateway or aggregator. For example, an online payment link might lead to a checkout page where the customer can pay by debit/credit card, netbanking, UPI, or wallet. We should ensure the merchant can initiate such requests easily from the app.
Settlement to Bank Accounts: Since merchants often need funds in their bank, the app should facilitate easy settlement of the wallet balance to their linked bank account. Ideally, payments received could automatically settle to the bank daily (as Google Pay and PhonePe do, with no fees) support.google.com. If using the Mifos/Fineract backend, the merchant’s wallet account could be a current account that is credited, with an option to transfer to a designated bank account.
Refunds and Dispute Management: In case a merchant needs to refund a payment or handle disputes (e.g., customer paid wrong amount), the app should offer a way to initiate refunds. This might tie into the payment gateway’s refund APIs or simply record a counter-transaction if on the same wallet system. Paytm’s merchant tools, for instance, support initiating instant refunds and viewing disputes business.paytm.com.
Merchant Onboarding & KYC: Flow to register a user as a merchant. This could involve additional KYC steps or business verification (since higher transaction volumes are expected). The app might allow an existing user to “upgrade” to a merchant account by providing business details and documentation. This ensures regulatory compliance (for example, requirements in certain countries to distinguish merchants for UPI or to allow higher limits). Google Pay for Business and others require business verification but then provide special benefits like higher transaction limits and rewards support.google.comsupport.google.com.
By covering these features, the merchant module will support both small in-store merchants (e.g. a shopkeeper using QR for walk-in customers) and online sellers (who need payment requests and multiple payment options). The Mifos Mobile Wallet (Mifos Pay) is envisioned to handle such use cases, as evidenced by its mention of merchant wallets supporting QR payments, invoices, and sales tracking openmf.github.io.
2. Merchant Payment Flows and User Journey (Diagrams)
Merchant transactions can follow slightly different flows depending on context. Below we describe two primary flows (in-store QR payment and remote payment request) and illustrate the interactions using Mermaid diagrams.
2.1 In-Store Payment via QR Code (Customer Scans Merchant QR)
In this scenario, the merchant uses the app to present a QR code, and the customer pays by scanning it with their payment app (which could be the same wallet app or any UPI-enabled app). The sequence diagram below outlines the process:
Mermaid
sequenceDiagram
participant M as Merchant App (Mifos Wallet)
participant C as Customer App (UPI/Wallet)
participant F as Backend (Fineract/Payment Hub)
Note over M: **Merchant generates QR code** (static or with amount)
M->>M: Display QR Code (contains merchant VPA/ID and [optional] amount)
C->>C: Customer scans QR and reviews payment details
C->>C: Customer confirms payment (chooses instrument & authenticates)
C->>F: Initiate payment to merchant (via UPI/card gateway)
F-->>C: Transaction processed (debit customer, credit merchant)
Note over F: Payment routed through bank/NPCI or<br/>internal switch, then credited to merchant
F-->>M: Notify merchant app of successful payment
M->>M: Update transaction history and show confirmation (e.g. receipt)
Explanation: The merchant opens the app’s “Receive Payment” screen which shows a QR code encoding the merchant’s payment address (and possibly a specific amount). The customer scans this QR with their own app and is prompted to pay. For example, if it’s a UPI QR, the customer’s UPI app will parse the merchant’s VPA (UPI ID) and amount medium.com, then the customer enters their UPI PIN to authorize. The payment is then processed through the UPI network or payment backend – the customer’s bank account is debited and the merchant’s account credited medium.com. The backend (Apache Fineract with Mifos Payment Hub in this case) records the transaction and sends a confirmation to the merchant’s app. The merchant app then notifies the user (sound or pop-up) and may display a digital receipt. This flow is pull-based from the customer perspective (customer initiates payment by scanning). It’s widely used in India’s UPI ecosystem and is supported in Mifos Payment Hub (which covers “QR code payments” and merchant collections under the hood payments.mifos.org).
2.2 Remote Payment via Request/Link (Merchant Initiated)
Now consider a remote or online payment scenario, where the merchant triggers the payment request. This could be via a “Request Money” to a known customer or generating a payment link/QR for the customer to complete the payment. The diagram below illustrates a generic “Request to Pay” flow:
Mermaid
sequenceDiagram
participant M as Merchant App
participant F as Backend (Payment Server)
participant C as Customer (Receiver)
M->>M: Enter amount and create Payment Request (invoice)
M->>F: Send payment request details (amount, payer info or link generation)
F-->>C: Notify customer (push notification or shareable link)
Note over C: Customer receives request (in app or via link) and initiates payment
C->>F: Complete payment using chosen instrument (UPI/card/netbanking)
F-->>M: Update status: Payment successful or failed
M->>M: Show transaction result (mark invoice paid if successful)Explanation: The merchant enters an amount and optionally selects a specific customer (or generates a link for an unspecified customer). The app communicates with the backend to create a payment request (essentially an invoice or a collect request). If the customer is on the same platform (e.g. the wallet app or connected via Payment Hub), they might get an in-app notification to approve the payment – this is how Request-to-Pay works in UPI and mobile money systemspayments.mifos.org. Alternatively, the app generates a payment link (URL or QR) which the merchant shares. The customer clicks the link and is taken to a web/mobile checkout page to complete payment. During payment, the customer can choose any available method: for instance, UPI if on mobile (which might invoke their UPI app), or entering card/banking details if provided by the payment gateway. Once the customer pays, the backend notifies the merchant’s app that the request is fulfilled. The merchant can see the status update in their app (e.g. “John has paid ₹500”). This push-based flow is useful for remote transactions and aligns with features from apps like Paytm and PhonePe which offer payment links and collect requestsbusiness.paytm.com.
Note: In both flows, the Mifos Mobile Wallet app will interact with backend services. Apache Fineract by itself is the ledger/store of accounts, while real-time payment routing may be handled by the Mifos Payment Hub or an integrated payment gateway. The Payment Hub Enterprise (PH-EE) supports merchant use cases such as P2M collections, request-to-pay, and integration to networks like UPI or mobile money payments.mifos.org, which can be leveraged by the mobile app.
3. Inspiration from Leading Apps (PhonePe, Paytm, Google Pay)
Designing the merchant module can be guided by industry-standard features offered by popular payment apps:
PhonePe & Paytm (QR Code and All-in-One Acceptance): Both PhonePe and Paytm provide merchants with a QR code that accepts multiple payment modes business.paytm.com. Paytm’s “All-in-One QR” is advertised as a single QR that can accept UPI payments from any app, Paytm wallet payments, and even card payments via linked methods. The mobile wallet should similarly generate a QR that conforms to a standard like BharatQR or UPI QR, so that any customer app can scan it. These apps also offer printed QR kits and stands – our app could include an option to order a printed QR or at least download the code image to print. Moreover, merchants on these platforms pay no transaction fees (at least for UPI), which is an attractive model. While building our module, focusing on zero-fee, seamless payments (perhaps subsidized by the platform) will make it competitive.
Instant Settlement and Bank Transfers: Google Pay for Business highlights that money paid by customers goes directly to the merchant’s bank account with no fees support.google.com. PhonePe and Paytm similarly offer fast or next-day settlements. Our merchant module should integrate with the backend to schedule automatic sweeps of wallet balance to the merchant’s bank account at end-of-day or provide an “Withdraw to Bank” on-demand. This requires the merchant to link a bank account during onboarding. If using Fineract, this could map to an internal transfer from a wallet (e.g. a savings account) to a connected bank account (via Payment Hub or manual payout).
Multiple Ways to Get Paid: Leading apps let customers pay merchants not only by scanning QR, but also via searching phone number, business name, or using a built-in nearby feature. For instance, Google Pay Business allows payment via the customer simply entering the merchant’s phone number in the Google Pay app (since the merchant is registered in the system). PhonePe has a merchant directory and lets users find merchants in-app by name or location phonepe.com. In our context, if both customer and merchant use the Mifos wallet, we can allow P2P transfers to merchant accounts via phone/email lookup (essentially treating merchant accounts as identified payees in the network).
Rewards and Promotions: To drive adoption, big wallets often give cashback or rewards for merchant transactions. Google Pay mentions special rewards for both merchants and customers on reaching certain transaction milestones. While implementing our module, we might not prioritize a full rewards system initially, but designing it in a way that can later accommodate offers (like “cashback on first X payments”) would align with industry practice.
Business Management Tools: Beyond payments, merchant apps like Paytm for Business provide a dashboard with sales analytics, the ability to initiate refunds, view dispute messages, and see all settlements. They also allow merchants to download reports (daily statements, etc.) and manage multiple stores or employees. As a first phase, our merchant module will focus on core payment acceptance, but we should structure data models for transactions and maybe basic analytics so that adding reports is straightforward. We can also include the ability to export transaction history (CSV/PDF) via email – a simple but useful feature.
In summary, learning from these apps: our solution should make receiving money frictionless (scan or click and pay), ensure the merchant has clear visibility on their earnings (history, analytics), and handle money movement to their bank seamlessly and cheaply. Wherever possible, incorporate flexibility to accept all common payment types, as merchants expect an “all-in-one” solution.
4. Third-Party SDKs and Integrations (QR, UPI, Cards, etc.)
To implement the above features efficiently, we can leverage third-party libraries and SDKs for various functionalities. The challenge is to integrate them in a Kotlin Multiplatform (KMP) context. Below are key SDKs/libraries and how we might use them in the merchant module:
QR Code Generation and Scanning: Rather than writing our own QR encoder, we can use a library. QRCode-Kotlin is a pure Kotlin, multiplatform library that can generate QR code images github.com or Qrose github.com. This means we can include it in the shared KMP code and use it on Android/iOS/Web without platform-specific code. By using such a library, the app can generate a merchant’s QR (containing e.g. UPI URI or a payment URL) on the fly. For scanning QR codes (when the merchant wants to scan a customer’s code or perhaps to activate something), we might use platform-specific solutions. There are emerging multiplatform scanning libraries (e.g. QRKit Compose Multiplatform github.com) that could simplify this with a shared UI component. Initially, focusing on generation (for display) is crucial; scanning by the merchant is secondary (since in P2M, usually the customer scans).
UPI Integration: UPI (Unified Payments Interface) is a real-time payment scheme (especially in India) that we want to support. To accept UPI payments, the simplest approach is to use the UPI Intent/Deep-link method on the customer side. Our merchant app doesn’t send money via UPI; it receives money. So for the merchant, what’s needed is to generate a UPI-compatible QR code or Collect Request. Generating a UPI QR is straightforward (it’s just a URI string embedded in a QR). We can compose a string like
"upi://pay?pa=<merchant_vpa>&pn=<name>&am=<amount>&cu=INR"etc. This URI, when encoded as a QR or launched, will trigger any UPI app to pay the merchant stackoverflow.com. Indeed, a generic"upi://pay"link with the required params opens a chooser of UPI apps on Android. For deeper integration (like notifying the merchant of payment without polling), we’d rely on backend notifications (since only a PSP app can directly listen for UPI incoming collect approvals).If we wanted the merchant app itself to be a UPI PSP (allowing it to create UPI collect requests and receive callbacks), that would involve using an NPCI library or bank SDK – which is beyond a typical open-source scope. Instead, we likely integrate with Mifos Payment Hub or any payment switch that can initiate a UPI “request to pay”. The mobile app would call the backend to initiate a collect (for which the backend might use NPCI APIs) and then wait for confirmation. For a simpler implementation, we might skip dynamic collect and focus on QR – since any UPI app can scan the QR and the merchant will see the result in their transaction list (the backend would receive the credit via the connected Fineract account).
In KMP terms, UPI deep-linking is mostly an Android concept (on iOS, UPI apps exist but not as widespread; still, an
upi://URI could launch something like BHIM or Google Pay on iOS if installed). We can handle this by platform-specific code: on Android, use anIntentto launch the URI; on iOS, useUIApplication.openUrl. The merchant module might not need to launch UPI intents (since the customer’s device does that), but if we ever implement a scenario where the merchant app can itself initiate a payment (e.g. merchant paying a supplier via UPI), we’d do similar. We should document the UPI QR format (NPCI provides specifications for static and dynamic QR, and BharatQR standard for UPI).Card and Netbanking Payments: Accepting cards or netbanking typically requires a Payment Gateway SDK. Open-source or self-hosted options are limited, so we might integrate a third-party like Razorpay, Stripe, or Paytm All-in-One SDK. These SDKs provide a ready-made checkout flow supporting cards, netbanking, UPI, and wallets. For example, Razorpay’s mobile SDK can pop up a payment form where the user can enter card details, pick a netbanking option, or UPI, and it handles the transaction securely. It supports both Android and iOS (though not KMP natively) and covers all common instruments. The Paytm All-in-One SDK similarly allows merchants to accept multiple modes in-app business.paytm.com.
To include such SDKs in our KMP app, we use the following strategy: add the SDK to each platform module and bridge to shared code. Concretely, we can define an interface in the shared code (e.g.
PaymentProcessorwith a method likeprocessPayment(amount, method)), then have an Android implementation that calls Razorpay’s Android SDK and an iOS implementation that calls Razorpay’s iOS SDK. KMP allows using expect/actual declarations or dependency injection for this. For instance, we declareexpect class PaymentSDK { fun startPayment(...) }in common, and then inandroidMainprovide theactual class PaymentSDKthat wraps the Razorpay (or chosen SDK) calls, and iniosMainthe actual class that wraps the iOS SDK. This follows the first approach described by experts for integrating platform-specific SDKs: “Create an interface in shared code, and pass in an implementation from each platform.”stackoverflow.com.Wallet Balance Payments: Since the app is a wallet itself, one instrument for payment is the internal wallet balance. This is essentially a transfer from the customer’s wallet account to the merchant’s wallet account on the backend. No external SDK is needed for this – it would be handled by calling a Fineract API (for transferring between accounts). However, to the customer it should appear as just another payment method (“Pay with Wallet”). In a merchant scenario, if both parties use the same wallet, the customer could simply use the app’s normal send money flow to the merchant’s number or ID. We should ensure that the merchant’s ID/QR is recognizable by our app to trigger an internal transfer (this could be encoded differently or detected by our scanning logic). For example, if our wallet QR encodes an internal account ID, the app would realize it can pay directly without UPI rails. This could be optimized for zero cost and instant settlement (all on-us transactions).
Other SDKs: If needed, there are additional third-party tools that could enhance the merchant module: e.g. an SDK for generating sound notifications (though simple audio file playback is enough), or SDKs for analytics and crash reporting (to monitor usage). Those would be integrated at the app level rather than feature-specific.
Integration Approach in KMP: Each third-party SDK integration will reside in the relevant platform code. The repository is KMP multi-module, meaning we have a mifospay-android and mifospay-ios where platform-specific dependencies are added. We will add the needed SDK dependency (e.g. Gradle coordinate for Android, CocoaPod for iOS) and then expose the functionality through the shared module via expect/actual or interfaces. This way, the shared merchant logic can call a generic function for (say) “collectCardPayment()” and under the hood the Android actual implementation will invoke the card SDK. Documentation from Kotlin Multiplatform guides and community suggests this pattern for incorporating non-KMP libraries stackoverflow.com. We must also handle callbacks from these SDKs (payment success/failure) and propagate them back to shared code (perhaps via coroutine completion or delegate methods). For instance, Razorpay SDK invokes a callback in the Android activity; we’d funnel that into a KMP-friendly flow (like suspend functions or state in ViewModel).
5. Handling Common Payment Instruments in the Merchant Module
To be truly useful, the merchant app should support all common payment instruments that customers may use. Here’s how each can be handled:
UPI Payments: UPI will likely be the primary mode for in-person transactions (in regions where UPI is available, e.g. India). Supporting UPI mostly means making sure the merchant has a UPI ID (which could be linked to their bank account) and then using QR codes or collect requests as described. If the Mifos backend is connected to UPI, we could even let the merchant create a UPI handle through the app (some banks allow third-party apps to create VPAs via APIs). Otherwise, we rely on the merchant’s existing UPI ID. The app should make the merchant’s UPI ID (or QR) easily accessible – much like how PhonePe shows “My QR” in a prominent place scanova.io. We will also include a UPI setup flow (the repository already has a
upi-setupmodule github.com) for users to link their bank for UPI. For merchants, ensuring their UPI is linked means payments go straight to bank. We should also respect UPI’s transaction limits and guidelines (the Google Pay for Business help notes that NPCI and banks impose limits on UPI transfers support.google.com).Debit/Credit Cards: Card payments are crucial for online transactions and even in-store if the merchant wants to accept cards without a POS machine. With our mobile app, truly swiping or tapping a physical card is not possible without external hardware. But we can accept card details in-app (for online payments) via a gateway SDK. So for the merchant’s remote payment links, we enable a card payment option. Using an aggregator (Razorpay, Stripe, etc.) as discussed is the straightforward path. The card info entry and processing happen through the secure SDK/UI of the provider, ensuring PCI compliance. If needed, the app could also support scanning a card (some payment SDKs or card reader SDKs allow scanning the card number via camera), but that’s an enhancement. To the merchant, these card payments will show up just like any other incoming payment in their history (the backend will just mark them appropriately, maybe with fees deducted if any). We also note that in markets like India, credit cards can be linked to UPI (e.g. RuPay credit via UPI) – the All-in-One QR would automatically handle those if the customer chooses that route business.paytm.com (the QR doesn’t change; the customer’s app decides whether it’s paying via bank account or card). So simply by having a UPI QR, a merchant might indirectly accept some cards (via UPI linkage). For broader card acceptance (Visa/MasterCard), the payment link approach is better.
Netbanking (Internet Banking): This is typically offered in web checkouts where the customer selects their bank and logs in to authorize payment. In the context of our mobile wallet, netbanking isn’t an in-app experience but can be part of an online payment flow. If we use a gateway’s SDK, netbanking will appear as an option (for example, Razorpay SDK will list banks for NetBanking and then open a webview to the bank’s site). The integration is similar to cards – we rely on the SDK for the heavy lifting. The merchant likely doesn’t need to know the details, just that the payment succeeded.
Wallet Balance (Internal Wallet): As mentioned, if a customer also has a wallet account on the same Mifos system, they could pay directly from their wallet balance to the merchant’s wallet. This is essentially a P2P transfer but marked as a merchant payment. We should incorporate merchant identification in the transfer request (so that the system, or the merchant, can potentially differentiate these transactions). For instance, a transfer could carry a flag or the merchant’s account is a special type. One idea: when a user scans the merchant’s QR through our own app, instead of going to external UPI, the app can detect “this is an internal merchant”. It could then simply do an internal transfer via API (immediately reflecting in both accounts) and perhaps still generate a UPI transaction behind the scenes if needed for interoperability. The module design should consider this scenario for closed-loop environments (all users on the same platform – like a campus or an MFI deployment where both clients and merchants use Mifos).
Other Instruments: If needed, the architecture could be extensible to support things like USSD payments, mobile money (in countries where mobile money is prevalent, e.g. via integrations with Mojaloop or GSMA Mobile Money API), or even Buy Now Pay Later if the platform offers credit. For now, the four instruments above cover the vast majority of use cases. Mifos Payment Hub’s design allows connecting to various rails – from real-time payment systems (like instant bank transfers) to mobile money and even card switches payments.mifos.orgpayments.mifos.org. Our app can remain flexible to plug into those as the backend expands.
In implementing each instrument, ensure the UI clearly differentiates them for the merchant (so they know how a customer paid, especially if fees or settlement times differ). For example, mark transactions as “Paid via UPI” vs “Paid via Card (Gateway)” etc., and possibly allow the merchant to filter by instrument in their history or dashboard.
Here are the reference links for the SDKs & concepts mentioned:
Razorpay Mobile SDK
Official Docs: https://razorpay.com/docs/payments/payment-gateway/web-integration/standard/
Mobile SDK Overview: https://razorpay.com/docs/payment-gateway/android-integration/standard/
Features supported:
Cards (Visa, Mastercard, RuPay, Amex, etc.)
Netbanking
UPI
Wallets
EMI
PayLater
Stripe Mobile SDK
Official Docs: https://stripe.com/docs/payments/accept-a-payment
Mobile SDK:
Features supported:
Cards
Bank redirects (netbanking equivalent in certain countries)
UPI (in India)
Wallets (Apple Pay, Google Pay)
Paytm All-in-One SDK
Official Docs: https://business.paytm.com/docs/all-in-one-sdk/
Overview Page: https://business.paytm.com
Features supported:
UPI
Cards
Netbanking
Wallet (Paytm wallet)
Postpaid
EMI
Notes:
These are not open-source SDKs, but they are free to integrate — they charge per successful transaction (standard for payment gateways).
There are no well-maintained fully open-source payment gateway SDKs for card+netbanking due to PCI-DSS compliance requirements (secure card handling).
Razorpay, Stripe, Paytm handle the compliance, tokenization, secure checkout — that's why we use their SDK rather than rolling our own.
The SDKs work on Android, iOS and some Web — not natively in Kotlin Multiplatform (KMP) — but can be used via platform-specific wrappers.
6. Developing the Merchant Module in the KMP Repository
Finally, we outline how to build this as a new module within the existing openMF/mobile-wallet project structure. The repository is organized as a multiplatform project with a shared code base and platform-specific subprojects (Android, iOS, Desktop, Web) github.comgithub.com. Each major feature in the app is separated into its own package or module (e.g. accounts, payments, qr, merchants, etc. exist in the codebase) github.com. To introduce merchant support cleanly, we will take the following approach:
Create a Feature Module for Merchants:
The codebase appears to already have a placeholder for merchants logic in the shared module structure github.com. We will build out this merchants module. If the project uses separate Gradle modules for features (as suggested by recent refactoring PRs where merchants were moved to a feature module gist.github.com), we ensure :merchants is included in settings.gradle.kts and set up with common, android, ios source sets. This module will contain all shared business logic for merchant operations.
Data Model and API Integration:
Define data models for merchant-specific entities – e.g. MerchantProfile (business name, maybe category, settlement bank info), MerchantTransaction (could extend a general Transaction model with fields like customer name, payment method, etc.), and Invoice or PaymentRequest for request-to-pay flows. We will interface with the backend via the existing network layer (likely Ktorfit + Fineract APIs). If Apache Fineract has no concept of “merchant” versus “customer”, we might handle that via a flag or a separate clients group. The mobile wallet, however, might rely on extension APIs (perhaps via Payment Hub or custom endpoints) for things like generating payment links or QR payloads. We should check Fineract’s API or Payment Hub documentation for any endpoints supporting merchant payments. If none, the module might use a combination of existing endpoints (for P2P transfers, etc.) and external services (for UPI QR, perhaps just construct locally).
For QR, we might not need an API call – the app can generate the string locally (for UPI QR: use the merchant’s UPI ID from profile and amount input). For payment links through a gateway, the app might call an API on a gateway service (for example, a cloud function or Payment Hub that returns a short URL to a hosted checkout). Part of building this module is deciding how the backend will be implemented; since this question is app-focused, we assume the necessary backend capability exists or will be added (e.g., Payment Hub EE can orchestrate these flows payments.mifos.org).
User Interface (Compose Multiplatform UI):
Design Compose Multiplatform screens for the merchant features. Likely screens include: Merchant Dashboard/Home (summary of recent transactions, total earnings, maybe a QR quick-access), Receive Payment screen (show QR code and maybe amount entry for dynamic QR), Payment Request screen (form to input amount and description and generate a link/QR), Transaction History (list of payments received, filterable by date or type), and Profile/Settings (view/edit business info, bank details, toggle notifications). Using Compose means we can write UI once for Android and iOS. We will follow the existing UI patterns in the app for consistency (e.g. use of Material 3 or analogous styling).
Mermaid diagrams or flowcharts can be converted into actual UI flows. For instance, the Receive Payment screen might have a switch for static vs dynamic QR: static just shows one code (perhaps stored for offline use), dynamic allows entering amount each time. After a payment arrives, perhaps a bottom sheet or new screen shows the transaction details and an option to share receipt. The Payment Request screen, after generating a link, could directly offer sharing options (copy link, share via WhatsApp, etc.).
Compose Multiplatform is already configured in the project github.com, so we will add our screens to the shared UI layer. If the project uses a navigation system, we’ll register new routes (e.g. “/merchant/home”, “/merchant/receive”, etc.) and ensure the main app can navigate to merchant flows (likely from a switch or a separate login mode).
Platform-Specific Implementations:
As discussed in the SDK section, we will implement platform-specific bits in the Android and iOS modules. Concretely:
In mifospay-android: add any dependencies like the QR scanning library (ZXing or MLKit) and payment SDK (if chosen). Implement Android-specific code for launching intents (for UPI, opening external apps) and handling callbacks (e.g. receiving a broadcast or deeplink after payment – though for UPI collect, the merchant’s phone typically wouldn’t get a callback; the backend would). Also, manage permissions if needed (camera for scanning QR if merchant scans something).
In mifospay-ios: add corresponding dependencies (maybe use AVFoundation for camera scanning, and any payment SDK pods). Implement iOS-specific code for similar actions (opening URLs for UPI, etc.). Ensure Swift interop is configured if we call any Swift/ObjC SDK.
The KMP project likely uses dependency injection (Koin, since Koin works in KMP) github.com. We will provide DI modules for our feature: e.g. a MerchantViewModel that uses a MerchantRepository. The repository would be injected with network services or storage as needed. The existing project’s patterns (as gleaned from other modules like payments/, accounts/) should be followed for consistency.
Testing and Quality:
Being comprehensive also means writing unit tests for the shared merchant logic (e.g. ensure QR generation produces correct strings, ensure formatting of transaction history entries, etc.). If the project has a test setup in place, we’ll add our tests accordingly. UI tests on multiplatform are evolving, but at least on Android we might add some instrumented tests for the new screens.
Documentation and Example Data:
Update the README or Wiki to include usage of merchant features. Possibly provide a demo in the documentation: e.g. how to simulate a merchant receiving a payment (which might involve using two accounts – one as merchant, one as customer – on a test Fineract instance). Given the open source nature, we want other contributors to easily understand how the module is structured and how to run a demo (the provided demo credentials on venus.mifos.io github.com could be used to test if merchant accounts are configured).
Gradual Rollout (Feature Toggle):
If this is a large addition, we might hide it behind a feature flag initially. For example, only show the “Merchant” section in the app if the user’s account is marked as merchant. This could be determined by a property from the backend (perhaps a role or a boolean in the user profile). This way, existing wallet users won’t see merchant options unless enabled, keeping the UI clean.
By following these steps, we ensure the merchant module is well-contained, maintainable, and fits into the Mifos Mobile Wallet architecture. The modular structure (one folder for merchants logic, possibly with sub-packages for UI, domain, data) prevents tight coupling with other featuresgist.github.com. This means future enhancements (like adding loyalty programs or multi-branch support) can be done within the merchant module without affecting core wallet features.
7. Recommendations and Next Steps
Security and Compliance: Ensure the module handles sensitive data securely. QR codes and links should not expose any more info than necessary (UPI QR includes just VPA, merchant name, amount). When using third-party SDKs for cards, let them handle PCI compliance (we never store card data ourselves). Also, protect merchant data on device – since transaction histories are business records, maybe provide a PIN or biometric lock for the merchant section of the app.
UX Considerations: Because merchants might be busy at a shop counter, the app should have an easy, quick-launch button to show the QR code (perhaps on the home screen). Also, use large fonts and high-contrast for QR code display for easy scanning. Provide an offline mode for QR (generate and save the static QR so payments still come even if merchant is briefly offline – the customer’s UPI app can still initiate). For dynamic amounts offline, that’s harder, but at least static QR can always work.
Incremental Development: Start with in-store QR payments (the most essential) and basic history. Then add request-to-pay and other refinements. This allows testing the waters – for example, deploying a pilot where merchants use QR and we verify that transactions appear via Fineract. Later, integrate a payment gateway for cards/netbanking if required by the use case.
In conclusion, adding a merchant module to the Mifos Mobile Wallet involves covering a broad set of features – from QR code payments to online links – but by studying existing apps and utilizing available SDKs and Mifos infrastructure, we can implement it in a modular, scalable way. This empowers merchants on the platform to conduct digital transactions easily, expanding the utility of the Mifos mobile wallet beyond person-to-person use cases openmf.github.io.
Sources:
Mifos Initiative – Mobile Wallet Use Cases openmf.github.ioproducts.mifos.org
Mifos Payment Hub EE – Support for Merchant QR and Request to Pay payments.mifos.org
Google Pay for Business Help – Benefits and payment methods support.google.comsupport.google.com
Paytm for Business – All-in-One QR and Dashboard features business.paytm.combusiness.paytm.com
UPI Workflow (Ayush Mittal, Medium) – QR payment steps medium.commedium.com
Razorpay Integration Guide – Multiple payment modes support medium.com
Kotlin Multiplatform Discussions – Integrating platform-specific SDKs stackoverflow.com
Loan Feature via Open Banking Integration
Overview: In addition to payments, the wallet can offer a digital credit feature – allowing users (consumers or merchants) to discover and take loans from external financial institutions. This aligns with the concept of a digital credit app that lets clients apply for and receive loans on their mobile openmf.github.io. To enable this, we can integrate with open banking APIs and open-source or free SDKs that connect to external banks and lenders. Open banking (under frameworks like PSD2) allows third-party apps (like our wallet) to access financial information and initiate transactions in a secure, standardized way crif.digitalcrif.digital. By leveraging these APIs, our app can gather a user’s banking data (with consent) to assess loan eligibility and facilitate loan applications to various providers.
The plan covers identifying suitable APIs/SDKs, how to integrate them into a KMP architecture, and the end-to-end customer flow for loan application, approval, and repayment.
Open-Source SDKs / Free APIs for Open Banking and Loans
Below is a list of relevant APIs and SDKs (either open-source or with free access tiers) that can be used to implement the loan feature:
Apache Fineract / Mifos APIs: Apache Fineract is an open-source core banking system that underpins Mifos X. It provides a full suite of loan management APIs (for loan applications, approvals, disbursements, repayments, etc.). In fact, the Mifos platform’s self-service API already includes endpoints like “Submit Loan Application” cwiki.apache.org. If an external bank is running Fineract, or if the wallet’s back-end (Mifos/Fineract) is extended to connect to external lenders, we can use these APIs to create loan accounts for the user. This option is fully open-source. Even if the external banks aren’t on Fineract, we could use Fineract as an intermediary: the wallet submits a loan request to a Fineract instance which either itself acts as the lender or forwards the request to actual lenders. It gives us flexibility to manage loan lifecycle in-house with open technology.
Open Bank Project (OBP API): The Open Bank Project provides an open-source RESTful API platform for banks, covering accounts, transactions, payments, etc github.com. While OBP’s focus is on account and transaction data, it can be extended to support loan-related functions or at least used to fetch the user’s financial data from their bank. OBP has a wide range of standardized endpoints and an active ecosystem. Using OBP, our app could, for example, retrieve the customer’s account balance and transaction history from various banks (with one unified API) – useful for credit scoring. If partner banks expose loan offers via OBP or if OBP’s API can be used to submit loan requests (not standard, but OBP is extensible), it’s a potential solution. Since OBP is open-source, we could deploy an OBP instance that aggregates multiple bank APIs for our app’s use.
Nordigen / GoCardless Account Data API: Nordigen (now acquired by GoCardless) offers a free open banking API that connects to over 2,300 banks across Europe gocardless.com. It provides account information services (AIS) – meaning with user consent, we can fetch bank account details and transactions for the last 12+ months. This is extremely useful for assessing a user’s creditworthiness (by analyzing income, expenses, etc.). Nordigen’s API is free for developers and well-documented fintech-market.com. It doesn’t directly provide loan offers, but it can feed data to lending algorithms or providers. In our context, we might use Nordigen to pull a user’s bank statement data as part of the loan application process. Nordigen is pure REST and can be consumed in a multiplatform project (no platform-specific SDK needed). The flow typically: get user consent through Nordigen’s hosted link, then Nordigen provides an access token to fetch data from the user’s bank account.
Plaid: Plaid is a popular financial API aggregator (especially in North America) that allows apps to connect to users’ bank accounts (retrieve balances, transactions, and even verify liabilities like existing loans or credit cards) github.com. Plaid isn’t open-source, but it has a free development tier and excellent documentation. Using Plaid’s Link flow, the user can log in to their bank in-app and we get tokens to access their data. Plaid can provide income verification and other products useful for lending decisions. Additionally, Plaid has a Liabilities API which can list a user’s current loans or credit lines, giving insight into their debt. For our KMP app, we’d integrate Plaid via web or native SDK (Android and iOS). Plaid’s SDK is not multiplatform, but we can invoke it on each platform (via
expect/actualor platform-specific UI code) and then handle the returned data in shared code.TrueLayer: TrueLayer is another aggregator (focused on UK/EU open banking). Like Plaid, it provides connections to bank data and payment initiation. TrueLayer has free tiers for sandbox/testing and is known for a developer-friendly API. It could be used similarly to fetch account info for loan decisions. Not open-source, but widely used in open banking implementations.
FinCity / Yodlee / Tink / MX: These are other aggregators (Yodlee and Tink in Europe, MX in US) that provide comprehensive financial data APIs. They are not free or open-source generally, but they might have trial programs. Likely we don’t choose them if we focus on free options, but it’s good to know the landscape. For instance, Tink (by Visa) and Yodlee (by Envestnet) could connect to banks and also have enriched data for credit scoring.
Bank-Specific Open APIs: Some banks (especially in the UK under PSD2) expose their own open APIs for account info and even for loans. For example, a bank might have an API to get a list of loan products or submit a loan application. These are typically OAuth-protected and standardized by Open Banking UK or Berlin Group standards. If integrating with a specific bank (say a partner bank that wants to offer loans through our wallet), we could connect directly to their API. The downside is handling each bank separately. This is where using an aggregator (like OBP or others) helps to avoid writing separate logic per bank.
Credit Bureau APIs: While not open banking per se, for loan processing we might want to integrate with credit scoring services (e.g., Experian, TransUnion provide APIs). Open-source solutions here are scarce due to the proprietary nature of credit data. However, integrating such API (if accessible for free in some contexts) can supplement open banking data to assess eligibility.
In summary, a likely approach for broad coverage is: Nordigen/Yapily for free account data in EU, Plaid for US/Canada (development use), and Fineract/OBP for managing the loan and connecting to lenders. We can cite an example: Lenders, a loan comparison platform in Europe, used Nordigen’s open banking to streamline loan applications, improving identity verification and automation finextra.com. This shows how connecting to bank data can speed up loan decisions and reduce paperwork.
Integration into a Kotlin Multiplatform App
Integrating open banking APIs in a KMP app involves both frontend (app) and possibly backend components:
Architecture Considerations: We should decide which calls are made directly from the app versus through a backend service. For security, sensitive operations (like exchanging tokens or storing API keys) are better done on a server. The mobile app can invoke the open banking SDK or a web-flow for user authentication, then receive a short-lived token or authorization code which it sends to our backend. The backend then interacts with the banking APIs using our secret credentials, and returns the needed data (account balances, etc.) to the app. This is the model Plaid and others recommend (the app gets a
public_token, the server exchanges it for aaccess_tokengithub.com).
However, since KMP allows us to share networking code, we could also call certain APIs directly if they allow public client usage. Nordigen’s API, for example, uses a secret key pair that could be safely stored in a secure storage on the app or issued via backend. Given it’s free, some developers call it directly from the app (but a more secure approach is to proxy through backend to avoid exposing keys).
Using Ktor for Networking: The shared KMP code can use Ktor HTTP client to make REST calls to open banking endpoints. Ktor is multiplatform, so the same code works on Android and iOS. For instance, to call Nordigen’s API to list banks, one could do:
val client = HttpClient() // Ktor client
val response = client.get("https://ob.nordigen.com/api/v2/institutions/?country=gb") {
header("Authorization", "Bearer $accessToken")
}
val institutions: List<BankInstitution> = response.body()This call would retrieve a list of available banks (institutions) for Great Britain in Nordigen’s system. We would have obtained $accessToken by first authenticating with our API keys (which can be done with a POST request to Nordigen’s token endpoint). Similarly, Ktor can be used to call Fineract or OBP APIs for submitting the loan application or retrieving loan status.
Platform-Specific SDKs: If using an SDK like Plaid Link, which provides a native UI to select a bank and login, we will integrate that in the Android and iOS UI modules (not in shared code). We’d use
expect/actualor just call it from Compose’s Platform-specific logic. The flow:
User clicks “Link Bank Account” in our app’s Loan section.
On Android: launch Plaid Link via its
Intentor Compose wrapper, on iOS: launch via Plaid’s iOS SDK method. These will present a secure webview for bank login.The result will be a callback with a
public_token(temporary token).The app then calls our backend (or Plaid’s API) to exchange
public_tokenfor a permanentaccess_tokenand anitem_id(identifying the bank account).Once we have
access_token, we can use either Plaid’s API (through Ktor HTTP calls from shared code, as Plaid API is a normal HTTPS API) to fetch transactions, balances, etc., or send the token to our backend to do the fetching and return processed data.
The extra step of a backend is recommended because it can also store the access_token for future use (so the app doesn’t need to re-authenticate repeatedly) and because some APIs require client secrets.
Data Storage and Models: In the shared domain model, define data classes for BankAccount, Transaction, LoanOffer, LoanApplication, etc. For example,
BankAccount(balance: Double, bankName: String, accountId: String)or similar. After fetching data from open banking, populate these models so we can display info to the user or send to lenders. Also defineLoanApplicationRequest(amount, term, income, ... )that combines user input with fetched data.Loan Offer Discovery: Depending on how we connect to lenders, there are two paths:
Single Lender (Direct): The app integrates with a specific bank’s loan API. Then the flow is straightforward: the user applies and we send the application to that bank’s API. E.g., if our partner bank “XYZ” has an open API endpoint
/loans/apply, we call that with the user’s data. The response might be immediate approval or a pending status.Loan Marketplace: Multiple lenders offer loans, and we want to pick the best offer. This requires either an aggregator or our own logic. For instance, PhonePe Business shows multiple loan offers from different partnered institutions. We could implement a simple marketplace where our backend pings multiple lender APIs (if available) with the user’s profile and gets offers (interest rate, max amount). The app then displays these for the user to choose. This approach likely needs a custom backend component because coordinating multiple external APIs and selecting best offers is server-side work.
Alternative: Use a third-party loan marketplace API. There are fintech APIs that aggregate loan offers (for example, in some regions, services that provide an endpoint: input user financial data, output a list of pre-qualified loan offers). If such a free/open API exists, we could integrate that. If not, we implement our own using a combination of open banking data and maybe simple rules for a few partners.
Sample API Calls & Documentation:
Using Fineract API: To submit a loan via Mifos/Fineract, one would call the self-service loan application endpoint. For example,
POST /loanswith a JSON body including clientId, loanProductId, principal, etc., as per Fineract API docs. A successful response creates a loan account which can then be approved/disbursed via workflow or auto-approved if configured.Using Nordigen:
POST /api/v2/token/newwith our API secret -> returns access token.GET /api/v2/institutions/?country=US-> list of banks (for user to choose).POST /api/v2/requisitions/with chosen institution ID and a redirect URL -> returns a link to that bank’s consent page.Open that link (in external browser or webview) – user logs in and consents.
The redirect goes to our specified URL (we catch an authorization code from it).
GET /api/v2/requisitions/{id}-> gives associated account IDs now linked.GET /api/v2/accounts/{accountId}/transactions/-> returns transactions JSON.We parse transactions to get monthly income, etc.
All these can be done with Ktor. Nordigen’s documentation provides example requests and responses fintech-market.com, and since it’s free, we can test with sandbox banks.
Using Plaid:
On client: open Link (no direct HTTP call).
On server:
POST /item/public_token/exchangeto trade public token for access token.Then either server or client:
POST /income/verificationorGET /transactionsetc., using access token in Authorization header.Plaid’s docs (http://plaid.com ) have detailed JSON specs for each endpoint; we would follow those. For instance,
GET /transactionsreturns transactions with categories, merchant names, etc., which we can feed into an algorithm for credit scoring.
Open Bank Project: If we had OBP, we’d use their API calls like:
GET /obp/v4.0.0/banks/{bankId}/accounts/{accountId}/transactionsfor account data, and if a bank had loan products, maybe an endpoint likePOST /banks/{bankId}/loan-applications(this would be custom if at all). OBP’s advantage is standardization; it even has a sandbox with dummy data.