# 2Checkout (now Verifone)

- Tool: FlutterFlow
- Difficulty: Advanced
- Time required: 90 minutes
- Last updated: July 2026

## TL;DR

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.

## 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.

## Before you start

- 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

### 1. 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.

**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.

### 2. 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.

```
const functions = require('firebase-functions');
const axios = require('axios');
const crypto = require('crypto');

// Generates the 2Checkout/Avangate HMAC-SHA256 authentication header
function generateAuthHeader(merchantCode, secretKey) {
  const date = new Date().toGMTString();
  const hmacInput = `${merchantCode.length}${merchantCode}${date.length}${date}`;
  const hmac = crypto
    .createHmac('sha256', secretKey)
    .update(hmacInput)
    .digest('hex');
  return {
    authHeader: `code="${merchantCode}" date="${date}" hash="${hmac}"`,
  };
}

exports.twocheckoutProxy = functions.https.onRequest(async (req, res) => {
  res.set('Access-Control-Allow-Origin', '*');
  if (req.method === 'OPTIONS') {
    res.set('Access-Control-Allow-Methods', 'POST');
    res.set('Access-Control-Allow-Headers', 'Content-Type');
    return res.status(204).send('');
  }

  const merchantCode = functions.config().twocheckout.merchant_code;
  const secretKey = functions.config().twocheckout.secret_key;
  const { endpoint, method = 'GET', body } = req.body;

  if (!endpoint) {
    return res.status(400).json({ error: 'Missing endpoint parameter' });
  }

  const { authHeader } = generateAuthHeader(merchantCode, secretKey);
  const baseUrl = 'https://api.2checkout.com/rest/6.0';

  try {
    const response = await axios({
      method: method.toLowerCase(),
      url: `${baseUrl}${endpoint}`,
      data: body || undefined,
      headers: {
        'X-Avangate-Authentication': authHeader,
        'Content-Type': 'application/json',
        'Accept': 'application/json',
      },
    });
    return res.status(200).json(response.data);
  } catch (error) {
    const errData = error.response?.data || { error: error.message };
    return res.status(error.response?.status || 500).json(errData);
  }
});
```

**Expected result:** Firebase Console shows twocheckoutProxy function deployed. You have the function URL (e.g. https://us-central1-PROJECT_ID.cloudfunctions.net/twocheckoutProxy) ready.

### 3. 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.

```
import 'package:webview_flutter/webview_flutter.dart';

class TwoCheckoutWebView extends FlutterFlowWidget {
  const TwoCheckoutWebView({
    super.key,
    required this.checkoutUrl,
    required this.returnUrl,
    this.onPaymentSuccess,
  });

  final String checkoutUrl;
  final String returnUrl;
  final Future<void> Function()? onPaymentSuccess;

  @override
  State<TwoCheckoutWebView> createState() => _TwoCheckoutWebViewState();
}

class _TwoCheckoutWebViewState extends State<TwoCheckoutWebView> {
  late final WebViewController _controller;

  @override
  void initState() {
    super.initState();
    _controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setNavigationDelegate(
        NavigationDelegate(
          onNavigationRequest: (request) {
            // Detect redirect to your return URL
            if (request.url.startsWith(widget.returnUrl)) {
              widget.onPaymentSuccess?.call();
              return NavigationDecision.prevent;
            }
            return NavigationDecision.navigate;
          },
        ),
      )
      ..loadRequest(Uri.parse(widget.checkoutUrl));
  }

  @override
  Widget build(BuildContext context) {
    return WebViewWidget(controller: _controller);
  }
}
```

**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.

### 4. 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.

```
{
  "endpoint": "{{ endpoint }}",
  "method": "{{ method }}",
  "body": {{ body }}
}
```

**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.

### 5. 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.

```
const crypto = require('crypto');

exports.twocheckoutIPN = functions.https.onRequest(async (req, res) => {
  const secretKey = functions.config().twocheckout.secret_key;
  const params = req.body;

  // Verify IPN HASH
  // 2Checkout signs IPN with HMAC-MD5 of specific fields (see 2CO docs for field order)
  // Implementation: sort all fields alphabetically, concatenate values, HMAC-MD5 with secret
  const receivedHash = params.HASH;
  delete params.HASH;

  const sortedKeys = Object.keys(params).sort();
  const dataString = sortedKeys
    .map(k => `${String(params[k]).length}${params[k]}`)
    .join('');

  const computedHash = crypto
    .createHmac('md5', secretKey)
    .update(dataString)
    .digest('hex');

  if (computedHash.toLowerCase() !== receivedHash.toLowerCase()) {
    console.error('IPN hash mismatch — possible spoofing');
    return res.status(403).send('HASH_MISMATCH');
  }

  // Update Firestore with order status
  const admin = require('firebase-admin');
  if (!admin.apps.length) admin.initializeApp();
  const db = admin.firestore();

  const orderRef = params.REFNOEXT; // Your internal order reference
  const orderStatus = params.ORDERSTATUS; // e.g. 'PAYMENT_AUTHORIZED', 'COMPLETE'

  await db.collection('orders').doc(orderRef).update({
    status: orderStatus,
    twocheckoutRef: params.REFNO,
    updatedAt: admin.firestore.FieldValue.serverTimestamp(),
  });

  // 2Checkout expects this exact response to confirm receipt
  return res.status(200).send('AUTHORIZEDSALE');
});
```

**Expected result:** IPN Cloud Function deployed. URL registered in 2Checkout Merchant Control Panel → IPN Settings. Test IPN delivery from the dashboard returns AUTHORIZEDSALE response.

### 6. 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.

**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.

## 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.

## 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.

Prompt example:

```
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.
```

### 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.

Prompt example:

```
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.
```

### 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.

Prompt example:

```
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.
```

## 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.

```
const 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.

```
return 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.

```
if (request.url.startsWith(widget.returnUrl)) {
```

## 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.

---

Source: https://www.rapidevelopers.com/flutterflow-integrations/2checkout-now-verifone
© RapidDev — https://www.rapidevelopers.com/flutterflow-integrations/2checkout-now-verifone
