import * as gracely from "gracely" import * as isoly from "isoly" import { Error } from "../../Error" import { Fraudio } from "../../Fraudio" import { Card } from "../../State/Card" import { PreAuthorization } from "../../State/PreAuthorization" import { Recurring } from "../Recurring" export type Create = Fail | Success | Pending interface Base { merchant: string number: string date: isoly.DateTime type: "create" status: "fail" | "success" | "pending" processor?: Record fraudio?: Fraudio } interface Fail extends Base { status: "fail" amount?: number currency?: isoly.Currency card?: Card descriptor?: string recurring?: Recurring verification?: "verified" | "rejected" | "unavailable" rule?: string[] reason: Error.Code declinedBy?: "issuer" | "intergiro" error: gracely.Error } interface Success extends Base { verification?: "verified" | "rejected" | "unavailable" status: "success" } interface Pending extends Base { status: "pending" rule: string[] reason: "verification required" amount?: number currency?: isoly.Currency card?: Card descriptor?: string recurring?: Recurring } export namespace Create { function isBase(value: any | Base): value is Base { return ( typeof value == "object" && typeof value.merchant == "string" && typeof value.number == "string" && (value.processor == undefined || (typeof value.processor == "object" && Object.keys(value.processor).every(v => typeof v == "string"))) && value.type == "create" && isoly.DateTime.is(value.date) && (value.fraudio == undefined || Fraudio.is(value.fraudio)) ) } export function isFail(value: any | Fail): value is Fail { return ( typeof value == "object" && (value.amount == undefined || typeof value.amount == "number") && (value.currency == undefined || isoly.Currency.is(value.currency)) && (value.card == undefined || Card.is(value.card)) && (value.descriptor == undefined || typeof value.descriptor == "string") && (value.verification == undefined || ["verified", "rejected", "unavailable"].includes(value.verification)) && value.status == "fail" && (value.rule == undefined || (Array.isArray(value.rule) && value.rule.every((r: any) => typeof r == "string"))) && Error.Code.is(value.reason) && (value.declinedBy == undefined || value.declinedBy == "issuer" || value.declinedBy == "intergiro") && gracely.Error.is(value.error) && (value.recurring == undefined || Recurring.is(value.recurring)) && isBase(value) ) } export function isSuccess(value: any | Success): value is Success { return ( typeof value == "object" && (value.verification == undefined || ["verified", "rejected", "unavailable"].includes(value.verification)) && value.status == "success" && isBase(value) ) } export function isPending(value: any | Pending): value is Pending { return ( typeof value == "object" && value.status == "pending" && Array.isArray(value.rule) && value.rule.every((r: any) => typeof r == "string") && value.reason == "verification required" && (value.recurring == undefined || Recurring.is(value.recurring)) && (value.amount == undefined || typeof value.amount == "number") && (value.currency == undefined || isoly.Currency.is(value.currency)) && (value.card == undefined || Card.is(value.card)) && (value.descriptor == undefined || typeof value.descriptor == "string") && isBase(value) ) } export function is(value: any | Create): value is Create { return isFail(value) || isSuccess(value) || isPending(value) } export function create( state: | (PreAuthorization & { processor?: Record }) | { merchant: { id: string } authorization: { number: string; fraudio?: Fraudio; verification?: undefined } processor?: Record }, input: gracely.Error | any ): Create { const card = "card" in state.authorization ? { scheme: state.authorization.card.scheme, iin: state.authorization.card.iin, last4: state.authorization.card.last4, csc: state.authorization.card.csc, expires: state.authorization.card.expires, country: state.authorization.card.country, } : undefined return { merchant: state.merchant.id, number: state.authorization.number, date: isoly.DateTime.now(), type: "create", ...(!gracely.Error.is(input) ? { status: "success", verification: state.authorization.verification, processor: state.processor, fraudio: state.authorization.fraudio, } : input.error != "verification required" ? { status: "fail", ...state.authorization, card, email: undefined, // To remove from state ip: undefined, // To remove from state reason: Error.Code.is(input.error) ? input.error : "unknown error", error: input, processor: state.processor, rule: gracely.client.FlawedContent.is(input) && input.error == "rule violation" ? input.content.flaws?.map(e => e.condition ?? "") : undefined, declinedBy: gracely.client.FlawedContent.is(input) && input.error == "rule violation" ? "intergiro" : "issuer", } : { status: "pending", ...state.authorization, reason: input.error, processor: state.processor, card, email: undefined, // To remove from state ip: undefined, // To remove from state rule: gracely.client.FlawedContent.is(input) ? input.content.flaws?.map(e => e.condition ?? "") ?? [] : [], }), } } }