feat: implement topup functionality with create, get, and cancel operations

This commit is contained in:
2025-07-04 23:06:13 +05:00
parent 89a35a9674
commit ee461bbbf8
3 changed files with 135 additions and 9 deletions

View File

@ -1,25 +1,31 @@
"use server";
import { revalidatePath } from "next/cache";
import { getServerSession } from "next-auth";
import { authOptions } from "@/app/auth";
import type {
ApiError,
ApiResponse,
NewPayment,
Payment,
Topup
} from "@/lib/backend-types";
import type { TopupResponse } from "@/lib/types";
import type { User } from "@/lib/types/user";
import { checkSession } from "@/utils/session";
import { handleApiResponse, tryCatch } from "@/utils/tryCatch";
import { getServerSession } from "next-auth";
import { revalidatePath } from "next/cache";
import { redirect } from "next/navigation";
import { handleApiResponse } from "@/utils/tryCatch";
type GenericGetResponseProps = {
offset?: number;
limit?: number;
page?: number;
[key: string]: string | number | undefined;
};
export async function createPayment(data: NewPayment) {
const session = await getServerSession(authOptions);
console.log("data", data);
const response = await fetch(
`${
process.env.SARLINK_API_BASE_URL // });
`${process.env.SARLINK_API_BASE_URL // });
}/api/billing/payment/`,
{
method: "POST",
@ -43,6 +49,22 @@ export async function createPayment(data: NewPayment) {
return payment;
}
export async function createTopup(data: { amount: number }) {
const session = await getServerSession(authOptions);
const response = await fetch(
`${process.env.SARLINK_API_BASE_URL}/api/billing/topup/`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Token ${session?.apiToken}`,
},
body: JSON.stringify(data),
},
);
return handleApiResponse<Topup>(response, "createTopup");
}
export async function getPayment({ id }: { id: string }) {
const session = await getServerSession(authOptions);
const response = await fetch(
@ -92,6 +114,67 @@ export async function getPayments() {
return data;
}
export async function getTopups(params: GenericGetResponseProps) {
// Build query string from all defined params
const query = Object.entries(params)
.filter(([_, value]) => value !== undefined && value !== "")
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
.join("&");
const session = await getServerSession(authOptions);
const response = await fetch(
`${process.env.SARLINK_API_BASE_URL}/api/billing/topup/?${query}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Token ${session?.apiToken}`,
},
},
);
return handleApiResponse<ApiResponse<Topup>>(response, "getTopups");
}
export async function getTopup({ id }: { id: string }) {
const session = await getServerSession(authOptions);
const response = await fetch(
`${process.env.SARLINK_API_BASE_URL}/api/billing/topup/${id}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Token ${session?.apiToken}`,
},
},
);
return handleApiResponse<Topup>(response, "getTopup");
}
export async function cancelTopup({ id }: { id: string }) {
const session = await getServerSession(authOptions);
const response = await fetch(
`${process.env.SARLINK_API_BASE_URL}/api/billing/topup/${id}/delete/`,
{
method: "DELETE",
headers: {
"Content-Type": "application/json",
Authorization: `Token ${session?.apiToken}`,
},
},
);
if (!response.ok) {
const errorData = (await response.json()) as ApiError;
const errorMessage =
errorData.message || errorData.detail || "An error occurred.";
const error = new Error(errorMessage);
(error as ApiError & { details?: ApiError }).details = errorData; // Attach the errorData to the error object
throw error;
}
return { message: "Topup successfully canceled." };
}
export async function cancelPayment({ id }: { id: string }) {
const session = await getServerSession(authOptions);
const response = await fetch(
@ -142,6 +225,25 @@ export async function verifyPayment({ id, method }: UpdatePayment) {
return handleApiResponse<Payment>(response, "updatePayment");
}
type UpdateTopupPayment = {
id: string;
};
export async function verifyTopupPayment({ id }: UpdateTopupPayment) {
const session = await getServerSession(authOptions);
const response = await fetch(
`${process.env.SARLINK_API_BASE_URL}/api/billing/topup/${id}/verify/`,
{
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: `Token ${session?.apiToken}`,
},
},
);
revalidatePath("/top-ups/[topupId]", "page");
return handleApiResponse<TopupResponse>(response, "verifyTopupPayment");
}
export async function getProfile() {
const session = await getServerSession(authOptions);

View File

@ -57,6 +57,20 @@ export interface ApiError {
detail?: string;
}
export interface Topup {
id: string;
amount: number;
user: Pick<User, "id" | "id_card" | "mobile"> & {
name: string;
};
paid: boolean;
mib_reference: string | null;
expires_at: string;
is_expired: boolean;
created_at: string;
updated_at: string;
}
export interface Payment {
id: string;
devices: Device[];

View File

@ -1,9 +1,19 @@
export type TopupType = {
amount: number;
userId: string;
paid: boolean;
};
export type Transaction = {
ref: string;
sourceBank: string;
trxDate: string;
}
export type TopupResponse = {
status: boolean;
message: string;
transaction?: Transaction
}
interface IpAddress {
ip: string;
mask: number;