@flopay/shared 1.2.8 → 1.3.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.
package/dist/index.mjs CHANGED
@@ -79,7 +79,8 @@ var PAYMENT_METHOD_LOGOS = {
79
79
  };
80
80
 
81
81
  // src/constants.ts
82
- var SDK_VERSION = "1.2.8";
82
+ var SDK_VERSION = "1.3.1";
83
+ var FLO_SDK_VERSION_HEADER = "x-flo-sdk-version";
83
84
  var BILLING_API_URL_STAGING = "https://api.stage.flopay.com";
84
85
  var BILLING_API_URL_PRODUCTION = "https://api.flopay.com";
85
86
  var DEFAULT_API_BASE_URL = BILLING_API_URL_STAGING;
@@ -761,6 +762,9 @@ function stripeExpressMethodToOptionKey(method) {
761
762
  function buildPlaceholderMark(glyph, discColor, glyphColor) {
762
763
  return `<svg viewBox="0 0 22 22" xmlns="http://www.w3.org/2000/svg" role="img" aria-hidden="true"><circle cx="11" cy="11" r="11" fill="${discColor}"/><text x="11" y="15.5" text-anchor="middle" font-size="13" font-weight="700" font-family="-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif" fill="${glyphColor}">${glyph}</text></svg>`;
763
764
  }
765
+ function buildBankMark(discColor, glyphColor) {
766
+ return `<svg viewBox="0 0 22 22" xmlns="http://www.w3.org/2000/svg" role="img" aria-hidden="true"><circle cx="11" cy="11" r="11" fill="${discColor}"/><g fill="${glyphColor}"><path d="M11 4 L17.5 8 L4.5 8 Z"/><rect x="5" y="8.4" width="12" height="1.2" rx="0.3"/><rect x="5.9" y="10" width="1.5" height="5"/><rect x="8.55" y="10" width="1.5" height="5"/><rect x="11.95" y="10" width="1.5" height="5"/><rect x="14.6" y="10" width="1.5" height="5"/><rect x="4.6" y="15.4" width="12.8" height="1.5" rx="0.3"/></g></svg>`;
767
+ }
764
768
  var SEPA_COUNTRIES = [
765
769
  "AT",
766
770
  "BE",
@@ -801,6 +805,7 @@ var SEPA_COUNTRIES = [
801
805
  "VA"
802
806
  // non-EEA SEPA participants
803
807
  ];
808
+ var BANK_TRANSFER_COUNTRIES = [...SEPA_COUNTRIES, "JP", "MX", "US"];
804
809
  var STRIPE_METHOD_MATRIX = {
805
810
  // ─── Express wallets ────────────────────────────────────────────────────
806
811
  apple_pay: {
@@ -833,14 +838,42 @@ var STRIPE_METHOD_MATRIX = {
833
838
  express: true,
834
839
  needsExplicitConfirm: false
835
840
  },
841
+ // ─── Klarna: PaymentElement tile, explicit confirm ─────────────────────
842
+ // Klarna renders as a PaymentElement tile (NOT express) so it always appears
843
+ // when the backend includes it in `enabledPaymentMethods`. Stripe's
844
+ // ExpressCheckoutElement only paints a Klarna button in eligible *real*
845
+ // browsers (never headless), which made it effectively invisible and looked
846
+ // like an SDK-level disable — as a tile it's purely backend-driven. Klarna
847
+ // may redirect during confirm, but it still surfaces a deliberate "Pay with
848
+ // Klarna" step: it omits `needsExplicitConfirm: false`, so the default
849
+ // `needsStripeMethodExplicitConfirm(...) === true` applies — unlike the
850
+ // auto-confirm APMs below.
836
851
  klarna: {
837
852
  displayName: "Klarna",
838
853
  currencies: ["usd", "eur", "gbp", "aud", "nzd", "cad", "chf", "sek", "nok", "dkk", "pln", "czk", "ron"],
839
854
  amounts: { usd: { min: 100 }, eur: { min: 100 }, gbp: { min: 100 } },
840
- express: true,
841
- needsExplicitConfirm: false
855
+ // Default (explicit "Pay with Klarna" button) — Klarna's PaymentElement can
856
+ // collect inline data and isn't a pure redirect-only method, so surface a
857
+ // deliberate confirm rather than auto-submitting on tile click.
858
+ theme: {
859
+ light: {
860
+ backgroundColor: "#FFB3C7",
861
+ textColor: "#0A0B09",
862
+ borderColor: "#FFB3C7",
863
+ logoSvg: buildPlaceholderMark("K", "#0A0B09", "#FFB3C7")
864
+ },
865
+ dark: {
866
+ backgroundColor: "#FFB3C7",
867
+ textColor: "#0A0B09",
868
+ borderColor: "#FFB3C7",
869
+ logoSvg: buildPlaceholderMark("K", "#0A0B09", "#FFB3C7")
870
+ }
871
+ }
842
872
  },
843
873
  // ─── PaymentElement APMs: auto-confirm (redirect-only, no Pay button) ───
874
+ // Affirm and Cash App Pay are pure redirect/handoff methods with no inline
875
+ // inputs, so they auto-submit on tile click (`needsExplicitConfirm: false`).
876
+ //
844
877
  // Affirm currently rejects on non-USD currencies via
845
878
  // /v1/elements/sessions, hence the narrow currency list. Below $35.00 USD
846
879
  // it returns `amount_too_small` and blanks out the whole accordion, hence
@@ -905,11 +938,28 @@ var STRIPE_METHOD_MATRIX = {
905
938
  gbp: { min: 100, max: 12e4 },
906
939
  aud: { min: 100, max: 2e5 },
907
940
  nzd: { min: 100, max: 2e5 }
941
+ },
942
+ // Afterpay's brand mint (#B2FCE4) with black wordmark/icon — the signature
943
+ // palette from afterpay.com's brand system.
944
+ theme: {
945
+ light: {
946
+ backgroundColor: "#B2FCE4",
947
+ textColor: "#0A0B09",
948
+ borderColor: "#B2FCE4",
949
+ logoSvg: buildPlaceholderMark("A", "#0A0B09", "#B2FCE4")
950
+ },
951
+ dark: {
952
+ backgroundColor: "#B2FCE4",
953
+ textColor: "#0A0B09",
954
+ borderColor: "#B2FCE4",
955
+ logoSvg: buildPlaceholderMark("A", "#0A0B09", "#B2FCE4")
956
+ }
908
957
  }
909
958
  },
910
959
  alipay: {
911
960
  displayName: "Alipay",
912
- currencies: ["cny", "aud", "cad", "eur", "gbp", "hkd", "jpy", "myr", "nzd", "sgd", "usd"],
961
+ // Presentment currencies only Alipay is offered to USD / CNY carts.
962
+ currencies: ["usd", "cny"],
913
963
  theme: {
914
964
  light: {
915
965
  backgroundColor: "#1677FF",
@@ -946,6 +996,25 @@ var STRIPE_METHOD_MATRIX = {
946
996
  }
947
997
  }
948
998
  },
999
+ bizum: {
1000
+ displayName: "Bizum",
1001
+ currencies: ["eur"],
1002
+ countries: ["ES"],
1003
+ theme: {
1004
+ light: {
1005
+ backgroundColor: "#00BFB3",
1006
+ textColor: "#FFFFFF",
1007
+ borderColor: "#00BFB3",
1008
+ logoSvg: buildPlaceholderMark("B", "#FFFFFF", "#00BFB3")
1009
+ },
1010
+ dark: {
1011
+ backgroundColor: "#00BFB3",
1012
+ textColor: "#FFFFFF",
1013
+ borderColor: "#00BFB3",
1014
+ logoSvg: buildPlaceholderMark("B", "#FFFFFF", "#00BFB3")
1015
+ }
1016
+ }
1017
+ },
949
1018
  blik: {
950
1019
  displayName: "BLIK",
951
1020
  currencies: ["pln"],
@@ -966,7 +1035,25 @@ var STRIPE_METHOD_MATRIX = {
966
1035
  }
967
1036
  },
968
1037
  boleto: { displayName: "Boleto", currencies: ["brl"], countries: ["BR"] },
969
- customer_balance: { displayName: "Customer Balance", currencies: ["*"] },
1038
+ customer_balance: {
1039
+ displayName: "Bank Transfer",
1040
+ currencies: ["eur", "usd"],
1041
+ countries: BANK_TRANSFER_COUNTRIES,
1042
+ theme: {
1043
+ light: {
1044
+ backgroundColor: "#1F2937",
1045
+ textColor: "#FFFFFF",
1046
+ borderColor: "#1F2937",
1047
+ logoSvg: buildBankMark("#1F2937", "#FFFFFF")
1048
+ },
1049
+ dark: {
1050
+ backgroundColor: "#374151",
1051
+ textColor: "#FFFFFF",
1052
+ borderColor: "#374151",
1053
+ logoSvg: buildBankMark("#374151", "#FFFFFF")
1054
+ }
1055
+ }
1056
+ },
970
1057
  eps: {
971
1058
  displayName: "EPS",
972
1059
  currencies: ["eur"],
@@ -1025,6 +1112,25 @@ var STRIPE_METHOD_MATRIX = {
1025
1112
  }
1026
1113
  },
1027
1114
  konbini: { displayName: "Konbini", currencies: ["jpy"], countries: ["JP"] },
1115
+ kr_card: {
1116
+ displayName: "Korean Card",
1117
+ currencies: ["krw"],
1118
+ countries: ["KR"],
1119
+ theme: {
1120
+ light: {
1121
+ backgroundColor: "#0B3D91",
1122
+ textColor: "#FFFFFF",
1123
+ borderColor: "#0B3D91",
1124
+ logoSvg: buildPlaceholderMark("K", "#FFFFFF", "#0B3D91")
1125
+ },
1126
+ dark: {
1127
+ backgroundColor: "#0B3D91",
1128
+ textColor: "#FFFFFF",
1129
+ borderColor: "#0B3D91",
1130
+ logoSvg: buildPlaceholderMark("K", "#FFFFFF", "#0B3D91")
1131
+ }
1132
+ }
1133
+ },
1028
1134
  multibanco: { displayName: "Multibanco", currencies: ["eur"], countries: ["PT"] },
1029
1135
  oxxo: { displayName: "OXXO", currencies: ["mxn"], countries: ["MX"] },
1030
1136
  p24: {
@@ -1090,10 +1196,30 @@ var STRIPE_METHOD_MATRIX = {
1090
1196
  }
1091
1197
  }
1092
1198
  },
1199
+ upi: {
1200
+ displayName: "UPI",
1201
+ currencies: ["inr"],
1202
+ countries: ["IN"],
1203
+ theme: {
1204
+ light: {
1205
+ backgroundColor: "#FF7909",
1206
+ textColor: "#FFFFFF",
1207
+ borderColor: "#FF7909",
1208
+ logoSvg: buildPlaceholderMark("U", "#FFFFFF", "#FF7909")
1209
+ },
1210
+ dark: {
1211
+ backgroundColor: "#FF7909",
1212
+ textColor: "#FFFFFF",
1213
+ borderColor: "#FF7909",
1214
+ logoSvg: buildPlaceholderMark("U", "#FFFFFF", "#FF7909")
1215
+ }
1216
+ }
1217
+ },
1093
1218
  us_bank_account: { displayName: "US Bank Account", currencies: ["usd"], countries: ["US"] },
1094
1219
  wechat_pay: {
1095
1220
  displayName: "WeChat Pay",
1096
- currencies: ["cny", "usd", "eur", "gbp", "aud", "cad", "jpy", "chf", "hkd", "sgd", "nzd", "nok", "sek", "dkk"],
1221
+ // Presentment currencies only WeChat Pay is offered to USD / CNY carts.
1222
+ currencies: ["usd", "cny"],
1097
1223
  theme: {
1098
1224
  light: {
1099
1225
  backgroundColor: "#07C160",
@@ -1730,6 +1856,67 @@ function getStateFromPostalCode(country, postalCode) {
1730
1856
  }
1731
1857
  }
1732
1858
 
1859
+ // src/postal-code-validation.ts
1860
+ import * as isPostalCodeModule from "validator/lib/isPostalCode.js";
1861
+ var mod = isPostalCodeModule;
1862
+ var isPostalCode = typeof mod.default === "function" ? mod.default : mod.default?.default;
1863
+ if (typeof isPostalCode !== "function") {
1864
+ throw new Error(
1865
+ "validator/lib/isPostalCode.js interop failed: unexpected module shape. This likely means the bundler's CJS/ESM interop changed."
1866
+ );
1867
+ }
1868
+ var SUPPORTED_LOCALES = new Set(
1869
+ mod.locales.map((code) => code.toUpperCase())
1870
+ );
1871
+ var LOCALE_ALIASES = {
1872
+ UK: "GB"
1873
+ };
1874
+ function normalizeCountry(country) {
1875
+ const upper = country.trim().toUpperCase();
1876
+ return LOCALE_ALIASES[upper] ?? upper;
1877
+ }
1878
+ var POSTAL_CODE_EXAMPLES = {
1879
+ US: "12345 or 12345-6789",
1880
+ GB: "SW1A 1AA",
1881
+ CA: "A1A 1A1",
1882
+ AU: "2000",
1883
+ NZ: "6011",
1884
+ IE: "D02 AF30",
1885
+ DE: "10115",
1886
+ FR: "75008",
1887
+ NL: "1011 AB",
1888
+ ES: "28001",
1889
+ IT: "00100",
1890
+ IN: "110001",
1891
+ JP: "100-0001",
1892
+ BR: "01310-100",
1893
+ MX: "01000",
1894
+ SE: "114 55",
1895
+ CH: "8001",
1896
+ PL: "00-001",
1897
+ PT: "1000-001",
1898
+ SG: "570150",
1899
+ ZA: "0001",
1900
+ NO: "0001",
1901
+ DK: "1050",
1902
+ FI: "00100",
1903
+ AT: "1010",
1904
+ BE: "1000",
1905
+ CZ: "100 00"
1906
+ };
1907
+ function isPostalCodeSupported(country) {
1908
+ if (!country) return false;
1909
+ return SUPPORTED_LOCALES.has(normalizeCountry(country));
1910
+ }
1911
+ function isValidPostalCode(country, postalCode) {
1912
+ if (!isPostalCodeSupported(country)) return true;
1913
+ return isPostalCode(postalCode.trim(), normalizeCountry(country));
1914
+ }
1915
+ function getPostalCodeExample(country) {
1916
+ if (!country) return void 0;
1917
+ return POSTAL_CODE_EXAMPLES[normalizeCountry(country)];
1918
+ }
1919
+
1733
1920
  // src/checkout-payload.ts
1734
1921
  function nonBlank(value) {
1735
1922
  if (typeof value !== "string") return void 0;
@@ -1955,6 +2142,7 @@ export {
1955
2142
  DEFAULT_CURRENCY,
1956
2143
  ELEMENT_TYPES,
1957
2144
  FLAT_APPEARANCE,
2145
+ FLO_SDK_VERSION_HEADER,
1958
2146
  FloPayError,
1959
2147
  GLASS_DARK_APPEARANCE,
1960
2148
  GLASS_LIGHT_APPEARANCE,
@@ -1985,6 +2173,7 @@ export {
1985
2173
  getCountryByCode,
1986
2174
  getCurrencyByCountry,
1987
2175
  getFloPayEnvironment,
2176
+ getPostalCodeExample,
1988
2177
  getPostalCodeLabel,
1989
2178
  getStateFromPostalCode,
1990
2179
  getStateLabel,
@@ -1993,7 +2182,9 @@ export {
1993
2182
  hasVendoredStripeMethodLogo,
1994
2183
  isAVSEnabled,
1995
2184
  isAVSFieldVisible,
2185
+ isPostalCodeSupported,
1996
2186
  isSetupIntentClientSecret,
2187
+ isValidPostalCode,
1997
2188
  isValidPublishableKey,
1998
2189
  isValidSecretKey,
1999
2190
  needsStripeMethodExplicitConfirm,