gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] 06/06: fix encoded uri, add pay template cta


From: gnunet
Subject: [taler-wallet-core] 06/06: fix encoded uri, add pay template cta
Date: Fri, 10 Mar 2023 05:27:47 +0100

This is an automated email from the git hooks/post-receive script.

sebasjm pushed a commit to branch master
in repository wallet-core.

commit 867d2ca76b2ca8903b2263a68243899749de7011
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Fri Mar 10 01:27:31 2023 -0300

    fix encoded uri, add pay template cta
---
 .../src/NavigationBar.tsx                          |   2 +-
 .../src/cta/Payment/index.ts                       |   2 +-
 .../src/cta/Payment/test.ts                        |   2 +-
 .../src/cta/PaymentTemplate/index.ts               |  37 ++++-
 .../src/cta/PaymentTemplate/state.ts               | 128 ++++++++++++++++--
 .../src/cta/PaymentTemplate/stories.tsx            |   2 +-
 .../src/cta/PaymentTemplate/test.ts                |   6 +-
 .../src/cta/PaymentTemplate/views.tsx              |  57 +++++++-
 .../taler-wallet-webextension/src/mui/handlers.ts  |   5 +
 .../src/platform/chrome.ts                         |  36 ++++-
 .../src/popup/TalerActionFound.tsx                 | 149 +++++++++++----------
 .../src/wallet/Application.tsx                     |  33 +++--
 .../taler-wallet-webextension/src/wxBackend.ts     |  25 ++--
 13 files changed, 361 insertions(+), 123 deletions(-)

diff --git a/packages/taler-wallet-webextension/src/NavigationBar.tsx 
b/packages/taler-wallet-webextension/src/NavigationBar.tsx
index fb6f280c3..e8ee4f475 100644
--- a/packages/taler-wallet-webextension/src/NavigationBar.tsx
+++ b/packages/taler-wallet-webextension/src/NavigationBar.tsx
@@ -117,7 +117,7 @@ export const Pages = {
 
   cta: pageDefinition<{ action: string }>("/cta/:action"),
   ctaPay: "/cta/pay",
-  ctaPayTemplate: "/cta/payTemplate",
+  ctaPayTemplate: "/cta/pay/template",
   ctaRecovery: "/cta/recovery",
   ctaRefund: "/cta/refund",
   ctaTips: "/cta/tip",
diff --git a/packages/taler-wallet-webextension/src/cta/Payment/index.ts 
b/packages/taler-wallet-webextension/src/cta/Payment/index.ts
index e844c1706..c9bead89c 100644
--- a/packages/taler-wallet-webextension/src/cta/Payment/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/Payment/index.ts
@@ -30,7 +30,7 @@ import { useComponentState } from "./state.js";
 import { BaseView } from "./views.js";
 
 export interface Props {
-  talerPayUri?: string;
+  talerPayUri: string;
   goToWalletManualWithdraw: (amount?: string) => Promise<void>;
   cancel: () => Promise<void>;
   onSuccess: (tx: string) => Promise<void>;
diff --git a/packages/taler-wallet-webextension/src/cta/Payment/test.ts 
b/packages/taler-wallet-webextension/src/cta/Payment/test.ts
index e92eb78c0..f4b63955d 100644
--- a/packages/taler-wallet-webextension/src/cta/Payment/test.ts
+++ b/packages/taler-wallet-webextension/src/cta/Payment/test.ts
@@ -41,7 +41,7 @@ describe("Payment CTA states", () => {
   it("should tell the user that the URI is missing", async () => {
     const { handler, TestingContext } = createWalletApiMock();
     const props = {
-      talerPayUri: undefined,
+      talerPayUri: "",
       cancel: nullFunction,
       goToWalletManualWithdraw: nullFunction,
       onSuccess: nullFunction,
diff --git 
a/packages/taler-wallet-webextension/src/cta/PaymentTemplate/index.ts 
b/packages/taler-wallet-webextension/src/cta/PaymentTemplate/index.ts
index 2cdc8d2e1..f5a8c8814 100644
--- a/packages/taler-wallet-webextension/src/cta/PaymentTemplate/index.ts
+++ b/packages/taler-wallet-webextension/src/cta/PaymentTemplate/index.ts
@@ -20,12 +20,25 @@ import { ErrorAlert } from "../../context/alert.js";
 import { compose, StateViewMap } from "../../utils/index.js";
 import { useComponentState } from "./state.js";
 import { ReadyView } from "./views.js";
+import { PaymentPage } from "../Payment/index.js";
+import {
+  AmountFieldHandler,
+  ButtonHandler,
+  TextFieldHandler,
+} from "../../mui/handlers.js";
 
 export interface Props {
-  talerTemplateUri?: string;
+  talerTemplateUri: string;
+  goToWalletManualWithdraw: (amount?: string) => Promise<void>;
+  cancel: () => Promise<void>;
+  onSuccess: (tx: string) => Promise<void>;
 }
 
-export type State = State.Loading | State.LoadingUriError | State.Ready;
+export type State =
+  | State.Loading
+  | State.LoadingUriError
+  | State.OrderReady
+  | State.FillTemplate;
 
 export namespace State {
   export interface Loading {
@@ -37,16 +50,30 @@ export namespace State {
     error: ErrorAlert;
   }
 
-  export interface Ready {
-    status: "ready";
+  export interface FillTemplate {
+    status: "fill-template";
     error: undefined;
+    currency: string;
+    amount?: AmountFieldHandler;
+    summary?: TextFieldHandler;
+    onCreate: ButtonHandler;
+  }
+
+  export interface OrderReady {
+    status: "order-ready";
+    error: undefined;
+    talerPayUri: string;
+    onSuccess: (tx: string) => Promise<void>;
+    cancel: () => Promise<void>;
+    goToWalletManualWithdraw: () => Promise<void>;
   }
 }
 
 const viewMapping: StateViewMap<State> = {
   loading: Loading,
   error: ErrorAlertView,
-  ready: ReadyView,
+  "fill-template": ReadyView,
+  "order-ready": PaymentPage,
 };
 
 export const PaymentTemplatePage = compose(
diff --git 
a/packages/taler-wallet-webextension/src/cta/PaymentTemplate/state.ts 
b/packages/taler-wallet-webextension/src/cta/PaymentTemplate/state.ts
index f5e6dee61..abcf040b7 100644
--- a/packages/taler-wallet-webextension/src/cta/PaymentTemplate/state.ts
+++ b/packages/taler-wallet-webextension/src/cta/PaymentTemplate/state.ts
@@ -14,27 +14,56 @@
  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
  */
 
+import { Amounts } from "@gnu-taler/taler-util";
 import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { alertFromError } from "../../context/alert.js";
+import { useState } from "preact/hooks";
+import { alertFromError, useAlertContext } from "../../context/alert.js";
 import { useBackendContext } from "../../context/backend.js";
 import { useTranslationContext } from "../../context/translation.js";
 import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
+import { AmountFieldHandler, TextFieldHandler } from "../../mui/handlers.js";
 import { Props, State } from "./index.js";
 
-export function useComponentState({ talerTemplateUri }: Props): State {
-  // const { pushAlertOnError } = useAlertContext();
+export function useComponentState({
+  talerTemplateUri,
+  cancel,
+  goToWalletManualWithdraw,
+  onSuccess,
+}: Props): State {
   const api = useBackendContext();
   const { i18n } = useTranslationContext();
+  const { safely } = useAlertContext();
+
+  const url = talerTemplateUri ? new URL(talerTemplateUri) : undefined;
+
+  const amountParam = !url
+    ? undefined
+    : url.searchParams.get("amount") ?? undefined;
+  const summaryParam = !url
+    ? undefined
+    : url.searchParams.get("summary") ?? undefined;
+
+  const parsedAmount = !amountParam ? undefined : Amounts.parse(amountParam);
+  const currency = parsedAmount ? parsedAmount.currency : amountParam;
+
+  const initialAmount =
+    parsedAmount ?? (currency ? Amounts.zeroOfCurrency(currency) : undefined);
+  const [amount, setAmount] = useState(initialAmount);
+  const [summary, setSummary] = useState(summaryParam);
+  const [newOrder, setNewOrder] = useState("");
 
   const hook = useAsyncAsHook(async () => {
     if (!talerTemplateUri) throw Error("ERROR_NO-URI-FOR-PAYMENT-TEMPLATE");
-    const payStatus = await api.wallet.call(
-      WalletApiOperation.PreparePayForTemplate,
-      {
-        talerPayTemplateUri: talerTemplateUri,
-        templateParams: {},
-      },
-    );
+    let payStatus;
+    if (!amountParam && !summaryParam) {
+      payStatus = await api.wallet.call(
+        WalletApiOperation.PreparePayForTemplate,
+        {
+          talerPayTemplateUri: talerTemplateUri,
+          templateParams: {},
+        },
+      );
+    }
     const balance = await api.wallet.call(WalletApiOperation.GetBalances, {});
     return { payStatus, balance, uri: talerTemplateUri };
   }, []);
@@ -56,8 +85,85 @@ export function useComponentState({ talerTemplateUri }: 
Props): State {
     };
   }
 
+  if (hook.response.payStatus) {
+    return {
+      status: "order-ready",
+      error: undefined,
+      cancel,
+      goToWalletManualWithdraw,
+      onSuccess,
+      talerPayUri: hook.response.payStatus.talerUri!,
+    };
+  }
+
+  if (newOrder) {
+    return {
+      status: "order-ready",
+      error: undefined,
+      cancel,
+      goToWalletManualWithdraw,
+      onSuccess,
+      talerPayUri: newOrder,
+    };
+  }
+
+  async function createOrder() {
+    try {
+      const templateParams: Record<string, string> = {};
+      if (amount) {
+        templateParams["amount"] = Amounts.stringify(amount);
+      }
+      if (summary) {
+        templateParams["summary"] = summary;
+      }
+      const payStatus = await api.wallet.call(
+        WalletApiOperation.PreparePayForTemplate,
+        {
+          talerPayTemplateUri: talerTemplateUri,
+          templateParams,
+        },
+      );
+      setNewOrder(payStatus.talerUri!);
+    } catch (e) {}
+  }
+  const errors = undefinedIfEmpty({
+    amount: amount && Amounts.isZero(amount) ? i18n.str`required` : undefined,
+    summary: !summary ? i18n.str`required` : undefined,
+  });
   return {
-    status: "ready",
+    status: "fill-template",
     error: undefined,
+    currency: currency!, //currency is always not null
+    amount:
+      amount !== undefined
+        ? ({
+            onInput: (a) => {
+              setAmount(a);
+            },
+            value: amount,
+            error: errors?.amount,
+          } as AmountFieldHandler)
+        : undefined,
+    summary:
+      summary !== undefined
+        ? ({
+            onInput: (t) => {
+              setSummary(t);
+            },
+            value: summary,
+            error: errors?.summary,
+          } as TextFieldHandler)
+        : undefined,
+    onCreate: {
+      onClick: errors
+        ? undefined
+        : safely(createOrder, i18n.str`Could not create order`),
+    },
   };
 }
+
+function undefinedIfEmpty<T extends object>(obj: T): T | undefined {
+  return Object.keys(obj).some((k) => (obj as any)[k] !== undefined)
+    ? obj
+    : undefined;
+}
diff --git 
a/packages/taler-wallet-webextension/src/cta/PaymentTemplate/stories.tsx 
b/packages/taler-wallet-webextension/src/cta/PaymentTemplate/stories.tsx
index 32a080959..93421eaa3 100644
--- a/packages/taler-wallet-webextension/src/cta/PaymentTemplate/stories.tsx
+++ b/packages/taler-wallet-webextension/src/cta/PaymentTemplate/stories.tsx
@@ -29,6 +29,6 @@ export default {
 };
 
 export const PaymentPossible = tests.createExample(ReadyView, {
-  status: "ready",
+  status: "fill-template",
   error: undefined,
 });
diff --git a/packages/taler-wallet-webextension/src/cta/PaymentTemplate/test.ts 
b/packages/taler-wallet-webextension/src/cta/PaymentTemplate/test.ts
index d4c65e008..72fbb6853 100644
--- a/packages/taler-wallet-webextension/src/cta/PaymentTemplate/test.ts
+++ b/packages/taler-wallet-webextension/src/cta/PaymentTemplate/test.ts
@@ -21,6 +21,7 @@
 
 import { expect } from "chai";
 import { tests } from "../../../../web-util/src/index.browser.js";
+import { nullFunction } from "../../mui/handlers.js";
 import { createWalletApiMock } from "../../test-utils.js";
 import { useComponentState } from "./state.js";
 
@@ -28,7 +29,10 @@ describe("Order template CTA states", () => {
   it("should tell the user that the URI is missing", async () => {
     const { handler, TestingContext } = createWalletApiMock();
     const props = {
-      talerTemplateUri: undefined,
+      talerTemplateUri: "",
+      cancel: nullFunction,
+      goToWalletManualWithdraw: nullFunction,
+      onSuccess: nullFunction,
     };
 
     const hookBehavior = await tests.hookBehaveLikeThis(
diff --git 
a/packages/taler-wallet-webextension/src/cta/PaymentTemplate/views.tsx 
b/packages/taler-wallet-webextension/src/cta/PaymentTemplate/views.tsx
index d3f893c7e..9f4c0f28c 100644
--- a/packages/taler-wallet-webextension/src/cta/PaymentTemplate/views.tsx
+++ b/packages/taler-wallet-webextension/src/cta/PaymentTemplate/views.tsx
@@ -15,15 +15,64 @@
  */
 
 import { Fragment, h, VNode } from "preact";
+import { AmountField } from "../../components/AmountField.js";
+import { Part } from "../../components/Part.js";
 import { useTranslationContext } from "../../context/translation.js";
+import { Button } from "../../mui/Button.js";
+import { TextField } from "../../mui/TextField.js";
 import { State } from "./index.js";
 
-export function ReadyView({ status }: State.Ready): VNode {
+export function ReadyView({
+  currency,
+  amount,
+  summary,
+  onCreate,
+}: State.FillTemplate): VNode {
   const { i18n } = useTranslationContext();
 
+  console.log("is summary", !!summary);
   return (
-    <div>
-      <i18n.Translate>Not yet implemented</i18n.Translate>
-    </div>
+    <Fragment>
+      <section style={{ textAlign: "left" }}>
+        {/* <Part
+          title={
+            <div
+              style={{
+                display: "flex",
+                alignItems: "center",
+              }}
+            >
+              <i18n.Translate>Merchant</i18n.Translate>
+            </div>
+          }
+          text={<ExchangeDetails exchange={exchangeUrl} />}
+          kind="neutral"
+          big
+        /> */}
+        {!amount ? undefined : (
+          <p>
+            <AmountField label={i18n.str`Amount`} handler={amount} />
+          </p>
+        )}
+        {!summary ? undefined : (
+          <p>
+            <TextField
+              label="Summary"
+              variant="filled"
+              required
+              fullWidth
+              error={summary.error}
+              value={summary.value}
+              onChange={summary.onInput}
+            />
+          </p>
+        )}
+      </section>
+      <section>
+        <Button onClick={onCreate.onClick} variant="contained" color="success">
+          <i18n.Translate>Review order</i18n.Translate>
+        </Button>
+      </section>
+    </Fragment>
   );
 }
diff --git a/packages/taler-wallet-webextension/src/mui/handlers.ts 
b/packages/taler-wallet-webextension/src/mui/handlers.ts
index 61786742f..0bc00ca45 100644
--- a/packages/taler-wallet-webextension/src/mui/handlers.ts
+++ b/packages/taler-wallet-webextension/src/mui/handlers.ts
@@ -56,6 +56,11 @@ export const nullFunction = async function (): Promise<void> 
{
   //do nothing
 } as SafeHandler<void>;
 
+//FIXME: UI button should required SafeHandler but
+//useStateComponent should not be required to create SafeHandlers
+//so this need to be splitted in two:
+// * ButtonHandlerUI =>  with i18n
+// * ButtonHandlerLogic => without i18n
 export interface ButtonHandler {
   onClick?: SafeHandler<void>;
   // error?: TalerError;
diff --git a/packages/taler-wallet-webextension/src/platform/chrome.ts 
b/packages/taler-wallet-webextension/src/platform/chrome.ts
index beb65b2d0..4b0bdbfb7 100644
--- a/packages/taler-wallet-webextension/src/platform/chrome.ts
+++ b/packages/taler-wallet-webextension/src/platform/chrome.ts
@@ -241,41 +241,63 @@ function openWalletURIFromPopup(maybeTalerUri: string): 
void {
     : maybeTalerUri;
   const uriType = classifyTalerUri(talerUri);
 
+  encodeURIComponent;
   let url: string | undefined = undefined;
   switch (uriType) {
     case TalerUriType.TalerWithdraw:
       url = chrome.runtime.getURL(
-        `static/wallet.html#/cta/withdraw?talerWithdrawUri=${talerUri}`,
+        
`static/wallet.html#/cta/withdraw?talerWithdrawUri=${encodeURIComponent(
+          talerUri,
+        )}`,
       );
       break;
     case TalerUriType.TalerRecovery:
       url = chrome.runtime.getURL(
-        `static/wallet.html#/cta/recovery?talerRecoveryUri=${talerUri}`,
+        
`static/wallet.html#/cta/recovery?talerRecoveryUri=${encodeURIComponent(
+          talerUri,
+        )}`,
       );
       break;
     case TalerUriType.TalerPay:
       url = chrome.runtime.getURL(
-        `static/wallet.html#/cta/pay?talerPayUri=${talerUri}`,
+        `static/wallet.html#/cta/pay?talerPayUri=${encodeURIComponent(
+          talerUri,
+        )}`,
       );
       break;
     case TalerUriType.TalerTip:
       url = chrome.runtime.getURL(
-        `static/wallet.html#/cta/tip?talerTipUri=${talerUri}`,
+        `static/wallet.html#/cta/tip?talerTipUri=${encodeURIComponent(
+          talerUri,
+        )}`,
       );
       break;
     case TalerUriType.TalerRefund:
       url = chrome.runtime.getURL(
-        `static/wallet.html#/cta/refund?talerRefundUri=${talerUri}`,
+        `static/wallet.html#/cta/refund?talerRefundUri=${encodeURIComponent(
+          talerUri,
+        )}`,
       );
       break;
     case TalerUriType.TalerPayPull:
       url = chrome.runtime.getURL(
-        `static/wallet.html#/cta/invoice/pay?talerPayPullUri=${talerUri}`,
+        
`static/wallet.html#/cta/invoice/pay?talerPayPullUri=${encodeURIComponent(
+          talerUri,
+        )}`,
       );
       break;
     case TalerUriType.TalerPayPush:
       url = chrome.runtime.getURL(
-        `static/wallet.html#/cta/transfer/pickup?talerPayPushUri=${talerUri}`,
+        
`static/wallet.html#/cta/transfer/pickup?talerPayPushUri=${encodeURIComponent(
+          talerUri,
+        )}`,
+      );
+      break;
+    case TalerUriType.TalerPayTemplate:
+      url = chrome.runtime.getURL(
+        
`static/wallet.html#/cta/pay/template?talerPayTemplateUri=${encodeURIComponent(
+          talerUri,
+        )}`,
       );
       break;
     case TalerUriType.Unknown:
diff --git a/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx 
b/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx
index 5c435a9a5..205e42d20 100644
--- a/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx
+++ b/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx
@@ -31,6 +31,86 @@ export interface Props {
   onDismiss: () => Promise<void>;
 }
 
+function ContentByUriType({
+  type,
+  onConfirm,
+}: {
+  type: TalerUriType;
+  onConfirm: () => Promise<void>;
+}) {
+  const { i18n } = useTranslationContext();
+  switch (type) {
+    case TalerUriType.TalerWithdraw:
+      return (
+        <div>
+          <p>
+            <i18n.Translate>This page has a withdrawal action.</i18n.Translate>
+          </p>
+          <Button variant="contained" color="success" onClick={onConfirm}>
+            <i18n.Translate>Open withdraw page</i18n.Translate>
+          </Button>
+        </div>
+      );
+
+    case TalerUriType.TalerPayTemplate:
+    case TalerUriType.TalerPay:
+      return (
+        <div>
+          <p>
+            <i18n.Translate>This page has pay action.</i18n.Translate>
+          </p>
+          <Button variant="contained" color="success" onClick={onConfirm}>
+            <i18n.Translate>Open pay page</i18n.Translate>
+          </Button>
+        </div>
+      );
+    case TalerUriType.TalerTip:
+      return (
+        <div>
+          <p>
+            <i18n.Translate>This page has a tip action.</i18n.Translate>
+          </p>
+          <Button variant="contained" color="success" onClick={onConfirm}>
+            <i18n.Translate>Open tip page</i18n.Translate>
+          </Button>
+        </div>
+      );
+
+    case TalerUriType.TalerRefund:
+      return (
+        <div>
+          <p>
+            <i18n.Translate>This page has a refund action.</i18n.Translate>
+          </p>
+          <Button variant="contained" color="success" onClick={onConfirm}>
+            <i18n.Translate>Open refund page</i18n.Translate>
+          </Button>
+        </div>
+      );
+
+    case TalerUriType.TalerDevExperiment:
+    case TalerUriType.TalerTemplate:
+    case TalerUriType.TalerPayPull:
+    case TalerUriType.TalerPayPush:
+    case TalerUriType.TalerRecovery:
+    case TalerUriType.Unknown:
+      return (
+        <div>
+          <p>
+            <i18n.Translate>
+              This page has a malformed taler uri.
+            </i18n.Translate>
+          </p>
+        </div>
+      );
+
+    default: {
+      const error: never = type;
+      return null;
+    }
+  }
+}
+
 export function TalerActionFound({ url, onDismiss }: Props): VNode {
   const uriType = classifyTalerUri(url);
   const { i18n } = useTranslationContext();
@@ -43,74 +123,7 @@ export function TalerActionFound({ url, onDismiss }: 
Props): VNode {
         <Title>
           <i18n.Translate>Taler Action</i18n.Translate>
         </Title>
-        {uriType === TalerUriType.TalerPay && (
-          <div>
-            <p>
-              <i18n.Translate>This page has pay action.</i18n.Translate>
-            </p>
-            <Button
-              variant="contained"
-              color="success"
-              onClick={redirectToWallet}
-            >
-              <i18n.Translate>Open pay page</i18n.Translate>
-            </Button>
-          </div>
-        )}
-        {uriType === TalerUriType.TalerWithdraw && (
-          <div>
-            <p>
-              <i18n.Translate>
-                This page has a withdrawal action.
-              </i18n.Translate>
-            </p>
-            <Button
-              variant="contained"
-              color="success"
-              onClick={redirectToWallet}
-            >
-              <i18n.Translate>Open withdraw page</i18n.Translate>
-            </Button>
-          </div>
-        )}
-        {uriType === TalerUriType.TalerTip && (
-          <div>
-            <p>
-              <i18n.Translate>This page has a tip action.</i18n.Translate>
-            </p>
-            <Button
-              variant="contained"
-              color="success"
-              onClick={redirectToWallet}
-            >
-              <i18n.Translate>Open tip page</i18n.Translate>
-            </Button>
-          </div>
-        )}
-        {uriType === TalerUriType.TalerRefund && (
-          <div>
-            <p>
-              <i18n.Translate>This page has a refund action.</i18n.Translate>
-            </p>
-            <Button
-              variant="contained"
-              color="success"
-              onClick={redirectToWallet}
-            >
-              <i18n.Translate>Open refund page</i18n.Translate>
-            </Button>
-          </div>
-        )}
-        {uriType === TalerUriType.Unknown && (
-          <div>
-            <p>
-              <i18n.Translate>
-                This page has a malformed taler uri.
-              </i18n.Translate>
-            </p>
-            <p>{url}</p>
-          </div>
-        )}
+        <ContentByUriType type={uriType} onConfirm={redirectToWallet} />
       </section>
       <footer>
         <div />
diff --git a/packages/taler-wallet-webextension/src/wallet/Application.tsx 
b/packages/taler-wallet-webextension/src/wallet/Application.tsx
index f29c169d0..fc8ddb804 100644
--- a/packages/taler-wallet-webextension/src/wallet/Application.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Application.tsx
@@ -289,7 +289,7 @@ export function Application(): VNode {
               component={({ talerPayUri }: { talerPayUri: string }) => (
                 <CallToActionTemplate title={i18n.str`Digital cash payment`}>
                   <PaymentPage
-                    talerPayUri={talerPayUri}
+                    talerPayUri={decodeURIComponent(talerPayUri)}
                     goToWalletManualWithdraw={(amount?: string) =>
                       redirectTo(Pages.receiveCash({ amount }))
                     }
@@ -302,14 +302,23 @@ export function Application(): VNode {
               )}
             />
             <Route
-              path={Pages.ctaPay}
+              path={Pages.ctaPayTemplate}
               component={({
-                talerTemplateUri,
+                talerPayTemplateUri,
               }: {
-                talerTemplateUri: string;
+                talerPayTemplateUri: string;
               }) => (
                 <CallToActionTemplate title={i18n.str`Digital cash payment`}>
-                  <PaymentTemplatePage talerTemplateUri={talerTemplateUri} />
+                  <PaymentTemplatePage
+                    talerTemplateUri={decodeURIComponent(talerPayTemplateUri)}
+                    goToWalletManualWithdraw={(amount?: string) =>
+                      redirectTo(Pages.receiveCash({ amount }))
+                    }
+                    cancel={() => redirectTo(Pages.balance)}
+                    onSuccess={(tid: string) =>
+                      redirectTo(Pages.balanceTransaction({ tid }))
+                    }
+                  />
                 </CallToActionTemplate>
               )}
             />
@@ -318,7 +327,7 @@ export function Application(): VNode {
               component={({ talerRefundUri }: { talerRefundUri: string }) => (
                 <CallToActionTemplate title={i18n.str`Digital cash refund`}>
                   <RefundPage
-                    talerRefundUri={talerRefundUri}
+                    talerRefundUri={decodeURIComponent(talerRefundUri)}
                     cancel={() => redirectTo(Pages.balance)}
                     onSuccess={(tid: string) =>
                       redirectTo(Pages.balanceTransaction({ tid }))
@@ -332,7 +341,7 @@ export function Application(): VNode {
               component={({ talerTipUri }: { talerTipUri: string }) => (
                 <CallToActionTemplate title={i18n.str`Digital cash tip`}>
                   <TipPage
-                    talerTipUri={talerTipUri}
+                    talerTipUri={decodeURIComponent(talerTipUri)}
                     onCancel={() => redirectTo(Pages.balance)}
                     onSuccess={(tid: string) =>
                       redirectTo(Pages.balanceTransaction({ tid }))
@@ -350,7 +359,7 @@ export function Application(): VNode {
               }) => (
                 <CallToActionTemplate title={i18n.str`Digital cash 
withdrawal`}>
                   <WithdrawPageFromURI
-                    talerWithdrawUri={talerWithdrawUri}
+                    talerWithdrawUri={decodeURIComponent(talerWithdrawUri)}
                     cancel={() => redirectTo(Pages.balance)}
                     onSuccess={(tid: string) =>
                       redirectTo(Pages.balanceTransaction({ tid }))
@@ -385,7 +394,7 @@ export function Application(): VNode {
                 <CallToActionTemplate title={i18n.str`Digital cash deposit`}>
                   <DepositPageCTA
                     amountStr={amount}
-                    talerDepositUri={talerDepositUri}
+                    talerDepositUri={decodeURIComponent(talerDepositUri)}
                     cancel={() => redirectTo(Pages.balance)}
                     onSuccess={(tid: string) =>
                       redirectTo(Pages.balanceTransaction({ tid }))
@@ -427,7 +436,7 @@ export function Application(): VNode {
               component={({ talerPayPullUri }: { talerPayPullUri: string }) => 
(
                 <CallToActionTemplate title={i18n.str`Digital cash invoice`}>
                   <InvoicePayPage
-                    talerPayPullUri={talerPayPullUri}
+                    talerPayPullUri={decodeURIComponent(talerPayPullUri)}
                     goToWalletManualWithdraw={(amount?: string) =>
                       redirectTo(Pages.receiveCash({ amount }))
                     }
@@ -444,7 +453,7 @@ export function Application(): VNode {
               component={({ talerPayPushUri }: { talerPayPushUri: string }) => 
(
                 <CallToActionTemplate title={i18n.str`Digital cash transfer`}>
                   <TransferPickupPage
-                    talerPayPushUri={talerPayPushUri}
+                    talerPayPushUri={decodeURIComponent(talerPayPushUri)}
                     onClose={() => redirectTo(Pages.balance)}
                     onSuccess={(tid: string) =>
                       redirectTo(Pages.balanceTransaction({ tid }))
@@ -462,7 +471,7 @@ export function Application(): VNode {
               }) => (
                 <CallToActionTemplate title={i18n.str`Digital cash recovery`}>
                   <RecoveryPage
-                    talerRecoveryUri={talerRecoveryUri}
+                    talerRecoveryUri={decodeURIComponent(talerRecoveryUri)}
                     onCancel={() => redirectTo(Pages.balance)}
                     onSuccess={() => redirectTo(Pages.backup)}
                   />
diff --git a/packages/taler-wallet-webextension/src/wxBackend.ts 
b/packages/taler-wallet-webextension/src/wxBackend.ts
index cca07941a..3655c5dbc 100644
--- a/packages/taler-wallet-webextension/src/wxBackend.ts
+++ b/packages/taler-wallet-webextension/src/wxBackend.ts
@@ -337,38 +337,44 @@ function parseTalerUriAndRedirect(tabId: number, 
maybeTalerUri: string): void {
     case TalerUriType.TalerWithdraw:
       return platform.redirectTabToWalletPage(
         tabId,
-        `/cta/withdraw?talerWithdrawUri=${talerUri}`,
+        `/cta/withdraw?talerWithdrawUri=${encodeURIComponent(talerUri)}`,
       );
     case TalerUriType.TalerPay:
       return platform.redirectTabToWalletPage(
         tabId,
-        `/cta/pay?talerPayUri=${talerUri}`,
+        `/cta/pay?talerPayUri=${encodeURIComponent(talerUri)}`,
       );
     case TalerUriType.TalerTip:
       return platform.redirectTabToWalletPage(
         tabId,
-        `/cta/tip?talerTipUri=${talerUri}`,
+        `/cta/tip?talerTipUri=${encodeURIComponent(talerUri)}`,
       );
     case TalerUriType.TalerRefund:
       return platform.redirectTabToWalletPage(
         tabId,
-        `/cta/refund?talerRefundUri=${talerUri}`,
+        `/cta/refund?talerRefundUri=${encodeURIComponent(talerUri)}`,
       );
     case TalerUriType.TalerPayPull:
       return platform.redirectTabToWalletPage(
         tabId,
-        `/cta/invoice/pay?talerPayPullUri=${talerUri}`,
+        `/cta/invoice/pay?talerPayPullUri=${encodeURIComponent(talerUri)}`,
       );
     case TalerUriType.TalerPayPush:
       return platform.redirectTabToWalletPage(
         tabId,
-        `/cta/transfer/pickup?talerPayPushUri=${talerUri}`,
+        `/cta/transfer/pickup?talerPayPushUri=${encodeURIComponent(talerUri)}`,
       );
     case TalerUriType.TalerRecovery:
       return platform.redirectTabToWalletPage(
         tabId,
-        `/cta/transfer/recovery?talerBackupUri=${talerUri}`,
+        
`/cta/transfer/recovery?talerBackupUri=${encodeURIComponent(talerUri)}`,
       );
+    case TalerUriType.TalerPayTemplate:
+      return platform.redirectTabToWalletPage(
+        tabId,
+        
`/cta/pay/template?talerPayTemplateUri=${encodeURIComponent(talerUri)}`,
+      );
+      return;
     case TalerUriType.Unknown:
       logger.warn(
         `Response with HTTP 402 the Taler header but could not classify 
${talerUri}`,
@@ -379,10 +385,7 @@ function parseTalerUriAndRedirect(tabId: number, 
maybeTalerUri: string): void {
       logger.warn("not implemented");
       return;
     case TalerUriType.TalerTemplate:
-      return platform.redirectTabToWalletPage(
-        tabId,
-        `/cta/template?talerTemplateUri=${talerUri}`,
-      );
+      logger.warn("not implemented");
       return;
     default: {
       const error: never = uriType;

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]