merchant

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

commit 2861254de6321015394591e0da1a61086134e86e
parent cf3495ccc44df0eb9cae3799333b744982588bb2
Author: bohdan-potuzhnyi <bohdan.potuzhnyi@gmail.com>
Date:   Wed, 16 Jul 2025 12:13:15 +0200

adding some comments to taler_merchant_pay_service.c/.h

Diffstat:
Msrc/include/taler_merchant_pay_service.h | 180+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Msrc/lib/taler_merchant_pay_service.c | 154++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
2 files changed, 237 insertions(+), 97 deletions(-)

diff --git a/src/include/taler_merchant_pay_service.h b/src/include/taler_merchant_pay_service.h @@ -67,7 +67,7 @@ enum TALER_MERCHANT_OrderPayOptionType TALER_MERCHANT_OrderPayOptionType_COINS, TALER_MERCHANT_OrderPayOptionType_INPUT_TOKENS, TALER_MERCHANT_OrderPayOptionType_OUTPUT_TOKENS, - TALER_MERCHANT_OrderPayOptionType_WALLET_DATA, //Used privately so no #define is present for it + TALER_MERCHANT_OrderPayOptionType_WALLET_DATA, // Used privately so no #define is present for it TALER_MERCHANT_OrderPayOptionType_DONAU_URL, TALER_MERCHANT_OrderPayOptionType_DONAU_YEAR, TALER_MERCHANT_OrderPayOptionType_DONAU_BUDIS, @@ -95,21 +95,24 @@ struct TALER_MERCHANT_OrderPayOption struct GNUNET_TIME_Timestamp pay_deadline; struct TALER_MerchantWireHashP h_wire; const char *order_id; - struct { + struct + { unsigned int num_coins; const struct TALER_MERCHANT_PayCoin *coins; } coins; - struct { + struct + { unsigned int num_tokens; const struct TALER_MERCHANT_UseToken *tokens; } input_tokens; - struct { + struct + { unsigned int num_output_tokens; const struct TALER_MERCHANT_OutputToken *output_tokens; } output_tokens; #ifdef HAVE_DONAU_DONAU_SERVICE_H const char *donau_url; - uint64_t donau_year; + uint64_t donau_year; json_t *donau_budis_json; #endif } details; @@ -131,143 +134,174 @@ enum TALER_MERCHANT_OrderPayOptionErrorCode #define TALER_MERCHANT_ORDER_PAY_OPTION_TERMINATE() \ (struct TALER_MERCHANT_OrderPayOption){ \ - .ot = TALER_MERCHANT_OrderPayOptionType_END \ - } + .ot = TALER_MERCHANT_OrderPayOptionType_END \ + } #define TALER_MERCHANT_ORDER_PAY_OPTION_MERCHANT_URL(_url) \ (struct TALER_MERCHANT_OrderPayOption){ \ - .ot = TALER_MERCHANT_OrderPayOptionType_MERCHANT_URL, \ - .details.merchant_url = (_url) \ - } + .ot = TALER_MERCHANT_OrderPayOptionType_MERCHANT_URL, \ + .details.merchant_url = (_url) \ + } #define TALER_MERCHANT_ORDER_PAY_OPTION_SESSION_ID(_sid) \ (struct TALER_MERCHANT_OrderPayOption){ \ - .ot = TALER_MERCHANT_OrderPayOptionType_SESSION_ID,\ - .details.session_id = (_sid) \ - } + .ot = TALER_MERCHANT_OrderPayOptionType_SESSION_ID, \ + .details.session_id = (_sid) \ + } #define TALER_MERCHANT_ORDER_PAY_OPTION_H_CONTRACT(_h) \ (struct TALER_MERCHANT_OrderPayOption){ \ - .ot = TALER_MERCHANT_OrderPayOptionType_H_CONTRACT, \ - .details.h_contract = (_h) \ - } + .ot = TALER_MERCHANT_OrderPayOptionType_H_CONTRACT, \ + .details.h_contract = (_h) \ + } #define TALER_MERCHANT_ORDER_PAY_OPTION_CHOICE_INDEX(_idx) \ (struct TALER_MERCHANT_OrderPayOption){ \ - .ot = TALER_MERCHANT_OrderPayOptionType_CHOICE_INDEX,\ - .details.choice_index = (_idx) \ - } + .ot = TALER_MERCHANT_OrderPayOptionType_CHOICE_INDEX, \ + .details.choice_index = (_idx) \ + } #define TALER_MERCHANT_ORDER_PAY_OPTION_AMOUNT(_amt) \ (struct TALER_MERCHANT_OrderPayOption){ \ - .ot = TALER_MERCHANT_OrderPayOptionType_AMOUNT,\ - .details.amount = *(_amt) \ - } + .ot = TALER_MERCHANT_OrderPayOptionType_AMOUNT, \ + .details.amount = *(_amt) \ + } #define TALER_MERCHANT_ORDER_PAY_OPTION_MAX_FEE(_fee) \ (struct TALER_MERCHANT_OrderPayOption){ \ - .ot = TALER_MERCHANT_OrderPayOptionType_MAX_FEE,\ - .details.max_fee = *(_fee) \ - } + .ot = TALER_MERCHANT_OrderPayOptionType_MAX_FEE, \ + .details.max_fee = *(_fee) \ + } #define TALER_MERCHANT_ORDER_PAY_OPTION_MERCHANT_PUB(_mpub) \ (struct TALER_MERCHANT_OrderPayOption){ \ - .ot = TALER_MERCHANT_OrderPayOptionType_MERCHANT_PUB, \ - .details.merchant_pub = *(_mpub) \ - } + .ot = TALER_MERCHANT_OrderPayOptionType_MERCHANT_PUB, \ + .details.merchant_pub = *(_mpub) \ + } #define TALER_MERCHANT_ORDER_PAY_OPTION_TIMESTAMP(_ts) \ (struct TALER_MERCHANT_OrderPayOption){ \ - .ot = TALER_MERCHANT_OrderPayOptionType_TIMESTAMP, \ - .details.timestamp = (_ts) \ - } + .ot = TALER_MERCHANT_OrderPayOptionType_TIMESTAMP, \ + .details.timestamp = (_ts) \ + } #define TALER_MERCHANT_ORDER_PAY_OPTION_REFUND_DEADLINE(_ts) \ (struct TALER_MERCHANT_OrderPayOption){ \ - .ot = TALER_MERCHANT_OrderPayOptionType_REFUND_DEADLINE, \ - .details.refund_deadline = (_ts) \ - } + .ot = TALER_MERCHANT_OrderPayOptionType_REFUND_DEADLINE, \ + .details.refund_deadline = (_ts) \ + } #define TALER_MERCHANT_ORDER_PAY_OPTION_PAY_DEADLINE(_ts) \ (struct TALER_MERCHANT_OrderPayOption){ \ - .ot = TALER_MERCHANT_OrderPayOptionType_PAY_DEADLINE, \ - .details.pay_deadline = (_ts) \ - } + .ot = TALER_MERCHANT_OrderPayOptionType_PAY_DEADLINE, \ + .details.pay_deadline = (_ts) \ + } #define TALER_MERCHANT_ORDER_PAY_OPTION_H_WIRE(_hwire) \ (struct TALER_MERCHANT_OrderPayOption){ \ - .ot = TALER_MERCHANT_OrderPayOptionType_H_WIRE, \ - .details.h_wire = *(_hwire) \ - } + .ot = TALER_MERCHANT_OrderPayOptionType_H_WIRE, \ + .details.h_wire = *(_hwire) \ + } #define TALER_MERCHANT_ORDER_PAY_OPTION_ORDER_ID(_oid) \ (struct TALER_MERCHANT_OrderPayOption){ \ - .ot = TALER_MERCHANT_OrderPayOptionType_ORDER_ID,\ - .details.order_id = (_oid) \ - } + .ot = TALER_MERCHANT_OrderPayOptionType_ORDER_ID, \ + .details.order_id = (_oid) \ + } #define TALER_MERCHANT_ORDER_PAY_OPTION_COINS(_num,_coins) \ (struct TALER_MERCHANT_OrderPayOption){ \ - .ot = TALER_MERCHANT_OrderPayOptionType_COINS, \ - .details.coins = { .num_coins = (_num), \ - .coins = (_coins) } \ - } + .ot = TALER_MERCHANT_OrderPayOptionType_COINS, \ + .details.coins = { .num_coins = (_num), \ + .coins = (_coins) } \ + } #define TALER_MERCHANT_ORDER_PAY_OPTION_INPUT_TOKENS(_num,_tokens) \ (struct TALER_MERCHANT_OrderPayOption){ \ - .ot = TALER_MERCHANT_OrderPayOptionType_INPUT_TOKENS, \ - .details.input_tokens = { .num_tokens = (_num), \ - .tokens = (_tokens) } \ - } + .ot = TALER_MERCHANT_OrderPayOptionType_INPUT_TOKENS, \ + .details.input_tokens = { .num_tokens = (_num), \ + .tokens = (_tokens) } \ + } #define TALER_MERCHANT_ORDER_PAY_OPTION_OUTPUT_TOKENS(_num,_otokens) \ (struct TALER_MERCHANT_OrderPayOption){ \ - .ot = TALER_MERCHANT_OrderPayOptionType_OUTPUT_TOKENS, \ - .details.output_tokens = { .num_output_tokens = (_num), \ - .output_tokens = (_otokens) } \ - } + .ot = TALER_MERCHANT_OrderPayOptionType_OUTPUT_TOKENS, \ + .details.output_tokens = { .num_output_tokens = (_num), \ + .output_tokens = (_otokens) } \ + } #define TALER_MERCHANT_ORDER_PAY_OPTION_DONAU_URL(_u) \ (struct TALER_MERCHANT_OrderPayOption){ \ - .ot = TALER_MERCHANT_OrderPayOptionType_DONAU_URL,\ - .details.donau_url = (_u) \ - } + .ot = TALER_MERCHANT_OrderPayOptionType_DONAU_URL, \ + .details.donau_url = (_u) \ + } #define TALER_MERCHANT_ORDER_PAY_OPTION_DONAU_YEAR(_y) \ (struct TALER_MERCHANT_OrderPayOption){ \ - .ot = TALER_MERCHANT_OrderPayOptionType_DONAU_YEAR,\ - .details.donau_year = (_y) \ - } + .ot = TALER_MERCHANT_OrderPayOptionType_DONAU_YEAR, \ + .details.donau_year = (_y) \ + } #define TALER_MERCHANT_ORDER_PAY_OPTION_DONAU_BUDIS(_js) \ (struct TALER_MERCHANT_OrderPayOption){ \ - .ot = TALER_MERCHANT_OrderPayOptionType_DONAU_BUDIS, \ - .details.donau_budis_json = (_js) \ - } + .ot = TALER_MERCHANT_OrderPayOptionType_DONAU_BUDIS, \ + .details.donau_budis_json = (_js) \ + } #define TALER_MERCHANT_ORDER_PAY_SET_OPTIONS(ph,...) \ - MHD_NOWARN_COMPOUND_LITERALS_ \ - TALER_MERCHANT_order_pay_set_options ( \ - daemon, \ - ((const struct TALER_MERCHANT_OrderPayHandle[]) \ - {__VA_ARGS__, TALER_MERCHANT_ORDER_PAY_OPTION_TERMINATE ()}), \ - MHD_OPTIONS_ARRAY_MAX_SIZE) \ + MHD_NOWARN_COMPOUND_LITERALS_ \ + TALER_MERCHANT_order_pay_set_options ( \ + daemon, \ + ((const struct TALER_MERCHANT_OrderPayHandle[]) \ + {__VA_ARGS__, TALER_MERCHANT_ORDER_PAY_OPTION_TERMINATE ()}), \ + MHD_OPTIONS_ARRAY_MAX_SIZE) \ +/** + * @brief Create and initialize a new payment handle. + * + * @param ctx GNUNET CURL context used for HTTP operations + * @param pay_cb callback to invoke when the payment completes or fails + * @param pay_cb_cls closure data passed back to @a pay_cb + * @return pointer to a newly allocated handle, or NULL on error + */ struct TALER_MERCHANT_OrderPayHandle * TALER_MERCHANT_order_pay_create (struct GNUNET_CURL_Context *ctx, TALER_MERCHANT_OrderPayCallback pay_cb, - TALER_MERCHANT_ORDER_PAY_CALLBACK_CLOSURE_TYPE *pay_cb_cls); + TALER_MERCHANT_ORDER_PAY_CALLBACK_CLOSURE_TYPE + *pay_cb_cls); +/** + * @brief Configure payment options on a handle. + * + * @param ph payment handle to configure + * @param options NULL-terminated array of options (use + * TALER_MERCHANT_ORDER_PAY_OPTION_* macros) + * @param max_options maximum number of options in the @a options array + * @return #TALER_MERCHANT_OPOEC_OK on success; + * error code otherwise + */ enum TALER_MERCHANT_OrderPayOptionErrorCode TALER_MERCHANT_order_pay_set_options (struct TALER_MERCHANT_OrderPayHandle *ph, - const struct TALER_MERCHANT_OrderPayOption options[], + const struct TALER_MERCHANT_OrderPayOption + options[], size_t max_options); +/** + * @brief Start processing the payment request. + * + * @param ph fully configured payment handle + * @return #TALER_MERCHANT_OPOEC_OK on successful dispatch; + * error code on validation or dispatch failure + */ enum TALER_MERCHANT_OrderPayOptionErrorCode TALER_MERCHANT_order_pay_start (struct TALER_MERCHANT_OrderPayHandle *ph); +/** + * @brief Cancel an in-flight or pending payment. + * + * @param ph payment handle to cancel and free + */ void TALER_MERCHANT_order_pay_cancel1 (struct TALER_MERCHANT_OrderPayHandle *ph); - #endif /* TALER_MERCHANT_PAY_SERVICE_H */ \ No newline at end of file diff --git a/src/lib/taler_merchant_pay_service.c b/src/lib/taler_merchant_pay_service.c @@ -43,93 +43,200 @@ */ struct TALER_MERCHANT_OrderPayHandle { + /** + * Reference to the GNUNET CURL execution context. + */ struct GNUNET_CURL_Context *ctx; /** - * Function to call with the result in "pay" @e mode. + * Callback to invoke with the payment result ("pay" mode). */ TALER_MERCHANT_OrderPayCallback cb; /** - * Closure for @a pay_cb. + * Closure data for @a cb. */ TALER_MERCHANT_ORDER_PAY_CALLBACK_CLOSURE_TYPE *cb_cls; - /* mandatory scalars: */ + /* Mandatory scalars: */ + + /** + * Base URL of the merchant service. + */ char *merchant_url; + + /** + * Identifier of the order being paid. + */ char *order_id; + + /** + * Session identifier for this payment attempt. + */ char *session_id; + /** + * Timestamp when the payment request was created. + */ struct GNUNET_TIME_Timestamp timestamp; + + /** + * Deadline after which refunds are no longer allowed. + */ struct GNUNET_TIME_Timestamp refund_deadline; + /** + * Wire hash for communicating payment details. + */ struct TALER_MerchantWireHashP h_wire; + + /** + * Indicates whether @a h_wire has been set. + */ bool has_h_wire; - /* for wallet mode: */ + /* Wallet mode fields: */ + + /** + * Indicates whether a contract hash was provided. + */ bool has_h_contract; + + /** + * Hash of the private contract terms (wallet mode only). + */ struct TALER_PrivateContractHashP h_contract_terms; + /** + * Indicates whether the merchant public key was provided. + */ bool has_merchant_pub; + + /** + * Merchant’s public key for verifying signatures (wallet mode). + */ struct TALER_MerchantPublicKeyP merchant_pub; + /** + * Indicates whether a choice index was provided. + */ bool has_choice_index; + + /** + * Selected index of the contract choice (for token operations). + */ int choice_index; - /*Used for strcmp in the legacy we just keep it for this time*/ + /** + * Legacy: pointer to the amount structure for strcmp checks. + */ const struct TALER_Amount *amount; + + /** + * Legacy: pointer to the maximum fee structure for strcmp checks. + */ const struct TALER_Amount *max_fee; - /* raw arrays as passed in via set_options(): */ + /* Raw arrays as passed in via set_options(): */ + + /** + * Coins used for payment. + */ struct { + /** + * Number of coins provided. + */ unsigned int num_coins; + /** + * Array of coins to spend. + */ const struct TALER_MERCHANT_PayCoin *coins; } coins; + /** + * Input tokens to use (wallet mode). + */ struct { + /** + * Number of tokens provided. + */ unsigned int num_tokens; + /** + * Array of tokens to redeem. + */ const struct TALER_MERCHANT_UseToken *tokens; } input_tokens; + /** + * Output tokens expected from the merchant. + */ struct { + /** + * Number of output tokens expected. + */ unsigned int num_output_tokens; + /** + * Array of expected output tokens. + */ const struct TALER_MERCHANT_OutputToken *output_tokens; } output_tokens; + /** + * JSON array of token envelope events (from Donau). + */ json_t *tokens_evs; - /* computed once we see both choice_index and tokens_evs(outputs in the env): */ + /* Computed once both choice_index and tokens_evs are available: */ + + /** + * JSON object containing wallet-specific data payload. + */ json_t *wallet_data; + + /** + * Hash code of @a wallet_data for integrity checks. + */ struct GNUNET_HashCode wallet_data_hash; - /* the JSON body we’ll keep appending into… */ + /** + * JSON body being constructed for the HTTP POST. + */ json_t *body; - /* final URL and CURL plumbing */ + /* Final URL and CURL plumbing: */ + + /** + * Fully formed URL for the POST /order/$ID/pay request. + */ char *url; + + /** + * CURL post context managing headers and body. + */ struct TALER_CURL_PostContext post_ctx; + + /** + * Handle for the asynchronous CURL job. + */ struct GNUNET_CURL_Job *job; + /** + * Flags indicating which payment options have been set. + */ bool field_seen[TALER_MERCHANT_OrderPayOptionType_LENGTH]; + /** + * True if operating in wallet mode (using tokens/contracts). + */ bool am_wallet; + /** + * Raw JSON data of `donau` for `wallet_data`. + */ json_t *donau_data; - // TODO: Remove this block; - /* --- Donau (optional) ------------------------------------------------- */ - #ifdef HAVE_DONAU_DONAU_SERVICE_H - bool has_donau_url; - char *donau_url; - - bool has_donau_year; - uint64_t donau_year; - - bool has_donau_budis; - json_t *donau_budikeypairs; /* array we’ll own */ - #endif }; /** @@ -467,9 +574,8 @@ TALER_MERCHANT_order_pay_cancel1 (struct TALER_MERCHANT_OrderPayHandle *ph) json_decref (ph->tokens_evs); ph->tokens_evs = NULL; - GNUNET_free (ph->donau_url); - if (ph->donau_budikeypairs) - json_decref (ph->donau_budikeypairs); + if (ph->donau_data) + json_decref (ph->donau_data); GNUNET_free (ph->url); GNUNET_free (ph->merchant_url);