PageSourceSearch

https://www.text-turbo.com/assets/landing/paddle_checkout-68b9acb3…71e57d6554dd083b2bffb4d22892c9dc16579e6f.js

js text-turbo.com collected 2026-10-02 01:45:49 UTC 4,765 bytes, 144 lines download raw bytes

1(() => {
2  function getConfig() {
3    const sdk = document.getElementById('paddle-sdk');
4    if (!sdk) return null;
5    return {
6      token: sdk.dataset.paddleToken,
7      environment: sdk.dataset.paddleEnvironment,
8      successUrl: sdk.dataset.paddleSuccessUrl
9    };
10  }
11
12  function initPaddle(config) {
13    if (!window.Paddle || !config || !config.token) return false;
14    if (config.environment === 'sandbox') {
15      window.Paddle.Environment.set('sandbox');
16    }
17    window.Paddle.Setup({ token: config.token });
18    return true;
19  }
20
21  function getSelectedPlan() {
22    const toggle = document.getElementById('billing-toggle');
23    return (toggle && toggle.checked) ? 'annual' : 'monthly';
24  }
25
26  function getLocale() {
27    return (document.documentElement.lang || 'en').toLowerCase().slice(0, 2);
28  }
29
30  async function launchCheckout(config, priceId, plan, opts = {}) {
31    const locale = opts.locale || getLocale();
32    const customData = {
33      plan: plan === 'annual' ? 'proAnnual' : 'proMonthly',
34      locale
35    };
36    if (opts.userId) customData.userId = opts.userId;
37
38    const resp = await fetch('/api/v1/checkouts/create_session', {
39      method: 'POST',
40      headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
41      body: JSON.stringify({ price_id: priceId, custom_data: customData })
42    });
43    const data = await resp.json();
44    if (!data.transaction_id) throw new Error(data.error || 'Failed to create transaction');
45
46    window.Paddle.Checkout.open({
47      transactionId: data.transaction_id,
48      settings: {
49        displayMode: 'overlay',
50        theme: 'light',
51        locale,
52        successUrl: withTransaction(config.successUrl, data.transaction_id)
53      }
54    });
55  }
56
57  // Embed our own transaction id so the success page can find the license
58  // without relying on Paddle's `_ptxn` (which is not reliably carried to
59  // successUrl in the overlay flow).
60  function withTransaction(url, transactionId) {
61    if (!url || !transactionId) return url;
62    const sep = url.indexOf('?') === -1 ? '?' : '&';
63    return url + sep + 'txn=' + encodeURIComponent(transactionId);
64  }
65
66  function makeClickHandler(config) {
67    return async (event) => {
68      event.preventDefault();
69      const button = event.currentTarget;
70      const plan = getSelectedPlan();
71      const priceId = plan === 'annual' ? button.dataset.priceAnnual : button.dataset.priceMonthly;
72      if (!priceId) {
73        console.error('[Paddle] Missing price ID for plan:', plan);
74        return;
75      }
76
77      button.disabled = true;
78      const originalText = button.textContent;
79      button.textContent = '...';
80
81      try {
82        await launchCheckout(config, priceId, plan);
83      } catch (err) {
84        console.error('[Paddle] Checkout error:', err);
85        alert('Could not start checkout. Please try again or contact support.');
86      } finally {
87        button.disabled = false;
88        button.textContent = originalText;
89      }
90    };
91  }
92
93  function autoLaunchFromUrl(config) {
94    const params = new URLSearchParams(window.location.search);
95    if (params.get('upgrade') !== 'pro') return;
96
97    const plan = params.get('plan') === 'annual' ? 'annual' : 'monthly';
98    const userId = params.get('user_id') || undefined;
99    const locale = params.get('locale') || undefined;
100
101    const button = document.querySelector('[data-paddle-checkout]');
102    if (!button) {
103      console.error('[Paddle] Auto-launch: Pro button not found');
104      return;
105    }
106    const priceId = plan === 'annual' ? button.dataset.priceAnnual : button.dataset.priceMonthly;
107    if (!priceId) {
108      console.error('[Paddle] Auto-launch: Missing price ID for plan:', plan);
109      return;
110    }
111
112    const toggle = document.getElementById('billing-toggle');
113    if (toggle) {
114      toggle.checked = (plan === 'annual');
115      toggle.dispatchEvent(new Event('change', { bubbles: true }));
116    }
117
118    history.replaceState({}, '', window.location.pathname + window.location.hash);
119
120    setTimeout(() => {
121      launchCheckout(config, priceId, plan, { userId, locale })
122        .catch((err) => {
123          console.error('[Paddle] Auto-launch error:', err);
124          alert('Could not start checkout. Please scroll to the pricing section and click "Upgrade to Pro".');
125        });
126    }, 100);
127  }
128
129  function ready(fn) {
130    if (document.readyState !== 'loading') fn();
131    else document.addEventListener('DOMContentLoaded', fn);
132  }
133
134  ready(() => {
135    const config = getConfig();
136    if (!config) return;
137    initPaddle(config);
138    const handler = makeClickHandler(config);
139    document.querySelectorAll('[data-paddle-checkout]').forEach((btn) => {
140      btn.addEventListener('click', handler);
141    });
142    autoLaunchFromUrl(config);
143  });
144})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.