@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.
- package/dist/country.cjs +108 -57
- package/dist/country.cjs.map +1 -1
- package/dist/country.d.cts +40 -8
- package/dist/country.d.ts +40 -8
- package/dist/country.mjs +105 -57
- package/dist/country.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/qr-parsers.cjs +94 -29
- package/dist/qr-parsers.cjs.map +1 -1
- package/dist/qr-parsers.d.cts +6 -3
- package/dist/qr-parsers.d.ts +6 -3
- package/dist/qr-parsers.mjs +94 -29
- package/dist/qr-parsers.mjs.map +1 -1
- package/package.json +1 -1
package/dist/qr-parsers.cjs
CHANGED
|
@@ -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/
|
|
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"
|
|
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
|
-
|
|
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
|
-
|
|
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 (!
|
|
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
|
-
|
|
1193
|
+
result = parseUPI(qrData, sellPrice);
|
|
1194
|
+
break;
|
|
1146
1195
|
case CURRENCY.IDR:
|
|
1147
|
-
|
|
1196
|
+
result = parseQRIS(qrData, sellPrice);
|
|
1197
|
+
break;
|
|
1148
1198
|
case CURRENCY.BRL:
|
|
1149
|
-
|
|
1199
|
+
result = await parsePIX(qrData, sellPrice, { proxyUrl, orderId });
|
|
1200
|
+
break;
|
|
1150
1201
|
case CURRENCY.ARS:
|
|
1151
|
-
|
|
1202
|
+
result = parseMercadoPago(qrData, sellPrice);
|
|
1203
|
+
break;
|
|
1152
1204
|
case CURRENCY.VEN:
|
|
1153
|
-
|
|
1205
|
+
result = parsePagoMovil(qrData, sellPrice);
|
|
1206
|
+
break;
|
|
1154
1207
|
case CURRENCY.BOB:
|
|
1155
|
-
|
|
1208
|
+
result = parseBolivia(qrData, sellPrice);
|
|
1209
|
+
break;
|
|
1156
1210
|
case CURRENCY.NGN:
|
|
1157
|
-
|
|
1211
|
+
result = parseNGN(qrData, sellPrice);
|
|
1212
|
+
break;
|
|
1158
1213
|
case CURRENCY.COP:
|
|
1159
|
-
|
|
1214
|
+
result = parseCOP(qrData, sellPrice);
|
|
1215
|
+
break;
|
|
1160
1216
|
case CURRENCY.CUP:
|
|
1161
|
-
|
|
1217
|
+
result = parseTransfermovil(qrData, sellPrice);
|
|
1218
|
+
break;
|
|
1162
1219
|
case CURRENCY.ECU:
|
|
1163
|
-
|
|
1220
|
+
result = parseDeUna(qrData, sellPrice);
|
|
1221
|
+
break;
|
|
1164
1222
|
case CURRENCY.PEN:
|
|
1165
|
-
|
|
1223
|
+
result = parsePeru(qrData, sellPrice);
|
|
1224
|
+
break;
|
|
1166
1225
|
case CURRENCY.PHP:
|
|
1167
|
-
|
|
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 = {
|