@p2pdotme/sdk 1.2.19 → 1.2.21

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.
@@ -148,6 +148,39 @@ function validateVenezuelanQr(payload) {
148
148
  if (!/^[A-Za-z0-9+/=]+$/.test(blob)) return false;
149
149
  return /(?:^|[?&])merchantId=\d{3,4}(?:&|$)/.test(trimmed.substring(qIdx));
150
150
  }
151
+ function payQrCandidate(paymentId) {
152
+ const trimmed = paymentId.trim();
153
+ const sep = trimmed.indexOf(PACKED_PAYMENT_ID_SEP);
154
+ return (sep >= 0 ? trimmed.slice(0, sep) : trimmed).trim();
155
+ }
156
+ function isPeruvianPayQr(payload) {
157
+ if (!payload.startsWith("0002")) return false;
158
+ return payload.includes("5802PE") && payload.includes("5303604");
159
+ }
160
+ function isVenezuelanPayQr(payload) {
161
+ if (!payload || payload.includes(PACKED_PAYMENT_ID_SEP)) return false;
162
+ const qIdx = payload.indexOf("?");
163
+ if (qIdx === -1) return false;
164
+ const blob = payload.slice(0, qIdx);
165
+ return blob.length > 0 && /^[A-Za-z0-9+/=]+$/.test(blob);
166
+ }
167
+ function isPhilippinePayQr(payload) {
168
+ if (!payload.startsWith("0002")) return false;
169
+ return payload.includes("5802PH") && payload.includes("5303608");
170
+ }
171
+ function isBolivianPayQr(payload) {
172
+ if (!payload || payload.includes(PACKED_PAYMENT_ID_SEP)) return false;
173
+ if (payload.startsWith("0002") && payload.includes("5802BO") && payload.includes("5303068")) {
174
+ return true;
175
+ }
176
+ const sep = payload.lastIndexOf("|");
177
+ if (sep < 40) return false;
178
+ const blob = payload.slice(0, sep);
179
+ const tag = payload.slice(sep + 1);
180
+ if (blob.length % 4 !== 0) return false;
181
+ if (!/^[A-Za-z0-9+/]+={0,2}$/.test(blob)) return false;
182
+ return /^[0-9A-Fa-f]{16,64}$/.test(tag);
183
+ }
151
184
 
152
185
  // src/country/currencies/bob.ts
153
186
  var BOB_COUNTRY_OPTION = {
@@ -163,7 +196,7 @@ var BOB_COUNTRY_OPTION = {
163
196
  flag: "\u{1F1E7}\u{1F1F4}",
164
197
  flagUrl: "https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/72x72/1f1e7-1f1f4.png",
165
198
  phoneCode: "+591",
166
- telegramSupportChannel: "https://t.me/p2pmebolivia",
199
+ telegramSupportChannel: "https://t.me/p2pme_bolivia_merchants",
167
200
  twitterUsername: "p2pmebolivia",
168
201
  smsCountryCodes: ["BO"],
169
202
  precision: 2,
@@ -171,7 +204,11 @@ var BOB_COUNTRY_OPTION = {
171
204
  disabled: false,
172
205
  disabledPaymentTypes: [],
173
206
  uploadPaymentQR: true,
174
- validateQr: validateBolivianQr
207
+ validateQr: validateBolivianQr,
208
+ getPayQrPayload: (paymentId) => {
209
+ const candidate = payQrCandidate(paymentId);
210
+ return isBolivianPayQr(candidate) ? candidate : null;
211
+ }
175
212
  };
176
213
 
177
214
  // src/country/currencies/brl.ts
@@ -237,7 +274,8 @@ var CUP_COUNTRY_OPTION = {
237
274
  precision: 2,
238
275
  isAlpha: true,
239
276
  disabled: false,
240
- disabledPaymentTypes: []
277
+ disabledPaymentTypes: [],
278
+ transferWarning: "CUP_BANDEC_WARNING"
241
279
  };
242
280
 
243
281
  // src/country/currencies/ecu.ts
@@ -445,6 +483,10 @@ var PEN_COUNTRY_OPTION = {
445
483
  disabledPaymentTypes: [],
446
484
  uploadPaymentQR: true,
447
485
  validateQr: validatePeruvianQr,
486
+ getPayQrPayload: (paymentId) => {
487
+ const candidate = payQrCandidate(paymentId);
488
+ return isPeruvianPayQr(candidate) ? candidate : null;
489
+ },
448
490
  hydrateFieldsFromQr: (qr) => {
449
491
  const phone = extractPeruvianPhoneFromQr(qr);
450
492
  return phone ? { phone } : {};
@@ -470,7 +512,11 @@ var PHP_COUNTRY_OPTION = {
470
512
  precision: 2,
471
513
  isAlpha: true,
472
514
  disabled: false,
473
- disabledPaymentTypes: []
515
+ disabledPaymentTypes: [],
516
+ getPayQrPayload: (paymentId) => {
517
+ const candidate = payQrCandidate(paymentId);
518
+ return isPhilippinePayQr(candidate) ? candidate : null;
519
+ }
474
520
  };
475
521
 
476
522
  // src/country/currencies/usd.ts
@@ -517,7 +563,11 @@ var VEN_COUNTRY_OPTION = {
517
563
  disabled: false,
518
564
  disabledPaymentTypes: [],
519
565
  uploadPaymentQR: true,
520
- validateQr: validateVenezuelanQr
566
+ validateQr: validateVenezuelanQr,
567
+ getPayQrPayload: (paymentId) => {
568
+ const candidate = payQrCandidate(paymentId);
569
+ return isVenezuelanPayQr(candidate) ? candidate : null;
570
+ }
521
571
  };
522
572
 
523
573
  // src/country/countries.ts
@@ -538,6 +588,10 @@ var COUNTRY_OPTIONS = [
538
588
  EUR_COUNTRY_OPTION,
539
589
  USD_COUNTRY_OPTION
540
590
  ];
591
+ function getCountryOption(currency) {
592
+ if (!currency) return void 0;
593
+ return COUNTRY_OPTIONS.find((c) => c.currency === currency);
594
+ }
541
595
 
542
596
  // src/qr-parsers/types.ts
543
597
  var import_neverthrow = require("neverthrow");
@@ -1063,16 +1117,16 @@ function parseNGN(qrData, sellPrice) {
1063
1117
  }
1064
1118
 
1065
1119
  // src/qr-parsers/parsers/pen.ts
1066
- var PEN_TAGS = { AMOUNT: "54", CURRENCY: "53", COUNTRY: "58" };
1120
+ var PEN_TAGS = { AMOUNT: "54" };
1067
1121
  function parsePeru(qrData, sellPrice) {
1068
1122
  if (!qrData || typeof qrData !== "string" || qrData.trim().length === 0) {
1069
1123
  return failure("INVALID_QR", "QR data is empty or invalid");
1070
1124
  }
1071
1125
  const trimmed = qrData.trim();
1072
- const tags = extractTags(trimmed, [PEN_TAGS.AMOUNT, PEN_TAGS.CURRENCY, PEN_TAGS.COUNTRY]);
1073
- if (tags[PEN_TAGS.COUNTRY] !== "PE" || tags[PEN_TAGS.CURRENCY] !== "604") {
1126
+ if (!validatePeruvianQr(trimmed)) {
1074
1127
  return failure("INVALID_QR", "Not a valid Peru Yape/Plin QR");
1075
1128
  }
1129
+ const tags = extractTags(trimmed, [PEN_TAGS.AMOUNT]);
1076
1130
  const result = { paymentAddress: trimmed };
1077
1131
  const amountStr = tags[PEN_TAGS.AMOUNT];
1078
1132
  if (amountStr) {
@@ -1114,21 +1168,14 @@ function parseQRPh(qrData, sellPrice) {
1114
1168
 
1115
1169
  // src/qr-parsers/parsers/ven.ts
1116
1170
  function isPagoMovilQr(qrData) {
1117
- if (!qrData || typeof qrData !== "string" || qrData.trim().length === 0) {
1118
- return false;
1119
- }
1120
- const trimmed = qrData.trim();
1121
- const qIdx = trimmed.indexOf("?");
1122
- if (qIdx === -1) return false;
1123
- const payload = trimmed.substring(0, qIdx);
1124
- return !!payload && /^[A-Za-z0-9+/=]+$/.test(payload);
1171
+ return validateVenezuelanQr(qrData);
1125
1172
  }
1126
1173
  function parsePagoMovil(qrData, _sellPrice) {
1127
1174
  if (!qrData || typeof qrData !== "string" || qrData.trim().length === 0) {
1128
1175
  return failure("INVALID_QR", "QR data is empty or invalid");
1129
1176
  }
1130
1177
  const trimmed = qrData.trim();
1131
- if (!isPagoMovilQr(trimmed)) {
1178
+ if (!validateVenezuelanQr(trimmed)) {
1132
1179
  return failure("INVALID_QR", "Not a valid Venezuelan QR code");
1133
1180
  }
1134
1181
  return success({ paymentAddress: trimmed });
@@ -1140,34 +1187,52 @@ async function parseQR(params) {
1140
1187
  if (!qrData || typeof qrData !== "string" || qrData.trim().length === 0) {
1141
1188
  return failure("INVALID_QR", "QR data is empty or invalid");
1142
1189
  }
1190
+ let result;
1143
1191
  switch (currency) {
1144
1192
  case CURRENCY.INR:
1145
- return parseUPI(qrData, sellPrice);
1193
+ result = parseUPI(qrData, sellPrice);
1194
+ break;
1146
1195
  case CURRENCY.IDR:
1147
- return parseQRIS(qrData, sellPrice);
1196
+ result = parseQRIS(qrData, sellPrice);
1197
+ break;
1148
1198
  case CURRENCY.BRL:
1149
- return parsePIX(qrData, sellPrice, { proxyUrl, orderId });
1199
+ result = await parsePIX(qrData, sellPrice, { proxyUrl, orderId });
1200
+ break;
1150
1201
  case CURRENCY.ARS:
1151
- return parseMercadoPago(qrData, sellPrice);
1202
+ result = parseMercadoPago(qrData, sellPrice);
1203
+ break;
1152
1204
  case CURRENCY.VEN:
1153
- return parsePagoMovil(qrData, sellPrice);
1205
+ result = parsePagoMovil(qrData, sellPrice);
1206
+ break;
1154
1207
  case CURRENCY.BOB:
1155
- return parseBolivia(qrData, sellPrice);
1208
+ result = parseBolivia(qrData, sellPrice);
1209
+ break;
1156
1210
  case CURRENCY.NGN:
1157
- return parseNGN(qrData, sellPrice);
1211
+ result = parseNGN(qrData, sellPrice);
1212
+ break;
1158
1213
  case CURRENCY.COP:
1159
- return parseCOP(qrData, sellPrice);
1214
+ result = parseCOP(qrData, sellPrice);
1215
+ break;
1160
1216
  case CURRENCY.CUP:
1161
- return parseTransfermovil(qrData, sellPrice);
1217
+ result = parseTransfermovil(qrData, sellPrice);
1218
+ break;
1162
1219
  case CURRENCY.ECU:
1163
- return parseDeUna(qrData, sellPrice);
1220
+ result = parseDeUna(qrData, sellPrice);
1221
+ break;
1164
1222
  case CURRENCY.PEN:
1165
- return parsePeru(qrData, sellPrice);
1223
+ result = parsePeru(qrData, sellPrice);
1224
+ break;
1166
1225
  case CURRENCY.PHP:
1167
- return parseQRPh(qrData, sellPrice);
1226
+ result = parseQRPh(qrData, sellPrice);
1227
+ break;
1168
1228
  default:
1169
1229
  return failure("INVALID_CURRENCY", `Currency "${currency}" is not supported`);
1170
1230
  }
1231
+ const validateQr = getCountryOption(currency)?.validateQr;
1232
+ if (result.isOk() && validateQr && !validateQr(qrData.trim())) {
1233
+ return failure("INVALID_QR", "QR does not match catalog validateQr");
1234
+ }
1235
+ return result;
1171
1236
  }
1172
1237
  // Annotate the CommonJS export names for ESM import in node:
1173
1238
  0 && (module.exports = {