Preserve Zerodha callback state in frontend
This commit is contained in:
parent
ccaa363d48
commit
bc1ea376a4
@ -7,7 +7,7 @@
|
|||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"typecheck": "tsc --noEmit",
|
"typecheck": "tsc --noEmit",
|
||||||
"test": "npm run typecheck && tsx --test src/pages/admin/api.test.ts",
|
"test": "npm run typecheck && tsx --test src/pages/admin/api.test.ts src/pages/zerodhaCallbackUtils.test.ts",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"start": "vite --host 0.0.0.0 --port 3001"
|
"start": "vite --host 0.0.0.0 --port 3001"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -3,28 +3,16 @@ import { Loader2 } from "lucide-react";
|
|||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { apiRequest } from "@/lib/queryClient";
|
import { apiRequest } from "@/lib/queryClient";
|
||||||
import PageEnter from "@/components/ui/page-enter";
|
import PageEnter from "@/components/ui/page-enter";
|
||||||
|
import {
|
||||||
|
buildZerodhaBackendCallbackUrl,
|
||||||
|
parseZerodhaCallbackParams,
|
||||||
|
type ZerodhaCallbackParams,
|
||||||
|
} from "./zerodhaCallbackUtils";
|
||||||
|
|
||||||
const CALLBACK_STORAGE_KEY = "zerodha:callback";
|
const CALLBACK_STORAGE_KEY = "zerodha:callback";
|
||||||
const RETURN_PATH = "/portfolio";
|
const RETURN_PATH = "/portfolio";
|
||||||
|
|
||||||
type CallbackParams = {
|
const parseParams = (): ZerodhaCallbackParams => parseZerodhaCallbackParams(window.location.search);
|
||||||
flow: string;
|
|
||||||
status: string;
|
|
||||||
requestToken: string;
|
|
||||||
error: string;
|
|
||||||
errorDescription: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const parseParams = (): CallbackParams => {
|
|
||||||
const params = new URLSearchParams(window.location.search);
|
|
||||||
return {
|
|
||||||
flow: (params.get("flow") || "").trim(),
|
|
||||||
status: (params.get("status") || "").trim(),
|
|
||||||
requestToken: (params.get("request_token") || "").trim(),
|
|
||||||
error: (params.get("error") || params.get("error_type") || "").trim(),
|
|
||||||
errorDescription: (params.get("error_description") || "").trim(),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function ZerodhaCallback() {
|
export default function ZerodhaCallback() {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -50,9 +38,12 @@ export default function ZerodhaCallback() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const callbackPath =
|
if (!params.state) {
|
||||||
params.flow === "reconnect" ? "/broker/callback" : "/broker/zerodha/callback";
|
finalize("error", "Missing callback state in the redirect URL.");
|
||||||
const url = `${callbackPath}?request_token=${encodeURIComponent(params.requestToken)}`;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = buildZerodhaBackendCallbackUrl(params);
|
||||||
apiRequest("GET", url)
|
apiRequest("GET", url)
|
||||||
.then(() => finalize("success"))
|
.then(() => finalize("success"))
|
||||||
.catch((err: any) => finalize("error", err?.message || "Unable to complete the login."));
|
.catch((err: any) => finalize("error", err?.message || "Unable to complete the login."));
|
||||||
|
|||||||
43
src/pages/zerodhaCallbackUtils.test.ts
Normal file
43
src/pages/zerodhaCallbackUtils.test.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import test from "node:test";
|
||||||
|
import assert from "node:assert/strict";
|
||||||
|
import {
|
||||||
|
buildZerodhaBackendCallbackUrl,
|
||||||
|
parseZerodhaCallbackParams,
|
||||||
|
} from "./zerodhaCallbackUtils";
|
||||||
|
|
||||||
|
test("parseZerodhaCallbackParams reads state from callback query", () => {
|
||||||
|
const parsed = parseZerodhaCallbackParams(
|
||||||
|
"?request_token=req-123&state=state-456&status=success&flow=reconnect",
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.equal(parsed.requestToken, "req-123");
|
||||||
|
assert.equal(parsed.state, "state-456");
|
||||||
|
assert.equal(parsed.status, "success");
|
||||||
|
assert.equal(parsed.flow, "reconnect");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("buildZerodhaBackendCallbackUrl forwards request token and state", () => {
|
||||||
|
const url = buildZerodhaBackendCallbackUrl({
|
||||||
|
flow: "connect",
|
||||||
|
status: "success",
|
||||||
|
requestToken: "req-123",
|
||||||
|
state: "state-456",
|
||||||
|
error: "",
|
||||||
|
errorDescription: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(url, "/broker/zerodha/callback?request_token=req-123&state=state-456");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("buildZerodhaBackendCallbackUrl uses reconnect callback route", () => {
|
||||||
|
const url = buildZerodhaBackendCallbackUrl({
|
||||||
|
flow: "reconnect",
|
||||||
|
status: "success",
|
||||||
|
requestToken: "req-123",
|
||||||
|
state: "state-456",
|
||||||
|
error: "",
|
||||||
|
errorDescription: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(url, "/broker/callback?request_token=req-123&state=state-456");
|
||||||
|
});
|
||||||
32
src/pages/zerodhaCallbackUtils.ts
Normal file
32
src/pages/zerodhaCallbackUtils.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
export type ZerodhaCallbackParams = {
|
||||||
|
flow: string;
|
||||||
|
status: string;
|
||||||
|
requestToken: string;
|
||||||
|
state: string;
|
||||||
|
error: string;
|
||||||
|
errorDescription: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function parseZerodhaCallbackParams(search: string): ZerodhaCallbackParams {
|
||||||
|
const params = new URLSearchParams(search);
|
||||||
|
return {
|
||||||
|
flow: (params.get("flow") || "").trim(),
|
||||||
|
status: (params.get("status") || "").trim(),
|
||||||
|
requestToken: (params.get("request_token") || "").trim(),
|
||||||
|
state: (params.get("state") || "").trim(),
|
||||||
|
error: (params.get("error") || params.get("error_type") || "").trim(),
|
||||||
|
errorDescription: (params.get("error_description") || "").trim(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildZerodhaBackendCallbackUrl(params: ZerodhaCallbackParams): string {
|
||||||
|
const callbackPath = params.flow === "reconnect" ? "/broker/callback" : "/broker/zerodha/callback";
|
||||||
|
const search = new URLSearchParams();
|
||||||
|
if (params.requestToken) {
|
||||||
|
search.set("request_token", params.requestToken);
|
||||||
|
}
|
||||||
|
if (params.state) {
|
||||||
|
search.set("state", params.state);
|
||||||
|
}
|
||||||
|
return `${callbackPath}?${search.toString()}`;
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user