medusa-payment-comgate-jc
Version:
Comgate payment gateway provider for MedusaJS
464 lines (404 loc) • 12.4 kB
text/typescript
import ComgateClient from "comgate-node";
import { EOL } from "os";
import {
AbstractPaymentProcessor,
CartService,
isPaymentProcessorError,
PaymentProcessorContext,
PaymentProcessorError,
PaymentSessionStatus,
} from "@medusajs/medusa";
import {
ComgatePaymentOptions,
ComgatePaymentProcessorSessionResponse,
ComgateSessionData,
PaymentProviderKeys,
} from "../types";
import { StatusResponseStatus } from "comgate-node/dist/types/endpoints/status";
abstract class ComgateBase extends AbstractPaymentProcessor {
static identifier = PaymentProviderKeys.COMGATE_CARD;
protected readonly options_: ComgatePaymentOptions;
public comgateClient: ComgateClient;
protected readonly cartService: CartService;
protected constructor(_, options) {
super(_, options);
this.options_ = options;
this.init();
this.cartService = _.cartService;
}
protected init(): void {
this.comgateClient =
this.comgateClient ||
new ComgateClient({
merchant: this.options_.merchant,
secret: this.options_.secret,
test: this.options_.test,
});
}
async getPaymentStatus(
paymentSessionData: ComgateSessionData
): Promise<PaymentSessionStatus> {
if (this.options_.debug) {
console.log("ComgateMedusa: " + "getPaymentStatus", "start");
}
const transId = paymentSessionData.comgateData.transId as string;
if (this.options_.debug) {
console.log("ComgateMedusa: " + "getPaymentStatus", "data: ", {
transId: transId,
});
}
try {
const transactionStatus = await this.getComgateTransactionStatus(transId);
if (this.options_.debug) {
console.log("ComgateMedusa: " + "getPaymentStatus", "response: ", {
transId: transactionStatus,
});
}
return transactionStatus.status;
} catch (error) {
if (this.options_.debug) {
console.log("ComgateMedusa: " + "getPaymentStatus", "error: ", error);
}
return PaymentSessionStatus.ERROR;
}
}
async initiatePayment(
context: PaymentProcessorContext
): Promise<PaymentProcessorError | ComgatePaymentProcessorSessionResponse> {
if (this.options_.debug) {
console.log("ComgateMedusa: " + "initiatePayment", "start");
}
const session_data: ComgateSessionData = {
status: PaymentSessionStatus.PENDING,
comgateData: {
transId: null,
status: "INITIATED",
redirect: null,
error: null,
},
};
if (this.options_.debug) {
console.log(
"ComgateMedusa: " + "initiatePayment",
"session_data: ",
session_data
);
}
return {
session_data: session_data,
};
}
async authorizePayment(
paymentSessionData: ComgateSessionData,
context?: Record<string, unknown>
): Promise<
| PaymentProcessorError
| {
status: PaymentSessionStatus;
data: ComgatePaymentProcessorSessionResponse["session_data"];
}
> {
if (this.options_.debug) {
console.log("ComgateMedusa: " + "authorizePayment", "start");
}
const transId = paymentSessionData.comgateData.transId as string;
if (this.options_.debug) {
console.log("ComgateMedusa: " + "authorizePayment", "transId: ", transId);
}
const transactionStatus = await this.getComgateTransactionStatus(transId);
if (this.options_.debug) {
console.log(
"ComgateMedusa: " + "authorizePayment",
"response: ",
transactionStatus
);
}
const sessionData = {
status: transactionStatus.status,
data: {
status: transactionStatus.status,
comgateData: {
transId: paymentSessionData.comgateData.transId,
status: transactionStatus.comgateStatus,
redirect: paymentSessionData.comgateData.redirect,
error: transactionStatus.comgateError,
},
},
};
if (this.options_.debug) {
console.log(
"ComgateMedusa: " + "authorizePayment",
"sessionData: ",
sessionData
);
}
return sessionData;
}
async cancelPayment(
paymentSessionData: ComgateSessionData
): Promise<
| PaymentProcessorError
| ComgatePaymentProcessorSessionResponse["session_data"]
> {
if (this.options_.debug) {
console.log("ComgateMedusa: " + "cancelPayment", "start");
}
const transId = paymentSessionData.comgateData.transId as string;
if (this.options_.debug) {
console.log("ComgateMedusa: " + "cancelPayment", "transId: ", transId);
}
try {
const { code, message } = await this.comgateClient.cancel({
transId: transId,
});
if (this.options_.debug) {
console.log(
"ComgateMedusa: " + "cancelPayment",
"response: ",
code,
message
);
}
if (code === 0) {
return {
status: PaymentSessionStatus.CANCELED,
comgateData: {
transId: paymentSessionData.comgateData.transId,
status: "CANCELLED",
redirect: paymentSessionData.comgateData.redirect,
error: null,
},
};
} else if (code === 1400) {
const error: PaymentProcessorError = {
error: message,
code: String(code),
};
return error;
} else {
const error: PaymentProcessorError = {
error: message,
code: String(code),
};
return error;
}
} catch (error: any) {
return this.buildError("An error occurred in cancelPayment", error);
}
}
async capturePayment(
paymentSessionData: ComgateSessionData
): Promise<
| PaymentProcessorError
| ComgatePaymentProcessorSessionResponse["session_data"]
> {
if (this.options_.debug) {
console.log("ComgateMedusa: " + "capturePayment", "start");
}
return paymentSessionData;
}
async deletePayment(
paymentSessionData: ComgateSessionData
): Promise<
| PaymentProcessorError
| ComgatePaymentProcessorSessionResponse["session_data"]
> {
if (this.options_.debug) {
console.log("ComgateMedusa: " + "deletePayment", "start");
}
return await this.cancelPayment(paymentSessionData);
}
async refundPayment(
paymentSessionData: ComgateSessionData,
refundAmount: number
): Promise<
| PaymentProcessorError
| ComgatePaymentProcessorSessionResponse["session_data"]
> {
if (this.options_.debug) {
console.log("ComgateMedusa: " + "refundPayment", "start");
}
const transId = paymentSessionData.comgateData.transId as string;
if (this.options_.debug) {
console.log("ComgateMedusa: " + "refundPayment", "transId: ", transId);
console.log(
"ComgateMedusa: " + "refundPayment",
"amount: ",
String(refundAmount)
);
}
try {
const refundPayment = await this.comgateClient.refund({
transId: transId,
amount: String(refundAmount),
});
if (this.options_.debug) {
console.log(
"ComgateMedusa: " + "refundPayment",
"response: ",
refundPayment
);
}
if (refundPayment.code !== 0) {
const error: PaymentProcessorError = {
error: String(refundPayment.message),
code: String(refundPayment.code),
};
return this.buildError("Failed to refund payment", error);
}
return {
status: paymentSessionData.status,
comgateData: {
transId: paymentSessionData.comgateData.transId,
status: paymentSessionData.comgateData.status,
redirect: paymentSessionData.comgateData.redirect,
error: null,
},
};
} catch (error: any) {
return this.buildError("Failed to refund payment", error);
}
}
async retrievePayment(
paymentSessionData: ComgateSessionData
): Promise<
| PaymentProcessorError
| ComgatePaymentProcessorSessionResponse["session_data"]
> {
if (this.options_.debug) {
console.log("ComgateMedusa: " + "retrievePayment", "start");
}
const transId = paymentSessionData.comgateData.transId as string;
if (this.options_.debug) {
console.log("ComgateMedusa: " + "retrievePayment", "transId: ", transId);
}
try {
const transactionStatus = await this.getComgateTransactionStatus(transId);
if (this.options_.debug) {
console.log(
"ComgateMedusa: " + "retrievePayment",
"response: ",
transactionStatus
);
}
return {
status: transactionStatus.status,
comgateData: {
transId: paymentSessionData.comgateData.transId,
status: transactionStatus.comgateStatus,
redirect: paymentSessionData.comgateData.redirect,
error: transactionStatus.comgateError,
},
};
} catch (error: any) {
return this.buildError("Failed to retrieve payment", error);
}
}
async updatePayment(
context: PaymentProcessorContext
): Promise<
PaymentProcessorError | ComgatePaymentProcessorSessionResponse | void
> {
if (this.options_.debug) {
console.log("ComgateMedusa: " + "updatePayment", "start");
}
// const { amount, customer } = context;
const paymentSessionData = context.paymentSessionData as ComgateSessionData;
// const transId = paymentSessionData.comgateData.transId as string;
if (this.options_.debug) {
console.log(
"ComgateMedusa: " + "updatePayment",
"paymentSessionData: ",
paymentSessionData
);
}
return {
session_data: paymentSessionData,
};
}
async updatePaymentData(
sessionId: string,
data: ComgateSessionData
): Promise<
| ComgatePaymentProcessorSessionResponse["session_data"]
| PaymentProcessorError
> {
if (this.options_.debug) {
console.log("ComgateMedusa: " + "updatePaymentData", "start");
console.log("ComgateMedusa: " + "updatePaymentData", "data: ", data);
}
return data;
}
protected buildError(
message: string,
e: PaymentProcessorError | Error
): PaymentProcessorError {
return {
error: message,
code: "code" in e ? e.code : "",
detail: isPaymentProcessorError(e)
? `${e.error}${EOL}${e.detail ?? ""}`
: "detail" in e
? e.detail
: e.message ?? "",
};
}
private async getComgateTransactionStatus(transId: string): Promise<{
status: PaymentSessionStatus;
comgateStatus: StatusResponseStatus | "ERROR";
comgateError: PaymentProcessorError | null;
}> {
let status: PaymentSessionStatus;
let comgateStatus: StatusResponseStatus | "ERROR";
let comgateError: PaymentProcessorError | null = null;
try {
const paymentStatus = await this.comgateClient.status({
transId,
});
if (paymentStatus.code !== "0") {
status = PaymentSessionStatus.ERROR;
comgateStatus = "ERROR";
const error: PaymentProcessorError = {
error: paymentStatus.message,
code: String(paymentStatus.code),
detail: paymentStatus.message,
};
comgateError = this.buildError(
"Error Comgate API payment status Response",
error
);
} else {
switch (paymentStatus.status.toUpperCase()) {
case "PENDING":
status = PaymentSessionStatus.AUTHORIZED;
break;
case "PAID":
status = PaymentSessionStatus.AUTHORIZED;
break;
case "AUTHORIZED":
status = PaymentSessionStatus.AUTHORIZED;
break;
case "CANCELLED":
status = PaymentSessionStatus.CANCELED;
break;
default:
status = PaymentSessionStatus.PENDING;
}
comgateStatus = paymentStatus.status;
}
} catch (error) {
status = PaymentSessionStatus.ERROR;
comgateStatus = "ERROR";
comgateError = this.buildError(
"Error in calling Comgate API payment status",
error
);
}
return {
status: status,
comgateStatus: comgateStatus,
comgateError: comgateError,
};
}
}
export default ComgateBase;