cashless2ecash

cashless2ecash: pay with cards for digital cash (experimental)
Log | Files | Refs | README

commit 6dabf9df382fce7fb3253b1ec575d2ca32291a5b
parent c4f86ebdfb9519cbb3dc4892ff0a46860561e1a9
Author: Joel-Haeberli <haebu@rubigen.ch>
Date:   Wed,  8 May 2024 19:10:16 +0200

fix: status api

Diffstat:
Mc2ec/api-bank-integration.go | 103+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
1 file changed, 61 insertions(+), 42 deletions(-)

diff --git a/c2ec/api-bank-integration.go b/c2ec/api-bank-integration.go @@ -186,7 +186,8 @@ func handleWithdrawalStatus(res http.ResponseWriter, req *http.Request) { var timeoutCtx context.Context notifications := make(chan *Notification) - withdrawalAlreadyChanged := make(chan *Withdrawal) + w := make(chan []byte) + errStat := make(chan int) if shouldStartLongPoll { go func() { @@ -200,10 +201,16 @@ func handleWithdrawalStatus(res http.ResponseWriter, req *http.Request) { LogError("bank-integration-api", err) } if withdrawal == nil { + // do nothing because other goroutine might deliver result return } if withdrawal.WithdrawalStatus != oldState { - withdrawalAlreadyChanged <- withdrawal + byts, status := formatWithdrawalOrErrorStatus(withdrawal) + if status != HTTP_OK { + errStat <- status + } else { + w <- byts + } } }() @@ -222,28 +229,41 @@ func handleWithdrawalStatus(res http.ResponseWriter, req *http.Request) { ) if err != nil { - res.WriteHeader(HTTP_NO_CONTENT) - return + LogError("api-bank-integration", err) + errStat <- HTTP_INTERNAL_SERVER_ERROR + } else { + go listenFunc(timeoutCtx) } + } else { + wthdrl, stat := getWithdrawalOrError(wpd) + if stat != HTTP_OK { + errStat <- stat + } else { + w <- wthdrl + } + } - go listenFunc(timeoutCtx) - - for { - select { - case <-timeoutCtx.Done(): - LogInfo("bank-integration-api", "long poll time exceeded") - res.WriteHeader(HTTP_NO_CONTENT) - return - case <-notifications: - writeWithdrawalOrError(wpd, res) - return - case w := <-withdrawalAlreadyChanged: - writeWithdrawalOrError(w.Wopid, res) - return + for { + select { + case <-timeoutCtx.Done(): + LogInfo("bank-integration-api", "long poll time exceeded") + res.WriteHeader(HTTP_NO_CONTENT) + return + case <-notifications: + wthdrl, stat := getWithdrawalOrError(wpd) + if stat != 200 { + res.WriteHeader(stat) + } else { + res.Write(wthdrl) } + return + case wthdrl := <-w: + res.Write(wthdrl) + return + case status := <-errStat: + res.WriteHeader(status) + return } - } else { - writeWithdrawalOrError(wpd, res) } } @@ -282,47 +302,46 @@ func handleWithdrawalAbort(res http.ResponseWriter, req *http.Request) { // Tries to load a WithdrawalOperationStatus from the database. If no // entry could been found, it will write the correct error to the response. -func writeWithdrawalOrError(wopid []byte, res http.ResponseWriter) { +func getWithdrawalOrError(wopid []byte) ([]byte, int) { // read the withdrawal from the database withdrawal, err := DB.GetWithdrawalByWopid(wopid) if err != nil { LogError("bank-integration-api", err) - res.WriteHeader(HTTP_NOT_FOUND) - return - } - - operator, err := DB.GetProviderByTerminal(int(*withdrawal.TerminalId)) - if err != nil { - LogError("bank-integration-api", err) - res.WriteHeader(HTTP_INTERNAL_SERVER_ERROR) - return + return nil, HTTP_NOT_FOUND } if withdrawal == nil { // not found -> 404 - res.WriteHeader(HTTP_NOT_FOUND) - return + return nil, HTTP_NOT_FOUND } // return the C2ECWithdrawalStatus - if amount, err := ToAmount(withdrawal.Amount); err != nil { + return formatWithdrawalOrErrorStatus(withdrawal) +} + +func formatWithdrawalOrErrorStatus(w *Withdrawal) ([]byte, int) { + + operator, err := DB.GetProviderByTerminal(int(*w.TerminalId)) + if err != nil { LogError("bank-integration-api", err) - res.WriteHeader(HTTP_INTERNAL_SERVER_ERROR) - return + return nil, HTTP_INTERNAL_SERVER_ERROR + } + + if amount, err := ToAmount(w.Amount); err != nil { + LogError("bank-integration-api", err) + return nil, HTTP_INTERNAL_SERVER_ERROR } else { withdrawalStatusBytes, err := NewJsonCodec[BankWithdrawalOperationStatus]().EncodeToBytes(&BankWithdrawalOperationStatus{ - Status: withdrawal.WithdrawalStatus, + Status: w.WithdrawalStatus, Amount: *amount, - SenderWire: fmt.Sprintf("payto://%s/%d", operator.PaytoTargetType, withdrawal.ProviderTransactionId), + SenderWire: fmt.Sprintf("payto://%s/%d", operator.PaytoTargetType, w.ProviderTransactionId), WireTypes: []string{operator.PaytoTargetType}, - ReservePubKey: EddsaPublicKey((encodeCrock(withdrawal.ReservePubKey))), + ReservePubKey: EddsaPublicKey((encodeCrock(w.ReservePubKey))), }) if err != nil { LogError("bank-integration-api", err) - res.WriteHeader(HTTP_INTERNAL_SERVER_ERROR) - return + return nil, HTTP_INTERNAL_SERVER_ERROR } - res.WriteHeader(HTTP_OK) - res.Write(withdrawalStatusBytes) + return withdrawalStatusBytes, HTTP_OK } }