aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2020-08-24 20:00:15 +0530
committerFlorian Dold <florian.dold@gmail.com>2020-08-24 20:00:15 +0530
commit7deefd5b2d58a9dc2ba91b2b824d4135a4e0837e (patch)
tree00dbbafdff84fd95ff956d852fbb493ada6099dc
parent0e88ef9bd2ea76e5b44cc0d4459b9a2e553b8d24 (diff)
fix wallet DB
-rw-r--r--packages/taler-integrationtests/src/test-merchant-refund-api.ts189
-rw-r--r--packages/taler-wallet-core/src/db.ts2
-rw-r--r--packages/taler-wallet-core/src/operations/pay.ts2
-rw-r--r--packages/taler-wallet-core/src/operations/transactions.ts4
-rw-r--r--packages/taler-wallet-core/src/types/dbTypes.ts9
5 files changed, 182 insertions, 24 deletions
diff --git a/packages/taler-integrationtests/src/test-merchant-refund-api.ts b/packages/taler-integrationtests/src/test-merchant-refund-api.ts
index 61f08780c..92d635b2c 100644
--- a/packages/taler-integrationtests/src/test-merchant-refund-api.ts
+++ b/packages/taler-integrationtests/src/test-merchant-refund-api.ts
@@ -17,35 +17,150 @@
/**
* Imports.
*/
-import { runTest, GlobalTestState, MerchantPrivateApi } from "./harness";
-import { createSimpleTestkudosEnvironment, withdrawViaBank } from "./helpers";
+import {
+ runTest,
+ GlobalTestState,
+ MerchantPrivateApi,
+ MerchantService,
+ BankServiceInterface,
+ MerchantServiceInterface,
+ WalletCli,
+ ExchangeServiceInterface,
+} from "./harness";
+import {
+ createSimpleTestkudosEnvironment,
+ withdrawViaBank,
+ SimpleTestEnvironment,
+} from "./helpers";
import { PreparePayResultType, URL } from "taler-wallet-core";
import axios from "axios";
-/**
- * Test case for the refund API of the merchant backend.
- */
-runTest(async (t: GlobalTestState) => {
- // Set up test environment
+async function testRefundApiWithFulfillmentUrl(
+ t: GlobalTestState,
+ env: {
+ merchant: MerchantServiceInterface;
+ bank: BankServiceInterface;
+ wallet: WalletCli;
+ exchange: ExchangeServiceInterface;
+ },
+): Promise<void> {
+ const { wallet, bank, exchange, merchant } = env;
- const {
- wallet,
- bank,
- exchange,
- merchant,
- } = await createSimpleTestkudosEnvironment(t);
+ // Set up order.
+ const orderResp = await MerchantPrivateApi.createOrder(merchant, "default", {
+ order: {
+ summary: "Buy me!",
+ amount: "TESTKUDOS:5",
+ fulfillment_url: "https://example.com/fulfillment",
+ },
+ });
- // Withdraw digital cash into the wallet.
+ let orderStatus = await MerchantPrivateApi.queryPrivateOrderStatus(merchant, {
+ orderId: orderResp.order_id,
+ });
- await withdrawViaBank(t, { wallet, bank, exchange, amount: "TESTKUDOS:20" });
+ t.assertTrue(orderStatus.order_status === "unpaid");
- // Set up order.
+ 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_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_url: "taler://fulfillment-success/thx",
+ fulfillment_message: "Thank you for buying foobar",
},
});
@@ -131,7 +246,41 @@ runTest(async (t: GlobalTestState) => {
publicOrderStatusResp = await axios.get(publicOrderStatusUrl.href, {
validateStatus: () => true,
});
- console.log(publicOrderStatusResp.data)
- // We didn't give any authentication, so this should be forbidden
- t.assertTrue(publicOrderStatusResp.status === 403);
+ 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,
+ });
});
diff --git a/packages/taler-wallet-core/src/db.ts b/packages/taler-wallet-core/src/db.ts
index f4d0b911e..a55d9bb16 100644
--- a/packages/taler-wallet-core/src/db.ts
+++ b/packages/taler-wallet-core/src/db.ts
@@ -8,7 +8,7 @@ import { IDBFactory, IDBDatabase } from "idb-bridge";
* with each major change. When incrementing the major 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
diff --git a/packages/taler-wallet-core/src/operations/pay.ts b/packages/taler-wallet-core/src/operations/pay.ts
index 6b45e3da2..7b8a1efac 100644
--- a/packages/taler-wallet-core/src/operations/pay.ts
+++ b/packages/taler-wallet-core/src/operations/pay.ts
@@ -686,7 +686,7 @@ async function processDownloadProposalImpl(
contractData: {
amount,
contractTermsHash: contractTermsHash,
- fulfillmentUrl: parsedContractTerms.fulfillment_url,
+ fulfillmentUrl: parsedContractTerms.fulfillment_url ?? "",
merchantBaseUrl: parsedContractTerms.merchant_base_url,
merchantPub: parsedContractTerms.merchant_pub,
merchantSig: proposalResp.sig,
diff --git a/packages/taler-wallet-core/src/operations/transactions.ts b/packages/taler-wallet-core/src/operations/transactions.ts
index 7b42b9a5f..d869ed770 100644
--- a/packages/taler-wallet-core/src/operations/transactions.ts
+++ b/packages/taler-wallet-core/src/operations/transactions.ts
@@ -235,7 +235,6 @@ export async function getTransactions(
return;
}
const info: OrderShortInfo = {
- fulfillmentUrl: pr.contractData.fulfillmentUrl,
merchant: pr.contractData.merchant,
orderId: pr.contractData.orderId,
products: pr.contractData.products,
@@ -243,6 +242,9 @@ export async function getTransactions(
summary_i18n: pr.contractData.summaryI18n,
contractTermsHash: pr.contractData.contractTermsHash,
};
+ if (pr.contractData.fulfillmentUrl !== "") {
+ info.fulfillmentUrl = pr.contractData.fulfillmentUrl;
+ }
const paymentTransactionId = makeEventId(
TransactionType.Payment,
pr.proposalId,
diff --git a/packages/taler-wallet-core/src/types/dbTypes.ts b/packages/taler-wallet-core/src/types/dbTypes.ts
index 79100b69f..0b2de8b0c 100644
--- a/packages/taler-wallet-core/src/types/dbTypes.ts
+++ b/packages/taler-wallet-core/src/types/dbTypes.ts
@@ -1271,7 +1271,14 @@ export interface AllowedExchangeInfo {
export interface WalletContractData {
products?: Product[];
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;
fulfillmentMessage?: string;
fulfillmentMessageI18n?: InternationalizedString;