Skip to content

Commit

Permalink
Merge pull request #8 from swikars1/add-types
Browse files Browse the repository at this point in the history
add types and axios
  • Loading branch information
swikars1 authored Apr 6, 2024
2 parents 5bc42a3 + b37669d commit f427bce
Show file tree
Hide file tree
Showing 7 changed files with 363 additions and 0 deletions.
119 changes: 119 additions & 0 deletions epaymentv2/initiatePayment.ts
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 };
10 changes: 10 additions & 0 deletions epaymentv2/khaltiInstanceServer.ts
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",
});
93 changes: 93 additions & 0 deletions epaymentv2/paymentLookup.ts
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.
63 changes: 63 additions & 0 deletions epaymentv2/paymentSuccessCallback.ts
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
9 changes: 9 additions & 0 deletions epaymentv2/utils.ts
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];
}
}
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,8 @@
"@changesets/cli": "^2.27.1",
"tsup": "^8.0.2",
"typescript": "^5.4.3"
},
"dependencies": {
"axios": "^1.6.8"
}
}
Loading

0 comments on commit f427bce

Please sign in to comment.