5
Verifying Payment Status

After payment completion or when a customer returns to your application, you may need to verify the payment status in your database to show the appropriate confirmation or error page.

Payment Verification Implementation

Implement a payment verification function to check the status:

Payment Verification
// In your return route or payment verification endpoint
import { PrismaClient, PaymentStatus } from "@prisma/client";
import type { LoaderFunctionArgs } from "react-router";

const prisma = new PrismaClient();

export const loader = async ({ params }: LoaderFunctionArgs) => {
  const { referenceId } = params;
  
  try {
    // Fetch payment from database
    const payment = await prisma.payment.findUnique({
      where: { externalId: referenceId },
      include: {
        paymentMethod: true,
        statusHistory: {
          orderBy: { createdAt: "desc" },
          take: 5,
        },
      },
    });
    
    if (!payment) {
      return {
        success: false,
        status: "NOT_FOUND",
        message: "Payment not found",
      };
    }
    
    // Prepare response based on payment status
    let message, details;
    
    switch (payment.status) {
      case PaymentStatus.COMPLETED:
        message = "Payment completed successfully";
        details = {
          paymentDate: payment.paidAt,
          transactionId: payment.transactionId,
        };
        break;
      case PaymentStatus.PROCESSING:
        message = "Payment is still processing";
        details = {
          lastUpdated: payment.updatedAt,
        };
        break;
      case PaymentStatus.FAILED:
        message = "Payment failed";
        details = {
          reason: payment.statusHistory[0]?.notes || "Unknown error",
          failedAt: payment.updatedAt,
        };
        break;
      case PaymentStatus.CANCELLED:
        message = "Payment was cancelled";
        details = {
          cancelledAt: payment.updatedAt,
        };
        break;
      default:
        message = `Payment status: ${payment.status}`;
        details = {
          lastUpdated: payment.updatedAt,
        };
    }
    
    return {
      success: true,
      status: payment.status,
      message,
      details,
      payment: {
        id: payment.id,
        externalId: payment.externalId,
        amount: payment.amount,
        currency: payment.currency,
        createdAt: payment.createdAt,
        updatedAt: payment.updatedAt,
        description: payment.description,
      }
    };
  } catch (err) {
    console.error("Payment verification error:", err);
    return {
      success: false,
      status: "ERROR",
      message: "Failed to verify payment",
    };
  }
};

Payment Status Handling

Here's how to handle different payment statuses:

COMPLETED

Payment has been successfully processed

Handling:

  • Update order status to 'paid'
  • Send confirmation email to customer
  • Trigger order fulfillment process

PROCESSING

Payment is being processed by the payment gateway

Handling:

  • Display waiting message to customer
  • Provide estimated processing time
  • Enable status checking functionality

FAILED

Payment attempt was unsuccessful

Handling:

  • Show specific failure reason to customer
  • Offer retry options with alternative payment methods
  • Provide support contact information

CANCELLED

Payment was cancelled by customer or merchant

Handling:

  • Release reserved inventory
  • Provide option to restart checkout
  • Log cancellation reason for analytics

REFUNDED

Payment was refunded to customer

Handling:

  • Update order status to 'refunded'
  • Send refund confirmation email
  • Record refund reason for reporting

Direct API Verification

Alternatively, you can verify payment status directly with the SaligPay API:

Direct API Verification
// Alternative: Verify directly with SaligPay API

Best Practice: Always verify payment status on your server before providing access to purchased goods or services. Relying solely on client-side verification is not secure as it could be manipulated.

Displaying Payment Result

In your return page component, display appropriate messages based on the payment status:

Return/Result Page Component
import { useLoaderData, Link } from "react-router";

export default function PaymentReturn() {
  const { success, payment, status, message } = useLoaderData();
  
  if (!success) {
    return (
      <div className="error-container">
        <h2>Payment Verification Failed</h2>
        <p>{message || "Unable to verify payment status"}</p>
        <Link to="/">Return to Home</Link>
      </div>
    );
  }
  
  // Render based on payment status
  return (
    <div className="payment-result">
      <h2>Payment {payment.status}</h2>
      <p>{payment.message}</p>
      
      {payment.status === "COMPLETED" && (
        <div className="success-details">
          <p>Thank you for your payment!</p>
          <p>Transaction ID: {payment.details.transactionId}</p>
          <p>Amount: {"$" + (payment.amount / 100).toFixed(2)}</p>
        </div>
      )}
      
      {payment.status === "FAILED" && (
        <div className="failure-details">
          <p>We encountered an issue with your payment:</p>
          <p>{payment.details.reason}</p>
          <Link to="/payment" className="retry-button">
            Try Again
          </Link>
        </div>
      )}
      
      <Link to="/">Return to Home</Link>
    </div>
  );
}