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 (c62ba498 -> 82d


From: gnunet
Subject: [GNUnet-SVN] [taler-wallet-webex] branch master updated (c62ba498 -> 82d9c2a7)
Date: Thu, 18 Jan 2018 01:37:42 +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 c62ba498 implement new mobile-compatible payment logic
     new d4c2f6f6 use full amount with wire fees when creating deposit 
permission
     new 82d9c2a7 access refunds correctly

The 2 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/crypto/cryptoApi.ts              |  5 +--
 src/crypto/cryptoWorker.ts           |  5 +--
 src/dbTypes.ts                       |  3 ++
 src/i18n/de.po                       |  8 ++---
 src/i18n/en-US.po                    |  8 ++---
 src/i18n/fr.po                       |  8 ++---
 src/i18n/it.po                       |  8 ++---
 src/i18n/taler-wallet-webex.pot      |  8 ++---
 src/query.ts                         |  1 +
 src/wallet.ts                        | 61 ++++++++++++++++++++++++++----------
 src/walletTypes.ts                   |  4 +++
 src/webex/pages/confirm-contract.tsx | 17 +++++++++-
 src/webex/wxApi.ts                   |  2 +-
 src/webex/wxBackend.ts               |  6 +++-
 14 files changed, 101 insertions(+), 43 deletions(-)

diff --git a/src/crypto/cryptoApi.ts b/src/crypto/cryptoApi.ts
index 1f45ba8e..c1f3f424 100644
--- a/src/crypto/cryptoApi.ts
+++ b/src/crypto/cryptoApi.ts
@@ -293,8 +293,9 @@ export class CryptoApi {
   }
 
   signDeposit(contractTerms: ContractTerms,
-              cds: CoinWithDenom[]): Promise<PayCoinInfo> {
-    return this.doRpc<PayCoinInfo>("signDeposit", 3, contractTerms, cds);
+              cds: CoinWithDenom[],
+              totalAmount: AmountJson): Promise<PayCoinInfo> {
+    return this.doRpc<PayCoinInfo>("signDeposit", 3, contractTerms, cds, 
totalAmount);
   }
 
   createEddsaKeypair(): Promise<{priv: string, pub: string}> {
diff --git a/src/crypto/cryptoWorker.ts b/src/crypto/cryptoWorker.ts
index b7c8e933..6b82f6bc 100644
--- a/src/crypto/cryptoWorker.ts
+++ b/src/crypto/cryptoWorker.ts
@@ -269,7 +269,8 @@ namespace RpcFunctions {
    * and deposit permissions for each given coin.
    */
   export function signDeposit(contractTerms: ContractTerms,
-                              cds: CoinWithDenom[]): PayCoinInfo {
+                              cds: CoinWithDenom[],
+                              totalAmount: AmountJson): PayCoinInfo {
     const ret: PayCoinInfo = {
       originalCoins: [],
       sigs: [],
@@ -282,7 +283,7 @@ namespace RpcFunctions {
     let fees = Amounts.add(Amounts.getZero(feeList[0].currency), 
...feeList).amount;
     // okay if saturates
     fees = Amounts.sub(fees, contractTerms.max_fee).amount;
-    const total = Amounts.add(fees, contractTerms.amount).amount;
+    const total = Amounts.add(fees, totalAmount).amount;
 
     const amountSpent = 
native.Amount.getZero(cds[0].coin.currentAmount.currency);
     const amountRemaining = new native.Amount(total);
diff --git a/src/dbTypes.ts b/src/dbTypes.ts
index 86f3e0a1..9e966321 100644
--- a/src/dbTypes.ts
+++ b/src/dbTypes.ts
@@ -782,6 +782,8 @@ export interface PurchaseRecord {
    * Set to 0 if no refund was made on the purchase.
    */
   timestamp_refund: number;
+
+  lastSessionSig: string | undefined;
 }
 
 
@@ -889,6 +891,7 @@ export namespace Stores {
         keyPath: "id",
       });
     }
+    urlIndex = new Index<string, ProposalDownloadRecord>(this, "urlIndex", 
"url");
     timestampIndex = new Index<string, ProposalDownloadRecord>(this, 
"timestampIndex", "timestamp");
   }
 
diff --git a/src/i18n/de.po b/src/i18n/de.po
index 5f163a0d..1f6e9896 100644
--- a/src/i18n/de.po
+++ b/src/i18n/de.po
@@ -42,13 +42,13 @@ msgstr ""
 msgid "Exchanges in the wallet:"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:175
+#: src/webex/pages/confirm-contract.tsx:188
 #, c-format
 msgid "You have insufficient funds of the requested currency in your wallet."
 msgstr ""
 
 #. tslint:disable-next-line:max-line-length
-#: src/webex/pages/confirm-contract.tsx:177
+#: src/webex/pages/confirm-contract.tsx:190
 #, c-format
 msgid ""
 "You do not have any funds from an exchange that is accepted by this "
@@ -56,12 +56,12 @@ msgid ""
 "wallet."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:236
+#: src/webex/pages/confirm-contract.tsx:249
 #, c-format
 msgid "The merchant%1$s offers you to purchase:\n"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:257
+#: src/webex/pages/confirm-contract.tsx:270
 #, fuzzy, c-format
 msgid "Confirm payment"
 msgstr "Bezahlung bestätigen"
diff --git a/src/i18n/en-US.po b/src/i18n/en-US.po
index 0dfa852c..3e47e952 100644
--- a/src/i18n/en-US.po
+++ b/src/i18n/en-US.po
@@ -42,13 +42,13 @@ msgstr ""
 msgid "Exchanges in the wallet:"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:175
+#: src/webex/pages/confirm-contract.tsx:188
 #, c-format
 msgid "You have insufficient funds of the requested currency in your wallet."
 msgstr ""
 
 #. tslint:disable-next-line:max-line-length
-#: src/webex/pages/confirm-contract.tsx:177
+#: src/webex/pages/confirm-contract.tsx:190
 #, c-format
 msgid ""
 "You do not have any funds from an exchange that is accepted by this "
@@ -56,12 +56,12 @@ msgid ""
 "wallet."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:236
+#: src/webex/pages/confirm-contract.tsx:249
 #, c-format
 msgid "The merchant%1$s offers you to purchase:\n"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:257
+#: src/webex/pages/confirm-contract.tsx:270
 #, c-format
 msgid "Confirm payment"
 msgstr ""
diff --git a/src/i18n/fr.po b/src/i18n/fr.po
index 55677763..97ff4706 100644
--- a/src/i18n/fr.po
+++ b/src/i18n/fr.po
@@ -42,13 +42,13 @@ msgstr ""
 msgid "Exchanges in the wallet:"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:175
+#: src/webex/pages/confirm-contract.tsx:188
 #, c-format
 msgid "You have insufficient funds of the requested currency in your wallet."
 msgstr ""
 
 #. tslint:disable-next-line:max-line-length
-#: src/webex/pages/confirm-contract.tsx:177
+#: src/webex/pages/confirm-contract.tsx:190
 #, c-format
 msgid ""
 "You do not have any funds from an exchange that is accepted by this "
@@ -56,12 +56,12 @@ msgid ""
 "wallet."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:236
+#: src/webex/pages/confirm-contract.tsx:249
 #, c-format
 msgid "The merchant%1$s offers you to purchase:\n"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:257
+#: src/webex/pages/confirm-contract.tsx:270
 #, c-format
 msgid "Confirm payment"
 msgstr ""
diff --git a/src/i18n/it.po b/src/i18n/it.po
index 55677763..97ff4706 100644
--- a/src/i18n/it.po
+++ b/src/i18n/it.po
@@ -42,13 +42,13 @@ msgstr ""
 msgid "Exchanges in the wallet:"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:175
+#: src/webex/pages/confirm-contract.tsx:188
 #, c-format
 msgid "You have insufficient funds of the requested currency in your wallet."
 msgstr ""
 
 #. tslint:disable-next-line:max-line-length
-#: src/webex/pages/confirm-contract.tsx:177
+#: src/webex/pages/confirm-contract.tsx:190
 #, c-format
 msgid ""
 "You do not have any funds from an exchange that is accepted by this "
@@ -56,12 +56,12 @@ msgid ""
 "wallet."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:236
+#: src/webex/pages/confirm-contract.tsx:249
 #, c-format
 msgid "The merchant%1$s offers you to purchase:\n"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:257
+#: src/webex/pages/confirm-contract.tsx:270
 #, c-format
 msgid "Confirm payment"
 msgstr ""
diff --git a/src/i18n/taler-wallet-webex.pot b/src/i18n/taler-wallet-webex.pot
index 55677763..97ff4706 100644
--- a/src/i18n/taler-wallet-webex.pot
+++ b/src/i18n/taler-wallet-webex.pot
@@ -42,13 +42,13 @@ msgstr ""
 msgid "Exchanges in the wallet:"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:175
+#: src/webex/pages/confirm-contract.tsx:188
 #, c-format
 msgid "You have insufficient funds of the requested currency in your wallet."
 msgstr ""
 
 #. tslint:disable-next-line:max-line-length
-#: src/webex/pages/confirm-contract.tsx:177
+#: src/webex/pages/confirm-contract.tsx:190
 #, c-format
 msgid ""
 "You do not have any funds from an exchange that is accepted by this "
@@ -56,12 +56,12 @@ msgid ""
 "wallet."
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:236
+#: src/webex/pages/confirm-contract.tsx:249
 #, c-format
 msgid "The merchant%1$s offers you to purchase:\n"
 msgstr ""
 
-#: src/webex/pages/confirm-contract.tsx:257
+#: src/webex/pages/confirm-contract.tsx:270
 #, c-format
 msgid "Confirm payment"
 msgstr ""
diff --git a/src/query.ts b/src/query.ts
index e45596c6..290d02a2 100644
--- a/src/query.ts
+++ b/src/query.ts
@@ -685,6 +685,7 @@ export class QueryRoot {
   put<T>(store: Store<T>, val: T, keyName?: string): QueryRoot {
     this.checkFinished();
     const doPut = (tx: IDBTransaction) => {
+      console.log("put into", store.name, "value", val);
       const req = tx.objectStore(store.name).put(val);
       if (keyName) {
         req.onsuccess = () => {
diff --git a/src/wallet.ts b/src/wallet.ts
index 24fab9f8..aa974369 100644
--- a/src/wallet.ts
+++ b/src/wallet.ts
@@ -312,6 +312,7 @@ export class Wallet {
   private processPreCoinThrottle: {[url: string]: number} = {};
   private timerGroup: TimerGroup;
   private speculativePayData: SpeculativePayData | undefined;
+  private cachedNextUrl: { [fulfillmentUrl: string]: string } = {};
 
   /**
    * Set of identifiers for running operations.
@@ -593,15 +594,23 @@ export class Wallet {
         continue;
       }
 
+      console.log("payment coins: wireFeeLimit", wireFeeLimit);
+      console.log("payment coins: wireFeeAmortization", wireFeeAmortization);
+      console.log("payment coins: fees", fees);
+      console.log("payment coins: wireMethod", wireMethod);
+      console.log("payment coins: wireFeeTime", wireFeeTime);
+
       let totalFees = Amounts.getZero(currency);
       let wireFee: AmountJson|undefined;
       for (const fee of (fees.feesForType[wireMethod] || [])) {
-        if (fee.startStamp >= wireFeeTime && fee.endStamp <= wireFeeTime) {
+        if (fee.startStamp <= wireFeeTime && fee.endStamp >= wireFeeTime) {
           wireFee = fee.wireFee;
           break;
         }
       }
 
+      console.log("payment coins: current wire fees", wireFee);
+
       if (wireFee) {
         const amortizedWireFee = Amounts.divide(wireFee, wireFeeAmortization);
         if (Amounts.cmp(wireFeeLimit, amortizedWireFee) < 0) {
@@ -616,6 +625,7 @@ export class Wallet {
         return {
           cds: res.cds,
           exchangeUrl: exchange.baseUrl,
+          totalAmount: remainingAmount,
           totalFees,
         };
       }
@@ -641,6 +651,7 @@ export class Wallet {
       contractTerms: proposal.contractTerms,
       contractTermsHash: proposal.contractTermsHash,
       finished: false,
+      lastSessionSig: undefined,
       merchantSig: proposal.merchantSig,
       payReq,
       refundsDone: {},
@@ -664,13 +675,19 @@ export class Wallet {
    * Returns an id for it to retrieve it later.
    */
   async downloadProposal(url: string): Promise<number> {
+
+    const oldProposal = await this.q().getIndexed(Stores.proposals.urlIndex, 
url);
+    if (oldProposal) {
+      return oldProposal.id!;
+    }
+
     const { priv, pub } = await this.cryptoApi.createEddsaKeypair();
     const parsed_url = new URI(url);
-    url = parsed_url.setQuery({ nonce: pub }).href();
-    console.log("downloading contract from '" + url + "'");
+    const urlWithNonce = parsed_url.setQuery({ nonce: pub }).href();
+    console.log("downloading contract from '" + urlWithNonce + "'");
     let resp;
     try {
-      resp = await axios.get(url, { validateStatus: (s) => s === 200 });
+      resp = await axios.get(urlWithNonce, { validateStatus: (s) => s === 200 
});
     } catch (e) {
       console.log("contract download failed", e);
       throw e;
@@ -698,7 +715,7 @@ export class Wallet {
     return id;
   }
 
-  async submitPay(purchase: PurchaseRecord, sessionId: string | undefined): 
Promise<ConfirmPayResult> {
+  private async submitPay(purchase: PurchaseRecord, sessionId: string | 
undefined): Promise<ConfirmPayResult> {
     let resp;
     const payReq = { ...purchase.payReq, session_id: sessionId };
     try {
@@ -715,13 +732,17 @@ export class Wallet {
     }
     const merchantResp = resp.data;
     console.log("got success from pay_url");
-    await this.paymentSucceeded(purchase.contractTermsHash, merchantResp.sig);
     const fu = new URI(purchase.contractTerms.fulfillment_url);
     fu.addSearch("order_id", purchase.contractTerms.order_id);
     if (merchantResp.session_sig) {
       fu.addSearch("session_sig", merchantResp.session_sig);
+      purchase.lastSessionSig = merchantResp.session_sig;
+      console.log("updating session sig", purchase);
+      await this.q().put(Stores.purchases, purchase).finish();
     }
+    await this.paymentSucceeded(purchase.contractTermsHash, merchantResp.sig);
     const nextUrl = fu.href();
+    this.cachedNextUrl[purchase.contractTerms.fulfillment_url] = nextUrl;
     return { nextUrl };
   }
 
@@ -766,8 +787,8 @@ export class Wallet {
 
     const sd = await this.getSpeculativePayData(proposalId);
     if (!sd) {
-      const { exchangeUrl, cds } = res;
-      const payCoinInfo = await 
this.cryptoApi.signDeposit(proposal.contractTerms, cds);
+      const { exchangeUrl, cds, totalAmount } = res;
+      const payCoinInfo = await 
this.cryptoApi.signDeposit(proposal.contractTerms, cds, totalAmount);
       purchase = await this.recordConfirmPay(proposal, payCoinInfo, 
exchangeUrl);
     } else {
       purchase = await this.recordConfirmPay(sd.proposal, sd.payCoinInfo, 
sd.exchangeUrl);
@@ -844,8 +865,8 @@ export class Wallet {
 
     // Only create speculative signature if we don't already have one for this 
proposal
     if ((!this.speculativePayData) || (this.speculativePayData && 
this.speculativePayData.proposalId !== proposalId)) {
-      const { exchangeUrl, cds } = res;
-      const payCoinInfo = await 
this.cryptoApi.signDeposit(proposal.contractTerms, cds);
+      const { exchangeUrl, cds, totalAmount } = res;
+      const payCoinInfo = await 
this.cryptoApi.signDeposit(proposal.contractTerms, cds, totalAmount);
       this.speculativePayData = {
         exchangeUrl,
         payCoinInfo,
@@ -878,6 +899,7 @@ export class Wallet {
       contractTerms: t.contractTerms,
       contractTermsHash: t.contractTermsHash,
       found: true,
+      lastSessionSig: t.lastSessionSig,
       payReq: t.payReq,
     };
   }
@@ -902,6 +924,7 @@ export class Wallet {
       contractTerms: t.contractTerms,
       contractTermsHash: t.contractTermsHash,
       found: true,
+      lastSessionSig: t.lastSessionSig,
       payReq: t.payReq,
     };
   }
@@ -1066,7 +1089,7 @@ export class Wallet {
         id: hash(senderWire),
         senderWire,
       };
-      await this.q().put(Stores.senderWires, rec);
+      await this.q().put(Stores.senderWires, rec).finish();
     }
 
     await this.updateExchangeUsedTime(req.exchange);
@@ -2250,10 +2273,10 @@ export class Wallet {
   }
 
 
-  async paymentSucceeded(contractTermsHash: string, merchantSig: string): 
Promise<any> {
+  private async paymentSucceeded(contractTermsHash: string, merchantSig: 
string): Promise<any> {
     const doPaymentSucceeded = async() => {
       const t = await this.q().get<PurchaseRecord>(Stores.purchases,
-                                                    contractTermsHash);
+                                                   contractTermsHash);
       if (!t) {
         console.error("contract not found");
         return;
@@ -2456,7 +2479,7 @@ export class Wallet {
 
     const contractTermsHash = await 
this.cryptoApi.hashString(canonicalJson(contractTerms));
 
-    const payCoinInfo = await this.cryptoApi.signDeposit(contractTerms, cds);
+    const payCoinInfo = await this.cryptoApi.signDeposit(contractTerms, cds, 
contractTerms.amount);
 
     console.log("pci", payCoinInfo);
 
@@ -2551,7 +2574,7 @@ export class Wallet {
     }
 
     // FIXME: validate schema
-    const refundPermissions = resp.data;
+    const refundPermissions = resp.data.refund_permissions;
 
     if (!refundPermissions.length) {
       console.warn("got empty refund list");
@@ -2862,8 +2885,14 @@ export class Wallet {
   }
 
 
+  /**
+   * Synchronously get the paid URL for a resource from the plain fulfillment
+   * URL.  Returns undefined if the fulfillment URL is not a resource that was
+   * payed for, or if it is not cached anymore.  Use the asynchronous
+   * queryPaymentByFulfillmentUrl to avoid false negatives.
+   */
   getNextUrlFromResourceUrl(resourceUrl: string): string | undefined {
-    return;
+    return this.cachedNextUrl[resourceUrl];
   }
 
   /**
diff --git a/src/walletTypes.ts b/src/walletTypes.ts
index d1a4f874..45a79587 100644
--- a/src/walletTypes.ts
+++ b/src/walletTypes.ts
@@ -415,6 +415,10 @@ export interface CoinSelectionResult {
   exchangeUrl: string;
   cds: CoinWithDenom[];
   totalFees: AmountJson;
+  /**
+   * Total amount, including wire fees payed by the customer.
+   */
+  totalAmount: AmountJson;
 }
 
 
diff --git a/src/webex/pages/confirm-contract.tsx 
b/src/webex/pages/confirm-contract.tsx
index 09073747..c302239c 100644
--- a/src/webex/pages/confirm-contract.tsx
+++ b/src/webex/pages/confirm-contract.tsx
@@ -105,6 +105,7 @@ interface ContractPromptProps {
   proposalId?: number;
   contractUrl?: string;
   sessionId?: string;
+  resourceUrl?: string;
 }
 
 interface ContractPromptState {
@@ -146,6 +147,18 @@ class ContractPrompt extends 
React.Component<ContractPromptProps, ContractPrompt
   }
 
   async update() {
+    if (this.props.resourceUrl) {
+      const p = await 
wxApi.queryPaymentByFulfillmentUrl(this.props.resourceUrl);
+      console.log("query for resource url", this.props.resourceUrl, "result", 
p);
+      if (p.found) {
+        const nextUrl = new URI(p.contractTerms.fulfillment_url);
+        nextUrl.addSearch("order_id", p.contractTerms.order_id);
+        if (p.lastSessionSig) {
+          nextUrl.addSearch("session_sig", p.lastSessionSig);
+        }
+        location.href = nextUrl.href();
+      }
+    }
     let proposalId = this.props.proposalId;
     if (proposalId === undefined) {
       if (this.props.contractUrl === undefined) {
@@ -285,7 +298,9 @@ document.addEventListener("DOMContentLoaded", () => {
   const sessionId = query.sessionId;
   const contractUrl = query.contractUrl;
 
+  const resourceUrl = query.resourceUrl;
+
   ReactDOM.render(
-    <ContractPrompt {...{ proposalId, contractUrl, sessionId }}/>,
+    <ContractPrompt {...{ proposalId, contractUrl, sessionId, resourceUrl }}/>,
     document.getElementById("contract")!);
 });
diff --git a/src/webex/wxApi.ts b/src/webex/wxApi.ts
index efebf21d..84c44dba 100644
--- a/src/webex/wxApi.ts
+++ b/src/webex/wxApi.ts
@@ -238,7 +238,7 @@ export function confirmReserve(reservePub: string): 
Promise<void> {
 /**
  * Query for a payment by fulfillment URL.
  */
-export function queryPayment(url: string): Promise<QueryPaymentResult> {
+export function queryPaymentByFulfillmentUrl(url: string): 
Promise<QueryPaymentResult> {
   return callBackend("query-payment", { url });
 }
 
diff --git a/src/webex/wxBackend.ts b/src/webex/wxBackend.ts
index c0b42a76..7bbba175 100644
--- a/src/webex/wxBackend.ts
+++ b/src/webex/wxBackend.ts
@@ -416,11 +416,12 @@ async function talerPay(fields: any, url: string, tabId: 
number): Promise<string
     if (p.lastSessionSig) {
       nextUrl.addSearch("session_sig", p.lastSessionSig);
     }
-    return url;
+    return nextUrl.href();
   };
 
   if (fields.resource_url) {
     const p = await w.queryPaymentByFulfillmentUrl(fields.resource_url);
+    console.log("query for resource url", fields.resource_url, "result", p);
     if (p.found) {
       return goToPayment(p);
     }
@@ -519,6 +520,9 @@ function handleHttpPayment(headerList: 
chrome.webRequest.HttpHeader[], url: stri
     if (fields.session_id) {
       uri.addSearch("sessionId", fields.session_id);
     }
+    if (fields.resource_url) {
+      uri.addSearch("resourceUrl", fields.resource_url);
+    }
     return { redirectUrl: uri.href() };
   }
 

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



reply via email to

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