Skip to main content
RapidDev - Software Development Agency
flutterflow-tutorials

How to Create a Peer-to-Peer Payment System in FlutterFlow

Create a peer-to-peer payment system by building digital wallets stored as Firestore documents with a balance field. Transfer money between users via a Cloud Function that executes atomic Firestore transactions to debit the sender and credit the recipient simultaneously. Add payment request functionality where users can request money from others, a unified transaction history timeline, and a bill-splitting feature that divides totals and sends payment requests to multiple friends.

What you'll learn

  • How to implement wallet-based transfers with Firestore transactions
  • How to build a payment request flow with accept and decline actions
  • How to display a unified transaction history for sent and received payments
  • How to create a bill-splitting feature that generates multiple payment requests
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner9 min read30-40 minFlutterFlow Pro+ (Cloud Functions required for atomic transfers)March 2026RapidDev Engineering Team
TL;DR

Create a peer-to-peer payment system by building digital wallets stored as Firestore documents with a balance field. Transfer money between users via a Cloud Function that executes atomic Firestore transactions to debit the sender and credit the recipient simultaneously. Add payment request functionality where users can request money from others, a unified transaction history timeline, and a bill-splitting feature that divides totals and sends payment requests to multiple friends.

Building a Peer-to-Peer Payment System in FlutterFlow

Peer-to-peer payments let users send money directly to each other within your app. This tutorial builds a complete P2P system with wallet balances, instant transfers, payment requests, transaction history, and bill splitting. All transfers use Firestore transactions via Cloud Functions to ensure money never gets lost in transit.

Prerequisites

  • A FlutterFlow project with Firestore and authentication configured
  • Firebase Cloud Functions enabled for atomic transfer logic
  • A wallets collection with balance field for each user
  • Basic familiarity with Cloud Functions and Firestore transactions

Step-by-step guide

1

Set up the Firestore data model for wallets, transactions, and requests

Create a wallets collection with fields: userId (String), balance (Double, default 0), lastUpdatedAt (Timestamp). Each user gets one wallet document, created on signup. Create a transactions collection with fields: fromUserId (String), toUserId (String), amount (Double), message (String, optional), type (String: send, receive, request_paid), timestamp (Timestamp). Create a payment_requests collection with fields: fromUserId (String), toUserId (String), amount (Double), message (String), status (String: pending, paid, declined), createdAt (Timestamp), resolvedAt (Timestamp, nullable). Add indexes on transactions for userId lookups and on payment_requests for status filtering.

Expected result: Firestore has wallets, transactions, and payment_requests collections ready for P2P operations.

2

Build the wallet home page with balance and quick actions

Create a WalletPage with the user's balance displayed prominently at the top in a Container with large styled text. Below the balance, add a Row with three action buttons: Send (paper plane icon), Request (hand icon), and Split (group icon). Below the actions, add a ListView showing recent transactions, querying the transactions collection where either fromUserId or toUserId equals the current user, ordered by timestamp descending, limited to the 10 most recent. Each transaction row shows the other user's name, the amount (green with + for received, red with - for sent), the message if any, and the timestamp. Add a 'See All' link that navigates to a full transaction history page.

Expected result: A wallet home screen showing the current balance, quick action buttons, and a feed of recent transactions.

3

Implement the send money flow with atomic Firestore transactions

On the Send button tap, navigate to a SendMoneyPage. Add a recipient search TextField that queries users by email or display name and shows results in a dropdown ListView. After selecting a recipient, show their avatar and name. Add an amount TextField with numeric keyboard and a message TextField. The Send button calls a Cloud Function named transferFunds that takes senderId, recipientId, amount, and message. The Cloud Function uses a Firestore transaction: read sender's wallet balance, verify balance is sufficient, debit sender (decrement balance), credit recipient (increment balance), create two transaction documents (one for sender, one for recipient). If balance is insufficient, the function throws an error that the client displays.

transfer_funds.js
1// Cloud Function: transferFunds (simplified)
2const functions = require('firebase-functions');
3const admin = require('firebase-admin');
4
5exports.transferFunds = functions.https.onCall(async (data, context) => {
6 const { recipientId, amount, message } = data;
7 const senderId = context.auth.uid;
8 const db = admin.firestore();
9
10 await db.runTransaction(async (t) => {
11 const senderWallet = await t.get(db.doc(`wallets/${senderId}`));
12 const recipientWallet = await t.get(db.doc(`wallets/${recipientId}`));
13
14 const senderBalance = senderWallet.data().balance;
15 if (senderBalance < amount) throw new Error('Insufficient balance');
16
17 t.update(senderWallet.ref, { balance: senderBalance - amount });
18 t.update(recipientWallet.ref, {
19 balance: recipientWallet.data().balance + amount
20 });
21 t.create(db.collection('transactions').doc(), {
22 fromUserId: senderId, toUserId: recipientId,
23 amount, message, type: 'send', timestamp: admin.firestore.Timestamp.now()
24 });
25 });
26 return { success: true };
27});

Expected result: Sending money atomically debits the sender's wallet and credits the recipient's wallet, with a transaction record for both.

4

Build the payment request flow with accept and decline

On the Request button tap, navigate to a RequestMoneyPage with the same recipient search and amount fields. On submit, create a payment_requests document with status set to pending. The recipient sees pending requests on their WalletPage: add a section above transactions showing a ListView of payment_requests where toUserId equals current user and status is pending. Each request card shows the requester's name, amount, message, and two buttons: Pay and Decline. Pay calls the transferFunds Cloud Function with the request amount (sender is the current user, recipient is the requester) and then updates the payment_requests document status to paid with resolvedAt timestamp. Decline updates the status to declined.

Expected result: Users can request money from others, and recipients see pending requests with one-tap Pay or Decline actions.

5

Add bill splitting functionality

On the Split button tap, navigate to a SplitBillPage. Add a total amount TextField at the top. Below, add a friends selector: query the user's contacts or friends and display them as selectable avatars in a Wrap widget. Tapped friends get a checkmark overlay and are added to a Page State selectedFriends list. Show the calculated per-person amount below: total divided by (selected friends + 1 for the current user), rounded to two decimal places. Add a tip adjustment Slider optionally. On Split, create a payment_request for each selected friend with the per-person amount and a message like 'Split: Dinner at Restaurant - your share'. Display a confirmation showing all requests sent.

Expected result: Users can enter a bill total, select friends, and automatically generate payment requests for each person's equal share.

6

Build the full transaction history with filters

Create a TransactionHistoryPage with a ChoiceChips filter at the top: All, Sent, Received, Requests. The All tab queries transactions where fromUserId or toUserId equals current user. The Sent tab filters to fromUserId. The Received tab filters to toUserId. The Requests tab shows payment_requests for the current user. Each transaction row includes a direction indicator icon (arrow up for sent, arrow down for received), the other party's name and avatar, the amount with color coding, the message, and the date. Add a DatePicker range at the top for filtering by time period. At the bottom, show a summary: total sent and total received for the selected period.

Expected result: A complete transaction history with type filters, date range selection, and period summary totals.

Complete working example

FlutterFlow P2P Payment Setup
1FIRESTORE DATA MODEL:
2 wallets/{userId}
3 userId: String
4 balance: Double
5 lastUpdatedAt: Timestamp
6
7 transactions/{transactionId}
8 fromUserId: String
9 toUserId: String
10 amount: Double
11 message: String (optional)
12 type: "send" | "receive" | "request_paid"
13 timestamp: Timestamp
14
15 payment_requests/{requestId}
16 fromUserId: String (requester)
17 toUserId: String (payer)
18 amount: Double
19 message: String
20 status: "pending" | "paid" | "declined"
21 createdAt: Timestamp
22 resolvedAt: Timestamp (nullable)
23
24PAGE: WalletPage
25WIDGET TREE:
26 Column
27 Container (balance display, large text)
28 Row (quick actions)
29 Button (Send SendMoneyPage)
30 Button (Request RequestMoneyPage)
31 Button (Split SplitBillPage)
32 Text ("Pending Requests")
33 ListView (payment_requests, status == pending, toUserId == me)
34 Container (request card)
35 Text (requester name + amount)
36 Button (Pay transferFunds + update request)
37 Button (Decline update request status)
38 Text ("Recent Activity")
39 ListView (transactions, limit 10, order by timestamp)
40 Container (transaction row)
41 Icon (arrow up/down)
42 Column (name + message)
43 Text (amount, green/red)
44
45PAGE: SendMoneyPage
46WIDGET TREE:
47 Column
48 TextField (search recipient by email/name)
49 ListView (search results)
50 Container (selected recipient: avatar + name)
51 TextField (amount, numeric)
52 TextField (message, optional)
53 Button (Send Cloud Function transferFunds)
54
55PAGE: SplitBillPage
56WIDGET TREE:
57 Column
58 TextField (total amount)
59 Wrap (friend avatars, tappable to select)
60 Text ("Each person pays: ${total / (selected + 1)}")
61 Slider (tip adjustment, optional)
62 Button (Split create payment_requests for each friend)

Common mistakes when creating a Peer-to-Peer Payment System in FlutterFlow

Why it's a problem: Not using a Firestore transaction for the wallet transfer

How to avoid: Always use a Firestore transaction in a Cloud Function that reads both wallets, verifies the balance, and writes both updates atomically. If any step fails, the entire transaction rolls back.

Why it's a problem: Allowing wallet balance updates directly from the client

How to avoid: Set Firestore Security Rules to deny client writes to the wallets collection. Only Cloud Functions with admin SDK access should modify wallet balances.

Why it's a problem: Not rounding currency amounts to two decimal places

How to avoid: Round all currency calculations to two decimal places. In the split bill function, assign any remainder cents to the first person so the total always matches exactly.

Best practices

  • Use Firestore transactions via Cloud Functions for all balance-modifying operations
  • Deny client-side writes to wallet documents in Firestore Security Rules
  • Round all currency values to two decimal places consistently
  • Create transaction records for both sender and recipient for complete audit trails
  • Show pending payment requests prominently on the wallet home page
  • Color-code transactions green for received and red for sent for quick scanning
  • Add confirmation dialogs before sending money to prevent accidental transfers

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I want to build a peer-to-peer payment system in FlutterFlow with Firestore. Show me the data model for wallets, transactions, and payment requests, a Cloud Function for atomic transfers using Firestore transactions, a payment request flow with accept/decline, and a bill splitting feature.

FlutterFlow Prompt

Create a wallet home page with a large balance number at the top, three action buttons (Send, Request, Split) in a row below, a pending requests section, and a list of recent transactions with green and red amount labels.

Frequently asked questions

How do users add money to their wallet?

Integrate Stripe or another payment gateway. Create a Cloud Function that handles a Stripe Checkout session for wallet top-up. On successful payment, the webhook triggers a wallet balance increment. Display an Add Funds button on the wallet page.

Can I add transaction fees to P2P transfers?

Yes. In the transferFunds Cloud Function, calculate a fee (e.g., 1% of the amount) and deduct it from the transferred amount. Create a separate transaction record for the fee. Credit the fee to a platform wallet for your business revenue.

How do I prevent users from going into negative balance?

The Cloud Function checks the sender's balance before executing the transfer. If balance is less than the transfer amount, the function throws an error. The client catches this and displays an insufficient funds message.

Can I add recurring payments between users?

Yes. Create a recurring_payments collection with sender, recipient, amount, frequency (weekly/monthly), and nextPaymentDate. A scheduled Cloud Function runs daily, finds due payments, and calls transferFunds for each one.

How do I handle unequal bill splits?

On the SplitBillPage, add a toggle between Equal Split and Custom Split. In custom mode, show a TextField per person where the organizer can type each person's specific amount. Validate that all amounts sum to the total before creating requests.

Can RapidDev help build a fintech payment application?

Yes. RapidDev can implement full payment platforms with KYC verification, multi-currency wallets, bank account integration, transaction fraud detection, regulatory compliance, and detailed financial reporting.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.