[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-cashless2ecash] branch master updated: code: impl routing
From: |
gnunet |
Subject: |
[taler-cashless2ecash] branch master updated: code: impl routing |
Date: |
Sat, 23 Mar 2024 14:33:24 +0100 |
This is an automated email from the git hooks/post-receive script.
joel-haeberli pushed a commit to branch master
in repository cashless2ecash.
The following commit(s) were added to refs/heads/master by this push:
new 0c79ae9 code: impl routing
0c79ae9 is described below
commit 0c79ae99713e6d4d6d31bd621a949617ebfe503a
Author: Joel-Haeberli <haebu@rubigen.ch>
AuthorDate: Sat Mar 23 14:33:16 2024 +0100
code: impl routing
---
c2ec/auth.go | 22 ++
c2ec/bank-integration.go | 182 +++++++++++++++++
c2ec/c2ec-config.yaml | 10 +
{nonce2ecash/pkg => c2ec}/common/amount.go | 6 +-
{nonce2ecash/pkg => c2ec}/common/amount_test.go | 0
{nonce2ecash/pkg => c2ec}/common/codec.go | 0
{nonce2ecash/pkg => c2ec}/common/codec_test.go | 3 +-
{nonce2ecash/pkg => c2ec}/common/http-util.go | 58 ++++++
{nonce2ecash/pkg => c2ec}/common/http-util_test.go | 2 +-
c2ec/common/model.go | 72 +++++++
c2ec/config.go | 76 +++++++
c2ec/db.go | 48 +++++
{nonce2ecash => c2ec}/go.mod | 5 +-
{nonce2ecash => c2ec}/go.sum | 6 +
c2ec/main.go | 145 +++++++++++++
c2ec/postgres.go | 52 +++++
.../model.go => c2ec/wire-gateway.go | 83 +++++---
data/{nonce2ecash_schema.sql => c2ec_schema.sql} | 26 ++-
docs/content/architecture/c2ec.tex | 16 +-
docs/thesis.pdf | Bin 1387923 -> 1388029
bytes
nonce2ecash/pkg/common/model.go | 31 ---
nonce2ecash/pkg/db/db.go | 66 ------
nonce2ecash/pkg/db/provider.go | 23 ---
nonce2ecash/pkg/db/withdrawal.go | 29 ---
nonce2ecash/pkg/handler.go | 70 -------
nonce2ecash/pkg/main.go | 33 ---
nonce2ecash/pkg/model.go | 25 ---
nonce2ecash/pkg/pkg | Bin 7293394 -> 0 bytes
nonce2ecash/pkg/taler-bank-integration/client.go | 163 ---------------
nonce2ecash/pkg/taler-bank-integration/model.go | 50 -----
nonce2ecash/pkg/taler-wirewatch-gateway/client.go | 226 ---------------------
specs/api-c2ec.rst | 181 -----------------
32 files changed, 766 insertions(+), 943 deletions(-)
diff --git a/c2ec/auth.go b/c2ec/auth.go
new file mode 100644
index 0000000..8fdb761
--- /dev/null
+++ b/c2ec/auth.go
@@ -0,0 +1,22 @@
+package main
+
+import (
+ "net/http"
+)
+
+const AUTHORIZATION_HEADER = "Authorization"
+const BEARER_TOKEN_PREFIX = "Bearer"
+
+func isAllowed(req *http.Request) bool {
+
+ return true
+
+ // auth := req.Header.Get(AUTHORIZATION_HEADER)
+ // token, found := strings.CutPrefix(auth, AUTHORIZATION_HEADER)
+ // if !found {
+ // // invalid token prefix
+ // return false
+ // }
+
+ // return strings.EqualFold(token, "")
+}
diff --git a/c2ec/bank-integration.go b/c2ec/bank-integration.go
new file mode 100644
index 0000000..c280c67
--- /dev/null
+++ b/c2ec/bank-integration.go
@@ -0,0 +1,182 @@
+package main
+
+import (
+ "bytes"
+ "c2ec/common"
+ "log"
+ http "net/http"
+)
+
+const BANK_INTEGRATION_CONFIG_ENDPOINT = "/config"
+const WITHDRAWAL_OPERATION = "/withdrawal-operation"
+
+const WOPID_PARAMETER = "wopid"
+const BANK_INTEGRATION_CONFIG_PATTERN = BANK_INTEGRATION_CONFIG_ENDPOINT
+const WITHDRAWAL_OPERATION_PATTERN = WITHDRAWAL_OPERATION
+const WITHDRAWAL_OPERATION_BY_WOPID_PATTERN = WITHDRAWAL_OPERATION + "/{" +
WOPID_PARAMETER + "}"
+const WITHDRAWAL_OPERATION_ABORTION_PATTERN =
WITHDRAWAL_OPERATION_BY_WOPID_PATTERN + "/abort"
+
+//
https://docs.taler.net/core/api-exchange.html#tsref-type-CurrencySpecification
+type CurrencySpecification struct {
+ Name string `json:"name"`
+ Currency string `json:"currency"`
+ NumFractionalInputDigits int
`json:"num_fractional_input_digits"`
+ NumFractionalNormalDigits int
`json:"num_fractional_normal_digits"`
+ NumFractionalTrailingZeroDigits int
`json:"num_fractional_trailing_zero_digits"`
+ AltUnitNames string `json:"alt_unit_names"`
+}
+
+//
https://docs.taler.net/core/api-bank-integration.html#tsref-type-BankIntegrationConfig
+type BankIntegrationConfig struct {
+ Name string `json:"name"`
+ Version string `json:"version"`
+ Implementation string `json:"implementation"`
+ Currency string `json:"currency"`
+ CurrencySpecification CurrencySpecification
`json:"currency_specification"`
+}
+
+type C2ECWithdrawRegistration struct {
+ Wopid common.WithdrawalIdentifier `json:"wopid"`
+ ReservePubKey common.EddsaPublicKey `json:"reserve_pub_key"`
+ Amount common.Amount `json:"amount"`
+ ProviderId uint64 `json:"provider_id"`
+}
+
+type C2ECWithdrawalStatus struct {
+ Status common.WithdrawalOperationStatus `json:"status"`
+ Amount common.Amount `json:"amount"`
+ SenderWire string `json:"sender_wire"`
+ WireTypes []string `json:"wire_types"`
+ ReservePubKey common.EddsaPublicKey
`json:"selected_reserve_pub"`
+}
+
+type C2ECPaymentNotification struct {
+ ProviderTransactionId string `json:"provider_transaction_id"`
+ Amount common.Amount `json:"amount"`
+ Fees common.Amount `json:"fees"`
+}
+
+func bankIntegrationConfig(res http.ResponseWriter, req *http.Request) {
+
+ cfg := BankIntegrationConfig{
+ Name: "taler-bank-integration",
+ Version: "0:0:1",
+ }
+
+ serializedCfg, err :=
common.NewJsonCodec[BankIntegrationConfig]().EncodeToBytes(&cfg)
+ if err != nil {
+ log.Default().Printf("failed serializing config: %s",
err.Error())
+ res.WriteHeader(common.HTTP_INTERNAL_SERVER_ERROR)
+ return
+ }
+
+ res.WriteHeader(common.HTTP_OK)
+ res.Write(serializedCfg)
+}
+
+func handleWithdrawalRegistration(res http.ResponseWriter, req *http.Request) {
+
+ jsonCodec := common.NewJsonCodec[C2ECWithdrawRegistration]()
+ registration, err :=
common.ReadStructFromBody[C2ECWithdrawRegistration](req, jsonCodec)
+ if err != nil {
+
+ err := common.WriteProblem(res, common.HTTP_BAD_REQUEST,
&common.RFC9457Problem{
+ TypeUri: common.TALER_URI_PROBLEM_PREFIX +
"/C2EC_WITHDRAW_REGISTRATION_INVALID_REQ",
+ Title: "invalid request",
+ Detail: "the registration request for the withdrawal
is malformed (error: " + err.Error() + ")",
+ Instance: req.RequestURI,
+ })
+ if err != nil {
+ res.WriteHeader(common.HTTP_INTERNAL_SERVER_ERROR)
+ }
+ return
+ }
+
+ err = DB.RegisterWithdrawal(registration)
+ if err != nil {
+
+ err := common.WriteProblem(res,
common.HTTP_INTERNAL_SERVER_ERROR, &common.RFC9457Problem{
+ TypeUri: common.TALER_URI_PROBLEM_PREFIX +
"/C2EC_WITHDRAW_REGISTRATION_DB_FAILURE",
+ Title: "databse failure",
+ Detail: "the registration of the withdrawal failed
due to db failure (error:" + err.Error() + ")",
+ Instance: req.RequestURI,
+ })
+ if err != nil {
+ res.WriteHeader(common.HTTP_INTERNAL_SERVER_ERROR)
+ }
+ return
+ }
+
+ res.WriteHeader(common.HTTP_NO_CONTENT)
+}
+
+// Get status of withdrawal associated with the given WOPID
+//
+// Parameters:
+// - long_poll_ms (optional):
+// milliseconds to wait for state to change
+// given old_state until responding
+// - old_state (optional):
+// Default is 'pending'
+// - terminal_provider_id (optional):
+// The terminal provider requesting for status update.
+func handleWithdrawalStatus(res http.ResponseWriter, req *http.Request) {
+
+ wopid := req.PathValue(WOPID_PARAMETER)
+ if wopid == "" {
+ res.WriteHeader(common.HTTP_BAD_REQUEST)
+ return
+ }
+
+ res.WriteHeader(common.HTTP_OK)
+ res.Write(bytes.NewBufferString("retrieved withdrawal status request
for wopid=" + wopid).Bytes())
+}
+
+func handlePaymentNotification(res http.ResponseWriter, req *http.Request) {
+
+ wopid := req.PathValue(WOPID_PARAMETER)
+ if wopid == "" {
+ res.WriteHeader(common.HTTP_BAD_REQUEST)
+ return
+ }
+
+ res.WriteHeader(common.HTTP_OK)
+ res.Write(bytes.NewBufferString("retrieved payment notification for
wopid=" + wopid).Bytes())
+}
+
+func handleWithdrawalAbort(res http.ResponseWriter, req *http.Request) {
+
+ res.WriteHeader(common.HTTP_OK)
+ res.Write(bytes.NewBufferString("retrieved withdrawal operation
abortion request").Bytes())
+}
+
+// ----------------------
+// OFFICIAL MODELS
+// ----------------------
+//
https://docs.taler.net/core/api-bank-integration.html#tsref-type-BankWithdrawalOperationPostRequest
+type BankWithdrawalOperationPostRequest struct {
+ ReservePub string `json:"reserve_pub"`
+ SelectedExchange string `json:"selected_exchange"`
+}
+
+//
https://docs.taler.net/core/api-bank-integration.html#tsref-type-BankWithdrawalOperationPostResponse
+type BankWithdrawalOperationPostResponse struct {
+ Status common.WithdrawalOperationStatus `json:"status"`
+ ConfirmTransferUrl string
`json:"confirm_transfer_url"`
+ TransferDone bool
`json:"transfer_done"`
+}
+
+//
https://docs.taler.net/core/api-bank-integration.html#tsref-type-BankWithdrawalOperationStatus
+type BankWithdrawalOperationStatus struct {
+ Status common.WithdrawalOperationStatus `json:"status"`
+ Amount common.Amount `json:"amount"`
+ SenderWire string
`json:"sender_wire"`
+ SuggestedExchange string
`json:"suggested_exchange"`
+ ConfirmTransferUrl string
`json:"confirm_transfer_url"`
+ WireTypes []string
`json:"wire_types"`
+ SelectedReservePub string
`json:"selected_reserve_pub"`
+ SelectedExchangeAccount string
`json:"selected_exchange_account"`
+ Aborted bool
`json:"aborted"`
+ SelectionDone bool
`json:"selection_done"`
+ TransferDone bool
`json:"transfer_done"`
+}
diff --git a/c2ec/c2ec-config.yaml b/c2ec/c2ec-config.yaml
new file mode 100644
index 0000000..8692007
--- /dev/null
+++ b/c2ec/c2ec-config.yaml
@@ -0,0 +1,10 @@
+c2ec:
+ host: "localhost"
+ port: 8081
+ unix-domain-socket: true
+ unix-socket-path: "c2ec.sock"
+db:
+ host: "localhost"
+ port: 5432
+ username: "user"
+ password: "password"
diff --git a/nonce2ecash/pkg/common/amount.go b/c2ec/common/amount.go
similarity index 97%
rename from nonce2ecash/pkg/common/amount.go
rename to c2ec/common/amount.go
index c9b6af5..a79e8a3 100644
--- a/nonce2ecash/pkg/common/amount.go
+++ b/c2ec/common/amount.go
@@ -31,13 +31,13 @@ import (
type Amount struct {
// The type of currency, e.g. EUR
- Currency string
+ Currency string `json:"currency"`
// The value (before the ".")
- Value uint64
+ Value uint64 `json:"value"`
// The fraction (after the ".", optional)
- Fraction uint64
+ Fraction uint64 `json:"fraction"`
}
// The maximim length of a fraction (in digits)
diff --git a/nonce2ecash/pkg/common/amount_test.go b/c2ec/common/amount_test.go
similarity index 100%
rename from nonce2ecash/pkg/common/amount_test.go
rename to c2ec/common/amount_test.go
diff --git a/nonce2ecash/pkg/common/codec.go b/c2ec/common/codec.go
similarity index 100%
rename from nonce2ecash/pkg/common/codec.go
rename to c2ec/common/codec.go
diff --git a/nonce2ecash/pkg/common/codec_test.go b/c2ec/common/codec_test.go
similarity index 97%
rename from nonce2ecash/pkg/common/codec_test.go
rename to c2ec/common/codec_test.go
index accb2aa..43962c2 100644
--- a/nonce2ecash/pkg/common/codec_test.go
+++ b/c2ec/common/codec_test.go
@@ -2,8 +2,9 @@ package common_test
import (
"bytes"
+ "c2ec/common"
"fmt"
- "nonce2ecash/pkg/common"
+
"testing"
"gotest.tools/v3/assert"
diff --git a/nonce2ecash/pkg/common/http-util.go b/c2ec/common/http-util.go
similarity index 73%
rename from nonce2ecash/pkg/common/http-util.go
rename to c2ec/common/http-util.go
index 8f7dafa..5aabc4d 100644
--- a/nonce2ecash/pkg/common/http-util.go
+++ b/c2ec/common/http-util.go
@@ -1,6 +1,7 @@
package common
import (
+ "bytes"
"errors"
"fmt"
"net/http"
@@ -16,6 +17,63 @@ const HTTP_METHOD_NOT_ALLOWED = 405
const HTTP_CONFLICT = 409
const HTTP_INTERNAL_SERVER_ERROR = 500
+const TALER_URI_PROBLEM_PREFIX = "taler://problem"
+
+type RFC9457Problem struct {
+ TypeUri string `json:"type"`
+ Title string `json:"title"`
+ Detail string `json:"detail"`
+ Instance string `json:"instance"`
+}
+
+// Writes a problem as specified by RFC 9457 to
+// the response. The problem is always serialized
+// as JSON.
+func WriteProblem(res http.ResponseWriter, status int, problem
*RFC9457Problem) error {
+
+ c := NewJsonCodec[RFC9457Problem]()
+ problm, err := c.EncodeToBytes(problem)
+ if err != nil {
+ return err
+ }
+
+ res.Write(problm)
+ res.WriteHeader(status)
+ return nil
+}
+
+// Reads a generic argument struct from the requests
+// body. It takes the codec as argument which is used to
+// decode the struct from the request. If an error occurs
+// nil and the error are returned.
+func ReadStructFromBody[T any](req *http.Request, codec Codec[T]) (*T, error) {
+
+ bodyBytes, err := ReadBody(req)
+ if err != nil {
+ return nil, err
+ }
+
+ return codec.Decode(bytes.NewReader(bodyBytes))
+}
+
+// Reads the body of a request into a byte array.
+// If the body is empty, an empty array is returned.
+// If an error occurs while reading the body, nil and
+// the respective error is returned.
+func ReadBody(req *http.Request) ([]byte, error) {
+
+ if req.ContentLength < 0 {
+ return make([]byte, 0), nil
+ }
+
+ body := make([]byte, req.ContentLength)
+ _, err := req.Body.Read(body)
+ if err != nil {
+ return nil, err
+ }
+ return body, nil
+}
+
// execute a GET request and parse body or retrieve error
func HttpGet2[T any](
req string,
diff --git a/nonce2ecash/pkg/common/http-util_test.go
b/c2ec/common/http-util_test.go
similarity index 97%
rename from nonce2ecash/pkg/common/http-util_test.go
rename to c2ec/common/http-util_test.go
index 88fa1b6..6b8379c 100644
--- a/nonce2ecash/pkg/common/http-util_test.go
+++ b/c2ec/common/http-util_test.go
@@ -1,8 +1,8 @@
package common_test
import (
+ "c2ec/common"
"fmt"
- "nonce2ecash/pkg/common"
"testing"
)
diff --git a/c2ec/common/model.go b/c2ec/common/model.go
new file mode 100644
index 0000000..6b08af3
--- /dev/null
+++ b/c2ec/common/model.go
@@ -0,0 +1,72 @@
+package common
+
+// https://docs.taler.net/core/api-common.html#hash-codes
+type WithdrawalIdentifier string
+
+// https://docs.taler.net/core/api-common.html#cryptographic-primitives
+type EddsaPublicKey string
+
+// https://docs.taler.net/core/api-common.html#hash-codes
+type HashCode string
+
+// https://docs.taler.net/core/api-common.html#hash-codes
+type ShortHashCode string
+
+// https://docs.taler.net/core/api-common.html#timestamps
+type Timestamp struct {
+ Ts int `json:"t_s"`
+}
+
+// https://docs.taler.net/core/api-common.html#wadid
+type WadId [6]uint32
+
+// according to
https://docs.taler.net/core/api-bank-integration.html#tsref-type-BankWithdrawalOperationStatus
+type WithdrawalOperationStatus string
+
+const (
+ PENDING WithdrawalOperationStatus = "pending"
+ SELECTED WithdrawalOperationStatus = "selected"
+ ABORTED WithdrawalOperationStatus = "aborted"
+ CONFIRMED WithdrawalOperationStatus = "confirmed"
+)
+
+type ErrorDetail struct {
+
+ // Numeric error code unique to the condition.
+ // The other arguments are specific to the error value reported here.
+ Code int `json:"code"`
+
+ // Human-readable description of the error, i.e. "missing parameter",
"commitment violation", ...
+ // Should give a human-readable hint about the error's nature.
Optional, may change without notice!
+ Hint string `json:"hint"`
+
+ // Optional detail about the specific input value that failed. May
change without notice!
+ Detail string `json:"detail"`
+
+ // Name of the parameter that was bogus (if applicable).
+ Parameter string `json:"parameter"`
+
+ // Path to the argument that was bogus (if applicable).
+ Path string `json:"path"`
+
+ // Offset of the argument that was bogus (if applicable).
+ Offset string `json:"offset"`
+
+ // Index of the argument that was bogus (if applicable).
+ Index string `json:"index"`
+
+ // Name of the object that was bogus (if applicable).
+ Object string `json:"object"`
+
+ // Name of the currency that was problematic (if applicable).
+ Currency string `json:"currency"`
+
+ // Expected type (if applicable).
+ TypeExpected string `json:"type_expected"`
+
+ // Type that was provided instead (if applicable).
+ TypeActual string `json:"type_actual"`
+
+ // Extra information that doesn't fit into the above (if applicable).
+ Extra []byte `json:"extra"`
+}
diff --git a/c2ec/config.go b/c2ec/config.go
new file mode 100644
index 0000000..4a85996
--- /dev/null
+++ b/c2ec/config.go
@@ -0,0 +1,76 @@
+package main
+
+import (
+ "os"
+ "strconv"
+ "strings"
+
+ "gopkg.in/yaml.v3"
+)
+
+const POSTGRESQL_SCHEME = "postgres://"
+const NONCE2ECASH_DATABASE = "nonce2ecash"
+
+type C2ECConfig struct {
+ Server C2ECServerConfig `yaml:"c2ec"`
+ Database C2ECDatabseConfig `yaml:"db"`
+}
+
+type C2ECServerConfig struct {
+ Host string `yaml:"host"`
+ Port int `yaml:"port"`
+ UseUnixDomainSocket bool `yaml:"unix-domain-socket"`
+ UnixSocketPath string `yaml:"unix-socket-path"`
+}
+
+type C2ECDatabseConfig struct {
+ Host string `yaml:"host"`
+ Port int `yaml:"port"`
+ Username string `yaml:"username"`
+ Password string `yaml:"password"`
+}
+
+func Parse(path string) (*C2ECConfig, error) {
+
+ f, err := os.Open(path)
+ if err != nil {
+ return nil, err
+ }
+ defer f.Close()
+
+ stat, err := f.Stat()
+ if err != nil {
+ return nil, err
+ }
+
+ content := make([]byte, stat.Size())
+ _, err = f.Read(content)
+ if err != nil {
+ return nil, err
+ }
+
+ cfg := new(C2ECConfig)
+ err = yaml.Unmarshal(content, cfg)
+ if err != nil {
+ return nil, err
+ }
+
+ return cfg, nil
+}
+
+func DBConnectionString(cfg *C2ECDatabseConfig) string {
+
+ // format: postgres://username:password@hostname:port/database_name
+ return strings.Join([]string{
+ POSTGRESQL_SCHEME,
+ cfg.Username,
+ ":",
+ cfg.Password,
+ "@",
+ cfg.Host,
+ ":",
+ strconv.FormatInt(int64(cfg.Port), 10),
+ "/",
+ NONCE2ECASH_DATABASE,
+ }, "")
+}
diff --git a/c2ec/db.go b/c2ec/db.go
new file mode 100644
index 0000000..866800e
--- /dev/null
+++ b/c2ec/db.go
@@ -0,0 +1,48 @@
+package main
+
+import "c2ec/common"
+
+type TerminalProvider struct {
+ ProviderTerminalID int64
+ Name string
+ BackendBaseURL string
+ BackendCredentials string
+}
+
+type Terminal struct {
+ TerminalID int64
+ AccessToken []byte
+ Active bool
+ ProviderID int64
+ Provider TerminalProvider
+ Description string
+}
+
+type Withdrawal struct {
+ WithdrawalId []byte
+ ReservePubKey []byte
+ RegistrationTs int64
+ Amount TalerAmountCurrency
+ Fees TalerAmountCurrency
+ WithdrawalStatus common.WithdrawalOperationStatus
+ TerminalId int64
+ ProviderTransactionId string
+ LastRetryTs int64
+ RetryCounter int32
+ CompletionProof []byte
+}
+
+type TalerAmountCurrency struct {
+ Val int64
+ Frac int32
+ Curr string
+}
+
+type C2ECDatabase interface {
+ RegisterWithdrawal(r *C2ECWithdrawRegistration) error
+ GetWithdrawalByWopid(wopid string) (*Withdrawal, error)
+ ConfirmPayment(c *C2ECPaymentNotification) error
+ GetUnconfirmedWithdrawals() ([]*Withdrawal, error)
+ GetTerminalProviderById(id int) (*TerminalProvider, error)
+ GetTerminalById(id int) (*Terminal, error)
+}
diff --git a/nonce2ecash/go.mod b/c2ec/go.mod
similarity index 78%
rename from nonce2ecash/go.mod
rename to c2ec/go.mod
index 8eb0dc2..8dc7a99 100644
--- a/nonce2ecash/go.mod
+++ b/c2ec/go.mod
@@ -1,4 +1,4 @@
-module nonce2ecash
+module c2ec
go 1.22.0
@@ -8,11 +8,14 @@ require (
github.com/google/go-cmp v0.5.9 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a //
indirect
+ github.com/jackc/pgx v3.6.2+incompatible // indirect
github.com/jackc/pgx/v5 v5.5.5 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/lib/pq v1.10.9 // indirect
+ github.com/pkg/errors v0.9.1 // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/text v0.14.0 // indirect
+ gopkg.in/yaml.v3 v3.0.1 // indirect
gorm.io/gorm v1.25.7 // indirect
)
diff --git a/nonce2ecash/go.sum b/c2ec/go.sum
similarity index 83%
rename from nonce2ecash/go.sum
rename to c2ec/go.sum
index 39d4d5f..c967af9 100644
--- a/nonce2ecash/go.sum
+++ b/c2ec/go.sum
@@ -5,6 +5,8 @@ github.com/jackc/pgpassfile v1.0.0
h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
github.com/jackc/pgpassfile v1.0.0/go.mod
h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a
h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod
h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
+github.com/jackc/pgx v3.6.2+incompatible
h1:2zP5OD7kiyR3xzRYMhOcXVvkDZsImVXfj+yIyTQf3/o=
+github.com/jackc/pgx v3.6.2+incompatible/go.mod
h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
github.com/jackc/pgx/v5 v5.5.5/go.mod
h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
github.com/jinzhu/inflection v1.0.0
h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
@@ -13,6 +15,8 @@ github.com/jinzhu/now v1.1.5
h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod
h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod
h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod
h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod
h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod
h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod
h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@@ -23,6 +27,8 @@ golang.org/x/text v0.14.0
h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod
h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod
h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod
h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/gorm v1.25.7 h1:VsD6acwRjz2zFxGO50gPO6AkNs7KKnvfzUjHQhZDz/A=
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
diff --git a/c2ec/main.go b/c2ec/main.go
new file mode 100644
index 0000000..d8e55f1
--- /dev/null
+++ b/c2ec/main.go
@@ -0,0 +1,145 @@
+package main
+
+import (
+ "fmt"
+ "net"
+ http "net/http"
+ "os"
+ "os/signal"
+ "syscall"
+)
+
+const GET = "GET "
+const POST = "POST "
+
+const BANK_INTEGRATION_API = "/c2ec"
+const WIRE_GATEWAY_API = "/wire"
+
+const DEFAULT_C2EC_CONFIG_PATH = "c2ec-config.yaml"
+
+var DB C2ECDatabase
+
+// Starts the c2ec process.
+// The program takes following arguments (ordered):
+// 1. path to configuration file (.yaml) (optional)
+//
+// The startup follows these steps:
+// 1. load configuration or panic
+// 2. setup database or panic
+// 3. setup routes for the bank-integration-api
+// 4. setup routes for the wire-gateway-api
+// 5. listen for incoming requests (as specified in config)
+func main() {
+
+ cfgPath := DEFAULT_C2EC_CONFIG_PATH
+ if len(os.Args) > 1 && os.Args[1] != "" {
+ cfgPath = os.Args[1]
+ }
+ cfg, err := Parse(cfgPath)
+ if err != nil {
+ panic("unable to load config: " + err.Error())
+ }
+
+ DB, err = setupDatabase()
+ if err != nil {
+ panic("unable initialize datatbase: " + err.Error())
+ }
+
+ router := http.NewServeMux()
+
+ setupBankIntegrationRoutes(router)
+
+ setupWireGatewayRoutes(router)
+
+ server := http.Server{
+ Handler: router,
+ }
+
+ if cfg.Server.UseUnixDomainSocket {
+
+ socket, err := net.Listen("unix", cfg.Server.UnixSocketPath)
+ if err != nil {
+ panic("failed listening on socket: " + err.Error())
+ }
+
+ // cleans up socket when process fails and is shutdown.
+ c := make(chan os.Signal, 1)
+ signal.Notify(c, os.Interrupt, syscall.SIGTERM)
+ go func() {
+ <-c
+ os.Remove(cfg.Server.UnixSocketPath)
+ os.Exit(1)
+ }()
+
+ if err = server.Serve(socket); err != nil {
+ panic(err.Error())
+ }
+ } else {
+
+ server.Addr = fmt.Sprintf("%s:%d", cfg.Server.Host,
cfg.Server.Port)
+ if err = server.ListenAndServe(); err != nil {
+ panic(err.Error())
+ }
+ }
+}
+
+func setupDatabase() (C2ECDatabase, error) {
+
+ return nil, nil
+}
+
+func setupBankIntegrationRoutes(router *http.ServeMux) {
+
+ router.HandleFunc(
+ GET+BANK_INTEGRATION_API+BANK_INTEGRATION_CONFIG_PATTERN,
+ bankIntegrationConfig,
+ )
+
+ router.HandleFunc(
+ POST+BANK_INTEGRATION_API+WITHDRAWAL_OPERATION_PATTERN,
+ handleWithdrawalRegistration,
+ )
+
+ router.HandleFunc(
+ GET+BANK_INTEGRATION_API+WITHDRAWAL_OPERATION_BY_WOPID_PATTERN,
+ handleWithdrawalStatus,
+ )
+
+ router.HandleFunc(
+ POST+BANK_INTEGRATION_API+WITHDRAWAL_OPERATION_BY_WOPID_PATTERN,
+ handlePaymentNotification,
+ )
+
+ router.HandleFunc(
+ POST+BANK_INTEGRATION_API+WITHDRAWAL_OPERATION_ABORTION_PATTERN,
+ handleWithdrawalAbort,
+ )
+}
+
+func setupWireGatewayRoutes(router *http.ServeMux) {
+
+ router.HandleFunc(
+ GET+WIRE_GATEWAY_API+WIRE_GATEWAY_CONFIG_PATTERN,
+ wireGatewayConfig,
+ )
+
+ router.HandleFunc(
+ POST+WIRE_GATEWAY_API+WIRE_TRANSFER_PATTERN,
+ transfer,
+ )
+
+ router.HandleFunc(
+ GET+WIRE_GATEWAY_API+WIRE_HISTORY_INCOMING_PATTERN,
+ historyIncoming,
+ )
+
+ router.HandleFunc(
+ GET+WIRE_GATEWAY_API+WIRE_HISTORY_OUTGOING_PATTERN,
+ historyOutgoing,
+ )
+
+ router.HandleFunc(
+ POST+WIRE_GATEWAY_API+WIRE_ADMIN_ADD_INCOMING_PATTERN,
+ adminAddIncoming,
+ )
+}
diff --git a/c2ec/postgres.go b/c2ec/postgres.go
new file mode 100644
index 0000000..845a415
--- /dev/null
+++ b/c2ec/postgres.go
@@ -0,0 +1,52 @@
+package main
+
+import (
+ "errors"
+ "time"
+
+ pgx "github.com/jackc/pgx"
+)
+
+const PS_INSERT_WITHDRAWAL = "INSERT INTO withdrawal " +
+ "(wopid, reserve_pub_key, registration_ts, amount, terminal_id)" +
+ " VALUES ($1, $2, $3, $4, $5)"
+
+const PS_GET_WITHDRAWAL_BY_ID = ""
+
+// Postgres implementation of the C2ECDatabase
+type C2ECPostgres struct {
+ C2ECDatabase
+
+ ConnPool *pgx.ConnPool
+}
+
+func (db *C2ECPostgres) RegisterWithdrawal(r *C2ECWithdrawRegistration) error {
+
+ ts := time.Now()
+ res, err := db.ConnPool.Query(
+ PS_INSERT_WITHDRAWAL,
+ r.Wopid,
+ r.ReservePubKey,
+ ts,
+ r.Amount,
+ r.ProviderId,
+ )
+ defer res.Close()
+
+ return err
+}
+
+func (db *C2ECPostgres) GetWithdrawalByWopid(wopid string) (*Withdrawal,
error) {
+
+ return nil, errors.New("not yet implemented")
+}
+
+func (db *C2ECPostgres) ConfirmPayment(c *C2ECPaymentNotification) error {
+
+ return errors.New("not yet implemented")
+}
+
+func (db *C2ECPostgres) GetUnconfirmedWithdrawals() ([]*Withdrawal, error) {
+
+ return nil, errors.New("not yet implemented")
+}
diff --git a/nonce2ecash/pkg/taler-wirewatch-gateway/model.go
b/c2ec/wire-gateway.go
similarity index 60%
rename from nonce2ecash/pkg/taler-wirewatch-gateway/model.go
rename to c2ec/wire-gateway.go
index 84a9250..94fe58a 100644
--- a/nonce2ecash/pkg/taler-wirewatch-gateway/model.go
+++ b/c2ec/wire-gateway.go
@@ -1,6 +1,20 @@
-package talerwirewatchgateway
+package main
-import "nonce2ecash/pkg/common"
+import (
+ "bytes"
+ "c2ec/common"
+ "log"
+ http "net/http"
+)
+
+const WIRE_GATEWAY_CONFIG_ENDPOINT = "/config"
+const WIRE_GATEWAY_HISTORY_ENDPOINT = "/history"
+
+const WIRE_GATEWAY_CONFIG_PATTERN = WIRE_GATEWAY_CONFIG_ENDPOINT
+const WIRE_TRANSFER_PATTERN = "/transfer"
+const WIRE_HISTORY_INCOMING_PATTERN = WIRE_GATEWAY_HISTORY_ENDPOINT +
"/incoming"
+const WIRE_HISTORY_OUTGOING_PATTERN = WIRE_GATEWAY_HISTORY_ENDPOINT +
"/outgoing"
+const WIRE_ADMIN_ADD_INCOMING_PATTERN = "/admin/add-incoming"
// https://docs.taler.net/core/api-bank-wire.html#tsref-type-WireConfig
type WireConfig struct {
@@ -25,17 +39,10 @@ type TransferResponse struct {
RowId int `json:"row_id"`
}
-//
https://docs.taler.net/core/api-bank-wire.html#tsref-type-IncomingBankTransaction
-// type IncomingBankTransaction = IncomingReserveTransaction |
IncomingWadTransaction
-type IncomingBankTransaction struct {
- IncomingReserveTransaction
- IncomingWadTransaction
-}
-
// https://docs.taler.net/core/api-bank-wire.html#tsref-type-IncomingHistory
type IncomingHistory struct {
- IncomingTransactions []IncomingBankTransaction
`json:"incoming_transactions"`
- CreditAccount string `json:"credit_account"`
+ IncomingTransactions []IncomingReserveTransaction
`json:"incoming_transactions"`
+ CreditAccount string
`json:"credit_account"`
}
// type RESERVE |
https://docs.taler.net/core/api-bank-wire.html#tsref-type-IncomingReserveTransaction
@@ -48,18 +55,6 @@ type IncomingReserveTransaction struct {
ReservePub common.EddsaPublicKey `json:"reserve_pub"`
}
-// type WAD |
https://docs.taler.net/core/api-bank-wire.html#tsref-type-IncomingWadTransaction
-type IncomingWadTransaction struct {
- Type string `json:"type"`
- RowId int `json:"row_id"`
- Date common.Timestamp `json:"date"`
- Amount common.Amount `json:"amount"`
- CreditAccount string `json:"credit_account"`
- DebitAccount string `json:"debit_account"`
- OriginExchangeUrl string `json:"origin_exchange_url"`
- WadId common.WadId `json:"wad_id"`
-}
-
// https://docs.taler.net/core/api-bank-wire.html#tsref-type-OutgoingHistory
type OutgoingHistory struct {
OutgoingBankTransaction []OutgoingBankTransaction
`json:"outgoing_bank_transaction"`
@@ -76,6 +71,42 @@ type OutgoingBankTransaction struct {
ExchangeBaseUrl string `json:"exchange_base_url"`
}
+func wireGatewayConfig(res http.ResponseWriter, req *http.Request) {
+
+ cfg := WireConfig{
+ Name: "taler-wire-gateway",
+ Version: "0:0:1",
+ }
+
+ serializedCfg, err :=
common.NewJsonCodec[WireConfig]().EncodeToBytes(&cfg)
+ if err != nil {
+ log.Default().Printf("failed serializing config: %s",
err.Error())
+ res.WriteHeader(common.HTTP_INTERNAL_SERVER_ERROR)
+ return
+ }
+
+ res.WriteHeader(common.HTTP_OK)
+ res.Write(serializedCfg)
+}
+
+func transfer(res http.ResponseWriter, req *http.Request) {
+
+ res.WriteHeader(common.HTTP_OK)
+ res.Write(bytes.NewBufferString("retrieved transfer request").Bytes())
+}
+
+func historyIncoming(res http.ResponseWriter, req *http.Request) {
+
+ res.WriteHeader(common.HTTP_OK)
+ res.Write(bytes.NewBufferString("retrieved history incoming
request").Bytes())
+}
+
+// This method is currently dead and implemented for API conformance
+func historyOutgoing(res http.ResponseWriter, req *http.Request) {
+
+ res.WriteHeader(common.HTTP_BAD_REQUEST)
+}
+
// ---------------------
// TESTING (ONLY ADMINS)
// ---------------------
@@ -91,3 +122,9 @@ type AddIncomingRequest struct {
type AddIncomingResponse struct {
Timestamp common.Timestamp `json:"timestamp"`
}
+
+// This method is currently dead and implemented for API conformance
+func adminAddIncoming(res http.ResponseWriter, req *http.Request) {
+
+ res.WriteHeader(common.HTTP_BAD_REQUEST)
+}
diff --git a/data/nonce2ecash_schema.sql b/data/c2ec_schema.sql
similarity index 83%
rename from data/nonce2ecash_schema.sql
rename to data/c2ec_schema.sql
index 71d338a..24a79b9 100644
--- a/data/nonce2ecash_schema.sql
+++ b/data/c2ec_schema.sql
@@ -1,11 +1,11 @@
-- => proper versioning.sql nehmen (siehe exchange.git),
-DROP SCHEMA IF EXISTS nonce2ecash CASCADE;
+DROP SCHEMA IF EXISTS c2ec CASCADE;
-CREATE SCHEMA nonce2ecash;
-COMMENT ON SCHEMA nonce2ecash
- IS 'Schema containing all tables and types related to nonce2ecash';
+CREATE SCHEMA c2ec;
+COMMENT ON SCHEMA c2ec
+ IS 'Schema containing all tables and types related to c2ec (cashless2ecash)';
-SET search_path TO nonce2ecash;
+SET search_path TO c2ec;
CREATE TYPE withdrawal_operation_status AS ENUM (
'pending',
@@ -36,7 +36,7 @@ CREATE TABLE IF NOT EXISTS terminal_provider (
backend_credentials TEXT NOT NULL
);
COMMENT ON TABLE terminal_provider
- IS 'Table describing providers of nonce2ecash terminal';
+ IS 'Table describing providers of c2ec terminal';
COMMENT ON COLUMN terminal_provider.provider_terminal_id
IS 'Uniquely identifies a provider';
COMMENT ON COLUMN terminal_provider.name
@@ -59,7 +59,7 @@ COMMENT ON TABLE terminal
COMMENT ON COLUMN terminal.terminal_id
IS 'Uniquely identifies a terminal';
COMMENT ON COLUMN terminal.access_token
- IS 'The access token of the terminal used for authentication against the
nonce2ecash API';
+ IS 'The access token of the terminal used for authentication against the
c2ec API';
COMMENT ON COLUMN terminal.active
IS 'Indicates if the terminal is active or deactivated';
COMMENT ON COLUMN terminal.description
@@ -69,12 +69,13 @@ COMMENT ON COLUMN terminal.provider_id
CREATE TABLE IF NOT EXISTS withdrawal (
- withdrawal_id BYTEA PRIMARY KEY CHECK (LENGTH(withdrawal_id)=32),
+ withdrawal_id INT8 GENERATED VALUE BY DEFAULT AS IDENTITY PRIMARY KEY,
+ wopid BYTEA CHECK (LENGTH(wopid)=32) NOT NULL,
reserve_pub_key BYTEA CHECK (LENGTH(reserve_pub_key)=32) NOT NULL,
registration_ts INT8 NOT NULL,
amount taler_amount_currency NOT NULL,
- fees taler_amount_currency NOT NULL,
- withdrawal_status withdrawal_operation_status NOT NULL,
+ fees taler_amount_currency,
+ withdrawal_status withdrawal_operation_status NOT NULL DEFAULT 'pending',
terminal_id INT8 NOT NULL REFERENCES terminal(terminal_id),
provider_transaction_id TEXT,
last_retry_ts INT8,
@@ -84,7 +85,10 @@ CREATE TABLE IF NOT EXISTS withdrawal (
COMMENT ON TABLE withdrawal
IS 'Table representing withdrawal processes initiated by terminals';
COMMENT ON COLUMN withdrawal.withdrawal_id
- IS 'The withdrawal id is a nonce generated by the terminal requesting a
withdrawal';
+ IS 'The withdrawal id is used a technical id used by the wire gateway to
sequentially select new transactions';
+COMMENT ON COLUMN withdrawal.wopid
+ IS 'The wopid (withdrawal operation id) is a nonce generated by the terminal
requesting a withdrawal. '+
+ 'The wopid identifies a specific withdrawal spawning all involved
systems.';
COMMENT ON COLUMN withdrawal.reserve_pub_key
IS 'Reserve public key for the reserve which will hold the withdrawal amount
after completion';
COMMENT ON COLUMN withdrawal.registration_ts
diff --git a/docs/content/architecture/c2ec.tex
b/docs/content/architecture/c2ec.tex
index 28b32c1..07368a5 100644
--- a/docs/content/architecture/c2ec.tex
+++ b/docs/content/architecture/c2ec.tex
@@ -10,7 +10,7 @@ A specification of the API in yaml format can be found in
\autoref*{appendix-api
Terminals which authenticate against the C2EC API must provide their
respective access token. Therefore, they provide a \texttt{Authorization:
Bearer \$ACCESS\_TOKEN} header, where \texttt{\$ACCESS\_TOKEN} is a secret
authentication token configured by the exchange and must begin with the prefix
specified in RFC 8959 \cite{rfc8959}: \textit{secret-token}.
-\subsubsection{Configuration of C2EC}
+\subsubsection{Configuration of C2EC Bank Integration API}
\begin{itemize}
\item \textbf{Method:} GET
@@ -19,9 +19,9 @@ Terminals which authenticate against the C2EC API must
provide their respective
\item \textbf{Response:} HTTP status code 200 OK. The exchange responds with
a \texttt{C2ECConfig} object.
\end{itemize}
-\subsubsection{Withdrawing using C2EC}
+\subsubsection{Taler Bank Integration API}
-Withdrawals with a C2EC are based on withdrawal operations which register a
withdrawal identifier (nonce) at the C2EC component. The provider must first
create a unique identifier for the withdrawal operation (the
\texttt{WITHDRAWAL\_ID}) to interact with the withdrawal operation and
eventually withdraw using the wallet.
+Withdrawals with a C2EC are based on withdrawal operations which register a
withdrawal identifier (nonce) at the C2EC component. The provider must first
create a unique identifier for the withdrawal operation (the
\texttt{WITHDRAWAL\_ID}) to interact with the withdrawal operation and
eventually withdraw using the wallet. The withdrawal operation API is an
implementation of the Bank Integration API \cite{taler-bank-integration-api}.
\textbf{POST - withdrawal-operation}
\begin{itemize}
@@ -52,10 +52,14 @@ Withdrawals with a C2EC are based on withdrawal operations
which register a with
\subsection{Taler Wirewatch Gateway API}
The Taler Wirewatch Gateway \cite{taler-wirewatch-gateway-api} must be
implemented in order to capture incoming transactions and allow the withdrawal
of money. The specification of the Taler Wirewatch Gateway can be found in the
official Taler documentation \cite{taler-wirewatch-gateway-api}.
-The wirewatch gateway helps the Exchange communicate with the C2EC component
using a the API. It helps the Exchange to get guarantees, that a certain
transaction went through and that the reserve can be created and withdrawn.
This will help C2EC to capture the transaction of the Terminal Backend to the
Exchange's account and therefore allow the withdrawal by the customer.
Therefore the wirewatch gateway API is used in C2EC. When the wirewatch gateway
can get the proof, that a transaction [...]
+The wirewatch gateway helps the Exchange communicate with the C2EC component
using a the API. It helps the Exchange to fetch guarantees, that a certain
transaction went through and that the reserve can be created and withdrawn.
This will help C2EC to capture the transaction of the Terminal Backend to the
Exchange's account and therefore allow the withdrawal by the customer.
Therefore the wirewatch gateway API is used in C2EC. When the wirewatch gateway
can get the proof, that a transacti [...]
+
+For C2EC not all endpoints of the Wire Gateway API are needed. Therefore the
endoints which are not needed will be implemented but always return http status
code 400 with explanatory error details as specified by the specification.
+
+\subsubsection{Configuration of C2EC Wire Gateway API}
+
+\subsubsection{Taler Bank Integration API}
-\subsection{Taler Bank Integration API}
-The Taler Bank Integration \cite{taler-bank-integration-api} must be
implemented in order to allow the Wallet to withdraw money using already
implemented flows. The wallet will use the implementation of the Bank
Integration API to withdraw. The documentation for the Bank Integration API can
also be found in the official Taler documentation.
\subsection{The C2EC database}
diff --git a/docs/thesis.pdf b/docs/thesis.pdf
index 9f1cd5f..248e2f8 100644
Binary files a/docs/thesis.pdf and b/docs/thesis.pdf differ
diff --git a/nonce2ecash/pkg/common/model.go b/nonce2ecash/pkg/common/model.go
deleted file mode 100644
index c3a1bab..0000000
--- a/nonce2ecash/pkg/common/model.go
+++ /dev/null
@@ -1,31 +0,0 @@
-package common
-
-// https://docs.taler.net/core/api-common.html#hash-codes
-type WithdrawalIdentifier string
-
-// https://docs.taler.net/core/api-common.html#cryptographic-primitives
-type EddsaPublicKey string
-
-// https://docs.taler.net/core/api-common.html#hash-codes
-type HashCode string
-
-// https://docs.taler.net/core/api-common.html#hash-codes
-type ShortHashCode string
-
-// https://docs.taler.net/core/api-common.html#timestamps
-type Timestamp struct {
- Ts int `json:"t_s"`
-}
-
-// https://docs.taler.net/core/api-common.html#wadid
-type WadId [6]uint32
-
-// according to
https://docs.taler.net/core/api-bank-integration.html#tsref-type-BankWithdrawalOperationStatus
-type WithdrawalOperationStatus string
-
-const (
- PENDING WithdrawalOperationStatus = "pending"
- SELECTED WithdrawalOperationStatus = "selected"
- ABORTED WithdrawalOperationStatus = "aborted"
- CONFIRMED WithdrawalOperationStatus = "confirmed"
-)
diff --git a/nonce2ecash/pkg/db/db.go b/nonce2ecash/pkg/db/db.go
deleted file mode 100644
index 0d5a07b..0000000
--- a/nonce2ecash/pkg/db/db.go
+++ /dev/null
@@ -1,66 +0,0 @@
-package db
-
-import (
- "context"
- "strconv"
- "strings"
-
- "github.com/jackc/pgx/v5"
-)
-
-const POSTGRESQL_SCHEME = "postgres://"
-const NONCE2ECASH_DATABASE = "nonce2ecash"
-
-type DatabaseConfig interface {
- ConnectionString() string
-}
-
-type PostgresNonce2ecashDatabaseConfig struct {
- DatabaseConfig
-
- host string
- username string
- password string
- port int
-}
-
-func NewDbConf(
- host string,
- port int,
- username string,
- password string,
-) DatabaseConfig {
-
- cfg := new(PostgresNonce2ecashDatabaseConfig)
- cfg.host = host
- cfg.port = port
- cfg.username = username
- cfg.password = password
-
- return cfg
-}
-
-func NewDb(cfg DatabaseConfig) (*pgx.Conn, error) {
-
- return pgx.Connect(
- context.Background(),
- cfg.ConnectionString(),
- )
-}
-
-func (cfg *PostgresNonce2ecashDatabaseConfig) ConnectionString() string {
-
- // format: postgres://username:password@hostname:port/database_name
- return strings.Join([]string{
- POSTGRESQL_SCHEME,
- cfg.username,
- ":",
- cfg.password,
- "@",
- cfg.host,
- ":",
- strconv.FormatInt(int64(cfg.port), 10),
- "/",
- NONCE2ECASH_DATABASE,
- }, "")
-}
diff --git a/nonce2ecash/pkg/db/provider.go b/nonce2ecash/pkg/db/provider.go
deleted file mode 100644
index e91eaca..0000000
--- a/nonce2ecash/pkg/db/provider.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package db
-
-import "gorm.io/gorm"
-
-type TerminalProvider struct {
- gorm.Model
-
- ProviderTerminalID int64 `gorm:"primaryKey"`
- Name string `gorm:"unique;not null"`
- BackendBaseURL string `gorm:"not null"`
- BackendCredentials string `gorm:"not null"`
-}
-
-type Terminal struct {
- gorm.Model
-
- TerminalID int64 `gorm:"primaryKey"`
- AccessToken []byte `gorm:"type:bytea;not
null;check:LENGTH(access_token)=32"`
- Active bool `gorm:"not null;default:true"`
- ProviderID int64 `gorm:"not null"`
- Provider TerminalProvider `gorm:"foreignKey:ProviderID"`
- Description string
-}
diff --git a/nonce2ecash/pkg/db/withdrawal.go b/nonce2ecash/pkg/db/withdrawal.go
deleted file mode 100644
index c696e7a..0000000
--- a/nonce2ecash/pkg/db/withdrawal.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package db
-
-import (
- "nonce2ecash/pkg/common"
-
- "gorm.io/gorm"
-)
-
-type Withdrawal struct {
- gorm.Model
-
- WithdrawalId []byte `gorm:"type:bytea;primaryKey"`
- ReservePubKey []byte `gorm:"type:bytea"`
- RegistrationTs int64
- Amount TalerAmountCurrency
- Fees TalerAmountCurrency
- WithdrawalStatus common.WithdrawalOperationStatus
- TerminalId int64
- ProviderTransactionId string
- LastRetryTs int64
- RetryCounter int32 `gorm:"default:0"`
- CompletionProof []byte `gorm:"type:blob"`
-}
-
-type TalerAmountCurrency struct {
- Val int64
- Frac int32
- Curr string `gorm:"size:12"`
-}
diff --git a/nonce2ecash/pkg/handler.go b/nonce2ecash/pkg/handler.go
deleted file mode 100644
index 67b0e60..0000000
--- a/nonce2ecash/pkg/handler.go
+++ /dev/null
@@ -1,70 +0,0 @@
-package main
-
-import (
- "bytes"
- "log"
- http "net/http"
- "nonce2ecash/pkg/common"
-)
-
-const CONFIG_ENDPOINT = "/config"
-const WITHDRAWAL_OPERATION = "/withdrawal-operation"
-
-const WOPID_PARAMETER = "wopid"
-const GET_CONFIG_PATTERN = GET + CONFIG_ENDPOINT
-const POST_WITHDRAWAL_OPERATION_PATTERN = POST + WITHDRAWAL_OPERATION
-const GET_WITHDRAWAL_OPERATION_BY_WOPID_PATTERN = GET + WITHDRAWAL_OPERATION +
"/{" + WOPID_PARAMETER + "}"
-const POST_WITHDRAWAL_OPERATION_BY_WOPID_PATTERN = POST + WITHDRAWAL_OPERATION
+ "/{" + WOPID_PARAMETER + "}"
-
-func config(res http.ResponseWriter, req *http.Request) {
-
- cfg := Nonce2ecashConfig{
- Name: "taler-nonce2ecash",
- Version: "0:0:1",
- }
-
- serializedCfg, err :=
common.NewJsonCodec[Nonce2ecashConfig]().EncodeToBytes(&cfg)
- if err != nil {
- log.Default().Printf("failed serializing config: %s",
err.Error())
- res.WriteHeader(common.HTTP_INTERNAL_SERVER_ERROR)
- return
- }
-
- res.WriteHeader(common.HTTP_OK)
- res.Write(serializedCfg)
-}
-
-func handleWithdrawalRegistration(res http.ResponseWriter, req *http.Request) {
-
- res.WriteHeader(common.HTTP_OK)
- res.Write(bytes.NewBufferString("retrieved withdrawal request").Bytes())
-}
-
-func handleWithdrawalStatus(res http.ResponseWriter, req *http.Request) {
-
- wopid := parseWopId(req)
- if wopid == "" {
- res.WriteHeader(common.HTTP_BAD_REQUEST)
- return
- }
-
- res.WriteHeader(common.HTTP_OK)
- res.Write(bytes.NewBufferString("retrieved withdrawal status request
for wopid=" + wopid).Bytes())
-}
-
-func handlePaymentNotification(res http.ResponseWriter, req *http.Request) {
-
- wopid := parseWopId(req)
- if wopid == "" {
- res.WriteHeader(common.HTTP_BAD_REQUEST)
- return
- }
-
- res.WriteHeader(common.HTTP_OK)
- res.Write(bytes.NewBufferString("retrieved payment notification for
wopid=" + wopid).Bytes())
-}
-
-func parseWopId(req *http.Request) string {
-
- return req.PathValue(WOPID_PARAMETER)
-}
diff --git a/nonce2ecash/pkg/main.go b/nonce2ecash/pkg/main.go
deleted file mode 100644
index 800a22f..0000000
--- a/nonce2ecash/pkg/main.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package main
-
-import (
- http "net/http"
-)
-
-const GET = "GET "
-const POST = "POST "
-
-func main() {
-
- http.HandleFunc(
- GET_CONFIG_PATTERN,
- config,
- )
-
- http.HandleFunc(
- POST_WITHDRAWAL_OPERATION_PATTERN,
- handleWithdrawalRegistration,
- )
-
- http.HandleFunc(
- GET_WITHDRAWAL_OPERATION_BY_WOPID_PATTERN,
- handleWithdrawalStatus,
- )
-
- http.HandleFunc(
- POST_WITHDRAWAL_OPERATION_BY_WOPID_PATTERN,
- handlePaymentNotification,
- )
-
- http.ListenAndServe(":8080", nil)
-}
diff --git a/nonce2ecash/pkg/model.go b/nonce2ecash/pkg/model.go
deleted file mode 100644
index f982784..0000000
--- a/nonce2ecash/pkg/model.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package main
-
-import "nonce2ecash/pkg/common"
-
-type Nonce2ecashConfig struct {
- Name string `json:"name"`
- Version string `json:"version"`
-}
-
-type WithdrawRegistration struct {
- WithdrawalId common.WithdrawalIdentifier `json:"withdrawal_id"`
- ReservePubKey common.EddsaPublicKey `json:"reserve_pub_key"`
- Amount common.Amount `json:"amount"`
- ProviderId uint64 `json:"provider_id"`
-}
-
-type Withdrawal struct {
- ReservePubKey common.EddsaPublicKey `json:"reserve_pub_key"`
-}
-
-type PaymentNotification struct {
- ProviderTransactionId string `json:"provider_transaction_id"`
- Amount common.Amount `json:"amount"`
- Fees common.Amount `json:"fees"`
-}
diff --git a/nonce2ecash/pkg/pkg b/nonce2ecash/pkg/pkg
deleted file mode 100755
index e92ee4d..0000000
Binary files a/nonce2ecash/pkg/pkg and /dev/null differ
diff --git a/nonce2ecash/pkg/taler-bank-integration/client.go
b/nonce2ecash/pkg/taler-bank-integration/client.go
deleted file mode 100644
index 66b823f..0000000
--- a/nonce2ecash/pkg/taler-bank-integration/client.go
+++ /dev/null
@@ -1,163 +0,0 @@
-package talerbankintegration
-
-import (
- "errors"
- "fmt"
- "nonce2ecash/pkg/common"
-)
-
-const WITHDRAWAL_ID_PATH_PARAM_NAME = "withdrawal_id"
-
-const TALER_BANK_INTEGRATION_CONFIG_API = "/config"
-const WITHDRAWAL_OPERATION_API = "/withdrawal-operation"
-const WITHDRAWAL_OPERATION_BY_ID_API = WITHDRAWAL_OPERATION_API + "/:" +
WITHDRAWAL_ID_PATH_PARAM_NAME
-const WITHDRAWAL_OPERATION_ABORT_BY_ID_API = WITHDRAWAL_OPERATION_BY_ID_API +
"/abort"
-
-type TalerBankIntegration interface {
- init(string)
-
- BankIntegrationConfig() (*BankIntegrationConfig, error)
- WithdrawalOperationStatus(common.WithdrawalIdentifier)
(*BankWithdrawalOperationStatus, error)
- WithdrawalOperationCreate(common.EddsaPublicKey, string)
(*BankWithdrawalOperationPostResponse, error)
- WithdrawalOperationAbort(common.WithdrawalIdentifier) error
-}
-
-type TalerBankIntegrationImpl struct {
- TalerBankIntegration
-
- exchangeBaseUrl string
-}
-
-func (tbi *TalerBankIntegrationImpl) BankIntegrationConfig()
(*BankIntegrationConfig, error) {
-
- cfg, status, err := common.HttpGet(
- tbi.exchangeBaseUrl+TALER_BANK_INTEGRATION_CONFIG_API,
- nil,
- nil,
- common.NewJsonCodec[BankIntegrationConfig](),
- )
-
- if err != nil {
- return nil, err
- }
-
- if status == common.HTTP_OK {
-
- return cfg, nil
- }
-
- return nil, fmt.Errorf("HTTP %d - unexpected", status)
-}
-
-// Initialize the taler bank integration implementation.
-// The exchangeBaseUrl will be used as target by the impl.
-func (tbi *TalerBankIntegrationImpl) init(exchangeBaseUrl string) {
-
- tbi.exchangeBaseUrl = exchangeBaseUrl
-}
-
-// check status of withdrawal
-func (tbi *TalerBankIntegrationImpl) WithdrawalOperationStatus(
- id common.WithdrawalIdentifier,
-) (*BankWithdrawalOperationStatus, error) {
-
- WithdrawalOperationStatus, status, err := common.HttpGet(
- tbi.exchangeBaseUrl+WITHDRAWAL_OPERATION_BY_ID_API,
- map[string]string{WITHDRAWAL_ID_PATH_PARAM_NAME: string(id)},
- nil,
- common.NewJsonCodec[BankWithdrawalOperationStatus](),
- )
-
- if err != nil {
- return nil, err
- }
-
- if status == common.HTTP_OK {
-
- return WithdrawalOperationStatus, nil
- }
-
- if status == common.HTTP_NOT_FOUND {
-
- return nil, errors.New("HTTP 404 - The operation was not found")
- }
-
- return nil, fmt.Errorf("HTTP %d - unexpected", status)
-}
-
-// send parameters for reserve to exchange core.
-func (tbi *TalerBankIntegrationImpl) WithdrawalOperationCreate(
- id common.WithdrawalIdentifier,
- reservePubKey common.EddsaPublicKey,
- exchangPayToAddress string,
-) (*BankWithdrawalOperationPostResponse, error) {
-
- bankWithdrawalOperationPostResponse, status, err := common.HttpPost(
- tbi.exchangeBaseUrl+WITHDRAWAL_OPERATION_BY_ID_API,
- map[string]string{WITHDRAWAL_ID_PATH_PARAM_NAME: string(id)},
- nil,
- &BankWithdrawalOperationPostRequest{
- string(reservePubKey),
- exchangPayToAddress,
- },
- common.NewJsonCodec[BankWithdrawalOperationPostRequest](),
- common.NewJsonCodec[BankWithdrawalOperationPostResponse](),
- )
-
- if err != nil {
- return nil, err
- }
-
- if status == common.HTTP_OK {
-
- return bankWithdrawalOperationPostResponse, nil
- }
-
- if status == common.HTTP_NOT_FOUND {
-
- return nil, errors.New("HTTP 404 - The operation was not found")
- }
-
- if status == common.HTTP_CONFLICT {
-
- return nil, errors.New("HTTP 409 - conflict")
- }
-
- return nil, fmt.Errorf("HTTP %d - unexpected", status)
-}
-
-// abort withdrawal
-func (tbi *TalerBankIntegrationImpl) WithdrawalOperationAbort(
- id common.WithdrawalIdentifier,
-) error {
-
- _, status, err := common.HttpPost[any, any](
- tbi.exchangeBaseUrl+WITHDRAWAL_OPERATION_BY_ID_API,
- map[string]string{WITHDRAWAL_ID_PATH_PARAM_NAME: string(id)},
- nil,
- nil,
- nil,
- nil,
- )
-
- if err != nil {
- return err
- }
-
- if status == common.HTTP_NO_CONTENT {
-
- return nil
- }
-
- if status == common.HTTP_NOT_FOUND {
-
- return errors.New("HTTP 404 - The withdrawal operation was not
found")
- }
-
- if status == common.HTTP_CONFLICT {
-
- return errors.New("HTTP 409 - The withdrawal operation has been
confirmed previously and can’t be aborted")
- }
-
- return fmt.Errorf("HTTP %d - unexpected", status)
-}
diff --git a/nonce2ecash/pkg/taler-bank-integration/model.go
b/nonce2ecash/pkg/taler-bank-integration/model.go
deleted file mode 100644
index 97614f1..0000000
--- a/nonce2ecash/pkg/taler-bank-integration/model.go
+++ /dev/null
@@ -1,50 +0,0 @@
-package talerbankintegration
-
-import "nonce2ecash/pkg/common"
-
-//
https://docs.taler.net/core/api-exchange.html#tsref-type-CurrencySpecification
-type CurrencySpecification struct {
- Name string `json:"name"`
- Currency string `json:"currency"`
- NumFractionalInputDigits int
`json:"num_fractional_input_digits"`
- NumFractionalNormalDigits int
`json:"num_fractional_normal_digits"`
- NumFractionalTrailingZeroDigits int
`json:"num_fractional_trailing_zero_digits"`
- AltUnitNames string `json:"alt_unit_names"`
-}
-
-//
https://docs.taler.net/core/api-bank-integration.html#tsref-type-BankIntegrationConfig
-type BankIntegrationConfig struct {
- Name string `json:"name"`
- Version string `json:"version"`
- Implementation string `json:"implementation"`
- Currency string `json:"currency"`
- CurrencySpecification CurrencySpecification
`json:"currency_specification"`
-}
-
-//
https://docs.taler.net/core/api-bank-integration.html#tsref-type-BankWithdrawalOperationPostRequest
-type BankWithdrawalOperationPostRequest struct {
- ReservePub string `json:"reserve_pub"`
- SelectedExchange string `json:"selected_exchange"`
-}
-
-//
https://docs.taler.net/core/api-bank-integration.html#tsref-type-BankWithdrawalOperationPostResponse
-type BankWithdrawalOperationPostResponse struct {
- Status common.WithdrawalOperationStatus `json:"status"`
- ConfirmTransferUrl string
`json:"confirm_transfer_url"`
- TransferDone bool
`json:"transfer_done"`
-}
-
-//
https://docs.taler.net/core/api-bank-integration.html#tsref-type-BankWithdrawalOperationStatus
-type BankWithdrawalOperationStatus struct {
- Status common.WithdrawalOperationStatus `json:"status"`
- Amount common.Amount `json:"amount"`
- SenderWire string
`json:"sender_wire"`
- SuggestedExchange string
`json:"suggested_exchange"`
- ConfirmTransferUrl string
`json:"confirm_transfer_url"`
- WireTypes []string
`json:"wire_types"`
- SelectedReservePub string
`json:"selected_reserve_pub"`
- SelectedExchangeAccount string
`json:"selected_exchange_account"`
- Aborted bool
`json:"aborted"`
- SelectionDone bool
`json:"selection_done"`
- TransferDone bool
`json:"transfer_done"`
-}
diff --git a/nonce2ecash/pkg/taler-wirewatch-gateway/client.go
b/nonce2ecash/pkg/taler-wirewatch-gateway/client.go
deleted file mode 100644
index 5892475..0000000
--- a/nonce2ecash/pkg/taler-wirewatch-gateway/client.go
+++ /dev/null
@@ -1,226 +0,0 @@
-package talerwirewatchgateway
-
-import (
- "errors"
- "fmt"
- "nonce2ecash/pkg/common"
- "strconv"
-)
-
-const WIRE_GATEWAY_START_QUERY = "start"
-const WIRE_GATEWAY_DELTA_QUERY = "delta"
-const WIRE_GATEWAY_LONGPOLL_QUERY = "long_poll_ms"
-
-const WIRE_GATEWAY_API = ""
-const WIRE_GATEWAY_API_CONFIG = WIRE_GATEWAY_API + "/config"
-const WIRE_GATEWAY_TRANSFER_API = WIRE_GATEWAY_API + "/transfer"
-const WIRE_GATEWAY_HISTORY_INCOMING_API = WIRE_GATEWAY_API +
"/history/incoming"
-const WIRE_GATEWAY_HISTORY_OUTGOING_API = WIRE_GATEWAY_API +
"/history/outgoing"
-
-type TalerWirewatchGateway interface {
- Init(string, string)
-
- WirewatchGatewayConfig() (*WireConfig, error)
- WirewatchGatewayTransfer(*TransferRequest) (*TransferResponse, error)
- WirewatchGatewayHistoryIncoming(int, int, int) (*IncomingHistory, error)
- WirewatchGatewayHistoryOutgoing(int, int, int) (*OutgoingHistory, error)
-}
-
-type TalerWirewatchGatewayImpl struct {
- TalerWirewatchGateway
-
- exchangeBaseUrl string
- authToken string
-}
-
-func NewWirewatchGateway(exchangeBaseUrl string, authToken string)
TalerWirewatchGateway {
-
- twg := new(TalerWirewatchGatewayImpl)
- twg.Init(exchangeBaseUrl, authToken)
- return twg
-}
-
-func (twg *TalerWirewatchGatewayImpl) Init(exchangeBaseUrl string, authToken
string) {
-
- twg.exchangeBaseUrl = exchangeBaseUrl
- twg.authToken = authToken
-}
-
-// https://docs.taler.net/core/api-bank-wire.html#making-transactions
-func (twg *TalerWirewatchGatewayImpl) WirewatchGatewayConfig() (*WireConfig,
error) {
-
- res, status, err := common.HttpGet2(
- WIRE_GATEWAY_API_CONFIG,
- common.NewJsonCodec[WireConfig](),
- )
-
- if err != nil {
- return nil, err
- }
-
- if status == common.HTTP_OK {
-
- return res, nil
- }
-
- return nil, fmt.Errorf("HTTP %d - unexpected", status)
-}
-
-// https://docs.taler.net/core/api-bank-wire.html#making-transactions
-func (twg *TalerWirewatchGatewayImpl) WirewatchGatewayTransfer(
- transferRequest *TransferRequest,
-) (*TransferResponse, error) {
-
- res, status, err := common.HttpPost2(
- WIRE_GATEWAY_TRANSFER_API,
- transferRequest,
- common.NewJsonCodec[TransferRequest](),
- common.NewJsonCodec[TransferResponse](),
- )
-
- if err != nil {
- return nil, err
- }
-
- if status == common.HTTP_OK {
-
- return res, nil
- }
-
- if status == common.HTTP_BAD_REQUEST {
-
- return nil, errors.New("request malformed")
- }
-
- if status == common.HTTP_UNAUTHORIZED {
-
- return nil, errors.New("authentication failed, likely the
credentials are wrong")
- }
-
- if status == common.HTTP_NOT_FOUND {
-
- return nil, errors.New("the endpoint is wrong or the user name
is unknown")
- }
-
- if status == common.HTTP_CONFLICT {
-
- return nil, errors.New("a transaction with the same request_uid
but different transaction details has been submitted before")
- }
-
- return nil, fmt.Errorf("HTTP %d - unexpected", status)
-}
-
-//
https://docs.taler.net/core/api-bank-wire.html#querying-the-transaction-history
-func (twg *TalerWirewatchGatewayImpl) WirewatchGatewayHistoryIncoming(
- optionalStartRow int,
- deltaRows int,
- optionalLongPollMsTimeout int,
-) (*IncomingHistory, error) {
-
- res, status, err := common.HttpGet(
- WIRE_GATEWAY_HISTORY_INCOMING_API,
- nil,
- buildHistoryQueryMap(optionalStartRow, deltaRows,
optionalLongPollMsTimeout),
- common.NewJsonCodec[IncomingHistory](),
- )
-
- if err != nil {
- return nil, err
- }
-
- if status == common.HTTP_OK {
-
- return res, nil
- }
-
- if status == common.HTTP_BAD_REQUEST {
-
- return nil, errors.New("request malformed")
- }
-
- if status == common.HTTP_UNAUTHORIZED {
-
- return nil, errors.New("authentication failed, likely the
credentials are wrong")
- }
-
- if status == common.HTTP_NOT_FOUND {
-
- return nil, errors.New("the endpoint is wrong or the user name
is unknown")
- }
-
- if status == common.HTTP_CONFLICT {
-
- return nil, errors.New("a transaction with the same request_uid
but different transaction details has been submitted before")
- }
-
- return nil, fmt.Errorf("HTTP %d - unexpected", 0)
-}
-
-//
https://docs.taler.net/core/api-bank-wire.html#querying-the-transaction-history
-func (twg *TalerWirewatchGatewayImpl) WirewatchGatewayHistoryOutgoing(
- optionalStartRow int,
- deltaRows int,
- optionalLongPollMsTimeout int,
-) (*OutgoingHistory, error) {
-
- res, status, err := common.HttpGet(
- WIRE_GATEWAY_HISTORY_OUTGOING_API,
- nil,
- buildHistoryQueryMap(optionalStartRow, deltaRows,
optionalLongPollMsTimeout),
- common.NewJsonCodec[OutgoingHistory](),
- )
-
- if err != nil {
- return nil, err
- }
-
- if status == common.HTTP_OK {
-
- return res, nil
- }
-
- if status == common.HTTP_BAD_REQUEST {
-
- return nil, errors.New("request malformed")
- }
-
- if status == common.HTTP_UNAUTHORIZED {
-
- return nil, errors.New("authentication failed, likely the
credentials are wrong")
- }
-
- if status == common.HTTP_NOT_FOUND {
-
- return nil, errors.New("the endpoint is wrong or the user name
is unknown")
- }
-
- if status == common.HTTP_CONFLICT {
-
- return nil, errors.New("a transaction with the same request_uid
but different transaction details has been submitted before")
- }
-
- return nil, fmt.Errorf("HTTP %d - unexpected", 0)
-}
-
-func buildHistoryQueryMap(
- optionalStartRow int,
- deltaRows int,
- optionalLongPollMsTimeout int,
-) map[string]string {
-
- startStr := strconv.FormatInt(int64(optionalStartRow), 10)
- deltaRowsStr := strconv.FormatInt(int64(deltaRows), 10)
- longPollMsStr := strconv.FormatInt(int64(optionalLongPollMsTimeout), 10)
-
- queryParams := map[string]string{
- WIRE_GATEWAY_DELTA_QUERY: deltaRowsStr,
- }
- if optionalStartRow > 0 {
- queryParams[WIRE_GATEWAY_START_QUERY] = startStr
- }
- if optionalLongPollMsTimeout > 0 {
- queryParams[WIRE_GATEWAY_LONGPOLL_QUERY] = longPollMsStr
- }
-
- return queryParams
-}
diff --git a/specs/api-c2ec.rst b/specs/api-c2ec.rst
deleted file mode 100644
index 030b961..0000000
--- a/specs/api-c2ec.rst
+++ /dev/null
@@ -1,181 +0,0 @@
-..
- This file is part of GNU TALER.
-
- Copyright (C) 2014-2024 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 2.1, 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 <http://www.gnu.org/licenses/>
-
- @author Joel Häberli
-
-===========================
-The C2EC RESTful API
-===========================
-
-.. note::
-
- **This API is experimental and not yet implemented**
-
-This chapter describe the APIs that third party providers need to integrate to
allow
-withdrawals through indirect payment channels like credit cards or ATM.
-
-.. contents:: Table of Contents
-
---------------
-Authentication
---------------
-
-Terminals which authenticate against the C2EC API must provide their
respective
-access token. Therefore they provide a ``Authorization: Bearer $ACCESS_TOKEN``
header,
-where `$ACCESS_TOKEN`` is a secret authentication token configured by the
exchange and
-must begin with the RFC 8959 prefix.
-
-----------------------------
-Configuration of C2EC
-----------------------------
-
-.. http:get:: /config
-
- Return the protocol version and configuration information about the C2EC API.
-
- **Response:**
-
- :http:statuscode:`200 OK`:
- The exchange responds with a `C2ECConfig` object. This request should
- virtually always be successful.
-
- **Details:**
-
- .. ts:def:: C2ECConfig
-
- interface C2ECConfig {
- // Name of the API.
- name: "taler-c2ec";
-
- // libtool-style representation of the C2EC protocol version, see
- //
https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
- // The format is "current:revision:age".
- version: string;
- }
-
------------------------------
-Withdrawing using C2EC
------------------------------
-
-Withdrawals with a C2EC are based on withdrawal operations which register a
withdrawal identifier
-(nonce) at the C2EC component. The provider must first create a unique
identifier for the withdrawal
-operation (the ``WITHDRAWAL_ID``) to interact with the withdrawal operation
and eventually withdraw using the wallet.
-
-.. http:post:: /withdrawal-operation
-
- Initiate the withdrawal operation, identified by the ``WITHDRAWAL_ID``.
-
- **Request:**
-
- .. ts:def:: C2ECWithdrawalOperationPostRequest
-
- interface WithdrawRegistration {
- // Maps a nonce generated by the provider to a reserve public key
generated by the wallet.
- withdrawal_id: ShortHashCode;
-
- // Reserve public key generated by the wallet.
- // According to TALER_ReservePublicKeyP
(https://docs.taler.net/core/api-common.html#cryptographic-primitives)
- reserve_pub_key: EddsaPublicKey;
-
- // Optional amount for the withdrawal.
- amount?: Amount;
-
- // Id of the terminal of the provider requesting a withdrawal by nonce.
- // Assigned by the exchange.
- provider_terminal_id: SafeUint64;
- }
-
- **Response:**
-
- :http:statuscode:`204 No content`:
- The withdrawal was successfully registered.
- :http:statuscode:`400 Bad request`:
- The ``WithdrawRegistration`` request was malformed or contained invalid
parameters.
- :http:statuscode:`500 Internal Server error`:
- The registration of the withdrawal failed due to server side issues.
-
-.. http:get:: /withdrawal-operation/$WITHDRAWAL_ID
-
- Query information about a withdrawal operation, identified by the
``WITHDRAWAL_ID``.
-
- **Response:**
-
- :http:statuscode:`200 Ok`:
- The withdrawal was found and is returned in the response body as
``C2ECWithdrawalStatus``.
- :http:statuscode:`404 Not found`:
- C2EC does not have a withdrawal registered with the specified
``WITHDRAWAL_ID``.
-
- **Details**
-
- .. ts:def:: C2ECWithdrawalStatus
-
- interface C2ECWithdrawalStatus {
- // Current status of the operation
- // pending: the operation is pending parameters selection (exchange
and reserve public key)
- // selected: the operations has been selected and is pending
confirmation
- // aborted: the operation has been aborted
- // confirmed: the transfer has been confirmed and registered by the
bank
- // Since protocol v1.
- status: "pending" | "selected" | "aborted" | "confirmed";
-
- // Amount that will be withdrawn with this operation
- // (raw amount without fee considerations).
- amount: Amount;
-
- // A refund address as ``payto`` URI. This address shall be used
- // in case a refund must be done. Only not-null if the status
- // is "confirmed" or "aborted"
- refund_wire?: string;
-
- // Reserve public key selected by the exchange,
- // only non-null if ``status`` is ``selected`` or ``confirmed``.
- // Since protocol v1.
- selected_reserve_pub?: string;
- }
-
-
-.. http:post:: /withdrawal-operation/$WITHDRAWAL_ID
-
- Notifies C2EC about an executed payment for a specific withdrawal.
-
- **Request:**
-
- .. ts:def:: C2ECPaymentNotification
-
- interface C2ECPaymentNotification {
-
- // Unique identifier of the provider transaction.
- provider_transaction_id: string;
-
- // Specifies the amount which was payed to the provider (without fees).
- // This amount shall be put into the reserve linked to by the withdrawal
id.
- amount: Amount;
-
- // Fees associated with the payment.
- fees: Amount;
- }
-
- **Response:**
-
- :http:statuscode:`204 No content`:
- C2EC received the ``C2ECPaymentNotification`` successfully and will
further process
- the withdrawal.
- :http:statuscode:`400 Bad request`:
- The ``C2ECPaymentNotification`` request was malformed or contained invalid
parameters.
- :http:statuscode:`404 Not found`:
- C2EC does not have a withdrawal registered with the specified
``WITHDRAWAL_ID``.
- :http:statuscode:`500 Internal Server error`:
- The ``C2ECPaymentNotification`` could not be processed due to server side
issues.
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [taler-cashless2ecash] branch master updated: code: impl routing,
gnunet <=