fix wallet DB
This commit is contained in:
parent
0e88ef9bd2
commit
7deefd5b2d
@ -17,35 +17,41 @@
|
|||||||
/**
|
/**
|
||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import { runTest, GlobalTestState, MerchantPrivateApi } from "./harness";
|
import {
|
||||||
import { createSimpleTestkudosEnvironment, withdrawViaBank } from "./helpers";
|
runTest,
|
||||||
|
GlobalTestState,
|
||||||
|
MerchantPrivateApi,
|
||||||
|
MerchantService,
|
||||||
|
BankServiceInterface,
|
||||||
|
MerchantServiceInterface,
|
||||||
|
WalletCli,
|
||||||
|
ExchangeServiceInterface,
|
||||||
|
} from "./harness";
|
||||||
|
import {
|
||||||
|
createSimpleTestkudosEnvironment,
|
||||||
|
withdrawViaBank,
|
||||||
|
SimpleTestEnvironment,
|
||||||
|
} from "./helpers";
|
||||||
import { PreparePayResultType, URL } from "taler-wallet-core";
|
import { PreparePayResultType, URL } from "taler-wallet-core";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
/**
|
async function testRefundApiWithFulfillmentUrl(
|
||||||
* Test case for the refund API of the merchant backend.
|
t: GlobalTestState,
|
||||||
*/
|
env: {
|
||||||
runTest(async (t: GlobalTestState) => {
|
merchant: MerchantServiceInterface;
|
||||||
// Set up test environment
|
bank: BankServiceInterface;
|
||||||
|
wallet: WalletCli;
|
||||||
const {
|
exchange: ExchangeServiceInterface;
|
||||||
wallet,
|
},
|
||||||
bank,
|
): Promise<void> {
|
||||||
exchange,
|
const { wallet, bank, exchange, merchant } = env;
|
||||||
merchant,
|
|
||||||
} = await createSimpleTestkudosEnvironment(t);
|
|
||||||
|
|
||||||
// Withdraw digital cash into the wallet.
|
|
||||||
|
|
||||||
await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
|
|
||||||
|
|
||||||
// Set up order.
|
// Set up order.
|
||||||
|
|
||||||
const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
|
const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
|
||||||
order: {
|
order: {
|
||||||
summary: "Buy me!",
|
summary: "Buy me!",
|
||||||
amount: "TESTKUDOS:5",
|
amount: "TESTKUDOS:5",
|
||||||
fulfillment_url: "taler://fulfillment-success/thx",
|
fulfillment_url: "https://example.com/fulfillment",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -131,7 +137,150 @@ runTest(async (t: GlobalTestState) => {
|
|||||||
publicOrderStatusResp = await axios.get(publicOrderStatusUrl.href, {
|
publicOrderStatusResp = await axios.get(publicOrderStatusUrl.href, {
|
||||||
validateStatus: () => true,
|
validateStatus: () => true,
|
||||||
});
|
});
|
||||||
console.log(publicOrderStatusResp.data)
|
console.log(publicOrderStatusResp.data);
|
||||||
// We didn't give any authentication, so this should be forbidden
|
// We didn't give any authentication, so we should get a fulfillment URL back
|
||||||
t.assertTrue(publicOrderStatusResp.status === 403);
|
t.assertTrue(publicOrderStatusResp.status === 202);
|
||||||
|
const fu = publicOrderStatusResp.data.fulfillment_url;
|
||||||
|
t.assertTrue(typeof fu === "string" && fu.startsWith("https://example.com"));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function testRefundApiWithFulfillmentMessage(
|
||||||
|
t: GlobalTestState,
|
||||||
|
env: {
|
||||||
|
merchant: MerchantServiceInterface;
|
||||||
|
bank: BankServiceInterface;
|
||||||
|
wallet: WalletCli;
|
||||||
|
exchange: ExchangeServiceInterface;
|
||||||
|
},
|
||||||
|
): Promise<void> {
|
||||||
|
const { wallet, bank, exchange, merchant } = env;
|
||||||
|
|
||||||
|
// Set up order.
|
||||||
|
const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
|
||||||
|
order: {
|
||||||
|
summary: "Buy me!",
|
||||||
|
amount: "TESTKUDOS:5",
|
||||||
|
fulfillment_message: "Thank you for buying foobar",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
|
||||||
|
orderId: orderResp.order_id,
|
||||||
|
});
|
||||||
|
|
||||||
|
t.assertTrue(orderStatus.order_status === "unpaid");
|
||||||
|
|
||||||
|
const talerPayUri = orderStatus.taler_pay_uri;
|
||||||
|
const orderId = orderResp.order_id;
|
||||||
|
|
||||||
|
// Make wallet pay for the order
|
||||||
|
|
||||||
|
let preparePayResult = await wallet.preparePay({
|
||||||
|
talerPayUri,
|
||||||
|
});
|
||||||
|
|
||||||
|
t.assertTrue(
|
||||||
|
preparePayResult.status === PreparePayResultType.PaymentPossible,
|
||||||
|
);
|
||||||
|
|
||||||
|
const r2 = await wallet.apiRequest("confirmPay", {
|
||||||
|
proposalId: preparePayResult.proposalId,
|
||||||
|
});
|
||||||
|
t.assertTrue(r2.type === "response");
|
||||||
|
|
||||||
|
// Check if payment was successful.
|
||||||
|
|
||||||
|
orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
|
||||||
|
orderId: orderResp.order_id,
|
||||||
|
});
|
||||||
|
|
||||||
|
t.assertTrue(orderStatus.order_status === "paid");
|
||||||
|
|
||||||
|
preparePayResult = await wallet.preparePay({
|
||||||
|
talerPayUri,
|
||||||
|
});
|
||||||
|
|
||||||
|
t.assertTrue(
|
||||||
|
preparePayResult.status === PreparePayResultType.AlreadyConfirmed,
|
||||||
|
);
|
||||||
|
|
||||||
|
await MerchantPrivateApi.giveRefund(merchant, {
|
||||||
|
amount: "TESTKUDOS:5",
|
||||||
|
instance: "default",
|
||||||
|
justification: "foo",
|
||||||
|
orderId: orderResp.order_id,
|
||||||
|
});
|
||||||
|
|
||||||
|
orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
|
||||||
|
orderId: orderResp.order_id,
|
||||||
|
});
|
||||||
|
|
||||||
|
t.assertTrue(orderStatus.order_status === "paid");
|
||||||
|
|
||||||
|
t.assertAmountEquals(orderStatus.refund_amount, "TESTKUDOS:5");
|
||||||
|
|
||||||
|
// Now test what the merchant gives as a response for various requests to the
|
||||||
|
// public order status URL!
|
||||||
|
|
||||||
|
let publicOrderStatusUrl = new URL(
|
||||||
|
`orders/${orderId}`,
|
||||||
|
merchant.makeInstanceBaseUrl(),
|
||||||
|
);
|
||||||
|
publicOrderStatusUrl.searchParams.set(
|
||||||
|
"h_contract",
|
||||||
|
preparePayResult.contractTermsHash,
|
||||||
|
);
|
||||||
|
|
||||||
|
let publicOrderStatusResp = await axios.get(publicOrderStatusUrl.href, {
|
||||||
|
validateStatus: () => true,
|
||||||
|
});
|
||||||
|
console.log(publicOrderStatusResp.data);
|
||||||
|
t.assertTrue(publicOrderStatusResp.status === 200);
|
||||||
|
t.assertAmountEquals(publicOrderStatusResp.data.refund_amount, "TESTKUDOS:5");
|
||||||
|
|
||||||
|
publicOrderStatusUrl = new URL(
|
||||||
|
`orders/${orderId}`,
|
||||||
|
merchant.makeInstanceBaseUrl(),
|
||||||
|
);
|
||||||
|
|
||||||
|
publicOrderStatusResp = await axios.get(publicOrderStatusUrl.href, {
|
||||||
|
validateStatus: () => true,
|
||||||
|
});
|
||||||
|
console.log(publicOrderStatusResp.data);
|
||||||
|
// We didn't give any authentication, so we should get a fulfillment URL back
|
||||||
|
t.assertTrue(publicOrderStatusResp.status === 202);
|
||||||
|
const fu = publicOrderStatusResp.data.fulfillment_message;
|
||||||
|
t.assertTrue(typeof fu === "string" && fu.startsWith("Thank you"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test case for the refund API of the merchant backend.
|
||||||
|
*/
|
||||||
|
runTest(async (t: GlobalTestState) => {
|
||||||
|
// Set up test environment
|
||||||
|
|
||||||
|
const {
|
||||||
|
wallet,
|
||||||
|
bank,
|
||||||
|
exchange,
|
||||||
|
merchant,
|
||||||
|
} = await createSimpleTestkudosEnvironment(t);
|
||||||
|
|
||||||
|
// Withdraw digital cash into the wallet.
|
||||||
|
|
||||||
|
await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
|
||||||
|
|
||||||
|
await testRefundApiWithFulfillmentUrl(t, {
|
||||||
|
wallet,
|
||||||
|
bank,
|
||||||
|
exchange,
|
||||||
|
merchant,
|
||||||
|
});
|
||||||
|
|
||||||
|
await testRefundApiWithFulfillmentMessage(t, {
|
||||||
|
wallet,
|
||||||
|
bank,
|
||||||
|
exchange,
|
||||||
|
merchant,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -8,7 +8,7 @@ import { IDBFactory, IDBDatabase } from "idb-bridge";
|
|||||||
* with each major change. When incrementing the major version,
|
* with each major change. When incrementing the major version,
|
||||||
* the wallet should import data from the previous version.
|
* the wallet should import data from the previous version.
|
||||||
*/
|
*/
|
||||||
const TALER_DB_NAME = "taler-walletdb-v7";
|
const TALER_DB_NAME = "taler-walletdb-v8";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current database minor version, should be incremented
|
* Current database minor version, should be incremented
|
||||||
|
@ -686,7 +686,7 @@ async function processDownloadProposalImpl(
|
|||||||
contractData: {
|
contractData: {
|
||||||
amount,
|
amount,
|
||||||
contractTermsHash: contractTermsHash,
|
contractTermsHash: contractTermsHash,
|
||||||
fulfillmentUrl: parsedContractTerms.fulfillment_url,
|
fulfillmentUrl: parsedContractTerms.fulfillment_url ?? "",
|
||||||
merchantBaseUrl: parsedContractTerms.merchant_base_url,
|
merchantBaseUrl: parsedContractTerms.merchant_base_url,
|
||||||
merchantPub: parsedContractTerms.merchant_pub,
|
merchantPub: parsedContractTerms.merchant_pub,
|
||||||
merchantSig: proposalResp.sig,
|
merchantSig: proposalResp.sig,
|
||||||
|
@ -235,7 +235,6 @@ export async function getTransactions(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const info: OrderShortInfo = {
|
const info: OrderShortInfo = {
|
||||||
fulfillmentUrl: pr.contractData.fulfillmentUrl,
|
|
||||||
merchant: pr.contractData.merchant,
|
merchant: pr.contractData.merchant,
|
||||||
orderId: pr.contractData.orderId,
|
orderId: pr.contractData.orderId,
|
||||||
products: pr.contractData.products,
|
products: pr.contractData.products,
|
||||||
@ -243,6 +242,9 @@ export async function getTransactions(
|
|||||||
summary_i18n: pr.contractData.summaryI18n,
|
summary_i18n: pr.contractData.summaryI18n,
|
||||||
contractTermsHash: pr.contractData.contractTermsHash,
|
contractTermsHash: pr.contractData.contractTermsHash,
|
||||||
};
|
};
|
||||||
|
if (pr.contractData.fulfillmentUrl !== "") {
|
||||||
|
info.fulfillmentUrl = pr.contractData.fulfillmentUrl;
|
||||||
|
}
|
||||||
const paymentTransactionId = makeEventId(
|
const paymentTransactionId = makeEventId(
|
||||||
TransactionType.Payment,
|
TransactionType.Payment,
|
||||||
pr.proposalId,
|
pr.proposalId,
|
||||||
|
@ -1271,7 +1271,14 @@ export interface AllowedExchangeInfo {
|
|||||||
export interface WalletContractData {
|
export interface WalletContractData {
|
||||||
products?: Product[];
|
products?: Product[];
|
||||||
summaryI18n: { [lang_tag: string]: string } | undefined;
|
summaryI18n: { [lang_tag: string]: string } | undefined;
|
||||||
fulfillmentUrl?: string;
|
|
||||||
|
/**
|
||||||
|
* Fulfillment URL, or the empty string if the order has no fulfillment URL.
|
||||||
|
*
|
||||||
|
* Stored as a non-nullable string as we use this field for IndexedDB indexing.
|
||||||
|
*/
|
||||||
|
fulfillmentUrl: string;
|
||||||
|
|
||||||
contractTermsHash: string;
|
contractTermsHash: string;
|
||||||
fulfillmentMessage?: string;
|
fulfillmentMessage?: string;
|
||||||
fulfillmentMessageI18n?: InternationalizedString;
|
fulfillmentMessageI18n?: InternationalizedString;
|
||||||
|
Loading…
Reference in New Issue
Block a user