case-insensitive URIs
This commit is contained in:
parent
b4d36fca18
commit
ee1fc03ae8
@ -699,11 +699,11 @@ export class ProposalDownload {
|
|||||||
*/
|
*/
|
||||||
@Checkable.Class()
|
@Checkable.Class()
|
||||||
export class ProposalRecord {
|
export class ProposalRecord {
|
||||||
/**
|
|
||||||
* URL where the proposal was downloaded.
|
|
||||||
*/
|
|
||||||
@Checkable.String()
|
@Checkable.String()
|
||||||
url: string;
|
orderId: string;
|
||||||
|
|
||||||
|
@Checkable.String()
|
||||||
|
merchantBaseUrl: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Downloaded data from the merchant.
|
* Downloaded data from the merchant.
|
||||||
@ -970,7 +970,6 @@ export interface WireFee {
|
|||||||
sig: string;
|
sig: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Record that stores status information about one purchase, starting from when
|
* Record that stores status information about one purchase, starting from when
|
||||||
* the customer accepts a proposal. Includes refund status if applicable.
|
* the customer accepts a proposal. Includes refund status if applicable.
|
||||||
@ -1242,7 +1241,10 @@ export namespace Stores {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super("proposals", { keyPath: "proposalId" });
|
super("proposals", { keyPath: "proposalId" });
|
||||||
}
|
}
|
||||||
urlIndex = new Index<string, ProposalRecord>(this, "urlIndex", "url");
|
urlAndOrderIdIndex = new Index<string, ProposalRecord>(this, "urlIndex", [
|
||||||
|
"merchantBaseUrl",
|
||||||
|
"orderId",
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
class PurchasesStore extends Store<PurchaseRecord> {
|
class PurchasesStore extends Store<PurchaseRecord> {
|
||||||
|
@ -28,6 +28,7 @@ import * as Amounts from "../util/amounts";
|
|||||||
import { decodeCrock } from "../crypto/talerCrypto";
|
import { decodeCrock } from "../crypto/talerCrypto";
|
||||||
import { OperationFailedAndReportedError } from "../wallet-impl/errors";
|
import { OperationFailedAndReportedError } from "../wallet-impl/errors";
|
||||||
import { Bank } from "./bank";
|
import { Bank } from "./bank";
|
||||||
|
import { classifyTalerUri, TalerUriType } from "../util/taleruri";
|
||||||
|
|
||||||
const logger = new Logger("taler-wallet-cli.ts");
|
const logger = new Logger("taler-wallet-cli.ts");
|
||||||
|
|
||||||
@ -212,15 +213,23 @@ walletCli
|
|||||||
.action(async args => {
|
.action(async args => {
|
||||||
await withWallet(args, async wallet => {
|
await withWallet(args, async wallet => {
|
||||||
const uri: string = args.handleUri.uri;
|
const uri: string = args.handleUri.uri;
|
||||||
if (uri.startsWith("taler://pay/")) {
|
const uriType = classifyTalerUri(uri);
|
||||||
|
switch (uriType) {
|
||||||
|
case TalerUriType.TalerPay:
|
||||||
await doPay(wallet, uri, { alwaysYes: args.handleUri.autoYes });
|
await doPay(wallet, uri, { alwaysYes: args.handleUri.autoYes });
|
||||||
} else if (uri.startsWith("taler://tip/")) {
|
break;
|
||||||
|
case TalerUriType.TalerTip:
|
||||||
|
{
|
||||||
const res = await wallet.getTipStatus(uri);
|
const res = await wallet.getTipStatus(uri);
|
||||||
console.log("tip status", res);
|
console.log("tip status", res);
|
||||||
await wallet.acceptTip(res.tipId);
|
await wallet.acceptTip(res.tipId);
|
||||||
} else if (uri.startsWith("taler://refund/")) {
|
}
|
||||||
|
break;
|
||||||
|
case TalerUriType.TalerRefund:
|
||||||
await wallet.applyRefund(uri);
|
await wallet.applyRefund(uri);
|
||||||
} else if (uri.startsWith("taler://withdraw/")) {
|
break;
|
||||||
|
case TalerUriType.TalerWithdraw:
|
||||||
|
{
|
||||||
const withdrawInfo = await wallet.getWithdrawalInfo(uri);
|
const withdrawInfo = await wallet.getWithdrawalInfo(uri);
|
||||||
const selectedExchange = withdrawInfo.suggestedExchange;
|
const selectedExchange = withdrawInfo.suggestedExchange;
|
||||||
if (!selectedExchange) {
|
if (!selectedExchange) {
|
||||||
@ -231,6 +240,12 @@ walletCli
|
|||||||
const res = await wallet.acceptWithdrawal(uri, selectedExchange);
|
const res = await wallet.acceptWithdrawal(uri, selectedExchange);
|
||||||
await wallet.processReserve(res.reservePub);
|
await wallet.processReserve(res.reservePub);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log(`URI type (${uriType}) not handled`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -445,7 +460,7 @@ testCli
|
|||||||
.requiredOption("bank", ["-b", "--bank"], clk.STRING, {
|
.requiredOption("bank", ["-b", "--bank"], clk.STRING, {
|
||||||
default: "https://bank.test.taler.net/",
|
default: "https://bank.test.taler.net/",
|
||||||
})
|
})
|
||||||
.action(async (args) => {
|
.action(async args => {
|
||||||
const b = new Bank(args.genWithdrawUri.bank);
|
const b = new Bank(args.genWithdrawUri.bank);
|
||||||
const user = await b.registerRandomUser();
|
const user = await b.registerRandomUser();
|
||||||
const url = await b.generateWithdrawUri(user, args.genWithdrawUri.amount);
|
const url = await b.generateWithdrawUri(user, args.genWithdrawUri.amount);
|
||||||
|
@ -22,23 +22,6 @@ import {
|
|||||||
parseTipUri,
|
parseTipUri,
|
||||||
} from "./taleruri";
|
} from "./taleruri";
|
||||||
|
|
||||||
test("taler pay url parsing: http(s)", t => {
|
|
||||||
const url1 = "https://example.com/bar?spam=eggs";
|
|
||||||
const r1 = parsePayUri(url1);
|
|
||||||
if (!r1) {
|
|
||||||
t.fail();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
t.is(r1.downloadUrl, url1);
|
|
||||||
t.is(r1.sessionId, undefined);
|
|
||||||
const url2 = "http://example.com/bar?spam=eggs";
|
|
||||||
const r2 = parsePayUri(url2);
|
|
||||||
if (!r2) {
|
|
||||||
t.fail();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test("taler pay url parsing: wrong scheme", t => {
|
test("taler pay url parsing: wrong scheme", t => {
|
||||||
const url1 = "talerfoo://";
|
const url1 = "talerfoo://";
|
||||||
const r1 = parsePayUri(url1);
|
const r1 = parsePayUri(url1);
|
||||||
@ -56,7 +39,7 @@ test("taler pay url parsing: defaults", t => {
|
|||||||
t.fail();
|
t.fail();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
t.is(r1.downloadUrl, "https://example.com/public/proposal?order_id=myorder");
|
t.is(r1.merchantBaseUrl, "https://example.com/public/");
|
||||||
t.is(r1.sessionId, undefined);
|
t.is(r1.sessionId, undefined);
|
||||||
|
|
||||||
const url2 = "taler://pay/example.com/-/-/myorder/mysession";
|
const url2 = "taler://pay/example.com/-/-/myorder/mysession";
|
||||||
@ -65,7 +48,7 @@ test("taler pay url parsing: defaults", t => {
|
|||||||
t.fail();
|
t.fail();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
t.is(r2.downloadUrl, "https://example.com/public/proposal?order_id=myorder");
|
t.is(r2.merchantBaseUrl, "https://example.com/public/");
|
||||||
t.is(r2.sessionId, "mysession");
|
t.is(r2.sessionId, "mysession");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -76,7 +59,7 @@ test("taler pay url parsing: trailing parts", t => {
|
|||||||
t.fail();
|
t.fail();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
t.is(r1.downloadUrl, "https://example.com/public/proposal?order_id=myorder");
|
t.is(r1.merchantBaseUrl, "https://example.com/public/");
|
||||||
t.is(r1.sessionId, "mysession");
|
t.is(r1.sessionId, "mysession");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -87,10 +70,8 @@ test("taler pay url parsing: instance", t => {
|
|||||||
t.fail();
|
t.fail();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
t.is(
|
t.is(r1.merchantBaseUrl, "https://example.com/public/instances/myinst/");
|
||||||
r1.downloadUrl,
|
t.is(r1.orderId, "myorder");
|
||||||
"https://example.com/public/instances/myinst/proposal?order_id=myorder",
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("taler pay url parsing: path prefix and instance", t => {
|
test("taler pay url parsing: path prefix and instance", t => {
|
||||||
@ -100,10 +81,7 @@ test("taler pay url parsing: path prefix and instance", t => {
|
|||||||
t.fail();
|
t.fail();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
t.is(
|
t.is(r1.merchantBaseUrl, "https://example.com/mypfx/instances/myinst/");
|
||||||
r1.downloadUrl,
|
|
||||||
"https://example.com/mypfx/instances/myinst/proposal?order_id=myorder",
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("taler pay url parsing: complex path prefix", t => {
|
test("taler pay url parsing: complex path prefix", t => {
|
||||||
@ -113,10 +91,9 @@ test("taler pay url parsing: complex path prefix", t => {
|
|||||||
t.fail();
|
t.fail();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
t.is(
|
t.is(r1.merchantBaseUrl, "https://example.com/mypfx/public/");
|
||||||
r1.downloadUrl,
|
t.is(r1.orderId, "myorder");
|
||||||
"https://example.com/mypfx/public/proposal?order_id=myorder",
|
t.is(r1.sessionId, undefined);
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("taler pay url parsing: complex path prefix and instance", t => {
|
test("taler pay url parsing: complex path prefix and instance", t => {
|
||||||
@ -126,10 +103,8 @@ test("taler pay url parsing: complex path prefix and instance", t => {
|
|||||||
t.fail();
|
t.fail();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
t.is(
|
t.is(r1.merchantBaseUrl, "https://example.com/mypfx/public/instances/foo/");
|
||||||
r1.downloadUrl,
|
t.is(r1.orderId, "myorder");
|
||||||
"https://example.com/mypfx/public/instances/foo/proposal?order_id=myorder",
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("taler pay url parsing: non-https #1", t => {
|
test("taler pay url parsing: non-https #1", t => {
|
||||||
@ -139,7 +114,8 @@ test("taler pay url parsing: non-https #1", t => {
|
|||||||
t.fail();
|
t.fail();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
t.is(r1.downloadUrl, "http://example.com/public/proposal?order_id=myorder");
|
t.is(r1.merchantBaseUrl, "http://example.com/public/");
|
||||||
|
t.is(r1.orderId, "myorder")
|
||||||
});
|
});
|
||||||
|
|
||||||
test("taler pay url parsing: non-https #2", t => {
|
test("taler pay url parsing: non-https #2", t => {
|
||||||
@ -149,7 +125,8 @@ test("taler pay url parsing: non-https #2", t => {
|
|||||||
t.fail();
|
t.fail();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
t.is(r1.downloadUrl, "https://example.com/public/proposal?order_id=myorder");
|
t.is(r1.merchantBaseUrl, "https://example.com/public/");
|
||||||
|
t.is(r1.orderId, "myorder");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("taler withdraw uri parsing", t => {
|
test("taler withdraw uri parsing", t => {
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export interface PayUriResult {
|
export interface PayUriResult {
|
||||||
downloadUrl: string;
|
merchantBaseUrl: string;
|
||||||
|
orderId: string;
|
||||||
sessionId?: string;
|
sessionId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ export interface TipUriResult {
|
|||||||
|
|
||||||
export function parseWithdrawUri(s: string): WithdrawUriResult | undefined {
|
export function parseWithdrawUri(s: string): WithdrawUriResult | undefined {
|
||||||
const pfx = "taler://withdraw/";
|
const pfx = "taler://withdraw/";
|
||||||
if (!s.startsWith(pfx)) {
|
if (!s.toLowerCase().startsWith(pfx)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,6 +45,20 @@ export function parseWithdrawUri(s: string): WithdrawUriResult | undefined {
|
|||||||
|
|
||||||
let [host, path, withdrawId] = rest.split("/");
|
let [host, path, withdrawId] = rest.split("/");
|
||||||
|
|
||||||
|
if (!host) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
host = host.toLowerCase();
|
||||||
|
|
||||||
|
if (!path) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!withdrawId) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
if (path === "-") {
|
if (path === "-") {
|
||||||
path = "api/withdraw-operation";
|
path = "api/withdraw-operation";
|
||||||
}
|
}
|
||||||
@ -53,15 +68,45 @@ export function parseWithdrawUri(s: string): WithdrawUriResult | undefined {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parsePayUri(s: string): PayUriResult | undefined {
|
export const enum TalerUriType {
|
||||||
if (s.startsWith("https://") || s.startsWith("http://")) {
|
TalerPay = "taler-pay",
|
||||||
return {
|
TalerWithdraw = "taler-withdraw",
|
||||||
downloadUrl: s,
|
TalerTip = "taler-tip",
|
||||||
sessionId: undefined,
|
TalerRefund = "taler-refund",
|
||||||
};
|
TalerNotifyReserve = "taler-notify-reserve",
|
||||||
|
Unknown = "unknown",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function classifyTalerUri(s: string): TalerUriType {
|
||||||
|
const sl = s.toLowerCase();
|
||||||
|
if (sl.startsWith("taler://pay/")) {
|
||||||
|
return TalerUriType.TalerPay;
|
||||||
|
}
|
||||||
|
if (sl.startsWith("taler://tip/")) {
|
||||||
|
return TalerUriType.TalerTip;
|
||||||
|
}
|
||||||
|
if (sl.startsWith("taler://refund/")) {
|
||||||
|
return TalerUriType.TalerRefund;
|
||||||
|
}
|
||||||
|
if (sl.startsWith("taler://withdraw/")) {
|
||||||
|
return TalerUriType.TalerWithdraw;
|
||||||
|
}
|
||||||
|
if (sl.startsWith("taler://notify-reserve/")) {
|
||||||
|
return TalerUriType.TalerWithdraw;
|
||||||
|
}
|
||||||
|
return TalerUriType.Unknown;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getOrderDownloadUrl(merchantBaseUrl: string, orderId: string) {
|
||||||
|
const u = new URL("proposal", merchantBaseUrl);
|
||||||
|
u.searchParams.set("order_id", orderId);
|
||||||
|
return u.href
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parsePayUri(s: string): PayUriResult | undefined {
|
||||||
const pfx = "taler://pay/";
|
const pfx = "taler://pay/";
|
||||||
if (!s.startsWith(pfx)) {
|
if (!s.toLowerCase().startsWith(pfx)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,6 +120,8 @@ export function parsePayUri(s: string): PayUriResult | undefined {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
host = host.toLowerCase();
|
||||||
|
|
||||||
if (!maybePath) {
|
if (!maybePath) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@ -99,21 +146,21 @@ export function parsePayUri(s: string): PayUriResult | undefined {
|
|||||||
protocol = "http";
|
protocol = "http";
|
||||||
}
|
}
|
||||||
|
|
||||||
const downloadUrl =
|
const merchantBaseUrl =
|
||||||
`${protocol}://${host}/` +
|
`${protocol}://${host}/` +
|
||||||
decodeURIComponent(maybePath) +
|
decodeURIComponent(maybePath) +
|
||||||
maybeInstancePath +
|
maybeInstancePath;
|
||||||
`proposal?order_id=${orderId}`;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
downloadUrl,
|
merchantBaseUrl,
|
||||||
|
orderId,
|
||||||
sessionId: maybeSessionid,
|
sessionId: maybeSessionid,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseTipUri(s: string): TipUriResult | undefined {
|
export function parseTipUri(s: string): TipUriResult | undefined {
|
||||||
const pfx = "taler://tip/";
|
const pfx = "taler://tip/";
|
||||||
if (!s.startsWith(pfx)) {
|
if (!s.toLowerCase().startsWith(pfx)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,6 +172,8 @@ export function parseTipUri(s: string): TipUriResult | undefined {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
host = host.toLowerCase();
|
||||||
|
|
||||||
if (!maybePath) {
|
if (!maybePath) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@ -155,7 +204,7 @@ export function parseTipUri(s: string): TipUriResult | undefined {
|
|||||||
export function parseRefundUri(s: string): RefundUriResult | undefined {
|
export function parseRefundUri(s: string): RefundUriResult | undefined {
|
||||||
const pfx = "taler://refund/";
|
const pfx = "taler://refund/";
|
||||||
|
|
||||||
if (!s.startsWith(pfx)) {
|
if (!s.toLowerCase().startsWith(pfx)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,6 +216,8 @@ export function parseRefundUri(s: string): RefundUriResult | undefined {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
host = host.toLowerCase();
|
||||||
|
|
||||||
if (!maybePath) {
|
if (!maybePath) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ import {
|
|||||||
} from "../util/helpers";
|
} from "../util/helpers";
|
||||||
import { Logger } from "../util/logging";
|
import { Logger } from "../util/logging";
|
||||||
import { InternalWalletState } from "./state";
|
import { InternalWalletState } from "./state";
|
||||||
import { parsePayUri, parseRefundUri } from "../util/taleruri";
|
import { parsePayUri, parseRefundUri, getOrderDownloadUrl } from "../util/taleruri";
|
||||||
import { getTotalRefreshCost, refresh } from "./refresh";
|
import { getTotalRefreshCost, refresh } from "./refresh";
|
||||||
import { encodeCrock, getRandomBytes } from "../crypto/talerCrypto";
|
import { encodeCrock, getRandomBytes } from "../crypto/talerCrypto";
|
||||||
import { guardOperationException } from "./errors";
|
import { guardOperationException } from "./errors";
|
||||||
@ -557,9 +557,10 @@ async function processDownloadProposalImpl(
|
|||||||
if (proposal.proposalStatus != ProposalStatus.DOWNLOADING) {
|
if (proposal.proposalStatus != ProposalStatus.DOWNLOADING) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const parsed_url = new URL(proposal.url);
|
|
||||||
parsed_url.searchParams.set("nonce", proposal.noncePub);
|
const parsedUrl = new URL(getOrderDownloadUrl(proposal.merchantBaseUrl, proposal.orderId));
|
||||||
const urlWithNonce = parsed_url.href;
|
parsedUrl.searchParams.set("nonce", proposal.noncePub);
|
||||||
|
const urlWithNonce = parsedUrl.href;
|
||||||
console.log("downloading contract from '" + urlWithNonce + "'");
|
console.log("downloading contract from '" + urlWithNonce + "'");
|
||||||
let resp;
|
let resp;
|
||||||
try {
|
try {
|
||||||
@ -629,13 +630,14 @@ async function processDownloadProposalImpl(
|
|||||||
*/
|
*/
|
||||||
async function startDownloadProposal(
|
async function startDownloadProposal(
|
||||||
ws: InternalWalletState,
|
ws: InternalWalletState,
|
||||||
url: string,
|
merchantBaseUrl: string,
|
||||||
|
orderId: string,
|
||||||
sessionId?: string,
|
sessionId?: string,
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const oldProposal = await oneShotGetIndexed(
|
const oldProposal = await oneShotGetIndexed(
|
||||||
ws.db,
|
ws.db,
|
||||||
Stores.proposals.urlIndex,
|
Stores.proposals.urlAndOrderIdIndex,
|
||||||
url,
|
[merchantBaseUrl, orderId],
|
||||||
);
|
);
|
||||||
if (oldProposal) {
|
if (oldProposal) {
|
||||||
await processDownloadProposal(ws, oldProposal.proposalId);
|
await processDownloadProposal(ws, oldProposal.proposalId);
|
||||||
@ -650,8 +652,8 @@ async function startDownloadProposal(
|
|||||||
noncePriv: priv,
|
noncePriv: priv,
|
||||||
noncePub: pub,
|
noncePub: pub,
|
||||||
timestamp: getTimestampNow(),
|
timestamp: getTimestampNow(),
|
||||||
url,
|
merchantBaseUrl,
|
||||||
downloadSessionId: sessionId,
|
orderId,
|
||||||
proposalId: proposalId,
|
proposalId: proposalId,
|
||||||
proposalStatus: ProposalStatus.DOWNLOADING,
|
proposalStatus: ProposalStatus.DOWNLOADING,
|
||||||
repurchaseProposalId: undefined,
|
repurchaseProposalId: undefined,
|
||||||
@ -763,7 +765,8 @@ export async function preparePay(
|
|||||||
|
|
||||||
let proposalId = await startDownloadProposal(
|
let proposalId = await startDownloadProposal(
|
||||||
ws,
|
ws,
|
||||||
uriResult.downloadUrl,
|
uriResult.merchantBaseUrl,
|
||||||
|
uriResult.orderId,
|
||||||
uriResult.sessionId,
|
uriResult.sessionId,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -312,7 +312,8 @@ async function gatherProposalPending(
|
|||||||
resp.pendingOperations.push({
|
resp.pendingOperations.push({
|
||||||
type: "proposal-download",
|
type: "proposal-download",
|
||||||
givesLifeness: true,
|
givesLifeness: true,
|
||||||
merchantBaseUrl: proposal.download?.contractTerms.merchant_base_url || "",
|
merchantBaseUrl: proposal.merchantBaseUrl,
|
||||||
|
orderId: proposal.orderId,
|
||||||
proposalId: proposal.proposalId,
|
proposalId: proposal.proposalId,
|
||||||
proposalTimestamp: proposal.timestamp,
|
proposalTimestamp: proposal.timestamp,
|
||||||
lastError: proposal.lastError,
|
lastError: proposal.lastError,
|
||||||
|
@ -741,6 +741,7 @@ export interface PendingProposalDownloadOperation {
|
|||||||
merchantBaseUrl: string;
|
merchantBaseUrl: string;
|
||||||
proposalTimestamp: Timestamp;
|
proposalTimestamp: Timestamp;
|
||||||
proposalId: string;
|
proposalId: string;
|
||||||
|
orderId: string;
|
||||||
lastError?: OperationError;
|
lastError?: OperationError;
|
||||||
retryInfo: RetryInfo;
|
retryInfo: RetryInfo;
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ import Port = chrome.runtime.Port;
|
|||||||
import MessageSender = chrome.runtime.MessageSender;
|
import MessageSender = chrome.runtime.MessageSender;
|
||||||
import { BrowserCryptoWorkerFactory } from "../crypto/workers/cryptoApi";
|
import { BrowserCryptoWorkerFactory } from "../crypto/workers/cryptoApi";
|
||||||
import { OpenedPromise, openPromise } from "../util/promiseUtils";
|
import { OpenedPromise, openPromise } from "../util/promiseUtils";
|
||||||
|
import { classifyTalerUri, TalerUriType } from "../util/taleruri";
|
||||||
|
|
||||||
const NeedsWallet = Symbol("NeedsWallet");
|
const NeedsWallet = Symbol("NeedsWallet");
|
||||||
|
|
||||||
@ -257,7 +258,11 @@ async function handleMessage(
|
|||||||
await walletInit.promise;
|
await walletInit.promise;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
errors.push("Error during wallet initialization: " + e);
|
errors.push("Error during wallet initialization: " + e);
|
||||||
if (currentDatabase === undefined && outdatedDbVersion === undefined && isFirefox()) {
|
if (
|
||||||
|
currentDatabase === undefined &&
|
||||||
|
outdatedDbVersion === undefined &&
|
||||||
|
isFirefox()
|
||||||
|
) {
|
||||||
firefoxIdbProblem = true;
|
firefoxIdbProblem = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -435,7 +440,7 @@ async function reinitWallet() {
|
|||||||
http,
|
http,
|
||||||
new BrowserCryptoWorkerFactory(),
|
new BrowserCryptoWorkerFactory(),
|
||||||
);
|
);
|
||||||
wallet.runRetryLoop().catch((e) => {
|
wallet.runRetryLoop().catch(e => {
|
||||||
console.log("error during wallet retry loop", e);
|
console.log("error during wallet retry loop", e);
|
||||||
});
|
});
|
||||||
// Useful for debugging in the background page.
|
// Useful for debugging in the background page.
|
||||||
@ -601,13 +606,9 @@ export async function wxMain() {
|
|||||||
for (let header of details.responseHeaders || []) {
|
for (let header of details.responseHeaders || []) {
|
||||||
if (header.name.toLowerCase() === "taler") {
|
if (header.name.toLowerCase() === "taler") {
|
||||||
const talerUri = header.value || "";
|
const talerUri = header.value || "";
|
||||||
if (!talerUri.startsWith("taler://")) {
|
const uriType = classifyTalerUri(talerUri);
|
||||||
console.warn(
|
switch (uriType) {
|
||||||
"Response with HTTP 402 has Taler header, but header value is not a taler:// URI.",
|
case TalerUriType.TalerWithdraw:
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (talerUri.startsWith("taler://withdraw/")) {
|
|
||||||
return makeSyncWalletRedirect(
|
return makeSyncWalletRedirect(
|
||||||
"withdraw.html",
|
"withdraw.html",
|
||||||
details.tabId,
|
details.tabId,
|
||||||
@ -616,7 +617,7 @@ export async function wxMain() {
|
|||||||
talerWithdrawUri: talerUri,
|
talerWithdrawUri: talerUri,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else if (talerUri.startsWith("taler://pay/")) {
|
case TalerUriType.TalerPay:
|
||||||
return makeSyncWalletRedirect(
|
return makeSyncWalletRedirect(
|
||||||
"pay.html",
|
"pay.html",
|
||||||
details.tabId,
|
details.tabId,
|
||||||
@ -625,7 +626,7 @@ export async function wxMain() {
|
|||||||
talerPayUri: talerUri,
|
talerPayUri: talerUri,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else if (talerUri.startsWith("taler://tip/")) {
|
case TalerUriType.TalerTip:
|
||||||
return makeSyncWalletRedirect(
|
return makeSyncWalletRedirect(
|
||||||
"tip.html",
|
"tip.html",
|
||||||
details.tabId,
|
details.tabId,
|
||||||
@ -634,7 +635,7 @@ export async function wxMain() {
|
|||||||
talerTipUri: talerUri,
|
talerTipUri: talerUri,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else if (talerUri.startsWith("taler://refund/")) {
|
case TalerUriType.TalerRefund:
|
||||||
return makeSyncWalletRedirect(
|
return makeSyncWalletRedirect(
|
||||||
"refund.html",
|
"refund.html",
|
||||||
details.tabId,
|
details.tabId,
|
||||||
@ -643,7 +644,7 @@ export async function wxMain() {
|
|||||||
talerRefundUri: talerUri,
|
talerRefundUri: talerUri,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
} else if (talerUri.startsWith("taler://notify-reserve/")) {
|
case TalerUriType.TalerNotifyReserve:
|
||||||
Promise.resolve().then(() => {
|
Promise.resolve().then(() => {
|
||||||
const w = currentWallet;
|
const w = currentWallet;
|
||||||
if (!w) {
|
if (!w) {
|
||||||
@ -651,11 +652,14 @@ export async function wxMain() {
|
|||||||
}
|
}
|
||||||
w.handleNotifyReserve();
|
w.handleNotifyReserve();
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
|
||||||
console.warn("Unknown action in taler:// URI, ignoring.");
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
console.warn(
|
||||||
|
"Response with HTTP 402 has Taler header, but header value is not a taler:// URI.",
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user