//#region src/errors.ts
var WebhookVerificationError = class extends Error {
	name = "WebhookVerificationError";
	code = "WEBHOOK_VERIFICATION_FAILED";
	httpStatus = 400;
	constructor(message) {
		super(message);
	}
};
var RefundFailedError = class extends Error {
	context;
	name = "RefundFailedError";
	code = "REFUND_FAILED";
	httpStatus = 502;
	constructor(context) {
		super(`refund ${context.providerRef} for "${context.chargeKey}" failed: status=${context.status}`);
		this.context = context;
	}
};
//#endregion
//#region src/index.ts
/**
* Deterministic idempotency key — stable parts only; never Date.now/random/UUID.
* Each part is percent-encoded before joining so a host-supplied part containing
* the `:` separator cannot collide two distinct part-vectors onto one key
* (e.g. `['refund','ord','1:r']` vs `['refund','ord:1','r']`) — that collision
* would silently no-op the second `appendEntry` (`inserted:false`) and overstate
* the ledger. Encoding keeps `join(':')` injective over arbitrary parts.
*/
function idempotencyKey(parts) {
	return parts.map(encodeURIComponent).join(":");
}
//#endregion
//#region src/paypal/types.ts
const MAX_DECIMAL_DIGITS = 21;
const GENERIC_PAYPAL_CHARGE_KEY = /^[A-Za-z0-9._-]+$/;
const PAYPAL_SUBSCRIPTION_STATUSES = /* @__PURE__ */ new Set([
	"APPROVAL_PENDING",
	"APPROVED",
	"ACTIVE",
	"SUSPENDED",
	"CANCELLED",
	"EXPIRED"
]);
var PaypalApiError = class extends Error {
	path;
	status;
	body;
	name = "PaypalApiError";
	constructor(path, status, body) {
		super(`PayPal ${path} failed with status ${status}`);
		this.path = path;
		this.status = status;
		this.body = body;
	}
};
var PaypalPayloadError = class extends Error {
	name = "PaypalPayloadError";
	constructor(message) {
		super(message);
	}
};
function getPaypalFetch(creds) {
	return creds.fetch ?? fetch;
}
function getPaypalApiBaseUrl(creds) {
	return creds.apiBaseUrl ?? "https://api-m.paypal.com";
}
function normalizeMinorUnits(value) {
	const amount = Number(value);
	if (!Number.isSafeInteger(amount)) throw new PaypalPayloadError(`PayPal amount exceeds Number safe integer range: ${value}`);
	return amount;
}
function assertPositiveMinorUnits(amount, field) {
	if (!Number.isSafeInteger(amount) || amount <= 0) throw new PaypalPayloadError(`PayPal ${field} must be a positive safe integer minor-unit amount`);
}
function decimalToMinorUnits(value) {
	const trimmed = value.trim();
	if (!/^-?\d+(\.\d+)?$/.test(trimmed)) throw new PaypalPayloadError(`invalid PayPal decimal amount "${value}"`);
	const negative = trimmed.startsWith("-");
	const [wholePart = "", fractionPart = ""] = (negative ? trimmed.slice(1) : trimmed).split(".");
	if (wholePart.length + fractionPart.length > MAX_DECIMAL_DIGITS) throw new PaypalPayloadError(`PayPal decimal amount has too many digits: ${value}`);
	if (fractionPart.length > 2 && /[^0]/.test(fractionPart.slice(2))) throw new PaypalPayloadError(`unsupported sub-minor-unit precision in "${value}"`);
	const normalizedFraction = (fractionPart + "00").slice(0, 2);
	const whole = BigInt(wholePart || "0");
	const fraction = BigInt(normalizedFraction);
	const minorUnits = whole * 100n + fraction;
	return negative ? -minorUnits : minorUnits;
}
function minorUnitsToDecimal(amount) {
	if (!Number.isInteger(amount)) throw new PaypalPayloadError(`PayPal amount must be integer minor units, got ${amount}`);
	const negative = amount < 0;
	const absolute = Math.abs(amount);
	const whole = Math.trunc(absolute / 100);
	const fraction = absolute % 100;
	return `${negative ? "-" : ""}${whole}.${String(fraction).padStart(2, "0")}`;
}
function parsePaypalMoney(money) {
	if (!money) throw new PaypalPayloadError("missing PayPal money payload");
	const rawValue = money.value ?? money.total;
	if (typeof rawValue !== "string") throw new PaypalPayloadError("missing PayPal money value");
	const currency = typeof money.currency_code === "string" ? money.currency_code : typeof money.currency === "string" ? money.currency : null;
	return {
		amountMinor: decimalToMinorUnits(rawValue),
		currency
	};
}
function parsePositivePaypalMoney(money) {
	const parsed = parsePaypalMoney(money);
	if (parsed.amountMinor <= 0n) throw new PaypalPayloadError("PayPal amount must be positive minor units");
	if (!parsed.currency) throw new PaypalPayloadError("missing PayPal money currency");
	return {
		amountMinor: parsed.amountMinor,
		currency: parsed.currency
	};
}
function mapSubscriptionRecord(record) {
	const id = requireString(record.id, "subscription.id");
	const planId = requireString(record.plan_id, "subscription.plan_id");
	const currentPeriod = resolveSubscriptionPeriod(record);
	const status = requireString(record.status, "subscription.status");
	if (!PAYPAL_SUBSCRIPTION_STATUSES.has(status)) throw new PaypalPayloadError(`unsupported PayPal subscription status "${status}"`);
	return {
		id,
		status,
		currentPeriod,
		planId
	};
}
function buildSubscriptionCreateBody(input) {
	return {
		plan_id: input.planId,
		custom_id: input.currentPeriod
	};
}
function buildOrderCreateBody(req) {
	assertPositiveMinorUnits(req.amount, "charge amount");
	if (!GENERIC_PAYPAL_CHARGE_KEY.test(req.chargeKey)) throw new PaypalPayloadError("PayPal chargeKey must contain only letters, numbers, \".\", \"_\", or \"-\"");
	return {
		intent: "CAPTURE",
		purchase_units: [{
			invoice_id: req.chargeKey,
			custom_id: req.chargeKey,
			amount: {
				currency_code: req.currency.toUpperCase(),
				value: minorUnitsToDecimal(req.amount)
			}
		}]
	};
}
function requireString(value, field) {
	if (typeof value !== "string" || value.trim() === "") throw new PaypalPayloadError(`missing PayPal field "${field}"`);
	return value;
}
function resolveSubscriptionPeriod(record) {
	if (typeof record.custom_id === "string" && record.custom_id.trim() !== "") return validatePeriod(record.custom_id, "subscription.custom_id");
	const normalized = normalizePeriod(record.start_time);
	if (normalized) return normalized;
	throw new PaypalPayloadError("missing PayPal subscription current period");
}
function validatePeriod(value, field) {
	if (!/^\d{4}-\d{2}$/.test(value)) throw new PaypalPayloadError(`invalid PayPal ${field} period "${value}"`);
	return value;
}
function normalizePeriod(value) {
	if (typeof value !== "string" || value.trim() === "") return null;
	if (/^\d{4}-\d{2}$/.test(value)) return value;
	const date = new Date(value);
	if (Number.isNaN(date.getTime())) return null;
	return `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, "0")}`;
}
function resolveChargeKey(subscriptionId, period, fallback) {
	if (subscriptionId && period) return `${subscriptionId}:${period}`;
	return fallback;
}
function extractApproveUrl(order) {
	for (const link of order.links ?? []) if (link.rel === "approve" && typeof link.href === "string" && link.href.trim() !== "") return link.href;
	return null;
}
function extractSettledCapture(order) {
	const capture = order.purchase_units?.[0]?.payments?.captures?.[0];
	if (!capture || capture.status !== "COMPLETED") return null;
	const captureId = requireString(capture.id, "order.purchase_units[0].payments.captures[0].id");
	const { amountMinor, currency } = parsePositivePaypalMoney(capture.amount);
	return {
		captureId,
		amountMinor,
		currency
	};
}
function extractCaptureId(refund) {
	if (refund.providerChargeId?.trim()) return refund.providerChargeId;
	if (refund.refundId.trim() !== "") return refund.refundId;
	throw new PaypalPayloadError("PayPal refund requires a providerChargeId");
}
//#endregion
//#region src/paypal/client.ts
function encodeBasicAuth(value) {
	return btoa(value);
}
var PaypalClient = class {
	creds;
	fetchImpl;
	apiBaseUrl;
	accessToken = null;
	accessTokenExpiresAt = 0;
	constructor(creds) {
		this.creds = creds;
		this.fetchImpl = getPaypalFetch(creds);
		this.apiBaseUrl = getPaypalApiBaseUrl(creds);
	}
	async createOrder(req) {
		return this.requestJson("/v2/checkout/orders", {
			method: "POST",
			headers: {
				"Content-Type": "application/json",
				"PayPal-Request-Id": req.chargeKey
			},
			body: JSON.stringify(buildOrderCreateBody(req))
		}, [200, 201]);
	}
	async getCapture(id) {
		return this.requestJson(`/v2/payments/captures/${id}`, { method: "GET" });
	}
	async refundCapture(req) {
		assertPositiveMinorUnits(req.amount, "refund amount");
		const captureId = extractCaptureId(req);
		const capture = await this.getCapture(captureId);
		const currency = capture.amount?.currency_code ?? capture.amount?.currency ?? void 0;
		return this.requestJson(`/v2/payments/captures/${captureId}/refund`, {
			method: "POST",
			headers: {
				"Content-Type": "application/json",
				"PayPal-Request-Id": req.refundKey
			},
			body: JSON.stringify(currency ? { amount: {
				currency_code: currency,
				value: (req.amount / 100).toFixed(2)
			} } : {})
		}, [
			200,
			201,
			202
		]);
	}
	async createSubscription(input) {
		return mapSubscriptionRecord(await this.requestJson("/v1/billing/subscriptions", {
			method: "POST",
			headers: {
				"Content-Type": "application/json",
				"PayPal-Request-Id": input.idempotencyKey
			},
			body: JSON.stringify(buildSubscriptionCreateBody(input))
		}, [200, 201]));
	}
	async cancelSubscription(id) {
		await this.requestJson(`/v1/billing/subscriptions/${id}/cancel`, {
			method: "POST",
			headers: { "Content-Type": "application/json" },
			body: JSON.stringify({ reason: "Canceled by merchant" })
		}, [
			200,
			202,
			204
		]);
	}
	async getSubscription(id) {
		return mapSubscriptionRecord(await this.requestJson(`/v1/billing/subscriptions/${id}`, { method: "GET" }));
	}
	async fetchCertificate(url) {
		const response = await this.fetchImpl(url, { method: "GET" });
		if (!response.ok) throw new PaypalApiError(url, response.status, await safeParseBody(response));
		return response.text();
	}
	async requestJson(path, init, okStatuses = [200]) {
		const token = await this.getAccessToken();
		const response = await this.fetchImpl(`${this.apiBaseUrl}${path}`, {
			...init,
			headers: {
				Accept: "application/json",
				Authorization: `Bearer ${token}`,
				...init.headers ?? {}
			}
		});
		if (!okStatuses.includes(response.status)) throw new PaypalApiError(path, response.status, await safeParseBody(response));
		if (response.status === 204) return;
		return await response.json();
	}
	async getAccessToken() {
		const now = Date.now();
		if (this.accessToken && now < this.accessTokenExpiresAt) return this.accessToken;
		const response = await this.fetchImpl(`${this.apiBaseUrl}/v1/oauth2/token`, {
			method: "POST",
			headers: {
				Accept: "application/json",
				Authorization: `Basic ${encodeBasicAuth(`${this.creds.clientId}:${this.creds.clientSecret}`)}`,
				"Content-Type": "application/x-www-form-urlencoded"
			},
			body: new URLSearchParams({ grant_type: "client_credentials" }).toString()
		});
		const body = await safeParseBody(response);
		if (!response.ok) throw new PaypalApiError("/v1/oauth2/token", response.status, body);
		const accessToken = typeof body === "object" && body !== null ? body.access_token : void 0;
		if (typeof accessToken !== "string" || accessToken.trim() === "") throw new PaypalApiError("/v1/oauth2/token", response.status, body);
		const expiresIn = typeof body === "object" && body !== null && typeof body.expires_in === "number" ? body.expires_in : 300;
		this.accessToken = accessToken;
		this.accessTokenExpiresAt = now + Math.max(1, expiresIn - 30) * 1e3;
		return accessToken;
	}
};
async function safeParseBody(response) {
	if ((response.headers.get("content-type") ?? "").includes("application/json")) try {
		return await response.json();
	} catch {
		return null;
	}
	try {
		return await response.text();
	} catch {
		return null;
	}
}
//#endregion
//#region src/paypal/webhook.ts
const TEXT_ENCODER = new TextEncoder();
async function parsePaypalWebhook(creds, rawBody, headers) {
	const client = new PaypalClient(creds);
	const signatureHeaders = readWebhookHeaders(headers);
	await verifyWebhookSignature(client, creds.webhookId, signatureHeaders, rawBody);
	let payload;
	try {
		payload = JSON.parse(rawBody);
	} catch {
		throw new PaypalPayloadError("PayPal webhook payload is not valid JSON");
	}
	const eventId = requireString(payload.id, "webhook.id");
	const eventType = requireString(payload.event_type, "webhook.event_type");
	const resource = asRecord(payload.resource, "webhook.resource");
	if (eventType === "PAYMENT.SALE.COMPLETED") {
		const providerRef = requireString(resource.id, "resource.id");
		const subscriptionId = readFirstString(resource, "billing_agreement_id", "subscription_id", "agreement_id");
		const period = resolveWebhookPeriod(resource);
		const chargeKey = resolveChargeKey(subscriptionId, period, providerRef);
		const { amountMinor, currency } = parsePositivePaypalMoney(readMoney(resource));
		return {
			eventId,
			kind: "settlement",
			chargeKey,
			providerRef,
			amount: normalizeMinorUnits(amountMinor),
			currency,
			subscriptionId: subscriptionId ?? void 0,
			period: period ?? void 0,
			amountMinor
		};
	}
	if (eventType === "PAYMENT.SALE.REFUNDED") {
		const refundId = requireString(resource.id, "resource.id");
		const subscriptionId = readFirstString(resource, "billing_agreement_id", "subscription_id", "agreement_id");
		const period = resolveRefundChargePeriod(resource);
		const fallbackChargeKey = readFirstString(resource, "sale_id", "parent_payment") ?? refundId;
		const providerChargeId = requireString(readFirstString(resource, "sale_id", "parent_payment"), "resource.sale_id");
		const chargeKey = resolveChargeKey(subscriptionId, period, fallbackChargeKey);
		const { amountMinor, currency } = parsePositivePaypalMoney(readMoney(resource));
		return {
			eventId,
			kind: "refund",
			refundKey: idempotencyKey([
				"refund",
				chargeKey,
				refundId
			]),
			chargeKey,
			providerChargeId,
			providerRef: refundId,
			amount: normalizeMinorUnits(amountMinor),
			currency
		};
	}
	return {
		eventId,
		kind: "other",
		raw: payload
	};
}
function readWebhookHeaders(headers) {
	return {
		authAlgo: requireHeader(headers, "paypal-auth-algo", "paypal-auth-algo", "paypal-auth_algo"),
		certUrl: requireHeader(headers, "paypal-cert-url", "paypal-cert_url"),
		signature: requireHeader(headers, "paypal-transmission-sig", "paypal-transmission_sig"),
		transmissionId: requireHeader(headers, "paypal-transmission-id", "paypal-transmission_id"),
		transmissionTime: requireHeader(headers, "paypal-transmission-time", "paypal-transmission_time")
	};
}
async function verifyWebhookSignature(client, webhookId, headers, rawBody) {
	assertTrustedCertUrl(headers.certUrl);
	const spki = pemToSpki(await client.fetchCertificate(headers.certUrl));
	const algorithm = resolveVerifyAlgorithm(headers.authAlgo);
	const key = await crypto.subtle.importKey("spki", spki, algorithm, false, ["verify"]);
	const signedMessage = `${headers.transmissionId}|${headers.transmissionTime}|${webhookId}|${crc32(rawBody)}`;
	const signature = decodeBase64(headers.signature);
	if (!await crypto.subtle.verify(algorithm, key, copyBytes(signature), copyBytes(TEXT_ENCODER.encode(signedMessage)))) throw new WebhookVerificationError("PayPal webhook signature verification failed");
}
function requireHeader(headers, ...names) {
	for (const name of names) {
		const value = headers.get(name);
		if (typeof value === "string" && value.trim() !== "") return value;
	}
	throw new WebhookVerificationError(`missing PayPal webhook header: ${names[0]}`);
}
function resolveVerifyAlgorithm(name) {
	if (name === "SHA256withRSA" || name === "RSASSA-PKCS1-v1_5") return {
		name: "RSASSA-PKCS1-v1_5",
		hash: "SHA-256"
	};
	throw new WebhookVerificationError(`unsupported PayPal webhook algorithm: ${name}`);
}
function assertTrustedCertUrl(value) {
	let url;
	try {
		url = new URL(value);
	} catch {
		throw new WebhookVerificationError(`invalid PayPal cert url: ${value}`);
	}
	const hostname = url.hostname.toLowerCase();
	if (url.protocol !== "https:" || hostname !== "paypal.com" && hostname !== "api-m.paypal.com" && !hostname.endsWith(".paypal.com")) throw new WebhookVerificationError(`untrusted PayPal cert url: ${value}`);
}
function pemToSpki(pem) {
	const trimmed = pem.trim();
	if (trimmed.includes("BEGIN PUBLIC KEY")) return copyArrayBuffer(decodePemBlock(trimmed, "PUBLIC KEY"));
	if (trimmed.includes("BEGIN CERTIFICATE")) return copyArrayBuffer(extractSpkiFromCertificate(decodePemBlock(trimmed, "CERTIFICATE")));
	throw new WebhookVerificationError("unsupported PayPal certificate PEM block");
}
function decodePemBlock(pem, label) {
	const begin = `-----BEGIN ${label}-----`;
	const end = `-----END ${label}-----`;
	return decodeBase64(pem.replace(begin, "").replace(end, "").replace(/\s+/g, ""));
}
function decodeBase64(value) {
	const decoded = atob(value);
	const bytes = new Uint8Array(decoded.length);
	for (let index = 0; index < decoded.length; index += 1) bytes[index] = decoded.charCodeAt(index);
	return bytes;
}
function copyBytes(bytes) {
	const copy = new Uint8Array(bytes.byteLength);
	copy.set(bytes);
	return copy;
}
function copyArrayBuffer(bytes) {
	return copyBytes(bytes).buffer;
}
function extractSpkiFromCertificate(certificateDer) {
	const certificate = readDerElement(certificateDer, 0);
	const certificateBody = certificateDer.subarray(certificate.valueOffset, certificate.endOffset);
	let cursor = 0;
	const tbsCertificate = readDerElement(certificateBody, cursor);
	const tbsValue = certificateBody.subarray(tbsCertificate.valueOffset, tbsCertificate.endOffset);
	cursor = 0;
	let element = readDerElement(tbsValue, cursor);
	if (element.tag === 160) {
		cursor = element.nextOffset;
		element = readDerElement(tbsValue, cursor);
	}
	cursor = element.nextOffset;
	element = readDerElement(tbsValue, cursor);
	cursor = element.nextOffset;
	element = readDerElement(tbsValue, cursor);
	cursor = element.nextOffset;
	element = readDerElement(tbsValue, cursor);
	cursor = element.nextOffset;
	element = readDerElement(tbsValue, cursor);
	cursor = element.nextOffset;
	element = readDerElement(tbsValue, cursor);
	return tbsValue.subarray(element.startOffset, element.nextOffset);
}
function readDerElement(bytes, offset) {
	const tag = bytes[offset];
	if (tag === void 0) throw new WebhookVerificationError("unexpected end of DER payload");
	const lengthByte = bytes[offset + 1];
	if (lengthByte === void 0) throw new WebhookVerificationError("missing DER length");
	let length = 0;
	let valueOffset = offset + 2;
	if ((lengthByte & 128) === 0) length = lengthByte;
	else {
		const lengthBytes = lengthByte & 127;
		if (lengthBytes === 0 || lengthBytes > 4) throw new WebhookVerificationError("unsupported DER length encoding");
		valueOffset = offset + 2 + lengthBytes;
		for (let index = 0; index < lengthBytes; index += 1) {
			const value = bytes[offset + 2 + index];
			if (value === void 0) throw new WebhookVerificationError("truncated DER length");
			length = length << 8 | value;
		}
	}
	const endOffset = valueOffset + length;
	if (endOffset > bytes.length) throw new WebhookVerificationError("truncated DER element");
	return {
		tag,
		startOffset: offset,
		valueOffset,
		endOffset,
		nextOffset: endOffset
	};
}
function crc32(value) {
	let crc = 4294967295;
	const bytes = TEXT_ENCODER.encode(value);
	for (const byte of bytes) {
		crc ^= byte;
		for (let bit = 0; bit < 8; bit += 1) {
			const mask = -(crc & 1);
			crc = crc >>> 1 ^ 3988292384 & mask;
		}
	}
	return (crc ^ 4294967295) >>> 0;
}
function asRecord(value, field) {
	if (!value || typeof value !== "object") throw new PaypalPayloadError(`missing PayPal object "${field}"`);
	return value;
}
function readFirstString(record, ...keys) {
	for (const key of keys) {
		const value = record[key];
		if (typeof value === "string" && value.trim() !== "") return value;
	}
	return null;
}
function readMoney(resource) {
	const amount = resource.amount;
	if (!amount || typeof amount !== "object") throw new PaypalPayloadError("missing PayPal resource amount");
	return amount;
}
function resolveWebhookPeriod(resource) {
	const billingPeriod = resource.billing_period;
	if (billingPeriod && typeof billingPeriod === "object") {
		const record = billingPeriod;
		const normalized = normalizePeriod(record.start_date) ?? normalizePeriod(record.period_start) ?? normalizePeriod(record.end_date) ?? normalizePeriod(record.period_end);
		if (normalized) return normalized;
	}
	return normalizePeriod(resource.create_time) ?? normalizePeriod(resource.update_time) ?? normalizePeriod(resource.time) ?? normalizePeriod(resource.sale_time);
}
function resolveRefundChargePeriod(resource) {
	for (const key of [
		"sale",
		"capture",
		"parent_sale",
		"parent_capture"
	]) {
		const nested = resource[key];
		if (nested && typeof nested === "object") {
			const period = resolveWebhookPeriod(nested);
			if (period) return period;
		}
	}
	const billingPeriod = resource.billing_period;
	if (billingPeriod && typeof billingPeriod === "object") {
		const period = resolveWebhookPeriod({ billing_period: billingPeriod });
		if (period) return period;
	}
	if (readFirstString(resource, "billing_agreement_id", "subscription_id", "agreement_id")) throw new PaypalPayloadError("missing PayPal original charge period for subscription refund");
	return null;
}
//#endregion
//#region src/paypal/index.ts
var PaypalProvider = class {
	creds;
	provider = "paypal";
	emitsInvoiceOnCharge = false;
	client;
	constructor(creds) {
		this.creds = creds;
		this.client = new PaypalClient(creds);
	}
	async charge(req) {
		const order = await this.client.createOrder(req);
		const orderId = typeof order.id === "string" && order.id.trim() !== "" ? order.id : req.chargeKey;
		const settledCapture = extractSettledCapture(order);
		if (settledCapture) return {
			kind: "settled",
			chargeKey: req.chargeKey,
			providerRef: settledCapture.captureId,
			amount: normalizeMinorUnits(settledCapture.amountMinor),
			currency: settledCapture.currency
		};
		const approvalUrl = extractApproveUrl(order);
		if (!approvalUrl) throw new PaypalPayloadError("PayPal order requires payer approval but no approve link was returned");
		return {
			kind: "requires_client_action",
			chargeKey: req.chargeKey,
			providerRef: orderId,
			clientSecret: approvalUrl
		};
	}
	async refund(req) {
		const refund = await this.client.refundCapture(req);
		if (refund.status === "PENDING") return { kind: "pending" };
		const refundId = typeof refund.id === "string" && refund.id.trim() !== "" ? refund.id : req.refundKey;
		const { amountMinor, currency } = parsePositivePaypalMoney(refund.amount);
		const amount = normalizeMinorUnits(amountMinor);
		if (refund.status && refund.status !== "COMPLETED") throw new RefundFailedError({
			chargeKey: req.chargeKey,
			providerRef: refundId,
			status: refund.status
		});
		return {
			kind: "refunded",
			refundKey: req.refundKey,
			chargeKey: req.chargeKey,
			providerRef: refundId,
			amount,
			currency
		};
	}
	async reconcileRefund(req) {
		if (req.amountMinor <= 0n || req.amountMinor > BigInt(Number.MAX_SAFE_INTEGER)) return {
			kind: "definite_failure",
			code: "INVALID_AMOUNT"
		};
		try {
			const refund = await this.client.refundCapture({
				refundKey: req.refundKey,
				chargeKey: req.providerChargeId,
				refundId: req.refundKey,
				providerChargeId: req.providerChargeId,
				amount: Number(req.amountMinor)
			});
			const { amountMinor, currency } = parsePositivePaypalMoney(refund.amount);
			if (refund.status === "PENDING") return { kind: "pending_or_unknown" };
			if (refund.status && refund.status !== "COMPLETED") return {
				kind: "definite_failure",
				code: refund.status
			};
			if (amountMinor !== req.amountMinor || currency !== req.currency) return {
				kind: "definite_failure",
				code: "REFUND_FACT_MISMATCH"
			};
			return {
				kind: "confirmed",
				providerRefundId: typeof refund.id === "string" && refund.id.trim() !== "" ? refund.id : req.refundKey,
				amountMinor,
				currency
			};
		} catch {
			return { kind: "pending_or_unknown" };
		}
	}
	async parseWebhook(rawOrHeaders, headersOrRaw) {
		const rawBody = typeof rawOrHeaders === "string" ? rawOrHeaders : headersOrRaw;
		const headers = rawOrHeaders instanceof Headers ? rawOrHeaders : headersOrRaw;
		if (typeof rawBody !== "string" || !(headers instanceof Headers)) throw new PaypalPayloadError("PayPal parseWebhook requires a raw body string and Headers");
		return parsePaypalWebhook(this.creds, rawBody, headers);
	}
	async createSubscription(input) {
		return this.client.createSubscription(input);
	}
	async cancelSubscription(id) {
		await this.client.cancelSubscription(id);
	}
	async getSubscription(id) {
		return this.client.getSubscription(id);
	}
};
//#endregion
export { PaypalApiError, PaypalPayloadError, PaypalProvider };
