@pandait.tech/payment-nuvei 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -922,7 +922,43 @@ function createWebhookHandler(deps) {
922
922
  }
923
923
 
924
924
  // src/handlers/3ds-callback.ts
925
+ function pickCres(src) {
926
+ for (const key of Object.keys(src)) {
927
+ const k = key.toLowerCase();
928
+ if (k === "cres" || k === "cres_value" || k === "cresvalue" || k === "value" || k === "param.value" || k === "paramvalue") {
929
+ const v = src[key];
930
+ if (typeof v === "string" && v.length > 0) return v;
931
+ }
932
+ }
933
+ return src.cres || src.CRes || src.CRES || src.value || "";
934
+ }
935
+ function transStatusFromCres(cres, logger) {
936
+ try {
937
+ const base64 = cres.replace(/-/g, "+").replace(/_/g, "/");
938
+ const pad = base64.length % 4;
939
+ const padded = pad ? base64 + "=".repeat(4 - pad) : base64;
940
+ const decoded = JSON.parse(
941
+ Buffer.from(padded, "base64").toString("utf-8")
942
+ );
943
+ if (decoded && typeof decoded.transStatus === "string") {
944
+ return decoded.transStatus;
945
+ }
946
+ } catch (e) {
947
+ logger.warn(
948
+ "[3ds-callback] Could not decode CRES payload:",
949
+ e instanceof Error ? e.message : e
950
+ );
951
+ }
952
+ return null;
953
+ }
954
+ function paramsToObject(params) {
955
+ const obj = {};
956
+ for (const [k, v] of params.entries()) obj[k] = v;
957
+ return obj;
958
+ }
925
959
  function buildCompletionPage(orderId, transStatus) {
960
+ const safeOrderId = String(orderId).replace(/[^a-zA-Z0-9_-]/g, "");
961
+ const safeTransStatus = String(transStatus).replace(/[^a-zA-Z0-9]/g, "");
926
962
  const html = `<!DOCTYPE html>
927
963
  <html><head><meta charset="utf-8"><title>3DS Verification</title></head>
928
964
  <body>
@@ -930,8 +966,8 @@ function buildCompletionPage(orderId, transStatus) {
930
966
  (function() {
931
967
  var message = {
932
968
  type: "3DS_COMPLETE",
933
- orderId: "${orderId}",
934
- transStatus: "${transStatus}"
969
+ orderId: "${safeOrderId}",
970
+ transStatus: "${safeTransStatus}"
935
971
  };
936
972
  try {
937
973
  if (window.parent && window.parent !== window) {
@@ -954,46 +990,68 @@ Verificando autenticaci&oacute;n...
954
990
  function create3dsCallbackHandler(deps) {
955
991
  const logger = deps.logger ?? console;
956
992
  const { db } = deps.firebase;
957
- async function storeCres(orderId, cres) {
958
- if (orderId && cres) {
959
- try {
960
- await db.collection("orders").doc(orderId).update({
961
- threeDSCres: cres,
962
- updatedAt: /* @__PURE__ */ new Date()
963
- });
964
- } catch (err) {
965
- logger.error("Failed to store cres on order:", err);
993
+ async function persist(orderId, cres, transStatus) {
994
+ if (!orderId) return;
995
+ try {
996
+ const ref = db.collection("orders").doc(orderId);
997
+ const snap = await ref.get();
998
+ const status = snap.data()?.status;
999
+ if (!snap.exists || status !== "3ds-pending") {
1000
+ logger.warn(
1001
+ "[3ds-callback] rejected: order not in 3ds-pending state",
1002
+ { orderId, status }
1003
+ );
1004
+ return;
966
1005
  }
1006
+ const update = { updatedAt: /* @__PURE__ */ new Date() };
1007
+ if (cres) update.threeDSCres = cres;
1008
+ if (transStatus) update.threeDSTransStatus = transStatus;
1009
+ await ref.update(update);
1010
+ } catch (err) {
1011
+ logger.error("[3ds-callback] failed to store cres on order:", err);
967
1012
  }
968
1013
  }
1014
+ function resolveTransStatus(cres, fallback) {
1015
+ if (cres) {
1016
+ const fromCres = transStatusFromCres(cres, logger);
1017
+ if (fromCres) return fromCres;
1018
+ }
1019
+ return fallback;
1020
+ }
969
1021
  const POST = async function POST2(request) {
970
- const { searchParams } = new URL(request.url);
971
- const orderId = searchParams.get("orderId") || "";
1022
+ const orderId = new URL(request.url).searchParams.get("orderId") || "";
972
1023
  let transStatus = "U";
973
1024
  let cres = "";
974
1025
  try {
975
1026
  const contentType = request.headers.get("content-type") || "";
1027
+ const raw = await request.text();
976
1028
  if (contentType.includes("application/x-www-form-urlencoded")) {
977
- const text = await request.text();
978
- const params = new URLSearchParams(text);
979
- transStatus = params.get("transStatus") || "U";
980
- cres = params.get("cres") || params.get("CRes") || "";
1029
+ const obj = paramsToObject(new URLSearchParams(raw));
1030
+ transStatus = obj.transStatus || obj.TransStatus || "U";
1031
+ cres = pickCres(obj);
981
1032
  } else {
982
- const body = await request.json();
983
- transStatus = body.transStatus || "U";
984
- cres = body.cres || body.CRes || "";
1033
+ try {
1034
+ const body = JSON.parse(raw);
1035
+ transStatus = body.transStatus || body.TransStatus || "U";
1036
+ cres = pickCres(body);
1037
+ } catch {
1038
+ }
1039
+ }
1040
+ if (!cres && raw) {
1041
+ cres = pickCres(paramsToObject(new URLSearchParams(raw)));
985
1042
  }
986
1043
  } catch {
987
1044
  }
988
- await storeCres(orderId, cres);
1045
+ transStatus = resolveTransStatus(cres, transStatus);
1046
+ await persist(orderId, cres, transStatus);
989
1047
  return buildCompletionPage(orderId, transStatus);
990
1048
  };
991
1049
  const GET = async function GET2(request) {
992
- const { searchParams } = new URL(request.url);
993
- const orderId = searchParams.get("orderId") || "";
994
- const transStatus = searchParams.get("transStatus") || "Y";
995
- const cres = searchParams.get("cres") || searchParams.get("CRes") || "";
996
- await storeCres(orderId, cres);
1050
+ const params = new URL(request.url).searchParams;
1051
+ const orderId = params.get("orderId") || "";
1052
+ const cres = params.get("cres") || params.get("CRes") || params.get("value") || "";
1053
+ const transStatus = resolveTransStatus(cres, params.get("transStatus") || "Y");
1054
+ await persist(orderId, cres, transStatus);
997
1055
  return buildCompletionPage(orderId, transStatus);
998
1056
  };
999
1057
  return { POST, GET };