Providers
Hoikka uses a provider pattern for payments and shipping, making it easy to add new integrations.
Payment Providers
Interface
interface PaymentProvider {
code: string;
createPayment(order: Order): Promise<PaymentInfo>;
confirmPayment(transactionId: string): Promise<PaymentStatus>;
refundPayment?(transactionId: string, amount: number): Promise<RefundInfo>;
}Adding a Provider
src/lib/server/services/payments/providers/klarna.ts
export class KlarnaProvider implements PaymentProvider {
code = "klarna";
async createPayment(order: Order): Promise<PaymentInfo> {
// Create Klarna payment session
const session = await klarnaClient.createSession({
amount: order.total,
currency: "EUR"
// ...
});
return {
transactionId: session.id,
redirectUrl: session.redirect_url,
status: "pending"
};
}
async confirmPayment(transactionId: string): Promise<PaymentStatus> {
const payment = await klarnaClient.getPayment(transactionId);
return payment.status === "CAPTURED" ? "settled" : "pending";
}
}Register it:
src/lib/server/services/payments/index.ts
import { KlarnaProvider } from "./providers/klarna";
PROVIDERS.set("klarna", new KlarnaProvider());Enabling Stripe
Stripe is the built-in real payment provider. To enable it:
- Get API keys from Stripe Dashboard
- Set environment variables:
STRIPE_SECRET_KEY="sk_test_..."
PUBLIC_STRIPE_PUBLISHABLE_KEY="pk_test_..."Stripe is already registered in the provider map and seeded in the database. Once the env vars are set, customers will see a card form powered by Stripe Elements at checkout.
Without Stripe keys, the mock payment provider is used instead. Mock payments complete the order immediately without a separate confirmation step.
Shipping Providers
Interface
interface ShippingProvider {
code: string;
getRates(order: Order): Promise<ShippingRate[]>;
createShipment(order: Order): Promise<ShipmentInfo>;
trackShipment?(trackingNumber: string): Promise<ShipmentStatus>;
}Adding a Provider
src/lib/server/services/shipping/providers/dhl.ts
export class DhlProvider implements ShippingProvider {
code = "dhl";
async getRates(order: Order): Promise<ShippingRate[]> {
const rates = await dhlClient.getRates({
from: WAREHOUSE_ADDRESS,
to: order.shippingAddress,
weight: calculateWeight(order)
});
return rates.map((rate) => ({
id: rate.serviceCode,
name: rate.serviceName,
price: rate.totalPrice,
estimatedDays: rate.transitDays
}));
}
// ... other methods
}Register it:
src/lib/server/services/shipping/index.ts
import { DhlProvider } from "./providers/dhl";
PROVIDERS.set("dhl", new DhlProvider());Then add a matching row to the shipping_methods table (or add it to initializeDefaultMethods()).
Built-in Providers
Payments
- Stripe - Full integration with Payment Intents and Stripe Elements
- Mock - For development/testing (auto-completes orders immediately)
Shipping
- Flat Rate - Simple flat-rate shipping for development and demos
Last updated on