taler-api-procedures.sql (3831B)
1 -- 2 -- This file is part of TALER 3 -- Copyright (C) 2025 Taler Systems SA 4 -- 5 -- TALER is free software; you can redistribute it and/or modify it under the 6 -- terms of the GNU General Public License as published by the Free Software 7 -- Foundation; either version 3, or (at your option) any later version. 8 -- 9 -- TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 -- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 -- A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 -- 13 -- You should have received a copy of the GNU General Public License along with 14 -- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 16 SET search_path TO taler_api; 17 18 -- Remove all existing functions 19 DO 20 $do$ 21 DECLARE 22 _sql text; 23 BEGIN 24 SELECT INTO _sql 25 string_agg(format('DROP %s %s CASCADE;' 26 , CASE prokind 27 WHEN 'f' THEN 'FUNCTION' 28 WHEN 'p' THEN 'PROCEDURE' 29 END 30 , oid::regprocedure) 31 , E'\n') 32 FROM pg_proc 33 WHERE pronamespace = 'taler_api'::regnamespace; 34 35 IF _sql IS NOT NULL THEN 36 EXECUTE _sql; 37 END IF; 38 END 39 $do$; 40 41 CREATE FUNCTION taler_transfer( 42 IN in_amount taler_amount, 43 IN in_exchange_base_url TEXT, 44 IN in_subject TEXT, 45 IN in_credit_payto TEXT, 46 IN in_request_uid BYTEA, 47 IN in_wtid BYTEA, 48 IN in_now INT8, 49 -- Error status 50 OUT out_request_uid_reuse BOOLEAN, 51 OUT out_wtid_reuse BOOLEAN, 52 -- Success return 53 OUT out_transfer_row_id INT8, 54 OUT out_created_at INT8 55 ) 56 LANGUAGE plpgsql AS $$ 57 BEGIN 58 -- Check for idempotence and conflict 59 SELECT (amount != in_amount 60 OR credit_payto != in_credit_payto 61 OR exchange_base_url != in_exchange_base_url 62 OR wtid != in_wtid) 63 ,transfer_id, created_at 64 INTO out_request_uid_reuse, out_transfer_row_id, out_created_at 65 FROM transfer 66 WHERE request_uid = in_request_uid; 67 IF FOUND THEN 68 out_wtid_reuse=FALSE; 69 RETURN; 70 END IF; 71 out_request_uid_reuse=FALSE; 72 -- Check for wtid reuse 73 out_wtid_reuse = EXISTS(SELECT FROM transfer WHERE wtid=in_wtid); 74 IF out_wtid_reuse THEN 75 RETURN; 76 END IF; 77 out_created_at=in_now; 78 -- Register exchange 79 INSERT INTO transfer ( 80 amount, 81 exchange_base_url, 82 subject, 83 credit_payto, 84 request_uid, 85 wtid, 86 status, 87 status_msg, 88 created_at 89 ) VALUES ( 90 in_amount, 91 in_exchange_base_url, 92 in_subject, 93 in_credit_payto, 94 in_request_uid, 95 in_wtid, 96 'success', 97 NULL, 98 in_now 99 ) RETURNING transfer_id INTO out_transfer_row_id; 100 -- Notify new transaction 101 PERFORM pg_notify('outgoing_tx', out_transfer_row_id || ''); 102 END $$; 103 COMMENT ON FUNCTION taler_transfer IS 'Create an outgoing taler transaction and register it'; 104 105 CREATE FUNCTION add_incoming( 106 IN in_amount taler_amount, 107 IN in_subject TEXT, 108 IN in_debit_payto TEXT, 109 IN in_type incoming_type, 110 IN in_metadata BYTEA, 111 IN in_now INT8, 112 -- Error status 113 OUT out_reserve_pub_reuse BOOLEAN, 114 -- Success return 115 OUT out_tx_row_id INT8, 116 OUT out_created_at INT8 117 ) 118 LANGUAGE plpgsql AS $$ 119 BEGIN 120 -- Check conflict 121 SELECT in_type = 'reserve'::incoming_type AND EXISTS(SELECT FROM tx_in WHERE metadata = in_metadata AND type = 'reserve') 122 INTO out_reserve_pub_reuse; 123 IF out_reserve_pub_reuse THEN 124 RETURN; 125 END IF; 126 -- Register incoming transaction 127 out_created_at=in_now; 128 INSERT INTO tx_in ( 129 amount, 130 debit_payto, 131 created_at, 132 subject, 133 type, 134 metadata, 135 origin_exchange_url 136 ) VALUES ( 137 in_amount, 138 in_debit_payto, 139 in_now, 140 in_subject, 141 in_type, 142 in_metadata, 143 NULL 144 ) RETURNING tx_in_id INTO out_tx_row_id; 145 -- Notify new incoming transaction 146 PERFORM pg_notify('incoming_tx', out_tx_row_id || ''); 147 END $$; 148 COMMENT ON FUNCTION add_incoming IS 'Create an incoming taler transaction and register it';