@@ -2,17 +2,18 @@ package internal
2
2
3
3
import (
4
4
"context"
5
- "encoding/json"
6
5
"errors"
7
6
"fmt"
8
7
"net/http"
8
+ "reflect"
9
9
"strconv"
10
10
"strings"
11
+ "unsafe"
11
12
12
13
"github.com/formancehq/formance-sdk-go"
13
14
"github.com/formancehq/formance-sdk-go/pkg/models/operations"
14
15
"github.com/formancehq/formance-sdk-go/pkg/models/shared"
15
- "github.com/formancehq/stack/libs/go-libs/api "
16
+ "github.com/formancehq/formance-sdk-go/pkg/utils "
16
17
"github.com/formancehq/stack/libs/go-libs/collectionutils"
17
18
"golang.org/x/mod/semver"
18
19
)
@@ -55,7 +56,97 @@ func TransactionIDOrLastN(ctx context.Context, ledgerClient *formance.Formance,
55
56
return strconv .ParseInt (id , 10 , 64 )
56
57
}
57
58
58
- func CreateTransaction (client * formance.Formance , ctx context.Context , ledger string , request operations.CreateTransactionRequest ) (* shared.Transaction , error ) {
59
+ // CreateTransactionResponse - OK
60
+ type CreateTransactionResponse struct {
61
+ Data []shared.Transaction `json:"data"`
62
+ }
63
+
64
+ type CreateTransactionWrapper struct {
65
+ ContentType string
66
+ // OK
67
+ CreateTransactionResponse * CreateTransactionResponse
68
+ // Error
69
+ ErrorResponse * shared.ErrorResponse
70
+ StatusCode int
71
+ RawResponse * http.Response
72
+ }
73
+
74
+ // CreateTransaction - Create a new transaction to a ledger
75
+ func createTransactionV1 (ctx context.Context , client * formance.Formance , baseURL string , request operations.CreateTransactionRequest ) (* CreateTransactionWrapper , error ) {
76
+
77
+ // Dirty hack to get the http client from the sdk client struct
78
+ field := reflect .ValueOf (client ).Elem ().FieldByName ("_securityClient" )
79
+ httpClient := reflect .NewAt (field .Type (), unsafe .Pointer (field .UnsafeAddr ())).Elem ().Interface ().(formance.HTTPClient )
80
+
81
+ url , err := utils .GenerateURL (ctx , baseURL , "/api/ledger/{ledger}/transactions" , request , nil )
82
+ if err != nil {
83
+ return nil , fmt .Errorf ("error generating URL: %w" , err )
84
+ }
85
+
86
+ bodyReader , reqContentType , err := utils .SerializeRequestBody (ctx , request , "PostTransaction" , "json" )
87
+ if err != nil {
88
+ return nil , fmt .Errorf ("error serializing request body: %w" , err )
89
+ }
90
+ if bodyReader == nil {
91
+ return nil , fmt .Errorf ("request body is required" )
92
+ }
93
+
94
+ req , err := http .NewRequestWithContext (ctx , "POST" , url , bodyReader )
95
+ if err != nil {
96
+ return nil , fmt .Errorf ("error creating request: %w" , err )
97
+ }
98
+ req .Header .Set ("Accept" , "application/json;q=1, application/json;q=0" )
99
+ req .Header .Set ("Content-Type" , reqContentType )
100
+
101
+ utils .PopulateHeaders (ctx , req , request )
102
+
103
+ if err := utils .PopulateQueryParams (ctx , req , request , nil ); err != nil {
104
+ return nil , fmt .Errorf ("error populating query params: %w" , err )
105
+ }
106
+
107
+ httpRes , err := httpClient .Do (req )
108
+ if err != nil {
109
+ return nil , fmt .Errorf ("error sending request: %w" , err )
110
+ }
111
+ if httpRes == nil {
112
+ return nil , fmt .Errorf ("error sending request: no response" )
113
+ }
114
+ defer httpRes .Body .Close ()
115
+
116
+ contentType := httpRes .Header .Get ("Content-Type" )
117
+
118
+ res := & CreateTransactionWrapper {
119
+ StatusCode : httpRes .StatusCode ,
120
+ ContentType : contentType ,
121
+ RawResponse : httpRes ,
122
+ }
123
+ switch {
124
+ case httpRes .StatusCode == 200 :
125
+ switch {
126
+ case utils .MatchContentType (contentType , `application/json` ):
127
+ var out * CreateTransactionResponse
128
+ if err := utils .UnmarshalJsonFromResponseBody (httpRes .Body , & out ); err != nil {
129
+ return nil , err
130
+ }
131
+
132
+ res .CreateTransactionResponse = out
133
+ }
134
+ default :
135
+ switch {
136
+ case utils .MatchContentType (contentType , `application/json` ):
137
+ var out * shared.ErrorResponse
138
+ if err := utils .UnmarshalJsonFromResponseBody (httpRes .Body , & out ); err != nil {
139
+ return nil , err
140
+ }
141
+
142
+ res .ErrorResponse = out
143
+ }
144
+ }
145
+
146
+ return res , nil
147
+ }
148
+
149
+ func CreateTransaction (client * formance.Formance , ctx context.Context , request operations.CreateTransactionRequest ) (* shared.Transaction , error ) {
59
150
60
151
versionsResponse , err := client .GetVersions (ctx )
61
152
if err != nil {
@@ -69,15 +160,17 @@ func CreateTransaction(client *formance.Formance, ctx context.Context, ledger st
69
160
return version .Name == "ledger"
70
161
})[0 ].Version
71
162
72
- response , err := client .Ledger .CreateTransaction (ctx , request )
73
-
74
163
if semver .IsValid (version ) && semver .Compare (version , "v2.0.0" ) < 0 {
75
- baseResponse := api.BaseResponse [[]shared.Transaction ]{}
76
- if err := json .NewDecoder (response .RawResponse .Body ).Decode (& baseResponse ); err != nil {
164
+ baseURL := strings .TrimSuffix (versionsResponse .RawResponse .Request .URL .String (), "/versions" )
165
+
166
+ v , err := createTransactionV1 (ctx , client , baseURL , request )
167
+ if err != nil {
77
168
return nil , err
78
169
}
79
- return & (* baseResponse .Data )[0 ], nil
170
+
171
+ return & v .CreateTransactionResponse .Data [0 ], nil
80
172
} else {
173
+ response , err := client .Ledger .CreateTransaction (ctx , request )
81
174
if err != nil {
82
175
return nil , err
83
176
}
0 commit comments