solydflow-js
v0.2.2
Published
Official SolydFlow JavaScript SDK
Maintainers
Readme
SolydFlow JavaScript SDK
Official JavaScript SDK for SolydFlow.
SolydFlow is a hybrid revenue infrastructure that helps businesses manage subscriptions, purchases, entitlements, and customer access across local payment gateways, app stores, and global payment providers.
The JavaScript SDK enables web applications to use the same pricing logic, entitlement management, smart routing, and subscription lifecycle capabilities available across the SolydFlow platform.
For complete integration guides, API references, webhook events, and advanced configuration, visit:
https://docs.solydflow.com
What is SolydFlow?
SolydFlow unifies app stores (Apple App Store and Google Play), local African payment gateways (Paystack and Flutterwave), and Stripe for global coverage and portability into a single platform.
Beyond payment aggregation, SolydFlow includes:
- Smart Payment Routing
- Purchasing Power Parity (PPP)
- Smart Upgrade Credits
- Entitlement Management
- Subscription Lifecycle Tracking
- Hosted Checkout Flows
- No-Code Paywalls
This allows businesses to manage revenue, subscriptions, and customer access from a single source of truth.
Key Features
- 🌍 Unified Revenue Infrastructure
- 🧠 Smart Payment Routing
- 💳 Dynamic Pricing & Purchasing Power Parity (PPP)
- 🎯 Drop-In No-Code Paywalls
- 🔄 Smart Upgrade Credits
- 🔐 Entitlement Management
- 📡 Subscription Lifecycle Events
- 🔗 Hosted Checkout Flows
Installation
Install the SDK:
npm install solydflow-jsor
yarn add solydflow-jsor
pnpm add solydflow-jsQuick Start
Initialize the SDK as early as possible after the customer has been identified.
import { SolydFlow } from "solydflow-js";
await SolydFlow.configure(
"sf_pk_live_YOUR_PUBLIC_KEY",
"user_12345",
"[email protected]"
);Parameters
| Parameter | Description |
|------------|------------|
| publicKey | Your SolydFlow Public API Key |
| customerId | Your application's unique customer identifier |
Choose Your Integration Strategy
The JavaScript SDK supports two integration approaches.
| Option | Best For | |----------|----------| | Drop-In Paywall | Fastest implementation with dashboard-managed UI | | Custom UI | Complete control over the customer experience |
Option A: Drop-In Paywall (Recommended)
Instead of spending days building your own pricing interface, SolydFlow provides a fully responsive, high-converting Drop-In Paywall.
The paywall automatically stays synchronized with the products, pricing, design, colors, and messaging configured in your SolydFlow Console.
Automatically Handles
- Purchasing Power Parity (PPP)
- Geo-based pricing
- Smart Upgrade Credits
- Checkout routing
- Product rendering
- Hosted checkout initiation
Step 1: Add a Container
<div id="solydflow-paywall-container"></div>Step 2: Render the Paywall
import { SolydFlow } from "solydflow-js";
async function showPricing() {
await SolydFlow.configure(
"sf_pk_live_YOUR_PUBLIC_KEY",
"user_12345",
"[email protected]"
);
await SolydFlow.renderPaywall(
"solydflow-paywall-container"
);
}That's all that's required.
The SDK automatically loads and renders the paywall you designed in the SolydFlow Console.
When Should You Use This?
Choose the Drop-In Paywall if:
- You want the fastest implementation.
- Product teams manage pricing and promotions.
- You want paywall updates without website deployments.
- You want built-in localization and optimization.
Option B: Custom UI (Advanced)
If you prefer to build your own pricing experience, you can fetch package information directly and render your own components.
SolydFlow will still calculate:
- Purchasing Power Parity pricing
- Smart Upgrade Credits
- Regional pricing adjustments
async function fetchRawPackages() {
const offerings = await SolydFlow.getOfferings();
offerings.forEach(pkg => {
if (pkg.is_upgrade) {
console.log(
`Upgrade for ${pkg.currency} ${pkg.calculated_amount_kobo / 100}`
);
} else {
console.log(
`Standard Price: ${pkg.currency} ${pkg.amount_kobo / 100}`
);
}
});
}You remain responsible for rendering the UI, while SolydFlow manages pricing logic, checkout routing, and entitlement calculations.
Check Customer Access
Determine whether a customer has access to a specific entitlement.
const hasAccess = await SolydFlow.hasEntitlement(
"gold_access"
);
if (hasAccess) {
console.log("Access granted");
}Use entitlements to gate premium features, subscriptions, and customer access.
Smart Payment Routing
SolydFlow can automatically route payments to the most appropriate payment rail based on currency, geography, and routing rules configured in the SolydFlow Console.
Example Routing Rules
| Currency | Payment Rail | |-----------|--------------| | NGN | Monnify | | KES | M-Pesa | | USD | Stripe | | Other | Paystack / Flutterwave |
Routing rules can be updated without redeploying your application.
Start Checkout
Launch a checkout session for a package.
await SolydFlow.purchasePackage(
packageId,
customerPhoneNumber
);Example:
await SolydFlow.purchasePackage(
"gold_monthly",
"2348012345678"
);Optional Phone Number
A phone number is recommended for:
- Local payment rails
- Mobile money flows
- Customer recovery workflows
- Subscription re-engagement campaigns
Checkout Experience
The SDK automatically selects the appropriate checkout experience based on your routing configuration.
Examples include:
- Hosted checkout pages
- Virtual account payments
- Mobile money payment flows
No additional application logic is required.
Understanding the Web Purchase Flow
Unlike mobile SDKs, web applications cannot wait for payment completion inside the browser.
Mobile SDK Flow
User
↓
In-App Purchase
↓
Payment Completed
↓
CustomerInfo Returned
↓
Entitlement ActivatedWeb SDK Flow
User
↓
Hosted Checkout
↓
Payment Completed
↓
SolydFlow Verification
↓
Webhook Sent
↓
Backend Updated
↓
Entitlement ActivatedBecause checkout occurs outside your application, purchase completion is communicated through webhooks.
Configure Webhooks
To receive subscription updates:
- Open the SolydFlow Console.
- Navigate to your project settings.
- Configure a webhook endpoint.
- Deploy your backend listener.
Subscription Events
SolydFlow can notify your backend when a customer:
- Starts a subscription
- Renews a subscription
- Upgrades a subscription
- Cancels a subscription
- Restores access
Backend Responsibilities
Your backend should:
- Verify the cryptographic webhook signature.
- Filter out Sandbox/Test events if running in production.
- Synchronize user entitlements in your database.
- Unlock application features.
Without a backend webhook, your application will not know when a user completes a payment or when a subscription is revoked due to a chargeback.
Securing & Handling Webhooks
SolydFlow sends webhooks to your server to notify you of successful payments, recovered transactions, and subscription changes.
Because webhooks are public endpoints on your server, you must verify that incoming requests are genuinely from SolydFlow and have not been intercepted or delayed by malicious actors (Replay Attacks).
The 4 Webhook Events
To keep your integration incredibly simple while still supporting powerful marketing analytics, SolydFlow consolidates all billing complexity into just four specific events.
1. subscription_started
When it fires: A user successfully pays for an entitlement for the very first time, or they purchase it again after their previous subscription completely expired.
What to do: Grant the user access to the entitlement until the expires_at date. Tip: This is the perfect event to trigger a "Welcome to Premium" onboarding email!
{
"event": "subscription_started",
"event_id": "evt_110e8400-e29b-41d4-a716-446655440001",
"environment": "live",
"is_test": false,
"user_id": "user_12345",
"package_id": "gold_monthly",
"entitlement": "gold_access",
"provider": "paystack",
"expires_at": "2026-07-27T18:33:00Z"
}2. subscription_renewed
When it fires: A user's active subscription is renewed, upgraded, or a dropped payment is rescued by the SolydFlow Sweeper. Time is added to their current access.
What to do: Silently extend the user's access in your database to the new expires_at date.
{
"event": "subscription_renewed",
"event_id": "evt_550e8400-e29b-41d4-a716-446655440000",
"environment": "live",
"is_test": false,
"user_id": "user_12345",
"package_id": "gold_monthly",
"entitlement": "gold_access",
"provider": "paystack",
"expires_at": "2026-08-27T18:33:00Z"
}3. subscription_revoked
When it fires: A user's access is forcefully killed before their natural expiration date (e.g., a card chargeback, an Apple refund, or a manual Admin rejection in the dashboard).
What to do: Immediately revoke the user's access to the entitlement and pause their services.
{
"event": "subscription_revoked",
"event_id": "evt_991f8400-e29b-41d4-a716-446655440001",
"environment": "live",
"is_test": false,
"user_id": "user_12345",
"package_id": "gold_monthly",
"entitlement": "gold_access",
"reason": "chargeback",
"revoked_at": "2026-06-27T18:33:00Z"
}4. test_event
When it fires: You click "Send Test Webhook" in the SolydFlow Console API Vault. What to do: Use this to verify your HMAC SHA-256 cryptographic signature logic is working correctly before going live.
{
"event": "test_event",
"user_id": "sf_test_user_999",
"package_id": "test_monthly_gold",
"entitlement": "gold_access",
"provider": "solydflow_test",
"expires_at": "2026-07-27T18:33:00Z"
}Backend Example (Node.js / Express)
To secure your endpoint, you must verify the X-SolydFlow-Signature header. This header contains a UNIX timestamp (t=...) and the HMAC signature (v1=...).
The following example demonstrates how to capture the raw body, securely verify the signature to prevent replay attacks, isolate Sandbox data, and handle the 4 events.
import express from "express";
import crypto from "crypto";
const app = express();
// The secret key found in your SolydFlow Project Dashboard
const SOLYDFLOW_WEBHOOK_SECRET = process.env.SOLYDFLOW_WEBHOOK_SECRET;
// You MUST capture the raw request body to accurately calculate the cryptographic hash
app.use(express.json({
verify: (req, res, buf) => {
req.rawBody = buf.toString();
}
}));
app.post("/webhooks/solydflow", async (req, res) => {
try {
const signatureHeader = req.headers['x-solydflow-signature'];
if (!signatureHeader) {
return res.status(401).send('Missing SolydFlow signature');
}
// 1. Extract timestamp (t) and signature (v1)
const parsedHeader = signatureHeader.split(',').reduce((acc, pair) => {
const [key, value] = pair.split('=');
acc[key] = value;
return acc;
}, {});
const timestamp = parsedHeader['t'];
const providedSignature = parsedHeader['v1'];
// 2. Prevent Replay Attacks (Reject if older than 5 minutes)
const currentTimestamp = Math.floor(Date.now() / 1000);
if (currentTimestamp - parseInt(timestamp, 10) > 300) {
return res.status(401).send('Webhook timestamp is too old');
}
// 3. Compute and Verify the Signature
const payloadToSign = `${timestamp}.${req.rawBody}`;
const expectedSignature = crypto
.createHmac('sha256', SOLYDFLOW_WEBHOOK_SECRET)
.update(payloadToSign)
.digest('hex');
// Use timingSafeEqual to prevent timing attacks
const isValid = crypto.timingSafeEqual(
Buffer.from(expectedSignature),
Buffer.from(providedSignature)
);
if (!isValid) {
return res.status(401).send('Cryptographic signature mismatch');
}
// --- WEBHOOK IS SECURE ---
const payload = req.body;
// 4. Prevent Sandbox data from corrupting your Production database
if (payload.is_test && process.env.NODE_ENV === "production") {
console.log("Ignored SolydFlow Sandbox event.");
return res.status(200).send("Ignored");
}
// 5. Handle Business Logic
switch (payload.event) {
case "subscription_started":
console.log(`NEW CUSTOMER! Access granted for user ${payload.user_id}. Unlocking: ${payload.entitlement} until ${payload.expires_at}`);
// TODO: Grant access and trigger Welcome Email
break;
case "subscription_renewed":
console.log(`Access extended for user ${payload.user_id}. Unlocking: ${payload.entitlement} until ${payload.expires_at}`);
// TODO: Update your database to extend user access
break;
case "subscription_revoked":
console.log(`Access revoked for user ${payload.user_id}. Reason: ${payload.reason}`);
// TODO: Remove user access immediately
break;
case "test_event":
console.log(`Test webhook received successfully! Signature logic is working.`);
break;
default:
console.log("Unhandled event:", payload.event);
}
// Always return a 200 OK so SolydFlow knows the event was received successfully
res.status(200).json({ received: true });
} catch (error) {
console.error("Webhook processing error:", error);
res.status(500).json({ error: "Webhook processing failed" });
}
});
app.listen(3000, () => console.log('Listening on port 3000'));Recommended Integration Pattern
Frontend
↓
Display Paywall
↓
Customer Selects Plan
↓
Hosted Checkout
↓
Payment Completed
↓
SolydFlow Verification
↓
Webhook Event
↓
Backend Updates Customer
↓
Customer Access GrantedPlatform Status
Live
- Paystack
- Flutterwave
- No-Code Paywalls
- Entitlements
- Subscription Events
Testing
- Stripe
Planned
- Monnify
- M-Pesa / Daraja
- Additional regional payment rails
Security
Non-Custodial
SolydFlow never holds your funds.
Payments move directly between your customers and your connected payment providers.
Verification
All transactions are verified before subscription events and entitlements are issued.
Signed Webhooks
Webhook events are cryptographically signed and should always be verified by your backend.
Documentation
For production deployments, entitlement architecture, webhook setup, SDK methods, pricing configuration, routing rules, and API references:
👉 https://docs.solydflow.com
Support
- Documentation: https://docs.solydflow.com
- Console: https://console.solydflow.com
- Website: https://solydflow.com
- Support: [email protected]
