feat(payment): expose secure APIs and themed pages
This commit is contained in:
1 parent
dd8d6ecc3b
commit
2d77f5457c
15 files changed
+654
-13
No files matched your search
@@ -10,6 +10,7 @@ import {
|
||||
} from "./adapters.ts";
|
||||
import { configurePayment, type PaymentOptions, type PaymentService } from "./core.ts";
|
||||
import type { PaymentGateway, PaymentStore } from "./types.ts";
|
||||
import type { PaymentApiConfig } from "./http.ts";
|
||||
|
||||
export type ConfiguredPaymentGateway =
|
||||
| ({ provider: "sandbox" } & SandboxOptions)
|
||||
@@ -23,6 +24,43 @@ export interface PaymentConfig {
|
||||
/** Any number of named gateway accounts. Names are persisted with payment intents. */
|
||||
gateways: Record<string, ConfiguredPaymentGateway | false>;
|
||||
environment?: "development" | "test" | "production";
|
||||
api?: PaymentApiConfig | false;
|
||||
/** Defaults to the package database store. Override for custom persistence or tests. */
|
||||
store?: PaymentStore;
|
||||
}
|
||||
|
||||
function required(name: string, fields: Record<string, unknown>) {
|
||||
for (const [field, value] of Object.entries(fields))
|
||||
if (typeof value !== "string" || !value.trim())
|
||||
throw new Error(`WRN-PAYMENT-CONFIG: gateway '${name}' requires ${field}`);
|
||||
}
|
||||
|
||||
export function validatePaymentConfig(config: PaymentConfig) {
|
||||
if (!config?.default?.trim()) throw new Error("WRN-PAYMENT-CONFIG: payment.default is required");
|
||||
if (!config.gateways || typeof config.gateways !== "object")
|
||||
throw new Error("WRN-PAYMENT-CONFIG: payment.gateways is required");
|
||||
for (const [name, value] of Object.entries(config.gateways)) {
|
||||
if (value === false) continue;
|
||||
if (!name.trim()) throw new Error("WRN-PAYMENT-CONFIG: gateway name is required");
|
||||
if (value.provider === "stripe")
|
||||
required(name, {
|
||||
secretKey: value.secretKey,
|
||||
publishableKey: value.publishableKey,
|
||||
webhookSecret: value.webhookSecret,
|
||||
});
|
||||
if (value.provider === "razorpay")
|
||||
required(name, { keyId: value.keyId, keySecret: value.keySecret });
|
||||
if (value.provider === "paypal")
|
||||
required(name, {
|
||||
clientId: value.clientId,
|
||||
clientSecret: value.clientSecret,
|
||||
webhookId: value.webhookId,
|
||||
});
|
||||
}
|
||||
if (!config.gateways[config.default])
|
||||
throw new Error(
|
||||
`WRN-PAYMENT-CONFIG: default gateway '${config.default}' is not enabled or configured`,
|
||||
);
|
||||
}
|
||||
|
||||
function namedGateway(name: string, gateway: PaymentGateway): PaymentGateway {
|
||||
@@ -33,9 +71,7 @@ export function paymentOptionsFromConfig(
|
||||
config: PaymentConfig,
|
||||
store: PaymentStore,
|
||||
): PaymentOptions {
|
||||
if (!config?.default?.trim()) throw new Error("WRN-PAYMENT-CONFIG: payment.default is required");
|
||||
if (!config.gateways || typeof config.gateways !== "object")
|
||||
throw new Error("WRN-PAYMENT-CONFIG: payment.gateways is required");
|
||||
validatePaymentConfig(config);
|
||||
|
||||
const adapters: PaymentGateway[] = [];
|
||||
const webhookSecrets: Record<string, string> = {};
|
||||
@@ -63,10 +99,6 @@ export function paymentOptionsFromConfig(
|
||||
if ("webhookSecret" in value && value.webhookSecret) webhookSecrets[name] = value.webhookSecret;
|
||||
if (value.provider === "paypal" && value.webhookId) webhookSecrets[name] = value.webhookId;
|
||||
}
|
||||
if (!adapters.some((adapter) => adapter.id === config.default))
|
||||
throw new Error(
|
||||
`WRN-PAYMENT-CONFIG: default gateway '${config.default}' is not enabled or configured`,
|
||||
);
|
||||
return {
|
||||
store,
|
||||
adapters,
|
||||
|
||||
Reference in new issue
Block a user