@gmisoftware/przelewy24-payments-medusa
Version:
Przelewy24 (P24) payment integration plugin for Medusa e-commerce with BLIK, cards, and general P24 support.
293 lines • 21.9 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.P24ApiService = exports.P24ApiError = void 0;
const crypto_1 = __importDefault(require("crypto"));
const coerce_sandbox_1 = require("../../../utils/coerce-sandbox");
const p24_errors_1 = require("../../../utils/p24-errors");
const p24_webhook_ips_1 = require("../../../utils/p24-webhook-ips");
class P24ApiError extends Error {
responseCode;
payload;
constructor(message, responseCode, payload) {
super(message);
this.name = "P24ApiError";
this.responseCode = responseCode;
this.payload = payload;
}
}
exports.P24ApiError = P24ApiError;
class P24ApiService {
options;
baseURL;
constructor(options) {
this.options = {
...options,
sandbox: (0, coerce_sandbox_1.coerceSandbox)(options.sandbox),
};
this.baseURL = this.options.sandbox
? "https://sandbox.przelewy24.pl/api/v1"
: "https://secure.przelewy24.pl/api/v1";
}
getBaseURL() {
return this.baseURL;
}
/**
* Register a new transaction with P24
*/
async registerTransaction(data) {
const requestData = {
merchantId: parseInt(this.options.merchant_id),
posId: parseInt(this.options.pos_id),
sessionId: data.sessionId,
amount: data.amount,
currency: data.currency,
description: data.description,
email: data.email,
country: data.country,
language: data.language,
urlReturn: data.urlReturn,
urlStatus: data.urlStatus,
sign: this.generateSign({
sessionId: data.sessionId,
merchantId: parseInt(this.options.merchant_id),
amount: data.amount,
currency: data.currency,
crc: this.options.crc,
}),
};
if (data.channel != null && data.channel > 0) {
requestData.channel = data.channel;
}
if (data.method != null) {
requestData.method = data.method;
}
if (data.regulationAccept === true) {
requestData.regulationAccept = true;
}
if (data.cardData) {
requestData.cardData = data.cardData;
}
if (data.additional) {
requestData.additional = data.additional;
}
return this.makeRequest("/transaction/register", "POST", requestData);
}
/**
* Verify a transaction with P24
*/
async verifyTransaction(sessionId, amount, currency, orderId) {
const data = {
merchantId: parseInt(this.options.merchant_id),
posId: parseInt(this.options.pos_id),
sessionId,
amount,
currency,
orderId,
sign: this.generateVerificationSign({
sessionId,
orderId,
amount,
currency,
crc: this.options.crc,
}),
};
return this.makeRequest("/transaction/verify", "PUT", data);
}
/**
* List available payment methods for amount/currency.
*/
async getPaymentMethods(lang, amountGrosze, currency) {
const params = new URLSearchParams({
amount: String(Math.max(0, Math.trunc(amountGrosze))),
currency: currency.toUpperCase(),
});
return this.makeRequest(`/payment/methods/${encodeURIComponent(lang.toLowerCase())}?${params.toString()}`, "GET");
}
/**
* Get transaction details by session ID
*/
async getTransactionBySessionId(sessionId) {
const endpoint = `/transaction/by/sessionId/${encodeURIComponent(sessionId)}`;
return this.makeRequest(endpoint, "GET");
}
/**
* Process a refund
*/
async processRefund(refundData) {
return this.makeRequest("/transaction/refund", "POST", refundData);
}
/**
* Charge payment using BLIK code
*/
async chargeBlikByCode(data) {
return this.makeRequest("/paymentMethod/blik/chargeByCode", "POST", {
token: data.token,
blikCode: data.blikCode,
});
}
/**
* Charge card with 3DS (white-label iframe flow)
*/
async chargeCardWith3ds(token) {
return this.makeRequest("/card/chargeWith3ds", "POST", { token });
}
/**
* Charge card without 3DS redirect
*/
async chargeCard(token) {
return this.makeRequest("/card/charge", "POST", { token });
}
/**
* Get card metadata for an order
*/
async getCardInfo(orderId) {
return this.makeRequest(`/card/info/${orderId}`, "GET");
}
/**
* Make a generic request to P24 API
*/
async makeRequest(endpoint, method, data) {
const url = `${this.baseURL}${endpoint}`;
const credentials = Buffer.from(`${this.options.pos_id}:${this.options.api_key}`).toString("base64");
const response = await fetch(url, {
method,
headers: {
"Content-Type": "application/json",
Authorization: `Basic ${credentials}`,
},
body: data ? JSON.stringify(data) : undefined,
});
const responseText = await response.text();
let parsed = {};
if (responseText) {
try {
parsed = JSON.parse(responseText);
}
catch {
parsed = { message: responseText };
}
}
if (!response.ok) {
throw new P24ApiError((0, p24_errors_1.buildLocalizedP24ErrorMessage)(parsed, `P24 API request failed: ${response.status} ${response.statusText}`), parsed?.responseCode, parsed);
}
return parsed;
}
/**
* Generate signature for transaction registration
*/
generateSign(data) {
const jsonString = JSON.stringify(data, null, 0).replace(/\\\//g, "/");
return crypto_1.default.createHash("sha384").update(jsonString, "utf8").digest("hex");
}
/**
* Generate signature for transaction verification
*/
generateVerificationSign(data) {
const jsonString = JSON.stringify(data, null, 0).replace(/\\\//g, "/");
return crypto_1.default.createHash("sha384").update(jsonString, "utf8").digest("hex");
}
secureCompareHex(expected, received) {
const expectedBuf = Buffer.from(expected, "hex");
const receivedBuf = Buffer.from(received, "hex");
if (expectedBuf.length !== receivedBuf.length) {
return false;
}
return crypto_1.default.timingSafeEqual(expectedBuf, receivedBuf);
}
/**
* Verify webhook signature
*/
verifyWebhookSignature(payload, receivedSign) {
const signData = {
merchantId: parseInt(this.options.merchant_id),
posId: parseInt(this.options.pos_id),
sessionId: payload.sessionId,
amount: payload.amount,
originAmount: payload.originAmount,
currency: payload.currency,
orderId: payload.orderId,
methodId: payload.methodId,
statement: payload.statement,
crc: this.options.crc,
};
const expectedSign = this.hashSignaturePayload(signData);
return this.secureCompareHex(expectedSign, receivedSign);
}
verifyCardPaymentNotificationSignature(payload, receivedSign, isFailure = false) {
const signData = isFailure
? {
merchantId: parseInt(this.options.merchant_id),
posId: parseInt(this.options.pos_id),
sessionId: payload.sessionId,
orderId: payload.orderId,
amount: payload.amount,
currency: payload.currency,
status: payload.status,
crc: this.options.crc,
}
: {
merchantId: parseInt(this.options.merchant_id),
posId: parseInt(this.options.pos_id),
sessionId: payload.sessionId,
orderId: payload.orderId,
amount: payload.amount,
currency: payload.currency,
refId: payload.refId,
bin: payload.bin,
mask: payload.mask,
cardType: payload.cardType,
cardDate: payload.cardDate,
hash: payload.hash,
crc: this.options.crc,
};
const expectedSign = this.hashSignaturePayload(signData);
return this.secureCompareHex(expectedSign, receivedSign);
}
isAllowedWebhookIp(ipAddress) {
return (0, p24_webhook_ips_1.isAllowedP24WebhookSourceIp)(ipAddress, {
sandbox: this.options.sandbox,
});
}
hashSignaturePayload(payload) {
const jsonString = JSON.stringify(payload, null, 0).replace(/\\\//g, "/");
return crypto_1.default.createHash("sha384").update(jsonString, "utf8").digest("hex");
}
/**
* Get base redirect URL for P24
*/
getBaseRedirectURL() {
return this.options.sandbox
? "https://sandbox.przelewy24.pl/trnRequest"
: "https://secure.przelewy24.pl/trnRequest";
}
generateCardTokenizationSign(sessionId) {
return this.hashSignaturePayload({
merchantId: parseInt(this.options.merchant_id),
sessionId,
crc: this.options.crc,
});
}
getCardTokenizationScriptUrl() {
const base = this.options.sandbox
? "https://sandbox.przelewy24.pl"
: "https://secure.przelewy24.pl";
return `${base}/js/cardTokenizationIframe.min.js`;
}
getCardWhitelabelScriptUrl(token) {
const base = this.options.sandbox
? "https://sandbox.przelewy24.pl"
: "https://secure.przelewy24.pl";
return `${base}/whitelabel/card/javascript/${encodeURIComponent(token)}`;
}
getCardWidgetScriptUrl(token) {
const base = this.options.sandbox
? "https://sandbox.przelewy24.pl"
: "https://secure.przelewy24.pl";
return `${base}/inchtml/ajaxPayment/ajax.js?token=${encodeURIComponent(token)}`;
}
}
exports.P24ApiService = P24ApiService;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicDI0LWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9wcm92aWRlcnMvcHJ6ZWxld3kyNC9zZXJ2aWNlcy9wMjQtYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLG9EQUE0QjtBQWtCNUIsa0VBQThEO0FBQzlELDBEQUEwRTtBQUMxRSxvRUFBNkU7QUFFN0UsTUFBYSxXQUFZLFNBQVEsS0FBSztJQUMzQixZQUFZLENBQVU7SUFDdEIsT0FBTyxDQUFXO0lBRTNCLFlBQVksT0FBZSxFQUFFLFlBQXFCLEVBQUUsT0FBaUI7UUFDbkUsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2YsSUFBSSxDQUFDLElBQUksR0FBRyxhQUFhLENBQUM7UUFDMUIsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUM7UUFDakMsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7SUFDekIsQ0FBQztDQUNGO0FBVkQsa0NBVUM7QUFFRCxNQUFhLGFBQWE7SUFDUCxPQUFPLENBQWE7SUFDcEIsT0FBTyxDQUFTO0lBRWpDLFlBQVksT0FBbUI7UUFDN0IsSUFBSSxDQUFDLE9BQU8sR0FBRztZQUNiLEdBQUcsT0FBTztZQUNWLE9BQU8sRUFBRSxJQUFBLDhCQUFhLEVBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQztTQUN4QyxDQUFDO1FBQ0YsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU87WUFDakMsQ0FBQyxDQUFDLHNDQUFzQztZQUN4QyxDQUFDLENBQUMscUNBQXFDLENBQUM7SUFDNUMsQ0FBQztJQUVELFVBQVU7UUFDUixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDdEIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLG1CQUFtQixDQUN2QixJQUFvQjtRQUVwQixNQUFNLFdBQVcsR0FBNEI7WUFDM0MsVUFBVSxFQUFFLFFBQVEsQ0FBQyxJQUFJLENBQUMs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