fl_openpay 0.0.1 copy "fl_openpay: ^0.0.1" to clipboard
fl_openpay: ^0.0.1 copied to clipboard

Flutter plugin for Openpay payment gateway. Supports card tokenization, device fingerprinting, and 3D Secure for iOS and Android.

fl_openpay #

Flutter plugin for Openpay payment gateway. Provides card tokenization, device fingerprinting (anti-fraud), one-time charges, customer management, subscription billing, and 3D Secure support for iOS and Android.

Built on top of the official native SDKs:

Features #

Feature Description
Card tokenization Convert card data into a single-use token (PCI DSS compliant, via native SDKs)
Device fingerprinting Generate a device_session_id for Openpay's anti-fraud engine
One-time charges Create, capture, refund, and list card charges
Customers Create, update, delete, and list customers
Stored cards Save cards on customers for one-click payments
Subscription plans Create and manage recurring billing plans
Subscriptions Subscribe customers to plans with automatic recurring charges
Multi-country Mexico (MX), Colombia (CO) and Peru (PE)
3D Secure Support for 3DS authentication flows

Requirements #

Platform Minimum version
iOS 14.3
Android API 24 (Android 7.0)
Flutter 3.3.0+
Dart 3.10+

Installation #

Add the dependency to your pubspec.yaml:

dependencies:
  fl_openpay: ^0.0.1

Or run:

flutter pub add fl_openpay

Android setup #

Your app's android/gradle.properties must include jetifier (the Openpay SDK uses legacy support libraries):

android.useAndroidX=true
android.enableJetifier=true

Your app's android/app/build.gradle (or .kts) needs packaging excludes for duplicate META-INF files:

// build.gradle.kts
android {
    packaging {
        resources {
            excludes += setOf(
                "META-INF/DEPENDENCIES",
                "META-INF/LICENSE",
                "META-INF/LICENSE.txt",
                "META-INF/NOTICE",
                "META-INF/NOTICE.txt",
            )
        }
    }
}

No other Android configuration is needed. Internet and network state permissions are declared by the plugin automatically.

iOS setup #

Set the deployment target to at least 14.3 in your ios/Podfile:

platform :ios, '14.3'

Then run cd ios && pod install. No other iOS configuration is needed.


Two components #

This plugin provides two separate clients for different use cases:

Component Class Purpose Auth
Native SDK FlOpenpay Card tokenization + device fingerprint (runs on-device via native Openpay SDKs) Public API key
REST API OpenpayApi Charges, customers, cards, plans, subscriptions (calls Openpay HTTP API) Private API key

Use FlOpenpay in your mobile app to securely tokenize cards. Use OpenpayApi on your backend (or in the app for prototyping) to create charges and manage subscriptions.

Security note: The OpenpayApi class uses your private API key. In production, these calls should be made from your backend server, not from the mobile app. For prototyping and sandbox testing, using it directly in the app is fine.


Quick start: One-time charge #

import 'package:fl_openpay/fl_openpay.dart';

// === MOBILE APP (public key) ===

final sdk = FlOpenpay();
await sdk.initialize(
  merchantId: 'YOUR_MERCHANT_ID',
  publicApiKey: 'pk_test_XXXX',
  productionMode: false,
  country: OpenpayCountry.mexico,
);

// 1. Get device fingerprint
final sessionId = await sdk.createDeviceSessionId();

// 2. Tokenize the card
final token = await sdk.tokenizeCard(
  OpenpayCard(
    holderName: 'Juan Perez',
    cardNumber: '4111111111111111',
    expirationMonth: '12',
    expirationYear: '29',
    cvv2: '123',
  ),
);

// 3. Send token.id + sessionId to your backend...

// === BACKEND (private key) ===

final api = OpenpayApi(
  merchantId: 'YOUR_MERCHANT_ID',
  apiKey: 'sk_test_XXXX',
  isSandbox: true,
  countryCode: 'MX',
);

// 4. Create the charge
final charge = await api.charges.create(OpenpayCharge(
  sourceId: token.id,
  method: 'card',
  amount: 150.00,
  currency: 'MXN',
  description: 'Order #1234',
  deviceSessionId: sessionId,
  customer: OpenpayChargeCustomer(
    name: 'Juan',
    lastName: 'Perez',
    email: 'juan@example.com',
  ),
));

print(charge.id);     // "trfcfhakixfkpsjubnk"
print(charge.status); // "completed"

Quick start: Subscription #

final api = OpenpayApi(
  merchantId: 'YOUR_MERCHANT_ID',
  apiKey: 'sk_test_XXXX',
  isSandbox: true,
);

// 1. Create a customer
final customer = await api.customers.create(OpenpayCustomer(
  name: 'Maria',
  lastName: 'Garcia',
  email: 'maria@example.com',
  phoneNumber: '5512345678',
));

// 2. Save a card on the customer (using a token from FlOpenpay.tokenizeCard)
final card = await api.cards.createForCustomer(
  customer.id!,
  'tok_XXXXXXXXXXXX', // token.id from tokenizeCard()
  deviceSessionId: sessionId,
);

// 3. Create a plan (do this once, reuse the plan ID)
final plan = await api.plans.create(OpenpayPlan(
  name: 'Premium Monthly',
  amount: 299.00,
  currency: 'MXN',
  repeatEvery: 1,
  repeatUnit: 'month',
  trialDays: 14,
  retryTimes: 3,
  statusAfterRetry: 'unpaid',
));

// 4. Subscribe the customer to the plan
final subscription = await api.subscriptions.create(
  customer.id!,
  OpenpaySubscription(
    planId: plan.id!,
    cardId: card.id,
  ),
);

print(subscription.id);     // "szfcfhakixfkpsjubnk"
print(subscription.status); // "trial" (14-day trial)

Full integration guide #

Architecture overview #

┌──────────────────────────────┐
│      Your Flutter App         │
│                               │
│  FlOpenpay (public key)       │
│  ├─ tokenizeCard() ──────────────► Openpay servers (returns token)
│  └─ createDeviceSessionId()   │
│                               │
│  Sends token_id + session_id  │
│  to your backend              │
└──────────────┬────────────────┘
               │
               ▼
┌──────────────────────────────┐       ┌──────────────────────┐
│      Your Backend             │       │    Openpay REST API   │
│                               │       │                      │
│  OpenpayApi (private key)     │──────►│  /charges            │
│  ├─ api.charges.create()      │       │  /customers          │
│  ├─ api.customers.create()    │       │  /cards              │
│  ├─ api.plans.create()        │       │  /plans              │
│  └─ api.subscriptions.create()│       │  /subscriptions      │
└───────────────────────────────┘       └──────────────────────┘

Step 1: Get your Openpay credentials #

  1. Create an account at openpay.mx (or .co / .pe)
  2. Go to Dashboard > API Keys
  3. Copy your Merchant ID, Public API Key, and Private API Key
  4. For testing, use the sandbox credentials

Step 2: Initialize the native SDK (mobile app) #

final sdk = FlOpenpay();

await sdk.initialize(
  merchantId: 'YOUR_MERCHANT_ID',
  publicApiKey: 'pk_test_XXXX',
  productionMode: false,
  country: OpenpayCountry.mexico,
);

Step 3: Generate device session ID #

final sessionId = await sdk.createDeviceSessionId();

Step 4: Tokenize the card #

final token = await sdk.tokenizeCard(
  OpenpayCard(
    holderName: _nameController.text,
    cardNumber: _cardController.text.replaceAll(' ', ''),
    expirationMonth: '12',
    expirationYear: '29',
    cvv2: '123',
    address: OpenpayAddress( // optional, improves anti-fraud
      line1: 'Av. Insurgentes Sur 253',
      city: 'Ciudad de Mexico',
      state: 'CDMX',
      postalCode: '06600',
      countryCode: 'MX',
    ),
  ),
);
// Send token.id + sessionId to your backend

Step 5: One-time charge (backend) #

final api = OpenpayApi(
  merchantId: 'YOUR_MERCHANT_ID',
  apiKey: 'sk_test_XXXX',
  isSandbox: true,
);

final charge = await api.charges.create(OpenpayCharge(
  sourceId: token.id,
  method: 'card',
  amount: 150.00,
  currency: 'MXN',
  description: 'Order #1234',
  deviceSessionId: sessionId,
));

if (charge.status == 'completed') {
  // Payment successful
}

Step 6: Pre-authorized charge (capture later) #

// Create a pre-auth (hold funds without capturing)
final preAuth = await api.charges.create(OpenpayCharge(
  sourceId: token.id,
  method: 'card',
  amount: 500.00,
  currency: 'MXN',
  description: 'Hotel reservation hold',
  deviceSessionId: sessionId,
  capture: false, // <-- pre-authorization
));

// Later, capture the full or partial amount
final captured = await api.charges.capture(preAuth.id!, amount: 450.00);

// Or refund if not needed
final refunded = await api.charges.refund(preAuth.id!, description: 'Cancelled');

Step 7: Set up recurring subscriptions #

// 1. Create customer
final customer = await api.customers.create(OpenpayCustomer(
  name: 'Carlos',
  lastName: 'Lopez',
  email: 'carlos@example.com',
));

// 2. Save card on customer
final card = await api.cards.createForCustomer(customer.id!, token.id);

// 3. Create a plan (reuse across customers)
final plan = await api.plans.create(OpenpayPlan(
  name: 'Pro Monthly',
  amount: 499.00,
  currency: 'MXN',
  repeatEvery: 1,
  repeatUnit: 'month',
  trialDays: 7,
  retryTimes: 3,
  statusAfterRetry: 'cancelled',
));

// 4. Subscribe
final sub = await api.subscriptions.create(customer.id!, OpenpaySubscription(
  planId: plan.id!,
  cardId: card.id,
));

// 5. Check subscription status
final updated = await api.subscriptions.get(customer.id!, sub.id!);
print(updated.status); // "trial", "active", "past_due", "unpaid", "cancelled"

// 6. Cancel at end of period (soft cancel)
await api.subscriptions.update(customer.id!, sub.id!, OpenpaySubscription(
  planId: plan.id!,
  cancelAtPeriodEnd: true,
));

// 7. Or cancel immediately
await api.subscriptions.cancel(customer.id!, sub.id!);

Step 8: Handle 3D Secure #

final charge = await api.charges.create(OpenpayCharge(
  sourceId: token.id,
  method: 'card',
  amount: 150.00,
  currency: 'MXN',
  description: 'Order #1234',
  deviceSessionId: sessionId,
  use3dSecure: true,
  redirectUrl: 'https://yoursite.com/payment-callback',
));

if (charge.status == 'charge_pending' && charge.paymentMethod?.url != null) {
  // Open the URL in a WebView or browser for 3DS authentication
  // After authentication, verify charge status on your backend
}

REST API reference #

OpenpayApi #

final api = OpenpayApi(
  merchantId: 'xxx',
  apiKey: 'sk_xxx',
  isSandbox: true,     // default: true
  countryCode: 'MX',   // default: 'MX'. Also: 'CO', 'PE'
);

api.charges #

Method Description
create(OpenpayCharge) Create a merchant-level charge
createForCustomer(customerId, OpenpayCharge) Charge a specific customer
get(chargeId) Get charge details
getForCustomer(customerId, chargeId) Get customer charge details
capture(chargeId, {amount}) Capture a pre-authorized charge
captureForCustomer(customerId, chargeId, {amount}) Capture customer pre-auth
refund(chargeId, {amount, description}) Refund (full or partial)
refundForCustomer(customerId, chargeId, {amount, description}) Refund customer charge
list({offset, limit, orderId, status}) List merchant charges
listForCustomer(customerId, {offset, limit}) List customer charges

api.customers #

Method Description
create(OpenpayCustomer) Create a new customer
get(customerId) Get customer details
update(customerId, OpenpayCustomer) Update customer info
delete(customerId) Delete customer (cancels subscriptions)
list({offset, limit, externalId}) List customers

api.cards #

Method Description
create(tokenId, {deviceSessionId}) Store card at merchant level
createForCustomer(customerId, tokenId, {deviceSessionId}) Store card on customer
get(cardId) / getForCustomer(...) Get card details
delete(cardId) / deleteForCustomer(...) Remove a stored card
list({offset, limit}) / listForCustomer(...) List stored cards

api.plans #

Method Description
create(OpenpayPlan) Create a subscription plan
get(planId) Get plan details
update(planId, OpenpayPlan) Update plan (name, trial days, retry config)
delete(planId) Delete plan (existing subscriptions continue)
list({offset, limit}) List all plans

api.subscriptions #

Method Description
create(customerId, OpenpaySubscription) Subscribe customer to plan
get(customerId, subscriptionId) Get subscription details
update(customerId, subscriptionId, OpenpaySubscription) Update subscription (change card, set cancel_at_period_end)
cancel(customerId, subscriptionId) Cancel immediately
list(customerId, {offset, limit}) List customer subscriptions

Native SDK reference (FlOpenpay) #

Method Returns Description
initialize(...) Future<void> Configure native SDK. Call once at startup.
tokenizeCard(OpenpayCard) Future<OpenpayToken> Tokenize card data securely.
createDeviceSessionId() Future<String> Generate device fingerprint.
isInitialized bool Whether initialize() has been called.

Exceptions #

Exception When
OpenpayNotInitializedException FlOpenpay methods called before initialize()
OpenpayRequestException Validation errors (codes 1001-2999)
OpenpayGatewayException Bank declines (codes 3001-3005)
OpenpayNetworkException No internet / timeout
OpenpayApiException REST API errors (from OpenpayApi calls)
OpenpayException Base class for native SDK errors

Sandbox test cards #

Card Number Behavior
Visa (success) 4111111111111111 Approved
Mastercard (success) 5555555555554444 Approved
Amex (success) 345678000000007 Approved
Declined 4000000000000002 Error 3001
Insufficient funds 4000000000000036 Error 3003
Stolen card 4000000000000044 Error 3004
Fraud rejection 4000000000000051 Error 3005

Error codes reference #

General (1xxx) #

Code HTTP Description
1000 500 Internal server error
1001 400 Invalid JSON or missing fields
1002 401 Authentication failed
1003 422 Invalid parameter format
1004 503 Service unavailable
1005 404 Resource not found
1008 423 Account deactivated
1010 403 Wrong key type (public vs private)
1012 412 Amount out of range
1015 504 Gateway timeout

Card / storage (2xxx) #

Code HTTP Description
2004 422 Invalid Luhn check digit
2005 400 Card expired
2006 400 CVV required but missing
2007 412 Test card used in production

Gateway (3xxx) #

Code HTTP Description
3001 402 Card declined by issuer
3002 402 Card expired
3003 402 Insufficient funds
3004 402 Stolen / blacklisted card
3005 402 Fraud rejection

ProGuard / R8 #

The plugin ships its own proguard-rules.pro via consumerProguardFiles. No additional configuration needed.

Running the example app #

cd example
flutter run

Contributing #

  1. Edit the Pigeon schema in pigeons/openpay_api.dart
  2. Regenerate: flutter pub run pigeon --input pigeons/openpay_api.dart
  3. Implement in FlOpenpayPlugin.kt (Android) and FlOpenpayPlugin.swift (iOS)
  4. Run flutter analyze && flutter test

License #

MIT License. See LICENSE file.

0
likes
150
points
58
downloads

Publisher

unverified uploader

Weekly Downloads

Flutter plugin for Openpay payment gateway. Supports card tokenization, device fingerprinting, and 3D Secure for iOS and Android.

Repository (GitHub)
View/report issues

Topics

#payments #openpay #tokenization #subscriptions

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on fl_openpay

Packages that implement fl_openpay