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.
Recommended Architecture
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 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?
- Check the API Reference
- View code examples
- Email support@blaqpay.io
