gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated: updated preparePay API accord


From: gnunet
Subject: [taler-wallet-core] branch master updated: updated preparePay API according to spec
Date: Tue, 28 Jul 2020 11:48:48 +0200

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

dold pushed a commit to branch master
in repository wallet-core.

The following commit(s) were added to refs/heads/master by this push:
     new 43655adf updated preparePay API according to spec
43655adf is described below

commit 43655adff0f8f1db082e1f0c18f1271a29ab8905
Author: Florian Dold <florian.dold@gmail.com>
AuthorDate: Tue Jul 28 15:18:01 2020 +0530

    updated preparePay API according to spec
---
 src/TalerErrorCode.ts            | 23 ++++++++++++++++-
 src/headless/taler-wallet-cli.ts | 32 ++++++++++++-----------
 src/operations/pay.ts            | 55 ++++++++++++++++++++++++++--------------
 src/types/walletTypes.ts         | 26 ++++++++++---------
 src/webex/pages/pay.tsx          |  8 ++----
 5 files changed, 91 insertions(+), 53 deletions(-)

diff --git a/src/TalerErrorCode.ts b/src/TalerErrorCode.ts
index f338f1ad..56c28ee2 100644
--- a/src/TalerErrorCode.ts
+++ b/src/TalerErrorCode.ts
@@ -550,7 +550,7 @@ export enum TalerErrorCode {
   DEPOSIT_INVALID_WIRE_FORMAT_JSON = 1210,
 
   /**
-   * The hash of the given wire address does not match the hash specified in 
the proposal data.
+   * The hash of the given wire address does not match the wire hash specified 
in the proposal data.
    * Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).
    * (A value of 0 indicates that the error is generated client-side).
    */
@@ -1403,6 +1403,13 @@ export enum TalerErrorCode {
    */
   PAY_EXCHANGE_FAILED = 2135,
 
+  /**
+   * The merchant backend couldn't verify the order payment because of a 
database failure.
+   * Returned with an HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR 
(500).
+   * (A value of 0 indicates that the error is generated client-side).
+   */
+  PAID_DB_ERROR = 2146,
+
   /**
    * The order is not known.
    * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).
@@ -2677,6 +2684,13 @@ export enum TalerErrorCode {
    */
   MERCHANT_ORDER_GET_REPLY_MALFORMED = 2922,
 
+  /**
+   * The token used to authenticate the client is invalid for this order.
+   * Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).
+   * (A value of 0 indicates that the error is generated client-side).
+   */
+  MERCHANT_GET_ORDER_INVALID_TOKEN = 2923,
+
   /**
    * The signature from the exchange on the deposit confirmation is invalid.  
Returned with a "400 Bad Request" status code.
    * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).
@@ -3062,6 +3076,13 @@ export enum TalerErrorCode {
    */
   WALLET_CORE_API_OPERATION_UNKNOWN = 7007,
 
+  /**
+   * The given taler://pay URI is invalid.
+   * Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).
+   * (A value of 0 indicates that the error is generated client-side).
+   */
+  WALLET_INVALID_TALER_PAY_URI = 7008,
+
   /**
    * The exchange does not know about the reserve (yet), and thus withdrawal 
can't progress.
    * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).
diff --git a/src/headless/taler-wallet-cli.ts b/src/headless/taler-wallet-cli.ts
index 4bae298a..ca0f0f5d 100644
--- a/src/headless/taler-wallet-cli.ts
+++ b/src/headless/taler-wallet-cli.ts
@@ -43,6 +43,7 @@ import { NodeHttpLib } from "./NodeHttpLib";
 import * as nacl from "../crypto/primitives/nacl-fast";
 import { addPaytoQueryParams } from "../util/payto";
 import { handleCoreApiRequest } from "../walletCoreApiHandler";
+import { PreparePayResultType } from "../types/walletTypes";
 
 const logger = new Logger("taler-wallet-cli.ts");
 
@@ -58,19 +59,19 @@ async function doPay(
   options: { alwaysYes: boolean } = { alwaysYes: true },
 ): Promise<void> {
   const result = await wallet.preparePayForUri(payUrl);
-  if (result.status === "error") {
-    console.error("Could not pay:", result.error);
-    process.exit(1);
-    return;
-  }
-  if (result.status === "insufficient-balance") {
+  if (result.status === PreparePayResultType.InsufficientBalance) {
     console.log("contract", result.contractTermsRaw);
     console.error("insufficient balance");
     process.exit(1);
     return;
   }
-  if (result.status === "paid") {
-    console.log("already paid!");
+  if (result.status === PreparePayResultType.AlreadyConfirmed) {
+    if (result.paid) {
+      console.log("already paid!");
+    } else {
+      console.log("payment already in progress");
+    }
+    
     process.exit(0);
     return;
   }
@@ -502,16 +503,17 @@ advancedCli
     await withWallet(args, async (wallet) => {
       const res = await wallet.preparePayForUri(args.payPrepare.url);
       switch (res.status) {
-        case "error":
-          console.log("error:", res.error);
-          break;
-        case "insufficient-balance":
+        case PreparePayResultType.InsufficientBalance:
           console.log("insufficient balance");
           break;
-        case "paid":
-          console.log("already paid");
+        case PreparePayResultType.AlreadyConfirmed:
+          if (res.paid) {
+            console.log("already paid!");
+          } else {
+            console.log("payment in progress");
+          }
           break;
-        case "payment-possible":
+        case PreparePayResultType.PaymentPossible:
           console.log("payment possible");
           break;
         default:
diff --git a/src/operations/pay.ts b/src/operations/pay.ts
index 58911b4b..08bbe43a 100644
--- a/src/operations/pay.ts
+++ b/src/operations/pay.ts
@@ -48,19 +48,19 @@ import {
   OperationErrorDetails,
   PreparePayResult,
   RefreshReason,
+  PreparePayResultType,
 } from "../types/walletTypes";
 import * as Amounts from "../util/amounts";
 import { AmountJson } from "../util/amounts";
 import { Logger } from "../util/logging";
 import { parsePayUri } from "../util/taleruri";
-import { guardOperationException } from "./errors";
+import { guardOperationException, OperationFailedError } from "./errors";
 import { createRefreshGroup, getTotalRefreshCost } from "./refresh";
 import { InternalWalletState } from "./state";
 import { getTimestampNow, timestampAddDuration } from "../util/time";
 import { strcmp, canonicalJson } from "../util/helpers";
-import {
-  readSuccessResponseJsonOrThrow,
-} from "../util/http";
+import { readSuccessResponseJsonOrThrow } from "../util/http";
+import { TalerErrorCode } from "../TalerErrorCode";
 
 /**
  * Logger.
@@ -783,7 +783,7 @@ export async function submitPay(
     coins: purchase.coinDepositPermissions,
     session_id: purchase.lastSessionId,
   };
-  
+
   logger.trace("making pay request", JSON.stringify(reqBody, undefined, 2));
 
   const resp = await ws.http.postJson(payUrl, reqBody);
@@ -860,10 +860,13 @@ export async function preparePayForUri(
   const uriResult = parsePayUri(talerPayUri);
 
   if (!uriResult) {
-    return {
-      status: "error",
-      error: "URI not supported",
-    };
+    throw OperationFailedError.fromCode(
+      TalerErrorCode.WALLET_INVALID_TALER_PAY_URI,
+      `invalid taler://pay URI (${talerPayUri})`,
+      {
+        talerPayUri,
+      }
+    );
   }
 
   let proposalId = await startDownloadProposal(
@@ -911,7 +914,7 @@ export async function preparePayForUri(
     if (!res) {
       console.log("not confirming payment, insufficient coins");
       return {
-        status: "insufficient-balance",
+        status: PreparePayResultType.InsufficientBalance,
         contractTermsRaw: d.contractTermsRaw,
         proposalId: proposal.proposalId,
       };
@@ -923,14 +926,14 @@ export async function preparePayForUri(
     const totalFees = Amounts.sub(costInfo.totalCost, 
res.paymentAmount).amount;
 
     return {
-      status: "payment-possible",
+      status: PreparePayResultType.PaymentPossible,
       contractTermsRaw: d.contractTermsRaw,
       proposalId: proposal.proposalId,
       totalFees,
     };
   }
 
-  if (uriResult.sessionId && purchase.lastSessionId !== uriResult.sessionId) {
+  if (purchase.lastSessionId !== uriResult.sessionId) {
     console.log(
       "automatically re-submitting payment with different session ID",
     );
@@ -942,14 +945,28 @@ export async function preparePayForUri(
       p.lastSessionId = uriResult.sessionId;
       await tx.put(Stores.purchases, p);
     });
-    await submitPay(ws, proposalId);
+    const r = await submitPay(ws, proposalId);
+    return {
+      status: PreparePayResultType.AlreadyConfirmed,
+      contractTermsRaw: purchase.contractTermsRaw,
+      paid: true,
+      nextUrl: r.nextUrl,
+    };
+  } else if (!purchase.timestampFirstSuccessfulPay) {
+    return {
+      status: PreparePayResultType.AlreadyConfirmed,
+      contractTermsRaw: purchase.contractTermsRaw,
+      paid: false,
+    };    
+  } else if (purchase.paymentSubmitPending) {
+    return {
+      status: PreparePayResultType.AlreadyConfirmed,
+      contractTermsRaw: purchase.contractTermsRaw,
+      paid: false,
+    };
   }
-
-  return {
-    status: "paid",
-    contractTermsRaw: purchase.contractTermsRaw,
-    nextUrl: getNextUrl(purchase.contractData),
-  };
+  // FIXME: we don't handle aborted payments correctly here.
+  throw Error("BUG: invariant violation (purchase status)");
 }
 
 /**
diff --git a/src/types/walletTypes.ts b/src/types/walletTypes.ts
index 2ca95bf4..d68f4156 100644
--- a/src/types/walletTypes.ts
+++ b/src/types/walletTypes.ts
@@ -337,34 +337,36 @@ export interface NextUrlResult {
   lastSessionId: string | undefined;
 }
 
+export const enum PreparePayResultType {
+  PaymentPossible = "payment-possible",
+  InsufficientBalance = "insufficient-balance",
+  AlreadyConfirmed = "already-confirmed",
+}
+
 export type PreparePayResult =
-  | PreparePayResultError
   | PreparePayResultInsufficientBalance
-  | PreparePayResultPaid
+  | PreparePayResultAlreadyConfirmed
   | PreparePayResultPaymentPossible;
 
 export interface PreparePayResultPaymentPossible {
-  status: "payment-possible";
+  status: PreparePayResultType.PaymentPossible;
   proposalId: string;
   contractTermsRaw: string;
   totalFees: AmountJson;
 }
 
 export interface PreparePayResultInsufficientBalance {
-  status: "insufficient-balance";
+  status: PreparePayResultType.InsufficientBalance;
   proposalId: string;
   contractTermsRaw: any;
 }
 
-export interface PreparePayResultError {
-  status: "error";
-  error: string;
-}
-
-export interface PreparePayResultPaid {
-  status: "paid";
+export interface PreparePayResultAlreadyConfirmed {
+  status: PreparePayResultType.AlreadyConfirmed;
   contractTermsRaw: any;
-  nextUrl: string;
+  paid: boolean;
+  // Only specified if paid.
+  nextUrl?: string;
 }
 
 export interface BankWithdrawDetails {
diff --git a/src/webex/pages/pay.tsx b/src/webex/pages/pay.tsx
index a69b6b76..87f3c83d 100644
--- a/src/webex/pages/pay.tsx
+++ b/src/webex/pages/pay.tsx
@@ -24,7 +24,7 @@
  */
 import * as i18n from "../i18n";
 
-import { PreparePayResult } from "../../types/walletTypes";
+import { PreparePayResult, PreparePayResultType } from 
"../../types/walletTypes";
 
 import { renderAmount, ProgressButton } from "../renderHtml";
 import * as wxApi from "../wxApi";
@@ -58,15 +58,11 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: 
string }): JSX.Element {
     insufficientBalance = true;
   }
 
-  if (payStatus.status === "error") {
-    return <span>Error: {payStatus.error}</span>;
-  }
-
   if (payStatus.status === "payment-possible") {
     totalFees = payStatus.totalFees;
   }
 
-  if (payStatus.status === "paid" && numTries === 0) {
+  if (payStatus.status === PreparePayResultType.AlreadyConfirmed && numTries 
=== 0) {
     return (
       <span>
         You have already paid for this article. Click{" "}

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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