From f2173098803d6afde9273ab9996adc4a357bc23c Mon Sep 17 00:00:00 2001 From: Tomas Zijdemans <113360400+tomas-zijdemans-vipps@users.noreply.github.com> Date: Mon, 15 Jan 2024 10:35:54 +0100 Subject: [PATCH] Fix types (#27) * Fix epayment types to address: https://github.com/vippsas/deno-sdk/issues/23 * Add missing Webhook event types --- scripts/script_deps.ts | 6 ++-- src/apis/epayment.ts | 18 +++++------ src/apis/types/epayment_types.ts | 49 ++++++++++++++++++++---------- src/apis/types/qr_types.ts | 50 ++++++++++++++++++++++++++++--- src/apis/types/recurring_types.ts | 4 ++- src/apis/types/webhooks_types.ts | 13 ++++++-- src/deps.ts | 6 ++-- tests/error_test.ts | 4 +-- tests/test_deps.ts | 2 +- 9 files changed, 111 insertions(+), 41 deletions(-) diff --git a/scripts/script_deps.ts b/scripts/script_deps.ts index 5351a21..f7c836d 100644 --- a/scripts/script_deps.ts +++ b/scripts/script_deps.ts @@ -1,5 +1,5 @@ -export { gt, parse } from "https://deno.land/std@0.211.0/semver/mod.ts"; -export { Spinner } from "https://deno.land/std@0.211.0/cli/mod.ts"; -export * as colors from "https://deno.land/std@0.211.0/fmt/colors.ts"; +export { gt, parse } from "https://deno.land/std@0.212.0/semver/mod.ts"; +export { Spinner } from "https://deno.land/std@0.212.0/cli/mod.ts"; +export * as colors from "https://deno.land/std@0.212.0/fmt/colors.ts"; export { build, emptyDir } from "https://deno.land/x/dnt@0.39.0/mod.ts"; diff --git a/src/apis/epayment.ts b/src/apis/epayment.ts index e4c7bdf..4eb49c8 100644 --- a/src/apis/epayment.ts +++ b/src/apis/epayment.ts @@ -2,12 +2,12 @@ import { RequestData } from "../types.ts"; import { EPaymentCreatePaymentOKResponse, EPaymentCreatePaymentRequest, - EpaymentErrorResponse, + EPaymentErrorResponse, EPaymentForceApproveRequest, + EPaymentGetEventLogOKResponse, EPaymentGetPaymentOKResponse, EPaymentModificationOKResponse, EPaymentModificationRequest, - EPaymentPaymentEventOKResponse, } from "./types/epayment_types.ts"; /** @@ -24,7 +24,7 @@ export const ePaymentRequestFactory = { create( token: string, body: EPaymentCreatePaymentRequest, - ): RequestData { + ): RequestData { const newBody = { ...body }; // Fill in missing props if (!body.reference) { @@ -47,7 +47,7 @@ export const ePaymentRequestFactory = { info( token: string, reference: string, - ): RequestData { + ): RequestData { return { url: `/epayment/v1/payments/${reference}`, method: "GET", @@ -64,7 +64,7 @@ export const ePaymentRequestFactory = { history( token: string, reference: string, - ): RequestData { + ): RequestData { return { url: `/epayment/v1/payments/${reference}/events`, method: "GET", @@ -81,7 +81,7 @@ export const ePaymentRequestFactory = { cancel( token: string, reference: string, - ): RequestData { + ): RequestData { return { url: `/epayment/v1/payments/${reference}/cancel`, method: "POST", @@ -100,7 +100,7 @@ export const ePaymentRequestFactory = { token: string, reference: string, body: EPaymentModificationRequest, - ): RequestData { + ): RequestData { return { url: `/epayment/v1/payments/${reference}/capture`, method: "POST", @@ -120,7 +120,7 @@ export const ePaymentRequestFactory = { token: string, reference: string, body: EPaymentModificationRequest, - ): RequestData { + ): RequestData { return { url: `/epayment/v1/payments/${reference}/refund`, method: "POST", @@ -140,7 +140,7 @@ export const ePaymentRequestFactory = { token: string, reference: string, body: EPaymentForceApproveRequest, - ): RequestData { + ): RequestData { return { url: `/epayment/v1/test/payments/${reference}/approve`, method: "POST", diff --git a/src/apis/types/epayment_types.ts b/src/apis/types/epayment_types.ts index e9e2bf1..9e7e99a 100644 --- a/src/apis/types/epayment_types.ts +++ b/src/apis/types/epayment_types.ts @@ -1,5 +1,7 @@ /////////////// Error Types /////////////// +import { Scope } from "./shared_types.ts"; + export type EPaymentProblemJSON = { type: string; title: string; @@ -7,7 +9,7 @@ export type EPaymentProblemJSON = { status: number; instance: string; }; -export type EpaymentErrorResponse = EPaymentProblemJSON & { +export type EPaymentErrorResponse = EPaymentProblemJSON & { traceId: string; extraDetails: { name: string; @@ -40,7 +42,7 @@ export type EPaymentCreatePaymentRequest = { customerInteraction?: "CUSTOMER_PRESENT" | "CUSTOMER_NOT_PRESENT"; /** Additional compliance data related to the transaction. */ industryData?: EPaymentIndustryData; - paymentMethod: EPaymentPaymentMethod; + paymentMethod: EPaymentMethod; profile?: EPaymentProfileRequest; reference?: EPaymentReference; /** @@ -278,12 +280,12 @@ export type EPaymentAirlineData = { ticketNumber?: string; }; -export type EPaymentPaymentMethod = { +export type EPaymentMethod = { /** * The paymentMethod type to be performed. * `CARD` has to be combined with a `userFlow` of `WEB_REDIRECT`. */ - type: EPaymentPaymentMethodType; + type: EPaymentMethodType; }; /** @@ -298,7 +300,7 @@ export type EPaymentPaymentMethod = { * * @example "WALLET" */ -export type EPaymentPaymentMethodType = "WALLET" | "CARD"; +export type EPaymentMethodType = "WALLET" | "CARD"; export type EPaymentProfileRequest = { /** @@ -318,7 +320,7 @@ export type EPaymentProfileRequest = { * * @example "name phoneNumber" */ - scope: string; + scope: Scope; }; /** @@ -508,7 +510,7 @@ export type EPaymentBottomLine = { * @example "vipps_pos_122" */ posId: string | null; - paymentSources?: EPaymentPaymentSources; + paymentSources?: EPaymentSources; barcode?: EPaymentBarcode; /** * Receipt number from the POS. @@ -527,7 +529,7 @@ export type EPaymentBottomLine = { * cash: 25 * } */ -export type EPaymentPaymentSources = { +export type EPaymentSources = { giftCard?: number | null; card?: number | null; voucher?: number | null; @@ -578,7 +580,7 @@ export type EPaymentGetPaymentOKResponse = { aggregate: EPaymentAggregate; amount: EPaymentAmount; state: EPaymentState; - paymentMethod: EPaymentPaymentMethodResponse; + paymentMethod: EPaymentMethodResponse; profile: EPaymentProfileResponse; pspReference: string; /** @@ -624,12 +626,12 @@ export type EPaymentState = | "AUTHORIZED" | "TERMINATED"; -export type EPaymentPaymentMethodResponse = { +export type EPaymentMethodResponse = { /** * The paymentMethod type to be performed. * `CARD` has to be combined with a `userFlow` of `WEB_REDIRECT`. */ - type: EPaymentPaymentMethodType; + type: EPaymentMethodType; /** * The payment card's Bank Identification Number (BIN), * that identifies which bank has issued the card. @@ -653,10 +655,12 @@ export type EPaymentProfileResponse = { /////////////// Payment Event History Response /////////////// -export type EPaymentPaymentEventOKResponse = { +export type EPaymentGetEventLogOKResponse = EPaymentEvent[]; + +export type EPaymentEvent = { reference: EPaymentReference; pspReference: string; - name: EPaymentPaymentEventName; + name: EPaymentEventName; amount: EPaymentAmount; /** * @example: '2022-12-31T00:00:00Z' @@ -672,9 +676,24 @@ export type EPaymentPaymentEventOKResponse = { idempotencyKey?: string | null; /** The outcome of the event */ success: boolean; -}[]; +}; + +/** + * The merchant serial number (MSN) for the sales unit. + * + * @minLength 4 + * @maxLength 6 + * @pattern ^[0-9]{4,6}$ + * @example "123456" + */ +export type EPaymentMSN = string; + +export type EPaymentWebhookEvent = { + /** The merchant serial number (MSN) for the sales unit. */ + msn: EPaymentMSN; +} & EPaymentEvent; -export type EPaymentPaymentEventName = +export type EPaymentEventName = | "CREATED" | "ABORTED" | "EXPIRED" diff --git a/src/apis/types/qr_types.ts b/src/apis/types/qr_types.ts index 9739098..552d296 100644 --- a/src/apis/types/qr_types.ts +++ b/src/apis/types/qr_types.ts @@ -87,16 +87,28 @@ export type CallbackQrImageFormat = "PNG" | "SVG"; export type CallbackQrImageSize = number; export type CallbackQrRequest = { - /** A description of where the QR code will be located. It will be shown in the app when a user scans the QR code. Examples could be ‘Kasse 1’ , ‘Kiosk’ or ‘Platform 3’. */ + /** + * A description of where the QR code will be located. + * It will be shown in the app when a user scans the QR code. + * Examples could be ‘Kasse 1’ , ‘Kiosk’ or ‘Platform 3’. + */ locationDescription: string; }; export type CallbackQrResponse = { /** The merchant serial number (MSN) for the sale unit */ merchantSerialNumber?: string; - /** The merchant defined identifier for a QR code. It will be provided in the callback to the merchant when the QR code has been scanned. */ + /** + * The merchant defined identifier for a QR code. + * It will be provided in the callback to the merchant when the + * QR code has been scanned. + */ merchantQrId?: string; - /** A description of where the QR code will be located. It will be shown in the app when a user scans the QR code. Examples could be ‘Kasse 1’ , ‘Kiosk’ or ‘Platform 3’. */ + /** + * A description of where the QR code will be located. + * It will be shown in the app when a user scans the QR code. + * Examples could be ‘Kasse 1’ , ‘Kiosk’ or ‘Platform 3’. + */ locationDescription?: string; /** * The link to the actual QR code. @@ -104,10 +116,40 @@ export type CallbackQrResponse = { * @example "https://qr.vipps.no/generate/qr.png?..." */ qrImageUrl?: string; - /** The text that is being encoded by the QR code. This is the actual content of the QR code. */ + /** + * The text that is being encoded by the QR code. + * This is the actual content of the QR code. + */ qrContent?: string; }; +export type QrWebhookEvent = { + /** + * A distinct token per customer + * + * @example "wbA8ceVRKkoYiQAVELHeFCC3Sn5dtNCvvEtVPiOT77j6wx7uR965AG6Q+q0ATP4=" + */ + customerToken: string; + /** + * The merchant defined identifier for a QR code. + * It will be provided in the callback to the merchant when the + * QR code has been scanned. + * + * @example "d8b7d76d-49aa-48b8-90c6-38779372c163" + */ + merchantQrId: string; + /** + * The merchant serial number (MSN) for the sale unit. + * + * @example "123456" + */ + msn: string; + /** + * @example "2023-10-06T10:45:40.3061965Z" + */ + initiatedAt: string; +}; + export type QrErrorResponse = { /** @minLength 1 */ type?: string; diff --git a/src/apis/types/recurring_types.ts b/src/apis/types/recurring_types.ts index d656965..9195912 100644 --- a/src/apis/types/recurring_types.ts +++ b/src/apis/types/recurring_types.ts @@ -1,5 +1,7 @@ //////////////// Common types ///////////////// +import { Scope } from "./shared_types.ts"; + /** * Only NOK is supported at the moment. Support for EUR and DKK will be provided in early 2024. * @minLength 3 @@ -452,7 +454,7 @@ export type DraftAgreementV3Request = { * - nin * @example "address name email birthDate phoneNumber" */ - scope?: string; + scope?: Scope; /** * If the property is set to `true`, it will cause a push notification * to be sent to the given phone number immediately, without loading diff --git a/src/apis/types/webhooks_types.ts b/src/apis/types/webhooks_types.ts index bc8fa1b..3b1a7ae 100644 --- a/src/apis/types/webhooks_types.ts +++ b/src/apis/types/webhooks_types.ts @@ -36,10 +36,15 @@ export type WebhookDetails = { events: WebhookEventType[]; }; -// All event types currently supported in the SDK for all APIs -export type WebhookEventType = EpaymentEventTypes | "user.checked-in.v1"; +/* + * All event types currently supported in the SDK for all APIs + * + * Please refer to the individual API types for the response payload + * for each event type. For example EPaymentWebhookEvent + */ +export type WebhookEventType = EPaymentEventTypes | QrEventTypes; -type EpaymentEventTypes = +export type EPaymentEventTypes = | "epayments.payment.created.v1" | "epayments.payment.aborted.v1" | "epayments.payment.expired.v1" @@ -48,3 +53,5 @@ type EpaymentEventTypes = | "epayments.payment.refunded.v1" | "epayments.payment.authorized.v1" | "epayments.payment.terminated.v1"; + +export type QrEventTypes = "user.checked-in.v1"; diff --git a/src/deps.ts b/src/deps.ts index b439175..e55bcd2 100644 --- a/src/deps.ts +++ b/src/deps.ts @@ -1,6 +1,6 @@ export { retry, RetryError, -} from "https://deno.land/std@0.210.0/async/retry.ts"; -export { isErrorStatus } from "https://deno.land/std@0.210.0/http/status.ts"; -export { filterKeys } from "https://deno.land/std@0.210.0/collections/mod.ts"; +} from "https://deno.land/std@0.212.0/async/retry.ts"; +export { isErrorStatus } from "https://deno.land/std@0.212.0/http/status.ts"; +export { filterKeys } from "https://deno.land/std@0.212.0/collections/mod.ts"; diff --git a/tests/error_test.ts b/tests/error_test.ts index b633fb8..471814c 100644 --- a/tests/error_test.ts +++ b/tests/error_test.ts @@ -1,5 +1,5 @@ import { AccessTokenError } from "../src/apis/types/auth_types.ts"; -import { EpaymentErrorResponse } from "../src/apis/types/epayment_types.ts"; +import { EPaymentErrorResponse } from "../src/apis/types/epayment_types.ts"; import { QrErrorResponse } from "../src/apis/types/qr_types.ts"; import { RetryError } from "../src/deps.ts"; import { parseError } from "../src/errors.ts"; @@ -56,7 +56,7 @@ Deno.test("parseError - Should return correct error message for AccessTokenError }); Deno.test("parseError - Should return correct error message for Problem JSON", () => { - const error: EpaymentErrorResponse = { + const error: EPaymentErrorResponse = { type: "https://example.com/error", title: "Some problem", status: 400, diff --git a/tests/test_deps.ts b/tests/test_deps.ts index 1ed8f29..ced5b10 100644 --- a/tests/test_deps.ts +++ b/tests/test_deps.ts @@ -3,5 +3,5 @@ export { assertEquals, assertExists, assertNotEquals, -} from "https://deno.land/std@0.210.0/assert/mod.ts"; +} from "https://deno.land/std@0.212.0/assert/mod.ts"; export * as mf from "https://deno.land/x/mock_fetch@0.3.0/mod.ts";