recurly-pricing.ts 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import { SubscriptionPricingState } from '@recurly/recurly-js'
  2. import { PriceForDisplayData } from '../../../../../types/subscription/plan'
  3. import { currencies, CurrencyCode } from '../data/currency'
  4. import { getRecurlyGroupPlanCode } from './recurly-group-plan-code'
  5. function queryRecurlyPlanPrice(planCode: string, currency: CurrencyCode) {
  6. return new Promise(resolve => {
  7. recurly.Pricing.Subscription()
  8. .plan(planCode, { quantity: 1 })
  9. .currency(currency)
  10. .catch(function (error) {
  11. console.error(error)
  12. })
  13. .done(response => {
  14. if (response) {
  15. resolve(response)
  16. } else {
  17. resolve(undefined)
  18. }
  19. })
  20. })
  21. }
  22. function priceToWithCents(price: number) {
  23. return price % 1 !== 0 ? price.toFixed(2) : price
  24. }
  25. export function formatPriceForDisplayData(
  26. price: string,
  27. taxRate: number,
  28. currencyCode: CurrencyCode
  29. ): PriceForDisplayData {
  30. const currencySymbol = currencies[currencyCode]
  31. const totalPriceExTax = parseFloat(price)
  32. let taxAmount = totalPriceExTax * taxRate
  33. if (isNaN(taxAmount)) {
  34. taxAmount = 0
  35. }
  36. const totalWithTax = totalPriceExTax + taxAmount
  37. return {
  38. totalForDisplay: `${currencySymbol}${priceToWithCents(totalWithTax)}`,
  39. totalAsNumber: totalWithTax,
  40. subtotal: `${currencySymbol}${totalPriceExTax.toFixed(2)}`,
  41. tax: `${currencySymbol}${taxAmount.toFixed(2)}`,
  42. includesTax: taxAmount !== 0,
  43. }
  44. }
  45. function getPerUserDisplayPrice(
  46. totalPrice: number,
  47. currencySymbol: string,
  48. size: string
  49. ): string {
  50. return `${currencySymbol}${priceToWithCents(totalPrice / parseInt(size))}`
  51. }
  52. export async function loadDisplayPriceWithTaxPromise(
  53. planCode: string,
  54. currencyCode: CurrencyCode,
  55. taxRate: number
  56. ) {
  57. if (!recurly) return
  58. const price = (await queryRecurlyPlanPrice(
  59. planCode,
  60. currencyCode
  61. )) as SubscriptionPricingState['price']
  62. if (price)
  63. return formatPriceForDisplayData(price.next.total, taxRate, currencyCode)
  64. }
  65. export async function loadGroupDisplayPriceWithTaxPromise(
  66. groupPlanCode: string,
  67. currencyCode: CurrencyCode,
  68. taxRate: number,
  69. size: string,
  70. usage: string
  71. ) {
  72. if (!recurly) return
  73. const planCode = getRecurlyGroupPlanCode(groupPlanCode, size, usage)
  74. const price = await loadDisplayPriceWithTaxPromise(
  75. planCode,
  76. currencyCode,
  77. taxRate
  78. )
  79. if (price) {
  80. const currencySymbol = currencies[currencyCode]
  81. price.perUserDisplayPrice = getPerUserDisplayPrice(
  82. price.totalAsNumber,
  83. currencySymbol,
  84. size
  85. )
  86. }
  87. return price
  88. }