/* * SPDX-FileCopyrightText: 2023 jordi fita mas * SPDX-License-Identifier: AGPL-3.0-only */ package database import ( "context" "github.com/jackc/pgtype" "github.com/jackc/pgx/v4" ) const ( OptionUnitsTypeName = "option_units" RedsysRequestTypeName = "redsys_request" RedsysResponseTypeName = "redsys_response" RedsysSignedRequestTypeName = "redsys_signed_request" ) var ( oidCache = make(map[string]uint32) ) func registerTypes(ctx context.Context, connString string) error { conn, err := pgx.Connect(ctx, connString) if err != nil { return err } defer conn.Close(context.Background()) if _, err := conn.Exec(ctx, "set role to guest"); err != nil { return err } if _, err := conn.Exec(ctx, searchPathQuery); err != nil { return err } if err := registerConnectionTypes(ctx, conn); err != nil { return err } return nil } func registerConnectionTypes(ctx context.Context, conn *pgx.Conn) error { uriOID, err := registerType(ctx, conn, &pgtype.Text{}, "uri") if err != nil { return err } redsysRequestType, err := pgtype.NewCompositeType( RedsysRequestTypeName, []pgtype.CompositeTypeField{ {"transaction_type", pgtype.Int4OID}, {"amount", pgtype.TextOID}, {"order_number", pgtype.TextOID}, {"product", pgtype.TextOID}, {"card_holder", pgtype.TextOID}, {"success_uri", uriOID}, {"failure_uri", uriOID}, {"notification_uri", uriOID}, {"lang_tag", pgtype.TextOID}, }, conn.ConnInfo(), ) if err != nil { return err } if _, err = registerType(ctx, conn, redsysRequestType, redsysRequestType.TypeName()); err != nil { return err } redsysResponseType, err := pgtype.NewCompositeType( RedsysResponseTypeName, []pgtype.CompositeTypeField{ {"merchant_code", pgtype.TextOID}, {"terminal_number", pgtype.Int4OID}, {"response_code", pgtype.Int4OID}, {"date_time", pgtype.TimestampOID}, {"secure_payment", pgtype.BoolOID}, {"transaction_type", pgtype.Int4OID}, {"amount", pgtype.TextOID}, {"currency_code", pgtype.TextOID}, {"order_number", pgtype.TextOID}, {"authorization_code", pgtype.TextOID}, {"error_code", pgtype.TextOID}, }, conn.ConnInfo(), ) if err != nil { return err } if _, err = registerType(ctx, conn, redsysResponseType, redsysResponseType.TypeName()); err != nil { return err } redsysSignedRequestType, err := pgtype.NewCompositeType( RedsysSignedRequestTypeName, []pgtype.CompositeTypeField{ {"merchant_parameters", pgtype.TextOID}, {"signature", pgtype.TextOID}, {"signature_version", pgtype.TextOID}, }, conn.ConnInfo(), ) if err != nil { return err } if _, err = registerType(ctx, conn, redsysSignedRequestType, redsysSignedRequestType.TypeName()); err != nil { return err } optionUnitsType, err := pgtype.NewCompositeType( OptionUnitsTypeName, []pgtype.CompositeTypeField{ {"option_id", pgtype.Int4OID}, {"units", pgtype.Int4OID}, }, conn.ConnInfo(), ) if err != nil { return err } if _, err = registerType(ctx, conn, optionUnitsType, optionUnitsType.TypeName()); err != nil { return err } return nil } func registerType(ctx context.Context, conn *pgx.Conn, value pgtype.Value, name string) (oid uint32, err error) { var found bool if oid, found = oidCache[name]; !found { if err = conn.QueryRow(ctx, "select $1::regtype::oid", name).Scan(&oid); err != nil { return } oidCache[name] = oid } conn.ConnInfo().RegisterDataType(pgtype.DataType{Value: value, Name: name, OID: oid}) return }