After the free trial, we ask a user to buy a subscription. To get monthly and yearly prices, I have useMembershipPricesQuery
. First, we want to get Paddle SDK. I have a post about loading third-party scripts - you can reade it here.
import { MembershipPeriod } from "membership"
import { usePaddleSdk } from "membership/paddle/hooks/usePaddleSdk"
import { PaddleProductCode } from "membership/paddle/PaddleProductCode"
import { PaddleSdk, PaddleSdkProductPrice } from "membership/paddle/PaddleSdk"
import { ProductPlanPrice } from "membership/ProductPlanPrice"
import { useQuery } from "react-query"
const getPaddleProductPrice = async (
Paddle: PaddleSdk,
product: number
): Promise<ProductPlanPrice> => {
const { price }: PaddleSdkProductPrice = await new Promise(resolve =>
Paddle.Product.Prices(product, resolve)
)
const { gross } = price
const index = gross.search(/\d/)
const currency = gross.slice(0, index)
const amountAsString = gross.slice(index).replace(",", "")
const amount = Number(amountAsString)
return { currency, amount }
}
export const membershipPricesQueryKey = "membershipPrices"
export const useMembershipPricesQuery = () => {
const { data: paddleSdk } = usePaddleSdk()
return useQuery(
membershipPricesQueryKey,
async () => {
const [monthly, yearly] = await Promise.all(
[PaddleProductCode.monthly, PaddleProductCode.yearly].map(product =>
getPaddleProductPrice(paddleSdk as PaddleSdk, product)
)
)
return {
monthly,
yearly,
} as Record<MembershipPeriod, ProductPlanPrice>
},
{
keepPreviousData: true,
refetchOnWindowFocus: false,
refetchOnMount: false,
refetchOnReconnect: false,
staleTime: Infinity,
enabled: !!paddleSdk,
}
)
}
Once we have the SDK, we can use it to get prices for monthly and yearly subscriptions. We iterate over a record with product codes and call getPaddleProductPrice
. Since Paddle doesn't have type definitions, I fill up the PaddleSdk
interface as I go. We call the prices method to get the product price and wrap the call with a promise since Paddle uses callbacks.
export interface PaddleSdkProductPrice {
price: {
gross: string
}
}
interface PaddleSdkSetupParams {
vendor: number
}
export interface CheckoutSuccessInfo {
checkout: {
id: string
}
product: {
id: number
}
user: {
id: string
}
}
interface PaddleSdkOpenCheckoutParams {
method: string
product: number
allowQuantity: boolean
disableLogout: boolean
frameTarget: string
successCallback: (info: CheckoutSuccessInfo) => void
closeCallback: () => void
frameInitialHeight: number
loadCallback: () => void
email?: string | null
passthrough: string
override: any
frameStyle: string
}
export interface PaddleSdk {
Product: {
Prices: (
code: number,
resolve: (prices: PaddleSdkProductPrice) => void
) => void
}
Setup: (params: PaddleSdkSetupParams) => void
Checkout: {
open: (params: PaddleSdkOpenCheckoutParams) => void
}
Environment: {
set: (mode: "sandbox") => void
}
Order: {
details: (checkoutId: string, callback: (info: any) => void) => void
}
}
We use a regular expression to separate a number from a currency name. Since Paddle formats big numbers with commas, we need to remove them.
Top comments (0)