Connect FlutterFlow to 2Checkout (now Verifone) using an API Call group pointed at a Firebase Cloud Function that handles HMAC-SHA256 request signing with your Secret Key. For the easiest checkout path, embed a hosted Verifone Buy Link in a Custom Widget WebView — this keeps the Secret Key entirely off-device and avoids complex signature logic in FlutterFlow.
| Fact | Value |
|---|---|
| Tool | 2Checkout (now Verifone) |
| Category | Payments |
| Method | FlutterFlow API Call |
| Difficulty | Advanced |
| Time required | 90 minutes |
| Last updated | July 2026 |
2Checkout (Verifone): HMAC Signing or Buy Link WebView
2Checkout was acquired by Verifone in 2020 and rebranded, though developers often still search for it by the original name. The platform focuses on digital goods, subscriptions, and global commerce — it's particularly popular with software companies selling worldwide. In FlutterFlow, connecting to 2Checkout involves a security challenge that distinguishes it from simpler REST integrations: every API request must carry an HMAC-SHA256 signature computed from your Secret Key plus a date header. Since the Secret Key must never live in a compiled Flutter app, the signature computation must happen on a server.
There are two practical paths in FlutterFlow. The first is the hosted Buy Link: 2Checkout/Verifone provides a URL for each product (available in the Merchant Control Panel → Products) that opens a fully hosted checkout page managed by Verifone. You embed this URL in a Custom Widget WebView inside your FlutterFlow app, the customer pays, and Verifone redirects back to a return URL you specify. This path requires no HMAC signing, no Cloud Function for the initial checkout, and is the fastest way to accept payments. Its limitation is less customization and a redirect experience rather than a native checkout sheet.
The second path is the REST API through a Firebase Cloud Function proxy. For order management, subscription lookups, refunds, and custom checkout flows, you call a Cloud Function that generates the HMAC-SHA256 signature header, appends it to the request, and calls https://api.2checkout.com/rest/6.0. Your FlutterFlow API Call hits the Cloud Function URL — never 2Checkout directly. IPN (Instant Payment Notification) confirmations — the equivalent of webhooks — also require a Cloud Function endpoint registered in your 2Checkout dashboard, since FlutterFlow apps can't receive incoming HTTP requests. Note: pricing is plan-dependent and not published on the current Verifone website — verify current rates directly with Verifone.
Integration method
2Checkout (Verifone) has no native FlutterFlow support. Every REST API call to https://api.2checkout.com/rest/6.0 must carry an HMAC-SHA256 X-Avangate-Authentication header computed from your Secret Key and a date string — a computation that must happen server-side because the Secret Key cannot live in a client-side Flutter app. The recommended approach has two paths: a Firebase Cloud Function that signs requests and proxies them to the REST API (for order management and subscriptions), or a hosted Buy Link embedded in a Custom Widget WebView (for simple one-time checkout with zero client-side logic).
Prerequisites
- A 2Checkout / Verifone merchant account — sign up at verifone.com or the legacy 2checkout.com portal
- Your Merchant Code (public, visible in account settings) and Secret Key (private, from Account → Integrations → Secret Word/Key)
- A Firebase project on the Blaze plan for Cloud Functions
- A FlutterFlow project with Firebase connected (Settings → Firebase)
- At least one product configured in the 2Checkout Merchant Control Panel with a hosted Buy Link URL
Step-by-step guide
Locate your Merchant Code, Secret Key, and a product Buy Link
Log in to your 2Checkout/Verifone Merchant Control Panel at secure.2checkout.com (or the Verifone equivalent if your account has been migrated). Navigate to Account → Integrations → API & Webhooks section. Here you'll find two critical values: **Merchant Code**: a short alphanumeric string (e.g., 'ABCDE12345') that publicly identifies your merchant account in API requests. This is safe to store in FlutterFlow as an App Value (App Settings → App Values) — it's not a secret. **Secret Key**: a long string used to compute HMAC-SHA256 signatures. This MUST stay in your Firebase Cloud Function environment variable — never enter it into FlutterFlow. While in the Merchant Control Panel, navigate to Products → your product → click on it → look for the Buy Link URL. It looks like: `https://secure.2checkout.com/checkout/buy/?merchant=MERCHANTCODE&tpl=default&prod=PRODUCTCODE`. Save this URL. For the WebView approach in Step 3, you'll embed this URL directly — no HMAC signing needed. Also navigate to Account → Integrations → IPN Settings. You'll add an IPN URL here in a later step, once your Firebase Cloud Function is deployed. IPN is how 2Checkout tells your server about completed payments, charge-backs, and refunds — it's the equivalent of webhooks and is the only reliable server-side payment confirmation.
Pro tip: The Verifone rebrand has been gradual — some accounts still log in at secure.2checkout.com while others are on the Verifone portal. If you're not sure which URL to use, check the welcome email from when you signed up, or contact Verifone support.
Expected result: You have your Merchant Code (stored in FlutterFlow App Values), Secret Key (ready for Cloud Function environment), and at least one product's Buy Link URL.
Deploy a Firebase Cloud Function for HMAC signing and API proxying
The Cloud Function is the heart of your 2Checkout integration. It does three things: generates the HMAC-SHA256 X-Avangate-Authentication header on every request (using your Secret Key, Merchant Code, and current timestamp), proxies the signed request to https://api.2checkout.com/rest/6.0, and returns the response to FlutterFlow. The authentication header format required by 2Checkout is: `code="MERCHANTCODE" date="DATE" hash="HMAC_SHA256_HEX"`. The HMAC input string is `strlen(MERCHANTCODE) . MERCHANTCODE . strlen(DATE) . DATE` where strlen is a character count (not a hash). An incorrect format returns AUTHORIZATION_ERROR — the exact error string from 2Checkout's API. In your Firebase project's `functions/index.js`, paste the code below. Set environment variables before deploying: ``` firebase functions:config:set twocheckout.merchant_code='YOUR_CODE' twocheckout.secret_key='YOUR_SECRET' ``` Then deploy: `firebase deploy --only functions:twocheckoutProxy`. The function exposes a POST endpoint that accepts `{ endpoint, method, body }` from FlutterFlow — the endpoint is a relative path like '/orders' or '/subscriptions', the method is GET/POST, and body is the request body (for POST calls). The function constructs the full URL, adds the HMAC header, and forwards the request.
1const functions = require('firebase-functions');2const axios = require('axios');3const crypto = require('crypto');45// Generates the 2Checkout/Avangate HMAC-SHA256 authentication header6function generateAuthHeader(merchantCode, secretKey) {7 const date = new Date().toGMTString();8 const hmacInput = `${merchantCode.length}${merchantCode}${date.length}${date}`;9 const hmac = crypto10 .createHmac('sha256', secretKey)11 .update(hmacInput)12 .digest('hex');13 return {14 authHeader: `code="${merchantCode}" date="${date}" hash="${hmac}"`,15 };16}1718exports.twocheckoutProxy = functions.https.onRequest(async (req, res) => {19 res.set('Access-Control-Allow-Origin', '*');20 if (req.method === 'OPTIONS') {21 res.set('Access-Control-Allow-Methods', 'POST');22 res.set('Access-Control-Allow-Headers', 'Content-Type');23 return res.status(204).send('');24 }2526 const merchantCode = functions.config().twocheckout.merchant_code;27 const secretKey = functions.config().twocheckout.secret_key;28 const { endpoint, method = 'GET', body } = req.body;2930 if (!endpoint) {31 return res.status(400).json({ error: 'Missing endpoint parameter' });32 }3334 const { authHeader } = generateAuthHeader(merchantCode, secretKey);35 const baseUrl = 'https://api.2checkout.com/rest/6.0';3637 try {38 const response = await axios({39 method: method.toLowerCase(),40 url: `${baseUrl}${endpoint}`,41 data: body || undefined,42 headers: {43 'X-Avangate-Authentication': authHeader,44 'Content-Type': 'application/json',45 'Accept': 'application/json',46 },47 });48 return res.status(200).json(response.data);49 } catch (error) {50 const errData = error.response?.data || { error: error.message };51 return res.status(error.response?.status || 500).json(errData);52 }53});Pro tip: The HMAC date must be the current GMT time at the moment of the request — do NOT cache or reuse the auth header between requests. Each call generates a fresh header.
Expected result: Firebase Console shows twocheckoutProxy function deployed. You have the function URL (e.g. https://us-central1-PROJECT_ID.cloudfunctions.net/twocheckoutProxy) ready.
Embed a hosted Buy Link in a Custom Widget WebView (simplest checkout)
For straightforward product checkout — the most common use case — you don't need to call the REST API at all. 2Checkout/Verifone provides a hosted checkout page for every product that handles card entry, currency conversion, and receipt delivery. Embedding it as a WebView Custom Widget in FlutterFlow is the fastest path to a working checkout. In FlutterFlow, go to Custom Code in the left nav → + Add → Widget. Name it 'TwoCheckoutWebView'. In the Dependencies field, add 'webview_flutter' (latest stable, currently 4.x on pub.dev). Set two parameters: `checkoutUrl` (String) — the Buy Link URL — and `returnUrl` (String) — the URL you want 2Checkout to redirect to after payment. Paste the Dart code below, which displays the WebView and monitors URL changes. When the WebView navigates to your return URL, the widget calls an optional callback so your FlutterFlow Action Flow can show a success screen. On your checkout screen, drag the TwoCheckoutWebView widget from the Components panel, set the `checkoutUrl` to your product's Buy Link (from App Values), and set `returnUrl` to a URL you control (e.g. https://yourapp.com/payment-success — this URL doesn't need to serve anything real, it's just a signal). When 2Checkout redirects to that URL after payment, the WebView detects it and fires the success callback. For the customer, the experience is: tap 'Buy' → in-app browser opens → complete checkout in Verifone's hosted page → app shows confirmation screen. No card data ever enters FlutterFlow's widget tree.
1import 'package:webview_flutter/webview_flutter.dart';23class TwoCheckoutWebView extends FlutterFlowWidget {4 const TwoCheckoutWebView({5 super.key,6 required this.checkoutUrl,7 required this.returnUrl,8 this.onPaymentSuccess,9 });1011 final String checkoutUrl;12 final String returnUrl;13 final Future<void> Function()? onPaymentSuccess;1415 @override16 State<TwoCheckoutWebView> createState() => _TwoCheckoutWebViewState();17}1819class _TwoCheckoutWebViewState extends State<TwoCheckoutWebView> {20 late final WebViewController _controller;2122 @override23 void initState() {24 super.initState();25 _controller = WebViewController()26 ..setJavaScriptMode(JavaScriptMode.unrestricted)27 ..setNavigationDelegate(28 NavigationDelegate(29 onNavigationRequest: (request) {30 // Detect redirect to your return URL31 if (request.url.startsWith(widget.returnUrl)) {32 widget.onPaymentSuccess?.call();33 return NavigationDecision.prevent;34 }35 return NavigationDecision.navigate;36 },37 ),38 )39 ..loadRequest(Uri.parse(widget.checkoutUrl));40 }4142 @override43 Widget build(BuildContext context) {44 return WebViewWidget(controller: _controller);45 }46}Pro tip: Test the returnUrl redirect on both iOS and Android — iOS uses WKWebView and Android uses WebView with slightly different redirect-handling timing. Both should work with this NavigationDelegate pattern.
Expected result: The TwoCheckoutWebView Custom Widget appears in FlutterFlow's component list and can be placed on a screen. Tapping the Buy button (which calls a Navigate action to the checkout screen) shows the hosted 2Checkout page inside the app.
Create a FlutterFlow API Call to trigger the Cloud Function for REST operations
For order lookup, subscription management, refunds, or any REST API operation beyond simple checkout, set up an API Call in FlutterFlow that hits your Cloud Function. In the left nav, click API Calls → + Add → Create API Group. Name it '2CheckoutAPI'. Set the base URL to your Cloud Function URL (e.g. https://us-central1-PROJECT_ID.cloudfunctions.net). Leave Authentication as 'None' — the Cloud Function handles auth internally. Inside the group, click + Add API Call. Name it 'ProxyRequest'. Set the Method to POST. Set the endpoint to '/twocheckoutProxy'. In the Body tab, set body type to JSON and define three variables: - `endpoint` (String) — the 2Checkout API path, e.g. '/orders' or '/subscriptions/{{subscriptionId}}' - `method` (String) — 'GET' or 'POST' - `body` (JSON Object) — the request body for POST calls; pass an empty object for GETs Body template: ``` { "endpoint": "{{ endpoint }}", "method": "{{ method }}", "body": {{ body }} } ``` In Response & Test, paste a sample order response from the 2Checkout REST API documentation (or from a real test call). Click 'Generate JSON Paths' to create path variables for the fields you need — for example, `$.Status` for order status, `$.RefNo` for the order reference number, `$.Items[0].Name` for the first item name. For a subscription lookup, set `endpoint` to '/subscriptions' and `method` to 'GET'. For creating an order, set `endpoint` to '/orders' and `method` to 'POST' with the order body in the body variable. The Cloud Function handles signing both types of requests transparently.
1{2 "endpoint": "{{ endpoint }}",3 "method": "{{ method }}",4 "body": {{ body }}5}Pro tip: The 2Checkout REST API returns deeply nested JSON — map only the fields you need using JSON Path. For order status, the key path is typically $.Status (values: 'PAYMENT_AUTHORIZED', 'COMPLETE', 'REVERSED').
Expected result: API Call test returns 200 with a JSON body. JSON Paths are generated for order status, reference number, and any other fields you need.
Set up an IPN handler Cloud Function for server-side payment confirmation
The Buy Link WebView shows a success screen when the user is redirected, but the redirect alone is not a trustworthy confirmation — it can be triggered by the user navigating to the return URL manually. The authoritative payment confirmation comes from 2Checkout's IPN (Instant Payment Notification) — a server-to-server POST request that 2Checkout sends to your registered endpoint when a payment completes, fails, or is refunded. Create a second Firebase Cloud Function to receive IPN events. In your `functions/index.js`, add the IPN handler shown below. The IPN request contains order data plus a `HASH` parameter — verify this hash before trusting the data (compute it the same way as the authentication header and compare). The IPN handler should: 1. Verify the HASH to confirm the request is from 2Checkout (reject if mismatched — someone is spoofing) 2. Parse the order status and reference number from the IPN fields 3. Update the corresponding Firestore document (matched by order reference) to status 'paid' 4. Return HTTP 200 with the string 'AUTHORIZEDSALE' in the body — 2Checkout checks for this exact response and retries if it doesn't receive it After deploying the IPN function, register its URL in the 2Checkout Merchant Control Panel: Account → Integrations → IPN → Add URL → paste your Cloud Function URL. Select the event types you want to receive (at minimum: ORDER_CREATED, FRAUD_STATUS_CHANGED, REFUND_ISSUED). IPN is not real-time — it can arrive seconds to minutes after the payment. Show a 'Processing your order...' screen after the WebView redirect and poll Firestore for the status update rather than assuming it's immediate.
1const crypto = require('crypto');23exports.twocheckoutIPN = functions.https.onRequest(async (req, res) => {4 const secretKey = functions.config().twocheckout.secret_key;5 const params = req.body;67 // Verify IPN HASH8 // 2Checkout signs IPN with HMAC-MD5 of specific fields (see 2CO docs for field order)9 // Implementation: sort all fields alphabetically, concatenate values, HMAC-MD5 with secret10 const receivedHash = params.HASH;11 delete params.HASH;1213 const sortedKeys = Object.keys(params).sort();14 const dataString = sortedKeys15 .map(k => `${String(params[k]).length}${params[k]}`)16 .join('');1718 const computedHash = crypto19 .createHmac('md5', secretKey)20 .update(dataString)21 .digest('hex');2223 if (computedHash.toLowerCase() !== receivedHash.toLowerCase()) {24 console.error('IPN hash mismatch — possible spoofing');25 return res.status(403).send('HASH_MISMATCH');26 }2728 // Update Firestore with order status29 const admin = require('firebase-admin');30 if (!admin.apps.length) admin.initializeApp();31 const db = admin.firestore();3233 const orderRef = params.REFNOEXT; // Your internal order reference34 const orderStatus = params.ORDERSTATUS; // e.g. 'PAYMENT_AUTHORIZED', 'COMPLETE'3536 await db.collection('orders').doc(orderRef).update({37 status: orderStatus,38 twocheckoutRef: params.REFNO,39 updatedAt: admin.firestore.FieldValue.serverTimestamp(),40 });4142 // 2Checkout expects this exact response to confirm receipt43 return res.status(200).send('AUTHORIZEDSALE');44});Pro tip: 2Checkout retries IPN delivery up to 24 hours if it doesn't receive the 'AUTHORIZEDSALE' response. Make your handler idempotent — multiple deliveries of the same IPN should not create duplicate Firestore updates (use Firestore's merge: true option or check if the field is already set).
Expected result: IPN Cloud Function deployed. URL registered in 2Checkout Merchant Control Panel → IPN Settings. Test IPN delivery from the dashboard returns AUTHORIZEDSALE response.
Wire the checkout flow in FlutterFlow and handle order status
With the WebView widget, Cloud Function proxy, and IPN handler in place, connect everything in your FlutterFlow UI. On your checkout screen, place the TwoCheckoutWebView Custom Widget and set its `checkoutUrl` to your product Buy Link (an App Value constant or a dynamic URL with product code appended). Set `returnUrl` to your return URL. Configure the `onPaymentSuccess` callback: in the Action Flow, this callback triggers when the WebView detects the redirect to your return URL. In the `onPaymentSuccess` Action Flow: 1. Create a Firestore document in 'orders' with: userId (from Authenticated User), orderStatus 'pending', createdAt (current datetime), and an orderRef (generate a UUID as your REFNOEXT — this should be passed as a URL parameter in the Buy Link, e.g. `&REFNOEXT=UUID`, so 2Checkout includes it in the IPN). 2. Navigate to an 'Order Pending' screen that shows 'We're confirming your payment...' with a loading indicator. 3. On the 'Order Pending' screen, set up a Firestore Document listener (the document you just created) — when the `status` field changes from 'pending' to 'COMPLETE' or 'PAYMENT_AUTHORIZED', the IPN Cloud Function will have updated it. Use a Conditional Widget or Action to navigate to a 'Payment Confirmed' screen when the status updates. For the REST API path (subscription or order management), add buttons on a 'My Account' screen that trigger API Calls to the ProxyRequest API Call with appropriate endpoint and method values. Parse the JSON Path variables and display them in Text widgets. If you'd rather skip the Cloud Function setup and IPN configuration, RapidDev's team builds FlutterFlow payment integrations like this every week — free scoping call at rapidevelopers.com/contact.
Pro tip: Append your REFNOEXT parameter to the Buy Link URL dynamically: '${buyLinkBaseUrl}&REFNOEXT=${orderId}'. 2Checkout passes this value back in the IPN, letting your Cloud Function match the IPN to the correct Firestore document.
Expected result: Tapping Buy opens the hosted checkout page in the WebView. On payment, the WebView fires onPaymentSuccess, a Firestore 'pending' order is created, and the IPN Cloud Function later updates it to 'COMPLETE'. The app navigates to a confirmation screen.
Common use cases
SaaS app selling software subscriptions globally
A productivity or utility app built in FlutterFlow uses 2Checkout to sell annual software licenses. The app displays a product detail screen with a 'Buy Now' button that opens a 2Checkout hosted Buy Link in a Custom Widget WebView. On successful payment, the IPN Cloud Function updates the user's subscription status in Firestore, unlocking premium features.
A task manager app where users can buy a Pro license for $49/year — tapping 'Upgrade to Pro' opens a 2Checkout checkout page in-app, and the app shows premium features as soon as payment is confirmed via IPN.
Copy this prompt to try it in FlutterFlow
Digital content marketplace with subscription tiers
An e-learning or media FlutterFlow app where users subscribe to monthly or annual content access. The app calls a Cloud Function to create a 2Checkout Subscription (POST /rest/6.0/subscriptions), stores the subscription ID in Firestore, and displays subscription status in the profile screen.
An online course platform where students subscribe to a monthly plan — the app creates the subscription via a Cloud Function, sends a confirmation email through 2Checkout, and unlocks course content in Firestore.
Copy this prompt to try it in FlutterFlow
Global software license reseller app
A reseller or affiliate FlutterFlow app that surfaces 2Checkout products from a catalog, displays local currency pricing (via 2Checkout's pricing endpoints), and redirects users to hosted Buy Links for checkout. Order history is fetched from the 2Checkout REST API via the Cloud Function proxy.
A software bundle app showing a catalog of products with country-localized pricing — tapping a product opens the hosted Buy Link checkout, and past orders are shown in a 'My Licenses' screen pulled from 2Checkout's REST API.
Copy this prompt to try it in FlutterFlow
Troubleshooting
AUTHORIZATION_ERROR returned by the 2Checkout API
Cause: The HMAC-SHA256 signature is incorrectly computed — usually due to a wrong date format, incorrect string concatenation (strlen prefix is a character count, not a hash), or a stale date header reused from a previous request.
Solution: Verify the auth header construction: the input string must be exactly `${merchantCode.length}${merchantCode}${date.length}${date}` where the date is the current GMT string at request time, not a cached value. Each API call must generate a fresh HMAC with the current date. Log the `hmacInput` string and `date` in the Cloud Function to debug.
1const hmacInput = `${merchantCode.length}${merchantCode}${date.length}${date}`;IPN not being received — order status stays 'pending' in Firestore
Cause: The IPN URL was not registered in the 2Checkout Merchant Control Panel, the Cloud Function URL is wrong or returning a non-200 response, or the function is not returning the exact string 'AUTHORIZEDSALE'.
Solution: In the 2Checkout dashboard → IPN Settings, verify the URL matches your deployed Cloud Function URL exactly. Check Firebase Console → Functions → Logs for the twocheckoutIPN function to see if requests are arriving. Ensure the response body is exactly the string 'AUTHORIZEDSALE' — 2Checkout checks for this literal string and retries if absent.
1return res.status(200).send('AUTHORIZEDSALE');WebView Buy Link checkout page does not load or shows blank screen
Cause: On web builds, Flutter's WebView widget may conflict with the web renderer (html vs canvaskit). On mobile, the webview_flutter plugin may not be compiled into the FlutterFlow build.
Solution: For web builds, switch Flutter's web renderer to 'html' instead of 'canvaskit' — add `--web-renderer html` as a custom build argument. For mobile, ensure the webview_flutter package is listed in your Custom Widget dependencies and test on a real device or downloaded build, not in FlutterFlow's web Run mode preview.
Return URL redirect not detected — app stays on the WebView page after payment
Cause: The returnUrl passed to the WebView widget doesn't exactly match the URL 2Checkout redirects to, or 2Checkout is appending query parameters that change the URL before the NavigationDelegate checks it.
Solution: Use `startsWith` (not exact equality) in the NavigationDelegate to match the return URL regardless of appended parameters. Also verify in the 2Checkout dashboard that the Approved URL (under your product settings) matches what you configured. 2Checkout redirects to the Approved URL, not an arbitrary URL you pass — configure your return URL there.
1if (request.url.startsWith(widget.returnUrl)) {Best practices
- Never put your 2Checkout Secret Key in a FlutterFlow API Call header — it compiles into the Flutter app bundle; always generate the HMAC signature in a Firebase Cloud Function.
- Generate a fresh HMAC-SHA256 date and signature for every API request — do not cache or reuse the X-Avangate-Authentication header.
- Use the hosted Buy Link WebView for simple product checkout rather than the full REST API — it's faster to implement, keeps card handling entirely within 2Checkout's PCI-compliant environment, and requires no HMAC signing on the checkout side.
- Set REFNOEXT on the Buy Link URL to a UUID you generate and store in Firestore — this lets the IPN Cloud Function match payment notifications to the correct order without guessing.
- Make your IPN handler idempotent: use Firestore's merge: true option so repeated IPN deliveries for the same order don't corrupt data.
- Always verify the IPN HASH before updating Firestore — failing to verify allows anyone to fake a 'payment confirmed' notification and access paid features for free.
- Show a 'Payment processing...' pending screen after the WebView redirect and poll Firestore for the IPN status update, since IPN delivery can take seconds to minutes.
- Test all event types (ORDER_CREATED, FRAUD_STATUS_CHANGED, REFUND_ISSUED) with 2Checkout's IPN test tool in the Merchant Control Panel before going live.
Alternatives
Stripe is natively supported in FlutterFlow with a built-in Payment action and no HMAC signing — choose Stripe if you're in a supported country and want the lowest-effort checkout setup.
Worldpay also requires a Cloud Function proxy (for OAuth2 token management) and is better suited for UK/European enterprise card processing with negotiated acquiring rates.
Adyen offers better multi-currency support and more payment methods for global commerce, though it also requires a custom API Call setup in FlutterFlow with no native support.
Frequently asked questions
Is 2Checkout the same as Verifone? What name should I use?
2Checkout was acquired by Verifone in 2020 and gradually rebranded. The product is increasingly referred to as 'Verifone' for online payments, but many developers, documentation pages, and API endpoints still use the '2Checkout' and 'Avangate' names. The REST API base URL (api.2checkout.com) and the HMAC header name (X-Avangate-Authentication) still use the legacy naming as of 2026. Use whichever name appears in your account portal — both refer to the same platform.
Can FlutterFlow receive 2Checkout IPN notifications directly?
No — FlutterFlow apps run on the user's device and can't expose a public HTTP endpoint for incoming webhooks or IPN events. You must register a Firebase Cloud Function URL (or Supabase Edge Function URL) in the 2Checkout Merchant Control Panel as your IPN endpoint. The function receives the IPN, verifies the HASH, and updates Firestore, which your app then reads via a real-time listener.
Do I need to implement the full REST API, or is the Buy Link enough?
For most apps selling one or a few products, the hosted Buy Link WebView is completely sufficient and significantly easier to implement. The REST API is needed when you want to: look up past orders in-app, manage subscriptions (pause, cancel, upgrade), process refunds, or build a custom checkout UI that doesn't redirect to 2Checkout's hosted page. Start with the Buy Link and add REST API calls only for features that require them.
What is the current pricing for 2Checkout / Verifone?
2Checkout's (Verifone's) pricing is plan-dependent and not publicly listed on the current website — rates vary by plan, region, and volume. Historically, rates have been in the 3–4% range per transaction plus a per-transaction fee, but you should verify current pricing directly with Verifone's sales team or in your merchant account dashboard. The platform does not have a self-serve free tier like Stripe's test mode, though a sandbox testing environment is available after account approval.
Why does the HMAC header need to be computed on the server and not in Dart?
The HMAC-SHA256 signature requires your 2Checkout Secret Key as the signing key. If you compute the signature in Dart — even in a Custom Action — the Secret Key must be present in the Dart code, which compiles into the Flutter app bundle on the user's device. Anyone can decompile a Flutter app and extract hardcoded strings. Keeping the Secret Key in a Firebase Cloud Function environment variable means it never leaves the server, protecting your account from unauthorized API access.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation