implement new protocol / naming
This commit is contained in:
parent
dd5b679791
commit
08d4a5b625
@ -90,6 +90,19 @@ namespace TalerNotify {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function queryPayment(query: any): Promise<any> {
|
||||||
|
// current URL without fragment
|
||||||
|
const walletMsg = {
|
||||||
|
type: "query-payment",
|
||||||
|
detail: query,
|
||||||
|
};
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
chrome.runtime.sendMessage(walletMsg, (resp: any) => {
|
||||||
|
resolve(resp);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function putHistory(historyEntry: any): Promise<void> {
|
function putHistory(historyEntry: any): Promise<void> {
|
||||||
const walletMsg = {
|
const walletMsg = {
|
||||||
type: "put-history-entry",
|
type: "put-history-entry",
|
||||||
@ -109,16 +122,20 @@ namespace TalerNotify {
|
|||||||
type: "save-offer",
|
type: "save-offer",
|
||||||
detail: {
|
detail: {
|
||||||
offer: {
|
offer: {
|
||||||
contract: offer.contract,
|
contract: offer.data,
|
||||||
merchant_sig: offer.merchant_sig,
|
merchant_sig: offer.sig,
|
||||||
H_contract: offer.H_contract,
|
H_contract: offer.hash,
|
||||||
offer_time: new Date().getTime() / 1000
|
offer_time: new Date().getTime() / 1000
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
chrome.runtime.sendMessage(walletMsg, (resp: any) => {
|
chrome.runtime.sendMessage(walletMsg, (resp: any) => {
|
||||||
|
if (resp && resp.error) {
|
||||||
|
reject(resp);
|
||||||
|
} else {
|
||||||
resolve(resp);
|
resolve(resp);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -141,17 +158,10 @@ namespace TalerNotify {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (resp && resp.type === "fetch") {
|
if (resp && resp.type == "pay") {
|
||||||
logVerbose && console.log("it's fetch");
|
logVerbose && console.log("doing taler.pay with", resp.payDetail);
|
||||||
taler.internalOfferContractFrom(resp.contractUrl);
|
taler.internalPay(resp.payDetail);
|
||||||
document.documentElement.style.visibility = "hidden";
|
document.documentElement.style.visibility = "hidden";
|
||||||
|
|
||||||
} else if (resp && resp.type === "execute") {
|
|
||||||
logVerbose && console.log("it's execute");
|
|
||||||
document.documentElement.style.visibility = "hidden";
|
|
||||||
taler.internalExecutePayment(resp.contractHash,
|
|
||||||
resp.payUrl,
|
|
||||||
resp.offerUrl);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -163,6 +173,104 @@ namespace TalerNotify {
|
|||||||
(detail: any, sendResponse: (msg: any) => void): void;
|
(detail: any, sendResponse: (msg: any) => void): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function downloadContract(url: string): Promise<any> {
|
||||||
|
// FIXME: include and check nonce!
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const contract_request = new XMLHttpRequest();
|
||||||
|
console.log("downloading contract from '" + url + "'")
|
||||||
|
contract_request.open("GET", url, true);
|
||||||
|
contract_request.onload = function (e) {
|
||||||
|
if (contract_request.readyState == 4) {
|
||||||
|
if (contract_request.status == 200) {
|
||||||
|
console.log("response text:",
|
||||||
|
contract_request.responseText);
|
||||||
|
var contract_wrapper = JSON.parse(contract_request.responseText);
|
||||||
|
if (!contract_wrapper) {
|
||||||
|
console.error("response text was invalid json");
|
||||||
|
let detail = {hint: "invalid json", status: contract_request.status, body: contract_request.responseText};
|
||||||
|
reject(detail);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resolve(contract_wrapper);
|
||||||
|
} else {
|
||||||
|
let detail = {hint: "contract download failed", status: contract_request.status, body: contract_request.responseText};
|
||||||
|
reject(detail);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
contract_request.onerror = function (e) {
|
||||||
|
let detail = {hint: "contract download failed", status: contract_request.status, body: contract_request.responseText};
|
||||||
|
reject(detail);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
contract_request.send();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function processProposal(proposal: any) {
|
||||||
|
if (!proposal.data) {
|
||||||
|
console.error("field proposal.data field missing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!proposal.hash) {
|
||||||
|
console.error("proposal.hash field missing");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let contractHash = await hashContract(proposal.data);
|
||||||
|
|
||||||
|
if (contractHash != proposal.hash) {
|
||||||
|
console.error("merchant-supplied contract hash is wrong");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let resp = await checkRepurchase(proposal.data);
|
||||||
|
|
||||||
|
if (resp.error) {
|
||||||
|
console.error("wallet backend error", resp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (resp.isRepurchase) {
|
||||||
|
logVerbose && console.log("doing repurchase");
|
||||||
|
console.assert(resp.existingFulfillmentUrl);
|
||||||
|
console.assert(resp.existingContractHash);
|
||||||
|
window.location.href = subst(resp.existingFulfillmentUrl,
|
||||||
|
resp.existingContractHash);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
let merchantName = "(unknown)";
|
||||||
|
try {
|
||||||
|
merchantName = proposal.data.merchant.name;
|
||||||
|
} catch (e) {
|
||||||
|
// bad contract / name not included
|
||||||
|
}
|
||||||
|
|
||||||
|
let historyEntry = {
|
||||||
|
timestamp: (new Date).getTime(),
|
||||||
|
subjectId: `contract-${contractHash}`,
|
||||||
|
type: "offer-contract",
|
||||||
|
detail: {
|
||||||
|
contractHash,
|
||||||
|
merchantName,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await putHistory(historyEntry);
|
||||||
|
let offerId = await saveOffer(proposal);
|
||||||
|
|
||||||
|
const uri = URI(chrome.extension.getURL(
|
||||||
|
"/src/pages/confirm-contract.html"));
|
||||||
|
const params = {
|
||||||
|
offerId: offerId.toString(),
|
||||||
|
};
|
||||||
|
const target = uri.query(params).href();
|
||||||
|
document.location.replace(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function registerHandlers() {
|
function registerHandlers() {
|
||||||
/**
|
/**
|
||||||
* Add a handler for a DOM event, which automatically
|
* Add a handler for a DOM event, which automatically
|
||||||
@ -237,70 +345,28 @@ namespace TalerNotify {
|
|||||||
|
|
||||||
const proposal = msg.contract_wrapper;
|
const proposal = msg.contract_wrapper;
|
||||||
|
|
||||||
if (!proposal.data) {
|
processProposal(proposal);
|
||||||
console.error("field proposal.data field missing");
|
});
|
||||||
|
|
||||||
|
addHandler("taler-pay", async(msg: any, sendResponse: any) => {
|
||||||
|
let res = await queryPayment(msg.contract_query);
|
||||||
|
logVerbose && console.log("taler-pay: got response", res);
|
||||||
|
if (res && res.payReq) {
|
||||||
|
sendResponse(res);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (msg.contract_url) {
|
||||||
|
let proposal = await downloadContract(msg.contract_url);
|
||||||
|
await processProposal(proposal);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!proposal.hash) {
|
if (msg.offer_url) {
|
||||||
console.error("proposal.hash field missing");
|
document.location.href = msg.offer_url;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let contractHash = await hashContract(proposal.data);
|
console.log("can't proceed with payment, no way to get contract specified");
|
||||||
|
|
||||||
if (contractHash != proposal.hash) {
|
|
||||||
console.error("merchant-supplied contract hash is wrong");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let resp = await checkRepurchase(proposal.data);
|
|
||||||
|
|
||||||
if (resp.error) {
|
|
||||||
console.error("wallet backend error", resp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (resp.isRepurchase) {
|
|
||||||
logVerbose && console.log("doing repurchase");
|
|
||||||
console.assert(resp.existingFulfillmentUrl);
|
|
||||||
console.assert(resp.existingContractHash);
|
|
||||||
window.location.href = subst(resp.existingFulfillmentUrl,
|
|
||||||
resp.existingContractHash);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
let merchantName = "(unknown)";
|
|
||||||
try {
|
|
||||||
merchantName = proposal.data.merchant.name;
|
|
||||||
} catch (e) {
|
|
||||||
// bad contract / name not included
|
|
||||||
}
|
|
||||||
|
|
||||||
let historyEntry = {
|
|
||||||
timestamp: (new Date).getTime(),
|
|
||||||
subjectId: `contract-${contractHash}`,
|
|
||||||
type: "offer-contract",
|
|
||||||
detail: {
|
|
||||||
contractHash,
|
|
||||||
merchantName,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
await putHistory(historyEntry);
|
|
||||||
let offerId = await saveOffer(proposal);
|
|
||||||
|
|
||||||
const uri = URI(chrome.extension.getURL(
|
|
||||||
"/src/pages/confirm-contract.html"));
|
|
||||||
const params = {
|
|
||||||
offerId: offerId.toString(),
|
|
||||||
};
|
|
||||||
const target = uri.query(params).href();
|
|
||||||
if (msg.replace_navigation === true) {
|
|
||||||
document.location.replace(target);
|
|
||||||
} else {
|
|
||||||
document.location.href = target;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
addHandler("taler-payment-failed", (msg: any, sendResponse: any) => {
|
addHandler("taler-payment-failed", (msg: any, sendResponse: any) => {
|
||||||
@ -331,41 +397,5 @@ namespace TalerNotify {
|
|||||||
sendResponse();
|
sendResponse();
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
addHandler("taler-get-payment", (msg: any, sendResponse: any) => {
|
|
||||||
const walletMsg = {
|
|
||||||
type: "execute-payment",
|
|
||||||
detail: {
|
|
||||||
H_contract: msg.H_contract,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
chrome.runtime.sendMessage(walletMsg, (resp) => {
|
|
||||||
if (resp.rateLimitExceeded) {
|
|
||||||
console.error("rate limit exceeded, check for redirect loops");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!resp.success) {
|
|
||||||
if (msg.offering_url) {
|
|
||||||
window.location.href = msg.offering_url;
|
|
||||||
} else {
|
|
||||||
console.error("execute-payment failed", resp);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let contract = resp.contract;
|
|
||||||
if (!contract) {
|
|
||||||
throw Error("contract missing");
|
|
||||||
}
|
|
||||||
|
|
||||||
// We have the details for then payment, the merchant page
|
|
||||||
// is responsible to give it to the merchant.
|
|
||||||
sendResponse({
|
|
||||||
H_contract: msg.H_contract,
|
|
||||||
contract: resp.contract,
|
|
||||||
payment: resp.payReq,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,12 @@ export function prettyAmount(amount: AmountJson) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function renderContract(contract: Contract): JSX.Element {
|
export function renderContract(contract: Contract): JSX.Element {
|
||||||
let merchantName = <strong>{contract.merchant.name}</strong>;
|
let merchantName;
|
||||||
|
if (contract.merchant && contract.merchant.name) {
|
||||||
|
merchantName = <strong>{contract.merchant.name}</strong>;
|
||||||
|
} else {
|
||||||
|
merchantName = <strong>(pub: {contract.merchant_pub})</strong>;
|
||||||
|
}
|
||||||
let amount = <strong>{prettyAmount(contract.amount)}</strong>;
|
let amount = <strong>{prettyAmount(contract.amount)}</strong>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -164,20 +164,10 @@ export interface HistoryRecord {
|
|||||||
|
|
||||||
|
|
||||||
interface PayReq {
|
interface PayReq {
|
||||||
amount: AmountJson;
|
|
||||||
coins: CoinPaySig[];
|
coins: CoinPaySig[];
|
||||||
H_contract: string;
|
merchant_pub: string;
|
||||||
max_fee: AmountJson;
|
order_id: string;
|
||||||
merchant_sig: string;
|
|
||||||
exchange: string;
|
exchange: string;
|
||||||
refund_deadline: string;
|
|
||||||
timestamp: string;
|
|
||||||
pay_deadline: string;
|
|
||||||
/**
|
|
||||||
* Merchant instance identifier that should receive the
|
|
||||||
* payment, if applicable.
|
|
||||||
*/
|
|
||||||
instance?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TransactionRecord {
|
interface TransactionRecord {
|
||||||
@ -352,6 +342,8 @@ export namespace Stores {
|
|||||||
"contract.merchant_pub",
|
"contract.merchant_pub",
|
||||||
"contract.repurchase_correlation_id"
|
"contract.repurchase_correlation_id"
|
||||||
]);
|
]);
|
||||||
|
fulfillmentUrlIndex = new Index<string,TransactionRecord>(this, "fulfillment_url", "contract.fulfillment_url");
|
||||||
|
orderIdIndex = new Index<string,TransactionRecord>(this, "order_id", "contract.order_id");
|
||||||
}
|
}
|
||||||
|
|
||||||
class DenominationsStore extends Store<DenominationRecord> {
|
class DenominationsStore extends Store<DenominationRecord> {
|
||||||
@ -552,16 +544,10 @@ export class Wallet {
|
|||||||
payCoinInfo: PayCoinInfo,
|
payCoinInfo: PayCoinInfo,
|
||||||
chosenExchange: string): Promise<void> {
|
chosenExchange: string): Promise<void> {
|
||||||
let payReq: PayReq = {
|
let payReq: PayReq = {
|
||||||
amount: offer.contract.amount,
|
|
||||||
coins: payCoinInfo.map((x) => x.sig),
|
coins: payCoinInfo.map((x) => x.sig),
|
||||||
H_contract: offer.H_contract,
|
merchant_pub: offer.contract.merchant_pub,
|
||||||
max_fee: offer.contract.max_fee,
|
order_id: offer.contract.order_id,
|
||||||
merchant_sig: offer.merchant_sig,
|
exchange: chosenExchange,
|
||||||
exchange: URI(chosenExchange).href(),
|
|
||||||
refund_deadline: offer.contract.refund_deadline,
|
|
||||||
pay_deadline: offer.contract.pay_deadline,
|
|
||||||
timestamp: offer.contract.timestamp,
|
|
||||||
instance: offer.contract.merchant.instance
|
|
||||||
};
|
};
|
||||||
let t: TransactionRecord = {
|
let t: TransactionRecord = {
|
||||||
contractHash: offer.H_contract,
|
contractHash: offer.H_contract,
|
||||||
@ -679,18 +665,36 @@ export class Wallet {
|
|||||||
* Retrieve all necessary information for looking up the contract
|
* Retrieve all necessary information for looking up the contract
|
||||||
* with the given hash.
|
* with the given hash.
|
||||||
*/
|
*/
|
||||||
async executePayment(H_contract: string): Promise<any> {
|
async queryPayment(query: any): Promise<any> {
|
||||||
let t = await this.q().get<TransactionRecord>(Stores.transactions,
|
let t: TransactionRecord | undefined;
|
||||||
H_contract);
|
|
||||||
|
console.log("query for payment", query);
|
||||||
|
|
||||||
|
switch (query.type) {
|
||||||
|
case "fulfillment_url":
|
||||||
|
t = await this.q().getIndexed(Stores.transactions.fulfillmentUrlIndex, query.value);
|
||||||
|
break;
|
||||||
|
case "order_id":
|
||||||
|
t = await this.q().getIndexed(Stores.transactions.orderIdIndex, query.value);
|
||||||
|
break;
|
||||||
|
case "hash":
|
||||||
|
t = await this.q().get<TransactionRecord>(Stores.transactions, query.value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw Error("invalid type");
|
||||||
|
}
|
||||||
|
|
||||||
if (!t) {
|
if (!t) {
|
||||||
|
console.log("query for payment failed");
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
contractFound: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
console.log("query for payment succeeded:", t);
|
||||||
let resp = {
|
let resp = {
|
||||||
success: true,
|
success: true,
|
||||||
payReq: t.payReq,
|
payReq: t.payReq,
|
||||||
|
H_contract: t.contractHash,
|
||||||
contract: t.contract,
|
contract: t.contract,
|
||||||
};
|
};
|
||||||
return resp;
|
return resp;
|
||||||
|
@ -139,20 +139,20 @@ function makeHandlers(db: IDBDatabase,
|
|||||||
}
|
}
|
||||||
return wallet.checkPay(offer);
|
return wallet.checkPay(offer);
|
||||||
},
|
},
|
||||||
["execute-payment"]: function (detail: any, sender: MessageSender) {
|
["query-payment"]: function (detail: any, sender: MessageSender) {
|
||||||
if (sender.tab && sender.tab.id) {
|
if (sender.tab && sender.tab.id) {
|
||||||
rateLimitCache[sender.tab.id]++;
|
rateLimitCache[sender.tab.id]++;
|
||||||
if (rateLimitCache[sender.tab.id] > 10) {
|
if (rateLimitCache[sender.tab.id] > 10) {
|
||||||
console.warn("rate limit for execute payment exceeded");
|
console.warn("rate limit for query-payment exceeded");
|
||||||
let msg = {
|
let msg = {
|
||||||
error: "rate limit exceeded for execute-payment",
|
error: "rate limit exceeded for query-payment",
|
||||||
rateLimitExceeded: true,
|
rateLimitExceeded: true,
|
||||||
hint: "Check for redirect loops",
|
hint: "Check for redirect loops",
|
||||||
};
|
};
|
||||||
return Promise.resolve(msg);
|
return Promise.resolve(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return wallet.executePayment(detail.H_contract);
|
return wallet.queryPayment(detail);
|
||||||
},
|
},
|
||||||
["exchange-info"]: function (detail) {
|
["exchange-info"]: function (detail) {
|
||||||
if (!detail.baseUrl) {
|
if (!detail.baseUrl) {
|
||||||
@ -179,8 +179,10 @@ function makeHandlers(db: IDBDatabase,
|
|||||||
if (!offer) {
|
if (!offer) {
|
||||||
return Promise.resolve({ error: "offer missing" });
|
return Promise.resolve({ error: "offer missing" });
|
||||||
}
|
}
|
||||||
console.log("handling safe-offer");
|
console.log("handling safe-offer", detail);
|
||||||
return wallet.saveOffer(offer);
|
// FIXME: fully migrate to new terminology
|
||||||
|
let checkedOffer = OfferRecord.checked(offer);
|
||||||
|
return wallet.saveOffer(checkedOffer);
|
||||||
},
|
},
|
||||||
["reserve-creation-info"]: function (detail, sender) {
|
["reserve-creation-info"]: function (detail, sender) {
|
||||||
if (!detail.baseUrl || typeof detail.baseUrl !== "string") {
|
if (!detail.baseUrl || typeof detail.baseUrl !== "string") {
|
||||||
@ -317,8 +319,7 @@ class ChromeNotifier implements Notifier {
|
|||||||
*/
|
*/
|
||||||
let paymentRequestCookies: { [n: number]: any } = {};
|
let paymentRequestCookies: { [n: number]: any } = {};
|
||||||
|
|
||||||
function handleHttpPayment(headerList: chrome.webRequest.HttpHeader[],
|
function handleHttpPayment(headerList: chrome.webRequest.HttpHeader[], url: string, tabId: number): any {
|
||||||
url: string, tabId: number): any {
|
|
||||||
const headers: { [s: string]: string } = {};
|
const headers: { [s: string]: string } = {};
|
||||||
for (let kv of headerList) {
|
for (let kv of headerList) {
|
||||||
if (kv.value) {
|
if (kv.value) {
|
||||||
@ -326,35 +327,52 @@ function handleHttpPayment(headerList: chrome.webRequest.HttpHeader[],
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const contractUrl = headers["x-taler-contract-url"];
|
let fields = {
|
||||||
if (contractUrl !== undefined) {
|
contract_url: headers["x-taler-contract-url"],
|
||||||
paymentRequestCookies[tabId] = { type: "fetch", contractUrl };
|
contract_query: headers["x-taler-contract-query"],
|
||||||
return;
|
offer_url: headers["x-taler-offer-url"],
|
||||||
|
pay_url: headers["x-taler-pay-url"],
|
||||||
}
|
}
|
||||||
|
|
||||||
const contractHash = headers["x-taler-contract-hash"];
|
let n: number = 0;
|
||||||
|
|
||||||
if (contractHash !== undefined) {
|
for (let key of Object.keys(fields)) {
|
||||||
const payUrl = headers["x-taler-pay-url"];
|
if ((fields as any)[key]) {
|
||||||
if (payUrl === undefined) {
|
n++;
|
||||||
console.log("malformed 402, X-Taler-Pay-Url missing");
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Offer URL is optional
|
|
||||||
const offerUrl = headers["x-taler-offer-url"];
|
|
||||||
paymentRequestCookies[tabId] = {
|
|
||||||
type: "execute",
|
|
||||||
offerUrl,
|
|
||||||
payUrl,
|
|
||||||
contractHash
|
|
||||||
};
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
// looks like it's not a taler request, it might be
|
// looks like it's not a taler request, it might be
|
||||||
// for a different payment system (or the shop is buggy)
|
// for a different payment system (or the shop is buggy)
|
||||||
console.log("ignoring non-taler 402 response");
|
console.log("ignoring non-taler 402 response");
|
||||||
|
}
|
||||||
|
|
||||||
|
let contract_query = undefined;
|
||||||
|
// parse " type [ ':' value ] " format
|
||||||
|
if (fields.contract_query) {
|
||||||
|
let res = /[-a-zA-Z0-9_.,]+(:.*)?/.exec(fields.contract_query);
|
||||||
|
if (res) {
|
||||||
|
contract_query = {type: res[0], value: res[1]};
|
||||||
|
if (contract_query.type == "fulfillment_url" && !contract_query.value) {
|
||||||
|
contract_query.value = url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let payDetail = {
|
||||||
|
contract_query,
|
||||||
|
contract_url: fields.contract_url,
|
||||||
|
offer_url: fields.offer_url,
|
||||||
|
pay_url: fields.pay_url,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log("got pay detail", payDetail)
|
||||||
|
|
||||||
|
paymentRequestCookies[tabId] = {
|
||||||
|
type: "pay",
|
||||||
|
payDetail,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit d4de1c912ecaac7991067027b352de61b237c0c9
|
Subproject commit 4831e664d69759da288625911c053d145aa1b68c
|
Loading…
Reference in New Issue
Block a user