summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-04-06 19:49:25 +0200
committerChristian Grothoff <christian@grothoff.org>2020-04-06 19:49:25 +0200
commit01b900cf48569cc58e3f8c447606275a99546669 (patch)
treed53dc4cffd0f926025102fee255444e4017bb990
parent76243c5398d79d370636d69df7368648e3e14770 (diff)
downloadmerchant-01b900cf48569cc58e3f8c447606275a99546669.tar.gz
merchant-01b900cf48569cc58e3f8c447606275a99546669.tar.bz2
merchant-01b900cf48569cc58e3f8c447606275a99546669.zip
make API return exchange data systematically, fixes #4939
-rw-r--r--src/include/taler_merchant_service.h469
-rw-r--r--src/lib/Makefile.am3
-rw-r--r--src/lib/merchant_api_check_payment.c75
-rw-r--r--src/lib/merchant_api_common.c118
-rw-r--r--src/lib/merchant_api_history.c64
-rw-r--r--src/lib/merchant_api_pay.c209
-rw-r--r--src/lib/merchant_api_poll_payment.c60
-rw-r--r--src/lib/merchant_api_proposal.c312
-rw-r--r--src/lib/merchant_api_proposal_lookup.c279
-rw-r--r--src/lib/merchant_api_refund.c34
-rw-r--r--src/lib/merchant_api_refund_increase.c35
-rw-r--r--src/lib/merchant_api_tip_authorize.c70
-rw-r--r--src/lib/merchant_api_tip_pickup.c42
-rw-r--r--src/lib/merchant_api_tip_query.c127
-rw-r--r--src/lib/merchant_api_track_transaction.c54
-rw-r--r--src/lib/merchant_api_track_transfer.c72
-rw-r--r--src/lib/testing_api_cmd_check_payment.c14
-rw-r--r--src/lib/testing_api_cmd_history.c21
-rw-r--r--src/lib/testing_api_cmd_pay.c507
-rw-r--r--src/lib/testing_api_cmd_pay_abort.c595
-rw-r--r--src/lib/testing_api_cmd_poll_payment.c18
-rw-r--r--src/lib/testing_api_cmd_proposal.c75
-rw-r--r--src/lib/testing_api_cmd_proposal_lookup.c13
-rw-r--r--src/lib/testing_api_cmd_refund_increase.c25
-rw-r--r--src/lib/testing_api_cmd_refund_lookup.c85
-rw-r--r--src/lib/testing_api_cmd_tip_authorize.c132
-rw-r--r--src/lib/testing_api_cmd_tip_pickup.c212
-rw-r--r--src/lib/testing_api_cmd_tip_query.c124
-rw-r--r--src/lib/testing_api_cmd_track_transaction.c124
-rw-r--r--src/lib/testing_api_cmd_track_transfer.c98
30 files changed, 2306 insertions, 1760 deletions
diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h
index 320399cb..d8d51d40 100644
--- a/src/include/taler_merchant_service.h
+++ b/src/include/taler_merchant_service.h
@@ -29,6 +29,98 @@
#include <jansson.h>
+/**
+ * General information about the HTTP response we obtained
+ * from the merchant for a request.
+ */
+struct TALER_MERCHANT_HttpResponse
+{
+
+ /**
+ * The complete JSON reply. NULL if we failed to parse the
+ * reply (too big, invalid JSON).
+ */
+ const json_t *reply;
+
+ /**
+ * The complete JSON reply from the exchange, if we generated an error in
+ * response to an exchange error. Usually set if @e http_status is
+ * #MHD_HTTP_FAILED_DEPENDENDCY or #MHD_HTTP_SERVICE_UNAVAILABLE. NULL if we
+ * failed to obtain a JSON reply from the exchange or if we did not receive
+ * an error from the exchange.
+ */
+ const json_t *exchange_reply;
+
+ /**
+ * Set to the human-readable 'hint' that is optionally
+ * provided by the exchange together with errors. NULL
+ * if no hint was provided or if there was no error.
+ */
+ const char *hint;
+
+ /**
+ * The error hint from the exchange, if we generated an error in
+ * response to an exchange error. Usually set if @e http_status is
+ * #MHD_HTTP_FAILED_DEPENDENDCY or #MHD_HTTP_SERVICE_UNAVAILABLE. NULL if we
+ * failed to obtain a hint from the exchange or if we did not receive
+ * an error from the exchange.
+ */
+ const char *exchange_hint;
+
+ /**
+ * HTTP status code for the response. 0 if the
+ * HTTP request failed and we did not get any answer, or
+ * if the answer was invalid and we set @a ec to a
+ * client-side error code.
+ */
+ unsigned int http_status;
+
+ /**
+ * The HTTP status code from the exchange, if we generated an error in
+ * response to an exchange error. Usually set if @e http_status is
+ * #MHD_HTTP_FAILED_DEPENDENDCY or #MHD_HTTP_SERVICE_UNAVAILABLE. 0 if we
+ * failed to obtain a JSON reply from the exchange or if we did not receive
+ * an error from the exchange.
+ */
+ unsigned int exchange_http_status;
+
+ /**
+ * Taler error code. #TALER_EC_NONE if everything was
+ * OK. Usually set to the "code" field of an error
+ * response, but may be set to values created at the
+ * client side, for example when the response was
+ * not in JSON format or was otherwise ill-formed.
+ */
+ enum TALER_ErrorCode ec;
+
+ /**
+ * The error code from the reply from the exchange, if we generated an error in
+ * response to an exchange error. Usually set if @e http_status is
+ * #MHD_HTTP_FAILED_DEPENDENDCY or #MHD_HTTP_SERVICE_UNAVAILABLE. NULL if we
+ * failed to obtain a error code from the exchange or if we did not receive
+ * an error from the exchange.
+ */
+ enum TALER_ErrorCode exchange_code;
+
+};
+
+
+/**
+ * Take a @a response from the merchant API that (presumably) contains
+ * error details and setup the corresponding @a hr structure. Internally
+ * used to convert merchant's responses in to @a hr.
+ *
+ * @param response, if NULL we will report #TALER_EC_INVALIDD_RESPONSE in `ec`
+ * @param http_status http status to use
+ * @param[out] hr response object to initialize, fields will
+ * only be valid as long as @a response is valid as well
+ */
+void
+TALER_MERCHANT_parse_error_details_ (const json_t *response,
+ unsigned int http_status,
+ struct TALER_MERCHANT_HttpResponse *hr);
+
+
/* ********************* /refund ************************** */
/**
@@ -41,15 +133,13 @@ struct TALER_MERCHANT_RefundLookupOperation;
* Callback to process a GET /refund request
*
* @param cls closure
- * @param http_status HTTP status code for this request
- * @param ec taler-specific error code
- * @param obj the response body
+ * @param hr HTTP response details
*/
typedef void
-(*TALER_MERCHANT_RefundLookupCallback) (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const json_t *obj);
+(*TALER_MERCHANT_RefundLookupCallback) (
+ void *cls,
+ const struct TALER_MERCHANT_HttpResponse *hr);
+
/**
* Does a GET /refund.
@@ -74,8 +164,8 @@ TALER_MERCHANT_refund_lookup (struct GNUNET_CURL_Context *ctx,
* @param rlo the refund increasing operation to cancel
*/
void
-TALER_MERCHANT_refund_lookup_cancel (struct
- TALER_MERCHANT_RefundLookupOperation *rlo);
+TALER_MERCHANT_refund_lookup_cancel (
+ struct TALER_MERCHANT_RefundLookupOperation *rlo);
/**
@@ -90,13 +180,11 @@ struct TALER_MERCHANT_RefundIncreaseOperation;
* @param cls closure
* @param http_status HTTP status code for this request
* @param ec taler-specific error code
- * @param obj the response body
*/
typedef void
-(*TALER_MERCHANT_RefundIncreaseCallback) (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const json_t *obj);
+(*TALER_MERCHANT_RefundIncreaseCallback) (
+ void *cls,
+ const struct TALER_MERCHANT_HttpResponse *hr);
/**
@@ -125,9 +213,8 @@ TALER_MERCHANT_refund_increase (struct GNUNET_CURL_Context *ctx,
* @param rio the refund increasing operation to cancel
*/
void
-TALER_MERCHANT_refund_increase_cancel (struct
- TALER_MERCHANT_RefundIncreaseOperation *
- rio);
+TALER_MERCHANT_refund_increase_cancel (
+ struct TALER_MERCHANT_RefundIncreaseOperation *rio);
/* ********************* /proposal *********************** */
@@ -143,18 +230,14 @@ struct TALER_MERCHANT_ProposalOperation;
* /contract request to a merchant.
*
* @param cls closure
- * @param http_status HTTP response code, 200 indicates success;
- * 0 if the backend's reply is bogus (fails to follow the protocol)
- * @param ec taler-specific error code
- * @param obj raw JSON reply, or error details if the request failed
+ * @param hr HTTP response details
* @param order_id order id of the newly created order
*/
typedef void
-(*TALER_MERCHANT_ProposalCallback) (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const json_t *obj,
- const char *order_id);
+(*TALER_MERCHANT_ProposalCallback) (
+ void *cls,
+ const struct TALER_MERCHANT_HttpResponse *hr,
+ const char *order_id);
/**
@@ -196,19 +279,18 @@ struct TALER_MERCHANT_ProposalLookupOperation;
* Callback called to work a GET /proposal response.
*
* @param cls closure
- * @param http_status HTTP status code of the request
- * @param body JSON containing the response's payload.
- * In case of errors, it contains the appropriate error encoding.
+ * @param hr HTTP response details
+ * @param contract_terms the details of the contract
+ * @param sig merchant's signature over @a contract_terms
+ * @param contract_hash hash over @a contract_terms
*/
typedef void
-(*TALER_MERCHANT_ProposalLookupOperationCallback) (void *cls,
- unsigned int http_status,
- const json_t *body,
- const json_t *contract_terms,
- const struct
- TALER_MerchantSignatureP *sig,
- const struct
- GNUNET_HashCode *hash);
+(*TALER_MERCHANT_ProposalLookupOperationCallback) (
+ void *cls,
+ const struct TALER_MERCHANT_HttpResponse *hr,
+ const json_t *contract_terms,
+ const struct TALER_MerchantSignatureP *sig,
+ const struct GNUNET_HashCode *contract_hash);
/**
@@ -225,14 +307,13 @@ typedef void
* @return handle for this operation, NULL upon errors
*/
struct TALER_MERCHANT_ProposalLookupOperation *
-TALER_MERCHANT_proposal_lookup (struct GNUNET_CURL_Context *ctx,
- const char *backend_url,
- const char *order_id,
- const struct
- GNUNET_CRYPTO_EddsaPublicKey *nonce,
- TALER_MERCHANT_ProposalLookupOperationCallback
- plo_cb,
- void *plo_cb_cls);
+TALER_MERCHANT_proposal_lookup (
+ struct GNUNET_CURL_Context *ctx,
+ const char *backend_url,
+ const char *order_id,
+ const struct GNUNET_CRYPTO_EddsaPublicKey *nonce,
+ TALER_MERCHANT_ProposalLookupOperationCallback plo_cb,
+ void *plo_cb_cls);
/**
@@ -241,9 +322,8 @@ TALER_MERCHANT_proposal_lookup (struct GNUNET_CURL_Context *ctx,
* @param plo handle to the request to be canceled
*/
void
-TALER_MERCHANT_proposal_lookup_cancel (struct
- TALER_MERCHANT_ProposalLookupOperation *
- plo);
+TALER_MERCHANT_proposal_lookup_cancel (
+ struct TALER_MERCHANT_ProposalLookupOperation *plo);
/* ********************* /pay *********************** */
@@ -266,18 +346,11 @@ struct TALER_MERCHANT_Pay;
* /pay request to a merchant.
*
* @param cls closure
- * @param http_status HTTP response code, 200 or 300-level response codes
- * can indicate success, depending on whether the interaction
- * was with a merchant frontend or backend;
- * 0 if the merchant's reply is bogus (fails to follow the protocol)
- * @param ec taler-specific error code
- * @param obj the received JSON reply, with error details if the request failed
+ * @param hr HTTP response details
*/
typedef void
(*TALER_MERCHANT_PayCallback) (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const json_t *obj);
+ const struct TALER_MERCHANT_HttpResponse *hr);
/**
@@ -397,28 +470,20 @@ struct TALER_MERCHANT_RefundEntry
* /pay request to a merchant.
*
* @param cls closure
- * @param http_status HTTP response code, 200 or 300-level response codes
- * can indicate success, depending on whether the interaction
- * was with a merchant frontend or backend;
- * 0 if the merchant's reply is bogus (fails to follow the protocol)
- * @param ec taler-specific error code
+ * @param hr HTTP response details
* @param merchant_pub public key of the merchant
* @param h_contract hash of the contract
* @param num_refunds size of the @a res array, 0 on errors
* @param res merchant signatures refunding coins, NULL on errors
- * @param obj the received JSON reply, with error details if the request failed
*/
typedef void
-(*TALER_MERCHANT_PayRefundCallback) (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const struct
- TALER_MerchantPublicKeyP *merchant_pub,
- const struct GNUNET_HashCode *h_contract,
- unsigned int num_refunds,
- const struct
- TALER_MERCHANT_RefundEntry *res,
- const json_t *obj);
+(*TALER_MERCHANT_PayRefundCallback) (
+ void *cls,
+ const struct TALER_MERCHANT_HttpResponse *hr,
+ const struct TALER_MerchantPublicKeyP *merchant_pub,
+ const struct GNUNET_HashCode *h_contract,
+ unsigned int num_refunds,
+ const struct TALER_MERCHANT_RefundEntry *res);
/**
@@ -525,32 +590,24 @@ struct TALER_MERCHANT_PaidCoin
*
* @param ctx execution context
* @param merchant_url base URL of the merchant
- * @param h_contract hash of the contact of the merchant with the customer
- * @param amount total value of the contract to be paid to the merchant
- * @param max_fee maximum fee covered by the merchant (according to the contract)
- * @param transaction_id transaction id for the transaction between merchant and customer
- * @param merchant_sig the signature of the merchant over the original contract
- * @param refund_deadline date until which the merchant can issue a refund to the customer via the merchant (can be zero if refunds are not allowed)
- * @param pay_deadline maximum time limit to pay for this contract
- * @param timestamp timestamp when the contract was finalized, must match approximately the current time of the merchant
- * @param wire_transfer_deadline date by which the merchant would like the exchange to execute the wire transfer (can be zero if there is no specific date desired by the frontend). If non-zero, must be larger than @a refund_deadline.
- * @param num_coins number of coins used to pay
- * @param coins array of coins we use to pay
- * @param coin_sig the signature made with purpose #TALER_SIGNATURE_WALLET_COIN_DEPOSIT made by the customer with the coin’s private key.
+ * @param merchant_pub public key of the merchant
+ * @param order_id which order should be paid
+ * @param num_coins length of the @a coins array
+ * @param coins array of coins to pay with
* @param pay_cb the callback to call when a reply for this request is available
* @param pay_cb_cls closure for @a pay_cb
* @return a handle for this request
*/
struct TALER_MERCHANT_Pay *
-TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context *ctx,
- const char *merchant_url,
- const struct
- TALER_MerchantPublicKeyP *merchant_pub,
- const char *order_id,
- unsigned int num_coins,
- const struct TALER_MERCHANT_PaidCoin *coins,
- TALER_MERCHANT_PayCallback pay_cb,
- void *pay_cb_cls);
+TALER_MERCHANT_pay_frontend (
+ struct GNUNET_CURL_Context *ctx,
+ const char *merchant_url,
+ const struct TALER_MerchantPublicKeyP *merchant_pub,
+ const char *order_id,
+ unsigned int num_coins,
+ const struct TALER_MERCHANT_PaidCoin *coins,
+ TALER_MERCHANT_PayCallback pay_cb,
+ void *pay_cb_cls);
/**
@@ -561,7 +618,7 @@ TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context *ctx,
* obtain a definitive result, or /refresh the coins involved to
* ensure that the merchant can no longer complete the payment.
*
- * @param wh the wire information request handle
+ * @param ph the payment request handle
*/
void
TALER_MERCHANT_pay_cancel (struct TALER_MERCHANT_Pay *ph);
@@ -603,11 +660,8 @@ struct TALER_MERCHANT_TrackTransferDetails
* Callbacks of this type are used to work the result of submitting a /track/transfer request to a merchant
*
* @param cls closure
- * @param http_status HTTP status code we got, 0 on exchange protocol violation
- * @param ec taler-specific error code
+ * @param hr HTTP response details
* @param sign_key exchange key used to sign @a json, or NULL
- * @param json original json reply (may include signatures, those have then been
- * validated already)
* @param h_wire hash of the wire transfer address the transfer went to, or NULL on error
* @param total_amount total amount of the wire transfer, or NULL if the exchange could
* not provide any @a wtid (set only if @a http_status is #MHD_HTTP_OK)
@@ -615,19 +669,14 @@ struct TALER_MERCHANT_TrackTransferDetails
* @param details array with details about the combined transactions
*/
typedef void
-(*TALER_MERCHANT_TrackTransferCallback) (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const struct
- TALER_ExchangePublicKeyP *sign_key,
- const json_t *json,
- const struct GNUNET_HashCode *h_wire,
- const struct
- TALER_Amount *total_amount,
- unsigned int details_length,
- const struct
- TALER_MERCHANT_TrackTransferDetails *
- details);
+(*TALER_MERCHANT_TrackTransferCallback) (
+ void *cls,
+ const struct TALER_MERCHANT_HttpResponse *hr,
+ const struct TALER_ExchangePublicKeyP *sign_key,
+ const struct GNUNET_HashCode *h_wire,
+ const struct TALER_Amount *total_amount,
+ unsigned int details_length,
+ const struct TALER_MERCHANT_TrackTransferDetails *details);
/**
@@ -643,15 +692,15 @@ typedef void
* @return a handle for this request
*/
struct TALER_MERCHANT_TrackTransferHandle *
-TALER_MERCHANT_track_transfer (struct GNUNET_CURL_Context *ctx,
- const char *backend_url,
- const char *wire_method,
- const struct
- TALER_WireTransferIdentifierRawP *wtid,
- const char *exchange_url,
- TALER_MERCHANT_TrackTransferCallback
- track_transfer_cb,
- void *track_transfer_cb_cls);
+TALER_MERCHANT_track_transfer (
+ struct GNUNET_CURL_Context *ctx,
+ const char *backend_url,
+ const char *wire_method,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ const char *exchange_url,
+ TALER_MERCHANT_TrackTransferCallback
+ track_transfer_cb,
+ void *track_transfer_cb_cls);
/**
@@ -661,8 +710,8 @@ TALER_MERCHANT_track_transfer (struct GNUNET_CURL_Context *ctx,
* @param co the deposit's tracking operation
*/
void
-TALER_MERCHANT_track_transfer_cancel (struct
- TALER_MERCHANT_TrackTransferHandle *tdo);
+TALER_MERCHANT_track_transfer_cancel (
+ struct TALER_MERCHANT_TrackTransferHandle *tdo);
/* ********************* /track/transaction *********************** */
@@ -709,10 +758,9 @@ struct TALER_MERCHANT_CoinWireTransfer
* @param transfers details about each transfer and which coins are aggregated in it
*/
typedef void
-(*TALER_MERCHANT_TrackTransactionCallback) (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const json_t *json);
+(*TALER_MERCHANT_TrackTransactionCallback) (
+ void *cls,
+ const struct TALER_MERCHANT_HttpResponse *hr);
/**
@@ -720,30 +768,29 @@ typedef void
*
* @param ctx execution context
* @param backend_url base URL of the backend
- * @param transaction_id which transaction should we trace
+ * @param order_id which order should we trace
* @param track_transaction_cb the callback to call when a reply for this request is available
* @param track_transaction_cb_cls closure for @a track_transaction_cb
* @return a handle for this request
*/
struct TALER_MERCHANT_TrackTransactionHandle *
-TALER_MERCHANT_track_transaction (struct GNUNET_CURL_Context *ctx,
- const char *backend_url,
- const char *order_id,
- TALER_MERCHANT_TrackTransactionCallback
- track_transaction_cb,
- void *track_transaction_cb_cls);
+TALER_MERCHANT_track_transaction (
+ struct GNUNET_CURL_Context *ctx,
+ const char *backend_url,
+ const char *order_id,
+ TALER_MERCHANT_TrackTransactionCallback track_transaction_cb,
+ void *track_transaction_cb_cls);
/**
* Cancel a /track/transaction request. This function cannot be used
* on a request handle if a response is already served for it.
*
- * @param co the deposit's tracking operation
+ * @param tdo the tracking request to cancel
*/
void
-TALER_MERCHANT_track_transaction_cancel (struct
- TALER_MERCHANT_TrackTransactionHandle *
- tdo);
+TALER_MERCHANT_track_transaction_cancel (
+ struct TALER_MERCHANT_TrackTransactionHandle *tdo);
/* ********************* /history *********************** */
@@ -755,15 +802,13 @@ struct TALER_MERCHANT_HistoryOperation;
* documentation)
*
* @param cls closure
- * @param http_status HTTP status returned by the merchant backend
- * @param ec taler-specific error code
- * @param json actual body containing history
+ * @param hr HTTP response details
*/
typedef void
-(*TALER_MERCHANT_HistoryOperationCallback) (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const json_t *json);
+(*TALER_MERCHANT_HistoryOperationCallback) (
+ void *cls,
+ const struct TALER_MERCHANT_HttpResponse *hr);
+
/**
* Issue a /history request to the backend.
@@ -800,13 +845,13 @@ TALER_MERCHANT_history (struct GNUNET_CURL_Context *ctx,
* @return handle for this operation, NULL upon errors
*/
struct TALER_MERCHANT_HistoryOperation *
-TALER_MERCHANT_history_default_start (struct GNUNET_CURL_Context *ctx,
- const char *backend_url,
- long long delta,
- struct GNUNET_TIME_Absolute date,
- TALER_MERCHANT_HistoryOperationCallback
- history_cb,
- void *history_cb_cls);
+TALER_MERCHANT_history_default_start (
+ struct GNUNET_CURL_Context *ctx,
+ const char *backend_url,
+ long long delta,
+ struct GNUNET_TIME_Absolute date,
+ TALER_MERCHANT_HistoryOperationCallback history_cb,
+ void *history_cb_cls);
/**
@@ -831,17 +876,16 @@ struct TALER_MERCHANT_TipAuthorizeOperation;
* the operation.
*
* @param cls closure
- * @param http_status HTTP status returned by the merchant backend
- * @param ec taler-specific error code
- * @param taler_tip_uri tip URI
+ * @param hr HTTP response details
* @param tip_id which tip ID should be used to pickup the tip
+ * @param tip_uri URI for the tip
*/
typedef void
-(*TALER_MERCHANT_TipAuthorizeCallback) (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const char *taler_tip_uri,
- struct GNUNET_HashCode *tip_id);
+(*TALER_MERCHANT_TipAuthorizeCallback) (
+ void *cls,
+ const struct TALER_MERCHANT_HttpResponse *hr,
+ struct GNUNET_HashCode *tip_id,
+ const char *tip_uri);
/**
@@ -875,8 +919,8 @@ TALER_MERCHANT_tip_authorize (struct GNUNET_CURL_Context *ctx,
* @param ta handle from the operation to cancel
*/
void
-TALER_MERCHANT_tip_authorize_cancel (struct
- TALER_MERCHANT_TipAuthorizeOperation *ta);
+TALER_MERCHANT_tip_authorize_cancel (
+ struct TALER_MERCHANT_TipAuthorizeOperation *ta);
/* ********************** /tip-pickup ************************* */
@@ -892,23 +936,18 @@ struct TALER_MERCHANT_TipPickupOperation;
* the operation.
*
* @param cls closure
- * @param http_status HTTP status returned by the merchant backend, "200 OK" on success
- * @param ec taler-specific error code
+ * @param hr HTTP response details
* @param reserve_pub public key of the reserve that made the @a reserve_sigs, NULL on error
* @param num_reserve_sigs length of the @a reserve_sigs array, 0 on error
* @param reserve_sigs array of signatures authorizing withdrawals, NULL on error
- * @param json original json response
*/
typedef void
-(*TALER_MERCHANT_TipPickupCallback) (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const struct
- TALER_ReservePublicKeyP *reserve_pub,
- unsigned int num_reserve_sigs,
- const struct
- TALER_ReserveSignatureP *reserve_sigs,
- const json_t *json);
+(*TALER_MERCHANT_TipPickupCallback) (
+ void *cls,
+ const struct TALER_MERCHANT_HttpResponse *hr,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ unsigned int num_reserve_sigs,
+ const struct TALER_ReserveSignatureP *reserve_sigs);
/**
@@ -956,8 +995,7 @@ struct TALER_MERCHANT_CheckPaymentOperation;
* Callback to process a GET /check-payment request
*
* @param cls closure
- * @param http_status HTTP status code for this request
- * @param obj raw response body
+ * @param hr HTTP response details
* @param paid #GNUNET_YES if the payment is settled, #GNUNET_NO if not
* settled, $GNUNET_SYSERR on error
* (note that refunded payments are returned as paid!)
@@ -969,13 +1007,13 @@ struct TALER_MERCHANT_CheckPaymentOperation;
* the payment
*/
typedef void
-(*TALER_MERCHANT_CheckPaymentCallback) (void *cls,
- unsigned int http_status,
- const json_t *obj,
- int paid,
- int refunded,
- struct TALER_Amount *refund_amount,
- const char *taler_pay_uri);
+(*TALER_MERCHANT_CheckPaymentCallback) (
+ void *cls,
+ const struct TALER_MERCHANT_HttpResponse *hr,
+ int paid,
+ int refunded,
+ struct TALER_Amount *refund_amount,
+ const char *taler_pay_uri);
/**
@@ -1010,8 +1048,8 @@ TALER_MERCHANT_check_payment (struct GNUNET_CURL_Context *ctx,
* @param cpo handle to the request to be canceled
*/
void
-TALER_MERCHANT_check_payment_cancel (struct
- TALER_MERCHANT_CheckPaymentOperation *cpo);
+TALER_MERCHANT_check_payment_cancel (
+ struct TALER_MERCHANT_CheckPaymentOperation *cpo);
/* ********************** /tip-query ************************* */
@@ -1026,9 +1064,7 @@ struct TALER_MERCHANT_TipQueryOperation;
* Callback to process a GET /tip-query request
*
* @param cls closure
- * @param http_status HTTP status code for this request
- * @param ec Taler-specific error code
- * @param raw raw response body
+ * @param hr HTTP response details
* @param reserve_expiration when the tip reserve will expire
* @param reserve_pub tip reserve public key
* @param amount_authorized total amount authorized on tip reserve
@@ -1036,16 +1072,14 @@ struct TALER_MERCHANT_TipQueryOperation;
* @param amount_picked_up total amount picked up from tip reserve
*/
typedef void
-(*TALER_MERCHANT_TipQueryCallback) (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const json_t *raw,
- struct GNUNET_TIME_Absolute
- reserve_expiration,
- struct TALER_ReservePublicKeyP *reserve_pub,
- struct TALER_Amount *amount_authorized,
- struct TALER_Amount *amount_available,
- struct TALER_Amount *amount_picked_up);
+(*TALER_MERCHANT_TipQueryCallback) (
+ void *cls,
+ const struct TALER_MERCHANT_HttpResponse *hr,
+ struct GNUNET_TIME_Absolute reserve_expiration,
+ struct TALER_ReservePublicKeyP *reserve_pub,
+ struct TALER_Amount *amount_authorized,
+ struct TALER_Amount *amount_available,
+ struct TALER_Amount *amount_picked_up);
/**
@@ -1094,8 +1128,7 @@ struct TALER_MERCHANT_PollPaymentOperation;
* Callback to process a GET /poll-payment request
*
* @param cls closure
- * @param http_status HTTP status code for this request
- * @param obj raw response body
+ * @param hr HTTP response details
* @param paid #GNUNET_YES if the payment is settled, #GNUNET_NO if not
* settled, $GNUNET_SYSERR on error
* (note that refunded payments are returned as paid!)
@@ -1107,13 +1140,13 @@ struct TALER_MERCHANT_PollPaymentOperation;
* the payment
*/
typedef void
-(*TALER_MERCHANT_PollPaymentCallback) (void *cls,
- unsigned int http_status,
- const json_t *obj,
- int paid,
- int refunded,
- struct TALER_Amount *refund_amount,
- const char *taler_pay_uri);
+(*TALER_MERCHANT_PollPaymentCallback) (
+ void *cls,
+ const struct TALER_MERCHANT_HttpResponse *hr,
+ int paid,
+ int refunded,
+ struct TALER_Amount *refund_amount,
+ const char *taler_pay_uri);
/**
@@ -1134,15 +1167,15 @@ typedef void
* @return handle for this operation, NULL upon errors
*/
struct TALER_MERCHANT_PollPaymentOperation *
-TALER_MERCHANT_poll_payment (struct GNUNET_CURL_Context *ctx,
- const char *backend_url,
- const char *order_id,
- const struct GNUNET_HashCode *h_contract,
- const char *session_id,
- struct GNUNET_TIME_Relative timeout,
- TALER_MERCHANT_PollPaymentCallback
- poll_payment_cb,
- void *poll_payment_cls);
+TALER_MERCHANT_poll_payment (
+ struct GNUNET_CURL_Context *ctx,
+ const char *backend_url,
+ const char *order_id,
+ const struct GNUNET_HashCode *h_contract,
+ const char *session_id,
+ struct GNUNET_TIME_Relative timeout,
+ TALER_MERCHANT_PollPaymentCallback poll_payment_cb,
+ void *poll_payment_cls);
/**
@@ -1151,8 +1184,8 @@ TALER_MERCHANT_poll_payment (struct GNUNET_CURL_Context *ctx,
* @param cpo handle to the request to be canceled
*/
void
-TALER_MERCHANT_poll_payment_cancel (struct
- TALER_MERCHANT_PollPaymentOperation *cpo);
+TALER_MERCHANT_poll_payment_cancel (
+ struct TALER_MERCHANT_PollPaymentOperation *cpo);
#endif /* _TALER_MERCHANT_SERVICE_H */
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index b225d2ba..308d649a 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -20,8 +20,10 @@ libtalermerchanttesting_la_LDFLAGS = \
libtalermerchant_la_SOURCES = \
merchant_api_check_payment.c \
+ merchant_api_common.c \
merchant_api_history.c \
merchant_api_proposal.c \
+ merchant_api_proposal_lookup.c \
merchant_api_pay.c \
merchant_api_poll_payment.c \
merchant_api_refund.c \
@@ -46,6 +48,7 @@ libtalermerchanttesting_la_SOURCES = \
testing_api_cmd_check_payment.c \
testing_api_cmd_history.c \
testing_api_cmd_pay.c \
+ testing_api_cmd_pay_abort.c \
testing_api_cmd_pay_abort_refund.c \
testing_api_cmd_poll_payment.c \
testing_api_cmd_proposal.c \
diff --git a/src/lib/merchant_api_check_payment.c b/src/lib/merchant_api_check_payment.c
index 9802b496..5196d5b7 100644
--- a/src/lib/merchant_api_check_payment.c
+++ b/src/lib/merchant_api_check_payment.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2018 GNUnet e.V. and INRIA
+ Copyright (C) 2018, 2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
@@ -92,13 +92,18 @@ handle_check_payment_finished (void *cls,
if (MHD_HTTP_OK != response_code)
{
+ struct TALER_MERCHANT_HttpResponse hr;
+
+ TALER_MERCHANT_parse_error_details_ (response,
+ response_code,
+ &hr);
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Checking payment failed with HTTP status code %u\n",
- (unsigned int) response_code);
+ "Checking payment failed with HTTP status code %u/%d\n",
+ (unsigned int) response_code,
+ (int) hr.ec);
GNUNET_break_op (0);
cpo->cb (cpo->cb_cls,
- response_code,
- json,
+ &hr,
GNUNET_SYSERR,
GNUNET_SYSERR,
NULL,
@@ -113,12 +118,15 @@ handle_check_payment_finished (void *cls,
"taler_pay_uri"));
if (NULL == taler_pay_uri)
{
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .ec = TALER_EC_CHECK_PAYMENT_RESPONSE_MALFORMED,
+ .reply = json
+ };
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"no taler_pay_uri in unpaid check-payment response\n");
GNUNET_break_op (0);
cpo->cb (cpo->cb_cls,
- 0,
- json,
+ &hr,
GNUNET_SYSERR,
GNUNET_SYSERR,
NULL,
@@ -126,9 +134,12 @@ handle_check_payment_finished (void *cls,
}
else
{
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .reply = json,
+ .http_status = MHD_HTTP_OK
+ };
cpo->cb (cpo->cb_cls,
- response_code,
- json,
+ &hr,
GNUNET_NO,
GNUNET_NO,
NULL,
@@ -145,12 +156,15 @@ handle_check_payment_finished (void *cls,
spec,
NULL, NULL)) ) )
{
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .ec = TALER_EC_CHECK_PAYMENT_RESPONSE_MALFORMED,
+ .reply = json
+ };
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"check payment failed to parse JSON\n");
GNUNET_break_op (0);
cpo->cb (cpo->cb_cls,
- 0,
- json,
+ &hr,
GNUNET_SYSERR,
GNUNET_SYSERR,
NULL,
@@ -158,14 +172,19 @@ handle_check_payment_finished (void *cls,
TALER_MERCHANT_check_payment_cancel (cpo);
return;
}
+ {
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .reply = json,
+ .http_status = MHD_HTTP_OK
+ };
- cpo->cb (cpo->cb_cls,
- MHD_HTTP_OK,
- json,
- GNUNET_YES,
- (json_true () == refunded),
- (json_true () == refunded) ? &refund_amount : NULL,
- NULL);
+ cpo->cb (cpo->cb_cls,
+ &hr,
+ GNUNET_YES,
+ (json_true () == refunded),
+ (json_true () == refunded) ? &refund_amount : NULL,
+ NULL);
+ }
TALER_MERCHANT_check_payment_cancel (cpo);
}
@@ -187,14 +206,14 @@ handle_check_payment_finished (void *cls,
* @return handle for this operation, NULL upon errors
*/
struct TALER_MERCHANT_CheckPaymentOperation *
-TALER_MERCHANT_check_payment (struct GNUNET_CURL_Context *ctx,
- const char *backend_url,
- const char *order_id,
- const char *session_id,
- struct GNUNET_TIME_Relative timeout,
- TALER_MERCHANT_CheckPaymentCallback
- check_payment_cb,
- void *check_payment_cb_cls)
+TALER_MERCHANT_check_payment (
+ struct GNUNET_CURL_Context *ctx,
+ const char *backend_url,
+ const char *order_id,
+ const char *session_id,
+ struct GNUNET_TIME_Relative timeout,
+ TALER_MERCHANT_CheckPaymentCallback check_payment_cb,
+ void *check_payment_cb_cls)
{
struct TALER_MERCHANT_CheckPaymentOperation *cpo;
CURL *eh;
@@ -279,8 +298,8 @@ TALER_MERCHANT_check_payment (struct GNUNET_CURL_Context *ctx,
* @param cph handle to the request to be canceled
*/
void
-TALER_MERCHANT_check_payment_cancel (struct
- TALER_MERCHANT_CheckPaymentOperation *cph)
+TALER_MERCHANT_check_payment_cancel (
+ struct TALER_MERCHANT_CheckPaymentOperation *cph)
{
if (NULL != cph->job)
{
diff --git a/src/lib/merchant_api_common.c b/src/lib/merchant_api_common.c
new file mode 100644
index 00000000..33175958
--- /dev/null
+++ b/src/lib/merchant_api_common.c
@@ -0,0 +1,118 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2020 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser General Public License as published by the Free Software
+ Foundation; either version 2.1, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License along with
+ TALER; see the file COPYING.LGPL. If not, see
+ <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file lib/merchant_api_common.c
+ * @brief Implementation of common logic for libtalermerchant
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <curl/curl.h>
+#include <jansson.h>
+#include <microhttpd.h> /* just for HTTP status codes */
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_merchant_service.h"
+#include <taler/taler_json_lib.h>
+
+
+/**
+ * Take a @a response from the merchant API that (presumably) contains
+ * error details and setup the corresponding @a hr structure. Internally
+ * used to convert merchant's responses in to @a hr.
+ *
+ * @param response, if NULL we will report #TALER_EC_INVALID_RESPONSE in `ec
+ * @param http_status http status to use
+ * @param[out] hr response object to initialize, fields will
+ * only be valid as long as @a response is valid as well
+ */
+void
+TALER_MERCHANT_parse_error_details_ (const json_t *response,
+ unsigned int http_status,
+ struct TALER_MERCHANT_HttpResponse *hr)
+{
+ const json_t *jc;
+
+ memset (hr, 0, sizeof (*hr));
+ hr->reply = response;
+ hr->http_status = http_status;
+ if (NULL == response)
+ {
+ hr->ec = TALER_EC_INVALID_RESPONSE;
+ return;
+ }
+ hr->ec = TALER_JSON_get_error_code (response);
+ hr->hint = TALER_JSON_get_error_hint (response);
+
+ /* handle 'exchange-http-status' */
+ jc = json_object_get (response,
+ "exchange-http-status");
+ /* The caller already knows that the JSON represents an error,
+ so we are dealing with a missing error code here. */
+ if (NULL == jc)
+ return; /* no need to bother with exchange-code/hint if we had no status */
+ if (! json_is_integer (jc))
+ {
+ GNUNET_break_op (0);
+ return;
+ }
+ hr->exchange_http_status = (unsigned int) json_integer_value (jc);
+
+ /* handle 'exchange-reply' */
+ jc = json_object_get (response,
+ "exchange-reply");
+ if (! json_is_object (jc))
+ {
+ GNUNET_break_op (0);
+ }
+ else
+ {
+ hr->exchange_reply = jc;
+ }
+
+ /* handle 'exchange-code' */
+ jc = json_object_get (response,
+ "exchange-code");
+ /* The caller already knows that the JSON represents an error,
+ so we are dealing with a missing error code here. */
+ if (NULL == jc)
+ return; /* no need to bother with exchange-hint if we had no code */
+ if (! json_is_integer (jc))
+ {
+ GNUNET_break_op (0);
+ hr->exchange_code = TALER_EC_INVALID;
+ }
+ else
+ {
+ hr->exchange_code = (enum TALER_ErrorCode) json_integer_value (jc);
+ }
+
+ /* handle 'exchange-hint' */
+ jc = json_object_get (response,
+ "exchange-hint");
+ /* The caller already knows that the JSON represents an error,
+ so we are dealing with a missing error code here. */
+ if (NULL == jc)
+ return;
+ if (! json_is_string (jc))
+ {
+ GNUNET_break_op (0);
+ }
+ else
+ {
+ hr->exchange_hint = json_string_value (jc);
+ }
+}
diff --git a/src/lib/merchant_api_history.c b/src/lib/merchant_api_history.c
index c00cfa83..2bf49ef8 100644
--- a/src/lib/merchant_api_history.c
+++ b/src/lib/merchant_api_history.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014, 2015, 2016 GNUnet e.V. and INRIA
+ Copyright (C) 2014, 2015, 2016, 2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
@@ -18,7 +18,7 @@
*/
/**
- * @file lib/merchant_api_contract.c
+ * @file lib/merchant_api_history.c
* @brief Implementation of the /history request of the merchant's
* HTTP API
* @author Marcello Stanisci
@@ -99,6 +99,10 @@ history_raw_cb (void *cls,
{
struct TALER_MERCHANT_HistoryOperation *ho = cls;
const json_t *json = response;
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .http_status = (unsigned int) response_code,
+ .reply = json
+ };
ho->job = NULL;
switch (response_code)
@@ -110,41 +114,36 @@ history_raw_cb (void *cls,
* The response was malformed or didn't have the
* application/json header.
*/
- ho->cb (ho->cb_cls,
- response_code,
- TALER_EC_INVALID_RESPONSE,
- json);
- TALER_MERCHANT_history_cancel (ho);
- return;
+ hr.ec = TALER_EC_INVALID_RESPONSE;
+ break;
case MHD_HTTP_OK:
- ho->cb (ho->cb_cls,
- MHD_HTTP_OK,
- TALER_EC_NONE,
- json);
- TALER_MERCHANT_history_cancel (ho);
- return;
+ /* all good already */
+ break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"/history URL not found\n");
break;
case MHD_HTTP_BAD_REQUEST:
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Wrong/missing URL parameter\n");
break;
default:
/* unexpected response code */
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u\n",
- (unsigned int) response_code);
- GNUNET_break (0);
- response_code = 0;
+ "Unexpected response code %u/%d\n",
+ (unsigned int) response_code,
+ (int) hr.ec);
+ GNUNET_break_op (0);
break;
}
-
ho->cb (ho->cb_cls,
- response_code,
- TALER_JSON_get_error_code (json),
- json);
+ &hr);
TALER_MERCHANT_history_cancel (ho);
}
@@ -245,8 +244,8 @@ TALER_MERCHANT_history2 (struct GNUNET_CURL_Context *ctx,
* @return handle for this operation, NULL upon errors
*/
struct TALER_MERCHANT_HistoryOperation *
-TALER_MERCHANT_history_default_start
- (struct GNUNET_CURL_Context *ctx,
+TALER_MERCHANT_history_default_start (
+ struct GNUNET_CURL_Context *ctx,
const char *backend_url,
long long delta,
struct GNUNET_TIME_Absolute date,
@@ -284,14 +283,13 @@ TALER_MERCHANT_history_default_start
* @return handle for this operation, NULL upon errors
*/
struct TALER_MERCHANT_HistoryOperation *
-TALER_MERCHANT_history
- (struct GNUNET_CURL_Context *ctx,
- const char *backend_url,
- unsigned long long start,
- long long delta,
- struct GNUNET_TIME_Absolute date,
- TALER_MERCHANT_HistoryOperationCallback history_cb,
- void *history_cb_cls)
+TALER_MERCHANT_history (struct GNUNET_CURL_Context *ctx,
+ const char *backend_url,
+ unsigned long long start,
+ long long delta,
+ struct GNUNET_TIME_Absolute date,
+ TALER_MERCHANT_HistoryOperationCallback history_cb,
+ void *history_cb_cls)
{
return TALER_MERCHANT_history2 (ctx,
backend_url,
@@ -304,4 +302,4 @@ TALER_MERCHANT_history
}
-/* end of merchant_api_contract.c */
+/* end of merchant_api_history.c */
diff --git a/src/lib/merchant_api_pay.c b/src/lib/merchant_api_pay.c
index 1f12b76b..0db4631e 100644
--- a/src/lib/merchant_api_pay.c
+++ b/src/lib/merchant_api_pay.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014, 2015, 2016, 2017 GNUnet e.V. and INRIA
+ Copyright (C) 2014, 2015, 2016, 2017, 2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
@@ -198,11 +198,10 @@ check_abort_refund (struct TALER_MERCHANT_Pay *ph,
TALER_amount_hton (&rr.refund_fee,
&ph->coins[found].refund_fee);
if (GNUNET_OK !=
- GNUNET_CRYPTO_eddsa_verify
- (TALER_SIGNATURE_MERCHANT_REFUND,
- &rr.purpose,
- &sig->eddsa_sig,
- &merchant_pub.eddsa_pub))
+ GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND,
+ &rr.purpose,
+ &sig->eddsa_sig,
+ &merchant_pub.eddsa_pub))
{
GNUNET_break_op (0);
GNUNET_JSON_parse_free (spec);
@@ -210,14 +209,19 @@ check_abort_refund (struct TALER_MERCHANT_Pay *ph,
}
}
}
- ph->abort_cb (ph->abort_cb_cls,
- MHD_HTTP_OK,
- TALER_EC_NONE,
- &merchant_pub,
- &ph->h_contract_terms,
- num_refunds,
- res,
- json);
+ {
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .reply = json,
+ .http_status = MHD_HTTP_OK
+ };
+
+ ph->abort_cb (ph->abort_cb_cls,
+ &hr,
+ &merchant_pub,
+ &ph->h_contract_terms,
+ num_refunds,
+ res);
+ }
ph->abort_cb = NULL;
}
GNUNET_JSON_parse_free (spec);
@@ -302,7 +306,6 @@ check_conflict (struct TALER_MERCHANT_Pay *ph,
GNUNET_JSON_spec_json ("history", &history),
GNUNET_JSON_spec_end ()
};
- int ret;
if (GNUNET_OK !=
GNUNET_JSON_parse (json,
@@ -329,6 +332,8 @@ check_conflict (struct TALER_MERCHANT_Pay *ph,
&coin_pub,
sizeof (struct TALER_CoinSpendPublicKeyP)))
{
+ int ret;
+
ret = check_coin_history (&ph->coins[i],
history);
GNUNET_JSON_parse_free (hspec);
@@ -357,7 +362,10 @@ handle_pay_finished (void *cls,
{
struct TALER_MERCHANT_Pay *ph = cls;
const json_t *json = response;
- enum TALER_ErrorCode ec;
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .http_status = (unsigned int) response_code,
+ .reply = json
+ };
ph->job = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -369,50 +377,57 @@ handle_pay_finished (void *cls,
switch (response_code)
{
case 0:
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_EC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
- ec = TALER_EC_NONE;
break;
/* Tolerating Not Acceptable because sometimes
* - especially in tests - we might want to POST
* coins one at a time. */
case MHD_HTTP_NOT_ACCEPTABLE:
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_BAD_REQUEST:
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
/* This should never happen, either us
* or the merchant is buggy (or API version conflict);
* just pass JSON reply to the application */
break;
case MHD_HTTP_FORBIDDEN:
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
/* Nothing really to verify, merchant says we tried to abort the payment
* after it was successful. We should pass the JSON reply to the
* application */
break;
case MHD_HTTP_NOT_FOUND:
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
/* Nothing really to verify, this should never
- happen, we should pass the JSON reply to the
+ happen, we should pass the JSON reply to the
application */
break;
case MHD_HTTP_PRECONDITION_FAILED:
- ec = TALER_JSON_get_error_code (json);
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &hr);
/* Nothing really to verify, the merchant is blaming us for failing to
satisfy some constraint (likely it does not like our exchange because
of some disagreement on the PKI). We should pass the JSON reply to the
application */
break;
case MHD_HTTP_REQUEST_TIMEOUT:
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
/* The merchant couldn't generate a timely response, likely because
it itself waited too long on the exchange.
Pass on to application. */
break;
case MHD_HTTP_CONFLICT:
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
if (GNUNET_OK != check_conflict (ph,
json))
{
@@ -421,40 +436,46 @@ handle_pay_finished (void *cls,
}
break;
case MHD_HTTP_GONE:
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
/* The merchant says we are too late, the offer has expired or some
denomination key of a coin involved has expired.
Might be a disagreement in timestamps? Still, pass on to application. */
break;
case MHD_HTTP_FAILED_DEPENDENCY:
- ec = TALER_JSON_get_error_code (json);
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &hr);
/* Nothing really to verify, the merchant is blaming the exchange.
We should pass the JSON reply to the application */
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
/* Server had an internal issue; we should retry,
but this API leaves this to the application */
break;
case MHD_HTTP_SERVICE_UNAVAILABLE:
- ec = TALER_JSON_get_error_code (json);
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &hr);
/* Exchange couldn't respond properly; the retry is
left to the application */
break;
default:
- ec = TALER_JSON_get_error_code (json);
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &hr);
/* unexpected response code */
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u\n",
- (unsigned int) response_code);
- GNUNET_break (0);
- response_code = 0;
+ "Unexpected response code %u/%d\n",
+ (unsigned int) response_code,
+ (int) hr.ec);
+ GNUNET_break_op (0);
break;
}
ph->pay_cb (ph->pay_cb_cls,
- response_code,
- ec,
- json);
+ &hr);
}
else
{
@@ -464,7 +485,7 @@ handle_pay_finished (void *cls,
switch (response_code)
{
case 0:
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_EC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
if (GNUNET_OK ==
@@ -474,54 +495,66 @@ handle_pay_finished (void *cls,
TALER_MERCHANT_pay_cancel (ph);
return;
}
- response_code = 0;
- ec = TALER_EC_NONE;
+ hr.http_status = 0;
+ hr.ec = TALER_EC_PAY_MERCHANT_INVALID_RESPONSE;
break;
case MHD_HTTP_BAD_REQUEST:
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
/* This should never happen, either us or the
merchant is buggy (or API version conflict); just
pass JSON reply to the application */
break;
case MHD_HTTP_CONFLICT:
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_FORBIDDEN:
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
/* Nothing really to verify, merchant says one of
the signatures is invalid; as we checked them,
this should never happen, we should pass the JSON
reply to the application */
break;
case MHD_HTTP_NOT_FOUND:
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
/* Nothing really to verify, this should never
happen, we should pass the JSON reply to the
application */
break;
+ case MHD_HTTP_FAILED_DEPENDENCY:
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &hr);
+ /* Nothing really to verify, the merchant is blaming the exchange.
+ We should pass the JSON reply to the application */
+ break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
/* Server had an internal issue; we should retry,
but this API leaves this to the application */
break;
default:
- ec = TALER_JSON_get_error_code (json);
/* unexpected response code */
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &hr);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u\n",
- (unsigned int) response_code);
- GNUNET_break (0);
- response_code = 0;
+ "Unexpected response code %u/%d\n",
+ (unsigned int) response_code,
+ (int) hr.ec);
+ GNUNET_break_op (0);
break;
}
ph->abort_cb (ph->abort_cb_cls,
- response_code,
- ec,
+ &hr,
NULL,
NULL,
0,
- NULL,
- json);
+ NULL);
}
TALER_MERCHANT_pay_cancel (ph);
}
@@ -545,8 +578,8 @@ handle_pay_finished (void *cls,
* @return a handle for this request
*/
static struct TALER_MERCHANT_Pay *
-request_pay_generic
- (struct GNUNET_CURL_Context *ctx,
+request_pay_generic (
+ struct GNUNET_CURL_Context *ctx,
const char *merchant_url,
const struct TALER_MerchantPublicKeyP *merchant_pub,
const char *order_id,
@@ -612,20 +645,22 @@ request_pay_generic
}
/* create JSON for this coin */
- j_coin = json_pack
- ("{s:o, s:o," /* contribution/coin_pub */
- " s:s, s:o," /* exchange_url / denom_pub */
- " s:o, s:o}", /* ub_sig / coin_sig */
- "contribution", TALER_JSON_from_amount
- (&pc->amount_with_fee),
- "coin_pub", GNUNET_JSON_from_data_auto
- (&pc->coin_pub),
- "exchange_url", pc->exchange_url,
- "denom_pub", GNUNET_JSON_from_rsa_public_key
- (pc->denom_pub.rsa_public_key),
- "ub_sig", GNUNET_JSON_from_rsa_signature
- (pc->denom_sig.rsa_signature),
- "coin_sig", GNUNET_JSON_from_data_auto (&pc->coin_sig));
+ j_coin = json_pack (
+ "{s:o, s:o," /* contribution/coin_pub */
+ " s:s, s:o," /* exchange_url / denom_pub */
+ " s:o, s:o}", /* ub_sig / coin_sig */
+ "contribution",
+ TALER_JSON_from_amount (&pc->amount_with_fee),
+ "coin_pub",
+ GNUNET_JSON_from_data_auto (&pc->coin_pub),
+ "exchange_url",
+ pc->exchange_url,
+ "denom_pub",
+ GNUNET_JSON_from_rsa_public_key (pc->denom_pub.rsa_public_key),
+ "ub_sig",
+ GNUNET_JSON_from_rsa_signature (pc->denom_sig.rsa_signature),
+ "coin_sig",
+ GNUNET_JSON_from_data_auto (&pc->coin_sig));
if (0 !=
json_array_append_new (j_coins,
j_coin))
@@ -642,11 +677,14 @@ request_pay_generic
" s:s," /* order_id */
" s:o," /* merchant_pub */
"}",
- "mode", mode,
- "coins", j_coins,
- "order_id", order_id,
- "merchant_pub", GNUNET_JSON_from_data_auto
- (merchant_pub));
+ "mode",
+ mode,
+ "coins",
+ j_coins, /* reference consumed! */
+ "order_id",
+ order_id,
+ "merchant_pub",
+ GNUNET_JSON_from_data_auto (merchant_pub));
if (NULL == pay_obj)
{
GNUNET_break (0);
@@ -676,7 +714,6 @@ request_pay_generic
num_coins * sizeof (struct TALER_MERCHANT_PaidCoin));
eh = curl_easy_init ();
-
if (GNUNET_OK != TALER_curl_easy_post (&ph->post_ctx,
eh,
pay_obj))
@@ -983,15 +1020,15 @@ TALER_MERCHANT_pay_abort (struct GNUNET_CURL_Context *ctx,
* @return a handle for this request
*/
struct TALER_MERCHANT_Pay *
-TALER_MERCHANT_pay_frontend (struct GNUNET_CURL_Context *ctx,
- const char *merchant_url,
- const struct
- TALER_MerchantPublicKeyP *merchant_pub,
- const char *order_id,
- unsigned int num_coins,
- const struct TALER_MERCHANT_PaidCoin *coins,
- TALER_MERCHANT_PayCallback pay_cb,
- void *pay_cb_cls)
+TALER_MERCHANT_pay_frontend (
+ struct GNUNET_CURL_Context *ctx,
+ const char *merchant_url,
+ const struct TALER_MerchantPublicKeyP *merchant_pub,
+ const char *order_id,
+ unsigned int num_coins,
+ const struct TALER_MERCHANT_PaidCoin *coins,
+ TALER_MERCHANT_PayCallback pay_cb,
+ void *pay_cb_cls)
{
return request_pay_generic (ctx,
merchant_url,
diff --git a/src/lib/merchant_api_poll_payment.c b/src/lib/merchant_api_poll_payment.c
index c00fc182..bef2aac8 100644
--- a/src/lib/merchant_api_poll_payment.c
+++ b/src/lib/merchant_api_poll_payment.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2018, 2019 GNUnet e.V. and INRIA
+ Copyright (C) 2018, 2019, 2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
@@ -81,7 +81,10 @@ handle_poll_payment_finished (void *cls,
struct TALER_Amount refund_amount = { 0 };
const json_t *json = response;
const json_t *refunded;
-
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .http_status = (unsigned int) response_code,
+ .reply = json
+ };
struct GNUNET_JSON_Specification spec[] = {
TALER_JSON_spec_amount ("refund_amount",
&refund_amount),
@@ -93,9 +96,10 @@ handle_poll_payment_finished (void *cls,
switch (response_code)
{
case MHD_HTTP_NOT_FOUND:
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
cpo->cb (cpo->cb_cls,
- response_code,
- json,
+ &hr,
GNUNET_NO,
GNUNET_NO,
NULL,
@@ -106,13 +110,15 @@ handle_poll_payment_finished (void *cls,
/* see below */
break;
default:
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Polling payment failed with HTTP status code %u\n",
- (unsigned int) response_code);
+ "Polling payment failed with HTTP status code %u/%d\n",
+ (unsigned int) response_code,
+ (int) hr.ec);
GNUNET_break_op (0);
cpo->cb (cpo->cb_cls,
- response_code,
- json,
+ &hr,
GNUNET_SYSERR,
GNUNET_SYSERR,
NULL,
@@ -131,9 +137,10 @@ handle_poll_payment_finished (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"no taler_pay_uri in unpaid poll-payment response\n");
GNUNET_break_op (0);
+ hr.http_status = 0;
+ hr.ec = TALER_EC_POLL_PAYMENT_REPLY_MALFORMED;
cpo->cb (cpo->cb_cls,
- 0,
- json,
+ &hr,
GNUNET_SYSERR,
GNUNET_SYSERR,
NULL,
@@ -142,8 +149,7 @@ handle_poll_payment_finished (void *cls,
else
{
cpo->cb (cpo->cb_cls,
- response_code,
- json,
+ &hr,
GNUNET_NO,
GNUNET_NO,
NULL,
@@ -164,9 +170,10 @@ handle_poll_payment_finished (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"poll payment failed to parse JSON\n");
GNUNET_break_op (0);
+ hr.http_status = 0;
+ hr.ec = TALER_EC_POLL_PAYMENT_REPLY_MALFORMED;
cpo->cb (cpo->cb_cls,
- 0,
- json,
+ &hr,
GNUNET_SYSERR,
GNUNET_SYSERR,
NULL,
@@ -176,8 +183,7 @@ handle_poll_payment_finished (void *cls,
}
cpo->cb (cpo->cb_cls,
- MHD_HTTP_OK,
- json,
+ &hr,
GNUNET_YES,
(json_true () == refunded),
(json_true () == refunded) ? &refund_amount : NULL,
@@ -204,15 +210,15 @@ handle_poll_payment_finished (void *cls,
* @return handle for this operation, NULL upon errors
*/
struct TALER_MERCHANT_PollPaymentOperation *
-TALER_MERCHANT_poll_payment (struct GNUNET_CURL_Context *ctx,
- const char *backend_url,
- const char *order_id,
- const struct GNUNET_HashCode *h_contract,
- const char *session_id,
- struct GNUNET_TIME_Relative timeout,
- TALER_MERCHANT_PollPaymentCallback
- poll_payment_cb,
- void *poll_payment_cb_cls)
+TALER_MERCHANT_poll_payment (
+ struct GNUNET_CURL_Context *ctx,
+ const char *backend_url,
+ const char *order_id,
+ const struct GNUNET_HashCode *h_contract,
+ const char *session_id,
+ struct GNUNET_TIME_Relative timeout,
+ TALER_MERCHANT_PollPaymentCallback poll_payment_cb,
+ void *poll_payment_cb_cls)
{
struct TALER_MERCHANT_PollPaymentOperation *cpo;
CURL *eh;
@@ -296,8 +302,8 @@ TALER_MERCHANT_poll_payment (struct GNUNET_CURL_Context *ctx,
* @param cph handle to the request to be canceled
*/
void
-TALER_MERCHANT_poll_payment_cancel (struct
- TALER_MERCHANT_PollPaymentOperation *cph)
+TALER_MERCHANT_poll_payment_cancel (
+ struct TALER_MERCHANT_PollPaymentOperation *cph)
{
if (NULL != cph->job)
{
diff --git a/src/lib/merchant_api_proposal.c b/src/lib/merchant_api_proposal.c
index d532231d..e5e155fe 100644
--- a/src/lib/merchant_api_proposal.c
+++ b/src/lib/merchant_api_proposal.c
@@ -16,10 +16,9 @@
License along with TALER; see the file COPYING.LGPL. If not,
see <http://www.gnu.org/licenses/>
*/
-
/**
* @file lib/merchant_api_proposal.c
- * @brief Implementation of the /proposal POST and GET
+ * @brief Implementation of the /proposal POST
* @author Christian Grothoff
* @author Marcello Stanisci
*/
@@ -72,48 +71,6 @@ struct TALER_MERCHANT_ProposalOperation
struct TALER_CURL_PostContext post_ctx;
};
-/**
- * Structure representing a GET /proposal operation.
- */
-struct TALER_MERCHANT_ProposalLookupOperation
-{
- /**
- * Full URL, includes "/proposal".
- */
- char *url;
-
- /**
- * Handle for the request.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * Function to call with the result.
- */
- TALER_MERCHANT_ProposalLookupOperationCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Reference to the execution context.
- */
- struct GNUNET_CURL_Context *ctx;
-
- /**
- * Should we send the lookup operation with a nonce?
- */
- int has_nonce;
-
- /**
- * Nonce, only initialized if has_nonce is GNUNET_YES.
- */
- struct GNUNET_CRYPTO_EddsaPublicKey nonce;
-
-};
-
/**
* Function called when we're done processing the
@@ -129,9 +86,12 @@ handle_proposal_finished (void *cls,
const void *response)
{
struct TALER_MERCHANT_ProposalOperation *po = cls;
- const char *order_id;
+ const char *order_id = NULL;
const json_t *json = response;
- enum TALER_ErrorCode ec;
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .http_status = (unsigned int) response_code,
+ .reply = json
+ };
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_string ("order_id",
&order_id),
@@ -142,73 +102,66 @@ handle_proposal_finished (void *cls,
switch (response_code)
{
case 0:
- po->cb (po->cb_cls,
- response_code,
- TALER_EC_INVALID_RESPONSE,
- json,
- order_id);
- TALER_MERCHANT_proposal_cancel (po);
- return;
+ hr.ec = TALER_EC_INVALID_RESPONSE;
+ break;
case MHD_HTTP_OK:
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (json,
+ spec,
+ NULL, NULL))
{
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- response_code = 0;
- ec = TALER_JSON_get_error_code (json);
- break;
- }
- else
- {
- ec = TALER_EC_NONE;
- }
+ GNUNET_break_op (0);
+ hr.http_status = 0;
+ hr.ec = TALER_EC_PROPOSAL_REPLY_MALFORMED;
}
break;
case MHD_HTTP_BAD_REQUEST:
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
/* This should never happen, either us or
the merchant is buggy (or API version conflict);
just pass JSON reply to the application */
break;
case MHD_HTTP_CONFLICT:
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_FORBIDDEN:
/* Nothing really to verify, merchant says one
of the signatures is invalid; as we checked them,
this should never happen, we should pass the JSON
reply to the application */
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry,
but this API leaves this to the application */
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
break;
default:
/* unexpected response code */
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u\n",
- (unsigned int) response_code);
- GNUNET_break (0);
- response_code = 0;
- ec = TALER_JSON_get_error_code (json);
+ "Unexpected response code %u/%d\n",
+ (unsigned int) response_code,
+ (int) hr.ec);
+ GNUNET_break_op (0);
break;
}
po->cb (po->cb_cls,
- response_code,
- ec,
- json,
+ &hr,
order_id);
- GNUNET_JSON_parse_free (spec);
+ if (MHD_HTTP_OK == response_code)
+ GNUNET_JSON_parse_free (spec);
TALER_MERCHANT_proposal_cancel (po);
}
@@ -269,187 +222,13 @@ TALER_MERCHANT_order_put (struct GNUNET_CURL_Context *ctx,
/**
- * Function called when we're done processing the GET /proposal request.
- *
- * @param cls the `struct TALER_MERCHANT_ProposalLookupOperation`
- * @param response_code HTTP response code, 0 on error
- * @param json response body, should be NULL
- */
-static void
-handle_proposal_lookup_finished (void *cls,
- long response_code,
- const void *response)
-{
- struct TALER_MERCHANT_ProposalLookupOperation *plo = cls;
- json_t *contract_terms;
- struct TALER_MerchantSignatureP sig;
- struct GNUNET_HashCode hash;
- const json_t *json = response;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_json ("contract_terms",
- &contract_terms),
- GNUNET_JSON_spec_fixed_auto ("sig",
- &sig),
- GNUNET_JSON_spec_end ()
- };
-
- plo->job = NULL;
- if (MHD_HTTP_OK != response_code)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Proposal lookup failed with HTTP status code %u\n",
- (unsigned int) response_code);
- GNUNET_break (0);
- plo->cb (plo->cb_cls,
- response_code,
- json,
- NULL,
- NULL,
- NULL);
- TALER_MERCHANT_proposal_lookup_cancel (plo);
- return;
- }
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json,
- spec,
- NULL, NULL))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "proposal lookup failed to parse JSON\n");
- GNUNET_break_op (0);
- plo->cb (plo->cb_cls,
- 0,
- json,
- NULL,
- NULL,
- NULL);
- TALER_MERCHANT_proposal_lookup_cancel (plo);
- return;
- }
-
- if (GNUNET_OK !=
- TALER_JSON_hash (contract_terms,
- &hash))
- {
- GNUNET_break (0);
- GNUNET_JSON_parse_free (spec);
- plo->cb (plo->cb_cls,
- 0,
- json,
- NULL,
- NULL,
- NULL);
- TALER_MERCHANT_proposal_lookup_cancel (plo);
- return;
- }
-
- plo->job = NULL;
- /**
- * As no data is supposed to be extracted from this
- * call, we just invoke the provided callback.
- */
- plo->cb (plo->cb_cls,
- response_code,
- json,
- contract_terms,
- &sig,
- &hash);
- GNUNET_JSON_parse_free (spec);
- TALER_MERCHANT_proposal_lookup_cancel (plo);
-}
-
-
-/**
- * Calls the GET /proposal API at the backend. That is,
- * retrieve a proposal data by providing its transaction id.
- *
- * @param ctx execution context
- * @param backend_url base URL of the merchant backend
- * @param order_id order id used to perform the lookup
- * @param nonce nonce used to perform the lookup
- * @param plo_cb callback which will work the response gotten from the backend
- * @param plo_cb_cls closure to pass to @a history_cb
- * @return handle for this operation, NULL upon errors
- */
-struct TALER_MERCHANT_ProposalLookupOperation *
-TALER_MERCHANT_proposal_lookup (struct GNUNET_CURL_Context *ctx,
- const char *backend_url,
- const char *order_id,
- const struct
- GNUNET_CRYPTO_EddsaPublicKey *nonce,
- TALER_MERCHANT_ProposalLookupOperationCallback
- plo_cb,
- void *plo_cb_cls)
-{
- struct TALER_MERCHANT_ProposalLookupOperation *plo;
- CURL *eh;
- char *nonce_str = NULL;
-
- plo = GNUNET_new (struct TALER_MERCHANT_ProposalLookupOperation);
- plo->ctx = ctx;
- plo->cb = plo_cb;
- plo->cb_cls = plo_cb_cls;
- if (NULL != nonce)
- {
- plo->has_nonce = GNUNET_YES;
- plo->nonce = *nonce;
- nonce_str = GNUNET_STRINGS_data_to_string_alloc (nonce, sizeof (struct
- GNUNET_CRYPTO_EddsaPublicKey));
- }
- plo->url = TALER_url_join (backend_url, "proposal",
- "order_id",
- order_id,
- "nonce",
- nonce_str,
- NULL);
- GNUNET_free_non_null (nonce_str);
- if (NULL == plo->url)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Could not construct request URL.\n");
- GNUNET_free (plo);
- return NULL;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "looking up proposal from %s\n",
- plo->url);
- eh = curl_easy_init ();
- if (CURLE_OK != curl_easy_setopt (eh,
- CURLOPT_URL,
- plo->url))
- {
- GNUNET_break (0);
- curl_easy_cleanup (eh);
- GNUNET_free (plo->url);
- GNUNET_free (plo);
- return NULL;
- }
-
- if (NULL == (plo->job = GNUNET_CURL_job_add (ctx,
- eh,
- GNUNET_YES,
- &handle_proposal_lookup_finished,
- plo)))
- {
- GNUNET_break (0);
- GNUNET_free (plo->url);
- GNUNET_free (plo);
- return NULL;
- }
- return plo;
-}
-
-
-/**
* Cancel a POST /proposal request. This function cannot be used
* on a request handle if a response is already served for it.
*
* @param po the proposal operation request handle
*/
void
-TALER_MERCHANT_proposal_cancel
- (struct TALER_MERCHANT_ProposalOperation *po)
+TALER_MERCHANT_proposal_cancel (struct TALER_MERCHANT_ProposalOperation *po)
{
if (NULL != po->job)
{
@@ -462,23 +241,4 @@ TALER_MERCHANT_proposal_cancel
}
-/**
- * Cancel a GET /proposal request.
- *
- * @param plo handle to the request to be canceled
- */
-void
-TALER_MERCHANT_proposal_lookup_cancel
- (struct TALER_MERCHANT_ProposalLookupOperation *plo)
-{
- if (NULL != plo->job)
- {
- GNUNET_CURL_job_cancel (plo->job);
- plo->job = NULL;
- }
- GNUNET_free (plo->url);
- GNUNET_free (plo);
-}
-
-
-/* end of merchant_api_contract.c */
+/* end of merchant_api_proposal.c */
diff --git a/src/lib/merchant_api_proposal_lookup.c b/src/lib/merchant_api_proposal_lookup.c
new file mode 100644
index 00000000..0f2b0f3e
--- /dev/null
+++ b/src/lib/merchant_api_proposal_lookup.c
@@ -0,0 +1,279 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014-2020 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1,
+ or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with TALER; see the file COPYING.LGPL. If not,
+ see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file lib/merchant_api_proposal_lookup.c
+ * @brief Implementation of the /proposal GET
+ * @author Christian Grothoff
+ * @author Marcello Stanisci
+ */
+#include "platform.h"
+#include <curl/curl.h>
+#include <jansson.h>
+#include <microhttpd.h> /* just for HTTP status codes */
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_curl_lib.h>
+#include "taler_merchant_service.h"
+#include <taler/taler_json_lib.h>
+#include <taler/taler_signatures.h>
+#include <taler/taler_curl_lib.h>
+
+
+/**
+ * Structure representing a GET /proposal operation.
+ */
+struct TALER_MERCHANT_ProposalLookupOperation
+{
+ /**
+ * Full URL, includes "/proposal".
+ */
+ char *url;
+
+ /**
+ * Handle for the request.
+ */
+ struct GNUNET_CURL_Job *job;
+
+ /**
+ * Function to call with the result.
+ */
+ TALER_MERCHANT_ProposalLookupOperationCallback cb;
+
+ /**
+ * Closure for @a cb.
+ */
+ void *cb_cls;
+
+ /**
+ * Reference to the execution context.
+ */
+ struct GNUNET_CURL_Context *ctx;
+
+ /**
+ * Should we send the lookup operation with a nonce?
+ */
+ int has_nonce;
+
+ /**
+ * Nonce, only initialized if has_nonce is GNUNET_YES.
+ */
+ struct GNUNET_CRYPTO_EddsaPublicKey nonce;
+
+};
+
+
+/**
+ * Function called when we're done processing the GET /proposal request.
+ *
+ * @param cls the `struct TALER_MERCHANT_ProposalLookupOperation`
+ * @param response_code HTTP response code, 0 on error
+ * @param json response body, should be NULL
+ */
+static void
+handle_proposal_lookup_finished (void *cls,
+ long response_code,
+ const void *response)
+{
+ struct TALER_MERCHANT_ProposalLookupOperation *plo = cls;
+ json_t *contract_terms;
+ struct TALER_MerchantSignatureP sig;
+ struct GNUNET_HashCode hash;
+ const json_t *json = response;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_json ("contract_terms",
+ &contract_terms),
+ GNUNET_JSON_spec_fixed_auto ("sig",
+ &sig),
+ GNUNET_JSON_spec_end ()
+ };
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .http_status = (unsigned int) response_code,
+ .reply = json
+ };
+
+ plo->job = NULL;
+ if (MHD_HTTP_OK != response_code)
+ {
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Proposal lookup failed with HTTP status code %u/%d\n",
+ (unsigned int) response_code,
+ (int) hr.ec);
+ plo->cb (plo->cb_cls,
+ &hr,
+ NULL,
+ NULL,
+ NULL);
+ TALER_MERCHANT_proposal_lookup_cancel (plo);
+ return;
+ }
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (json,
+ spec,
+ NULL, NULL))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "proposal lookup failed to parse JSON\n");
+ GNUNET_break_op (0);
+ hr.ec = TALER_EC_INVALID_RESPONSE;
+ hr.http_status = 0;
+ plo->cb (plo->cb_cls,
+ &hr,
+ NULL,
+ NULL,
+ NULL);
+ TALER_MERCHANT_proposal_lookup_cancel (plo);
+ return;
+ }
+
+ if (GNUNET_OK !=
+ TALER_JSON_hash (contract_terms,
+ &hash))
+ {
+ GNUNET_break (0);
+ hr.ec = TALER_EC_CLIENT_INTERNAL_FAILURE;
+ hr.http_status = 0;
+ GNUNET_JSON_parse_free (spec);
+ plo->cb (plo->cb_cls,
+ &hr,
+ NULL,
+ NULL,
+ NULL);
+ TALER_MERCHANT_proposal_lookup_cancel (plo);
+ return;
+ }
+
+ plo->job = NULL;
+ /**
+ * As no data is supposed to be extracted from this
+ * call, we just invoke the provided callback.
+ */
+ plo->cb (plo->cb_cls,
+ &hr,
+ contract_terms,
+ &sig,
+ &hash);
+ GNUNET_JSON_parse_free (spec);
+ TALER_MERCHANT_proposal_lookup_cancel (plo);
+}
+
+
+/**
+ * Calls the GET /proposal API at the backend. That is,
+ * retrieve a proposal data by providing its transaction id.
+ *
+ * @param ctx execution context
+ * @param backend_url base URL of the merchant backend
+ * @param order_id order id used to perform the lookup
+ * @param nonce nonce used to perform the lookup
+ * @param plo_cb callback which will work the response gotten from the backend
+ * @param plo_cb_cls closure to pass to @a history_cb
+ * @return handle for this operation, NULL upon errors
+ */
+struct TALER_MERCHANT_ProposalLookupOperation *
+TALER_MERCHANT_proposal_lookup (
+ struct GNUNET_CURL_Context *ctx,
+ const char *backend_url,
+ const char *order_id,
+ const struct GNUNET_CRYPTO_EddsaPublicKey *nonce,
+ TALER_MERCHANT_ProposalLookupOperationCallback plo_cb,
+ void *plo_cb_cls)
+{
+ struct TALER_MERCHANT_ProposalLookupOperation *plo;
+ CURL *eh;
+ char *nonce_str = NULL;
+
+ plo = GNUNET_new (struct TALER_MERCHANT_ProposalLookupOperation);
+ plo->ctx = ctx;
+ plo->cb = plo_cb;
+ plo->cb_cls = plo_cb_cls;
+ if (NULL != nonce)
+ {
+ plo->has_nonce = GNUNET_YES;
+ plo->nonce = *nonce;
+ nonce_str = GNUNET_STRINGS_data_to_string_alloc (
+ nonce,
+ sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
+ }
+ plo->url = TALER_url_join (backend_url,
+ "proposal",
+ "order_id",
+ order_id,
+ "nonce",
+ nonce_str,
+ NULL);
+ GNUNET_free_non_null (nonce_str);
+ if (NULL == plo->url)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Could not construct request URL.\n");
+ GNUNET_free (plo);
+ return NULL;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "looking up proposal from %s\n",
+ plo->url);
+ eh = curl_easy_init ();
+ if (CURLE_OK != curl_easy_setopt (eh,
+ CURLOPT_URL,
+ plo->url))
+ {
+ GNUNET_break (0);
+ curl_easy_cleanup (eh);
+ GNUNET_free (plo->url);
+ GNUNET_free (plo);
+ return NULL;
+ }
+
+ if (NULL == (plo->job = GNUNET_CURL_job_add (ctx,
+ eh,
+ GNUNET_YES,
+ &handle_proposal_lookup_finished,
+ plo)))
+ {
+ GNUNET_break (0);
+ GNUNET_free (plo->url);
+ GNUNET_free (plo);
+ return NULL;
+ }
+ return plo;
+}
+
+
+/**
+ * Cancel a GET /proposal request.
+ *
+ * @param plo handle to the request to be canceled
+ */
+void
+TALER_MERCHANT_proposal_lookup_cancel (
+ struct TALER_MERCHANT_ProposalLookupOperation *plo)
+{
+ if (NULL != plo->job)
+ {
+ GNUNET_CURL_job_cancel (plo->job);
+ plo->job = NULL;
+ }
+ GNUNET_free (plo->url);
+ GNUNET_free (plo);
+}
+
+
+/* end of merchant_api_proposal_lookup.c */
diff --git a/src/lib/merchant_api_refund.c b/src/lib/merchant_api_refund.c
index 9cf4d5f5..a1a5715a 100644
--- a/src/lib/merchant_api_refund.c
+++ b/src/lib/merchant_api_refund.c
@@ -65,11 +65,11 @@ struct TALER_MERCHANT_RefundLookupOperation
/**
* Cancel a /refund lookup operation
*
- * @param
+ * @param rlo operation to cancel
*/
void
-TALER_MERCHANT_refund_lookup_cancel (struct
- TALER_MERCHANT_RefundLookupOperation *rlo)
+TALER_MERCHANT_refund_lookup_cancel (
+ struct TALER_MERCHANT_RefundLookupOperation *rlo)
{
if (NULL != rlo->job)
{
@@ -95,6 +95,10 @@ handle_refund_lookup_finished (void *cls,
{
struct TALER_MERCHANT_RefundLookupOperation *rlo = cls;
const json_t *json = response;
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .http_status = (unsigned int) response_code,
+ .reply = json
+ };
rlo->job = NULL;
switch (response_code)
@@ -102,31 +106,23 @@ handle_refund_lookup_finished (void *cls,
case 0:
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Backend didn't even return from GET /refund\n");
- rlo->cb (rlo->cb_cls,
- 0,
- TALER_EC_INVALID_RESPONSE,
- NULL);
+ hr.ec = TALER_EC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
- rlo->cb (rlo->cb_cls,
- response_code,
- TALER_EC_NONE,
- json);
+ /* nothing to do, all good! */
break;
case MHD_HTTP_NOT_FOUND:
- rlo->cb (rlo->cb_cls,
- response_code,
- TALER_JSON_get_error_code (json),
- json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
break;
default:
GNUNET_break_op (0); /* unexpected status code */
- rlo->cb (rlo->cb_cls,
- response_code,
- TALER_JSON_get_error_code (json),
- json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
break;
}
+ rlo->cb (rlo->cb_cls,
+ &hr);
TALER_MERCHANT_refund_lookup_cancel (rlo);
}
diff --git a/src/lib/merchant_api_refund_increase.c b/src/lib/merchant_api_refund_increase.c
index 3adb9881..619d2b80 100644
--- a/src/lib/merchant_api_refund_increase.c
+++ b/src/lib/merchant_api_refund_increase.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014, 2015, 2016, 2017, 2019 Taler Systems SA
+ Copyright (C) 2014, 2015, 2016, 2017, 2019, 2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
@@ -15,7 +15,7 @@
<http://www.gnu.org/licenses/>
*/
/**
- * @file lib/merchant_api_refund.c
+ * @file lib/merchant_api_refund_increase.c
* @brief Implementation of the /refund POST and GET
* @author Christian Grothoff
* @author Marcello Stanisci
@@ -80,35 +80,37 @@ handle_refund_increase_finished (void *cls,
{
struct TALER_MERCHANT_RefundIncreaseOperation *rio = cls;
const json_t *json = response;
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .http_status = (unsigned int) response_code,
+ .reply = json
+ };
rio->job = NULL;
switch (response_code)
{
case 0:
+ hr.ec = TALER_EC_INVALID_RESPONSE;
rio->cb (rio->cb_cls,
- 0,
- TALER_EC_INVALID_RESPONSE,
- NULL);
+ &hr);
break;
case MHD_HTTP_OK:
rio->cb (rio->cb_cls,
- response_code,
- TALER_EC_NONE,
- json);
+ &hr);
break;
case MHD_HTTP_CONFLICT:
case MHD_HTTP_NOT_FOUND:
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
rio->cb (rio->cb_cls,
- response_code,
- TALER_JSON_get_error_code (json),
- json);
+ &hr);
break;
default:
GNUNET_break_op (0); /* unexpected status code */
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &hr);
rio->cb (rio->cb_cls,
- response_code,
- TALER_JSON_get_error_code (json),
- json);
+ &hr);
break;
}
TALER_MERCHANT_refund_increase_cancel (rio);
@@ -121,9 +123,8 @@ handle_refund_increase_finished (void *cls,
* @param rio the refund increasing operation to cancel
*/
void
-TALER_MERCHANT_refund_increase_cancel (struct
- TALER_MERCHANT_RefundIncreaseOperation *
- rio)
+TALER_MERCHANT_refund_increase_cancel (
+ struct TALER_MERCHANT_RefundIncreaseOperation *rio)
{
if (NULL != rio->job)
{
diff --git a/src/lib/merchant_api_tip_authorize.c b/src/lib/merchant_api_tip_authorize.c
index 632ee24d..37ad3904 100644
--- a/src/lib/merchant_api_tip_authorize.c
+++ b/src/lib/merchant_api_tip_authorize.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2017 Taler Systems SA
+ Copyright (C) 2014-2017, 2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
@@ -33,7 +33,7 @@
/**
- * @brief A handle for tracking transactions.
+ * @brief A handle for tip authorizations.
*/
struct TALER_MERCHANT_TipAuthorizeOperation
{
@@ -90,6 +90,10 @@ check_ok (struct TALER_MERCHANT_TipAuthorizeOperation *tao,
GNUNET_JSON_spec_fixed_auto ("tip_id", &tip_id),
GNUNET_JSON_spec_end ()
};
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .http_status = MHD_HTTP_OK,
+ .reply = json
+ };
if (GNUNET_OK !=
GNUNET_JSON_parse (json,
@@ -99,16 +103,18 @@ check_ok (struct TALER_MERCHANT_TipAuthorizeOperation *tao,
char *log;
GNUNET_break_op (0);
- log = json_dumps (json, 0);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "JSON %s\n", log);
+ log = json_dumps (json,
+ 0);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "JSON %s\n",
+ log);
free (log);
return GNUNET_SYSERR;
}
tao->cb (tao->cb_cls,
- MHD_HTTP_OK,
- TALER_EC_NONE,
- taler_tip_uri,
- &tip_id);
+ &hr,
+ &tip_id,
+ taler_tip_uri);
tao->cb = NULL; /* do not call twice */
GNUNET_JSON_parse_free (spec);
return GNUNET_OK;
@@ -130,7 +136,10 @@ handle_tip_authorize_finished (void *cls,
{
struct TALER_MERCHANT_TipAuthorizeOperation *tao = cls;
const json_t *json = response;
- enum TALER_ErrorCode ec;
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .http_status = (unsigned int) response_code,
+ .reply = json
+ };
tao->job = NULL;
switch (response_code)
@@ -144,42 +153,49 @@ handle_tip_authorize_finished (void *cls,
return;
}
GNUNET_break_op (0);
- response_code = 0;
- ec = TALER_EC_INVALID_RESPONSE;
+ hr.http_status = 0;
+ hr.ec = TALER_EC_INVALID_RESPONSE;
break;
case MHD_HTTP_NOT_FOUND:
/* Well-defined status code, pass on to application! */
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_PRECONDITION_FAILED:
/* Well-defined status code, pass on to application! */
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
- ec = TALER_JSON_get_error_code (json);
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_SERVICE_UNAVAILABLE:
/* Server had an unclear (internal or external) issue; we should retry,
but this API leaves this to the application */
- ec = TALER_JSON_get_error_code (json);
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &hr);
break;
default:
/* unexpected response code */
+ GNUNET_break_op (0);
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &hr);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u\n",
- (unsigned int) response_code);
- GNUNET_break (0);
- ec = TALER_JSON_get_error_code (json);
- response_code = 0;
+ "Unexpected response code %u/%d\n",
+ (unsigned int) response_code,
+ (int) hr.ec);
break;
}
if (NULL != tao->cb)
tao->cb (tao->cb_cls,
- response_code,
- ec,
- NULL, NULL);
+ &hr,
+ NULL,
+ NULL);
TALER_MERCHANT_tip_authorize_cancel (tao);
}
@@ -216,7 +232,9 @@ TALER_MERCHANT_tip_authorize (struct GNUNET_CURL_Context *ctx,
tao->ctx = ctx;
tao->cb = authorize_cb;
tao->cb_cls = authorize_cb_cls;
- tao->url = TALER_url_join (backend_url, "tip-authorize", NULL);
+ tao->url = TALER_url_join (backend_url,
+ "tip-authorize",
+ NULL);
if (NULL == tao->url)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -278,8 +296,8 @@ TALER_MERCHANT_tip_authorize (struct GNUNET_CURL_Context *ctx,
* @param tao handle to the tracking operation being cancelled
*/
void
-TALER_MERCHANT_tip_authorize_cancel (struct
- TALER_MERCHANT_TipAuthorizeOperation *tao)
+TALER_MERCHANT_tip_authorize_cancel (
+ struct TALER_MERCHANT_TipAuthorizeOperation *tao)
{
if (NULL != tao->job)
{
diff --git a/src/lib/merchant_api_tip_pickup.c b/src/lib/merchant_api_tip_pickup.c
index 668eb4bc..f402209f 100644
--- a/src/lib/merchant_api_tip_pickup.c
+++ b/src/lib/merchant_api_tip_pickup.c
@@ -90,12 +90,16 @@ check_ok (struct TALER_MERCHANT_TipPickupOperation *tpo,
{
struct TALER_ReservePublicKeyP reserve_pub;
json_t *ja;
+ unsigned int ja_len;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("reserve_pub", &reserve_pub),
GNUNET_JSON_spec_json ("reserve_sigs", &ja),
GNUNET_JSON_spec_end ()
};
- unsigned int ja_len;
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .http_status = MHD_HTTP_OK,
+ .reply = json
+ };
if (GNUNET_OK !=
GNUNET_JSON_parse (json,
@@ -135,12 +139,10 @@ check_ok (struct TALER_MERCHANT_TipPickupOperation *tpo,
}
}
tpo->cb (tpo->cb_cls,
- MHD_HTTP_OK,
- TALER_EC_NONE,
+ &hr,
&reserve_pub,
ja_len,
- reserve_sigs,
- json);
+ reserve_sigs);
tpo->cb = NULL; /* do not call twice */
}
GNUNET_JSON_parse_free (spec);
@@ -163,6 +165,10 @@ handle_tip_pickup_finished (void *cls,
{
struct TALER_MERCHANT_TipPickupOperation *tpo = cls;
const json_t *json = response;
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .http_status = (unsigned int) response_code,
+ .reply = json
+ };
tpo->job = NULL;
switch (response_code)
@@ -172,37 +178,45 @@ handle_tip_pickup_finished (void *cls,
json))
{
GNUNET_break_op (0);
- response_code = 0;
+ hr.http_status = 0;
+ hr.ec = TALER_EC_INVALID_RESPONSE;
}
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_CONFLICT:
/* legal, can happen if we pickup a tip twice... */
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_NOT_FOUND:
/* legal, can happen if tip ID is unknown */
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
break;
default:
/* unexpected response code */
+ GNUNET_break_op (0);
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &hr);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u\n",
- (unsigned int) response_code);
- GNUNET_break (0);
- response_code = 0;
+ "Unexpected response code %u/%d\n",
+ (unsigned int) response_code,
+ (int) hr.ec);
break;
}
if (NULL != tpo->cb)
{
tpo->cb (tpo->cb_cls,
- response_code,
- TALER_JSON_get_error_code (json),
+ &hr,
NULL,
0,
- NULL,
- json);
+ NULL);
tpo->cb = NULL;
}
TALER_MERCHANT_tip_pickup_cancel (tpo);
diff --git a/src/lib/merchant_api_tip_query.c b/src/lib/merchant_api_tip_query.c
index 65aece65..12633c86 100644
--- a/src/lib/merchant_api_tip_query.c
+++ b/src/lib/merchant_api_tip_query.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2018 Taler Systems SA
+ Copyright (C) 2014-2018, 2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
@@ -31,7 +31,7 @@
/**
- * @brief A handle for tracking /tip-pickup operations
+ * @brief A handle for tracking /tip-query operations
*/
struct TALER_MERCHANT_TipQueryOperation
{
@@ -73,54 +73,6 @@ struct TALER_MERCHANT_TipQueryOperation
/**
- * We got a 200 response back from the exchange (or the merchant).
- * Now we need to parse the response and if it is well-formed,
- * call the callback (and set it to NULL afterwards).
- *
- * @param tqo handle of the original operation
- * @param json cryptographic proof returned by the exchange/merchant
- * @return #GNUNET_OK if response is valid
- */
-static int
-check_ok (struct TALER_MERCHANT_TipQueryOperation *tqo,
- const json_t *json)
-{
- struct GNUNET_TIME_Absolute reserve_expiration;
- struct TALER_Amount amount_authorized;
- struct TALER_Amount amount_available;
- struct TALER_Amount amount_picked_up;
- struct TALER_ReservePublicKeyP reserve_pub;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("reserve_pub", &reserve_pub),
- GNUNET_JSON_spec_absolute_time ("reserve_expiration", &reserve_expiration),
- TALER_JSON_spec_amount ("amount_authorized", &amount_authorized),
- TALER_JSON_spec_amount ("amount_available", &amount_available),
- TALER_JSON_spec_amount ("amount_picked_up", &amount_picked_up),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- tqo->cb (tqo->cb_cls,
- MHD_HTTP_OK,
- TALER_EC_NONE,
- json,
- reserve_expiration,
- &reserve_pub,
- &amount_authorized,
- &amount_available,
- &amount_picked_up);
- return GNUNET_OK;
-}
-
-
-/**
* Function called when we're done processing the
* HTTP /track/transaction request.
*
@@ -135,6 +87,10 @@ handle_tip_query_finished (void *cls,
{
struct TALER_MERCHANT_TipQueryOperation *tqo = cls;
const json_t *json = response;
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .http_status = (unsigned int) response_code,
+ .reply = json
+ };
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Got /tip-query response with status code %u\n",
@@ -144,39 +100,72 @@ handle_tip_query_finished (void *cls,
switch (response_code)
{
case MHD_HTTP_OK:
- if (GNUNET_OK != check_ok (tqo,
- json))
{
- GNUNET_break_op (0);
- response_code = 0;
+ struct GNUNET_TIME_Absolute reserve_expiration;
+ struct TALER_Amount amount_authorized;
+ struct TALER_Amount amount_available;
+ struct TALER_Amount amount_picked_up;
+ struct TALER_ReservePublicKeyP reserve_pub;
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_fixed_auto ("reserve_pub", &reserve_pub),
+ GNUNET_JSON_spec_absolute_time ("reserve_expiration",
+ &reserve_expiration),
+ TALER_JSON_spec_amount ("amount_authorized", &amount_authorized),
+ TALER_JSON_spec_amount ("amount_available", &amount_available),
+ TALER_JSON_spec_amount ("amount_picked_up", &amount_picked_up),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (json,
+ spec,
+ NULL, NULL))
+ {
+ GNUNET_break_op (0);
+ hr.http_status = 0;
+ hr.ec = TALER_EC_INVALID_RESPONSE;
+ break;
+ }
+ tqo->cb (tqo->cb_cls,
+ &hr,
+ reserve_expiration,
+ &reserve_pub,
+ &amount_authorized,
+ &amount_available,
+ &amount_picked_up);
+ TALER_MERCHANT_tip_query_cancel (tqo);
+ return;
}
- break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_NOT_FOUND:
/* legal, can happen if instance or tip reserve is unknown */
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
break;
default:
/* unexpected response code */
+ GNUNET_break_op (0);
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &hr);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u\n",
- (unsigned int) response_code);
- GNUNET_break (0);
- response_code = 0;
+ "Unexpected response code %u/%d\n",
+ (unsigned int) response_code,
+ (int) hr.ec);
break;
}
- if (MHD_HTTP_OK != response_code)
- tqo->cb (tqo->cb_cls,
- response_code,
- TALER_JSON_get_error_code (json),
- json,
- GNUNET_TIME_UNIT_ZERO_ABS,
- NULL,
- NULL,
- NULL,
- NULL);
+ tqo->cb (tqo->cb_cls,
+ &hr,
+ GNUNET_TIME_UNIT_ZERO_ABS,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
TALER_MERCHANT_tip_query_cancel (tqo);
}
diff --git a/src/lib/merchant_api_track_transaction.c b/src/lib/merchant_api_track_transaction.c
index 6b1144d1..7a091d1e 100644
--- a/src/lib/merchant_api_track_transaction.c
+++ b/src/lib/merchant_api_track_transaction.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014, 2015, 2016 GNUnet e.V. and INRIA
+ Copyright (C) 2014, 2015, 2016, 2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
@@ -80,51 +80,64 @@ handle_track_transaction_finished (void *cls,
{
struct TALER_MERCHANT_TrackTransactionHandle *tdo = cls;
const json_t *json = response;
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .http_status = (unsigned int) response_code,
+ .reply = json
+ };
tdo->job = NULL;
switch (response_code)
{
case 0:
+ hr.ec = TALER_EC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
+ /* FIXME: should we not have a timestamp here as well? */
tdo->cb (tdo->cb_cls,
- MHD_HTTP_OK,
- TALER_EC_NONE,
- json);
+ &hr);
TALER_MERCHANT_track_transaction_cancel (tdo);
return;
case MHD_HTTP_ACCEPTED:
{
- /* Expect time stamp of when the transfer is supposed to happen */
+ /* FIXME: Expect time stamp of when the transfer is supposed to happen
+ => Parse it? */
}
break;
case MHD_HTTP_FAILED_DEPENDENCY:
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Exchange gave inconsistent response\n");
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &hr);
break;
case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Did not find any data\n");
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
break;
default:
/* unexpected response code */
+ GNUNET_break_op (0);
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &hr);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u\n",
- (unsigned int) response_code);
- GNUNET_break (0);
- response_code = 0;
+ "Unexpected response code %u/%d\n",
+ (unsigned int) response_code,
+ (int) hr.ec);
break;
}
tdo->cb (tdo->cb_cls,
- response_code,
- TALER_JSON_get_error_code (json),
- json);
+ &hr);
TALER_MERCHANT_track_transaction_cancel (tdo);
}
@@ -140,12 +153,12 @@ handle_track_transaction_finished (void *cls,
* @return a handle for this request
*/
struct TALER_MERCHANT_TrackTransactionHandle *
-TALER_MERCHANT_track_transaction (struct GNUNET_CURL_Context *ctx,
- const char *backend_url,
- const char *order_id,
- TALER_MERCHANT_TrackTransactionCallback
- track_transaction_cb,
- void *track_transaction_cb_cls)
+TALER_MERCHANT_track_transaction (
+ struct GNUNET_CURL_Context *ctx,
+ const char *backend_url,
+ const char *order_id,
+ TALER_MERCHANT_TrackTransactionCallback track_transaction_cb,
+ void *track_transaction_cb_cls)
{
struct TALER_MERCHANT_TrackTransactionHandle *tdo;
CURL *eh;
@@ -189,9 +202,8 @@ TALER_MERCHANT_track_transaction (struct GNUNET_CURL_Context *ctx,
* @param tdo handle to the tracking operation being cancelled
*/
void
-TALER_MERCHANT_track_transaction_cancel (struct
- TALER_MERCHANT_TrackTransactionHandle *
- tdo)
+TALER_MERCHANT_track_transaction_cancel (
+ struct TALER_MERCHANT_TrackTransactionHandle *tdo)
{
if (NULL != tdo->job)
{
diff --git a/src/lib/merchant_api_track_transfer.c b/src/lib/merchant_api_track_transfer.c
index 11ba6cf3..5743f2fe 100644
--- a/src/lib/merchant_api_track_transfer.c
+++ b/src/lib/merchant_api_track_transfer.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2017 GNUnet e.V. and INRIA
+ Copyright (C) 2014-2017, 2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Lesser General Public License as published by the Free Software
@@ -82,9 +82,9 @@ struct TALER_MERCHANT_TrackTransferHandle
* #GNUNET_SYSERR if the response was bogus
*/
static int
-check_transfers_get_response_ok (struct
- TALER_MERCHANT_TrackTransferHandle *wdh,
- const json_t *json)
+check_transfers_get_response_ok (
+ struct TALER_MERCHANT_TrackTransferHandle *wdh,
+ const json_t *json)
{
json_t *deposits;
struct GNUNET_HashCode h_wire;
@@ -100,6 +100,10 @@ check_transfers_get_response_ok (struct
GNUNET_JSON_spec_fixed_auto ("exchange_pub", &exchange_pub),
GNUNET_JSON_spec_end ()
};
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .http_status = MHD_HTTP_OK,
+ .reply = json
+ };
if (GNUNET_OK !=
GNUNET_JSON_parse (json,
@@ -135,10 +139,8 @@ check_transfers_get_response_ok (struct
}
}
wdh->cb (wdh->cb_cls,
- MHD_HTTP_OK,
- TALER_EC_NONE,
+ &hr,
&exchange_pub,
- json,
&h_wire,
&total_amount,
num_details,
@@ -164,11 +166,16 @@ handle_transfers_get_finished (void *cls,
{
struct TALER_MERCHANT_TrackTransferHandle *tdo = cls;
const json_t *json = response;
+ struct TALER_MERCHANT_HttpResponse hr = {
+ .http_status = (unsigned int) response_code,
+ .reply = json
+ };
tdo->job = NULL;
switch (response_code)
{
case 0:
+ hr.ec = TALER_EC_INVALID_RESPONSE;
break;
case MHD_HTTP_OK:
if (GNUNET_OK ==
@@ -179,33 +186,43 @@ handle_transfers_get_finished (void *cls,
return;
}
GNUNET_break_op (0);
- response_code = 0;
+ hr.http_status = 0;
+ hr.ec = TALER_EC_INVALID_RESPONSE; // TODO: use more specific code!
break;
case MHD_HTTP_FAILED_DEPENDENCY:
/* Not a reason to break execution. */
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &hr);
break;
case MHD_HTTP_NOT_FOUND:
/* Nothing really to verify, this should never
happen, we should pass the JSON reply to the application */
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
break;
case MHD_HTTP_INTERNAL_SERVER_ERROR:
/* Server had an internal issue; we should retry, but this API
leaves this to the application */
+ hr.ec = TALER_JSON_get_error_code (json);
+ hr.hint = TALER_JSON_get_error_hint (json);
break;
default:
/* unexpected response code */
+ GNUNET_break_op (0);
+ TALER_MERCHANT_parse_error_details_ (json,
+ response_code,
+ &hr);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u\n",
- (unsigned int) response_code);
- GNUNET_break (0);
+ "Unexpected response code %u/%d\n",
+ (unsigned int) response_code,
+ (int) hr.ec);
response_code = 0;
break;
}
tdo->cb (tdo->cb_cls,
- response_code,
- TALER_JSON_get_error_code (json),
+ &hr,
NULL,
- json,
NULL,
NULL,
0,
@@ -227,23 +244,22 @@ handle_transfers_get_finished (void *cls,
* @return a handle for this request
*/
struct TALER_MERCHANT_TrackTransferHandle *
-TALER_MERCHANT_track_transfer (struct GNUNET_CURL_Context *ctx,
- const char *backend_url,
- const char *wire_method,
- const struct
- TALER_WireTransferIdentifierRawP *wtid,
- const char *exchange_url,
- TALER_MERCHANT_TrackTransferCallback
- track_transfer_cb,
- void *track_transfer_cb_cls)
+TALER_MERCHANT_track_transfer (
+ struct GNUNET_CURL_Context *ctx,
+ const char *backend_url,
+ const char *wire_method,
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ const char *exchange_url,
+ TALER_MERCHANT_TrackTransferCallback track_transfer_cb,
+ void *track_transfer_cb_cls)
{
struct TALER_MERCHANT_TrackTransferHandle *tdo;
CURL *eh;
char *wtid_str;
- wtid_str = GNUNET_STRINGS_data_to_string_alloc (wtid,
- sizeof (struct
- TALER_WireTransferIdentifierRawP));
+ wtid_str = GNUNET_STRINGS_data_to_string_alloc (
+ wtid,
+ sizeof (struct TALER_WireTransferIdentifierRawP));
tdo = GNUNET_new (struct TALER_MERCHANT_TrackTransferHandle);
tdo->ctx = ctx;
tdo->cb = track_transfer_cb; // very last to be called
@@ -282,8 +298,8 @@ TALER_MERCHANT_track_transfer (struct GNUNET_CURL_Context *ctx,
* @param tdo handle to the tracking operation being cancelled
*/
void
-TALER_MERCHANT_track_transfer_cancel (struct
- TALER_MERCHANT_TrackTransferHandle *tdo)
+TALER_MERCHANT_track_transfer_cancel (
+ struct TALER_MERCHANT_TrackTransferHandle *tdo)
{
if (NULL != tdo->job)
{
diff --git a/src/lib/testing_api_cmd_check_payment.c b/src/lib/testing_api_cmd_check_payment.c
index b138e6ad..f72ab92b 100644
--- a/src/lib/testing_api_cmd_check_payment.c
+++ b/src/lib/testing_api_cmd_check_payment.c
@@ -227,11 +227,10 @@ conclude_task (void *cls)
* Callback for a /check-payment request.
*
* @param cls closure.
- * @param http_status HTTP status code we got.
- * @param json full response we got.
- * @param paid #GNUNET_YES (GNUNET_NO) if the contract was paid
+ * @param hr HTTP response we got
+ * @param paid #GNUNET_YES (#GNUNET_NO) if the contract was paid
* (not paid).
- * @param refunded #GNUNET_YES (GNUNET_NO) if the contract was
+ * @param refunded #GNUNET_YES (#GNUNET_NO) if the contract was
* refunded (not refunded).
* @param refund_amount the amount that was refunded to this
* contract.
@@ -240,8 +239,7 @@ conclude_task (void *cls)
*/
static void
check_payment_cb (void *cls,
- unsigned int http_status,
- const json_t *obj,
+ const struct TALER_MERCHANT_HttpResponse *hr,
int paid,
int refunded,
struct TALER_Amount *refund_amount,
@@ -257,14 +255,14 @@ check_payment_cb (void *cls,
paid,
taler_pay_uri);
cps->paid = paid;
- cps->http_status = http_status;
+ cps->http_status = hr->http_status;
cps->refunded = refunded;
if (0 == cps->timeout.rel_value_us)
{
/* synchronous variant */
if (paid != cps->expect_paid)
TALER_TESTING_FAIL (cps->is);
- if (cps->expected_http_status != http_status)
+ if (cps->expected_http_status != hr->http_status)
TALER_TESTING_FAIL (cps->is);
TALER_TESTING_interpreter_next (cps->is);
}
diff --git a/src/lib/testing_api_cmd_history.c b/src/lib/testing_api_cmd_history.c
index 2f4702a6..b87a6040 100644
--- a/src/lib/testing_api_cmd_history.c
+++ b/src/lib/testing_api_cmd_history.c
@@ -67,7 +67,6 @@ struct HistoryState
*/
unsigned long long start;
-
/**
* When this flag is GNUNET_YES, then the interpreter
* will request /history *omitting* the 'start' URL argument.
@@ -93,16 +92,11 @@ struct HistoryState
* the rows are sorted from the youngest to the oldest record.
*
* @param cls closure
- * @param http_status HTTP status returned by the merchant
- * backend
- * @param ec taler-specific error code
- * @param json actual body containing the history
+ * @param hr HTTP response we got
*/
static void
history_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const json_t *json)
+ const struct TALER_MERCHANT_HttpResponse *hr)
{
struct HistoryState *hs = cls;
unsigned int nresult;
@@ -112,7 +106,7 @@ history_cb (void *cls,
hs->ho = NULL;
- if (hs->http_status != http_status)
+ if (hs->http_status != hr->http_status)
TALER_TESTING_FAIL (hs->is);
if (0 == hs->http_status)
@@ -123,13 +117,13 @@ history_cb (void *cls,
return;
}
- arr = json_object_get (json, "history");
+ arr = json_object_get (hr->reply,
+ "history");
nresult = json_array_size (arr);
if (hs->nresult != nresult)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected number of history entries."
- " Got %d, expected %d\n",
+ "Unexpected number of history entries: Got %d, expected %d\n",
nresult,
hs->nresult);
TALER_TESTING_FAIL (hs->is);
@@ -157,8 +151,7 @@ history_cb (void *cls,
if (last_timestamp.abs_value_us < entry_timestamp.abs_value_us)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "History entries are NOT"
- " sorted from younger to older\n");
+ "History entries are NOT sorted from younger to older\n");
TALER_TESTING_interpreter_fail (hs->is);
return;
}
diff --git a/src/lib/testing_api_cmd_pay.c b/src/lib/testing_api_cmd_pay.c
index ff15bd36..7cd0f6c5 100644
--- a/src/lib/testing_api_cmd_pay.c
+++ b/src/lib/testing_api_cmd_pay.c
@@ -138,61 +138,6 @@ struct PayAgainState
/**
- * State for a "pay abort" CMD.
- */
-struct PayAbortState
-{
-
- /**
- * Expected HTTP response code.
- */
- unsigned int http_status;
-
- /**
- * Reference to the "pay" command to abort.
- */
- const char *pay_reference;
-
- /**
- * Merchant URL.
- */
- const char *merchant_url;
-
- /**
- * Handle to a "pay abort" operation.
- */
- struct TALER_MERCHANT_Pay *pao;
-
- /**
- * Interpreter state.
- */
- struct TALER_TESTING_Interpreter *is;
-
- /**
- * How many refund permissions this CMD got
- * the right for. Roughly, there is one refund
- * permission for one coin.
- */
- unsigned int num_refunds;
-
- /**
- * The actual refund data.
- */
- struct TALER_MERCHANT_RefundEntry *res;
-
- /**
- * The contract whose payment is to be aborted.
- */
- struct GNUNET_HashCode h_contract;
-
- /**
- * Merchant public key.
- */
- struct TALER_MerchantPublicKeyP merchant_pub;
-};
-
-
-/**
* Parse the @a coins specification and grow the @a pc
* array with the coins found, updating @a npc.
*
@@ -314,18 +259,11 @@ build_coins (struct TALER_MERCHANT_PayCoin **pc,
* HTTP response code matches our expectation.
*
* @param cls closure with the interpreter state
- * @param http_status HTTP response code, #MHD_HTTP_OK (200)
- * for successful deposit; 0 if the exchange's reply is
- * bogus (fails to follow the protocol)
- * @param ec taler-specific error object
- * @param obj the received JSON reply, should be kept as proof
- * (and, in case of errors, be forwarded to the customer)
+ * @param hr HTTP response
*/
static void
pay_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const json_t *obj)
+ const struct TALER_MERCHANT_HttpResponse *hr)
{
struct PayState *ps = cls;
struct GNUNET_CRYPTO_EddsaSignature sig;
@@ -334,17 +272,16 @@ pay_cb (void *cls,
const struct TALER_MerchantPublicKeyP *merchant_pub;
ps->po = NULL;
- if (ps->http_status != http_status)
+ if (ps->http_status != hr->http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u (%d) to command %s\n",
- http_status,
- ec,
- TALER_TESTING_interpreter_get_current_label (
- ps->is));
+ hr->http_status,
+ (int) hr->ec,
+ TALER_TESTING_interpreter_get_current_label (ps->is));
TALER_TESTING_FAIL (ps->is);
}
- if (MHD_HTTP_OK == http_status)
+ if (MHD_HTTP_OK == hr->http_status)
{
/* Check signature */
struct PaymentResponsePS mr;
@@ -357,29 +294,26 @@ pay_cb (void *cls,
};
const struct TALER_TESTING_Command *proposal_cmd;
- GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (
- obj, spec,
- &error_name,
- &error_line));
-
- mr.purpose.purpose = htonl (
- TALER_SIGNATURE_MERCHANT_PAYMENT_OK);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_JSON_parse (hr->reply,
+ spec,
+ &error_name,
+ &error_line));
+ mr.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_PAYMENT_OK);
mr.purpose.size = htonl (sizeof (mr));
mr.h_contract_terms = ps->h_contract_terms;
/* proposal reference was used at least once, at this point */
- GNUNET_assert
- (NULL !=
- (proposal_cmd =
- TALER_TESTING_interpreter_lookup_command (ps->is,
- ps->proposal_reference)));
-
+ GNUNET_assert (NULL !=
+ (proposal_cmd =
+ TALER_TESTING_interpreter_lookup_command (ps->is,
+ ps->
+ proposal_reference)));
if (GNUNET_OK !=
TALER_TESTING_get_trait_merchant_pub (proposal_cmd,
0,
&merchant_pub))
TALER_TESTING_FAIL (ps->is);
-
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_PAYMENT_OK,
&mr.purpose,
@@ -387,8 +321,7 @@ pay_cb (void *cls,
&merchant_pub->eddsa_pub))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Merchant signature given in response to /pay"
- " invalid\n");
+ "Merchant signature given in response to /pay invalid\n");
TALER_TESTING_FAIL (ps->is);
}
}
@@ -398,68 +331,6 @@ pay_cb (void *cls,
/**
- * Callback for a "pay abort" operation. Mainly, check HTTP
- * response code was as expected and stores refund permissions
- * in the state.
- *
- * @param cls closure.
- * @param http_status HTTP response code.
- * @param ec Taler error code.
- * @param merchant_pub public key of the merchant refunding the
- * contract.
- * @param h_contract the contract involved in the refund.
- * @param num_refunds how many refund permissions have been
- * issued.
- * @param res array containing the refund permissions.
- * @param obj raw response body.
- */
-static void
-pay_abort_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const struct TALER_MerchantPublicKeyP *merchant_pub,
- const struct GNUNET_HashCode *h_contract,
- unsigned int num_refunds,
- const struct TALER_MERCHANT_RefundEntry *res,
- const json_t *obj)
-{
- struct PayAbortState *pas = cls;
-
- pas->pao = NULL;
- if (pas->http_status != http_status)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u (%d) to command %s\n",
- http_status,
- ec,
- TALER_TESTING_interpreter_get_current_label
- (pas->is));
- TALER_TESTING_FAIL (pas->is);
- }
- if ( (MHD_HTTP_OK == http_status) &&
- (TALER_EC_NONE == ec) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Received %u refunds\n",
- num_refunds);
- pas->num_refunds = num_refunds;
- pas->res = GNUNET_new_array (num_refunds,
- struct TALER_MERCHANT_RefundEntry);
- memcpy (pas->res,
- res,
- num_refunds * sizeof (struct TALER_MERCHANT_RefundEntry));
- pas->h_contract = *h_contract;
- pas->merchant_pub = *merchant_pub;
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Successful pay-abort (HTTP status: %u)\n",
- http_status);
- TALER_TESTING_interpreter_next (pas->is);
-}
-
-
-/**
* Function used by both "pay" and "abort" operations.
* It prepares data and sends the "pay" request to the
* backend.
@@ -479,7 +350,7 @@ pay_abort_cb (void *cls,
* @param api_func "lib" function that will be called to either
* issue a "pay" or "abort" request.
* @param api_cb callback for @a api_func.
- * @param cls closure.
+ * @param api_cb_cls closure for @a api_cb
*
* @return handle to the operation, NULL if errors occur.
*/
@@ -491,9 +362,8 @@ _pay_run (const char *merchant_url,
const char *amount_with_fee,
const char *amount_without_fee,
const char *refund_fee,
- struct TALER_MERCHANT_Pay *(*api_func)(),
- void (*api_cb)(),
- void *cls)
+ TALER_MERCHANT_PayCallback api_cb,
+ void *api_cb_cls)
{
const struct TALER_TESTING_Command *proposal_cmd;
const json_t *contract_terms;
@@ -531,47 +401,48 @@ _pay_run (const char *merchant_url,
GNUNET_break (0);
return NULL;
}
-
- /* Get information that needs to be put verbatim in the
- * deposit permission */
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_string ("order_id",
- &order_id),
- GNUNET_JSON_spec_absolute_time ("refund_deadline",
- &refund_deadline),
- GNUNET_JSON_spec_absolute_time ("pay_deadline",
- &pay_deadline),
- GNUNET_JSON_spec_absolute_time ("timestamp",
- &timestamp),
- GNUNET_JSON_spec_fixed_auto ("merchant_pub",
- &merchant_pub),
- GNUNET_JSON_spec_fixed_auto ("h_wire",
- &h_wire),
- TALER_JSON_spec_amount ("amount",
- &total_amount),
- TALER_JSON_spec_amount ("max_fee",
- &max_fee),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (contract_terms,
- spec,
- &error_name,
- &error_line))
{
- char *js;
+ /* Get information that needs to be put verbatim in the
+ * deposit permission */
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_string ("order_id",
+ &order_id),
+ GNUNET_JSON_spec_absolute_time ("refund_deadline",
+ &refund_deadline),
+ GNUNET_JSON_spec_absolute_time ("pay_deadline",
+ &pay_deadline),
+ GNUNET_JSON_spec_absolute_time ("timestamp",
+ &timestamp),
+ GNUNET_JSON_spec_fixed_auto ("merchant_pub",
+ &merchant_pub),
+ GNUNET_JSON_spec_fixed_auto ("h_wire",
+ &h_wire),
+ TALER_JSON_spec_amount ("amount",
+ &total_amount),
+ TALER_JSON_spec_amount ("max_fee",
+ &max_fee),
+ GNUNET_JSON_spec_end ()
+ };
- js = json_dumps (contract_terms,
- JSON_INDENT (1));
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Parser failed on %s:%u for input `%s'\n",
- error_name,
- error_line,
- js);
- free (js);
- GNUNET_break_op (0);
- return NULL;
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (contract_terms,
+ spec,
+ &error_name,
+ &error_line))
+ {
+ char *js;
+
+ js = json_dumps (contract_terms,
+ JSON_INDENT (1));
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Parser failed on %s:%u for input `%s'\n",
+ error_name,
+ error_line,
+ js);
+ free (js);
+ GNUNET_break_op (0);
+ return NULL;
+ }
}
cr = GNUNET_strdup (coin_reference);
@@ -595,38 +466,38 @@ _pay_run (const char *merchant_url,
}
GNUNET_free (cr);
- if (GNUNET_OK != TALER_TESTING_get_trait_merchant_sig
- (proposal_cmd, 0, &merchant_sig))
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_merchant_sig (proposal_cmd,
+ 0,
+ &merchant_sig))
{
GNUNET_break (0);
return NULL;
}
-
-
- if (GNUNET_OK != TALER_TESTING_get_trait_h_contract_terms
- (proposal_cmd, 0, &h_proposal))
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_h_contract_terms (proposal_cmd,
+ 0,
+ &h_proposal))
{
GNUNET_break (0);
return NULL;
}
-
- ret = api_func (is->ctx,
- merchant_url,
- h_proposal,
- &total_amount,
- &max_fee,
- &merchant_pub,
- merchant_sig,
- timestamp,
- refund_deadline,
- pay_deadline,
- &h_wire,
- order_id,
- npay_coins,
- pay_coins,
- api_cb,
- cls);
-
+ ret = TALER_MERCHANT_pay_wallet (is->ctx,
+ merchant_url,
+ h_proposal,
+ &total_amount,
+ &max_fee,
+ &merchant_pub,
+ merchant_sig,
+ timestamp,
+ refund_deadline,
+ pay_deadline,
+ &h_wire,
+ order_id,
+ npay_coins,
+ pay_coins,
+ api_cb,
+ api_cb_cls);
GNUNET_array_grow (pay_coins,
npay_coins,
0);
@@ -657,7 +528,6 @@ pay_run (void *cls,
ps->amount_with_fee,
ps->amount_without_fee,
ps->refund_fee,
- &TALER_MERCHANT_pay_wallet,
&pay_cb,
ps)))
TALER_TESTING_FAIL (is);
@@ -810,179 +680,15 @@ TALER_TESTING_cmd_pay (const char *label,
/**
- * Free a "pay abort" CMD, and cancel it if need be.
- *
- * @param cls closure.
- * @param cmd command currently being freed.
- */
-static void
-pay_abort_cleanup (void *cls,
- const struct TALER_TESTING_Command *cmd)
-{
- struct PayAbortState *pas = cls;
-
- if (NULL != pas->pao)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Command `%s' did not complete.\n",
- TALER_TESTING_interpreter_get_current_label (
- pas->is));
- TALER_MERCHANT_pay_cancel (pas->pao);
- }
- GNUNET_free_non_null (pas->res);
- GNUNET_free (pas);
-}
-
-
-/**
- * Run a "pay abort" CMD.
- *
- * @param cls closure
- * @param cmd command being run.
- * @param is interpreter state
- */
-static void
-pay_abort_run (void *cls,
- const struct TALER_TESTING_Command *cmd,
- struct TALER_TESTING_Interpreter *is)
-{
-
- struct PayAbortState *pas = cls;
- const struct TALER_TESTING_Command *pay_cmd;
-
- const char *proposal_reference;
- const char *coin_reference;
- const char *amount_with_fee;
- const char *amount_without_fee;
- const char *refund_fee;
-
- pas->is = is;
- pay_cmd = TALER_TESTING_interpreter_lookup_command
- (is, pas->pay_reference);
- if (NULL == pay_cmd)
- TALER_TESTING_FAIL (is);
-
- if (GNUNET_OK != TALER_TESTING_get_trait_proposal_reference
- (pay_cmd, 0, &proposal_reference))
- TALER_TESTING_FAIL (is);
-
- if (GNUNET_OK != TALER_TESTING_get_trait_coin_reference
- (pay_cmd, 0, &coin_reference))
- TALER_TESTING_FAIL (is);
-
- if (GNUNET_OK != TALER_TESTING_get_trait_string
- (pay_cmd, AMOUNT_WITH_FEE, &amount_with_fee))
- TALER_TESTING_FAIL (is);
-
- if (GNUNET_OK != TALER_TESTING_get_trait_string
- (pay_cmd, AMOUNT_WITHOUT_FEE, &amount_without_fee))
- TALER_TESTING_FAIL (is);
-
- if (GNUNET_OK != TALER_TESTING_get_trait_string
- (pay_cmd, REFUND_FEE, &refund_fee))
- TALER_TESTING_FAIL (is);
-
- if (NULL == (pas->pao = _pay_run (pas->merchant_url,
- coin_reference,
- proposal_reference,
- is,
- amount_with_fee,
- amount_without_fee,
- refund_fee,
- &TALER_MERCHANT_pay_abort,
- &pay_abort_cb,
- pas)))
- TALER_TESTING_FAIL (is);
-}
-
-
-/**
- * Offer internal data useful to other commands.
- *
- * @param cls closure
- * @param ret[out] result (could be anything)
- * @param trait name of the trait
- * @param index index number of the object to extract.
- * @return #GNUNET_OK on success
- */
-static int
-pay_abort_traits (void *cls,
- const void **ret,
- const char *trait,
- unsigned int index)
-{
- struct PayAbortState *pas = cls;
- struct TALER_TESTING_Trait traits[] = {
- TALER_TESTING_make_trait_merchant_pub
- (0, &pas->merchant_pub),
- TALER_TESTING_make_trait_h_contract_terms
- (0, &pas->h_contract),
- TALER_TESTING_make_trait_refund_entry
- (0, pas->res),
- TALER_TESTING_make_trait_uint (0, &pas->num_refunds),
- TALER_TESTING_trait_end ()
- };
-
- return TALER_TESTING_get_trait (traits,
- ret,
- trait,
- index);
-}
-
-
-/**
- * Make a "pay abort" test command.
- *
- * @param label command label
- * @param merchant_url merchant base URL
- * @param pay_reference reference to the payment to abort
- * @param http_status expected HTTP response code
- *
- * @return the command
- */
-struct TALER_TESTING_Command
-TALER_TESTING_cmd_pay_abort (const char *label,
- const char *merchant_url,
- const char *pay_reference,
- unsigned int http_status)
-{
- struct PayAbortState *pas;
-
- pas = GNUNET_new (struct PayAbortState);
- pas->http_status = http_status;
- pas->pay_reference = pay_reference;
- pas->merchant_url = merchant_url;
- {
- struct TALER_TESTING_Command cmd = {
- .cls = pas,
- .label = label,
- .run = &pay_abort_run,
- .cleanup = &pay_abort_cleanup,
- .traits = &pay_abort_traits
- };
-
- return cmd;
- }
-}
-
-
-/**
* Function called with the result of a /pay again operation,
* check signature and HTTP response code are good.
*
* @param cls closure with the interpreter state
- * @param http_status HTTP response code, #MHD_HTTP_OK (200)
- * for successful deposit; 0 if the exchange's reply is
- * bogus (fails to follow the protocol)
- * @param ec taler-specific error object
- * @param obj the received JSON reply, should be kept as proof
- * (and, in case of errors, be forwarded to the customer)
+ * @param hr HTTP response
*/
static void
pay_again_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const json_t *obj)
+ const struct TALER_MERCHANT_HttpResponse *hr)
{
struct PayAgainState *pas = cls;
struct GNUNET_CRYPTO_EddsaSignature sig;
@@ -992,24 +698,23 @@ pay_again_cb (void *cls,
const struct TALER_MerchantPublicKeyP *merchant_pub;
pas->pao = NULL;
- if (pas->http_status != http_status)
+ if (pas->http_status != hr->http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u (%d) to command %s\n",
- http_status,
- ec,
- TALER_TESTING_interpreter_get_current_label
- (pas->is));
+ hr->http_status,
+ (int) hr->ec,
+ TALER_TESTING_interpreter_get_current_label (pas->is));
TALER_TESTING_interpreter_fail (pas->is);
return;
}
if (NULL ==
- (pay_cmd = TALER_TESTING_interpreter_lookup_command
- (pas->is, pas->pay_reference)))
+ (pay_cmd = TALER_TESTING_interpreter_lookup_command (pas->is,
+ pas->pay_reference)))
TALER_TESTING_FAIL (pas->is);
- if (MHD_HTTP_OK == http_status)
+ if (MHD_HTTP_OK == hr->http_status)
{
struct PaymentResponsePS mr;
/* Check signature */
@@ -1021,23 +726,24 @@ pay_again_cb (void *cls,
GNUNET_JSON_spec_end ()
};
- GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (obj,
+ GNUNET_assert (GNUNET_OK == GNUNET_JSON_parse (hr->reply,
spec,
&error_name,
&error_line));
- mr.purpose.purpose = htonl
- (TALER_SIGNATURE_MERCHANT_PAYMENT_OK);
+ mr.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_PAYMENT_OK);
mr.purpose.size = htonl (sizeof (mr));
- if (GNUNET_OK != TALER_TESTING_get_trait_merchant_pub
- (pay_cmd, 0, &merchant_pub))
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_merchant_pub (pay_cmd,
+ 0,
+ &merchant_pub))
TALER_TESTING_FAIL (pas->is);
- if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify
- (TALER_SIGNATURE_MERCHANT_PAYMENT_OK,
- &mr.purpose,
- &sig,
- &merchant_pub->eddsa_pub))
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_PAYMENT_OK,
+ &mr.purpose,
+ &sig,
+ &merchant_pub->eddsa_pub))
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Merchant signature given in"
@@ -1093,7 +799,6 @@ pay_again_run (void *cls,
amount_with_fee,
amount_without_fee,
pas->refund_fee,
- &TALER_MERCHANT_pay_wallet,
&pay_again_cb,
pas)))
TALER_TESTING_FAIL (is);
diff --git a/src/lib/testing_api_cmd_pay_abort.c b/src/lib/testing_api_cmd_pay_abort.c
new file mode 100644
index 00000000..6db46eb2
--- /dev/null
+++ b/src/lib/testing_api_cmd_pay_abort.c
@@ -0,0 +1,595 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2014-2018, 2020 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 3, or
+ (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public
+ License along with TALER; see the file COPYING. If not, see
+ <http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file lib/testing_api_cmd_pay_abort.c
+ * @brief command to test the /pay abort feature.
+ * @author Marcello Stanisci
+ */
+
+#include "platform.h"
+#include <taler/taler_exchange_service.h>
+#include <taler/taler_testing_lib.h>
+#include <taler/taler_signatures.h>
+#include "taler_merchant_service.h"
+#include "taler_merchant_testing_lib.h"
+
+#define AMOUNT_WITH_FEE 0
+#define AMOUNT_WITHOUT_FEE 1
+#define REFUND_FEE 2
+
+/**
+ * State for a "pay abort" CMD.
+ */
+struct PayAbortState
+{
+
+ /**
+ * Expected HTTP response code.
+ */
+ unsigned int http_status;
+
+ /**
+ * Reference to the "pay" command to abort.
+ */
+ const char *pay_reference;
+
+ /**
+ * Merchant URL.
+ */
+ const char *merchant_url;
+
+ /**
+ * Handle to a "pay abort" operation.
+ */
+ struct TALER_MERCHANT_Pay *pao;
+
+ /**
+ * Interpreter state.
+ */
+ struct TALER_TESTING_Interpreter *is;
+
+ /**
+ * How many refund permissions this CMD got
+ * the right for. Roughly, there is one refund
+ * permission for one coin.
+ */
+ unsigned int num_refunds;
+
+ /**
+ * The actual refund data.
+ */
+ struct TALER_MERCHANT_RefundEntry *res;
+
+ /**
+ * The contract whose payment is to be aborted.
+ */
+ struct GNUNET_HashCode h_contract;
+
+ /**
+ * Merchant public key.
+ */
+ struct TALER_MerchantPublicKeyP merchant_pub;
+};
+
+
+/**
+ * Parse the @a coins specification and grow the @a pc
+ * array with the coins found, updating @a npc.
+ *
+ * @param[in,out] pc pointer to array of coins found
+ * @param[in,out] npc length of array at @a pc
+ * @param[in] coins string specifying coins to add to @a pc,
+ * clobbered in the process
+ * @param is interpreter state
+ * @param amount_with_fee total amount to be paid for a contract.
+ * @param amount_without_fee to be removed, there is no
+ * per-contract fee, only per-coin exists.
+ * @param refund_fee per-contract? per-coin?
+ * @return #GNUNET_OK on success
+ */
+static int
+build_coins (struct TALER_MERCHANT_PayCoin **pc,
+ unsigned int *npc,
+ char *coins,
+ struct TALER_TESTING_Interpreter *is,
+ const char *amount_with_fee,
+ const char *amount_without_fee,
+ const char *refund_fee)
+{
+ char *token;
+
+ for (token = strtok (coins, ";");
+ NULL != token;
+ token = strtok (NULL, ";"))
+ {
+ const struct TALER_TESTING_Command *coin_cmd;
+ char *ctok;
+ unsigned int ci;
+ struct TALER_MERCHANT_PayCoin *icoin;
+ const struct TALER_EXCHANGE_DenomPublicKey *dpk;
+
+ /* Token syntax is "LABEL[/NUMBER]" */
+ ctok = strchr (token, '/');
+ ci = 0;
+ if (NULL != ctok)
+ {
+ *ctok = '\0';
+ ctok++;
+ if (1 != sscanf (ctok,
+ "%u",
+ &ci))
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ }
+
+ coin_cmd = TALER_TESTING_interpreter_lookup_command
+ (is, token);
+
+ if (NULL == coin_cmd)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+
+ GNUNET_array_grow (*pc,
+ *npc,
+ (*npc) + 1);
+
+ icoin = &((*pc)[(*npc) - 1]);
+
+ {
+ const struct TALER_CoinSpendPrivateKeyP *coin_priv;
+ const struct TALER_DenominationSignature *denom_sig;
+ const struct TALER_Amount *denom_value;
+ const struct TALER_EXCHANGE_DenomPublicKey *denom_pub;
+
+ GNUNET_assert
+ (GNUNET_OK == TALER_TESTING_get_trait_coin_priv
+ (coin_cmd, 0, &coin_priv));
+
+ GNUNET_assert
+ (GNUNET_OK == TALER_TESTING_get_trait_denom_pub
+ (coin_cmd, 0, &denom_pub));
+
+ GNUNET_assert
+ (GNUNET_OK == TALER_TESTING_get_trait_denom_sig
+ (coin_cmd, 0, &denom_sig));
+
+ GNUNET_assert
+ (GNUNET_OK == TALER_TESTING_get_trait_amount_obj
+ (coin_cmd, 0, &denom_value));
+
+ icoin->coin_priv = *coin_priv;
+ icoin->denom_pub = denom_pub->key;
+ icoin->denom_sig = *denom_sig;
+ icoin->denom_value = *denom_value;
+ icoin->amount_with_fee = *denom_value;
+ }
+ GNUNET_assert (NULL != (dpk =
+ TALER_TESTING_find_pk (is->keys,
+ &icoin->denom_value)));
+
+ GNUNET_assert (GNUNET_SYSERR !=
+ TALER_amount_subtract (&icoin->amount_without_fee,
+ &icoin->denom_value,
+ &dpk->fee_deposit));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_TESTING_get_trait_url (coin_cmd,
+ TALER_TESTING_UT_EXCHANGE_BASE_URL,
+ &icoin->exchange_url));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount (refund_fee,
+ &icoin->refund_fee));
+ }
+
+ return GNUNET_OK;
+}
+
+
+/**
+ * Callback for a "pay abort" operation. Mainly, check HTTP
+ * response code was as expected and stores refund permissions
+ * in the state.
+ *
+ * @param cls closure.
+ * @param hr HTTP response
+ * @param merchant_pub public key of the merchant refunding the
+ * contract.
+ * @param h_contract the contract involved in the refund.
+ * @param num_refunds how many refund permissions have been
+ * issued.
+ * @param res array containing the refund permissions.
+ */
+static void
+pay_abort_cb (void *cls,
+ const struct TALER_MERCHANT_HttpResponse *hr,
+ const struct TALER_MerchantPublicKeyP *merchant_pub,
+ const struct GNUNET_HashCode *h_contract,
+ unsigned int num_refunds,
+ const struct TALER_MERCHANT_RefundEntry *res)
+{
+ struct PayAbortState *pas = cls;
+
+ pas->pao = NULL;
+ if (pas->http_status != hr->http_status)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected response code %u (%d) to command %s\n",
+ hr->http_status,
+ (int) hr->ec,
+ TALER_TESTING_interpreter_get_current_label (pas->is));
+ TALER_TESTING_FAIL (pas->is);
+ }
+ if ( (MHD_HTTP_OK == hr->http_status) &&
+ (TALER_EC_NONE == hr->ec) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received %u refunds\n",
+ num_refunds);
+ pas->num_refunds = num_refunds;
+ pas->res = GNUNET_new_array (num_refunds,
+ struct TALER_MERCHANT_RefundEntry);
+ memcpy (pas->res,
+ res,
+ num_refunds * sizeof (struct TALER_MERCHANT_RefundEntry));
+ pas->h_contract = *h_contract;
+ pas->merchant_pub = *merchant_pub;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Successful pay-abort (HTTP status: %u)\n",
+ hr->http_status);
+ TALER_TESTING_interpreter_next (pas->is);
+}
+
+
+/**
+ * Function used by both the "abort" operation.
+ * It prepares data and sends the "pay-abort" request to the
+ * backend.
+ *
+ * @param merchant_url base URL of the merchant serving the
+ * request.
+ * @param coin_reference reference to the CMD(s) that offer
+ * "coins" traits. It is possible to give multiple
+ * references by using semicolons to separate them.
+ * @param proposal_refere reference to a "proposal" CMD.
+ * @param is interpreter state.
+ * @param amount_with_fee amount to be paid, including deposit
+ * fee.
+ * @param amount_without_fee amount to be paid, without deposit
+ * fee.
+ * @param refund_fee refund fee.
+ * @param api_func "lib" function that will be called to either
+ * issue a "pay" or "abort" request.
+ * @param api_cb callback for @a api_func.
+ * @param api_cb_cls closure for @a api_cb
+ * @return handle to the operation, NULL if errors occur.
+ */
+static struct TALER_MERCHANT_Pay *
+_pay_abort_run (const char *merchant_url,
+ const char *coin_reference,
+ const char *proposal_reference,
+ struct TALER_TESTING_Interpreter *is,
+ const char *amount_with_fee,
+ const char *amount_without_fee,
+ const char *refund_fee,
+ TALER_MERCHANT_PayRefundCallback api_cb,
+ void *api_cb_cls)
+{
+ const struct TALER_TESTING_Command *proposal_cmd;
+ const json_t *contract_terms;
+ const char *order_id;
+ struct GNUNET_TIME_Absolute refund_deadline;
+ struct GNUNET_TIME_Absolute pay_deadline;
+ struct GNUNET_TIME_Absolute timestamp;
+ struct TALER_MerchantPublicKeyP merchant_pub;
+ struct GNUNET_HashCode h_wire;
+ const struct GNUNET_HashCode *h_proposal;
+ struct TALER_Amount total_amount;
+ struct TALER_Amount max_fee;
+ const char *error_name;
+ unsigned int error_line;
+ struct TALER_MERCHANT_PayCoin *pay_coins;
+ unsigned int npay_coins;
+ char *cr;
+ struct TALER_MerchantSignatureP *merchant_sig;
+ struct TALER_MERCHANT_Pay *ret;
+
+ proposal_cmd = TALER_TESTING_interpreter_lookup_command (is,
+ proposal_reference);
+
+ if (NULL == proposal_cmd)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_contract_terms (proposal_cmd,
+ 0,
+ &contract_terms))
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ {
+ /* Get information that needs to be put verbatim in the
+ * deposit permission */
+ struct GNUNET_JSON_Specification spec[] = {
+ GNUNET_JSON_spec_string ("order_id",
+ &order_id),
+ GNUNET_JSON_spec_absolute_time ("refund_deadline",
+ &refund_deadline),
+ GNUNET_JSON_spec_absolute_time ("pay_deadline",
+ &pay_deadline),
+ GNUNET_JSON_spec_absolute_time ("timestamp",
+ &timestamp),
+ GNUNET_JSON_spec_fixed_auto ("merchant_pub",
+ &merchant_pub),
+ GNUNET_JSON_spec_fixed_auto ("h_wire",
+ &h_wire),
+ TALER_JSON_spec_amount ("amount",
+ &total_amount),
+ TALER_JSON_spec_amount ("max_fee",
+ &max_fee),
+ GNUNET_JSON_spec_end ()
+ };
+
+ if (GNUNET_OK !=
+ GNUNET_JSON_parse (contract_terms,
+ spec,
+ &error_name,
+ &error_line))
+ {
+ char *js;
+
+ js = json_dumps (contract_terms,
+ JSON_INDENT (1));
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Parser failed on %s:%u for input `%s'\n",
+ error_name,
+ error_line,
+ js);
+ free (js);
+ GNUNET_break_op (0);
+ return NULL;
+ }
+ }
+
+ cr = GNUNET_strdup (coin_reference);
+ pay_coins = NULL;
+ npay_coins = 0;
+ if (GNUNET_OK !=
+ build_coins (&pay_coins,
+ &npay_coins,
+ cr,
+ is,
+ amount_with_fee,
+ amount_without_fee,
+ refund_fee))
+ {
+ GNUNET_array_grow (pay_coins,
+ npay_coins,
+ 0);
+ GNUNET_free (cr);
+ GNUNET_break (0);
+ return NULL;
+ }
+
+ GNUNET_free (cr);
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_merchant_sig (proposal_cmd,
+ 0,
+ &merchant_sig))
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_h_contract_terms (proposal_cmd,
+ 0,
+ &h_proposal))
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ ret = TALER_MERCHANT_pay_abort (is->ctx,
+ merchant_url,
+ h_proposal,
+ &total_amount,
+ &max_fee,
+ &merchant_pub,
+ merchant_sig,
+ timestamp,
+ refund_deadline,
+ pay_deadline,
+ &h_wire,
+ order_id,
+ npay_coins,
+ pay_coins,
+ api_cb,
+ api_cb_cls);
+ GNUNET_array_grow (pay_coins,
+ npay_coins,
+ 0);
+ return ret;
+}
+
+
+/**
+ * Free a "pay abort" CMD, and cancel it if need be.
+ *
+ * @param cls closure.
+ * @param cmd command currently being freed.
+ */
+static void
+pay_abort_cleanup (void *cls,
+ const struct TALER_TESTING_Command *cmd)
+{
+ struct PayAbortState *pas = cls;
+
+ if (NULL != pas->pao)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Command `%s' did not complete.\n",
+ TALER_TESTING_interpreter_get_current_label (
+ pas->is));
+ TALER_MERCHANT_pay_cancel (pas->pao);
+ }
+ GNUNET_free_non_null (pas->res);
+ GNUNET_free (pas);
+}
+
+
+/**
+ * Run a "pay abort" CMD.
+ *
+ * @param cls closure
+ * @param cmd command being run.
+ * @param is interpreter state
+ */
+static void
+pay_abort_run (void *cls,
+ const struct TALER_TESTING_Command *cmd,
+ struct TALER_TESTING_Interpreter *is)
+{
+
+ struct PayAbortState *pas = cls;
+ const struct TALER_TESTING_Command *pay_cmd;
+
+ const char *proposal_reference;
+ const char *coin_reference;
+ const char *amount_with_fee;
+ const char *amount_without_fee;
+ const char *refund_fee;
+
+ pas->is = is;
+ pay_cmd = TALER_TESTING_interpreter_lookup_command
+ (is, pas->pay_reference);
+ if (NULL == pay_cmd)
+ TALER_TESTING_FAIL (is);
+
+ if (GNUNET_OK != TALER_TESTING_get_trait_proposal_reference
+ (pay_cmd, 0, &proposal_reference))
+ TALER_TESTING_FAIL (is);
+
+ if (GNUNET_OK != TALER_TESTING_get_trait_coin_reference
+ (pay_cmd, 0, &coin_reference))
+ TALER_TESTING_FAIL (is);
+
+ if (GNUNET_OK != TALER_TESTING_get_trait_string
+ (pay_cmd, AMOUNT_WITH_FEE, &amount_with_fee))
+ TALER_TESTING_FAIL (is);
+
+ if (GNUNET_OK != TALER_TESTING_get_trait_string
+ (pay_cmd, AMOUNT_WITHOUT_FEE, &amount_without_fee))
+ TALER_TESTING_FAIL (is);
+
+ if (GNUNET_OK != TALER_TESTING_get_trait_string
+ (pay_cmd, REFUND_FEE, &refund_fee))
+ TALER_TESTING_FAIL (is);
+
+ if (NULL == (pas->pao = _pay_abort_run (pas->merchant_url,
+ coin_reference,
+ proposal_reference,
+ is,
+ amount_with_fee,
+ amount_without_fee,
+ refund_fee,
+ &pay_abort_cb,
+ pas)))
+ TALER_TESTING_FAIL (is);
+}
+
+
+/**
+ * Offer internal data useful to other commands.
+ *
+ * @param cls closure
+ * @param ret[out] result (could be anything)
+ * @param trait name of the trait
+ * @param index index number of the object to extract.
+ * @return #GNUNET_OK on success
+ */
+static int
+pay_abort_traits (void *cls,
+ const void **ret,
+ const char *trait,
+ unsigned int index)
+{
+ struct PayAbortState *pas = cls;
+ struct TALER_TESTING_Trait traits[] = {
+ TALER_TESTING_make_trait_merchant_pub
+ (0, &pas->merchant_pub),
+ TALER_TESTING_make_trait_h_contract_terms
+ (0, &pas->h_contract),
+ TALER_TESTING_make_trait_refund_entry
+ (0, pas->res),
+ TALER_TESTING_make_trait_uint (0, &pas->num_refunds),
+ TALER_TESTING_trait_end ()
+ };
+
+ return TALER_TESTING_get_trait (traits,
+ ret,
+ trait,
+ index);
+}
+
+
+/**
+ * Make a "pay abort" test command.
+ *
+ * @param label command label
+ * @param merchant_url merchant base URL
+ * @param pay_reference reference to the payment to abort
+ * @param http_status expected HTTP response code
+ *
+ * @return the command
+ */
+struct TALER_TESTING_Command
+TALER_TESTING_cmd_pay_abort (const char *label,
+ const char *merchant_url,
+ const char *pay_reference,
+ unsigned int http_status)
+{
+ struct PayAbortState *pas;
+
+ pas = GNUNET_new (struct PayAbortState);
+ pas->http_status = http_status;
+ pas->pay_reference = pay_reference;
+ pas->merchant_url = merchant_url;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .cls = pas,
+ .label = label,
+ .run = &pay_abort_run,
+ .cleanup = &pay_abort_cleanup,
+ .traits = &pay_abort_traits
+ };
+
+ return cmd;
+ }
+}
+
+
+/* end of testing_api_cmd_pay_abort.c */
diff --git a/src/lib/testing_api_cmd_poll_payment.c b/src/lib/testing_api_cmd_poll_payment.c
index aa92043a..954b1d4d 100644
--- a/src/lib/testing_api_cmd_poll_payment.c
+++ b/src/lib/testing_api_cmd_poll_payment.c
@@ -225,8 +225,7 @@ conclude_task (void *cls)
* Callback for a /poll-payment request.
*
* @param cls closure.
- * @param http_status HTTP status code we got.
- * @param json full response we got.
+ * @param hr HTTP response we got
* @param paid #GNUNET_YES (#GNUNET_NO) if the contract was (not) paid
* @param refunded #GNUNET_YES (#GNUNET_NO) if the contract was
* (not) refunded.
@@ -237,8 +236,7 @@ conclude_task (void *cls)
*/
static void
poll_payment_cb (void *cls,
- unsigned int http_status,
- const json_t *obj,
+ const struct TALER_MERCHANT_HttpResponse *hr,
int paid,
int refunded,
struct TALER_Amount *refund_amount,
@@ -247,15 +245,15 @@ poll_payment_cb (void *cls,
struct PollPaymentStartState *cps = cls;
cps->cpo = NULL;
- if ( (MHD_HTTP_OK != http_status) &&
- (NULL != obj) )
+ if ( (MHD_HTTP_OK != hr->http_status) &&
+ (NULL != hr->reply) )
{
- char *log = json_dumps (obj,
+ char *log = json_dumps (hr->reply,
JSON_COMPACT);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Poll payment returned %u: %s\n",
- http_status,
+ hr->http_status,
log);
free (log);
}
@@ -263,12 +261,12 @@ poll_payment_cb (void *cls,
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Poll payment returned %u (%d/%d)\n",
- http_status,
+ hr->http_status,
paid,
refunded);
}
cps->paid = paid;
- cps->http_status = http_status;
+ cps->http_status = hr->http_status;
cps->refunded = refunded;
if (GNUNET_YES == refunded)
cps->refund = *refund_amount;
diff --git a/src/lib/testing_api_cmd_proposal.c b/src/lib/testing_api_cmd_proposal.c
index 087c1c82..1d99c1aa 100644
--- a/src/lib/testing_api_cmd_proposal.c
+++ b/src/lib/testing_api_cmd_proposal.c
@@ -119,16 +119,12 @@ proposal_traits (void *cls,
#define MAKE_TRAIT_NONCE(ptr) \
TALER_TESTING_make_trait_merchant_pub (1, (struct \
TALER_MerchantPublicKeyP *) (ptr))
-
struct TALER_TESTING_Trait traits[] = {
TALER_TESTING_make_trait_order_id (0, ps->order_id),
- TALER_TESTING_make_trait_contract_terms
- (0, ps->contract_terms),
- TALER_TESTING_make_trait_h_contract_terms
- (0, &ps->h_contract_terms),
+ TALER_TESTING_make_trait_contract_terms (0, ps->contract_terms),
+ TALER_TESTING_make_trait_h_contract_terms (0, &ps->h_contract_terms),
TALER_TESTING_make_trait_merchant_sig (0, &ps->merchant_sig),
- TALER_TESTING_make_trait_merchant_pub
- (0, &ps->merchant_pub),
+ TALER_TESTING_make_trait_merchant_pub (0, &ps->merchant_pub),
MAKE_TRAIT_NONCE (&ps->nonce),
TALER_TESTING_trait_end ()
};
@@ -146,17 +142,16 @@ proposal_traits (void *cls,
* created.
*
* @param cls closure
- * @param http_status HTTP status code we got
- * @param json full response we got
+ * @param hr HTTP response we got
+ * @param sig merchant's signature
+ * @param hash hash over the contract
*/
static void
-proposal_lookup_initial_cb
- (void *cls,
- unsigned int http_status,
- const json_t *json,
- const json_t *contract_terms,
- const struct TALER_MerchantSignatureP *sig,
- const struct GNUNET_HashCode *hash)
+proposal_lookup_initial_cb (void *cls,
+ const struct TALER_MERCHANT_HttpResponse *hr,
+ const json_t *contract_terms,
+ const struct TALER_MerchantSignatureP *sig,
+ const struct GNUNET_HashCode *hash)
{
struct ProposalState *ps = cls;
struct TALER_MerchantPublicKeyP merchant_pub;
@@ -169,13 +164,12 @@ proposal_lookup_initial_cb
};
ps->plo = NULL;
- if (ps->http_status != http_status)
+ if (ps->http_status != hr->http_status)
TALER_TESTING_FAIL (ps->is);
ps->contract_terms = json_deep_copy (contract_terms);
ps->h_contract_terms = *hash;
ps->merchant_sig = *sig;
-
if (GNUNET_OK !=
GNUNET_JSON_parse (contract_terms,
spec,
@@ -196,9 +190,7 @@ proposal_lookup_initial_cb
free (log);
TALER_TESTING_FAIL (ps->is);
}
-
ps->merchant_pub = merchant_pub;
-
TALER_TESTING_interpreter_next (ps->is);
}
@@ -210,28 +202,21 @@ proposal_lookup_initial_cb
* method.
*
* @param cls closure.
- * @param http_status HTTP response code coming from
- * the backend.
- * @param ec error code.
- * @param obj when successful, it has the format:
- * '{"order_id": "<order_id>"}'
+ * @param hr HTTP response
* @param order_id order id of the proposal.
*/
static void
proposal_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const json_t *obj,
+ const struct TALER_MERCHANT_HttpResponse *hr,
const char *order_id)
{
struct ProposalState *ps = cls;
ps->po = NULL;
-
- if (ps->http_status != http_status)
+ if (ps->http_status != hr->http_status)
{
TALER_LOG_ERROR ("Given vs expected: %u vs %u\n",
- http_status,
+ hr->http_status,
ps->http_status);
TALER_TESTING_FAIL (ps->is);
}
@@ -243,21 +228,20 @@ proposal_cb (void *cls,
return;
}
- switch (http_status)
+ switch (hr->http_status)
{
case MHD_HTTP_OK:
ps->order_id = GNUNET_strdup (order_id);
break;
default:
{
- char *s = json_dumps (obj, JSON_COMPACT);
+ char *s = json_dumps (hr->reply,
+ JSON_COMPACT);
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected status code from /proposal:" \
- " %u (%d). Command %s, response: %s\n",
- http_status,
- ec,
- TALER_TESTING_interpreter_get_current_label (
- ps->is),
+ "Unexpected status code from /proposal: %u (%d) at %s; JSON: %s\n",
+ hr->http_status,
+ hr->ec,
+ TALER_TESTING_interpreter_get_current_label (ps->is),
s);
GNUNET_free_non_null (s);
/**
@@ -270,13 +254,12 @@ proposal_cb (void *cls,
}
if (NULL ==
- (ps->plo = TALER_MERCHANT_proposal_lookup
- (ps->is->ctx,
- ps->merchant_url,
- ps->order_id,
- &ps->nonce,
- &proposal_lookup_initial_cb,
- ps)))
+ (ps->plo = TALER_MERCHANT_proposal_lookup (ps->is->ctx,
+ ps->merchant_url,
+ ps->order_id,
+ &ps->nonce,
+ &proposal_lookup_initial_cb,
+ ps)))
TALER_TESTING_FAIL (ps->is);
}
diff --git a/src/lib/testing_api_cmd_proposal_lookup.c b/src/lib/testing_api_cmd_proposal_lookup.c
index 66c88742..1ea0c0cb 100644
--- a/src/lib/testing_api_cmd_proposal_lookup.c
+++ b/src/lib/testing_api_cmd_proposal_lookup.c
@@ -123,8 +123,7 @@ proposal_lookup_cleanup (void *cls,
* response code is as expected.
*
* @param cls closure
- * @param http_status HTTP status code we got
- * @param json full response we got
+ * @param hr HTTP response we got
* @param contract_terms the contract terms; they are the
* backend-filled up proposal minus cryptographic
* information.
@@ -133,8 +132,7 @@ proposal_lookup_cleanup (void *cls,
*/
static void
proposal_lookup_cb (void *cls,
- unsigned int http_status,
- const json_t *json,
+ const struct TALER_MERCHANT_HttpResponse *hr,
const json_t *contract_terms,
const struct TALER_MerchantSignatureP *sig,
const struct GNUNET_HashCode *hash)
@@ -142,11 +140,12 @@ proposal_lookup_cb (void *cls,
struct ProposalLookupState *pls = cls;
pls->plo = NULL;
- if (pls->http_status != http_status)
+ if (pls->http_status != hr->http_status)
TALER_TESTING_FAIL (pls->is);
- if (MHD_HTTP_OK == http_status)
+ if (MHD_HTTP_OK == hr->http_status)
{
- pls->contract_terms = json_object_get (json, "contract_terms");
+ pls->contract_terms = json_object_get (hr->reply,
+ "contract_terms");
if (NULL == pls->contract_terms)
TALER_TESTING_FAIL (pls->is);
json_incref (pls->contract_terms);
diff --git a/src/lib/testing_api_cmd_refund_increase.c b/src/lib/testing_api_cmd_refund_increase.c
index 8a544d61..153d8a74 100644
--- a/src/lib/testing_api_cmd_refund_increase.c
+++ b/src/lib/testing_api_cmd_refund_increase.c
@@ -104,20 +104,16 @@ refund_increase_cleanup (void *cls,
* if the HTTP response code is the one expected.
*
* @param cls closure
- * @param http_status HTTP status code
- * @param ec taler-specific error object
- * @param obj response body; is NULL on success.
+ * @param hr HTTP response
*/
static void
refund_increase_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const json_t *obj)
+ const struct TALER_MERCHANT_HttpResponse *hr)
{
struct RefundIncreaseState *ris = cls;
ris->rio = NULL;
- if (ris->http_code != http_status)
+ if (ris->http_code != hr->http_status)
TALER_TESTING_FAIL (ris->is);
TALER_TESTING_interpreter_next (ris->is);
}
@@ -199,14 +195,13 @@ refund_increase_traits (void *cls,
* @return the command.
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_refund_increase
- (const char *label,
- const char *merchant_url,
- const char *reason,
- const char *order_id,
- const char *refund_amount,
- const char *refund_fee,
- unsigned int http_code)
+TALER_TESTING_cmd_refund_increase (const char *label,
+ const char *merchant_url,
+ const char *reason,
+ const char *order_id,
+ const char *refund_amount,
+ const char *refund_fee,
+ unsigned int http_code)
{
struct RefundIncreaseState *ris;
diff --git a/src/lib/testing_api_cmd_refund_lookup.c b/src/lib/testing_api_cmd_refund_lookup.c
index 35703cd4..986f72f1 100644
--- a/src/lib/testing_api_cmd_refund_lookup.c
+++ b/src/lib/testing_api_cmd_refund_lookup.c
@@ -130,15 +130,11 @@ hashmap_free (void *cls,
* expectation.
*
* @param cls closure
- * @param http_status HTTP status code
- * @param ec taler-specific error object
- * @param obj response body; is NULL on error.
+ * @param hr HTTP response we got
*/
static void
refund_lookup_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const json_t *obj)
+ const struct TALER_MERCHANT_HttpResponse *hr)
{
struct RefundLookupState *rls = cls;
struct GNUNET_CONTAINER_MultiHashMap *map;
@@ -158,10 +154,11 @@ refund_lookup_cb (void *cls,
const json_t *arr;
rls->rlo = NULL;
- if (rls->http_code != http_status)
+ if (rls->http_code != hr->http_status)
TALER_TESTING_FAIL (rls->is);
- arr = json_object_get (obj, "refund_permissions");
+ arr = json_object_get (hr->reply,
+ "refund_permissions");
if (NULL == arr)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -190,8 +187,9 @@ refund_lookup_cb (void *cls,
GNUNET_CRYPTO_hash (&coin_pub,
sizeof (struct TALER_CoinSpendPublicKeyP),
&h_coin_pub);
- GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put
- (map,
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CONTAINER_multihashmap_put (
+ map,
&h_coin_pub, // which
irefund_amount, // how much
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
@@ -199,17 +197,21 @@ refund_lookup_cb (void *cls,
/* Compare spent coins with refunded, and if they match,
* increase an accumulator. */
- if (NULL ==
- (pay_cmd = TALER_TESTING_interpreter_lookup_command
- (rls->is, rls->pay_reference)))
+ if (NULL == (pay_cmd = TALER_TESTING_interpreter_lookup_command (
+ rls->is,
+ rls->pay_reference)))
TALER_TESTING_FAIL (rls->is);
- if (GNUNET_OK != TALER_TESTING_get_trait_coin_reference
- (pay_cmd, 0, &coin_reference))
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_coin_reference (
+ pay_cmd,
+ 0,
+ &coin_reference))
TALER_TESTING_FAIL (rls->is);
- GNUNET_assert (GNUNET_OK == TALER_amount_get_zero ("EUR",
- &acc));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_get_zero ("EUR",
+ &acc));
coin_reference_dup = GNUNET_strdup (coin_reference);
for (icoin_reference = strtok (coin_reference_dup, ";");
NULL != icoin_reference;
@@ -222,8 +224,9 @@ refund_lookup_cb (void *cls,
const struct TALER_TESTING_Command *icoin_cmd;
if (NULL ==
- (icoin_cmd = TALER_TESTING_interpreter_lookup_command
- (rls->is, icoin_reference)) )
+ (icoin_cmd =
+ TALER_TESTING_interpreter_lookup_command (rls->is,
+ icoin_reference)) )
{
GNUNET_break (0);
TALER_LOG_ERROR ("Bad reference `%s'\n",
@@ -233,31 +236,30 @@ refund_lookup_cb (void *cls,
return;
}
- if (GNUNET_OK != TALER_TESTING_get_trait_coin_priv
- (icoin_cmd, 0, &icoin_priv))
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_coin_priv (icoin_cmd,
+ 0,
+ &icoin_priv))
{
GNUNET_break (0);
- TALER_LOG_ERROR ("Command `%s' failed to give coin"
- " priv trait\n",
+ TALER_LOG_ERROR ("Command `%s' failed to give coin priv trait\n",
icoin_reference);
TALER_TESTING_interpreter_fail (rls->is);
GNUNET_CONTAINER_multihashmap_destroy (map);
return;
}
-
GNUNET_CRYPTO_eddsa_key_get_public (&icoin_priv->eddsa_priv,
&icoin_pub.eddsa_pub);
GNUNET_CRYPTO_hash (&icoin_pub,
sizeof (struct TALER_CoinSpendPublicKeyP),
&h_icoin_pub);
- iamount = GNUNET_CONTAINER_multihashmap_get
- (map, &h_icoin_pub);
+ iamount = GNUNET_CONTAINER_multihashmap_get (map,
+ &h_icoin_pub);
/* Can be NULL: not all coins are involved in refund */
if (NULL == iamount)
continue;
-
GNUNET_assert (GNUNET_OK == TALER_amount_add (&acc,
&acc,
iamount));
@@ -266,23 +268,28 @@ refund_lookup_cb (void *cls,
GNUNET_free (coin_reference_dup);
if (NULL !=
- (increase_cmd = TALER_TESTING_interpreter_lookup_command
- (rls->is, rls->increase_reference)))
+ (increase_cmd
+ = TALER_TESTING_interpreter_lookup_command (rls->is,
+ rls->increase_reference)))
{
- if (GNUNET_OK != TALER_TESTING_get_trait_string
- (increase_cmd, 0, &refund_amount))
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_string (increase_cmd,
+ 0,
+ &refund_amount))
TALER_TESTING_FAIL (rls->is);
- if (GNUNET_OK != TALER_string_to_amount
- (refund_amount, &ra))
+ if (GNUNET_OK !=
+ TALER_string_to_amount (refund_amount,
+ &ra))
TALER_TESTING_FAIL (rls->is);
}
else
{
GNUNET_assert (NULL != rls->refund_amount);
- if (GNUNET_OK != TALER_string_to_amount
- (rls->refund_amount, &ra))
+ if (GNUNET_OK !=
+ TALER_string_to_amount (rls->refund_amount,
+ &ra))
TALER_TESTING_FAIL (rls->is);
}
@@ -350,8 +357,8 @@ refund_lookup_run (void *cls,
* @return the command.
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_refund_lookup
- (const char *label,
+TALER_TESTING_cmd_refund_lookup (
+ const char *label,
const char *merchant_url,
const char *increase_reference,
const char *pay_reference,
@@ -401,8 +408,8 @@ TALER_TESTING_cmd_refund_lookup
* @return the command.
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_refund_lookup_with_amount
- (const char *label,
+TALER_TESTING_cmd_refund_lookup_with_amount (
+ const char *label,
const char *merchant_url,
const char *increase_reference,
const char *pay_reference,
diff --git a/src/lib/testing_api_cmd_tip_authorize.c b/src/lib/testing_api_cmd_tip_authorize.c
index e10ecac0..928ec04d 100644
--- a/src/lib/testing_api_cmd_tip_authorize.c
+++ b/src/lib/testing_api_cmd_tip_authorize.c
@@ -95,53 +95,46 @@ struct TipAuthorizeState
* tip_expiration).
*
* @param cls closure
- * @param http_status HTTP status returned by the merchant backend
- * @param ec taler-specific error code
+ * @param hr HTTP response we got
* @param taler_tip_uri URI to let the wallet know about the tip
* @param tip_id unique identifier for the tip
*/
static void
tip_authorize_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const char *taler_tip_uri,
- struct GNUNET_HashCode *tip_id)
+ const struct TALER_MERCHANT_HttpResponse *hr,
+ struct GNUNET_HashCode *tip_id,
+ const char *taler_tip_uri)
{
struct TipAuthorizeState *tas = cls;
tas->tao = NULL;
- if (tas->http_status != http_status)
+ if (tas->http_status != hr->http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u (%d)"
- " to command %s\n",
- http_status,
- ec,
- TALER_TESTING_interpreter_get_current_label
- (tas->is));
-
+ "Unexpected response code %u (%d) to command %s\n",
+ hr->http_status,
+ hr->ec,
+ TALER_TESTING_interpreter_get_current_label (tas->is));
TALER_TESTING_interpreter_fail (tas->is);
return;
}
- if (tas->expected_ec != ec)
+ if (tas->expected_ec != hr->ec)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected error code %d (%u) to command %s\n",
- ec,
- http_status,
- TALER_TESTING_interpreter_get_current_label
- (tas->is));
+ (int) hr->ec,
+ hr->http_status,
+ TALER_TESTING_interpreter_get_current_label (tas->is));
TALER_TESTING_interpreter_fail (tas->is);
return;
}
- if ( (MHD_HTTP_OK == http_status) &&
- (TALER_EC_NONE == ec) )
+ if ( (MHD_HTTP_OK == hr->http_status) &&
+ (TALER_EC_NONE == hr->ec) )
{
tas->tip_uri = strdup (taler_tip_uri);
tas->tip_id = *tip_id;
}
-
TALER_TESTING_interpreter_next (tas->is);
}
@@ -195,15 +188,14 @@ tip_authorize_run (void *cls,
&amount))
TALER_TESTING_FAIL (is);
- tas->tao = TALER_MERCHANT_tip_authorize
- (is->ctx,
- tas->merchant_url,
- "http://merchant.com/pickup",
- "http://merchant.com/continue",
- &amount,
- tas->justification,
- tip_authorize_cb,
- tas);
+ tas->tao = TALER_MERCHANT_tip_authorize (is->ctx,
+ tas->merchant_url,
+ "http://merchant.com/pickup",
+ "http://merchant.com/continue",
+ &amount,
+ tas->justification,
+ tip_authorize_cb,
+ tas);
GNUNET_assert (NULL != tas->tao);
}
@@ -272,14 +264,13 @@ tip_authorize_cleanup (void *cls,
* @param ec expected Taler-defined error code.
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_tip_authorize_with_ec
- (const char *label,
- const char *merchant_url,
- const char *exchange_url,
- unsigned int http_status,
- const char *justification,
- const char *amount,
- enum TALER_ErrorCode ec)
+TALER_TESTING_cmd_tip_authorize_with_ec (const char *label,
+ const char *merchant_url,
+ const char *exchange_url,
+ unsigned int http_status,
+ const char *justification,
+ const char *amount,
+ enum TALER_ErrorCode ec)
{
struct TipAuthorizeState *tas;
@@ -289,16 +280,17 @@ TALER_TESTING_cmd_tip_authorize_with_ec
tas->amount = amount;
tas->http_status = http_status;
tas->expected_ec = ec;
-
- struct TALER_TESTING_Command cmd = {
- .label = label,
- .cls = tas,
- .run = &tip_authorize_run,
- .cleanup = &tip_authorize_cleanup,
- .traits = &tip_authorize_traits
- };
-
- return cmd;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .label = label,
+ .cls = tas,
+ .run = &tip_authorize_run,
+ .cleanup = &tip_authorize_cleanup,
+ .traits = &tip_authorize_traits
+ };
+
+ return cmd;
+ }
}
@@ -331,16 +323,17 @@ TALER_TESTING_cmd_tip_authorize (const char *label,
tas->justification = justification;
tas->amount = amount;
tas->http_status = http_status;
-
- struct TALER_TESTING_Command cmd = {
- .label = label,
- .cls = tas,
- .run = &tip_authorize_run,
- .cleanup = &tip_authorize_cleanup,
- .traits = &tip_authorize_traits
- };
-
- return cmd;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .label = label,
+ .cls = tas,
+ .run = &tip_authorize_run,
+ .cleanup = &tip_authorize_cleanup,
+ .traits = &tip_authorize_traits
+ };
+
+ return cmd;
+ }
}
@@ -359,16 +352,17 @@ TALER_TESTING_cmd_tip_authorize_fake (const char *label)
struct TipAuthorizeState *tas;
tas = GNUNET_new (struct TipAuthorizeState);
-
- struct TALER_TESTING_Command cmd = {
- .label = label,
- .cls = tas,
- .run = &tip_authorize_fake_run,
- .cleanup = &tip_authorize_cleanup,
- .traits = &tip_authorize_traits
- };
-
- return cmd;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .label = label,
+ .cls = tas,
+ .run = &tip_authorize_fake_run,
+ .cleanup = &tip_authorize_cleanup,
+ .traits = &tip_authorize_traits
+ };
+
+ return cmd;
+ }
}
diff --git a/src/lib/testing_api_cmd_tip_pickup.c b/src/lib/testing_api_cmd_tip_pickup.c
index fb243af6..21045a22 100644
--- a/src/lib/testing_api_cmd_tip_pickup.c
+++ b/src/lib/testing_api_cmd_tip_pickup.c
@@ -210,46 +210,40 @@ pickup_withdraw_cb (void *cls,
* (and if the status was 200 OK) proceede with the withdrawal.
*
* @param cls closure
- * @param http_status HTTP status returned by the merchant
- * backend, "200 OK" on success
- * @param ec taler-specific error code
+ * @param hr HTTP response
* @param reserve_pub public key of the reserve that made the
* @a reserve_sigs, NULL on error
* @param num_reserve_sigs length of the @a reserve_sigs array,
* 0 on error
* @param reserve_sigs array of signatures authorizing withdrawals,
* NULL on error
- * @param json original json response
*/
static void
pickup_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
+ const struct TALER_MERCHANT_HttpResponse *hr,
const struct TALER_ReservePublicKeyP *reserve_pub,
unsigned int num_reserve_sigs,
- const struct TALER_ReserveSignatureP *reserve_sigs,
- const json_t *json)
+ const struct TALER_ReserveSignatureP *reserve_sigs)
{
struct TipPickupState *tps = cls;
tps->tpo = NULL;
- if (http_status != tps->http_status)
+ if (hr->http_status != tps->http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u (%d) to command %s\n",
- http_status,
- ec,
- TALER_TESTING_interpreter_get_current_label
- (tps->is));
+ hr->http_status,
+ (int) hr->ec,
+ TALER_TESTING_interpreter_get_current_label (tps->is));
TALER_TESTING_FAIL (tps->is);
}
- if (ec != tps->expected_ec)
+ if (hr->ec != tps->expected_ec)
TALER_TESTING_FAIL (tps->is);
/* Safe to go ahead: http status was expected. */
- if ( (MHD_HTTP_OK != http_status) ||
- (TALER_EC_NONE != ec) )
+ if ( (MHD_HTTP_OK != hr->http_status) ||
+ (TALER_EC_NONE != hr->ec) )
{
TALER_TESTING_interpreter_next (tps->is);
return;
@@ -259,13 +253,12 @@ pickup_cb (void *cls,
/* pickup successful, now withdraw! */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Obtained %u signatures for withdrawal"
- " from picking up a tip\n",
+ "Obtained %u signatures for withdrawal from picking up a tip\n",
num_reserve_sigs);
GNUNET_assert (NULL == tps->withdraws);
- tps->withdraws = GNUNET_new_array
- (num_reserve_sigs, struct WithdrawHandle);
+ tps->withdraws = GNUNET_new_array (num_reserve_sigs,
+ struct WithdrawHandle);
for (unsigned int i = 0; i<num_reserve_sigs; i++)
{
@@ -274,18 +267,16 @@ pickup_cb (void *cls,
wh->off = i;
wh->is = tps->is;
wh->tps = tps;
- GNUNET_assert
- ( (NULL == wh->wsh) &&
- ( (NULL == tps->sigs) ||
- (NULL == tps->sigs[wh->off].rsa_signature) ) );
- wh->wsh = TALER_EXCHANGE_withdraw2
- (tps->is->exchange,
- tps->dks[i],
- &reserve_sigs[i],
- reserve_pub,
- &tps->psa[i],
- &pickup_withdraw_cb,
- wh);
+ GNUNET_assert ( (NULL == wh->wsh) &&
+ ( (NULL == tps->sigs) ||
+ (NULL == tps->sigs[wh->off].rsa_signature) ) );
+ wh->wsh = TALER_EXCHANGE_withdraw2 (tps->is->exchange,
+ tps->dks[i],
+ &reserve_sigs[i],
+ reserve_pub,
+ &tps->psa[i],
+ &pickup_withdraw_cb,
+ wh);
if (NULL == wh->wsh)
TALER_TESTING_FAIL (tps->is);
}
@@ -327,20 +318,25 @@ tip_pickup_run (void *cls,
else
{
const unsigned int *np;
+
if (NULL == /* looking for "parent" tip-pickup command */
- (replay_cmd = TALER_TESTING_interpreter_lookup_command
- (is, tps->replay_reference)) )
+ (replay_cmd
+ = TALER_TESTING_interpreter_lookup_command (is,
+ tps->replay_reference)) )
TALER_TESTING_FAIL (is);
- if (GNUNET_OK != TALER_TESTING_get_trait_uint
- (replay_cmd, 0, &np))
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_uint (replay_cmd,
+ 0,
+ &np))
TALER_TESTING_FAIL (is);
num_planchets = *np;
}
if (NULL ==
- (authorize_cmd = TALER_TESTING_interpreter_lookup_command
- (is, tps->authorize_reference)) )
+ (authorize_cmd
+ = TALER_TESTING_interpreter_lookup_command (is,
+ tps->authorize_reference)) )
TALER_TESTING_FAIL (is);
tps->num_coins = num_planchets;
@@ -349,51 +345,51 @@ tip_pickup_run (void *cls,
tps->psa = GNUNET_new_array (num_planchets,
struct TALER_PlanchetSecretsP);
- tps->dks = GNUNET_new_array
- (num_planchets,
- const struct TALER_EXCHANGE_DenomPublicKey *);
-
- tps->amounts_obj = GNUNET_new_array
- (num_planchets, struct TALER_Amount);
+ tps->dks = GNUNET_new_array (num_planchets,
+ const struct TALER_EXCHANGE_DenomPublicKey *);
+ tps->amounts_obj = GNUNET_new_array (num_planchets,
+ struct TALER_Amount);
for (unsigned int i = 0; i<num_planchets; i++)
{
if (NULL == replay_cmd)
{
- GNUNET_assert (GNUNET_OK == TALER_string_to_amount
- (tps->amounts[i], &tps->amounts_obj[i]));
-
- tps->dks[i] = TALER_TESTING_find_pk
- (is->keys,
- &tps->amounts_obj[i]);
-
+ GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount (tps->amounts[i],
+ &tps->amounts_obj[i]));
+ tps->dks[i] = TALER_TESTING_find_pk (is->keys,
+ &tps->amounts_obj[i]);
if (NULL == tps->dks[i])
TALER_TESTING_FAIL (is);
-
TALER_planchet_setup_random (&tps->psa[i]);
}
else
{
- if (GNUNET_OK != TALER_TESTING_get_trait_denom_pub
- (replay_cmd, i, &tps->dks[i]))
- TALER_TESTING_FAIL (is);
-
struct TALER_PlanchetSecretsP *ps;
- if (GNUNET_OK != TALER_TESTING_get_trait_planchet_secrets
- (replay_cmd, i, &ps))
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_denom_pub (replay_cmd,
+ i,
+ &tps->dks[i]))
+ TALER_TESTING_FAIL (is);
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_planchet_secrets (replay_cmd,
+ i,
+ &ps))
TALER_TESTING_FAIL (is);
tps->psa[i] = *ps;
}
- if (GNUNET_OK != TALER_planchet_prepare (&tps->dks[i]->key,
- &tps->psa[i],
- &planchets[i]))
+ if (GNUNET_OK !=
+ TALER_planchet_prepare (&tps->dks[i]->key,
+ &tps->psa[i],
+ &planchets[i]))
TALER_TESTING_FAIL (is);
}
-
- if (GNUNET_OK != TALER_TESTING_get_trait_tip_id
- (authorize_cmd, 0, &tip_id))
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_tip_id (authorize_cmd,
+ 0,
+ &tip_id))
TALER_TESTING_FAIL (is);
tps->tpo = TALER_MERCHANT_tip_pickup (is->ctx,
@@ -438,14 +434,11 @@ tip_pickup_cleanup (void *cls,
GNUNET_CRYPTO_rsa_signature_free (tps->sigs[i].rsa_signature);
GNUNET_free (tps->sigs);
}
-
if (NULL != tps->tpo)
{
- TALER_LOG_WARNING ("Tip-pickup operation"
- " did not complete\n");
+ TALER_LOG_WARNING ("Tip-pickup operation did not complete\n");
TALER_MERCHANT_tip_pickup_cancel (tps->tpo);
}
-
GNUNET_free (tps);
}
@@ -472,24 +465,21 @@ tip_pickup_traits (void *cls,
for (unsigned int i = 0; i<tps->num_coins; i++)
{
- traits[i] = TALER_TESTING_make_trait_planchet_secrets
- (i, &tps->psa[i]);
+ traits[i] = TALER_TESTING_make_trait_planchet_secrets (i,
+ &tps->psa[i]);
traits[i + tps->num_coins] =
- TALER_TESTING_make_trait_coin_priv
- (i, &tps->psa[i].coin_priv);
+ TALER_TESTING_make_trait_coin_priv (i, &tps->psa[i].coin_priv);
traits[i + (tps->num_coins * 2)] =
TALER_TESTING_make_trait_denom_pub (i, tps->dks[i]);
traits[i + (tps->num_coins * 3)] =
TALER_TESTING_make_trait_denom_sig (i, &tps->sigs[i]);
traits[i + (tps->num_coins * 4)] =
- TALER_TESTING_make_trait_amount_obj
- (i, &tps->amounts_obj[i]);
+ TALER_TESTING_make_trait_amount_obj (i, &tps->amounts_obj[i]);
}
- traits[NUM_TRAITS - 2] = TALER_TESTING_make_trait_url
- (TALER_TESTING_UT_EXCHANGE_BASE_URL,
- tps->exchange_url);
+ traits[NUM_TRAITS - 2]
+ = TALER_TESTING_make_trait_url (TALER_TESTING_UT_EXCHANGE_BASE_URL,
+ tps->exchange_url);
traits[NUM_TRAITS - 1] = TALER_TESTING_trait_end ();
-
return TALER_TESTING_get_trait (traits,
ret,
trait,
@@ -514,13 +504,12 @@ tip_pickup_traits (void *cls,
* @param ec expected Taler error code.
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_tip_pickup_with_ec
- (const char *label,
- const char *merchant_url,
- unsigned int http_status,
- const char *authorize_reference,
- const char **amounts,
- enum TALER_ErrorCode ec)
+TALER_TESTING_cmd_tip_pickup_with_ec (const char *label,
+ const char *merchant_url,
+ unsigned int http_status,
+ const char *authorize_reference,
+ const char **amounts,
+ enum TALER_ErrorCode ec)
{
struct TipPickupState *tps;
@@ -530,16 +519,17 @@ TALER_TESTING_cmd_tip_pickup_with_ec
tps->amounts = amounts;
tps->http_status = http_status;
tps->expected_ec = ec;
-
- struct TALER_TESTING_Command cmd = {
- .cls = tps,
- .label = label,
- .run = &tip_pickup_run,
- .cleanup = &tip_pickup_cleanup,
- .traits = &tip_pickup_traits
- };
-
- return cmd;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .cls = tps,
+ .label = label,
+ .run = &tip_pickup_run,
+ .cleanup = &tip_pickup_cleanup,
+ .traits = &tip_pickup_traits
+ };
+
+ return cmd;
+ }
}
@@ -556,12 +546,11 @@ TALER_TESTING_cmd_tip_pickup_with_ec
* which denominations will be accepted for tipping.
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_tip_pickup
- (const char *label,
- const char *merchant_url,
- unsigned int http_status,
- const char *authorize_reference,
- const char **amounts)
+TALER_TESTING_cmd_tip_pickup (const char *label,
+ const char *merchant_url,
+ unsigned int http_status,
+ const char *authorize_reference,
+ const char **amounts)
{
struct TipPickupState *tps;
@@ -570,16 +559,17 @@ TALER_TESTING_cmd_tip_pickup
tps->authorize_reference = authorize_reference;
tps->amounts = amounts;
tps->http_status = http_status;
-
- struct TALER_TESTING_Command cmd = {
- .cls = tps,
- .label = label,
- .run = &tip_pickup_run,
- .cleanup = &tip_pickup_cleanup,
- .traits = &tip_pickup_traits
- };
-
- return cmd;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .cls = tps,
+ .label = label,
+ .run = &tip_pickup_run,
+ .cleanup = &tip_pickup_cleanup,
+ .traits = &tip_pickup_traits
+ };
+
+ return cmd;
+ }
}
diff --git a/src/lib/testing_api_cmd_tip_query.c b/src/lib/testing_api_cmd_tip_query.c
index 114bde79..70e59c12 100644
--- a/src/lib/testing_api_cmd_tip_query.c
+++ b/src/lib/testing_api_cmd_tip_query.c
@@ -80,9 +80,7 @@ struct TipQueryState
* expectations.
*
* @param cls closure
- * @param http_status HTTP status code for this request
- * @param ec Taler-specific error code
- * @param raw raw response body
+ * @param hr HTTP response
* @param reserve_expiration when the tip reserve will expire
* @param reserve_pub tip reserve public key
* @param amount_authorized total amount authorized on tip reserve
@@ -92,9 +90,7 @@ struct TipQueryState
*/
static void
tip_query_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const json_t *raw,
+ const struct TALER_MERCHANT_HttpResponse *hr,
struct GNUNET_TIME_Absolute reserve_expiration,
struct TALER_ReservePublicKeyP *reserve_pub,
struct TALER_Amount *amount_authorized,
@@ -107,9 +103,7 @@ tip_query_cb (void *cls,
tqs->tqo = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Tip query callback at command `%s'\n",
- TALER_TESTING_interpreter_get_current_label
- (tqs->is));
-
+ TALER_TESTING_interpreter_get_current_label (tqs->is));
GNUNET_assert (NULL != reserve_pub);
GNUNET_assert (NULL != amount_authorized);
GNUNET_assert (NULL != amount_available);
@@ -117,8 +111,9 @@ tip_query_cb (void *cls,
if (tqs->expected_amount_available)
{
- GNUNET_assert (GNUNET_OK == TALER_string_to_amount
- (tqs->expected_amount_available, &a));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount (tqs->expected_amount_available,
+ &a));
{
char *str;
@@ -128,46 +123,50 @@ tip_query_cb (void *cls,
str);
GNUNET_free (str);
}
- if (0 != TALER_amount_cmp (amount_available, &a))
+ if (0 !=
+ TALER_amount_cmp (amount_available,
+ &a))
TALER_TESTING_FAIL (tqs->is);
}
if (tqs->expected_amount_authorized)
{
- GNUNET_assert (GNUNET_OK == TALER_string_to_amount
- (tqs->expected_amount_authorized, &a));
- {
- char *str;
-
- str = TALER_amount_to_string (amount_authorized);
- TALER_LOG_INFO ("expected authorized %s, actual %s\n",
- TALER_amount2s (&a),
- str);
- GNUNET_free (str);
- }
- if (0 != TALER_amount_cmp (amount_authorized, &a))
+ char *str;
+
+ GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount (tqs->expected_amount_authorized,
+ &a));
+ str = TALER_amount_to_string (amount_authorized);
+ TALER_LOG_INFO ("expected authorized %s, actual %s\n",
+ TALER_amount2s (&a),
+ str);
+ GNUNET_free (str);
+ if (0 !=
+ TALER_amount_cmp (amount_authorized,
+ &a))
TALER_TESTING_FAIL (tqs->is);
}
if (tqs->expected_amount_picked_up)
{
- GNUNET_assert (GNUNET_OK == TALER_string_to_amount
- (tqs->expected_amount_picked_up, &a));
- {
- char *str;
- str = TALER_amount_to_string (amount_picked_up);
- TALER_LOG_INFO ("expected picked_up %s, actual %s\n",
- TALER_amount2s (&a),
- str);
- GNUNET_free (str);
- }
- if (0 != TALER_amount_cmp (amount_picked_up, &a))
+ char *str;
+
+ GNUNET_assert (GNUNET_OK ==
+ TALER_string_to_amount (tqs->expected_amount_picked_up,
+ &a));
+ str = TALER_amount_to_string (amount_picked_up);
+ TALER_LOG_INFO ("expected picked_up %s, actual %s\n",
+ TALER_amount2s (&a),
+ str);
+ GNUNET_free (str);
+ if (0 !=
+ TALER_amount_cmp (amount_picked_up,
+ &a))
TALER_TESTING_FAIL (tqs->is);
}
- if (tqs->http_status != http_status)
+ if (tqs->http_status != hr->http_status)
TALER_TESTING_FAIL (tqs->is);
-
TALER_TESTING_interpreter_next (tqs->is);
}
@@ -235,13 +234,12 @@ tip_query_run (void *cls,
* @return the command
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_tip_query_with_amounts
- (const char *label,
- const char *merchant_url,
- unsigned int http_status,
- const char *expected_amount_picked_up,
- const char *expected_amount_authorized,
- const char *expected_amount_available)
+TALER_TESTING_cmd_tip_query_with_amounts (const char *label,
+ const char *merchant_url,
+ unsigned int http_status,
+ const char *expected_amount_picked_up,
+ const char *expected_amount_authorized,
+ const char *expected_amount_available)
{
struct TipQueryState *tqs;
@@ -251,15 +249,16 @@ TALER_TESTING_cmd_tip_query_with_amounts
tqs->expected_amount_picked_up = expected_amount_picked_up;
tqs->expected_amount_authorized = expected_amount_authorized;
tqs->expected_amount_available = expected_amount_available;
-
- struct TALER_TESTING_Command cmd = {
- .cls = tqs,
- .label = label,
- .run = &tip_query_run,
- .cleanup = &tip_query_cleanup
- };
-
- return cmd;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .cls = tqs,
+ .label = label,
+ .run = &tip_query_run,
+ .cleanup = &tip_query_cleanup
+ };
+
+ return cmd;
+ }
}
@@ -282,15 +281,16 @@ TALER_TESTING_cmd_tip_query (const char *label,
tqs = GNUNET_new (struct TipQueryState);
tqs->merchant_url = merchant_url;
tqs->http_status = http_status;
-
- struct TALER_TESTING_Command cmd = {
- .cls = tqs,
- .label = label,
- .run = &tip_query_run,
- .cleanup = &tip_query_cleanup
- };
-
- return cmd;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .cls = tqs,
+ .label = label,
+ .run = &tip_query_run,
+ .cleanup = &tip_query_cleanup
+ };
+
+ return cmd;
+ }
}
diff --git a/src/lib/testing_api_cmd_track_transaction.c b/src/lib/testing_api_cmd_track_transaction.c
index 8ae0a95c..e128ce5b 100644
--- a/src/lib/testing_api_cmd_track_transaction.c
+++ b/src/lib/testing_api_cmd_track_transaction.c
@@ -91,35 +91,29 @@ struct TrackTransactionState
* in the state what came from the backend.
*
* @param cls closure
- * @param http_status HTTP status code we got,
- * 0 on exchange protocol violation
- * @param ec taler-specific error code
- * @param json original json reply
+ * @param hr HTTP response
*/
static void
track_transaction_cb (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const json_t *json)
+ const struct TALER_MERCHANT_HttpResponse *hr)
{
struct TrackTransactionState *tts = cls;
tts->tth = NULL;
- if (tts->http_status != http_status)
+ if (tts->http_status != hr->http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u (%d) to command %s\n",
- http_status,
- ec,
- TALER_TESTING_interpreter_get_current_label
- (tts->is));
+ hr->http_status,
+ (int) hr->ec,
+ TALER_TESTING_interpreter_get_current_label (tts->is));
TALER_TESTING_interpreter_fail (tts->is);
return;
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"/track/transaction, response code: %u\n",
- http_status);
- if (MHD_HTTP_OK == http_status)
+ hr->http_status);
+ if (MHD_HTTP_OK == hr->http_status)
{
/* Only storing first element's wtid, as this works around
* the disability of the real bank to provide a "bank check"
@@ -127,25 +121,26 @@ track_transaction_cb (void *cls,
json_t *wtid_str;
json_t *exchange_url;
- if (NULL == (wtid_str = json_object_get
- (json_array_get (json, 0), "wtid")))
+ if (NULL == (wtid_str
+ = json_object_get (json_array_get (hr->reply,
+ 0),
+ "wtid")))
{
TALER_TESTING_interpreter_fail (tts->is);
return;
}
- if (NULL == (exchange_url = json_object_get
- (json_array_get (json, 0), "exchange")))
+ if (NULL == (exchange_url
+ = json_object_get (json_array_get (hr->reply,
+ 0),
+ "exchange")))
{
-
TALER_TESTING_interpreter_fail (tts->is);
return;
}
- tts->exchange_url = GNUNET_strdup
- (json_string_value (exchange_url));
- tts->wtid_str = GNUNET_strdup
- (json_string_value (wtid_str));
+ tts->exchange_url = GNUNET_strdup (json_string_value (exchange_url));
+ tts->wtid_str = GNUNET_strdup (json_string_value (wtid_str));
}
TALER_TESTING_interpreter_next (tts->is);
}
@@ -169,21 +164,20 @@ track_transaction_run (void *cls,
tts->is = is;
if (NULL ==
- (pay_cmd = TALER_TESTING_interpreter_lookup_command
- (is, tts->pay_reference)))
+ (pay_cmd = TALER_TESTING_interpreter_lookup_command (is,
+ tts->pay_reference)))
TALER_TESTING_FAIL (is);
-
- if (GNUNET_OK != TALER_TESTING_get_trait_order_id
- (pay_cmd, 0, &order_id))
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_order_id (pay_cmd,
+ 0,
+ &order_id))
TALER_TESTING_FAIL (is);
- tts->tth = TALER_MERCHANT_track_transaction
- (is->ctx,
- tts->merchant_url,
- order_id,
- &track_transaction_cb,
- tts);
-
+ tts->tth = TALER_MERCHANT_track_transaction (is->ctx,
+ tts->merchant_url,
+ order_id,
+ &track_transaction_cb,
+ tts);
GNUNET_assert (NULL != tts->tth);
}
@@ -212,7 +206,6 @@ track_transaction_cleanup (void *cls,
/* Need to discard 'const' before freeing. */
GNUNET_free_non_null ((char *) tts->exchange_url);
GNUNET_free_non_null ((char *) tts->wtid_str);
-
GNUNET_free (tts);
}
@@ -236,26 +229,27 @@ track_transaction_traits (void *cls,
struct TrackTransactionState *tts = cls;
struct TALER_WireTransferIdentifierRawP *wtid_ptr;
- if (GNUNET_OK != GNUNET_STRINGS_string_to_data
- (tts->wtid_str,
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (
+ tts->wtid_str,
strlen (tts->wtid_str),
&tts->wtid,
sizeof (struct TALER_WireTransferIdentifierRawP)))
wtid_ptr = NULL;
else
wtid_ptr = &tts->wtid;
-
- struct TALER_TESTING_Trait traits[] = {
- TALER_TESTING_make_trait_wtid (0, wtid_ptr),
- TALER_TESTING_make_trait_url (0, tts->exchange_url),
- TALER_TESTING_trait_end ()
- };
-
- return TALER_TESTING_get_trait (traits,
- ret,
- trait,
- index);
- return GNUNET_SYSERR;
+ {
+ struct TALER_TESTING_Trait traits[] = {
+ TALER_TESTING_make_trait_wtid (0, wtid_ptr),
+ TALER_TESTING_make_trait_url (0, tts->exchange_url),
+ TALER_TESTING_trait_end ()
+ };
+
+ return TALER_TESTING_get_trait (traits,
+ ret,
+ trait,
+ index);
+ }
}
@@ -270,11 +264,10 @@ track_transaction_traits (void *cls,
* @return the command.
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_merchant_track_transaction
- (const char *label,
- const char *merchant_url,
- unsigned int http_status,
- const char *pay_reference)
+TALER_TESTING_cmd_merchant_track_transaction (const char *label,
+ const char *merchant_url,
+ unsigned int http_status,
+ const char *pay_reference)
{
struct TrackTransactionState *tts;
@@ -282,16 +275,17 @@ TALER_TESTING_cmd_merchant_track_transaction
tts->merchant_url = merchant_url;
tts->http_status = http_status;
tts->pay_reference = pay_reference;
-
- struct TALER_TESTING_Command cmd = {
- .cls = tts,
- .label = label,
- .run = &track_transaction_run,
- .cleanup = &track_transaction_cleanup,
- .traits = &track_transaction_traits
- };
-
- return cmd;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .cls = tts,
+ .label = label,
+ .run = &track_transaction_run,
+ .cleanup = &track_transaction_cleanup,
+ .traits = &track_transaction_traits
+ };
+
+ return cmd;
+ }
}
diff --git a/src/lib/testing_api_cmd_track_transfer.c b/src/lib/testing_api_cmd_track_transfer.c
index a5796217..195d50b3 100644
--- a/src/lib/testing_api_cmd_track_transfer.c
+++ b/src/lib/testing_api_cmd_track_transfer.c
@@ -85,33 +85,29 @@ struct TrackTransferState
* transactions
*/
static void
-track_transfer_cb
- (void *cls,
- unsigned int http_status,
- enum TALER_ErrorCode ec,
- const struct TALER_ExchangePublicKeyP *sign_key,
- const json_t *json,
- const struct GNUNET_HashCode *h_wire,
- const struct TALER_Amount *total_amount,
- unsigned int details_length,
- const struct TALER_MERCHANT_TrackTransferDetails *details)
+track_transfer_cb (void *cls,
+ const struct TALER_MERCHANT_HttpResponse *hr,
+ const struct TALER_ExchangePublicKeyP *sign_key,
+ const struct GNUNET_HashCode *h_wire,
+ const struct TALER_Amount *total_amount,
+ unsigned int details_length,
+ const struct TALER_MERCHANT_TrackTransferDetails *details)
{
/* FIXME, deeper checks should be implemented here. */
struct TrackTransferState *tts = cls;
tts->tth = NULL;
- if (tts->http_status != http_status)
+ if (tts->http_status != hr->http_status)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Unexpected response code %u (%d) to command %s\n",
- http_status,
- ec,
- TALER_TESTING_interpreter_get_current_label
- (tts->is));
+ hr->http_status,
+ (int) hr->ec,
+ TALER_TESTING_interpreter_get_current_label (tts->is));
TALER_TESTING_interpreter_fail (tts->is);
return;
}
- switch (http_status)
+ switch (hr->http_status)
{
/**
* Check that all the deposits sum up to the total
@@ -128,9 +124,8 @@ track_transfer_cb
size_t index;
json_t *value;
- amount_str = json_string_value
- (json_object_get (json,
- "total"));
+ amount_str = json_string_value (json_object_get (hr->reply,
+ "total"));
if (GNUNET_OK !=
TALER_string_to_amount (amount_str,
&total))
@@ -141,9 +136,8 @@ track_transfer_cb
TALER_TESTING_FAIL (tts->is);
return;
}
- amount_str = json_string_value
- (json_object_get (json,
- "wire_fee"));
+ amount_str = json_string_value (json_object_get (hr->reply,
+ "wire_fee"));
if (GNUNET_OK !=
TALER_string_to_amount (amount_str,
&wire_fee))
@@ -157,13 +151,12 @@ track_transfer_cb
GNUNET_assert (GNUNET_OK ==
TALER_amount_get_zero (total.currency,
&sum));
- deposits = json_object_get (json,
+ deposits = json_object_get (hr->reply,
"deposits_sums");
json_array_foreach (deposits, index, value)
{
- amount_str = json_string_value
- (json_object_get (value,
- "deposit_value"));
+ amount_str = json_string_value (json_object_get (value,
+ "deposit_value"));
if (GNUNET_OK !=
TALER_string_to_amount (amount_str,
&amount_iter))
@@ -174,9 +167,8 @@ track_transfer_cb
TALER_TESTING_FAIL (tts->is);
return;
}
- amount_str = json_string_value
- (json_object_get (value,
- "deposit_fee"));
+ amount_str = json_string_value (json_object_get (value,
+ "deposit_fee"));
if (GNUNET_OK !=
TALER_string_to_amount (amount_str,
&deposit_fee_iter))
@@ -205,9 +197,8 @@ track_transfer_cb
&total))
{
GNUNET_break (0);
- TALER_LOG_ERROR
- ("Inconsistent amount transferred."
- " Sum: %s, claimed: %s\n",
+ TALER_LOG_ERROR (
+ "Inconsistent amount transferred: Sum %s, claimed %s\n",
TALER_amount_to_string (&sum),
TALER_amount_to_string (&total));
TALER_TESTING_interpreter_fail (tts->is);
@@ -241,15 +232,20 @@ track_transfer_run (void *cls,
const char *exchange_url;
tts->is = is;
- check_bank_cmd = TALER_TESTING_interpreter_lookup_command
- (is, tts->check_bank_reference);
+ check_bank_cmd
+ = TALER_TESTING_interpreter_lookup_command (is,
+ tts->check_bank_reference);
if (NULL == check_bank_cmd)
TALER_TESTING_FAIL (is);
- if (GNUNET_OK != TALER_TESTING_get_trait_wtid
- (check_bank_cmd, 0, &wtid))
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_wtid (check_bank_cmd,
+ 0,
+ &wtid))
TALER_TESTING_FAIL (is);
- if (GNUNET_OK != TALER_TESTING_get_trait_url
- (check_bank_cmd, TALER_TESTING_UT_EXCHANGE_BASE_URL, &exchange_url))
+ if (GNUNET_OK !=
+ TALER_TESTING_get_trait_url (check_bank_cmd,
+ TALER_TESTING_UT_EXCHANGE_BASE_URL,
+ &exchange_url))
TALER_TESTING_FAIL (is);
tts->tth = TALER_MERCHANT_track_transfer (is->ctx,
tts->merchant_url,
@@ -299,11 +295,10 @@ track_transfer_cleanup (void *cls,
* @return the command.
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_merchant_track_transfer
- (const char *label,
- const char *merchant_url,
- unsigned int http_status,
- const char *check_bank_reference)
+TALER_TESTING_cmd_merchant_track_transfer (const char *label,
+ const char *merchant_url,
+ unsigned int http_status,
+ const char *check_bank_reference)
{
struct TrackTransferState *tts;
@@ -311,15 +306,16 @@ TALER_TESTING_cmd_merchant_track_transfer
tts->merchant_url = merchant_url;
tts->http_status = http_status;
tts->check_bank_reference = check_bank_reference;
+ {
+ struct TALER_TESTING_Command cmd = {
+ .cls = tts,
+ .label = label,
+ .run = &track_transfer_run,
+ .cleanup = &track_transfer_cleanup
+ };
- struct TALER_TESTING_Command cmd = {
- .cls = tts,
- .label = label,
- .run = &track_transfer_run,
- .cleanup = &track_transfer_cleanup
- };
-
- return cmd;
+ return cmd;
+ }
}