@gmisoftware/przelewy24-payments-medusa
Version:
Przelewy24 (P24) payment integration plugin for Medusa e-commerce with BLIK, cards, and general P24 support.
491 lines • 44.7 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const crypto_1 = __importDefault(require("crypto"));
const utils_1 = require("@medusajs/framework/utils");
const p24_api_1 = require("../services/p24-api");
const p24_transaction_status_1 = require("./p24-transaction-status");
const p24_webhook_1 = require("./p24-webhook");
const get_smallest_unit_1 = require("../../../utils/get-smallest-unit");
const coerce_sandbox_1 = require("../../../utils/coerce-sandbox");
const p24_session_data_1 = require("../../../utils/p24-session-data");
const p24_payment_methods_1 = require("../../../utils/p24-payment-methods");
const p24_logger_1 = require("../../../utils/p24-logger");
const p24_errors_1 = require("../../../utils/p24-errors");
const payment_job_errors_1 = require("../../../utils/payment-job-errors");
class P24Base extends utils_1.AbstractPaymentProvider {
options_;
p24Api;
container_;
logger_;
static validateOptions(options) {
if (!(0, utils_1.isDefined)(options.merchant_id)) {
throw new Error("Required option `merchant_id` is missing in P24 plugin");
}
if (!(0, utils_1.isDefined)(options.pos_id)) {
throw new Error("Required option `pos_id` is missing in P24 plugin");
}
if (!(0, utils_1.isDefined)(options.api_key)) {
throw new Error("Required option `api_key` is missing in P24 plugin");
}
if (!(0, utils_1.isDefined)(options.crc)) {
throw new Error("Required option `crc` is missing in P24 plugin");
}
if (!(0, utils_1.isDefined)(options.frontend_url)) {
throw new Error("Required option `frontend_url` is missing in P24 plugin");
}
if (!(0, utils_1.isDefined)(options.backend_url)) {
throw new Error("Required option `backend_url` is missing in P24 plugin");
}
}
constructor(cradle, options) {
super(cradle, {
...options,
sandbox: (0, coerce_sandbox_1.coerceSandbox)(options.sandbox),
});
this.container_ = cradle;
this.options_ = {
...options,
sandbox: (0, coerce_sandbox_1.coerceSandbox)(options.sandbox),
debug: Boolean(options.debug),
};
this.p24Api = new p24_api_1.P24ApiService(this.options_);
this.logger_ = (0, p24_logger_1.createP24Logger)(cradle.logger, Boolean(this.options_.debug));
}
get options() {
return this.options_;
}
normalizePaymentCreateParams() {
const options = this.paymentIntentOptions;
const params = {
description: options.description ?? "Payment via Przelewy24",
};
if (options.channel != null && options.channel > 0) {
params.channel = options.channel;
}
if (options.method_id != null) {
params.method = options.method_id;
}
return params;
}
buildTransactionRequest(input, sessionId) {
const { currency_code, amount, data, context } = input;
const normalizedParams = this.normalizePaymentCreateParams();
const customerEmail = context?.customer?.email ||
(typeof data?.email === "string" && data.email.trim().length > 0
? data.email.trim()
: undefined) ||
data?.customer?.email ||
"customer@example.com";
const country = data?.country?.toUpperCase() || "PL";
const language = data?.language?.toLowerCase() || "pl";
const urlReturn = typeof data?.return_url === "string" && data.return_url.trim().length
? data.return_url
: `${this.options_.frontend_url}/payment/return?cart_id=${data?.cart_id ?? ""}`;
const psu = data?.psu;
const regulationAccept = data?.regulation_accept === true || data?.regulationAccept === true;
const cardRefId = typeof data?.card_ref_id === "string" ? data.card_ref_id : undefined;
const transactionRequest = {
sessionId,
amount: (0, get_smallest_unit_1.getSmallestUnit)(Number(amount), currency_code),
country,
language,
currency: currency_code.toUpperCase(),
description: normalizedParams.description || `Payment ${context?.idempotency_key}`,
email: customerEmail,
channel: normalizedParams.channel,
method: normalizedParams.method,
urlReturn,
urlStatus: `${this.options_.backend_url}/hooks/payment/${this.getProviderKey()}_przelewy24`,
...(regulationAccept ? { regulationAccept: true } : {}),
};
if (cardRefId) {
transactionRequest.cardData = {
means: {
referenceNumber: { id: cardRefId },
},
transactionType: "standard",
};
}
if (psu?.IP && psu?.userAgent) {
transactionRequest.additional = {
PSU: {
IP: psu.IP,
userAgent: psu.userAgent,
},
};
}
return transactionRequest;
}
resolvePaymentSessionQuery() {
const resolve = this.container_.resolve;
if (typeof resolve !== "function") {
return undefined;
}
try {
const query = resolve.call(this.container_, utils_1.ContainerRegistrationKeys.QUERY);
if (query && typeof query.graph === "function") {
return query;
}
}
catch {
// Payment provider scope does not register QUERY (e.g. webhook handling).
}
return undefined;
}
async findMedusaPaymentSessionId(p24SessionId) {
const inferred = (0, p24_session_data_1.inferMedusaPaymentSessionIdFromP24SessionId)(p24SessionId);
if (inferred) {
return inferred;
}
const query = this.resolvePaymentSessionQuery();
if (!query) {
return p24SessionId;
}
const byId = await query.graph({
entity: "payment_session",
fields: ["id", "data"],
filters: { id: p24SessionId },
});
if (byId.data?.[0]?.id) {
return byId.data[0].id;
}
const providerPrefix = `pp_${this.getProviderKey()}`;
const sessions = await query.graph({
entity: "payment_session",
fields: ["id", "data"],
filters: {
provider_id: { $like: `${providerPrefix}%` },
},
});
const matched = sessions.data?.find((session) => {
const sessionData = session.data ?? {};
return (sessionData.session_id === p24SessionId ||
sessionData.sessionId === p24SessionId);
});
return matched?.id ?? p24SessionId;
}
async enrichPaymentMethodFields(data) {
const methodId = (0, p24_payment_methods_1.extractMethodIdFromSessionData)(data);
if (!methodId) {
return data;
}
if (data.paymentMethod === methodId &&
typeof data.paymentMethodName === "string" &&
data.paymentMethodName.length > 0 &&
typeof data.paymentMethodGroup === "string" &&
data.paymentMethodGroup.length > 0) {
return data;
}
const currency = String(data.currency_code ?? data.currency ?? "PLN");
const lang = String(data.language ?? "pl").toLowerCase();
const amountGrosze = typeof data.amount_grosze === "number" && Number.isFinite(data.amount_grosze)
? Math.trunc(data.amount_grosze)
: typeof data.amount === "number" && Number.isFinite(data.amount)
? (0, get_smallest_unit_1.getSmallestUnit)(data.amount, currency)
: 0;
const metadata = await (0, p24_payment_methods_1.resolveP24PaymentMethodMetadata)(this.p24Api, {
methodId,
lang,
amountGrosze,
currency,
providerKey: this.getProviderKey(),
});
return {
...data,
...metadata,
method_id: methodId,
methodId,
};
}
async initiatePayment(input) {
const { currency_code, amount, context, data } = input;
try {
const sessionId = context?.idempotency_key;
const p24SessionId = data?.p24_session_id || sessionId;
if (!sessionId) {
throw this.buildError("Missing idempotency key for P24 transaction", new Error("idempotency_key is required"));
}
this.logger_.debug(`Initiating P24 payment amount=${amount} ${currency_code} session=${sessionId} context=${JSON.stringify((0, p24_logger_1.redactUnknown)(context))}`);
const transactionRequest = this.buildTransactionRequest(input, p24SessionId);
const sessionData = await this.p24Api.registerTransaction(transactionRequest);
if (sessionData.responseCode !== 0) {
throw this.buildError((0, p24_errors_1.buildLocalizedP24ErrorMessage)(sessionData, "Failed to register P24 transaction"), new Error(`P24 API error: ${sessionData.responseCode} - ${sessionData.message || "Unknown error"}`));
}
const isWhiteLabel = Boolean(this.paymentIntentOptions.white_label);
const redirectUrl = `${this.p24Api.getBaseRedirectURL()}/${sessionData.data.token}`;
const normalizedData = await this.enrichPaymentMethodFields((0, p24_session_data_1.normalizeP24SessionData)({
session_id: transactionRequest.sessionId,
medusa_payment_session_id: sessionId,
token: sessionData.data.token,
amount: Number(amount),
amount_grosze: transactionRequest.amount,
currency: currency_code,
currency_code,
description: transactionRequest.description,
email: transactionRequest.email,
country: transactionRequest.country,
language: transactionRequest.language,
channel: transactionRequest.channel,
method_id: transactionRequest.method,
...(transactionRequest.method != null
? { paymentMethod: transactionRequest.method }
: {}),
white_label: isWhiteLabel,
...(isWhiteLabel ? {} : { redirect_url: redirectUrl }),
responseCode: sessionData.responseCode,
}));
this.logger_.info(`P24 payment initiated for session ${sessionId}`);
return {
id: transactionRequest.sessionId,
data: normalizedData,
};
}
catch (error) {
this.logger_.error(`Error initiating P24 payment: ${error.message}`);
throw error;
}
}
async authorizePayment(input) {
const sessionId = (0, p24_session_data_1.getSessionId)(input.data);
if (!sessionId) {
throw this.buildError("Session ID is required for payment authorization", new Error("No session ID provided"));
}
try {
const { transactionDetails, p24Status, medusaStatus } = await this.getTransactionDetailsAndStatus(sessionId);
if (!["authorized", "captured"].includes(medusaStatus)) {
throw this.buildError(`Payment is not in a valid state for authorization: current status is ${medusaStatus}`, new Error(`Invalid payment status: ${medusaStatus}`));
}
let data = await this.enrichPaymentMethodFields((0, p24_session_data_1.normalizeP24SessionData)({
...input.data,
...transactionDetails.data,
amount_grosze: transactionDetails.data.amount,
p24_status: p24Status,
order_id: transactionDetails.data.orderId,
}));
const currencyCode = data.currency || input.data?.currency_code;
if (!currencyCode) {
throw this.buildError(`Missing currency code for amount conversion in authorizePayment (session: ${sessionId})`, new Error("currency_code is required to convert P24 amount"));
}
if (data.amount != null) {
data.amount = (0, get_smallest_unit_1.getAmountFromSmallestUnit)(data.amount, currencyCode);
}
if (data.originAmount != null) {
data.originAmount = (0, get_smallest_unit_1.getAmountFromSmallestUnit)(data.originAmount, currencyCode);
}
return {
data,
status: medusaStatus,
};
}
catch (error) {
this.logger_.error(`Error authorizing payment ${sessionId}: ${error.message}`);
throw error;
}
}
async capturePayment(input) {
const sessionId = (0, p24_session_data_1.getSessionId)(input.data);
const amount = input.data?.amount;
const currency = input.data?.currency || input.data?.currency_code;
const orderId = (0, p24_session_data_1.getOrderId)(input.data);
if (!sessionId || amount == null || !currency || orderId == null) {
throw this.buildError("Missing required data for payment capture", new Error("Session ID, amount, currency, and order ID are required"));
}
try {
const verification = await this.p24Api.verifyTransaction(sessionId, (0, get_smallest_unit_1.getSmallestUnit)(amount, currency), currency, orderId);
if (verification.responseCode !== 0 ||
verification.data.status !== "success") {
throw this.buildError("Payment capture failed", new Error(`Verification failed - responseCode: ${verification.responseCode}, status: ${verification.data.status}`));
}
return {
data: await this.enrichPaymentMethodFields((0, p24_session_data_1.normalizeP24SessionData)({
...input.data,
status: "captured",
captured_at: new Date().toISOString(),
order_id: orderId,
capture_verified: true,
})),
};
}
catch (error) {
const message = (0, payment_job_errors_1.getJobErrorMessage)(error);
if ((0, payment_job_errors_1.isExpectedStalePaymentJobFailure)(error)) {
this.logger_.debug(`Skipping stale payment capture for ${sessionId}: ${message}`);
}
else {
this.logger_.error(`Error capturing payment ${sessionId}: ${message}`);
}
throw error;
}
}
async deletePayment(input) {
return {
data: input.data,
};
}
async cancelPayment(input) {
return {
data: input.data,
};
}
async refundPayment(input) {
const { data: paymentData, amount: refundAmount, context } = input;
const sessionId = (0, p24_session_data_1.getSessionId)(paymentData);
const orderId = (0, p24_session_data_1.getOrderId)(paymentData);
if (!sessionId || orderId == null) {
throw this.buildError("No session ID or order ID provided while refunding payment", new Error("Missing session ID or order ID"));
}
try {
const refundsUuid = crypto_1.default.randomUUID();
const requestId = context?.idempotency_key;
if (typeof requestId !== "string" || requestId.length === 0) {
throw this.buildError("Missing idempotency key for refund request", new Error("context.idempotency_key is required"));
}
const currencyCode = paymentData?.currency_code ||
paymentData?.currency ||
"pln";
const refundData = {
requestId,
refunds: [
{
orderId,
sessionId,
amount: (0, get_smallest_unit_1.getSmallestUnit)(Number(refundAmount), currencyCode),
description: `Refund for order ${sessionId}`,
},
],
refundsUuid,
};
const refundResult = await this.p24Api.processRefund(refundData);
const refundStatus = refundResult.data[0]?.status;
const refundMessage = refundResult.data[0]?.message;
if (refundResult.responseCode !== 0 || !refundStatus) {
throw this.buildError("Refund request failed", new Error(`P24 API error: ${refundResult.responseCode} - ${refundMessage || "Unknown error"}`));
}
const p24RefundsNormal = Array.isArray(refundResult.data)
? refundResult.data.map((item) => {
const out = { ...item };
const curr = item.currency || currencyCode;
if (out.amount != null) {
out.amount = (0, get_smallest_unit_1.getAmountFromSmallestUnit)(out.amount, curr);
}
if (out.originAmount != null) {
out.originAmount = (0, get_smallest_unit_1.getAmountFromSmallestUnit)(out.originAmount, curr);
}
return out;
})
: refundResult.data;
return {
data: (0, p24_session_data_1.normalizeP24SessionData)({
...paymentData,
refund_amount: refundAmount,
refunded_at: new Date().toISOString(),
refunds_uuid: refundsUuid,
refund_request_id: requestId,
refund_status: refundStatus,
refund_message: refundMessage,
p24_refunds: p24RefundsNormal,
p24_response_code: refundResult.responseCode,
status: "refund_requested",
}),
};
}
catch (e) {
throw this.buildError("An error occurred in refundPayment", e);
}
}
async retrievePayment(input) {
try {
return {
data: (0, p24_session_data_1.normalizeP24SessionData)(input.data),
};
}
catch (e) {
throw this.buildError("An error occurred in retrievePayment", e);
}
}
async updatePayment(input) {
const { data, amount, currency_code, context } = input;
const amountNumeric = Number(amount);
const currentAmount = Number(data?.amount);
if (Number.isFinite(currentAmount) && currentAmount === amountNumeric) {
return { data: (0, p24_session_data_1.normalizeP24SessionData)(data) };
}
const baseSessionId = context?.idempotency_key || (0, p24_session_data_1.getSessionId)(data);
if (!baseSessionId) {
throw this.buildError("Cannot update P24 payment without session id", new Error("Missing session id"));
}
const newP24SessionId = `${baseSessionId}-${crypto_1.default.randomUUID()}`;
const initiated = await this.initiatePayment({
amount,
currency_code,
context: {
...context,
idempotency_key: baseSessionId,
},
data: {
...data,
amount: amountNumeric,
medusa_payment_session_id: baseSessionId,
p24_session_id: newP24SessionId,
},
});
return {
data: (0, p24_session_data_1.normalizeP24SessionData)({
...data,
...initiated.data,
session_id: initiated.data?.session_id,
medusa_payment_session_id: baseSessionId,
amount: amountNumeric,
}),
};
}
async getWebhookActionAndData(webhookData) {
return (0, p24_webhook_1.processP24Webhook)({
p24Api: this.p24Api,
logger: this.logger_,
findMedusaPaymentSessionId: (p24SessionId) => this.findMedusaPaymentSessionId(p24SessionId),
buildError: (message, error) => this.buildError(message, error),
}, webhookData);
}
async getPaymentStatus(input) {
const sessionId = input.context?.idempotency_key;
if (!sessionId) {
this.logger_.warn("No session ID provided for getPaymentStatus, returning pending");
return { status: "pending" };
}
try {
const { medusaStatus } = await this.getTransactionDetailsAndStatus(sessionId);
return { status: medusaStatus };
}
catch (error) {
this.logger_.error(`Error getting payment status for session ${sessionId}: ${error.message}`);
throw error;
}
}
async queryTransactionStatus(sessionId) {
return this.getTransactionDetailsAndStatus(sessionId);
}
async getTransactionDetailsAndStatus(sessionId) {
return (0, p24_transaction_status_1.fetchTransactionDetailsAndStatus)({
p24Api: this.p24Api,
logger: this.logger_,
buildError: (message, error) => this.buildError(message, error),
}, sessionId);
}
mapP24StatusToMedusaStatus(p24Status) {
return (0, p24_transaction_status_1.mapP24StatusToMedusaStatus)(p24Status);
}
buildError(message, error) {
const suffix = error instanceof Error
? error.message
: typeof error === "string"
? error
: "Unknown error";
return new Error(`${message}: ${suffix}`.trim());
}
}
exports.default = P24Base;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicDI0LWJhc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL3ByemVsZXd5MjQvY29yZS9wMjQtYmFzZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLG9EQUE0QjtBQU81QixxREFJbUM7QUFRbkMsaURBQW9EO0FBQ3BELHFFQUdrQztBQUNsQywrQ0FBa0Q7QUFDbEQsd0VBRzBDO0FBQzFDLGtFQUE4RDtBQUM5RCxzRUFLeUM7QUFDekMsNEVBRzRDO0FBQzVDLDBEQUEyRTtBQUMzRSwwREFBMEU7QUFDMUUsMEVBRzJDO0FBbUMzQyxNQUFlLE9BQVEsU0FBUSwrQkFBbUM7SUFDN0MsUUFBUSxDQUFhO0lBQ3JCLE1BQU0sQ0FBZ0I7SUFDdEIsVUFBVSxDQUFlO0lBQ3pCLE9BQU8sQ0FBcUM7SUFFL0QsTUFBTSxDQUFDLGVBQWUsQ0FBQyxPQUFtQjtRQUN4QyxJQUFJLENBQUMsSUFBQSxpQkFBUyxFQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDO1lBQ3BDLE1BQU0sSUFBSSxLQUFLLENBQUMsd0RBQXdELENBQUMsQ0FBQztRQUM1RSxDQUFDO1FBQ0QsSUFBSSxDQUFDLElBQUEsaUJBQVMsRUFBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUMvQixNQUFNLElBQUksS0FBSyxDQUFDLG1EQUFtRCxDQUFDLENBQUM7UUFDdkUsQ0FBQztRQUNELElBQUksQ0FBQyxJQUFBLGlCQUFTLEVBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDaEMsTUFBTSxJQUFJLEtBQUssQ0FBQyxvREFBb0QsQ0FBQyxDQUFDO1FBQ3hFLENBQUM7UUFDRCxJQUFJLENBQUMsSUFBQSxpQkFBUyxFQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQzVCLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0RBQWdELENBQUMsQ0FBQztRQUNwRSxDQUFDO1FBQ0Qs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