mirror of
https://github.com/i701/sarlink-portal.git
synced 2025-07-07 12:46:30 +00:00
feat: implement topup functionality with create, get, and cancel operations ✨
This commit is contained in:
@ -1,25 +1,31 @@
|
|||||||
"use server";
|
"use server";
|
||||||
|
|
||||||
|
import { revalidatePath } from "next/cache";
|
||||||
|
import { getServerSession } from "next-auth";
|
||||||
import { authOptions } from "@/app/auth";
|
import { authOptions } from "@/app/auth";
|
||||||
import type {
|
import type {
|
||||||
ApiError,
|
ApiError,
|
||||||
ApiResponse,
|
ApiResponse,
|
||||||
NewPayment,
|
NewPayment,
|
||||||
Payment,
|
Payment,
|
||||||
|
Topup
|
||||||
} from "@/lib/backend-types";
|
} from "@/lib/backend-types";
|
||||||
|
import type { TopupResponse } from "@/lib/types";
|
||||||
import type { User } from "@/lib/types/user";
|
import type { User } from "@/lib/types/user";
|
||||||
import { checkSession } from "@/utils/session";
|
import { handleApiResponse } from "@/utils/tryCatch";
|
||||||
import { handleApiResponse, tryCatch } from "@/utils/tryCatch";
|
|
||||||
import { getServerSession } from "next-auth";
|
type GenericGetResponseProps = {
|
||||||
import { revalidatePath } from "next/cache";
|
offset?: number;
|
||||||
import { redirect } from "next/navigation";
|
limit?: number;
|
||||||
|
page?: number;
|
||||||
|
[key: string]: string | number | undefined;
|
||||||
|
};
|
||||||
|
|
||||||
export async function createPayment(data: NewPayment) {
|
export async function createPayment(data: NewPayment) {
|
||||||
const session = await getServerSession(authOptions);
|
const session = await getServerSession(authOptions);
|
||||||
console.log("data", data);
|
console.log("data", data);
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
`${
|
`${process.env.SARLINK_API_BASE_URL // });
|
||||||
process.env.SARLINK_API_BASE_URL // });
|
|
||||||
}/api/billing/payment/`,
|
}/api/billing/payment/`,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@ -43,6 +49,22 @@ export async function createPayment(data: NewPayment) {
|
|||||||
return payment;
|
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 }) {
|
export async function getPayment({ id }: { id: string }) {
|
||||||
const session = await getServerSession(authOptions);
|
const session = await getServerSession(authOptions);
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
@ -92,6 +114,67 @@ export async function getPayments() {
|
|||||||
return data;
|
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 }) {
|
export async function cancelPayment({ id }: { id: string }) {
|
||||||
const session = await getServerSession(authOptions);
|
const session = await getServerSession(authOptions);
|
||||||
const response = await fetch(
|
const response = await fetch(
|
||||||
@ -142,6 +225,25 @@ export async function verifyPayment({ id, method }: UpdatePayment) {
|
|||||||
return handleApiResponse<Payment>(response, "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() {
|
export async function getProfile() {
|
||||||
const session = await getServerSession(authOptions);
|
const session = await getServerSession(authOptions);
|
||||||
|
@ -57,6 +57,20 @@ export interface ApiError {
|
|||||||
detail?: string;
|
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 {
|
export interface Payment {
|
||||||
id: string;
|
id: string;
|
||||||
devices: Device[];
|
devices: Device[];
|
||||||
|
14
lib/types.ts
14
lib/types.ts
@ -1,9 +1,19 @@
|
|||||||
export type TopupType = {
|
export type TopupType = {
|
||||||
amount: number;
|
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 {
|
interface IpAddress {
|
||||||
ip: string;
|
ip: string;
|
||||||
mask: number;
|
mask: number;
|
||||||
|
Reference in New Issue
Block a user