merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

commit b79fdc1a77ae3dc564e1205f9875ff9e1b0d0712
parent 5774dbd64e961f7d50933df711183cf6f194a14a
Author: Marcello Stanisci <marcello.stanisci@inria.fr>
Date:   Fri, 21 Oct 2016 10:37:20 +0200

Merge branch 'master' of taler.net:merchant

Diffstat:
Msrc/backend/taler-merchant-httpd_pay.c | 8++++----
Msrc/backend/taler-merchant-httpd_responses.c | 3++-
Msrc/backend/taler-merchant-httpd_track-transaction.c | 21+++++++++++++++------
Msrc/backend/taler-merchant-httpd_track-transfer.c | 25+++++++++++++++++--------
Msrc/include/taler_merchant_service.h | 11+++++++++++
Msrc/lib/merchant_api_contract.c | 1+
Msrc/lib/merchant_api_history.c | 16++++++++++------
Msrc/lib/merchant_api_pay.c | 1+
Msrc/lib/merchant_api_track_transaction.c | 2++
Msrc/lib/merchant_api_track_transfer.c | 2++
Msrc/lib/test_merchant_api.c | 17++++++++++++++++-
11 files changed, 81 insertions(+), 26 deletions(-)

diff --git a/src/backend/taler-merchant-httpd_pay.c b/src/backend/taler-merchant-httpd_pay.c @@ -337,6 +337,7 @@ abort_deposit (struct PayContext *pc) * @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 code, #TALER_EC_NONE on success * @param sign_key which key did the exchange use to sign the @a proof * @param proof the received JSON reply, * should be kept as proof (and, in case of errors, be forwarded to @@ -345,6 +346,7 @@ abort_deposit (struct PayContext *pc) static void deposit_cb (void *cls, unsigned int http_status, + enum TALER_ErrorCode ec, const struct TALER_ExchangePublicKeyP *sign_key, const json_t *proof) { @@ -366,12 +368,12 @@ deposit_cb (void *cls, if (NULL == proof) { /* We can't do anything meaningful here, the exchange did something wrong */ - /* FIXME: any useful information we can include? */ resume_pay_with_response (pc, MHD_HTTP_SERVICE_UNAVAILABLE, TMH_RESPONSE_make_json_pack ("{s:s, s:I, s:I, s:s}", "error", "exchange failed", "code", (json_int_t) TALER_EC_PAY_EXCHANGE_FAILED, + "exchange-code", (json_int_t) ec, "exchange-http-status", (json_int_t) http_status, "hint", "The exchange provided an unexpected response")); } @@ -926,9 +928,7 @@ MH_handler_pay (struct TMH_RequestHandler *rh, if (GNUNET_SYSERR == res) { GNUNET_break (0); - return TMH_RESPONSE_reply_external_error (connection, - TALER_EC_JSON_INVALID, - "failed to parse JSON body"); + return TMH_RESPONSE_reply_invalid_json (connection); } if ((GNUNET_NO == res) || (NULL == root)) return MHD_YES; /* the POST's body has to be further fetched */ diff --git a/src/backend/taler-merchant-httpd_responses.c b/src/backend/taler-merchant-httpd_responses.c @@ -245,7 +245,8 @@ TMH_RESPONSE_reply_invalid_json (struct MHD_Connection *connection) { return TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_BAD_REQUEST, - "{s:s}", + "{s:I, s:s}", + "code", (json_int_t) TALER_EC_JSON_INVALID, "error", "invalid json"); } diff --git a/src/backend/taler-merchant-httpd_track-transaction.c b/src/backend/taler-merchant-httpd_track-transaction.c @@ -331,6 +331,7 @@ trace_coins (struct TrackTransactionContext *tctx); * * @param cls closure * @param http_status HTTP status code we got, 0 on exchange protocol violation + * @param ec taler-specific error code * @param exchange_pub public key of the exchange used for signing * @param json original json reply (may include signatures, those have then been * validated already) @@ -345,6 +346,7 @@ trace_coins (struct TrackTransactionContext *tctx); static void wire_deposits_cb (void *cls, unsigned int http_status, + enum TALER_ErrorCode ec, const struct TALER_ExchangePublicKeyP *exchange_pub, const json_t *json, const struct GNUNET_HashCode *h_wire, @@ -363,8 +365,10 @@ wire_deposits_cb (void *cls, resume_track_transaction_with_response (tctx, MHD_HTTP_FAILED_DEPENDENCY, - TMH_RESPONSE_make_json_pack ("{s:I, s:O}", - "exchange_status", (json_int_t) http_status, + TMH_RESPONSE_make_json_pack ("{s:I, s:I, s:I, s:O}", + "code", (json_int_t) TALER_EC_TRACK_TRANSACTION_WIRE_TRANSFER_TRACE_ERROR, + "exchange-http-status", (json_int_t) http_status, + "exchange-code", (json_int_t) ec, "details", json)); return; } @@ -454,6 +458,7 @@ proof_cb (void *cls, * * @param cls closure with a `struct TrackCoinContext` * @param http_status HTTP status code we got, 0 on exchange protocol violation + * @param ec taler-specific error code, #TALER_EC_NONE on success * @param exchange_pub public key of the exchange used for signing @a json * @param json original json reply (may include signatures, those have then been * validated already), should be a `TrackTransactionResponse` @@ -466,6 +471,7 @@ proof_cb (void *cls, static void wtid_cb (void *cls, unsigned int http_status, + enum TALER_ErrorCode ec, const struct TALER_ExchangePublicKeyP *exchange_pub, const json_t *json, const struct TALER_WireTransferIdentifierRawP *wtid, @@ -487,8 +493,10 @@ wtid_cb (void *cls, (MHD_HTTP_ACCEPTED == http_status) ? MHD_HTTP_ACCEPTED : MHD_HTTP_FAILED_DEPENDENCY, - TMH_RESPONSE_make_json_pack ("{s:I, s:O}", - "exchange_status", (json_int_t) http_status, + TMH_RESPONSE_make_json_pack ("{s:I, s:I, s:I, s:O}", + "code", (json_int_t) TALER_EC_TRACK_TRANSACTION_COIN_TRACE_ERROR, + "exchange-http-status", (json_int_t) http_status, + "exchange-code", (json_int_t) ec, "details", json)); return; } @@ -505,8 +513,9 @@ wtid_cb (void *cls, GNUNET_break_op (0); resume_track_transaction_with_response (tcc->tctx, - MHD_HTTP_CONFLICT, - TMH_RESPONSE_make_json_pack ("{s:s, s:O, s:o, s:o}", + MHD_HTTP_FAILED_DEPENDENCY, + TMH_RESPONSE_make_json_pack ("{s:I, s:s, s:O, s:o, s:o}", + "code", (json_int_t) TALER_EC_TRACK_TRANSACTION_CONFLICTING_REPORTS, "error", "conflicting transfer data from exchange", "transaction_tracking_claim", json, "wtid_tracking_claim", pcc.p_ret, diff --git a/src/backend/taler-merchant-httpd_track-transfer.c b/src/backend/taler-merchant-httpd_track-transfer.c @@ -258,6 +258,7 @@ check_transfer (void *cls, * * @param cls closure * @param http_status HTTP status code we got, 0 on exchange protocol violation + * @param ec taler-specific error code for the operation, #TALER_EC_NONE on success * @param exchange_pub public key of the exchange used to sign @a json * @param json original json reply (may include signatures, those have then been * validated already) @@ -271,6 +272,7 @@ check_transfer (void *cls, static void wire_transfer_cb (void *cls, unsigned int http_status, + enum TALER_ErrorCode ec, const struct TALER_ExchangePublicKeyP *exchange_pub, const json_t *json, const struct GNUNET_HashCode *h_wire, @@ -292,8 +294,10 @@ wire_transfer_cb (void *cls, resume_track_transfer_with_response (rctx, MHD_HTTP_FAILED_DEPENDENCY, - TMH_RESPONSE_make_json_pack ("{s:I, s:O}", - "exchange_status", (json_int_t) http_status, + TMH_RESPONSE_make_json_pack ("{s:I, s:I, s:I, s:O}", + "code", (json_int_t) TALER_EC_TRACK_TRANSFER_EXCHANGE_ERROR, + "exchange-code", (json_int_t) ec, + "exchange-http-status", (json_int_t) http_status, "details", json)); return; } @@ -311,7 +315,8 @@ wire_transfer_cb (void *cls, resume_track_transfer_with_response (rctx, MHD_HTTP_INTERNAL_SERVER_ERROR, - TMH_RESPONSE_make_json_pack ("{s:s}", + TMH_RESPONSE_make_json_pack ("{s:I, s:s}", + "code", (json_int_t) TALER_EC_TRACK_TRANSFER_DB_STORE_TRANSER_ERROR, "details", "failed to store response from exchange to local database")); return; } @@ -334,7 +339,8 @@ wire_transfer_cb (void *cls, resume_track_transfer_with_response (rctx, MHD_HTTP_INTERNAL_SERVER_ERROR, - TMH_RESPONSE_make_json_pack ("{s:s}", + TMH_RESPONSE_make_json_pack ("{s:I, s:s}", + "code", (json_int_t) TALER_EC_TRACK_TRANSFER_DB_FETCH_DEPOSIT_ERROR, "details", "failed to obtain deposit data from local database")); return; } @@ -355,7 +361,8 @@ wire_transfer_cb (void *cls, resume_track_transfer_with_response (rctx, MHD_HTTP_INTERNAL_SERVER_ERROR, - TMH_RESPONSE_make_json_pack ("{s:s, s:I, s:s}", + TMH_RESPONSE_make_json_pack ("{s:I, s:s, s:I, s:s}", + "code", (json_int_t) TALER_EC_TRACK_TRANSFER_DB_INTERNAL_LOGIC_ERROR, "details", "internal logic error", "line", (json_int_t) __LINE__, "file", __FILE__)); @@ -368,7 +375,7 @@ wire_transfer_cb (void *cls, GNUNET_assert (NULL != rctx->response); resume_track_transfer_with_response (rctx, - MHD_HTTP_CONFLICT, + MHD_HTTP_FAILED_DEPENDENCY, rctx->response); rctx->response = NULL; return; @@ -386,7 +393,8 @@ wire_transfer_cb (void *cls, resume_track_transfer_with_response (rctx, MHD_HTTP_INTERNAL_SERVER_ERROR, - TMH_RESPONSE_make_json_pack ("{s:s}", + TMH_RESPONSE_make_json_pack ("{s:I, s:s}", + "code", (json_int_t) TALER_EC_TRACK_TRANSFER_DB_STORE_COIN_ERROR, "details", "failed to store response from exchange to local database")); return; } @@ -425,7 +433,8 @@ process_track_transfer_with_exchange (void *cls, resume_track_transfer_with_response (rctx, MHD_HTTP_INTERNAL_SERVER_ERROR, - TMH_RESPONSE_make_json_pack ("{s:s}", + TMH_RESPONSE_make_json_pack ("{s:I, s:s}", + "code", (json_int_t) TALER_EC_TRACK_TRANSFER_REQUEST_ERROR, "error", "failed to run /track/transfer on exchange")); } } diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h @@ -23,6 +23,7 @@ #define _TALER_MERCHANT_SERVICE_H #include <taler/taler_util.h> +#include <taler/taler_error_codes.h> #include <gnunet/gnunet_curl_lib.h> #include <jansson.h> @@ -43,6 +44,7 @@ struct TALER_MERCHANT_ContractOperation; * @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 the full received JSON reply, or * error details if the request failed * @param contract completed contract, NULL on error @@ -52,6 +54,7 @@ struct TALER_MERCHANT_ContractOperation; typedef void (*TALER_MERCHANT_ContractCallback) (void *cls, unsigned int http_status, + enum TALER_ErrorCode ec, const json_t *obj, const json_t *contract, const struct TALER_MerchantSignatureP *sig, @@ -110,11 +113,13 @@ struct TALER_MERCHANT_Pay; * 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 */ typedef void (*TALER_MERCHANT_PayCallback) (void *cls, unsigned int http_status, + enum TALER_ErrorCode ec, const json_t *obj); @@ -317,6 +322,7 @@ struct TALER_MERCHANT_TrackTransferHandle; * * @param cls closure * @param http_status HTTP status code we got, 0 on exchange protocol violation + * @param ec taler-specific error code * @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) @@ -329,6 +335,7 @@ struct TALER_MERCHANT_TrackTransferHandle; 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, @@ -436,6 +443,7 @@ struct TALER_MERCHANT_TransactionWireTransfer * * @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 from the backend * @param num_transfers number of wire transfers the exchange used for the transaction * @param transfers details about each transfer and which coins are aggregated in it @@ -443,6 +451,7 @@ struct TALER_MERCHANT_TransactionWireTransfer typedef void (*TALER_MERCHANT_TrackTransactionCallback) (void *cls, unsigned int http_status, + enum TALER_ErrorCode ec, const json_t *json, unsigned int num_transfers, const struct TALER_MERCHANT_TransactionWireTransfer *transfers); @@ -488,11 +497,13 @@ struct TALER_MERCHANT_HistoryOperation; * * @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 */ typedef void (*TALER_MERCHANT_HistoryOperationCallback) (void *cls, unsigned int http_status, + enum TALER_ErrorCode ec, const json_t *json); /** diff --git a/src/lib/merchant_api_contract.c b/src/lib/merchant_api_contract.c @@ -148,6 +148,7 @@ handle_contract_finished (void *cls, } co->cb (co->cb_cls, response_code, + TALER_JSON_get_error_code (json), json, contract, sigp, diff --git a/src/lib/merchant_api_history.c b/src/lib/merchant_api_history.c @@ -81,7 +81,7 @@ TALER_MERCHANT_history_cancel (struct TALER_MERCHANT_HistoryOperation *ho) /** * Function called when we're done processing the - * HTTP /track/transaction request. + * HTTP /history request. * * @param cls the `struct TALER_MERCHANT_TrackTransactionHandle` * @param response_code HTTP response code, 0 on error @@ -102,16 +102,18 @@ history_raw_cb (void *cls, break; case MHD_HTTP_OK: ho->cb (ho->cb_cls, - response_code, + MHD_HTTP_OK, + TALER_EC_NONE, json); return; break; case MHD_HTTP_INTERNAL_SERVER_ERROR: - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "history URI not found\n"); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "/history URI not found\n"); break; - case MHD_HTTP_BAD_REQUEST: - GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Wrong parameter passed in URL\n"); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Wrong parameter passed in URL\n"); break; default: /* unexpected response code */ @@ -124,10 +126,12 @@ history_raw_cb (void *cls, } ho->cb (ho->cb_cls, response_code, + TALER_JSON_get_error_code (json), json); TALER_MERCHANT_history_cancel (ho); } + /** * Issue a /history request to the backend. * @@ -135,7 +139,7 @@ history_raw_cb (void *cls, * @param backend_uri base URL of the merchant backend * @param date only transactions younger than/equals to date will be returned * @param history_cb callback which will work the response gotten from the backend - * @param history_cb_cls closure to pass to history_cb + * @param history_cb_cls closure to pass to @a history_cb * @return handle for this operation, NULL upon errors */ struct TALER_MERCHANT_HistoryOperation * diff --git a/src/lib/merchant_api_pay.c b/src/lib/merchant_api_pay.c @@ -241,6 +241,7 @@ handle_pay_finished (void *cls, (unsigned int) response_code); ph->cb (ph->cb_cls, response_code, + TALER_JSON_get_error_code (json), json); TALER_MERCHANT_pay_cancel (ph); } diff --git a/src/lib/merchant_api_track_transaction.c b/src/lib/merchant_api_track_transaction.c @@ -155,6 +155,7 @@ parse_track_transaction_ok (struct TALER_MERCHANT_TrackTransactionHandle *tdo, } tdo->cb (tdo->cb_cls, MHD_HTTP_OK, + TALER_EC_NONE, json, num_transfers, transfers); @@ -218,6 +219,7 @@ handle_track_transaction_finished (void *cls, } tdo->cb (tdo->cb_cls, response_code, + TALER_JSON_get_error_code (json), json, 0, NULL); diff --git a/src/lib/merchant_api_track_transfer.c b/src/lib/merchant_api_track_transfer.c @@ -138,6 +138,7 @@ check_track_transfer_response_ok (struct TALER_MERCHANT_TrackTransferHandle *wdh } wdh->cb (wdh->cb_cls, MHD_HTTP_OK, + TALER_EC_NONE, &exchange_pub, json, &h_wire, @@ -198,6 +199,7 @@ handle_track_transfer_finished (void *cls, } tdo->cb (tdo->cb_cls, response_code, + TALER_JSON_get_error_code (json), NULL, json, NULL, diff --git a/src/lib/test_merchant_api.c b/src/lib/test_merchant_api.c @@ -714,11 +714,13 @@ next_command (struct InterpreterState *is) * @param cls closure with the interpreter state * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request * 0 if the exchange's reply is bogus (fails to follow the protocol) + * @param ec taler-specific error code, #TALER_EC_NONE on success * @param full_response full response from the exchange (for logging, in case of errors) */ static void add_incoming_cb (void *cls, unsigned int http_status, + enum TALER_ErrorCode ec, const json_t *full_response) { struct InterpreterState *is = cls; @@ -742,11 +744,13 @@ add_incoming_cb (void *cls, * * @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 */ -void +static void history_cb (void *cls, unsigned int http_status, + enum TALER_ErrorCode ec, const json_t *json) { struct InterpreterState *is = cls; @@ -853,6 +857,7 @@ compare_reserve_withdraw_history (const struct TALER_EXCHANGE_ReserveHistory *h, static void reserve_status_cb (void *cls, unsigned int http_status, + enum TALER_ErrorCode ec, const json_t *json, const struct TALER_Amount *balance, unsigned int history_length, @@ -959,12 +964,14 @@ reserve_status_cb (void *cls, * @param cls closure with the interpreter state * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request * 0 if the exchange's reply is bogus (fails to follow the protocol) + * @param ec taler-specific error code * @param sig signature over the coin, NULL on error * @param full_response full response from the exchange (for logging, in case of errors) */ static void reserve_withdraw_cb (void *cls, unsigned int http_status, + enum TALER_ErrorCode ec, const struct TALER_DenominationSignature *sig, const json_t *full_response) { @@ -1014,6 +1021,7 @@ reserve_withdraw_cb (void *cls, * @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 the full received JSON reply, or * error details if the request failed * @param contract completed contract, NULL on error @@ -1023,6 +1031,7 @@ reserve_withdraw_cb (void *cls, static void contract_cb (void *cls, unsigned int http_status, + enum TALER_ErrorCode ec, const json_t *obj, const json_t *contract, const struct TALER_MerchantSignatureP *sig, @@ -1059,12 +1068,14 @@ contract_cb (void *cls, * @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 code * @param obj the received JSON reply, should be kept as proof (and, in case of errors, * be forwarded to the customer) */ static void pay_cb (void *cls, unsigned int http_status, + enum TALER_ErrorCode ec, const json_t *obj) { struct InterpreterState *is = cls; @@ -1158,6 +1169,7 @@ maint_child_death (void *cls) * * @param cls closure for this function * @param http_status HTTP response code returned by the server + * @param ec taler-specific error code * @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) @@ -1170,6 +1182,7 @@ maint_child_death (void *cls) 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, @@ -1266,6 +1279,7 @@ track_transfer_cb (void *cls, * * @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 num_transfers number of wire transfers involved in setting the transaction * @param transfers detailed list of transfers involved and their coins @@ -1273,6 +1287,7 @@ track_transfer_cb (void *cls, static void track_transaction_cb (void *cls, unsigned int http_status, + enum TALER_ErrorCode ec, const json_t *json, unsigned int num_transfers, const struct TALER_MERCHANT_TransactionWireTransfer *transfers)