The Stripe-to-Substream Migration Data Importer enables Web2 SaaS merchants to seamlessly migrate their existing customer base from Stripe to the SubStream Protocol Web3 ecosystem. This feature dramatically lowers the barrier to entry for enterprise merchants wanting to transition from credit card payments to cryptocurrency subscriptions.
-
StripeMigrationService (
services/stripeMigrationService.js)- CSV parsing and validation
- Plan mapping logic
- Migration link generation
- Database operations
-
Merchant API Routes (
routes/merchants.js)- File upload handling
- Migration job management
- Link verification and completion
-
Migration Database Schema
- Migration jobs tracking
- Customer migration records
- Plan mappings storage
POST /api/v1/merchants/import/stripe
Content-Type: multipart/form-data
Authorization: Bearer <JWT_TOKEN>
Form Data:
- csvFile: <STRIPE_EXPORT_CSV>
- planMappings: <JSON_STRING>
Response:
{
"success": true,
"data": {
"jobId": "uuid-1234",
"summary": {
"total": 1000,
"processed": 950,
"failed": 50
},
"message": "Stripe import processed successfully"
}
}GET /api/v1/merchants/migration/{jobId}/status
Authorization: Bearer <JWT_TOKEN>
Response:
{
"success": true,
"data": {
"jobId": "uuid-1234",
"status": "completed",
"totalRecords": 1000,
"processedRecords": 950,
"failedRecords": 50,
"createdAt": "2024-01-01T12:00:00.000Z",
"completedAt": "2024-01-01T12:05:00.000Z",
"records": [...]
}
}GET /api/v1/merchants/migration/verify?record=<ID>&email=<EMAIL>&ts=<TIMESTAMP>&sig=<SIGNATURE>
POST /api/v1/merchants/migration/complete
Content-Type: application/json
{
"recordId": "uuid-5678",
"stellarPublicKey": "GABC..."
}
POST /api/v1/merchants/plan-mappings
Authorization: Bearer <JWT_TOKEN>
{
"mappings": {
"stripe_plan_basic": "creator123_basic",
"stripe_plan_pro": "creator123_pro",
"stripe_plan_enterprise": "creator123_enterprise"
}
}
GET /api/v1/merchants/plan-mappings
Authorization: Bearer <JWT_TOKEN>
The system is flexible and supports various Stripe export formats:
Customer Email,Subscription Plan,Renewal Date,Status
john.doe@example.com,premium_basic,2024-02-15,active
jane.smith@example.com,premium_pro,2024-02-20,active
Email,Plan,Next Billing Date,Subscription Status
user1@test.com,plan_a,2024-02-15,active
user2@test.com,plan_b,2024-02-20,trialing
| Column Name | Variations | Required | Description |
|---|---|---|---|
| Customer Email | Email, customer_email, email | Yes | Customer's email address |
| Subscription Plan | Plan, Subscription Plan, plan, subscription_plan | Yes | Stripe plan ID |
| Renewal Date | Next Billing Date, renewal_date, next_billing_date | No | Next renewal date |
| Status | Subscription Status, status, subscription_status | No | Subscription status |
- Email Format: Valid email addresses only
- Status Filter: Only processes 'active' and 'trialing' subscriptions
- Missing Data: Skips rows with missing required fields
- Malformed Data: Gracefully handles invalid formats
{
"stripe_plan_id_1": "substream_plan_id_1",
"stripe_plan_id_2": "substream_plan_id_2",
"stripe_plan_id_3": "substream_plan_id_3"
}{
"price_1NQxZzZxZxZxZxZxZxZxZxZ": "creator123_basic_monthly",
"price_2NQxZzZxZxZxZxZxZxZxZ": "creator123_pro_monthly",
"price_3NQxZzZxZxZxZxZxZxZxZ": "creator123_enterprise_monthly"
}- Go to Stripe Dashboard
- Navigate to Products & Pricing
- Click on a product
- Copy the Price ID (starts with
price_) - Map to your SubStream plan ID
Migration links are cryptographically signed URLs that:
- Expire after 24 hours
- Contain customer email verification
- Include timestamp and signature
- Are single-use
https://app.substream-protocol.com/migrate?record=<UUID>&email=<EMAIL>&ts=<TIMESTAMP>&sig=<SIGNATURE>
- Merchant: Uploads CSV and gets migration links
- Customer: Receives email with migration link
- Customer: Clicks link and connects Stellar wallet
- System: Links email to wallet and creates subscription
| Error Type | Handling |
|---|---|
| Invalid Email | Row skipped, logged |
| Missing Plan | Row skipped, logged |
| No Plan Mapping | Row marked as failed |
| Malformed Date | Date set to null |
| Invalid Status | Row skipped if not active/trialing |
{
"success": false,
"error": "Error description"
}| Status Code | Description |
|---|---|
| 400 | Bad Request (invalid data, missing fields) |
| 401 | Unauthorized (no token) |
| 403 | Forbidden (invalid token, access denied) |
| 404 | Not Found (job not found) |
| 413 | Payload Too Large (file > 50MB) |
| 422 | Unprocessable Entity (invalid CSV) |
| 500 | Internal Server Error |
- HMAC Signatures: Links signed with secret key
- Timestamp Validation: Links expire after 24 hours
- Single Use: Each link can only be used once
- Email Verification: Email embedded in signature
- File Cleanup: Temporary files deleted after processing
- Input Validation: All inputs validated and sanitized
- Rate Limiting: API endpoints rate limited
- Authentication: All endpoints require valid JWT
- Secure Secret: Use strong
MIGRATION_SECRETenvironment variable - HTTPS Only: Always use HTTPS in production
- Limited Uploads: Set reasonable file size limits
- Audit Logging: Log all migration activities
- Regular Cleanup: Clean up old migration records
- Streaming Parser: Processes files line by line
- Memory Efficient: Low memory footprint
- Batch Processing: Records processed in batches
- Progress Tracking: Real-time progress updates
- Indexes: Proper indexes on migration tables
- Transactions: Batch operations in transactions
- Connection Pooling: Efficient database connections
- Cleanup Jobs: Regular cleanup of old records
# Run migration tests
npm test -- stripeMigration.test.js- CSV parsing with various formats
- Plan mapping logic
- Migration link generation/verification
- Error handling scenarios
- API endpoint functionality
Customer Email,Subscription Plan,Renewal Date,Status
test1@example.com,basic_plan,2024-02-15,active
test2@example.com,pro_plan,2024-02-20,trialing
test3@example.com,enterprise_plan,2024-02-25,active- Total Jobs: Number of migration jobs created
- Success Rate: Percentage of successful migrations
- Processing Time: Average time per migration
- Error Rate: Percentage of failed records
Migration data can be integrated into analytics dashboards:
// Example: Get migration statistics
const stats = await migrationService.getMigrationStats(merchantId);-
CSV Parsing Fails
- Check file format (must be CSV)
- Verify column headers
- Ensure valid email formats
-
Plan Mapping Errors
- Verify all Stripe plans have mappings
- Check SubStream plan IDs exist
- Validate mapping JSON format
-
Migration Link Issues
- Check
MIGRATION_SECRETenvironment variable - Verify timestamp is within 24 hours
- Ensure URL encoding is correct
- Check
-
Database Errors
- Check database connection
- Verify table schemas
- Check for constraint violations
Enable debug logging:
DEBUG=migration:* npm run devFor issues related to:
- Stripe Export: https://stripe.com/docs/reports/csv-exports
- Stellar Integration: https://github.com/stellar/js-stellar-sdk
- API Issues: Create GitHub issue with logs
- Advanced Mapping: AI-powered plan mapping suggestions
- Bulk Operations: Batch processing of multiple files
- Real-time Sync: Real-time Stripe webhook integration
- Analytics Dashboard: Built-in migration analytics
- Email Templates: Customizable migration email templates
- Multi-tenant: Support for multiple merchant accounts
- Webhook Support: Automated migration completion webhooks
- Export customer data from Stripe
- Create SubStream plans
- Configure plan mappings
- Test with small sample
- Set up email templates
- Upload CSV file
- Monitor processing status
- Send migration links to customers
- Track completion rates
- Handle support requests
- Verify all subscriptions created
- Update billing systems
- Cancel Stripe subscriptions
- Monitor customer satisfaction
- Analyze migration metrics
// Upload CSV file
const uploadStripeCSV = async (file, planMappings) => {
const formData = new FormData();
formData.append('csvFile', file);
formData.append('planMappings', JSON.stringify(planMappings));
const response = await fetch('/api/v1/merchants/import/stripe', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`
},
body: formData
});
return response.json();
};
// Check migration status
const checkMigrationStatus = async (jobId) => {
const response = await fetch(`/api/v1/merchants/migration/${jobId}/status`, {
headers: {
'Authorization': `Bearer ${token}`
}
});
return response.json();
};<h1>Migrate to Web3 with SubStream</h1>
<p>Hi {{customerName}},</p>
<p>We're migrating to Web3! Click below to connect your wallet and continue your subscription:</p>
<a href="{{migrationLink}}">Connect Wallet</a>
<p>This link expires in 24 hours.</p>This comprehensive migration system provides enterprise-grade functionality for seamless Web2 to Web3 migration, ensuring high success rates and excellent user experience.