/*
This file is part of TALER
Copyright (C) 2015-2020 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along with
TALER; see the file COPYING. If not, see
*/
/**
* @file include/taler_bank_service.h
* @brief C interface of libtalerbank, a C library to use the Taler bank's HTTP API
* This is currently ONLY used to provide the "test" wire transfer protocol.
* @author Christian Grothoff
*/
#ifndef _TALER_BANK_SERVICE_H
#define _TALER_BANK_SERVICE_H
#include
#include
#include "taler_util.h"
#include "taler_error_codes.h"
/**
* Authentication method types.
*/
enum TALER_BANK_AuthenticationMethod
{
/**
* No authentication.
*/
TALER_BANK_AUTH_NONE,
/**
* Basic authentication with cleartext username and password.
*/
TALER_BANK_AUTH_BASIC
};
/**
* Information used to authenticate to the bank.
*/
struct TALER_BANK_AuthenticationData
{
/**
* Which authentication method should we use?
*/
enum TALER_BANK_AuthenticationMethod method;
/**
* Further details as per @e method.
*/
union
{
/**
* Details for #TALER_BANK_AUTH_BASIC.
*/
struct
{
/**
* Username to use.
*/
char *username;
/**
* Password to use.
*/
char *password;
} basic;
} details;
};
/**
* Different account types supported by payto://.
*/
enum TALER_PaytoAccountType
{
/**
* Used to indicate an uninitialized struct.
*/
TALER_PAC_NONE = 0,
/**
* Account type of a bank running the x-taler-bank protocol.
*/
TALER_PAC_X_TALER_BANK,
/**
* Account identified by IBAN number.
*/
TALER_PAC_IBAN
};
/**
* Information about an account extracted from a payto://-URL.
*/
struct TALER_Account
{
/**
* How this the account represented.
*/
enum TALER_PaytoAccountType type;
/**
* Internals depending on @e type.
*/
union
{
/**
* Taler bank address from x-taler-bank. Set if
* @e type is #TALER_AC_X_TALER_BANK.
*/
struct
{
/**
* Bank account base URL.
*/
char *account_base_url;
/**
* Only the hostname of the bank.
*/
char *hostname;
} x_taler_bank;
/**
* Taler bank address from iban. Set if
* @e type is #TALER_AC_IBAN.
*/
struct
{
/**
* IBAN number.
*/
char *number;
} iban;
} details;
};
/* ********************* /admin/add/incoming *********************** */
/**
* @brief A /admin/add/incoming Handle
*/
struct TALER_BANK_AdminAddIncomingHandle;
/**
* Callbacks of this type are used to serve the result of submitting
* information about an incoming transaction to a bank.
*
* @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
* 0 if the bank's reply is bogus (fails to follow the protocol)
* @param ec detailed error code
* @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error
* @param timestamp time when the transaction was made.
* @param json detailed response from the HTTPD, or NULL if reply was not in JSON
*/
typedef void
(*TALER_BANK_AdminAddIncomingResultCallback) (void *cls,
unsigned int http_status,
enum TALER_ErrorCode ec,
uint64_t serial_id,
struct GNUNET_TIME_Absolute
timestamp,
const json_t *json);
/**
* Notify the bank that we have received an incoming transaction
* which fills a reserve. Note that this API is an administrative
* API and thus not accessible to typical bank clients, but only
* to the operators of the bank.
*
* @param ctx curl context for the event loop
* @param account_base_url URL of the bank (money flows into this account)
* @param auth authentication data to send to the bank
* @param reserve_pub wire transfer subject for the transfer
* @param amount amount that was deposited
* @param debit_account account to deposit from (payto URI, but used as 'payfrom')
* @param res_cb the callback to call when the final result for this request is available
* @param res_cb_cls closure for the above callback
* @return NULL
* if the inputs are invalid (i.e. invalid amount).
* In this case, the callback is not called.
*/
struct TALER_BANK_AdminAddIncomingHandle *
TALER_BANK_admin_add_incoming (struct GNUNET_CURL_Context *ctx,
const char *account_base_url,
const struct TALER_BANK_AuthenticationData *auth,
const struct
TALER_ReservePublicKeyP *reserve_pub,
const struct TALER_Amount *amount,
const char *debit_account,
TALER_BANK_AdminAddIncomingResultCallback res_cb,
void *res_cb_cls);
/**
* Cancel an add incoming. This function cannot be used on a request
* handle if a response is already served for it.
*
* @param aai the admin add incoming request handle
*/
void
TALER_BANK_admin_add_incoming_cancel (struct
TALER_BANK_AdminAddIncomingHandle *aai);
/* ********************* /taler/transfer *********************** */
/**
* Prepare for exeuction of a wire transfer.
*
* @param destination_account_url payto:// URL identifying where to send the money
* @param amount amount to transfer, already rounded
* @param exchange_base_url base URL of this exchange (included in subject
* to facilitate use of tracking API by merchant backend)
* @param wtid wire transfer identifier to use
* @param buf[out] set to transaction data to persist, NULL on error
* @param buf_size[out] set to number of bytes in @a buf, 0 on error
*/
void
TALER_BANK_prepare_wire_transfer (const char *destination_account_url,
const struct TALER_Amount *amount,
const char *exchange_base_url,
const struct
TALER_WireTransferIdentifierRawP *wtid,
void **buf,
size_t *buf_size);
/**
* Handle for active wire transfer.
*/
struct TALER_BANK_WireExecuteHandle;
/**
* Function called with the result from the execute step.
*
* @param cls closure
* @param response_code HTTP status code
* @param ec taler error code
* @param row_id unique ID of the wire transfer in the bank's records
* @param timestamp when did the transaction go into effect
*/
typedef void
(*TALER_BANK_ConfirmationCallback)(void *cls,
unsigned int response_code,
enum TALER_ErrorCode ec,
uint64_t row_id,
struct GNUNET_TIME_Absolute timestamp);
/**
* Execute a wire transfer.
*
* @param ctx context for HTTP interaction
* @param bank_base_url URL of the base INCLUDING account number
* @param buf buffer with the prepared execution details
* @param buf_size number of bytes in @a buf
* @param cc function to call upon success
* @param cc_cls closure for @a cc
* @return NULL on error
*/
struct TALER_BANK_WireExecuteHandle *
TALER_BANK_execute_wire_transfer (struct GNUNET_CURL_Context *ctx,
const char *bank_base_url,
const struct
TALER_BANK_AuthenticationData *auth,
const void *buf,
size_t buf_size,
TALER_BANK_ConfirmationCallback cc,
void *cc_cls);
/**
* Abort execution of a wire transfer. For example, because we are
* shutting down. Note that if an execution is aborted, it may or
* may not still succeed. The caller MUST run @e
* execute_wire_transfer again for the same request as soon as
* possilbe, to ensure that the request either ultimately succeeds
* or ultimately fails. Until this has been done, the transaction is
* in limbo (i.e. may or may not have been committed).
*
* @param eh execution to cancel
*/
void
TALER_BANK_execute_wire_transfer_cancel (struct
TALER_BANK_WireExecuteHandle *eh);
/* ********************* /taler/credits *********************** */
/**
* Handle for querying the bank for transactions
* made to the exchange.
*/
struct TALER_BANK_CreditHistoryHandle;
/**
* Details about a wire transfer to the exchange.
*/
struct TALER_BANK_CreditDetails
{
/**
* Amount that was transferred
*/
struct TALER_Amount amount;
/**
* Time of the the transfer
*/
struct GNUNET_TIME_Absolute execution_date;
/**
* Reserve public key encoded in the wire
* transfer subject.
*/
struct TALER_ReservePublicKeyP reserve_pub;
/**
* payto://-URL of the source account that
* send the funds.
*/
const char *debit_account_url;
/**
* payto://-URL of the target account that
* received the funds.
*/
const char *credit_account_url;
};
/**
* Callbacks of this type are used to serve the result of asking
* the bank for the credit transaction history.
*
* @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
* 0 if the bank's reply is bogus (fails to follow the protocol),
* #MHD_HTTP_NO_CONTENT if there are no more results; on success the
* last callback is always of this status (even if `abs(num_results)` were
* already returned).
* @param ec detailed error code
* @param serial_id monotonically increasing counter corresponding to the transaction
* @param details details about the wire transfer
* @param json detailed response from the HTTPD, or NULL if reply was not in JSON
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
*/
typedef int
(*TALER_BANK_CreditResultCallback) (void *cls,
unsigned int http_status,
enum TALER_ErrorCode ec,
uint64_t serial_id,
const struct
TALER_BANK_CreditDetails *details,
const json_t *json);
/**
* Request the wire credit history of an exchange's bank account.
*
* @param ctx curl context for the event loop
* @param account_base_url URL of the base INCLUDING account number
* @param auth authentication data to use
* @param start_row from which row on do we want to get results, use UINT64_MAX for the latest; exclusive
* @param num_results how many results do we want; negative numbers to go into the past,
* positive numbers to go into the future starting at @a start_row;
* must not be zero.
* @param hres_cb the callback to call with the transaction history
* @param hres_cb_cls closure for the above callback
* @return NULL
* if the inputs are invalid (i.e. zero value for @e num_results).
* In this case, the callback is not called.
*/
struct TALER_BANK_CreditHistoryHandle *
TALER_BANK_credit_history (struct GNUNET_CURL_Context *ctx,
const char *account_base_url,
const struct TALER_BANK_AuthenticationData *auth,
uint64_t start_row,
int64_t num_results,
TALER_BANK_CreditResultCallback hres_cb,
void *hres_cb_cls);
/**
* Cancel an history request. This function cannot be used on a request
* handle if the last response (anything with a status code other than
* 200) is already served for it.
*
* @param hh the history request handle
*/
void
TALER_BANK_credit_history_cancel (struct TALER_BANK_CreditHistoryHandle *hh);
/* ********************* /taler/debits *********************** */
/**
* Handle for querying the bank for transactions
* made from the exchange to merchants.
*/
struct TALER_BANK_DebitHistoryHandle;
/**
* Details about a wire transfer made by the exchange
* to a merchant.
*/
struct TALER_BANK_DebitDetails
{
/**
* Amount that was transferred
*/
struct TALER_Amount amount;
/**
* Time of the the transfer
*/
struct GNUNET_TIME_Absolute execution_date;
/**
* Wire transfer identifier used by the exchange.
*/
struct TALER_WireTransferIdentifierRawP wtid;
/**
* Exchange's base URL as given in the wire transfer.
*/
const char *exchange_base_url;
/**
* payto://-URL of the source account that
* send the funds.
*/
const char *debit_account_url;
/**
* payto://-URL of the target account that
* received the funds.
*/
const char *credit_account_url;
};
/**
* Callbacks of this type are used to serve the result of asking
* the bank for the debit transaction history.
*
* @param cls closure
* @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request
* 0 if the bank's reply is bogus (fails to follow the protocol),
* #MHD_HTTP_NO_CONTENT if there are no more results; on success the
* last callback is always of this status (even if `abs(num_results)` were
* already returned).
* @param ec detailed error code
* @param serial_id monotonically increasing counter corresponding to the transaction
* @param details details about the wire transfer
* @param json detailed response from the HTTPD, or NULL if reply was not in JSON
* @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration
*/
typedef int
(*TALER_BANK_DebitResultCallback) (void *cls,
unsigned int http_status,
enum TALER_ErrorCode ec,
uint64_t serial_id,
const struct
TALER_BANK_DebitDetails *details,
const json_t *json);
/**
* Request the wire credit history of an exchange's bank account.
*
* @param ctx curl context for the event loop
* @param bank_base_url URL of the base INCLUDING account number
* @param auth authentication data to use
* @param account_number which account number should we query
* @param start_row from which row on do we want to get results, use UINT64_MAX for the latest; exclusive
* @param num_results how many results do we want; negative numbers to go into the past,
* positive numbers to go into the future starting at @a start_row;
* must not be zero.
* @param hres_cb the callback to call with the transaction history
* @param hres_cb_cls closure for the above callback
* @return NULL
* if the inputs are invalid (i.e. zero value for @e num_results).
* In this case, the callback is not called.
*/
struct TALER_BANK_DebitHistoryHandle *
TALER_BANK_debit_history (struct GNUNET_CURL_Context *ctx,
const char *bank_base_url,
const struct TALER_BANK_AuthenticationData *auth,
uint64_t start_row,
int64_t num_results,
TALER_BANK_DebitResultCallback hres_cb,
void *hres_cb_cls);
/**
* Cancel an history request. This function cannot be used on a request
* handle if the last response (anything with a status code other than
* 200) is already served for it.
*
* @param hh the history request handle
*/
void
TALER_BANK_debit_history_cancel (struct TALER_BANK_DebitHistoryHandle *hh);
/* ******************** Convenience functions **************** */
/**
* Convenience method for parsing configuration section with bank account data.
*
* @param cfg configuration to parse
* @param section the section with the configuration data
* @param acc[out] set to the account details
* @return #GNUNET_OK on success
*/
int
TALER_BANK_account_parse_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
const char *section,
struct TALER_Account *acc);
/**
* Release memory allocated in @a acc.
*
* @param acc account to free, the pointer itself is NOT free'd.
*/
void
TALER_BANK_account_free (struct TALER_Account *acc);
/**
* Parse @a payto_url and store the result in @a acc
*
* @param payto_url URL to parse
* @param acc[in,out] account to initialize, free using #TALER_BANK_account_free() later
* @return #TALER_EC_NONE if @a payto_url is well-formed
*/
enum TALER_ErrorCode
TALER_BANK_payto_to_account (const char *payto_url,
struct TALER_Account *acc);
/**
* Convenience method for parsing configuration section with bank
* authentication data. The section must contain an option
* "METHOD", plus other options that depend on the METHOD specified.
*
* @param cfg configuration to parse
* @param section the section with the configuration data
* @param auth[out] set to the configuration data found
* @return #GNUNET_OK on success
*/
int
TALER_BANK_auth_parse_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
const char *section,
struct TALER_BANK_AuthenticationData *auth);
/**
* Free memory inside of @a auth (but not auth itself).
* Dual to #TALER_BANK_auth_parse_cfg().
*
* @param auth authentication data to free
*/
void
TALER_BANK_auth_free (struct TALER_BANK_AuthenticationData *auth);
#endif /* _TALER_BANK_SERVICE_H */