Migrating from Stripe
Wyrr's API design is intentionally familiar to Stripe users. Most concepts map directly. This guide shows side-by-side comparisons to help you migrate quickly.
| Stripe Concept | Wyrr Equivalent | Notes |
|---|---|---|
Secret Key | API Key + API Secret | Wyrr uses key pair for enhanced security |
PaymentIntent | Collection | Same lifecycle: create, confirm, capture |
Customer | Customer | Nearly identical API |
Payout | Payout | Wyrr adds mobile wallet + stablecoin destinations |
Webhook Endpoint | Webhook Endpoint | HMAC-SHA256 vs Stripe signature scheme |
Product / Price | Product / Price | Same model |
Dispute | Dispute | Same model |
Balance | Balance | Multi-currency with FX built in |
Stripe.js | Wyrr.js | Same pattern: client-side confirmation |
Dashboard | Dashboard | Full-featured merchant portal |
Authentication
Stripe uses a single secret key. Wyrr uses a key pair (public + secret) and short-lived access tokens for enhanced security.
1const stripe = require('stripe')('sk_live_...');
2
3// Stripe uses the secret key directly on every request
4const customer = await stripe.customers.create({
5 email: 'test@example.com'
6});
1const Wyrr = require('@wyrr/node');
2
3// Wyrr uses a key pair and auto-manages token lifecycle
4const client = new Wyrr({
5 apiKey: 'wyrr_live_pk_...',
6 apiSecret: 'wyrr_live_sk_...'
7});
8
9const customer = await client.customers.create({
10 email: 'test@example.com'
11});
Customers
Customer creation is nearly identical. Wyrr adds phone as a first-class field and uses a different ID prefix.
1const customer = await stripe.customers.create({
2 email: 'customer@example.com',
3 name: 'Amina Bello',
4 metadata: {
5 segment: 'enterprise'
6 }
7});
8
9console.log(customer.id); // cus_abc123...
1const customer = await client.customers.create({
2 email: 'customer@example.com',
3 name: 'Amina Bello',
4 phone: '+2348012345678', // First-class phone support
5 metadata: {
6 segment: 'enterprise'
7 }
8});
9
10console.log(customer.id); // cus_8a3b7c9d
Payment Intents vs Collections
Stripe's PaymentIntent maps directly to Wyrr's Collection. The core flow is the same: create server-side, confirm client-side. Wyrr uses the term "collection" to represent the full payment lifecycle.
1// Server-side: create PaymentIntent
2const paymentIntent = await stripe.paymentIntents.create({
3 amount: 5000,
4 currency: 'usd',
5 customer: 'cus_abc123',
6 payment_method_types: ['card'],
7 metadata: {
8 order_id: '12345'
9 }
10});
11
12// Send client_secret to frontend
13res.json({
14 clientSecret: paymentIntent.client_secret
15});
16
17// Client-side: confirm with Stripe.js
18const { error } = await stripe.confirmCardPayment(
19 clientSecret,
20 { payment_method: { card: cardElement } }
21);
1// Server-side: create Collection
2const collection = await client.collections.create({
3 amount: 5000,
4 currency: 'USD',
5 customerId: 'cus_8a3b7c9d',
6 paymentMethod: 'card',
7 metadata: {
8 orderId: '12345'
9 }
10}, { idempotencyKey: 'order-12345' });
11
12// Send client_secret to frontend
13res.json({
14 clientSecret: collection.client_secret
15});
16
17// Client-side: confirm with Wyrr.js
18const { error } = await wyrr.confirmPayment(
19 clientSecret,
20 { paymentMethod: { card: cardElement } }
21);
Payouts
Stripe payouts go to connected accounts or external accounts. Wyrr payouts support bank accounts, mobile wallets, and stablecoins with built-in FX.
1// Payout to a connected account's bank
2const payout = await stripe.payouts.create({
3 amount: 25000,
4 currency: 'usd',
5 method: 'standard'
6}, {
7 stripeAccount: 'acct_abc123'
8});
1// Payout to any bank globally (with auto FX)
2const payout = await client.payouts.create({
3 amount: 250000,
4 currency: 'NGN',
5 destination: {
6 type: 'bank_account',
7 bankCode: '044',
8 accountNumber: '0123456789',
9 accountName: 'Adebayo Ogunlesi'
10 },
11 description: 'Vendor payment'
12}, { idempotencyKey: 'payout-may-001' });
13
14// Also supports mobile wallets and stablecoins:
15// destination.type = 'mobile_wallet'
16// destination.type = 'stablecoin'
Webhooks
Both platforms use similar webhook patterns. Key differences: Wyrr uses HMAC-SHA256 (vs Stripe's custom signature scheme), and event type naming uses dots instead of underscores in the resource part.
1// Webhook verification
2const event = stripe.webhooks.constructEvent(
3 req.body,
4 req.headers['stripe-signature'],
5 endpointSecret
6);
7
8switch (event.type) {
9 case 'payment_intent.succeeded':
10 const paymentIntent = event.data.object;
11 // Handle success
12 break;
13 case 'payment_intent.payment_failed':
14 // Handle failure
15 break;
16}
1// Webhook verification
2const isValid = wyrr.webhooks.verifySignature(
3 req.body,
4 req.headers['wyrr-signature'],
5 endpointSecret
6);
7
8if (!isValid) return res.status(401).send();
9
10const event = req.body;
11switch (event.type) {
12 case 'payment.succeeded':
13 const collection = event.data;
14 // Handle success
15 break;
16 case 'payment.failed':
17 // Handle failure
18 break;
19}
Ready to migrate?
Our migration team can help you move from Stripe to Wyrr with zero downtime. Typical migration takes 1-2 weeks.
Contact Migration Team