@payloops/processor-core
v0.0.11
Published
The **processor-core** service is the workflow engine powering PayLoops. It orchestrates payment processing, handles retries, manages state transitions, and ensures reliable webhook delivery—all with durability guarantees from [Temporal](https://temporal.
Readme
PayLoops Processor Core
The processor-core service is the workflow engine powering PayLoops. It orchestrates payment processing, handles retries, manages state transitions, and ensures reliable webhook delivery—all with durability guarantees from Temporal.
Role in the Platform
┌─────────────────────────────────────────────────────────────────────────┐
│ │
│ Backend API │
│ │ │
│ │ Triggers workflows │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ ★ PROCESSOR-CORE (this repo) ★ │ │
│ │ │ │
│ │ ┌──────────────────────────────────────────────────────────┐ │ │
│ │ │ Temporal Workers │ │ │
│ │ │ │ │ │
│ │ │ PaymentWorkflow RefundWorkflow WebhookWorkflow │ │ │
│ │ │ │ │ │ │ │ │
│ │ │ ▼ ▼ ▼ │ │ │
│ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │
│ │ │ │Activities│ │Activities│ │Activities│ │ │ │
│ │ │ └─────────┘ └─────────┘ └─────────┘ │ │ │
│ │ └──────────────────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ └───────────────────────────────┼──────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────────┐ │
│ │ Payment Processors │ │
│ │ processor-stripe processor-razorpay │ │
│ └────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────┘Why Temporal?
Payment processing requires durability and reliability:
- If the server crashes mid-payment, the workflow resumes exactly where it left off
- Long-running operations (like waiting for 3DS) don't block resources
- Automatic retries with configurable backoff
- Full audit trail of every state transition
- Easy to add timeouts, deadlines, and cancellation
Workflows
PaymentWorkflow
Handles the complete lifecycle of a payment from order creation to completion.
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ pending │───▶│ routing │───▶│charging │───▶│ 3DS/SCA │───▶│completed│
└─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘
│
▼
Wait for signal
(threeDSComplete)States:
pending- Order created, awaiting paymentprocessing- Routing to optimal processorauthorized- Payment authorized, awaiting capturerequires_action- Waiting for 3DS/SCA verificationcaptured- Payment successfully capturedfailed- Payment failed
Signals:
threeDSComplete- Customer completed 3DS challenge
WebhookDeliveryWorkflow
Ensures merchants receive webhook notifications reliably.
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ attempt │───▶│ retry │───▶│ retry │───▶│ final │
│ #1 │ │ #2 │ │ #3 │ │ status │
└─────────┘ └─────────┘ └─────────┘ └─────────┘
1min 5min 30minRetry Schedule:
- Immediate
- 1 minute
- 5 minutes
- 30 minutes
- 2 hours
- 24 hours (final attempt)
Processor Registry
The core provides a plugin system for payment processors:
// In processor-stripe or processor-razorpay
import { registerProcessor, PaymentProcessor } from '@payloops/processor-core';
class StripeProcessor implements PaymentProcessor {
name = 'stripe';
async createPayment(input, config) { /* ... */ }
async capturePayment(orderId, amount, config) { /* ... */ }
async refundPayment(transactionId, amount, config) { /* ... */ }
async getPaymentStatus(orderId, config) { /* ... */ }
}
registerProcessor(new StripeProcessor());Workflows dynamically load the appropriate processor based on routing rules.
Activities
Activities are the building blocks that workflows orchestrate:
| Activity | Description |
|----------|-------------|
| getOrder | Fetch order details from database |
| updateOrderStatus | Update order status in database |
| getProcessorConfig | Get decrypted processor credentials |
| routePayment | Determine which processor to use |
| processPayment | Execute payment via processor |
| deliverWebhook | POST webhook to merchant endpoint |
Development
Prerequisites
- Node.js 22+
- npm
- Temporal server (via Docker)
- PostgreSQL (via Docker)
Setup
# Install dependencies
npm install
# Copy environment template
cp .env.example .env
# Start Temporal (from root loop repo)
docker-compose up -d temporal
# Start worker in development mode
npm devAvailable Scripts
| Command | Description |
|---------|-------------|
| npm dev | Start worker with hot reload |
| npm build | Build for production |
| npm start | Run production worker |
| npm typecheck | Run TypeScript compiler |
| npm lint | Run ESLint |
Configuration
| Variable | Required | Description |
|----------|----------|-------------|
| DATABASE_URL | Yes | PostgreSQL connection string |
| TEMPORAL_ADDRESS | Yes | Temporal server (default: localhost:7233) |
| TEMPORAL_NAMESPACE | Yes | Temporal namespace |
| ENCRYPTION_KEY | Yes | Key to decrypt processor credentials |
| OTEL_EXPORTER_OTLP_ENDPOINT | No | OpenTelemetry collector endpoint (default: http://localhost:4318) |
| OTEL_SERVICE_NAME | No | Service name for telemetry (default: loop-processor-core) |
Adding a New Processor
- Create a new repository (e.g.,
processor-paypal) - Implement the
PaymentProcessorinterface - Call
registerProcessor()on module load - Import the processor in this repo's worker
See processor-stripe for a complete example.
Observability
The processor-core is fully instrumented with OpenTelemetry for distributed tracing, metrics, and structured logging.
What's Collected
| Type | Description |
|------|-------------|
| Traces | Activity spans with workflow context, processor calls |
| Metrics | Activity execution counts, durations, error rates |
| Logs | Structured JSON logs with trace_id, span_id, workflow context |
Activity Tracing
Every activity execution is automatically traced with:
activity.processPayment
├── temporal.activity.type: processPayment
├── temporal.workflow.id: payment-ord_abc123
├── temporal.task_queue: payment-queue
└── duration: 245msCorrelation with Backend
When the backend triggers a workflow, the correlation ID is propagated via:
- Search Attributes:
CorrelationId,MerchantId,OrderId - Memo:
traceContext,correlationId
This enables end-to-end tracing from HTTP request → workflow → activities.
Viewing in OpenObserve
- Open http://localhost:5080 (login:
[email protected]/admin123) - Logs: Filter by
service: loop-processor-coreor workflow ID - Traces: View activity spans linked to parent workflow
- Metrics: Query activity execution metrics
Temporal UI
Access at http://localhost:8080 to:
- View running and completed workflows
- Inspect workflow history and state
- Search by
CorrelationIdsearch attribute - Manually trigger signals
- Terminate stuck workflows
Workflow IDs
Workflows use predictable IDs for easy lookup:
- Payment:
payment-{orderId} - Webhook:
webhook-{eventId}
Related Repositories
- backend - Triggers workflows via Temporal client
- processor-stripe - Stripe processor implementation
- processor-razorpay - Razorpay processor implementation
License
Copyright © 2025 PayLoops. All rights reserved.
