@whop/elements-react-native 0.1.0

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.
Files changed (339) hide show
  1. package/README.md +179 -0
  2. package/android/build.gradle +64 -0
  3. package/android/consumer-rules.pro +3 -0
  4. package/android/gradle.properties +5 -0
  5. package/android/src/main/java/com/whop/elements/WhopAddressSuggestionsModule.kt +102 -0
  6. package/android/src/main/java/com/whop/elements/WhopAuthSessionModule.kt +126 -0
  7. package/android/src/main/java/com/whop/elements/WhopElementsPackage.kt +39 -0
  8. package/android/src/main/java/com/whop/elements/WhopPayButtonManager.kt +74 -0
  9. package/android/src/main/java/com/whop/elements/WhopPayButtonPressEvent.kt +17 -0
  10. package/android/src/main/java/com/whop/elements/WhopPayButtonView.kt +178 -0
  11. package/android/src/main/java/com/whop/elements/WhopPlatformPayModule.kt +212 -0
  12. package/assets/whop-wordmark-dark.png +0 -0
  13. package/assets/whop-wordmark-dark@2x.png +0 -0
  14. package/assets/whop-wordmark-dark@3x.png +0 -0
  15. package/assets/whop-wordmark-light.png +0 -0
  16. package/assets/whop-wordmark-light@2x.png +0 -0
  17. package/assets/whop-wordmark-light@3x.png +0 -0
  18. package/ios/Package.swift +59 -0
  19. package/ios/Sources/ElementsReactNative/WhopAddressSuggestionsImpl.swift +189 -0
  20. package/ios/Sources/ElementsReactNative/WhopAuthSessionImpl.swift +106 -0
  21. package/ios/Sources/ElementsReactNative/WhopPayButtonImpl.swift +89 -0
  22. package/ios/Sources/ElementsReactNative/WhopPlatformPayImpl.swift +181 -0
  23. package/ios/generated/WhopAddressSuggestionsModule.h +11 -0
  24. package/ios/generated/WhopAddressSuggestionsModule.mm +46 -0
  25. package/ios/generated/WhopAuthSessionModule.h +11 -0
  26. package/ios/generated/WhopAuthSessionModule.mm +45 -0
  27. package/ios/generated/WhopElementsShims.h +35 -0
  28. package/ios/generated/WhopPayButtonComponentView.h +12 -0
  29. package/ios/generated/WhopPayButtonComponentView.mm +82 -0
  30. package/ios/generated/WhopPlatformPayModule.h +11 -0
  31. package/ios/generated/WhopPlatformPayModule.mm +51 -0
  32. package/lib/module/api/client.js +139 -0
  33. package/lib/module/api/client.js.map +1 -0
  34. package/lib/module/api/client.test.js +137 -0
  35. package/lib/module/api/client.test.js.map +1 -0
  36. package/lib/module/api/types.js +2 -0
  37. package/lib/module/api/types.js.map +1 -0
  38. package/lib/module/controller/actions.js +148 -0
  39. package/lib/module/controller/actions.js.map +1 -0
  40. package/lib/module/controller/actions.test.js +102 -0
  41. package/lib/module/controller/actions.test.js.map +1 -0
  42. package/lib/module/controller/store.js +158 -0
  43. package/lib/module/controller/store.js.map +1 -0
  44. package/lib/module/core/address/country-data.js +1370 -0
  45. package/lib/module/core/address/country-data.js.map +1 -0
  46. package/lib/module/core/address/country-name.js +38 -0
  47. package/lib/module/core/address/country-name.js.map +1 -0
  48. package/lib/module/core/address/country-names.generated.js +249 -0
  49. package/lib/module/core/address/country-names.generated.js.map +1 -0
  50. package/lib/module/core/address/engine.js +245 -0
  51. package/lib/module/core/address/engine.js.map +1 -0
  52. package/lib/module/core/address/engine.test.js +216 -0
  53. package/lib/module/core/address/engine.test.js.map +1 -0
  54. package/lib/module/core/address/form-state.js +409 -0
  55. package/lib/module/core/address/form-state.js.map +1 -0
  56. package/lib/module/core/address/form-state.test.js +516 -0
  57. package/lib/module/core/address/form-state.test.js.map +1 -0
  58. package/lib/module/core/address/places.js +36 -0
  59. package/lib/module/core/address/places.js.map +1 -0
  60. package/lib/module/core/address/required-coverage.test.js +57 -0
  61. package/lib/module/core/address/required-coverage.test.js.map +1 -0
  62. package/lib/module/core/address/suggest.js +102 -0
  63. package/lib/module/core/address/suggest.js.map +1 -0
  64. package/lib/module/core/address/suggest.test.js +156 -0
  65. package/lib/module/core/address/suggest.test.js.map +1 -0
  66. package/lib/module/core/address/use-suggestions.js +33 -0
  67. package/lib/module/core/address/use-suggestions.js.map +1 -0
  68. package/lib/module/core/payments/address-change.js +91 -0
  69. package/lib/module/core/payments/address-change.js.map +1 -0
  70. package/lib/module/core/payments/billing-merge.js +62 -0
  71. package/lib/module/core/payments/billing-merge.js.map +1 -0
  72. package/lib/module/core/payments/browser-info.js +42 -0
  73. package/lib/module/core/payments/browser-info.js.map +1 -0
  74. package/lib/module/core/payments/bt.js +151 -0
  75. package/lib/module/core/payments/bt.js.map +1 -0
  76. package/lib/module/core/payments/bt.test.js +23 -0
  77. package/lib/module/core/payments/bt.test.js.map +1 -0
  78. package/lib/module/core/payments/currency.js +37 -0
  79. package/lib/module/core/payments/currency.js.map +1 -0
  80. package/lib/module/core/payments/detail.js +159 -0
  81. package/lib/module/core/payments/detail.js.map +1 -0
  82. package/lib/module/core/payments/detail.test.js +225 -0
  83. package/lib/module/core/payments/detail.test.js.map +1 -0
  84. package/lib/module/core/payments/errors.js +115 -0
  85. package/lib/module/core/payments/errors.js.map +1 -0
  86. package/lib/module/core/payments/mint.js +89 -0
  87. package/lib/module/core/payments/mint.js.map +1 -0
  88. package/lib/module/core/payments/plan.js +131 -0
  89. package/lib/module/core/payments/plan.js.map +1 -0
  90. package/lib/module/core/payments/refusals.js +17 -0
  91. package/lib/module/core/payments/refusals.js.map +1 -0
  92. package/lib/module/core/payments/secure-fields.js +87 -0
  93. package/lib/module/core/payments/secure-fields.js.map +1 -0
  94. package/lib/module/core/payments/tax-id-catalog.js +616 -0
  95. package/lib/module/core/payments/tax-id-catalog.js.map +1 -0
  96. package/lib/module/core/payments/wallet-contact.js +42 -0
  97. package/lib/module/core/payments/wallet-contact.js.map +1 -0
  98. package/lib/module/core/payments/wallet-contact.test.js +77 -0
  99. package/lib/module/core/payments/wallet-contact.test.js.map +1 -0
  100. package/lib/module/elements/address.js +467 -0
  101. package/lib/module/elements/address.js.map +1 -0
  102. package/lib/module/elements/branding.js +114 -0
  103. package/lib/module/elements/branding.js.map +1 -0
  104. package/lib/module/elements/card-fields/context.js +254 -0
  105. package/lib/module/elements/card-fields/context.js.map +1 -0
  106. package/lib/module/elements/card-fields/fields.js +309 -0
  107. package/lib/module/elements/card-fields/fields.js.map +1 -0
  108. package/lib/module/elements/card-fields/index.js +30 -0
  109. package/lib/module/elements/card-fields/index.js.map +1 -0
  110. package/lib/module/elements/card.js +107 -0
  111. package/lib/module/elements/card.js.map +1 -0
  112. package/lib/module/elements/email.js +84 -0
  113. package/lib/module/elements/email.js.map +1 -0
  114. package/lib/module/elements/payment/declared-fields.js +186 -0
  115. package/lib/module/elements/payment/declared-fields.js.map +1 -0
  116. package/lib/module/elements/payment/index.js +448 -0
  117. package/lib/module/elements/payment/index.js.map +1 -0
  118. package/lib/module/elements/payment/wallet.js +132 -0
  119. package/lib/module/elements/payment/wallet.js.map +1 -0
  120. package/lib/module/elements/tax-id.js +100 -0
  121. package/lib/module/elements/tax-id.js.map +1 -0
  122. package/lib/module/i18n/catalogs.js +103 -0
  123. package/lib/module/i18n/catalogs.js.map +1 -0
  124. package/lib/module/i18n/index.js +45 -0
  125. package/lib/module/i18n/index.js.map +1 -0
  126. package/lib/module/index.js +27 -0
  127. package/lib/module/index.js.map +1 -0
  128. package/lib/module/namespace.js +174 -0
  129. package/lib/module/namespace.js.map +1 -0
  130. package/lib/module/native/index.js +128 -0
  131. package/lib/module/native/index.js.map +1 -0
  132. package/lib/module/package.json +1 -0
  133. package/lib/module/provider.js +56 -0
  134. package/lib/module/provider.js.map +1 -0
  135. package/lib/module/specs/NativeWhopAddressSuggestions.js +6 -0
  136. package/lib/module/specs/NativeWhopAddressSuggestions.js.map +1 -0
  137. package/lib/module/specs/NativeWhopAuthSession.js +10 -0
  138. package/lib/module/specs/NativeWhopAuthSession.js.map +1 -0
  139. package/lib/module/specs/NativeWhopPlatformPay.js +10 -0
  140. package/lib/module/specs/NativeWhopPlatformPay.js.map +1 -0
  141. package/lib/module/specs/WhopPayButtonNativeComponent.ts +22 -0
  142. package/lib/module/theme/appearance.js +85 -0
  143. package/lib/module/theme/appearance.js.map +1 -0
  144. package/lib/module/theme/appearance.test.js +124 -0
  145. package/lib/module/theme/appearance.test.js.map +1 -0
  146. package/lib/module/theme/provider.js +25 -0
  147. package/lib/module/theme/provider.js.map +1 -0
  148. package/lib/module/theme/resolve.js +69 -0
  149. package/lib/module/theme/resolve.js.map +1 -0
  150. package/lib/module/theme/scales.generated.js +419 -0
  151. package/lib/module/theme/scales.generated.js.map +1 -0
  152. package/lib/module/ui/element-frame.js +83 -0
  153. package/lib/module/ui/element-frame.js.map +1 -0
  154. package/lib/module/ui/payment-method-icon.js +69 -0
  155. package/lib/module/ui/payment-method-icon.js.map +1 -0
  156. package/lib/module/ui/primitives.js +266 -0
  157. package/lib/module/ui/primitives.js.map +1 -0
  158. package/lib/module/ui/select.js +281 -0
  159. package/lib/module/ui/select.js.map +1 -0
  160. package/lib/module/ui/suggestions.js +71 -0
  161. package/lib/module/ui/suggestions.js.map +1 -0
  162. package/lib/module/ui/whop-logo.js +42 -0
  163. package/lib/module/ui/whop-logo.js.map +1 -0
  164. package/lib/typescript/package.json +1 -0
  165. package/lib/typescript/src/api/client.d.ts +87 -0
  166. package/lib/typescript/src/api/client.d.ts.map +1 -0
  167. package/lib/typescript/src/api/types.d.ts +175 -0
  168. package/lib/typescript/src/api/types.d.ts.map +1 -0
  169. package/lib/typescript/src/controller/actions.d.ts +42 -0
  170. package/lib/typescript/src/controller/actions.d.ts.map +1 -0
  171. package/lib/typescript/src/controller/store.d.ts +90 -0
  172. package/lib/typescript/src/controller/store.d.ts.map +1 -0
  173. package/lib/typescript/src/core/address/country-data.d.ts +4 -0
  174. package/lib/typescript/src/core/address/country-data.d.ts.map +1 -0
  175. package/lib/typescript/src/core/address/country-name.d.ts +2 -0
  176. package/lib/typescript/src/core/address/country-name.d.ts.map +1 -0
  177. package/lib/typescript/src/core/address/country-names.generated.d.ts +2 -0
  178. package/lib/typescript/src/core/address/country-names.generated.d.ts.map +1 -0
  179. package/lib/typescript/src/core/address/engine.d.ts +97 -0
  180. package/lib/typescript/src/core/address/engine.d.ts.map +1 -0
  181. package/lib/typescript/src/core/address/form-state.d.ts +144 -0
  182. package/lib/typescript/src/core/address/form-state.d.ts.map +1 -0
  183. package/lib/typescript/src/core/address/places.d.ts +23 -0
  184. package/lib/typescript/src/core/address/places.d.ts.map +1 -0
  185. package/lib/typescript/src/core/address/suggest.d.ts +47 -0
  186. package/lib/typescript/src/core/address/suggest.d.ts.map +1 -0
  187. package/lib/typescript/src/core/address/use-suggestions.d.ts +3 -0
  188. package/lib/typescript/src/core/address/use-suggestions.d.ts.map +1 -0
  189. package/lib/typescript/src/core/payments/address-change.d.ts +52 -0
  190. package/lib/typescript/src/core/payments/address-change.d.ts.map +1 -0
  191. package/lib/typescript/src/core/payments/billing-merge.d.ts +39 -0
  192. package/lib/typescript/src/core/payments/billing-merge.d.ts.map +1 -0
  193. package/lib/typescript/src/core/payments/browser-info.d.ts +12 -0
  194. package/lib/typescript/src/core/payments/browser-info.d.ts.map +1 -0
  195. package/lib/typescript/src/core/payments/bt.d.ts +55 -0
  196. package/lib/typescript/src/core/payments/bt.d.ts.map +1 -0
  197. package/lib/typescript/src/core/payments/currency.d.ts +7 -0
  198. package/lib/typescript/src/core/payments/currency.d.ts.map +1 -0
  199. package/lib/typescript/src/core/payments/detail.d.ts +53 -0
  200. package/lib/typescript/src/core/payments/detail.d.ts.map +1 -0
  201. package/lib/typescript/src/core/payments/errors.d.ts +62 -0
  202. package/lib/typescript/src/core/payments/errors.d.ts.map +1 -0
  203. package/lib/typescript/src/core/payments/mint.d.ts +74 -0
  204. package/lib/typescript/src/core/payments/mint.d.ts.map +1 -0
  205. package/lib/typescript/src/core/payments/plan.d.ts +69 -0
  206. package/lib/typescript/src/core/payments/plan.d.ts.map +1 -0
  207. package/lib/typescript/src/core/payments/refusals.d.ts +12 -0
  208. package/lib/typescript/src/core/payments/refusals.d.ts.map +1 -0
  209. package/lib/typescript/src/core/payments/secure-fields.d.ts +33 -0
  210. package/lib/typescript/src/core/payments/secure-fields.d.ts.map +1 -0
  211. package/lib/typescript/src/core/payments/tax-id-catalog.d.ts +481 -0
  212. package/lib/typescript/src/core/payments/tax-id-catalog.d.ts.map +1 -0
  213. package/lib/typescript/src/core/payments/wallet-contact.d.ts +40 -0
  214. package/lib/typescript/src/core/payments/wallet-contact.d.ts.map +1 -0
  215. package/lib/typescript/src/elements/address.d.ts +55 -0
  216. package/lib/typescript/src/elements/address.d.ts.map +1 -0
  217. package/lib/typescript/src/elements/branding.d.ts +18 -0
  218. package/lib/typescript/src/elements/branding.d.ts.map +1 -0
  219. package/lib/typescript/src/elements/card-fields/context.d.ts +67 -0
  220. package/lib/typescript/src/elements/card-fields/context.d.ts.map +1 -0
  221. package/lib/typescript/src/elements/card-fields/fields.d.ts +15 -0
  222. package/lib/typescript/src/elements/card-fields/fields.d.ts.map +1 -0
  223. package/lib/typescript/src/elements/card-fields/index.d.ts +21 -0
  224. package/lib/typescript/src/elements/card-fields/index.d.ts.map +1 -0
  225. package/lib/typescript/src/elements/card.d.ts +21 -0
  226. package/lib/typescript/src/elements/card.d.ts.map +1 -0
  227. package/lib/typescript/src/elements/email.d.ts +31 -0
  228. package/lib/typescript/src/elements/email.d.ts.map +1 -0
  229. package/lib/typescript/src/elements/payment/declared-fields.d.ts +43 -0
  230. package/lib/typescript/src/elements/payment/declared-fields.d.ts.map +1 -0
  231. package/lib/typescript/src/elements/payment/index.d.ts +37 -0
  232. package/lib/typescript/src/elements/payment/index.d.ts.map +1 -0
  233. package/lib/typescript/src/elements/payment/wallet.d.ts +39 -0
  234. package/lib/typescript/src/elements/payment/wallet.d.ts.map +1 -0
  235. package/lib/typescript/src/elements/tax-id.d.ts +41 -0
  236. package/lib/typescript/src/elements/tax-id.d.ts.map +1 -0
  237. package/lib/typescript/src/i18n/catalogs.d.ts +7 -0
  238. package/lib/typescript/src/i18n/catalogs.d.ts.map +1 -0
  239. package/lib/typescript/src/i18n/index.d.ts +17 -0
  240. package/lib/typescript/src/i18n/index.d.ts.map +1 -0
  241. package/lib/typescript/src/index.d.ts +42 -0
  242. package/lib/typescript/src/index.d.ts.map +1 -0
  243. package/lib/typescript/src/namespace.d.ts +36 -0
  244. package/lib/typescript/src/namespace.d.ts.map +1 -0
  245. package/lib/typescript/src/native/index.d.ts +62 -0
  246. package/lib/typescript/src/native/index.d.ts.map +1 -0
  247. package/lib/typescript/src/provider.d.ts +37 -0
  248. package/lib/typescript/src/provider.d.ts.map +1 -0
  249. package/lib/typescript/src/specs/NativeWhopAddressSuggestions.d.ts +13 -0
  250. package/lib/typescript/src/specs/NativeWhopAddressSuggestions.d.ts.map +1 -0
  251. package/lib/typescript/src/specs/NativeWhopAuthSession.d.ts +20 -0
  252. package/lib/typescript/src/specs/NativeWhopAuthSession.d.ts.map +1 -0
  253. package/lib/typescript/src/specs/NativeWhopPlatformPay.d.ts +24 -0
  254. package/lib/typescript/src/specs/NativeWhopPlatformPay.d.ts.map +1 -0
  255. package/lib/typescript/src/specs/WhopPayButtonNativeComponent.d.ts +21 -0
  256. package/lib/typescript/src/specs/WhopPayButtonNativeComponent.d.ts.map +1 -0
  257. package/lib/typescript/src/theme/appearance.d.ts +71 -0
  258. package/lib/typescript/src/theme/appearance.d.ts.map +1 -0
  259. package/lib/typescript/src/theme/provider.d.ts +11 -0
  260. package/lib/typescript/src/theme/provider.d.ts.map +1 -0
  261. package/lib/typescript/src/theme/resolve.d.ts +19 -0
  262. package/lib/typescript/src/theme/resolve.d.ts.map +1 -0
  263. package/lib/typescript/src/theme/scales.generated.d.ts +18 -0
  264. package/lib/typescript/src/theme/scales.generated.d.ts.map +1 -0
  265. package/lib/typescript/src/ui/element-frame.d.ts +32 -0
  266. package/lib/typescript/src/ui/element-frame.d.ts.map +1 -0
  267. package/lib/typescript/src/ui/payment-method-icon.d.ts +21 -0
  268. package/lib/typescript/src/ui/payment-method-icon.d.ts.map +1 -0
  269. package/lib/typescript/src/ui/primitives.d.ts +94 -0
  270. package/lib/typescript/src/ui/primitives.d.ts.map +1 -0
  271. package/lib/typescript/src/ui/select.d.ts +25 -0
  272. package/lib/typescript/src/ui/select.d.ts.map +1 -0
  273. package/lib/typescript/src/ui/suggestions.d.ts +15 -0
  274. package/lib/typescript/src/ui/suggestions.d.ts.map +1 -0
  275. package/lib/typescript/src/ui/whop-logo.d.ts +4 -0
  276. package/lib/typescript/src/ui/whop-logo.d.ts.map +1 -0
  277. package/package.json +121 -0
  278. package/scripts/check-swift.sh +27 -0
  279. package/scripts/codegen-shims.mjs +409 -0
  280. package/scripts/gen-country-names.mjs +58 -0
  281. package/scripts/gen-theme.mjs +124 -0
  282. package/scripts/gen-wordmark.mjs +68 -0
  283. package/scripts/mirror.mjs +112 -0
  284. package/src/api/client.ts +202 -0
  285. package/src/api/types.ts +166 -0
  286. package/src/controller/actions.ts +197 -0
  287. package/src/controller/store.ts +201 -0
  288. package/src/core/address/country-data.ts +927 -0
  289. package/src/core/address/country-name.ts +36 -0
  290. package/src/core/address/country-names.generated.ts +246 -0
  291. package/src/core/address/engine.ts +349 -0
  292. package/src/core/address/form-state.ts +479 -0
  293. package/src/core/address/places.ts +39 -0
  294. package/src/core/address/suggest.ts +153 -0
  295. package/src/core/address/use-suggestions.ts +37 -0
  296. package/src/core/payments/address-change.ts +121 -0
  297. package/src/core/payments/billing-merge.ts +91 -0
  298. package/src/core/payments/browser-info.ts +43 -0
  299. package/src/core/payments/bt.ts +176 -0
  300. package/src/core/payments/currency.ts +54 -0
  301. package/src/core/payments/detail.ts +204 -0
  302. package/src/core/payments/errors.ts +171 -0
  303. package/src/core/payments/mint.ts +130 -0
  304. package/src/core/payments/plan.ts +198 -0
  305. package/src/core/payments/refusals.ts +24 -0
  306. package/src/core/payments/secure-fields.ts +85 -0
  307. package/src/core/payments/tax-id-catalog.ts +320 -0
  308. package/src/core/payments/wallet-contact.ts +56 -0
  309. package/src/elements/address.tsx +570 -0
  310. package/src/elements/branding.tsx +87 -0
  311. package/src/elements/card-fields/context.tsx +310 -0
  312. package/src/elements/card-fields/fields.tsx +281 -0
  313. package/src/elements/card-fields/index.tsx +37 -0
  314. package/src/elements/card.tsx +101 -0
  315. package/src/elements/email.tsx +100 -0
  316. package/src/elements/payment/declared-fields.tsx +238 -0
  317. package/src/elements/payment/index.tsx +497 -0
  318. package/src/elements/payment/wallet.tsx +155 -0
  319. package/src/elements/tax-id.tsx +143 -0
  320. package/src/i18n/catalogs.ts +100 -0
  321. package/src/i18n/index.tsx +46 -0
  322. package/src/index.ts +68 -0
  323. package/src/namespace.tsx +231 -0
  324. package/src/native/index.ts +173 -0
  325. package/src/provider.tsx +76 -0
  326. package/src/specs/NativeWhopAddressSuggestions.ts +14 -0
  327. package/src/specs/NativeWhopAuthSession.ts +21 -0
  328. package/src/specs/NativeWhopPlatformPay.ts +25 -0
  329. package/src/specs/WhopPayButtonNativeComponent.ts +22 -0
  330. package/src/theme/appearance.ts +150 -0
  331. package/src/theme/provider.tsx +28 -0
  332. package/src/theme/resolve.ts +68 -0
  333. package/src/theme/scales.generated.ts +427 -0
  334. package/src/ui/element-frame.tsx +94 -0
  335. package/src/ui/payment-method-icon.tsx +55 -0
  336. package/src/ui/primitives.tsx +269 -0
  337. package/src/ui/select.tsx +255 -0
  338. package/src/ui/suggestions.tsx +69 -0
  339. package/src/ui/whop-logo.tsx +37 -0
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+
3
+ import { sha256 } from '@noble/hashes/sha2';
4
+ import { bytesToHex } from '@noble/hashes/utils';
5
+ import { apiErrorMessage } from "./errors.js";
6
+
7
+ /** The package re-exports the hook but not its return type, so derive it rather than reach into a
8
+ * deep path that could move. */
9
+
10
+ /** The opaque handle a Basis Theory element hands out. It carries an id and a formatter, never the
11
+ * value the buyer typed — which is the whole isolation guarantee. */
12
+
13
+ const CARD_TOKEN_TTL_MS = 60 * 60 * 1000;
14
+
15
+ /**
16
+ * Assemble one Basis Theory card token from the three field refs.
17
+ *
18
+ * This is the web ceremony (`card-fields/bt.ts`) with the frame hops removed: a BT session anchors
19
+ * a nonce-derived container, the number seeds an ephemeral token into it, the Whop backend
20
+ * authorizes the session for that container alone, and the remaining fields patch in under the
21
+ * session key. The web element splits these across three iframes and threads a serializable grant
22
+ * between them; here all three refs live in one realm, so the grant never leaves this function.
23
+ *
24
+ * The ceremony is kept rather than collapsed into a single create because it is what the
25
+ * card-assembly Basis Theory application is configured to permit: the backend authorizes
26
+ * `token:update` scoped to `starts_with` the derived container, for ten minutes.
27
+ */
28
+ export async function tokenizeCard(bt, refs, command, sdk) {
29
+ if (!refs.number || !refs.expiryMonth || !refs.expiryYear || !refs.cvc) {
30
+ return {
31
+ ok: false,
32
+ code: 'card_fields_not_ready',
33
+ message: 'Card fields are not ready yet'
34
+ };
35
+ }
36
+ let session;
37
+ try {
38
+ session = await bt.sessions.create();
39
+ } catch (err) {
40
+ return collectFailure(err, 'card_tokenizer_session_failed', 'card_tokenizer_session_failed');
41
+ }
42
+ if (!session) {
43
+ return {
44
+ ok: false,
45
+ code: 'card_tokenizer_session_failed',
46
+ message: 'the tokenizer returned no session'
47
+ };
48
+ }
49
+ const container = `/card-assembly/${sha256Hex(session.nonce)}/`;
50
+ let tokenId;
51
+ try {
52
+ const token = await bt.tokens.create({
53
+ type: 'card',
54
+ data: {
55
+ number: refs.number
56
+ },
57
+ containers: [container],
58
+ expiresAt: new Date(Date.now() + CARD_TOKEN_TTL_MS).toISOString()
59
+ },
60
+ // The key is passed per call, never left to the client's config: Basis Theory's client
61
+ // is a module-level singleton whose first key wins for the whole process, so a second
62
+ // client built with a different application's key (a method's secure fields) would
63
+ // otherwise silently sign these calls.
64
+ {
65
+ apiKey: command.publicKey
66
+ });
67
+ if (!token?.id) {
68
+ return {
69
+ ok: false,
70
+ code: 'card_number_tokenization_failed',
71
+ message: 'the tokenizer returned no token'
72
+ };
73
+ }
74
+ tokenId = token.id;
75
+ } catch (err) {
76
+ return collectFailure(err, 'card_number_validation_failed', 'card_number_tokenization_failed');
77
+ }
78
+ try {
79
+ await sdk.paymentMethodTypes.createSession('card', {
80
+ account_id: command.accountId,
81
+ nonce: session.nonce
82
+ });
83
+ } catch (err) {
84
+ return {
85
+ ok: false,
86
+ code: 'card_session_authorization_failed',
87
+ message: apiErrorMessage(err, 'card session authorization failed')
88
+ };
89
+ }
90
+ try {
91
+ await bt.tokens.update(tokenId, {
92
+ data: {
93
+ expiration_month: refs.expiryMonth,
94
+ expiration_year: refs.expiryYear
95
+ }
96
+ }, {
97
+ apiKey: session.sessionKey
98
+ });
99
+ } catch (err) {
100
+ return collectFailure(err, 'card_expiry_validation_failed', 'card_expiry_tokenization_failed');
101
+ }
102
+ try {
103
+ await bt.tokens.update(tokenId, {
104
+ data: {
105
+ cvc: refs.cvc
106
+ }
107
+ }, {
108
+ apiKey: session.sessionKey
109
+ });
110
+ } catch (err) {
111
+ return collectFailure(err, 'card_cvc_validation_failed', 'card_cvc_tokenization_failed');
112
+ }
113
+ return {
114
+ ok: true,
115
+ token: tokenId
116
+ };
117
+ }
118
+
119
+ /**
120
+ * Must byte-match the backend's `Digest::SHA256.hexdigest` — lowercase hex, no separators.
121
+ *
122
+ * `@noble/hashes` UTF-8 encodes a string input itself, which is also why this does not reach for
123
+ * `TextEncoder`: React Native has no DOM and does not guarantee one.
124
+ */
125
+ export function sha256Hex(value) {
126
+ return bytesToHex(sha256(value));
127
+ }
128
+ function collectFailure(err, validationCode, failureCode) {
129
+ const details = err instanceof Error && err.name === 'BasisTheoryValidationError' ? err.details?.data : undefined;
130
+ if (details) {
131
+ return {
132
+ ok: false,
133
+ code: validationCode,
134
+ message: 'Your card details are incomplete or invalid',
135
+ fields: {
136
+ number: fieldFailure(details.number),
137
+ cvc: fieldFailure(details.cvc),
138
+ expiry: fieldFailure(details.expiration_month) ?? fieldFailure(details.expiration_year)
139
+ }
140
+ };
141
+ }
142
+ return {
143
+ ok: false,
144
+ code: failureCode,
145
+ message: err instanceof Error ? err.message : 'Card tokenization failed'
146
+ };
147
+ }
148
+ function fieldFailure(detail) {
149
+ return detail?.type === 'invalid' || detail?.type === 'incomplete' ? detail.type : undefined;
150
+ }
151
+ //# sourceMappingURL=bt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["sha256","bytesToHex","apiErrorMessage","CARD_TOKEN_TTL_MS","tokenizeCard","bt","refs","command","sdk","number","expiryMonth","expiryYear","cvc","ok","code","message","session","sessions","create","err","collectFailure","container","sha256Hex","nonce","tokenId","token","tokens","type","data","containers","expiresAt","Date","now","toISOString","apiKey","publicKey","id","paymentMethodTypes","createSession","account_id","accountId","update","expiration_month","expiration_year","sessionKey","value","validationCode","failureCode","details","Error","name","undefined","fields","fieldFailure","expiry","detail"],"sourceRoot":"../../../../src","sources":["core/payments/bt.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+
3
+ import { describe, expect, it } from 'vitest';
4
+ import { sha256Hex } from "./bt.js";
5
+ describe('sha256Hex', () => {
6
+ // The backend derives the card-assembly container as
7
+ // "/card-assembly/#{Digest::SHA256.hexdigest(nonce)}/". A mismatch here means every patch step
8
+ // 403s against a container the session was never authorized for, so this is pinned against
9
+ // known digests rather than against our own implementation.
10
+ it('matches Digest::SHA256.hexdigest for known inputs', () => {
11
+ expect(sha256Hex('')).toBe('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855');
12
+ expect(sha256Hex('abc')).toBe('ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad');
13
+ expect(sha256Hex('nonce')).toBe('78377b525757b494427f89014f97d79928f3938d14eb51e20fb5dec9834eb304');
14
+ });
15
+ it('emits lowercase hex with no separators', () => {
16
+ const digest = sha256Hex('Whop');
17
+ expect(digest).toMatch(/^[0-9a-f]{64}$/);
18
+ });
19
+ it('is UTF-8 encoded, so a non-ASCII nonce agrees with the server', () => {
20
+ expect(sha256Hex('é')).toBe('4a99557e4033c3539de2eb65472017cad5f9557f7a0625a09f1c3f6e2ba69c4c');
21
+ });
22
+ });
23
+ //# sourceMappingURL=bt.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["describe","expect","it","sha256Hex","toBe","digest","toMatch"],"sourceRoot":"../../../../src","sources":["core/payments/bt.test.ts"],"mappings":";;AAAA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,QAAQ;AAE7C,SAASC,SAAS,QAAQ,SAAM;AAEhCH,QAAQ,CAAC,WAAW,EAAE,MAAM;EAC3B;EACA;EACA;EACA;EACAE,EAAE,CAAC,mDAAmD,EAAE,MAAM;IAC7DD,MAAM,CAACE,SAAS,CAAC,EAAE,CAAC,CAAC,CAACC,IAAI,CAAC,kEAAkE,CAAC;IAC9FH,MAAM,CAACE,SAAS,CAAC,KAAK,CAAC,CAAC,CAACC,IAAI,CAAC,kEAAkE,CAAC;IACjGH,MAAM,CAACE,SAAS,CAAC,OAAO,CAAC,CAAC,CAACC,IAAI,CAAC,kEAAkE,CAAC;EACpG,CAAC,CAAC;EAEFF,EAAE,CAAC,wCAAwC,EAAE,MAAM;IAClD,MAAMG,MAAM,GAAGF,SAAS,CAAC,MAAM,CAAC;IAChCF,MAAM,CAACI,MAAM,CAAC,CAACC,OAAO,CAAC,gBAAgB,CAAC;EACzC,CAAC,CAAC;EAEFJ,EAAE,CAAC,+DAA+D,EAAE,MAAM;IACzED,MAAM,CAACE,SAAS,CAAC,GAAG,CAAC,CAAC,CAACC,IAAI,CAAC,kEAAkE,CAAC;EAChG,CAAC,CAAC;AACH,CAAC,CAAC","ignoreList":[]}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ // ported verbatim from frontend/apps/web/src/elements/payments/lib/currency.ts — keep in sync when the web element changes
4
+
5
+ /**
6
+ * The minor-unit factor, mirroring the BACKEND's conversion exactly (Utils.amount_in_cents /
7
+ * stripe_factor_decimal over ZERO_DECIMAL_CURRENCIES + THREE_DECIMAL_CURRENCIES in
8
+ * backend/lib/application_constants.rb) — the backend is the authority on a currency's factor,
9
+ * NOT Intl/CLDR: several acceptable plan currencies (huf, cop, idr, pkr, all) are zero-decimal
10
+ * in CLDR but charged in 1/100ths by the backend, so an Intl-derived factor is 100× off for
11
+ * them. Keep these lists in lockstep with the backend constants.
12
+ */
13
+
14
+ const ZERO_DECIMAL_CURRENCIES = new Set(['bif', 'clp', 'djf', 'gnf', 'jpy', 'kmf', 'krw', 'mga', 'pyg', 'rwf', 'ugx', 'vnd', 'vuv', 'xaf', 'xof', 'xpf']);
15
+ const THREE_DECIMAL_CURRENCIES = new Set(['bhd', 'jod', 'kwd', 'omr', 'tnd']);
16
+ export function currencyMinorDigits(currency) {
17
+ const code = currency.toLowerCase();
18
+ if (ZERO_DECIMAL_CURRENCIES.has(code)) return 0;
19
+ if (THREE_DECIMAL_CURRENCIES.has(code)) return 3;
20
+ return 2;
21
+ }
22
+
23
+ /** Major-unit decimal (how money rides the wire) → the minor-unit integer a charge takes, on the
24
+ * backend's factor above — never Intl's. toFixed(4) first (kills float-scale artifacts like
25
+ * 29.99×100 → 2998.999…), then trunc (a genuinely sub-minor fraction never rounds the charge UP). */
26
+ export function toMinorUnits(majorAmount, currency) {
27
+ return Math.trunc(Number((majorAmount * 10 ** currencyMinorDigits(currency)).toFixed(4)));
28
+ }
29
+
30
+ // Charged in minor units but shown without them (PaymentsConstants::NO_MINOR_UNIT_CURRENCIES).
31
+ const NO_MINOR_UNIT_CURRENCIES = new Set(['cop']);
32
+ export function currencyDisplayDigits(currency) {
33
+ const code = currency.toLowerCase();
34
+ if (NO_MINOR_UNIT_CURRENCIES.has(code)) return 0;
35
+ return currencyMinorDigits(code);
36
+ }
37
+ //# sourceMappingURL=currency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["ZERO_DECIMAL_CURRENCIES","Set","THREE_DECIMAL_CURRENCIES","currencyMinorDigits","currency","code","toLowerCase","has","toMinorUnits","majorAmount","Math","trunc","Number","toFixed","NO_MINOR_UNIT_CURRENCIES","currencyDisplayDigits"],"sourceRoot":"../../../../src","sources":["core/payments/currency.ts"],"mappings":";;AAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,MAAMA,uBAAuB,GAAG,IAAIC,GAAG,CAAC,CACtC,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,CACN,CAAC;AAEF,MAAMC,wBAAwB,GAAG,IAAID,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AAE7E,OAAO,SAASE,mBAAmBA,CAACC,QAAgB,EAAU;EAC5D,MAAMC,IAAI,GAAGD,QAAQ,CAACE,WAAW,CAAC,CAAC;EACnC,IAAIN,uBAAuB,CAACO,GAAG,CAACF,IAAI,CAAC,EAAE,OAAO,CAAC;EAC/C,IAAIH,wBAAwB,CAACK,GAAG,CAACF,IAAI,CAAC,EAAE,OAAO,CAAC;EAChD,OAAO,CAAC;AACV;;AAEA;AACA;AACA;AACA,OAAO,SAASG,YAAYA,CAACC,WAAmB,EAAEL,QAAgB,EAAU;EAC1E,OAAOM,IAAI,CAACC,KAAK,CAACC,MAAM,CAAC,CAACH,WAAW,GAAG,EAAE,IAAIN,mBAAmB,CAACC,QAAQ,CAAC,EAAES,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3F;;AAEA;AACA,MAAMC,wBAAwB,GAAG,IAAIb,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AAEjD,OAAO,SAASc,qBAAqBA,CAACX,QAAgB,EAAU;EAC9D,MAAMC,IAAI,GAAGD,QAAQ,CAACE,WAAW,CAAC,CAAC;EACnC,IAAIQ,wBAAwB,CAACP,GAAG,CAACF,IAAI,CAAC,EAAE,OAAO,CAAC;EAChD,OAAOF,mBAAmB,CAACE,IAAI,CAAC;AAClC","ignoreList":[]}
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+
3
+ // gating rules ported from frontend/apps/web/src/elements/payments/lib/detail.tsx — keep in sync
4
+
5
+ import { currencyMinorDigits } from "./currency.js";
6
+
7
+ /**
8
+ * Which checkout is asking. The matrix leaves out methods that do not serve the named surface, and
9
+ * the axis is who BUILT the checkout, not where it runs.
10
+ *
11
+ * A React Native mount is `direct_checkout`: it owns its own presentation the way a first-party
12
+ * whop.com document does, and unlike an iframe it can hand a full-page step to the system browser.
13
+ * Sending `external_checkout` would drop every `full_page`-only method from the list.
14
+ */
15
+
16
+ const TAB_OWNING_SURFACES = ['direct_checkout', 'modal_checkout'];
17
+
18
+ /**
19
+ * The categories this build can actually collect. An entry from a newer matrix in a category this
20
+ * build does not implement is a rail it cannot run, so it is skipped rather than rendered as a
21
+ * broken tile — the same gate web added in #25658 (apps/web/src/elements/payments/lib/detail.tsx).
22
+ *
23
+ * `balance` is web's list minus one: ledger-balance payment is not in this release (README), so
24
+ * claiming it here would render a tile that cannot complete.
25
+ */
26
+ const IMPLEMENTED_CATEGORIES = ['card', 'wallet', 'bank_debit', 'bank_transfer', 'voucher', 'redirect', 'crypto'];
27
+ const TEMPLATES = ['redirect', 'bnpl_confirm', 'bank_connect', 'bank_wire', 'wallet_sheet', 'none'];
28
+ export function detailTemplate(entry) {
29
+ const declared = entry.detail?.template;
30
+ if (declared && TEMPLATES.includes(declared)) return declared;
31
+ // An unknown template is a newer matrix than this build; redirect copy is the safe read.
32
+ return 'redirect';
33
+ }
34
+ export function passesConfiguration(type, configuration, platformDefault) {
35
+ if (!configuration) return platformDefault ?? true;
36
+ const enabled = configuration.enabled ?? [];
37
+ if (!(configuration.include_platform_defaults ?? true)) return enabled.includes(type);
38
+ // (platform defaults − disabled + enabled): an off-by-default type needs an explicit enable,
39
+ // so "not disabled" alone is not an allow.
40
+ return (platformDefault ?? true) && !(configuration.disabled ?? []).includes(type) || enabled.includes(type);
41
+ }
42
+
43
+ /** The entry's category-keyed config block, read generically. */
44
+ export function methodConfigBlock(entry) {
45
+ const block = entry[entry.category];
46
+ return block && typeof block === 'object' ? block : {};
47
+ }
48
+ export function methodTokenizerKey(entry) {
49
+ const key = methodConfigBlock(entry).public_key;
50
+ return typeof key === 'string' ? key : undefined;
51
+ }
52
+
53
+ /**
54
+ * Whether the entry is offered for this charge on this surface.
55
+ *
56
+ * Amount-gated methods are excluded outright rather than rendered disabled, and every absent field
57
+ * reads as unrestricted so an older matrix keeps its behavior.
58
+ */
59
+ export function presentMethod(entry, currency, amount, setupFutureUsage, walletAvailability, configuration, surface, country) {
60
+ // A category this build does not implement is a rail it cannot collect — an entry from a newer
61
+ // matrix must be skipped, never rendered as a broken tile.
62
+ if (!IMPLEMENTED_CATEGORIES.includes(entry.category)) return false;
63
+ if (!TAB_OWNING_SURFACES.includes(surface) && entry.next_action_render_modes && !entry.next_action_render_modes.includes('inline')) {
64
+ return false;
65
+ }
66
+ if (!passesConfiguration(entry.type, configuration, entry.platform_default)) return false;
67
+ if (!entry.usage?.one_time) return false;
68
+ if (setupFutureUsage === 'off_session' && !entry.usage?.off_session) return false;
69
+ if (setupFutureUsage === 'on_session' && !entry.usage?.on_session) return false;
70
+ if (entry.category === 'card' && !entry.card?.public_key) return false;
71
+ // A secure declared field tokenizes into the config block's key at collect time; without the key
72
+ // the method is broken at confirm, so it is never offered.
73
+ if ((entry.required_fields ?? []).some(field => field.secure) && !methodTokenizerKey(entry)) return false;
74
+ if (detailTemplate(entry) === 'wallet_sheet') {
75
+ if (entry.type === 'apple_pay' && !walletAvailability?.applePay) return false;
76
+ if (entry.type === 'google_pay' && !walletAvailability?.googlePay) return false;
77
+ }
78
+ const bounds = entry.currencies?.[currency.toLowerCase()];
79
+ if (!bounds) return false;
80
+ const {
81
+ min,
82
+ max
83
+ } = amountBounds(bounds, country);
84
+ if (min != null && amount < min) return false;
85
+ if (max != null && amount > max) return false;
86
+ return true;
87
+ }
88
+
89
+ /**
90
+ * A currency's limits, narrowed to the billing country when the matrix publishes a row for it.
91
+ *
92
+ * Reading only the currency-level pair offered methods that the selected country cannot actually
93
+ * take at this amount, which the buyer discovers at confirm rather than in the list. Mirrors
94
+ * `amountBounds` in apps/web/src/elements/payments/lib/detail.tsx.
95
+ */
96
+ function amountBounds(bounds, country) {
97
+ const code = country?.toLowerCase();
98
+ const row = code ? bounds.countries?.find(candidate => candidate.country?.toLowerCase() === code) : undefined;
99
+ if (!row) return {
100
+ min: bounds.min_amount,
101
+ max: bounds.max_amount
102
+ };
103
+ return {
104
+ min: row.min_amount,
105
+ max: row.max_amount
106
+ };
107
+ }
108
+
109
+ /** Listed types take their list position; unlisted types share the tail rank, so a stable sort
110
+ * preserves their incoming order. */
111
+ export function orderRank(type, order) {
112
+ const index = order.indexOf(type);
113
+ return index === -1 ? order.length : index;
114
+ }
115
+ export function formatMinorAmount(amount, currency, locale) {
116
+ // The divisor is the backend-mirrored factor; the display digits are Intl's. They disagree for
117
+ // currencies like huf, and the backend's answer is the one that priced the charge.
118
+ const major = amount / 10 ** currencyMinorDigits(currency);
119
+ try {
120
+ return new Intl.NumberFormat(locale, {
121
+ style: 'currency',
122
+ currency: currency.toUpperCase()
123
+ }).format(major);
124
+ } catch {
125
+ return `${major} ${currency.toUpperCase()}`;
126
+ }
127
+ }
128
+ export function fieldLabel(name) {
129
+ const spaced = name.replace(/_/g, ' ').replace(/\bid\b/gi, 'ID');
130
+ return spaced.charAt(0).toUpperCase() + spaced.slice(1);
131
+ }
132
+
133
+ /** A declared field's country-keyed pattern, `*` as the fallback. Never throws on a bad pattern. */
134
+ export function fieldMatches(formats, country, value) {
135
+ if (!formats) return true;
136
+ const trimmed = value.trim();
137
+ const patterns = [formats[(country ?? '').toLowerCase()], formats['*']].filter(p => typeof p === 'string');
138
+ return patterns.length === 0 || patterns.some(pattern => safeTest(pattern, trimmed));
139
+ }
140
+ function safeTest(pattern, value) {
141
+ try {
142
+ return new RegExp(pattern).test(value);
143
+ } catch {
144
+ return true;
145
+ }
146
+ }
147
+
148
+ /**
149
+ * The billing countries a method constrains the buyer to, or null when it constrains nothing.
150
+ *
151
+ * `*` anywhere in the entry's per-currency list means unrestricted, and so does an empty list — a
152
+ * method that names countries names ALL of the ones it serves. The address element intersects the
153
+ * result with the integrator's own `allowedCountries` rather than replacing it.
154
+ */
155
+ export function methodBillingCountries(entry, currency) {
156
+ const codes = (entry?.currencies?.[currency]?.countries ?? []).map(row => row.country);
157
+ return codes.length === 0 || codes.includes('*') ? null : codes;
158
+ }
159
+ //# sourceMappingURL=detail.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["currencyMinorDigits","TAB_OWNING_SURFACES","IMPLEMENTED_CATEGORIES","TEMPLATES","detailTemplate","entry","declared","detail","template","includes","passesConfiguration","type","configuration","platformDefault","enabled","include_platform_defaults","disabled","methodConfigBlock","block","category","methodTokenizerKey","key","public_key","undefined","presentMethod","currency","amount","setupFutureUsage","walletAvailability","surface","country","next_action_render_modes","platform_default","usage","one_time","off_session","on_session","card","required_fields","some","field","secure","applePay","googlePay","bounds","currencies","toLowerCase","min","max","amountBounds","code","row","countries","find","candidate","min_amount","max_amount","orderRank","order","index","indexOf","length","formatMinorAmount","locale","major","Intl","NumberFormat","style","toUpperCase","format","fieldLabel","name","spaced","replace","charAt","slice","fieldMatches","formats","value","trimmed","trim","patterns","filter","p","pattern","safeTest","RegExp","test","methodBillingCountries","codes","map"],"sourceRoot":"../../../../src","sources":["core/payments/detail.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,225 @@
1
+ "use strict";
2
+
3
+ import { describe, expect, it } from 'vitest';
4
+ import { methodBillingCountries, orderRank, passesConfiguration, presentMethod } from "./detail.js";
5
+ function entry(overrides = {}) {
6
+ return {
7
+ object: 'payment_method_type',
8
+ type: 'card',
9
+ category: 'card',
10
+ display_name: 'Card',
11
+ detail: {
12
+ template: 'none'
13
+ },
14
+ usage: {
15
+ one_time: true,
16
+ off_session: true,
17
+ on_session: true
18
+ },
19
+ currencies: {
20
+ usd: {
21
+ min_amount: null,
22
+ max_amount: null,
23
+ countries: []
24
+ }
25
+ },
26
+ card: {
27
+ public_key: 'key_live'
28
+ },
29
+ ...overrides
30
+ };
31
+ }
32
+ describe('presentMethod', () => {
33
+ const offer = (e, ...rest) => presentMethod(e, ...rest);
34
+ it('offers a card with a tokenizer key inside its currency bounds', () => {
35
+ expect(offer(entry(), 'usd', 1000, undefined, undefined, undefined, 'direct_checkout')).toBe(true);
36
+ });
37
+ it('refuses a card with no tokenizer key rather than rendering a broken tile', () => {
38
+ expect(offer(entry({
39
+ card: {
40
+ public_key: null
41
+ }
42
+ }), 'usd', 1000, undefined, undefined, undefined, 'direct_checkout')).toBe(false);
43
+ });
44
+ it('refuses a secure declared field with no tokenizer key', () => {
45
+ const sepa = entry({
46
+ type: 'sepa_debit',
47
+ category: 'bank_debit',
48
+ required_fields: [{
49
+ name: 'bank_account',
50
+ kind: 'payment_method',
51
+ secure: true
52
+ }]
53
+ });
54
+ expect(offer(sepa, 'usd', 1000, undefined, undefined, undefined, 'direct_checkout')).toBe(false);
55
+ });
56
+ it('excludes an amount outside the currency bounds outright', () => {
57
+ const bounded = entry({
58
+ currencies: {
59
+ usd: {
60
+ min_amount: 5000,
61
+ max_amount: null,
62
+ countries: []
63
+ }
64
+ }
65
+ });
66
+ expect(offer(bounded, 'usd', 1000, undefined, undefined, undefined, 'direct_checkout')).toBe(false);
67
+ expect(offer(bounded, 'usd', 5000, undefined, undefined, undefined, 'direct_checkout')).toBe(true);
68
+ });
69
+
70
+ // The currency-level pair was the only thing read, so a method the selected country cannot take
71
+ // at this amount was still offered and the buyer met the refusal at confirm instead of the list.
72
+ it('prefers the billing country row over the currency bounds', () => {
73
+ const bounded = entry({
74
+ currencies: {
75
+ usd: {
76
+ min_amount: 100,
77
+ max_amount: null,
78
+ countries: [{
79
+ country: 'GB',
80
+ min_amount: 5000,
81
+ max_amount: null
82
+ }]
83
+ }
84
+ }
85
+ });
86
+ expect(offer(bounded, 'usd', 1000, undefined, undefined, undefined, 'direct_checkout', 'GB')).toBe(false);
87
+ expect(offer(bounded, 'usd', 5000, undefined, undefined, undefined, 'direct_checkout', 'GB')).toBe(true);
88
+ });
89
+ it('falls back to the currency bounds for a country with no row', () => {
90
+ const bounded = entry({
91
+ currencies: {
92
+ usd: {
93
+ min_amount: 100,
94
+ max_amount: null,
95
+ countries: [{
96
+ country: 'GB',
97
+ min_amount: 5000,
98
+ max_amount: null
99
+ }]
100
+ }
101
+ }
102
+ });
103
+ expect(offer(bounded, 'usd', 1000, undefined, undefined, undefined, 'direct_checkout', 'US')).toBe(true);
104
+ expect(offer(bounded, 'usd', 1000, undefined, undefined, undefined, 'direct_checkout', undefined)).toBe(true);
105
+ });
106
+ it('matches the country case-insensitively, as the matrix publishes it', () => {
107
+ const bounded = entry({
108
+ currencies: {
109
+ usd: {
110
+ min_amount: 100,
111
+ max_amount: null,
112
+ countries: [{
113
+ country: 'gb',
114
+ min_amount: 5000,
115
+ max_amount: null
116
+ }]
117
+ }
118
+ }
119
+ });
120
+ expect(offer(bounded, 'usd', 1000, undefined, undefined, undefined, 'direct_checkout', 'GB')).toBe(false);
121
+ });
122
+ it('normalizes the currency the matrix keys lowercase', () => {
123
+ expect(offer(entry(), 'USD', 1000, undefined, undefined, undefined, 'direct_checkout')).toBe(true);
124
+ });
125
+ it('refuses a method that cannot vault when off_session save-consent is declared', () => {
126
+ const noVault = entry({
127
+ usage: {
128
+ one_time: true,
129
+ off_session: false,
130
+ on_session: true
131
+ }
132
+ });
133
+ expect(offer(noVault, 'usd', 1000, 'off_session', undefined, undefined, 'direct_checkout')).toBe(false);
134
+ });
135
+ it('hides a wallet until its probe lands true, without gating the rest', () => {
136
+ const wallet = entry({
137
+ type: 'apple_pay',
138
+ category: 'wallet',
139
+ detail: {
140
+ template: 'wallet_sheet'
141
+ },
142
+ card: null
143
+ });
144
+ expect(offer(wallet, 'usd', 1000, undefined, undefined, undefined, 'direct_checkout')).toBe(false);
145
+ expect(offer(wallet, 'usd', 1000, undefined, {
146
+ applePay: true
147
+ }, undefined, 'direct_checkout')).toBe(true);
148
+ });
149
+ it('keeps a full_page-only method on a tab-owning surface', () => {
150
+ const redirect = entry({
151
+ type: 'ideal',
152
+ category: 'redirect',
153
+ detail: {
154
+ template: 'redirect'
155
+ },
156
+ card: null,
157
+ next_action_render_modes: ['full_page']
158
+ });
159
+ // A React Native mount owns its presentation and can hand the step to the system browser.
160
+ expect(offer(redirect, 'usd', 1000, undefined, undefined, undefined, 'direct_checkout')).toBe(true);
161
+ expect(offer(redirect, 'usd', 1000, undefined, undefined, undefined, 'external_checkout')).toBe(false);
162
+ });
163
+ });
164
+ describe('passesConfiguration', () => {
165
+ it('treats an absent configuration as the platform default', () => {
166
+ expect(passesConfiguration('card', undefined, true)).toBe(true);
167
+ expect(passesConfiguration('card', undefined, false)).toBe(false);
168
+ });
169
+ it('needs an explicit enable for an off-by-default type', () => {
170
+ expect(passesConfiguration('pix', {
171
+ disabled: []
172
+ }, false)).toBe(false);
173
+ expect(passesConfiguration('pix', {
174
+ enabled: ['pix']
175
+ }, false)).toBe(true);
176
+ });
177
+ it('leaves only enabled types when platform defaults are excluded', () => {
178
+ expect(passesConfiguration('card', {
179
+ enabled: ['pix'],
180
+ include_platform_defaults: false
181
+ }, true)).toBe(false);
182
+ expect(passesConfiguration('pix', {
183
+ enabled: ['pix'],
184
+ include_platform_defaults: false
185
+ }, false)).toBe(true);
186
+ });
187
+ });
188
+ describe('orderRank', () => {
189
+ it('gives unlisted types a shared tail rank so a stable sort keeps their order', () => {
190
+ expect(orderRank('apple_pay', ['apple_pay', 'card'])).toBe(0);
191
+ expect(orderRank('card', ['apple_pay', 'card'])).toBe(1);
192
+ expect(orderRank('pix', ['apple_pay', 'card'])).toBe(2);
193
+ expect(orderRank('ideal', ['apple_pay', 'card'])).toBe(2);
194
+ });
195
+ });
196
+ describe('methodBillingCountries', () => {
197
+ const bound = (...codes) => ({
198
+ currencies: {
199
+ usd: {
200
+ min_amount: null,
201
+ max_amount: null,
202
+ countries: codes.map(country => ({
203
+ country,
204
+ min_amount: null,
205
+ max_amount: null
206
+ }))
207
+ }
208
+ }
209
+ });
210
+ it('returns the entry\'s countries for the charge currency', () => {
211
+ expect(methodBillingCountries(bound('DE', 'NL'), 'usd')).toEqual(['DE', 'NL']);
212
+ });
213
+ it('returns null when a wildcard is present', () => {
214
+ expect(methodBillingCountries(bound('*'), 'usd')).toBeNull();
215
+ expect(methodBillingCountries(bound('DE', '*'), 'usd')).toBeNull();
216
+ });
217
+ it('returns null when nothing is declared', () => {
218
+ expect(methodBillingCountries(bound(), 'usd')).toBeNull();
219
+ expect(methodBillingCountries(undefined, 'usd')).toBeNull();
220
+ });
221
+ it('is scoped to the charge currency, not the whole entry', () => {
222
+ expect(methodBillingCountries(bound('DE'), 'eur')).toBeNull();
223
+ });
224
+ });
225
+ //# sourceMappingURL=detail.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["describe","expect","it","methodBillingCountries","orderRank","passesConfiguration","presentMethod","entry","overrides","object","type","category","display_name","detail","template","usage","one_time","off_session","on_session","currencies","usd","min_amount","max_amount","countries","card","public_key","offer","e","rest","undefined","toBe","sepa","required_fields","name","kind","secure","bounded","country","noVault","wallet","applePay","redirect","next_action_render_modes","disabled","enabled","include_platform_defaults","bound","codes","map","toEqual","toBeNull"],"sourceRoot":"../../../../src","sources":["core/payments/detail.test.ts"],"mappings":"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","ignoreList":[]}