Skip to content

Commit d73d9fe

Browse files
Sebastian Fellner 💯Sebastian Fellner 💯
authored andcommitted
fix: restore PayPal payment flows
1 parent e41c4bb commit d73d9fe

6 files changed

Lines changed: 112 additions & 22 deletions

File tree

components/ChatVisualization/Payment.vue

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ export default {
1919
type: Number,
2020
},
2121
},
22-
data() {
23-
return {};
22+
setup() {
23+
const config = useRuntimeConfig();
24+
return { paypalClientId: config.public.paypalClientId };
2425
},
2526
mounted() {
2627
this.loadPayPalScript();
@@ -34,20 +35,24 @@ export default {
3435
3536
const script = document.createElement("script");
3637
script.id = "paypal-sdk";
37-
script.src =
38-
"https://www.paypal.com/sdk/js?currency=" +
39-
this.currency +
40-
"&client-id=" +
41-
this.$config.paypalClientId;
38+
const params = new URLSearchParams({
39+
currency: this.currency,
40+
"client-id": this.paypalClientId,
41+
});
42+
script.src = `https://www.paypal.com/sdk/js?${params}`;
4243
script.defer = true;
4344
script.addEventListener("load", () => this.initPayPalButton(this), {
4445
once: true,
4546
});
47+
script.addEventListener(
48+
"error",
49+
(error) => this.$emit("onError", error),
50+
{ once: true }
51+
);
4652
document.head.appendChild(script);
4753
},
4854
initPayPalButton(context) {
49-
// eslint-disable-next-line no-undef
50-
paypal
55+
window.paypal
5156
.Buttons({
5257
style: {
5358
size: "small",

components/ChatVisualization/PdfDownloadPopup.vue

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
<!-- Download dialog -->
2626
<v-dialog v-model="showDownloadPopup" width="550">
27-
<template #activator="{ on, attrs }">
27+
<template #activator="{ props: activatorProps }">
2828
<!-- Pricing Section -->
2929
<v-btn v-if="isValidSubscription" @click="downloadFull" color="success">
3030
<span v-html="$t('downloadNow')"></span>
@@ -72,9 +72,8 @@
7272
<v-btn
7373
color="success"
7474
class="mt-3 mb-4"
75-
v-bind="attrs"
75+
v-bind="activatorProps"
7676
@click="gtagEvent('full_pdf_pressed', GTAG_PAYMENT)"
77-
v-on="on"
7877
>
7978
<v-icon class="mr-1">mdi-download</v-icon>
8079
<span v-html="$t('downloadFullChatPDF')"></span>

components/SubscribeBtn.vue

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
<script>
1414
import { GTAG_PAYMENT, gtagEvent } from "~/utils/gtagValues";
1515
export default {
16+
setup() {
17+
const config = useRuntimeConfig();
18+
return { paypalClientId: config.public.paypalClientId };
19+
},
1620
data() {
1721
return {
1822
isLoading: false,
@@ -23,16 +27,23 @@ export default {
2327
if (this.isLoading) return;
2428
gtagEvent("subscription_pressed", GTAG_PAYMENT);
2529
this.isLoading = true;
26-
const response = await this.$firebase.callFunction("helloworld", {
27-
client_id: this.$config.paypalClientId,
28-
});
29-
// call fetch with https://www.sandbox.paypal.com/webapps/billing/subscriptions?ba_token=BA-2MW88471JV556644J
30-
if (!response.data.approveLink) {
31-
alert("Error opening paypal: " + response.error);
30+
31+
try {
32+
const response = await this.$firebase.callFunction("helloworld", {
33+
client_id: this.paypalClientId,
34+
});
35+
const approveLink = response.data?.approveLink;
36+
if (!approveLink) {
37+
throw new Error(response.data?.error || "No approval link returned");
38+
}
39+
40+
window.location.assign(approveLink);
41+
} catch (error) {
42+
console.error("Error opening PayPal", error);
43+
this.$sentry?.captureException(error);
44+
alert("Error opening PayPal. Please try again.");
3245
this.isLoading = false;
3346
}
34-
35-
location.href = response.data.approveLink;
3647
},
3748
},
3849
};

components/SubscriptionChecker.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
<script>
44
export default {
55
props: ["email", "id"],
6+
setup() {
7+
const config = useRuntimeConfig();
8+
return { paypalClientId: config.public.paypalClientId };
9+
},
610
data() {
711
return {
812
subscription_id: null,
@@ -56,7 +60,7 @@ export default {
5660
"checksubscriberstatus",
5761
{
5862
...data,
59-
client_id: this.$config.paypalClientId,
63+
client_id: this.paypalClientId,
6064
}
6165
);
6266

pages/subscribe.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ import { getSubscriptionParams } from "~/utils/subscription";
5454
export default {
5555
name: "Subscriptions",
5656
components: { SubscriptionChecker },
57+
setup() {
58+
const config = useRuntimeConfig();
59+
return { paypalClientId: config.public.paypalClientId };
60+
},
5761
data() {
5862
return {
5963
ba_token: null,
@@ -90,7 +94,7 @@ export default {
9094
"checksubscriberstatus",
9195
{
9296
...data,
93-
client_id: this.$config.paypalClientId,
97+
client_id: this.paypalClientId,
9498
}
9599
);
96100

tests/e2e/home.spec.js

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,25 @@ test("analyzes the example chat without uploading its contents", async ({
2828
page,
2929
}) => {
3030
const requests = [];
31+
let paypalSdkUrl;
3132
page.on("request", (request) => requests.push(request));
33+
await page.route("https://www.paypal.com/sdk/js?**", async (route) => {
34+
paypalSdkUrl = new URL(route.request().url());
35+
await route.fulfill({
36+
contentType: "text/javascript",
37+
body: `
38+
window.paypal = {
39+
Buttons: () => ({
40+
render: (selector) => {
41+
document.querySelector(selector).innerHTML =
42+
'<button type="button">Pay with PayPal</button>';
43+
return Promise.resolve();
44+
}
45+
})
46+
};
47+
`,
48+
});
49+
});
3250

3351
await page.locator("#uploadmytextfile").setInputFiles(exampleChat);
3452

@@ -50,6 +68,15 @@ test("analyzes the example chat without uploading its contents", async ({
5068
.getByRole("button", { name: /Download free preview PDF/i })
5169
.click();
5270
await downloadPromise;
71+
72+
await page.getByRole("button", { name: /Download full chat PDF/i }).click();
73+
await expect(page.getByText("Nice!!", { exact: true })).toBeVisible();
74+
await expect(
75+
page.getByRole("button", { name: "Pay with PayPal" })
76+
).toBeVisible();
77+
expect(paypalSdkUrl.origin).toBe("https://www.paypal.com");
78+
expect(paypalSdkUrl.searchParams.get("currency")).toBe("EUR");
79+
expect(paypalSdkUrl.searchParams.get("client-id")).toBeTruthy();
5380
});
5481

5582
test("switches to a localized route", async ({ page }) => {
@@ -61,6 +88,46 @@ test("switches to a localized route", async ({ page }) => {
6188
).toBeVisible();
6289
});
6390

91+
test("starts a subscription through the Firebase PayPal endpoint", async ({
92+
page,
93+
}) => {
94+
let functionRequest;
95+
await page.route("**/helloworld", async (route) => {
96+
const request = route.request();
97+
if (request.method() === "OPTIONS") {
98+
await route.fulfill({
99+
status: 204,
100+
headers: {
101+
"access-control-allow-origin": "*",
102+
"access-control-allow-headers": "content-type",
103+
},
104+
});
105+
return;
106+
}
107+
108+
functionRequest = request;
109+
await route.fulfill({
110+
contentType: "application/json",
111+
headers: { "access-control-allow-origin": "*" },
112+
body: JSON.stringify({
113+
data: { approveLink: "https://paypal.test/approve" },
114+
}),
115+
});
116+
});
117+
await page.route("https://paypal.test/approve", (route) =>
118+
route.fulfill({ contentType: "text/html", body: "PayPal approval" })
119+
);
120+
121+
await page.goto("/subscribe");
122+
await page.getByRole("button", { name: "Subscribe Now" }).click();
123+
124+
await expect(page).toHaveURL("https://paypal.test/approve");
125+
expect(functionRequest.url()).toBe(
126+
"https://us-central1-whatsanalyze-80665.cloudfunctions.net/helloworld"
127+
);
128+
expect(functionRequest.postDataJSON().data.client_id).toBeTruthy();
129+
});
130+
64131
test("renders migrated markdown content", async ({ page }) => {
65132
await page.goto("/how-to-export-your-whatsapp-chat");
66133

0 commit comments

Comments
 (0)