Skip to content

Commit

Permalink
Merge branch 'master' into IOBP-651-adapt-new-wallet-attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
Hantex9 committed May 29, 2024
2 parents 5699724 + e6f41b3 commit 70b68e8
Show file tree
Hide file tree
Showing 24 changed files with 340 additions and 8 deletions.
20 changes: 19 additions & 1 deletion assets/wallet/wallet_payment.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,25 @@
const urlParams = new URLSearchParams(queryString);
const transactionId = urlParams.get("transactionId");
const container = document.getElementById("outcomeSelect");
window.location.href = `iowallet://127.0.0.1:3000/ecommerce/io/v1/transactions/${transactionId}/outcomes?outcome=${container.value}`;
if (container.value === "0") {
fetch('/ecommerce/io/v1/mock-transaction', {
method: 'POST',
body: JSON.stringify({
transactionId,
}),
headers: new Headers({
'Content-Type': 'application/json',
'Accept': 'application/json'
})
})
.then(response => response.json())
.then(response => {
window.location = `iowallet://127.0.0.1:3000/ecommerce/io/v1/transactions/${transactionId}/outcomes?outcome=${container.value}`;
})
.catch(err => alert(err))
} else {
window.location.href = `iowallet://127.0.0.1:3000/ecommerce/io/v1/transactions/${transactionId}/outcomes?outcome=${container.value}`;
}
}

function onLoad() {
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"api_fast_login": "https://raw.githubusercontent.com/pagopa/io-backend/v13.32.1-RELEASE/openapi/generated/api_fast_login.yaml",
"api_pagopa_walletv3": "https://raw.githubusercontent.com/pagopa/pagopa-infra/95477f43e87016a979d26b5a81eee32c308af96d/src/domains/wallet-app/api/payment-wallet/v1/_openapi.json.tpl",
"api_pagopa_ecommerce": "https://raw.githubusercontent.com/pagopa/pagopa-infra/95477f43e87016a979d26b5a81eee32c308af96d/src/domains/ecommerce-app/api/ecommerce-io/v1/_openapi.json.tpl",
"api_pagopa_biz_events": "https://raw.githubusercontent.com/pagopa/pagopa-infra/0a6784276fd43aaff7709dd90e0d379e77326f28/src/domains/bizevents-app/api/transaction-service/v1/_openapi-jwt.json.tpl",
"api_services": "https://raw.githubusercontent.com/pagopa/io-backend/master/api_services_app_backend.yaml",
"author": "Matteo Boschi",
"license": "MIT",
Expand All @@ -45,6 +46,7 @@
"generate:pagopa-walletv2-definitions": "rimraf generated/definitions/pagopa/walletv2 && mkdir -p generated/definitions/pagopa/walletv2 && gen-api-models --api-spec $npm_package_api_pagopa_walletv2 --out-dir ./generated/definitions/pagopa/walletv2",
"generate:pagopa-walletv3-definitions": "rimraf generated/definitions/pagopa/walletv3 && mkdir -p generated/definitions/pagopa/walletv3 && gen-api-models --api-spec $npm_package_api_pagopa_walletv3 --out-dir ./generated/definitions/pagopa/walletv3",
"generate:pagopa-ecommerce-definitions": "rimraf generated/definitions/pagopa/ecommerce && mkdir -p generated/definitions/pagopa/ecommerce && gen-api-models --api-spec $npm_package_api_pagopa_ecommerce --out-dir ./generated/definitions/pagopa/ecommerce",
"generate:pagopa-transactions-definitions": "rimraf generated/definitions/pagopa/transactions && mkdir -p generated/definitions/pagopa/transactions && gen-api-models --api-spec $npm_package_api_pagopa_biz_events --out-dir ./generated/definitions/pagopa/transactions",
"generate:pagopa-api": "rimraf generated/definitions/pagopa && mkdir -p generated/definitions/pagopa && gen-api-models --api-spec $npm_package_api_pagopa --out-dir ./generated/definitions/pagopa",
"generate:cgn-definitions": "rimraf generated/definitions/cgn && mkdir -p generated/definitions/cgn && gen-api-models --api-spec $npm_package_api_cgn --out-dir ./generated/definitions/cgn ",
"generate:cgn-merchants-definitions": "rimraf generated/definitions/cgn/merchants && mkdir -p generated/definitions/cgn/merchants && gen-api-models --api-spec $npm_package_api_cgn_merchants --out-dir ./generated/definitions/cgn/merchants ",
Expand All @@ -55,7 +57,7 @@
"generate:pn-definitions": "rimraf generated/definitions/pn && mkdir -p generated/definitions/pn && gen-api-models --api-spec $npm_package_api_pn --out-dir ./generated/definitions/pn --no-strict --request-types --response-decoders",
"generate:idpay-definitions": "rimraf generated/definitions/idpay && mkdir -p generated/definitions/idpay && gen-api-models --api-spec $npm_package_api_idpay --out-dir ./generated/definitions/idpay --no-strict",
"generate:fast-login-definitions": "rimraf generated/definitions/fast_login && mkdir -p generated/definitions/fast_login && gen-api-models --api-spec $npm_package_api_fast_login --out-dir ./generated/definitions/fast_login --no-strict --request-types --response-decoders",
"generate:pagopa": "npm-run-all generate:pagopa-walletv2-definitions generate:pagopa-privative-configuration-definitions generate:pagopa-cobadge-configuration-definitions generate:pagopa-walletv3-definitions generate:pagopa-ecommerce-definitions",
"generate:pagopa": "npm-run-all generate:pagopa-walletv2-definitions generate:pagopa-privative-configuration-definitions generate:pagopa-cobadge-configuration-definitions generate:pagopa-walletv3-definitions generate:pagopa-ecommerce-definitions generate:pagopa-transactions-definitions",
"generate:services-definitions": "rimraf generated/definitions/services && mkdir -p generated/definitions/services && gen-api-models --api-spec $npm_package_api_services --out-dir ./generated/definitions/services --no-strict",
"generate": "npm-run-all generate:*"
},
Expand Down
3 changes: 3 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ const defaultConfig: IoDevServerConfig = {
allowRandomValues: true
},
features: {
payments: {
numberOfTransactions: 12
},
bonus: {
cgn: {
isCgnEligible: true,
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { PaymentMethodStatusEnum } from "../../../../generated/definitions/pagop
import { Range } from "../../../../generated/definitions/pagopa/walletv3/Range";
import { WalletInfoDetails } from "../../../../generated/definitions/pagopa/walletv3/WalletInfoDetails";

const generateRandomCardBrand = () =>
export const generateRandomCardBrand = () =>
faker.helpers.arrayElement(["VISA", "MASTERCARD", "AMEX", "MAESTRO"]);

export const paymentMethodsDB: ReadonlyArray<PaymentMethodResponse> = [
Expand Down
122 changes: 122 additions & 0 deletions src/features/payments/persistence/transactions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { faker } from "@faker-js/faker";
import { pipe } from "fp-ts/lib/function";
import * as O from "fp-ts/lib/Option";
import { TransactionListItem } from "../../../../generated/definitions/pagopa/transactions/TransactionListItem";
import { TransactionDetailResponse } from "../../../../generated/definitions/pagopa/transactions/TransactionDetailResponse";
import { TransactionInfo } from "../../../../generated/definitions/pagopa/ecommerce/TransactionInfo";
import { generateRandomInfoTransaction } from "../utils/transactions";
import { ioDevServerConfig } from "../../../config";

const mockedTaxCodes = ["1199250158", "13756881002", "262700362", "31500945"];

type TransactionId = TransactionListItem["transactionId"];

const userTransactions = new Map<TransactionId, TransactionListItem>();
const transactions = new Map<TransactionId, TransactionDetailResponse>();

const getUserTransactions = () =>
Array.from(userTransactions.size > 0 ? userTransactions.values() : []);

const getTransactionDetails = (transactionId: TransactionId) =>
pipe(
transactions,
O.fromNullable,
O.chain(transactions => O.fromNullable(transactions.get(transactionId)))
);

const addUserTransaction = (transaction: TransactionListItem) => {
userTransactions.set(transaction.transactionId, transaction);
};

const removeUserTransaction = (transactionId: TransactionId) => {
userTransactions.delete(transactionId);
removeTransactionDetails(transactionId);
};

const addTransactionDetails = (
transactionId: TransactionId,
transaction: TransactionDetailResponse
) => {
transactions.set(transactionId, transaction);
};

const removeTransactionDetails = (transactionId: TransactionId) => {
transactions.delete(transactionId);
};

const generateUserTransaction = (
transactionId: TransactionId,
idx: number,
additionalTransactionInfo: Partial<TransactionInfo> = {}
) => {
const payeeTaxCode =
mockedTaxCodes[
faker.datatype.number({ min: 0, max: mockedTaxCodes.length - 1 })
];
const randomTransaction: TransactionListItem = {
transactionId,
payeeName: faker.company.name(),
payeeTaxCode,
amount: additionalTransactionInfo.payments?.[0]?.amount.toString(),
transactionDate: new Date(
new Date().setDate(new Date().getDate() - 2 * idx)
).toISOString(),
isCart: false
};

const cartList = Array.from(
{ length: faker.datatype.number({ min: 1, max: 2 }) },
() => ({
subject: faker.lorem.sentence(faker.datatype.number({ min: 2, max: 4 })),
amount: faker.finance.amount(1, 1000),
payee: {
name: randomTransaction.payeeName,
taxCode: randomTransaction.payeeTaxCode
},
debtor: {
name: faker.name.fullName(),
taxCode: faker.random.alphaNumeric(16).toUpperCase()
},
refNumberType: "IBAN",
refNumberValue: faker.datatype
.number({ min: 100000000000, max: 999999999999 })
.toString()
})
);
// eslint-disable-next-line functional/immutable-data
randomTransaction.isCart = cartList.length > 1;
// eslint-disable-next-line functional/immutable-data
randomTransaction.amount = cartList
.reduce((acc, item) => acc + Number(item.amount), 0)
.toString();
addUserTransaction(randomTransaction);

const randomTransactionDetails: TransactionDetailResponse = {
infoTransaction: generateRandomInfoTransaction(cartList),
carts: cartList
};
addTransactionDetails(transactionId, randomTransactionDetails);
return randomTransaction;
};

const generateUserTransactionData = () => {
for (
// eslint-disable-next-line functional/no-let
let i = 0;
i < ioDevServerConfig.features.payments.numberOfTransactions;
i = i + 1
) {
generateUserTransaction(faker.datatype.uuid(), i);
}
};

// At server startup
generateUserTransactionData();

export default {
addUserTransaction,
getUserTransactions,
getTransactionDetails,
generateUserTransaction,
removeUserTransaction
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import "./payment";
import "./wallets";
import "./transactions";

export { walletRouter } from "./router";
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
getTransactionInfoPayload
} from "../payloads/transactions";
import WalletDB from "../persistence/userWallet";
import TransactionsDB from "../persistence/transactions";
import {
WalletPaymentFailure,
getStatusCodeForWalletFailure
Expand Down Expand Up @@ -182,6 +183,28 @@ addPaymentHandler(
)
);

// This API is used to create a mock transaction when the outcome selected is SUCCESS (0)
addPaymentHandler("post", "/mock-transaction", (req, res) =>
pipe(
req.body.transactionId,
O.fromNullable,
O.fold(
() => res.sendStatus(403),
transactionId =>
pipe(
getTransactionInfoPayload(transactionId),
O.fold(
() => res.sendStatus(404),
() => {
TransactionsDB.generateUserTransaction(transactionId, 0);
return res.status(200).json({ status: "ok" });
}
)
)
)
)
);

addPaymentHandler("get", "/wallets", (req, res) => {
res.json({
wallets: WalletDB.getUserWallets()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@ export const walletRouter = Router();

export const PAYMENT_WALLET_PREFIX = "/payment-wallet/v1";
export const ECOMMERCE_PREFIX = "/ecommerce/io/v1";
export const TRANSACTIONS_PREFIX = "/bizevents/bizevents/tx-service-jwt/v1";

export const addPaymentWalletPrefix = (path: string) =>
`${PAYMENT_WALLET_PREFIX}${path}`;

export const addECommercePrefix = (path: string) =>
`${ECOMMERCE_PREFIX}${path}`;

export const addTransactionPrefix = (path: string) =>
`${TRANSACTIONS_PREFIX}${path}`;

export const addPaymentWalletHandler = (
method: SupportedMethod,
path: string,
Expand All @@ -24,3 +28,10 @@ export const addPaymentHandler = (
path: string,
handleRequest: (request: Request, response: Response) => void
) => addHandler(walletRouter, method, addECommercePrefix(path), handleRequest);

export const addTransactionHandler = (
method: SupportedMethod,
path: string,
handleRequest: (request: Request, response: Response) => void
) =>
addHandler(walletRouter, method, addTransactionPrefix(path), handleRequest);
66 changes: 66 additions & 0 deletions src/features/payments/routers/transactions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import * as O from "fp-ts/lib/Option";
import { pipe } from "fp-ts/lib/function";
import TransactionsDB from "../persistence/transactions";

import { TransactionListWrapResponse } from "../../../../generated/definitions/pagopa/transactions/TransactionListWrapResponse";
import { addTransactionHandler } from "./router";

const CONTINUATION_TOKEN_HEADER = "x-continuation-token";

addTransactionHandler("get", "/transactions", (req, res) => {
const size = req.query.size ? Number(req.query.size) : 10;
const offset =
req.headers[CONTINUATION_TOKEN_HEADER] !== undefined &&
req.headers[CONTINUATION_TOKEN_HEADER] !== "undefined"
? Number(req.headers[CONTINUATION_TOKEN_HEADER])
: 0;
const response: TransactionListWrapResponse = {
transactions: TransactionsDB.getUserTransactions().slice(
offset,
offset + size
)
};
const continuationToken =
TransactionsDB.getUserTransactions().length > offset + size
? (offset + size).toString()
: undefined;
pipe(
response.transactions,
O.fromNullable,
O.chain(O.fromPredicate(transactions => transactions.length > 0)),
O.fold(
() =>
res.status(404).json({
title: "No transactions found",
status: 404,
detail: "No transactions found for the user"
}),
_ => {
if (continuationToken) {
res.setHeader(CONTINUATION_TOKEN_HEADER, continuationToken);
}
return res.status(200).json(response);
}
)
);
});

addTransactionHandler("get", "/transactions/:transactionId", (req, res) => {
pipe(
req.params.transactionId,
O.fromNullable,
O.fold(
() => res.sendStatus(400),
transactionId => {
const transaction = TransactionsDB.getTransactionDetails(transactionId);
return pipe(
transaction,
O.fold(
() => res.sendStatus(404),
transaction => res.status(200).json(transaction)
)
);
}
)
);
});
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 70b68e8

Please sign in to comment.