verify payment

This commit is contained in:
hamid zarghami
2025-12-21 12:21:43 +03:30
parent 34f30f1658
commit 59f79f2a3e
4 changed files with 235 additions and 41 deletions
+128 -41
View File
@@ -2,68 +2,155 @@
import Button from '@/components/button/PrimaryButton';
import { ef } from '@/lib/helpers/utfNumbers';
import { CardTick } from 'iconsax-react';
import { CardTick, CloseCircle } from 'iconsax-react';
import { useParams, useRouter } from 'next/navigation';
import React from 'react'
import React, { useEffect, useState } from 'react'
import { useVerify } from '../hooks/useVerifyData';
import { toast } from '@/components/Toast';
import { VerifyData } from '../types/Types';
type Props = object
const formatDate = (dateString: string): string => {
const date = new Date(dateString);
return date.toLocaleDateString('fa-IR', {
year: 'numeric',
month: '2-digit',
day: '2-digit'
});
};
const formatTime = (dateString: string): string => {
const date = new Date(dateString);
return date.toLocaleTimeString('fa-IR', {
hour: '2-digit',
minute: '2-digit'
});
};
const formatPrice = (value: number): string => {
return value.toLocaleString('fa-IR');
};
export default function VerifyIndex({ }: Props) {
// const { t } = useTranslation('notifications')
const router = useRouter();
const params = useParams();
const name = params.name as string;
const urlparams = new URLSearchParams(window.location.search);
const authority = urlparams.get('Authority');
const id = params.id
const [verifyData, setVerifyData] = useState<VerifyData | null>(null);
const [isError, setIsError] = useState(false);
const { mutate: verify } = useVerify();
useEffect(() => {
if (authority && id) {
verify({ authority: authority as string, orderId: id as string }, {
onSuccess: (data) => {
toast('پرداخت موفقیت آمیز بود', 'success');
setVerifyData(data.data);
setIsError(false);
},
onError: () => {
toast('پرداخت ناموفق بوده', 'error');
setIsError(true);
}
});
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [authority, id]);
const amount = verifyData?.amount || verifyData?.order?.total || 0;
const paidAt = verifyData?.paidAt || '';
const cardPan = verifyData?.verifyResponse?.data?.card_pan || '';
const gateway = verifyData?.order?.paymentMethod?.description || verifyData?.gateway || '';
const referenceId = verifyData?.referenceId || '';
const formattedCardPan = cardPan || '';
return (
<div className='h-full bg-inherit relative flex flex-col lg:gap-4'>
<div className='flex-1 flex flex-col items-center justify-center'>
<div className='bg-container py-5 px-2 rounded-container shadow-lg w-full'>
<div className='items-center gap-2 bg-gray-50 rounded-2xl h-35 flex flex-col justify-center'>
<CardTick className='size-10 stroke-primary' variant='TwoTone' />
<h5 className='font-bold text-sm'>پرداخت موفق</h5>
<p className='text-sm mt-1 leading-5 text-disabled-text'>
{ef('مبلغ: 560,000 تومان')}
</p>
<div className={`items-center gap-2 rounded-2xl h-35 flex flex-col justify-center ${isError ? 'bg-red-50' : 'bg-gray-50'}`}>
{isError ? (
<CloseCircle className='size-10 stroke-red-500' variant='TwoTone' />
) : (
<CardTick className='size-10 stroke-primary' variant='TwoTone' />
)}
<h5 className={`font-bold text-sm ${isError ? 'text-red-600' : ''}`}>
{isError ? 'پرداخت ناموفق' : 'پرداخت موفق'}
</h5>
{!isError && verifyData && (
<p className='text-sm mt-1 leading-5 text-disabled-text'>
{ef(`مبلغ: ${formatPrice(amount)} تومان`)}
</p>
)}
</div>
<div className='mt-5 w-full text-sm2'>
<div className='flex justify-between items-center'>
<div className='font-medium text-disabled-text'>تاریخ:</div>
<div className='font-medium'>{ef('1401/05/08')}</div>
</div>
<hr className='border border-border my-3' />
{!isError && (
<div className='mt-5 w-full text-sm2'>
{paidAt && (
<>
<div className='flex justify-between items-center'>
<div className='font-medium text-disabled-text'>تاریخ:</div>
<div className='font-medium'>{ef(formatDate(paidAt))}</div>
</div>
<hr className='border border-border my-3' />
</>
)}
<div className='flex justify-between items-center'>
<div className='text-disabled-text'>ساعت:</div>
<div className=''>{ef('21:45')}</div>
</div>
<hr className='border border-border my-3' />
{paidAt && (
<>
<div className='flex justify-between items-center'>
<div className='text-disabled-text'>ساعت:</div>
<div className=''>{ef(formatTime(paidAt))}</div>
</div>
<hr className='border border-border my-3' />
</>
)}
<div className='flex justify-between items-center'>
<div className='text-disabled-text'>از کارت:</div>
<div className=''>{ef('6104 6647 **** 1147')}</div>
</div>
<hr className='border border-border my-3' />
{cardPan && (
<>
<div className='flex justify-between items-center'>
<div className='text-disabled-text'>از کارت:</div>
<div className=''>{ef(formattedCardPan)}</div>
</div>
<hr className='border border-border my-3' />
</>
)}
<div className='flex justify-between items-center'>
<div className='text-disabled-text'>درگاه پرداخت:</div>
<div className=''>{ef('درگاه پرداخت')}</div>
</div>
<hr className='border border-border my-3' />
{gateway && (
<>
<div className='flex justify-between items-center'>
<div className='text-disabled-text'>درگاه پرداخت:</div>
<div className=''>{gateway}</div>
</div>
<hr className='border border-border my-3' />
</>
)}
<div className='flex justify-between items-center'>
<div className='text-disabled-text'>شماره پیگیری:</div>
<div className=''>{ef('556284526')}</div>
{referenceId && (
<>
<div className='flex justify-between items-center'>
<div className='text-disabled-text'>شماره پیگیری:</div>
<div className=''>{ef(referenceId)}</div>
</div>
<hr className='border border-border my-3' />
</>
)}
</div>
<hr className='border border-border my-3' />
)}
<Button
className='mt-12'
onClick={() => router.push(`/${name}`)} // TODO: redirect to order
>
بازگشت
</Button>
</div>
<Button
className='mt-12'
onClick={() => router.push(`/${name}`)}
>
بازگشت
</Button>
</div>
</div>
</div>
@@ -0,0 +1,8 @@
import { useMutation } from "@tanstack/react-query";
import * as api from "../service/VerifyService";
export const useVerify = () => {
return useMutation({
mutationFn: api.verify,
});
};
@@ -0,0 +1,10 @@
import { api } from "@/config/axios";
import { VerifyType, VerifyResponse } from "../types/Types";
export const verify = async (params: VerifyType): Promise<VerifyResponse> => {
const { data } = await api.post<VerifyResponse>(
"/public/payments/verify",
params
);
return data;
};
@@ -0,0 +1,89 @@
import { BaseResponse } from "@/app/[name]/(Main)/types/Types";
export interface VerifyType {
authority: string;
orderId: string;
}
export interface VerifyOrderHistory {
status: string;
changedAt: string;
}
export interface VerifyPaymentMethod {
id: string;
createdAt: string;
updatedAt: string;
deletedAt: string | null;
restaurant: string;
method: string;
gateway: string;
description: string;
enabled: boolean;
order: number;
merchantId: string;
}
export interface VerifyOrder {
id: string;
createdAt: string;
updatedAt: string;
deletedAt: string | null;
user: string;
restaurant: string;
deliveryMethod: string;
userAddress: string | null;
carAddress: string | null;
paymentMethod: VerifyPaymentMethod;
orderNumber: number;
couponDiscount: number;
couponDetail: unknown | null;
itemsDiscount: number;
totalDiscount: number;
subTotal: number;
tax: number;
deliveryFee: number;
total: number;
totalItems: number;
description: string;
tableNumber: string;
status: string;
history: VerifyOrderHistory[];
}
export interface VerifyResponseData {
data: {
fee: number;
code: number;
wages: unknown | null;
ref_id: number;
message: string;
card_pan: string;
fee_type: string;
order_id: string;
card_hash: string;
shaparak_fee: number;
};
errors: unknown[];
}
export interface VerifyData {
id: string;
createdAt: string;
updatedAt: string;
deletedAt: string | null;
order: VerifyOrder;
amount: number;
referenceId: string;
method: string;
gateway: string;
transactionId: string;
status: string;
cardPan: string | null;
verifyResponse: VerifyResponseData;
paidAt: string;
failedAt: string | null;
description: string | null;
}
export type VerifyResponse = BaseResponse<VerifyData>;