Mobile Integration

Integrate BLAQPAY into your mobile apps

Mobile Integration

Accept cryptocurrency payments in your mobile apps using BLAQPAY’s REST API.

Overview

BLAQPAY doesn’t provide native mobile SDKs. Instead, integrate using our REST API from your mobile app’s backend. This approach provides better security since API keys stay on your server.

┌─────────────┐      ┌─────────────┐      ┌─────────────┐
│  Mobile App │─────▶│ Your Backend│─────▶│   BLAQPAY   │
│  (iOS/Android)     │   Server    │      │     API     │
└─────────────┘      └─────────────┘      └─────────────┘

Why Backend Integration?

  • Security: API keys never exposed in mobile app
  • Flexibility: Easy to update without app store approval
  • Consistency: Same backend code for web and mobile
  • Control: Full control over payment flow

Integration Steps

1. Create Backend Endpoint

Create an endpoint in your backend to create transactions:

// Node.js/Express example
app.post('/api/mobile/create-payment', async (req, res) => {
  const { amount, userId, orderDetails } = req.body;
  
  try {
    const response = await fetch('https://blaqpay.io/api/transactions/create', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.BLAQPAY_API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        amount: amount,
        customer_email: req.user.email,
        order_description: orderDetails,
        metadata: {
          user_id: userId,
          platform: 'mobile'
        }
      })
    });
    
    const data = await response.json();
    res.json({ 
      paymentUrl: data.payment_url,
      transactionId: data.transaction.id
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

2. Call from Mobile App

iOS (Swift)

import UIKit

func createPayment(amount: Double) {
    let url = URL(string: "https://your-backend.com/api/mobile/create-payment")!
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    
    let body: [String: Any] = [
        "amount": amount,
        "userId": currentUserId,
        "orderDetails": "Order #123"
    ]
    request.httpBody = try? JSONSerialization.data(withJSONObject: body)
    
    URLSession.shared.dataTask(with: request) { data, response, error in
        guard let data = data else { return }
        
        if let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
           let paymentUrl = json["paymentUrl"] as? String {
            DispatchQueue.main.async {
                // Open payment URL in web view or browser
                self.openPaymentPage(url: paymentUrl)
            }
        }
    }.resume()
}

func openPaymentPage(url: String) {
    guard let url = URL(string: url) else { return }
    
    // Option 1: Open in Safari
    UIApplication.shared.open(url)
    
    // Option 2: Open in in-app web view (recommended)
    let webView = SFSafariViewController(url: url)
    present(webView, animated: true)
}

Android (Kotlin)

import okhttp3.*
import org.json.JSONObject

fun createPayment(amount: Double) {
    val client = OkHttpClient()
    
    val json = JSONObject().apply {
        put("amount", amount)
        put("userId", currentUserId)
        put("orderDetails", "Order #123")
    }
    
    val body = RequestBody.create(
        "application/json".toMediaType(),
        json.toString()
    )
    
    val request = Request.Builder()
        .url("https://your-backend.com/api/mobile/create-payment")
        .post(body)
        .build()
    
    client.newCall(request).enqueue(object : Callback {
        override fun onResponse(call: Call, response: Response) {
            response.body?.string()?.let { responseBody ->
                val jsonResponse = JSONObject(responseBody)
                val paymentUrl = jsonResponse.getString("paymentUrl")
                
                runOnUiThread {
                    openPaymentPage(paymentUrl)
                }
            }
        }
        
        override fun onFailure(call: Call, e: IOException) {
            e.printStackTrace()
        }
    })
}

fun openPaymentPage(url: String) {
    // Option 1: Open in browser
    val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
    startActivity(intent)
    
    // Option 2: Open in Custom Tabs (recommended)
    val builder = CustomTabsIntent.Builder()
    val customTabsIntent = builder.build()
    customTabsIntent.launchUrl(this, Uri.parse(url))
}

React Native

import React from 'react';
import { View, Button, Linking } from 'react-native';
import { WebView } from 'react-native-webview';

async function createPayment(amount) {
  try {
    const response = await fetch('https://your-backend.com/api/mobile/create-payment', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        amount: amount,
        userId: currentUserId,
        orderDetails: 'Order #123'
      })
    });
    
    const data = await response.json();
    return data.paymentUrl;
  } catch (error) {
    console.error('Payment error:', error);
  }
}

function PaymentScreen() {
  const [paymentUrl, setPaymentUrl] = React.useState(null);
  
  const handlePayment = async () => {
    const url = await createPayment(99.99);
    setPaymentUrl(url);
  };
  
  if (paymentUrl) {
    return (
      <WebView 
        source={{ uri: paymentUrl }}
        onNavigationStateChange={(navState) => {
          // Handle success/cancel redirects
          if (navState.url.includes('/success')) {
            // Payment completed
          }
        }}
      />
    );
  }
  
  return (
    <View>
      <Button title="Pay with Crypto" onPress={handlePayment} />
    </View>
  );
}

Flutter

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:webview_flutter/webview_flutter.dart';
import 'dart:convert';

Future<String> createPayment(double amount) async {
  final response = await http.post(
    Uri.parse('https://your-backend.com/api/mobile/create-payment'),
    headers: {'Content-Type': 'application/json'},
    body: jsonEncode({
      'amount': amount,
      'userId': currentUserId,
      'orderDetails': 'Order #123'
    }),
  );
  
  if (response.statusCode == 200) {
    final data = jsonDecode(response.body);
    return data['paymentUrl'];
  } else {
    throw Exception('Failed to create payment');
  }
}

class PaymentScreen extends StatefulWidget {
  @override
  _PaymentScreenState createState() => _PaymentScreenState();
}

class _PaymentScreenState extends State<PaymentScreen> {
  String? paymentUrl;
  
  Future<void> handlePayment() async {
    final url = await createPayment(99.99);
    setState(() {
      paymentUrl = url;
    });
  }
  
  @override
  Widget build(BuildContext context) {
    if (paymentUrl != null) {
      return Scaffold(
        body: WebView(
          initialUrl: paymentUrl,
          javascriptMode: JavascriptMode.unrestricted,
          navigationDelegate: (NavigationRequest request) {
            if (request.url.contains('/success')) {
              // Payment completed
              Navigator.pop(context);
            }
            return NavigationDecision.navigate;
          },
        ),
      );
    }
    
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: handlePayment,
          child: Text('Pay with Crypto'),
        ),
      ),
    );
  }
}

3. Handle Payment Completion

Use webhooks on your backend to know when payment completes:

app.post('/webhooks/blaqpay', (req, res) => {
  const event = req.body;
  
  if (event.event === 'transaction.completed') {
    // Notify mobile app via push notification
    // or update database for app to check
    notifyUser(event.transaction.metadata.user_id, {
      type: 'payment_completed',
      transactionId: event.transaction.id
    });
  }
  
  res.status(200).send('OK');
});

Deep Linking

Handle return from payment page using deep links:

iOS (Info.plist)

<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>yourapp</string>
    </array>
  </dict>
</array>

Android (AndroidManifest.xml)

<intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="yourapp" />
</intent-filter>

Then set redirect URLs:

{
  success_url: 'yourapp://payment/success',
  cancel_url: 'yourapp://payment/cancel'
}

Testing

Use test API keys in your backend for testing:

BLAQPAY_API_KEY=sk_test_YOUR_TEST_KEY

Test with testnet cryptocurrencies to avoid using real funds.

Best Practices

  • ✅ Always create transactions from your backend
  • ✅ Never expose API keys in mobile app code
  • ✅ Use HTTPS for all backend endpoints
  • ✅ Implement proper error handling
  • ✅ Use webhooks for payment confirmation
  • ✅ Test thoroughly before production

Need Help?