Skip to content

Commit

Permalink
add wip hpp implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
peelar committed Apr 22, 2024
1 parent 4705e92 commit 5d7816f
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 24 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ SECRET_KEY=aaaaaaaa

APP_API_BASE_URL=
APP_IFRAME_BASE_URL=
STOREFRONT_URL=""
2 changes: 2 additions & 0 deletions src/lib/env.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const env = createEnv({
REST_APL_TOKEN: z.string().optional(),
APP_API_BASE_URL: z.string().optional(),
APP_IFRAME_BASE_URL: z.string().optional(),
STOREFRONT_URL: z.string(),
},

/*
Expand Down Expand Up @@ -60,5 +61,6 @@ export const env = createEnv({
REST_APL_TOKEN: process.env.REST_APL_TOKEN,
APP_API_BASE_URL: process.env.APP_API_BASE_URL,
APP_IFRAME_BASE_URL: process.env.APP_IFRAME_BASE_URL,
STOREFRONT_URL: process.env.STOREFRONT_URL,
},
});
4 changes: 3 additions & 1 deletion src/modules/klarna/klarna-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import {
type components as PaymentComponents,
} from "generated/klarna-payments";
import { type paths as OrdersPaths } from "generated/klarna-orders";
type AllKlarnaPaths = PaymentPaths & OrdersPaths;
import { type paths as HppPaths } from "generated/klarna-hpp";

type AllKlarnaPaths = PaymentPaths & OrdersPaths & HppPaths;

import { KlarnaHttpClientError } from "@/errors";

Expand Down
68 changes: 47 additions & 21 deletions src/modules/webhooks/transaction-initialize-session.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
import { type TransactionInitializeSessionResponse } from "@/schemas/TransactionInitializeSession/TransactionInitializeSessionResponse.mjs";
import {
TransactionFlowStrategyEnum,
type TransactionInitializeSessionEventFragment,
} from "generated/graphql";
import { getNormalizedLocale } from "@/backend-lib/api-route-utils";
import { KlarnaHttpClientError } from "@/errors";
import { env } from "@/lib/env.mjs";
import { invariant } from "@/lib/invariant";
import { createLogger } from "@/lib/logger";
import { getConfigurationForChannel } from "@/modules/payment-app-configuration/payment-app-configuration";
import { getWebhookPaymentAppConfigurator } from "@/modules/payment-app-configuration/payment-app-configuration-factory";
import { paymentAppFullyConfiguredEntrySchema } from "@/modules/payment-app-configuration/config-entry";
import { obfuscateConfig } from "@/modules/app-configuration/utils";
import { getKlarnaIntegerAmountFromSaleor } from "@/modules/klarna/currencies";
import {
getLineItems,
getKlarnaApiClient,
type KlarnaMetadata,
getLineItems,
prepareRequestAddress,
type KlarnaMetadata,
} from "@/modules/klarna/klarna-api";
import { type components } from "generated/klarna-payments";
import { obfuscateConfig } from "@/modules/app-configuration/utils";
import { type JSONObject } from "@/types";
import { KlarnaHttpClientError } from "@/errors";
import { getKlarnaIntegerAmountFromSaleor } from "@/modules/klarna/currencies";
import { getNormalizedLocale } from "@/backend-lib/api-route-utils";
import { env } from "@/lib/env.mjs";
import { paymentAppFullyConfiguredEntrySchema } from "@/modules/payment-app-configuration/config-entry";
import { getConfigurationForChannel } from "@/modules/payment-app-configuration/payment-app-configuration";
import { getWebhookPaymentAppConfigurator } from "@/modules/payment-app-configuration/payment-app-configuration-factory";
import { type TransactionInitializeSessionResponse } from "@/schemas/TransactionInitializeSession/TransactionInitializeSessionResponse.mjs";
import {
TransactionFlowStrategyEnum,
type TransactionInitializeSessionEventFragment,
} from "generated/graphql";
import { type components as hppComponents } from "generated/klarna-hpp";
import { type components as paymentsComponents } from "generated/klarna-payments";

export const TransactionInitializeSessionWebhookHandler = async (
event: TransactionInitializeSessionEventFragment,
Expand Down Expand Up @@ -63,6 +63,8 @@ export const TransactionInitializeSessionWebhookHandler = async (

const createKlarnaSession = klarnaClient.path("/payments/v1/sessions").method("post").create();

const createHppSession = klarnaClient.path("/hpp/v1/sessions").method("post").create();

const locale = getNormalizedLocale(event);

const country = event.sourceObject.billingAddress?.country.code;
Expand All @@ -88,7 +90,7 @@ export const TransactionInitializeSessionWebhookHandler = async (
authorizationCallbackUrl.searchParams.set("saleorApiUrl", saleorApiUrl);

const email = sourceObject.userEmail;
const createKlarnaSessionPayload: components["schemas"]["session_create"] = {
const createKlarnaSessionPayload: paymentsComponents["schemas"]["session_create"] = {
locale: locale.split("_")[0],
purchase_country: country,
purchase_currency: event.action.currency,
Expand All @@ -105,29 +107,53 @@ export const TransactionInitializeSessionWebhookHandler = async (
authorization: authorizationCallbackUrl.toString(),
},
};

logger.info(authorizationCallbackUrl.toString());
logger.debug({ ...obfuscateConfig(createKlarnaSessionPayload) }, "createKlarnaSession payload");

const klarnaSession = await createKlarnaSession(createKlarnaSessionPayload);

logger.debug({ ...obfuscateConfig(klarnaSession) }, "createKlarnaSession result");

if (!klarnaSession.ok) {
throw new KlarnaHttpClientError(klarnaSession.statusText, { errors: [klarnaSession.data] });
}

const createHppSessionPayload: hppComponents["schemas"]["SessionCreationRequestV1"] = {
payment_session_url:
klarnaConfig.apiUrl + "/payments/v1/sessions/" + klarnaSession.data.session_id,
merchant_urls: {
success: env.STOREFRONT_URL + `/${transactionId}?authorization_token={{authorization_token}}`,
cancel: env.STOREFRONT_URL + "/cancel",
back: env.STOREFRONT_URL + "/back",
failure: env.STOREFRONT_URL + "/failure",
error: env.STOREFRONT_URL + "/error",
},
};

const klarnaHpp = await createHppSession(createHppSessionPayload);

if (!klarnaHpp.ok) {
throw new KlarnaHttpClientError(klarnaHpp.statusText, { errors: [klarnaHpp.data] });
}

invariant(klarnaHpp.data.redirect_url, "Missing redirect_url in klarnaHpp response");

const transactionInitializeSessionResponse: TransactionInitializeSessionResponse = {
data: {
klarnaSessionResponse: klarnaSession.data as JSONObject,
klarnaHppResponse: {
redirectUrl: klarnaHpp.data.redirect_url,
},
},
pspReference: klarnaSession.data.session_id,
pspReference: klarnaHpp.data.session_id,
result:
event.action.actionType === TransactionFlowStrategyEnum.Authorization
? "AUTHORIZATION_ACTION_REQUIRED"
: "CHARGE_ACTION_REQUIRED",
actions: [],
amount: action.amount,
message: "",
externalUrl: undefined, // @todo,
externalUrl: klarnaHpp.data.session_url,
};
return transactionInitializeSessionResponse;
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
"type": "object",
"additionalProperties": true,
"properties": {
"klarnaSessionResponse": { "$ref": "definitions.json#/definitions/JSON" },
"klarnaHppResponse": { "$ref": "definitions.json#/definitions/JSON" },
"errors": { "$ref": "definitions.json#/definitions/SyncWebhookAppErrors" }
},
"required": ["klarnaSessionResponse"]
"required": ["klarnaHppResponse"]
},
"result": { "$ref": "definitions.json#/definitions/TransactionSessionResult" },
"amount": { "$ref": "definitions.json#/definitions/PositiveDecimal" },
Expand Down

0 comments on commit 5d7816f

Please sign in to comment.