-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
363 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import { khaltiInstanceServer } from "./khaltiInstanceServer"; | ||
import { awTry } from "./utils"; | ||
|
||
/** | ||
* Represents the successful response when initiating a payment. | ||
*/ | ||
interface InitiatePaymentResponse { | ||
/** | ||
* A unique request identifier provided upon success. Use this 'pidx' | ||
* for future references to this payment. | ||
*/ | ||
pidx: string; | ||
|
||
/** The URL to redirect the user to in order to complete the payment. */ | ||
payment_url: string; | ||
|
||
/** Date and time (likely in ISO format) when the payment link expires. */ | ||
expires_at: string; | ||
|
||
/** Number of seconds until the payment link expires. */ | ||
expires_in: number; | ||
} | ||
|
||
/** | ||
* Represents an error response when initiating a payment. | ||
*/ | ||
interface InitiatePaymentError { | ||
/** The return URL that was likely invalid or problematic. */ | ||
return_url: string[]; | ||
|
||
/** A fixed error key indicating a validation issue. */ | ||
error_key: "validation_error"; | ||
} | ||
|
||
/** | ||
* Represents the request payload for initiating a payment. | ||
*/ | ||
interface InitiatePaymentRequest { | ||
/** URL where the user will be redirected after completing the transaction */ | ||
return_url: string; | ||
|
||
/** The main website URL associated with the transaction */ | ||
website_url: string; | ||
|
||
/** Total amount of the transaction (in Paisa) */ | ||
amount: number; | ||
|
||
/** Unique identifier for the purchase order */ | ||
purchase_order_id: string; | ||
|
||
/** Descriptive name of the purchase order */ | ||
purchase_order_name: string; | ||
|
||
/** Customer's billing information (optional) */ | ||
customer_info?: CustomerInfo; | ||
|
||
/** Detailed breakdown of the total amount (e.g., taxes, fees) (optional) */ | ||
amount_breakdown?: AmountBreakdownItem[]; | ||
|
||
/** Details about the products or services included in the transaction (optional) */ | ||
product_details?: ProductDetail[]; | ||
} | ||
|
||
/** | ||
* Contains customer information for billing purposes. | ||
*/ | ||
interface CustomerInfo { | ||
/** Customer's full name */ | ||
name: string; | ||
|
||
/** Customer's email address */ | ||
email: string; | ||
|
||
/** Customer's contact phone number */ | ||
phone: string; | ||
} | ||
|
||
/** | ||
* Represents a single charge item within the amount breakdown. | ||
*/ | ||
interface AmountBreakdownItem { | ||
/** Description of a particular charge within the total amount */ | ||
label: string; | ||
|
||
/** Amount (in Paisa) associated with the label */ | ||
amount: number; | ||
} | ||
|
||
/** | ||
* Holds information about a product included in the transaction. | ||
*/ | ||
interface ProductDetail { | ||
/** Unique identifier for the product */ | ||
identity: string; | ||
|
||
/** Name or description of the product */ | ||
name: string; | ||
|
||
/** Total price for this product (including quantity) */ | ||
total_price: number; | ||
|
||
/** Number of units of this product purchased */ | ||
quantity: number; | ||
|
||
/** Price per single unit of this product */ | ||
unit_price: number; | ||
} | ||
|
||
const initiatePayment = async (payload: InitiatePaymentRequest) => { | ||
const [response, error] = await awTry<{ data: InitiatePaymentResponse }>( | ||
khaltiInstanceServer.post("/epayment/initiate/", payload) | ||
); | ||
if (error) { | ||
console.log("Error, in initiatePayment: ", error); | ||
} | ||
return response.data; | ||
}; | ||
|
||
export { initiatePayment }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import axios from "axios"; | ||
|
||
export const khaltiInstanceServer = axios.create({ | ||
baseURL: "https://a.khalti.com/api/v2", | ||
headers: { | ||
"Content-Type": "application/json", | ||
Authorization: `Key f79110302bbf46828fca3a7b7514da97`, // live secret key | ||
}, | ||
responseType: "json", | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/** | ||
* Represents the possible statuses of a payment transaction. | ||
*/ | ||
type PaymentStatus = | ||
| "Completed" | ||
| "Pending" | ||
| "Refunded" | ||
| "Expired" | ||
| "UserCanceled" | ||
| "PartiallyRefunded" | ||
| "Initiated"; | ||
|
||
/** | ||
* Represents the request payload for the payment lookup API. | ||
*/ | ||
interface PaymentLookupRequest { | ||
/** The initial payment identifier. */ | ||
pidx: string; | ||
} | ||
|
||
/** | ||
* Represents the base structure of a successful lookup API response. | ||
*/ | ||
interface PaymentLookupSuccessResponse { | ||
/** The initial payment identifier. */ | ||
pidx: string; | ||
|
||
/** The total amount of the transaction (in what currency? Assuming Paisa here). */ | ||
total_amount: number; | ||
|
||
/** The current status of the transaction. */ | ||
status: PaymentStatus; | ||
|
||
/** The unique transaction identifier assigned by Khalti. */ | ||
transaction_id: string | null; | ||
|
||
/** The fee associated with the transaction. */ | ||
fee: number; | ||
|
||
/** Indicates whether the transaction has been refunded. */ | ||
refunded: boolean; | ||
} | ||
|
||
/** | ||
* Represents a specific lookup response for a 'Pending' transaction. | ||
*/ | ||
interface PaymentLookupPendingResponse extends PaymentLookupSuccessResponse { | ||
status: "Pending"; // Enforce the specific status | ||
transaction_id: null; // Transaction ID not yet generated | ||
} | ||
|
||
/** | ||
* Represents a specific lookup response for an 'Initiated' transaction. | ||
*/ | ||
interface PaymentLookupInitiatedResponse extends PaymentLookupSuccessResponse { | ||
status: "Initiated"; | ||
} | ||
|
||
/** | ||
* Represents a specific lookup response for a 'Refunded' transaction. | ||
*/ | ||
interface PaymentLookupRefundedResponse extends PaymentLookupSuccessResponse { | ||
status: "Refunded"; | ||
refunded: true; | ||
} | ||
|
||
/** | ||
* Represents a specific lookup response for an 'Expired' transaction. | ||
*/ | ||
interface PaymentLookupExpiredResponse extends PaymentLookupSuccessResponse { | ||
status: "Expired"; | ||
transaction_id: null; | ||
} | ||
|
||
/** | ||
* Represents a specific lookup response for a 'UserCanceled' transaction. | ||
*/ | ||
interface PaymentLookupCanceledResponse extends PaymentLookupSuccessResponse { | ||
status: "UserCanceled"; | ||
transaction_id: null; | ||
} | ||
|
||
// Completed - Provide service to user. | ||
// Pending - Hold, do not provide service. And contact Khalti team. | ||
// Refunded - Transaction has been refunded to user. Do not provide service. | ||
// Expired - User have not made the payment, Do not provide the service. | ||
// User canceled User have canceled the payment, Do not provide the service. | ||
|
||
// Only the status with Completed must be treated as success. | ||
// Status Canceled , Expired , Failed must be treated as failed. | ||
// If any negative consequences occur due to incomplete API integration or providing service without checking lookup status, Khalti won’t be accountable for any such losses. | ||
// For status other than these, hold the transaction and contact KHALTI team. | ||
// Payment link expires in 60 minutes in production. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
/** | ||
* Represents the data received in the redirect callback URL after a payment attempt. | ||
*/ | ||
interface PaymentRedirectResponse { | ||
/** The initial payment identifier provided during initiation. */ | ||
pidx: string; | ||
|
||
/** | ||
* The current status of the transaction. | ||
* - "Completed": Payment completed successfully. | ||
* - "Pending": Payment in progress. Use the Lookup API for final confirmation. | ||
* - "UserCanceled": The user canceled the payment process. | ||
*/ | ||
status: "Completed" | "Pending" | "UserCanceled"; | ||
|
||
/** The unique transaction identifier assigned by Khalti. */ | ||
transaction_id: string; | ||
|
||
/** (Synonym for transaction_id) - The unique transaction identifier assigned by Khalti. */ | ||
tidx: string; | ||
|
||
/** The total amount paid by the user (in Paisa). */ | ||
amount: number; | ||
|
||
/** The payer's Khalti ID. */ | ||
mobile: string; | ||
|
||
/** The unique purchase order ID provided when initiating the payment. */ | ||
purchase_order_id: string; | ||
|
||
/** The name associated with the purchase order. */ | ||
purchase_order_name: string; | ||
|
||
/** (Synonym for amount) - The total amount paid by the user (in Paisa). */ | ||
total_amount: number; | ||
} | ||
|
||
// It's recommended that during implementation, payment lookup API is checked for confirmation after the redirect callback is received | ||
|
||
// Success transaction callback | ||
|
||
// http://example.com/?pidx=bZQLD9wRVWo4CdESSfuSsB | ||
// &txnId=4H7AhoXDJWg5WjrcPT9ixW | ||
// &amount=1000 | ||
// &total_amount=1000 | ||
// &status=Completed | ||
// &mobile=98XXXXX904 | ||
// &tidx=4H7AhoXDJWg5WjrcPT9ixW | ||
// &purchase_order_id=test12 | ||
// &purchase_order_name=test | ||
// &transaction_id=4H7AhoXDJWg5WjrcPT9ixW | ||
|
||
// Canceled transaction callback | ||
|
||
// http://example.com/?pidx=bZQLD9wRVWo4CdESSfuSsB | ||
// &transaction_id= | ||
// &tidx= | ||
// &amount=1000 | ||
// &total_amount=1000 | ||
// &mobile= | ||
// &status=User canceled | ||
// &purchase_order_id=test12 | ||
// &purchase_order_name=test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
export async function awTry<T>(promise: unknown) { | ||
try { | ||
const data = await promise; | ||
return [data, null] as [T, never]; | ||
} catch (err) { | ||
console.error(err); | ||
return [null, err] as [never, unknown]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.