fix encoded uri, add pay template cta
This commit is contained in:
parent
f404878063
commit
867d2ca76b
@ -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",
|
||||
|
@ -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>;
|
||||
|
@ -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,
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -29,6 +29,6 @@ export default {
|
||||
};
|
||||
|
||||
export const PaymentPossible = tests.createExample(ReadyView, {
|
||||
status: "ready",
|
||||
status: "fill-template",
|
||||
error: undefined,
|
||||
});
|
||||
|
@ -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(
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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 />
|
||||
|
@ -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)}
|
||||
/>
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user