Explorar el Código

Merge pull request #28270 from overleaf/kh-add-stripe-payment-context

[web] add stripe payment context

GitOrigin-RevId: 79dfbb1da0dd6b1d36c68c86debffc1edb169961
Kristina hace 11 meses
padre
commit
c79cc52fcf

+ 15 - 0
package-lock.json

@@ -11605,6 +11605,20 @@
         "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0"
       }
     },
+    "node_modules/@stripe/react-stripe-js": {
+      "version": "3.9.0",
+      "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-3.9.0.tgz",
+      "integrity": "sha512-pN1Re7zUc3m61FFQROok685g3zsBQRzCmZDmTzO8iPU6zhLvu2JnC0LrG0FCzSp6kgGa8AQSzq4rpFSgyhkjKg==",
+      "license": "MIT",
+      "dependencies": {
+        "prop-types": "^15.7.2"
+      },
+      "peerDependencies": {
+        "@stripe/stripe-js": ">=1.44.1 <8.0.0",
+        "react": ">=16.8.0 <20.0.0",
+        "react-dom": ">=16.8.0 <20.0.0"
+      }
+    },
     "node_modules/@stripe/stripe-js": {
       "version": "7.7.0",
       "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-7.7.0.tgz",
@@ -44655,6 +44669,7 @@
         "@overleaf/stream-utils": "*",
         "@phosphor-icons/react": "^2.1.7",
         "@slack/webhook": "^7.0.2",
+        "@stripe/react-stripe-js": "^3.9.0",
         "@stripe/stripe-js": "^7.7.0",
         "@xmldom/xmldom": "^0.7.13",
         "accepts": "^1.3.7",

+ 16 - 0
services/web/frontend/js/shared/utils/currency.ts

@@ -26,3 +26,19 @@ export function formatCurrency(
 
   return `${currency} ${amount}`
 }
+
+export function convertToMinorUnits(amount: number, currency: string): number {
+  const isNoCentsCurrency = ['clp', 'jpy', 'krw', 'vnd'].includes(
+    currency.toLowerCase()
+  )
+
+  // Determine the multiplier based on currency
+  let multiplier = 100 // default for most currencies (2 decimal places)
+
+  if (isNoCentsCurrency) {
+    multiplier = 1 // no decimal places
+  }
+
+  // Convert and round to an integer
+  return Math.round(amount * multiplier)
+}

+ 4 - 0
services/web/frontend/js/utils/meta.ts

@@ -57,6 +57,7 @@ import { Subscription as ProjectDashboardSubscription } from '../../../types/pro
 import { ThirdPartyIds } from '../../../types/third-party-ids'
 import { Publisher } from '../../../types/subscription/dashboard/publisher'
 import { SubscriptionChangePreview } from '../../../types/subscription/subscription-change-preview'
+import { SubscriptionCreationPreview } from '../../../types/subscription/subscription-creation-preview'
 import { DefaultNavbarMetadata } from '@/shared/components/types/default-navbar-metadata'
 import { FooterMetadata } from '@/shared/components/types/footer-metadata'
 import type { ScriptLogType } from '../../../modules/admin-panel/frontend/js/features/script-logs/script-log'
@@ -270,6 +271,8 @@ export interface Meta {
   'ol-ssoErrorMessage': string
   'ol-ssoInitPath': string
   'ol-stripeAccountId': string
+  'ol-stripePublicKeyUK': string
+  'ol-stripePublicKeyUS': string
   'ol-stripeSubscriptionData': {
     customerId: string
     subscriptionState: string | null
@@ -277,6 +280,7 @@ export interface Meta {
   }
   'ol-subscription': any // TODO: mixed types, split into two fields
   'ol-subscriptionChangePreview': SubscriptionChangePreview
+  'ol-subscriptionCreationPreview': SubscriptionCreationPreview
   'ol-subscriptionFeatures': {
     managedUsers?: boolean
     groupSSO?: boolean

+ 1 - 0
services/web/package.json

@@ -94,6 +94,7 @@
     "@overleaf/stream-utils": "*",
     "@phosphor-icons/react": "^2.1.7",
     "@slack/webhook": "^7.0.2",
+    "@stripe/react-stripe-js": "^3.9.0",
     "@stripe/stripe-js": "^7.7.0",
     "@xmldom/xmldom": "^0.7.13",
     "accepts": "^1.3.7",

+ 4 - 2
services/web/types/subscription/dashboard/subscription.ts

@@ -20,10 +20,12 @@ export type PurchasingAddOnCode = {
   code: string
 }
 
-type PaymentProviderCoupon = {
+export type PaymentProviderCoupon = {
   code: string
   name: string
-  description: string
+  description?: string
+  isSingleUse?: boolean
+  discountMonths?: number | null
 }
 
 type PaymentProviderRecord = {

+ 16 - 14
services/web/types/subscription/subscription-change-preview.ts

@@ -1,3 +1,18 @@
+export type ImmediateCharge = {
+  subtotal: number
+  tax: number
+  total: number
+  discount: number
+  lineItems: {
+    planCode: string | null | undefined
+    description: string
+    subtotal: number
+    discount: number
+    tax: number
+    isAiAssist: boolean
+  }[]
+}
+
 export type SubscriptionChangePreview = {
   change: SubscriptionChangeDescription
   currency: string
@@ -6,20 +21,7 @@ export type SubscriptionChangePreview = {
   nextPlan: {
     annual: boolean
   }
-  immediateCharge: {
-    subtotal: number
-    tax: number
-    total: number
-    discount: number
-    lineItems: {
-      planCode: string | null | undefined
-      description: string
-      subtotal: number
-      discount: number
-      tax: number
-      isAiAssist: boolean
-    }[]
-  }
+  immediateCharge: ImmediateCharge
   nextInvoice: {
     date: string
     plan: {

+ 12 - 0
services/web/types/subscription/subscription-creation-preview.ts

@@ -0,0 +1,12 @@
+import { ImmediateCharge } from './subscription-change-preview'
+import { PaymentProviderCoupon } from './dashboard/subscription'
+import { Plan } from './plan'
+
+export type SubscriptionCreationPreview = {
+  immediateCharge: ImmediateCharge
+  taxRate: number
+  billingCycleInterval: 'month' | 'year'
+  coupon: PaymentProviderCoupon
+  trialLength: number | null
+  plan: Plan
+}