STC Pay Integration Guide
This guide will walk you through integrating STC Pay payments into your Flutter application using the Moyasar Flutter SDK.
Prerequisites
Before you begin, ensure you have:
- A Moyasar account with STC Pay enabled
- Your Moyasar publishable API key
- Flutter SDK installed (v2.0.17 or later)
Installation
Add the latest version of the moyasar package to your pubspec.yaml:
dependencies:
moyasar: ^3.0.5 # or the latest version
Then run:
flutter pub get
Implementation
1. Add the STCPay Widget
// Initialize payment config
final paymentConfig = PaymentConfig(
publishableApiKey: 'YOUR_PUBLISHABLE_API_KEY',
amount: 10000, // 100.00 SAR
description: 'Order #12345',
metadata: {'order_id': '12345'},
);
// In your widget
STCPay(
config: paymentConfig,
onPaymentResult: onPaymentResult,
locale: const Localization.ar(), // optional, defaults to English
)
// Payment result handler
void onPaymentResult(result) {
if (result is PaymentResponse) {
switch (result.status) {
case PaymentStatus.paid:
print('Payment successful: ${result.id}');
break;
case PaymentStatus.failed:
print('Payment failed: ${result.id}');
break;
case PaymentStatus.initiated:
print('Awaiting OTP: ${result.id}');
break;
default:
break;
}
}
}
STCPaymentComponent is deprecated and will be removed in the next major version. It is a drop-in rename:
- STCPaymentComponent(config: paymentConfig, onPaymentResult: onPaymentResult)
+ STCPay(config: paymentConfig, onPaymentResult: onPaymentResult)
Testing
Test Environment
- Use the sandbox environment for testing
- Enter a valid Saudi mobile number starting with 05
- For testing OTP:
- Use
123456for successful payment - Use
000000for failed payment
- Use
Error Handling
Handle different payment statuses in your onPaymentResult callback:
void onPaymentResult(result) {
if (result is PaymentResponse) {
switch (result.status) {
case PaymentStatus.paid:
// Handle successful payment
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Payment successful!')),
);
break;
case PaymentStatus.failed:
// Handle failed payment. Details are on the source:
// (result.source as StcResponseSource).message
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Payment failed')),
);
break;
case PaymentStatus.initiated:
// Handle initiated state (waiting for OTP)
break;
default:
break;
}
return;
}
// Otherwise the result is one of the SDK error types.
if (result is ValidationError) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: ${result.message}')),
);
} else if (result is NetworkError || result is TimeoutError) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Connection problem. Please try again.')),
);
}
}
onPaymentResult receives a dynamic value — either a PaymentResponse or one of the error types (ValidationError, AuthError, ApiError, NetworkError, TimeoutError, PaymentCanceledError, UnprocessableTokenError, UnspecifiedError). Always check the type before reading fields. Note that PaymentResponse itself has no message field — per-method details live on result.source.
Production Deployment
Before going live:
- Replace the test API key with your live publishable API key
- Test the complete payment flow with real STC Pay accounts
- Ensure you have proper error handling in place
Support
For any issues or questions, please contact Moyasar Support.