-
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.
Showing
7 changed files
with
420 additions
and
1 deletion.
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,58 @@ | ||
import "https://deno.land/std@0.209.0/dotenv/load.ts"; | ||
import { Client } from "../src/mod.ts"; | ||
|
||
// First, get your API keys from https://portal.vipps.no/ | ||
// Here we assume they are stored in a .env file, see .env.example | ||
const clientId = Deno.env.get("CLIENT_ID") || ""; | ||
const clientSecret = Deno.env.get("CLIENT_SECRET") || ""; | ||
|
||
const merchantSerialNumber = Deno.env.get("MERCHANT_SERIAL_NUMBER") || ""; | ||
const subscriptionKey = Deno.env.get("SUBSCRIPTION_KEY") || ""; | ||
|
||
// Create a client | ||
const client = Client({ | ||
merchantSerialNumber, | ||
subscriptionKey, | ||
useTestMode: true, | ||
retryRequests: false, | ||
}); | ||
|
||
// Grab a token | ||
const accessToken = await client.auth.getToken({ | ||
clientId, | ||
clientSecret, | ||
subscriptionKey, | ||
}); | ||
|
||
// Check if the token was retrieved successfully | ||
if (!accessToken.ok) { | ||
console.error("😟 Error retrieving token 😟"); | ||
console.error(accessToken.message); | ||
Deno.exit(1); | ||
} | ||
|
||
const token = accessToken.data.access_token; | ||
|
||
const qrId = crypto.randomUUID(); | ||
|
||
const qr = await client.callbackQR.create(token, qrId, { | ||
locationDescription: "Kasse 1", | ||
}); | ||
|
||
// Check if the QR was created successfully | ||
if (!qr.ok) { | ||
console.error("😟 Error creating QR 😟"); | ||
console.error(qr.message); | ||
Deno.exit(1); | ||
} | ||
|
||
const qrInfo = await client.callbackQR.info(token, qrId); | ||
|
||
// Check if the QR was retrieved successfully | ||
if (!qrInfo.ok) { | ||
console.error("😟 Error retrieving QR 😟"); | ||
console.error(qrInfo.message); | ||
Deno.exit(1); | ||
} | ||
|
||
console.log(qrInfo.data.qrImageUrl); |
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,129 @@ | ||
import { RequestData } from "../types.ts"; | ||
import { | ||
MerchantCallbackQr, | ||
MerchantCallbackRequest, | ||
QrErrorResponse, | ||
QrImageFormat, | ||
QrImageSize, | ||
} from "./types/qr_types.ts"; | ||
|
||
/** | ||
* Factory for creating Merchant callback QR request. | ||
*/ | ||
export const callbackQRRequestFactory = { | ||
/** | ||
* Creates a callback QR request. | ||
* | ||
* @param token - The authentication token. | ||
* @param merchantQrId - The merchant defined identifier for a QR code. | ||
* @param body - The request body. | ||
* @returns A `RequestData` object representing the callback QR request. | ||
*/ | ||
create( | ||
token: string, | ||
merchantQrId: string, | ||
body: MerchantCallbackRequest, | ||
): RequestData<void, QrErrorResponse> { | ||
return { | ||
url: `/qr/v1/merchant-callback/${merchantQrId}`, | ||
method: "PUT", | ||
body, | ||
token, | ||
}; | ||
}, | ||
/** | ||
* Returns the QR code represented by the merchantQrId and | ||
* Merchant-Serial-Number provided in the path and header respectively. | ||
* The image format and size of the QR code is defined by the Accept | ||
* and Size headers respectively. | ||
* | ||
* @param token - The authentication token. | ||
* @param merchantQrId - The ID of the merchant callback QR code. | ||
* @param qrImageFormat - The format of the QR code image (default: "SVG"). | ||
* @param qrImageSize - The size of the QR code image (optional). | ||
* @returns A `RequestData` object containing the URL, method, and token. | ||
*/ | ||
info( | ||
token: string, | ||
merchantQrId: string, | ||
qrImageFormat: QrImageFormat = "SVG", | ||
qrImageSize?: QrImageSize, | ||
): RequestData<MerchantCallbackQr, QrErrorResponse> { | ||
const url = qrImageSize | ||
? `/qr/v1/merchant-callback/${merchantQrId}?QrImageFormat=${qrImageFormat}&QrImageSize=${qrImageSize}` | ||
: `/qr/v1/merchant-callback/${merchantQrId}?QrImageFormat=${qrImageFormat}`; | ||
|
||
return { url, method: "GET", token }; | ||
}, | ||
/** | ||
* Returns all QR codes that matches the provided Merchant-Serial-Number. | ||
* | ||
* @param token - The authentication token. | ||
* @param qrImageFormat - The format of the QR image. Defaults to "SVG". | ||
* @param qrImageSize - The size of the QR image. | ||
* @returns A `RequestData` object containing the URL, method, and token. | ||
*/ | ||
list( | ||
token: string, | ||
qrImageFormat: QrImageFormat = "SVG", | ||
qrImageSize?: QrImageSize, | ||
): RequestData<MerchantCallbackQr[], QrErrorResponse> { | ||
const url = qrImageSize | ||
? `/qr/v1/merchant-callback?QrImageFormat=${qrImageFormat}&QrImageSize=${qrImageSize}` | ||
: `/qr/v1/merchant-callback?QrImageFormat=${qrImageFormat}`; | ||
|
||
return { url, method: "GET", token }; | ||
}, | ||
/** | ||
* Deletes the QR code that matches the provided merchantQrId and merchantSerialNumber. | ||
* | ||
* @param token - The authentication token. | ||
* @param merchantQrId - The ID of the merchant QR to delete. | ||
* @returns A `RequestData` object with the URL, method, and token for the delete request. | ||
*/ | ||
delete( | ||
token: string, | ||
merchantQrId: string, | ||
): RequestData<void, QrErrorResponse> { | ||
return { | ||
url: `/qr/v1/merchant-callback/${merchantQrId}`, | ||
method: "DELETE", | ||
token, | ||
}; | ||
}, | ||
/** | ||
* NOTE: This endpoint is only intended for MobilePay PoS customers. | ||
* It will be removed as soon as migration is completed. | ||
* | ||
* This endpoint is for migrating existing MobilePay PoS QR codes from the | ||
* current solution that will end its lifetime. It is meant for merchants | ||
* that have printed QR codes and want them to stay functional for the new | ||
* product offering that will replace the now deprecated solution. | ||
* | ||
* This endpoint will not create a new QR code but rather map the provided | ||
* beaconId with the Merchant-Serial-Number, to make sure the already | ||
* printed QR code can be re-used. When the QR code is scanned by MobilePay | ||
* users, it will result in a callback being sent to the merchant if the | ||
* merchant has registered a webhook for the user.checked-in.v1 event. | ||
* | ||
* The callback will include a MerchantQrId which in this scenario will | ||
* equal the beaconId. | ||
* | ||
* @param token - The authentication token. | ||
* @param beaconId - The beacon ID. | ||
* @param body - The request body. | ||
* @returns The request data. | ||
*/ | ||
createMobilePayQR( | ||
token: string, | ||
beaconId: string, | ||
body: MerchantCallbackRequest, | ||
): RequestData<void, QrErrorResponse> { | ||
return { | ||
url: `/qr/v1/merchant-callback/mobilepay/${beaconId}`, | ||
method: "PUT", | ||
body, | ||
token, | ||
}; | ||
}, | ||
}; |
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,135 @@ | ||
export type MerchantCallbackRequest = { | ||
/** 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; | ||
}; | ||
|
||
/** | ||
* @description Requested image format. Supported values: {PNG, SVG}. If not provided, SVG is chosen. | ||
* @example "PNG" | ||
* @default "SVG" | ||
*/ | ||
export type QrImageFormat = "PNG" | "SVG"; | ||
|
||
/** | ||
* @description Dimensions for the image. Only relevant if PNG is chosen as image format. | ||
* @minimum 100 | ||
* @maximum 2000 | ||
* @example 200. Then 200x200 px is set at dimension for the QR. | ||
*/ | ||
export type QrImageSize = number; | ||
|
||
export type MerchantCallbackQr = { | ||
/** 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. */ | ||
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’. */ | ||
locationDescription?: string; | ||
/** | ||
* The link to the actual QR code. | ||
* @format uri | ||
* @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. */ | ||
qrContent?: string; | ||
}; | ||
|
||
export type QrErrorResponse = { | ||
/** @minLength 1 */ | ||
type?: string; | ||
/** @minLength 1 */ | ||
title: string; | ||
/** @minLength 1 */ | ||
detail: string; | ||
/** @minLength 1 */ | ||
instance: string; | ||
invalidParams?: { | ||
/** @minLength 1 */ | ||
name: string; | ||
/** @minLength 1 */ | ||
reason: string; | ||
}[]; | ||
}; | ||
|
||
type OneTimePaymentQrRequest = { | ||
/** | ||
* Url to the Vipps landing page, obtained from ecom/recurring apis | ||
* @example "https://api.vipps.no/dwo-api-application/v1/deeplink/vippsgateway?v=2&token=eyJraWQiO...." | ||
*/ | ||
url: string; | ||
}; | ||
|
||
type OneTimePaymentQrResponse = { | ||
/** | ||
* Link to QR image | ||
* @example "https://qr.vipps.no/generate/qr.png?..." | ||
*/ | ||
url: string; | ||
/** | ||
* How many seconds more this QR will be active | ||
* @example 544 | ||
*/ | ||
expiresIn: number; | ||
}; | ||
|
||
type MerchantRedirectQrRequest = { | ||
/** | ||
* Merchant supplied Id for QR | ||
* @minLength 1 | ||
* @maxLength 128 | ||
* @pattern ^[-_+%æøåÆØÅ\w\s]*$ | ||
* @example "billboard_1" | ||
*/ | ||
id: string | null; | ||
/** | ||
* The target url of the QR (redirect destination) | ||
* @format uri | ||
* @pattern ^https:\/\/[\w\.]+([\w#!:.?+=&%@\-\/]+)?$ | ||
* @example "https://example.com/myProduct" | ||
*/ | ||
redirectUrl: string | null; | ||
/** | ||
* Optional time-to-live field, given in seconds | ||
* @min 300 | ||
* @max 2147483647 | ||
* @example 600 | ||
*/ | ||
ttl?: number | null; | ||
}; | ||
|
||
type MerchantRedirectQrResponse = { | ||
/** | ||
* Merchant supplied Id for QR | ||
* @pattern ^[-_+%æøåÆØÅ\w\s]*$ | ||
* @example "billboard_1" | ||
*/ | ||
id: string; | ||
/** | ||
* Link to QR image | ||
* @format uri | ||
* @example "https://qr.vipps.no/generate/qr.png?..." | ||
*/ | ||
url: string; | ||
/** | ||
* The target url of the QR (redirect destination) | ||
* @format uri | ||
* @pattern ^https:\/\/[\w\.]+([\w#!:.?+=&%@\-\/]+)?$ | ||
* @example "https://example.com/myProduct" | ||
*/ | ||
redirectUrl: string; | ||
/** | ||
* Time in seconds until expiration. -1 means no expiration (infinite QR code) | ||
* @example 598 | ||
*/ | ||
expiresIn?: number; | ||
}; | ||
|
||
type MerchantRedirectQrUpdateRequest = { | ||
/** | ||
* @format uri | ||
* @pattern ^https:\/\/[\w\.]+([\w#!:.?+=&%@\-\/]+)?$ | ||
* @example "https://example.com/myProduct" | ||
*/ | ||
redirectUrl: string; | ||
}; |
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
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
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.