gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-wallet-webex] branch master updated (f8edc4f -> 08d4


From: gnunet
Subject: [GNUnet-SVN] [taler-wallet-webex] branch master updated (f8edc4f -> 08d4a5b)
Date: Mon, 13 Feb 2017 00:44:47 +0100

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

dold pushed a change to branch master
in repository wallet-webex.

    from f8edc4f  fix superfluous field
     new bd02776  make summary optional
     new cce3f58  remove transaction_id
     new dd5b679  remove deprecated contract fields and add 'extra' field for 
merchant data
     new 08d4a5b  implement new protocol / naming

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/content_scripts/notify.ts | 247 +++++++++++++++++++++++-------------------
 src/cryptoLib.ts              |   1 -
 src/emscriptif.ts             |   2 -
 src/renderHtml.tsx            |   7 +-
 src/types.ts                  |  23 ++--
 src/wallet.ts                 |  56 +++++-----
 src/wxBackend.ts              |  78 ++++++++-----
 web-common                    |   2 +-
 8 files changed, 227 insertions(+), 189 deletions(-)

diff --git a/src/content_scripts/notify.ts b/src/content_scripts/notify.ts
index ef3a3ed..10b988c 100644
--- a/src/content_scripts/notify.ts
+++ b/src/content_scripts/notify.ts
@@ -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> {
     const walletMsg = {
       type: "put-history-entry",
@@ -109,16 +122,20 @@ namespace TalerNotify {
       type: "save-offer",
       detail: {
         offer: {
-          contract: offer.contract,
-          merchant_sig: offer.merchant_sig,
-          H_contract: offer.H_contract,
+          contract: offer.data,
+          merchant_sig: offer.sig,
+          H_contract: offer.hash,
           offer_time: new Date().getTime() / 1000
         },
       },
     };
     return new Promise((resolve, reject) => {
       chrome.runtime.sendMessage(walletMsg, (resp: any) => {
-        resolve(resp);
+        if (resp && resp.error) {
+          reject(resp);
+        } else {
+          resolve(resp);
+        }
       });
     });
   }
@@ -141,17 +158,10 @@ namespace TalerNotify {
         }
       });
 
-      if (resp && resp.type === "fetch") {
-        logVerbose && console.log("it's fetch");
-        taler.internalOfferContractFrom(resp.contractUrl);
-        document.documentElement.style.visibility = "hidden";
-
-      } else if (resp && resp.type === "execute") {
-        logVerbose && console.log("it's execute");
+      if (resp && resp.type == "pay") {
+        logVerbose && console.log("doing taler.pay with", resp.payDetail);
+        taler.internalPay(resp.payDetail);
         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;
   }
 
+  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() {
     /**
      * Add a handler for a DOM event, which automatically
@@ -235,77 +343,30 @@ namespace TalerNotify {
         return;
       }
 
-      const offer = msg.contract_wrapper;
+      const proposal = msg.contract_wrapper;
 
-      if (!offer.contract) {
-        console.error("contract field missing");
-        return;
-      }
+      processProposal(proposal);
+    });
 
-      if (!offer.H_contract) {
-        console.error("H_contract 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;
       }
-
-      let walletHashContractMsg = {
-        type: "hash-contract",
-        detail: {contract: offer.contract}
-      };
-
-      let contractHash = await hashContract(offer.contract);
-
-      if (contractHash != offer.H_contract) {
-        console.error("merchant-supplied contract hash is wrong");
+      if (msg.contract_url) {
+        let proposal = await downloadContract(msg.contract_url);
+        await processProposal(proposal);
         return;
       }
 
-      let resp = await checkRepurchase(offer.contract);
-
-      if (resp.error) {
-        console.error("wallet backend error", resp);
+      if (msg.offer_url) {
+        document.location.href = msg.offer_url;
         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 = offer.contract.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(offer);
-
-        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;
-        }
-      }
+      console.log("can't proceed with payment, no way to get contract 
specified");
     });
 
     addHandler("taler-payment-failed", (msg: any, sendResponse: any) => {
@@ -336,41 +397,5 @@ namespace TalerNotify {
         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,
-                     });
-      });
-    });
   }
 }
diff --git a/src/cryptoLib.ts b/src/cryptoLib.ts
index fe1d6f3..7a363e6 100644
--- a/src/cryptoLib.ts
+++ b/src/cryptoLib.ts
@@ -222,7 +222,6 @@ namespace RpcFunctions {
         merchant: native.EddsaPublicKey.fromCrock(offer.contract.merchant_pub),
         refund_deadline: 
native.AbsoluteTimeNbo.fromTalerString(offer.contract.refund_deadline),
         timestamp: 
native.AbsoluteTimeNbo.fromTalerString(offer.contract.timestamp),
-        transaction_id: 
native.UInt64.fromNumber(offer.contract.transaction_id),
       });
 
       let coinSig = native.eddsaSign(d.toPurpose(),
diff --git a/src/emscriptif.ts b/src/emscriptif.ts
index f42bb55..cf519a3 100644
--- a/src/emscriptif.ts
+++ b/src/emscriptif.ts
@@ -1064,7 +1064,6 @@ export interface DepositRequestPS_Args {
   h_wire: HashCode;
   timestamp: AbsoluteTimeNbo;
   refund_deadline: AbsoluteTimeNbo;
-  transaction_id: UInt64;
   amount_with_fee: AmountNbo;
   deposit_fee: AmountNbo;
   merchant: EddsaPublicKey;
@@ -1087,7 +1086,6 @@ export class DepositRequestPS extends SignatureStruct {
       ["h_wire", HashCode],
       ["timestamp", AbsoluteTimeNbo],
       ["refund_deadline", AbsoluteTimeNbo],
-      ["transaction_id", UInt64],
       ["amount_with_fee", AmountNbo],
       ["deposit_fee", AmountNbo],
       ["merchant", EddsaPublicKey],
diff --git a/src/renderHtml.tsx b/src/renderHtml.tsx
index 40b4809..79e101b 100644
--- a/src/renderHtml.tsx
+++ b/src/renderHtml.tsx
@@ -30,7 +30,12 @@ export function prettyAmount(amount: AmountJson) {
 }
 
 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>;
 
   return (
diff --git a/src/types.ts b/src/types.ts
index b044537..ab50c73 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -441,8 +441,8 @@ export class Contract {
   @Checkable.String
   H_wire: string;
 
-  @Checkable.String
-  summary: string;
+  @Checkable.Optional(Checkable.String)
+  summary?: string;
 
   @Checkable.Value(AmountJson)
   amount: AmountJson;
@@ -450,12 +450,6 @@ export class Contract {
   @Checkable.List(Checkable.AnyObject)
   auditors: any[];
 
-  /**
-   * DEPRECATED alias for pay_deadline.
-   */
-  @Checkable.Optional(Checkable.String)
-  expiry: string;
-
   @Checkable.Optional(Checkable.String)
   pay_deadline: string;
 
@@ -483,8 +477,8 @@ export class Contract {
   @Checkable.String
   timestamp: string;
 
-  @Checkable.Number
-  transaction_id: number;
+  @Checkable.String
+  order_id: string;
 
   @Checkable.String
   fulfillment_url: string;
@@ -492,15 +486,12 @@ export class Contract {
   @Checkable.Optional(Checkable.String)
   repurchase_correlation_id: string;
 
-  /**
-   * DEPRECATED alias for instance
-   */
-  @Checkable.Optional(Checkable.String)
-  receiver: string;
-
   @Checkable.Optional(Checkable.String)
   instance: string;
 
+  @Checkable.Any
+  extra: any;
+
   static checked: (obj: any) => Contract;
 }
 
diff --git a/src/wallet.ts b/src/wallet.ts
index 971fa67..1c9de01 100644
--- a/src/wallet.ts
+++ b/src/wallet.ts
@@ -164,21 +164,10 @@ export interface HistoryRecord {
 
 
 interface PayReq {
-  amount: AmountJson;
   coins: CoinPaySig[];
-  H_contract: string;
-  max_fee: AmountJson;
-  merchant_sig: string;
+  merchant_pub: string;
+  order_id: string;
   exchange: string;
-  refund_deadline: string;
-  timestamp: string;
-  transaction_id: number;
-  pay_deadline: string;
-  /**
-   * Merchant instance identifier that should receive the
-   * payment, if applicable.
-   */
-  instance?: string;
 }
 
 interface TransactionRecord {
@@ -353,6 +342,8 @@ export namespace Stores {
       "contract.merchant_pub",
       "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> {
@@ -553,17 +544,10 @@ export class Wallet {
                                  payCoinInfo: PayCoinInfo,
                                  chosenExchange: string): Promise<void> {
     let payReq: PayReq = {
-      amount: offer.contract.amount,
       coins: payCoinInfo.map((x) => x.sig),
-      H_contract: offer.H_contract,
-      max_fee: offer.contract.max_fee,
-      merchant_sig: offer.merchant_sig,
-      exchange: URI(chosenExchange).href(),
-      refund_deadline: offer.contract.refund_deadline,
-      pay_deadline: offer.contract.pay_deadline,
-      timestamp: offer.contract.timestamp,
-      transaction_id: offer.contract.transaction_id,
-      instance: offer.contract.merchant.instance
+      merchant_pub: offer.contract.merchant_pub,
+      order_id: offer.contract.order_id,
+      exchange: chosenExchange,
     };
     let t: TransactionRecord = {
       contractHash: offer.H_contract,
@@ -681,18 +665,36 @@ export class Wallet {
    * Retrieve all necessary information for looking up the contract
    * with the given hash.
    */
-  async executePayment(H_contract: string): Promise<any> {
-    let t = await this.q().get<TransactionRecord>(Stores.transactions,
-                                                  H_contract);
+  async queryPayment(query: any): Promise<any> {
+    let t: TransactionRecord | undefined;
+
+    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) {
+      console.log("query for payment failed");
       return {
         success: false,
-        contractFound: false,
       }
     }
+    console.log("query for payment succeeded:", t);
     let resp = {
       success: true,
       payReq: t.payReq,
+      H_contract: t.contractHash,
       contract: t.contract,
     };
     return resp;
diff --git a/src/wxBackend.ts b/src/wxBackend.ts
index 637ab5d..50e0689 100644
--- a/src/wxBackend.ts
+++ b/src/wxBackend.ts
@@ -139,20 +139,20 @@ function makeHandlers(db: IDBDatabase,
       }
       return wallet.checkPay(offer);
     },
-    ["execute-payment"]: function (detail: any, sender: MessageSender) {
+    ["query-payment"]: function (detail: any, sender: MessageSender) {
       if (sender.tab && sender.tab.id) {
         rateLimitCache[sender.tab.id]++;
         if (rateLimitCache[sender.tab.id] > 10) {
-          console.warn("rate limit for execute payment exceeded");
+          console.warn("rate limit for query-payment exceeded");
           let msg = {
-            error: "rate limit exceeded for execute-payment",
+            error: "rate limit exceeded for query-payment",
             rateLimitExceeded: true,
             hint: "Check for redirect loops",
           };
           return Promise.resolve(msg);
         }
       }
-      return wallet.executePayment(detail.H_contract);
+      return wallet.queryPayment(detail);
     },
     ["exchange-info"]: function (detail) {
       if (!detail.baseUrl) {
@@ -179,8 +179,10 @@ function makeHandlers(db: IDBDatabase,
       if (!offer) {
         return Promise.resolve({ error: "offer missing" });
       }
-      console.log("handling safe-offer");
-      return wallet.saveOffer(offer);
+      console.log("handling safe-offer", detail);
+      // FIXME:  fully migrate to new terminology
+      let checkedOffer = OfferRecord.checked(offer);
+      return wallet.saveOffer(checkedOffer);
     },
     ["reserve-creation-info"]: function (detail, sender) {
       if (!detail.baseUrl || typeof detail.baseUrl !== "string") {
@@ -317,8 +319,7 @@ class ChromeNotifier implements Notifier {
  */
 let paymentRequestCookies: { [n: number]: any } = {};
 
-function handleHttpPayment(headerList: chrome.webRequest.HttpHeader[],
-  url: string, tabId: number): any {
+function handleHttpPayment(headerList: chrome.webRequest.HttpHeader[], url: 
string, tabId: number): any {
   const headers: { [s: string]: string } = {};
   for (let kv of headerList) {
     if (kv.value) {
@@ -326,35 +327,52 @@ function handleHttpPayment(headerList: 
chrome.webRequest.HttpHeader[],
     }
   }
 
-  const contractUrl = headers["x-taler-contract-url"];
-  if (contractUrl !== undefined) {
-    paymentRequestCookies[tabId] = { type: "fetch", contractUrl };
-    return;
+  let fields = {
+    contract_url: headers["x-taler-contract-url"],
+    contract_query: headers["x-taler-contract-query"],
+    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) {
-    const payUrl = headers["x-taler-pay-url"];
-    if (payUrl === undefined) {
-      console.log("malformed 402, X-Taler-Pay-Url missing");
-      return;
+  for (let key of Object.keys(fields)) {
+    if ((fields as any)[key]) {
+      n++;
     }
+  }
 
-    // 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
+    // for a different payment system (or the shop is buggy)
+    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;
+      }
+    }
   }
 
-  // looks like it's not a taler request, it might be
-  // for a different payment system (or the shop is buggy)
-  console.log("ignoring non-taler 402 response");
+  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,
+  };
 }
 
 
diff --git a/web-common b/web-common
index d4de1c9..4831e66 160000
--- a/web-common
+++ b/web-common
@@ -1 +1 @@
-Subproject commit d4de1c912ecaac7991067027b352de61b237c0c9
+Subproject commit 4831e664d69759da288625911c053d145aa1b68c

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

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