@@ -100,7 +100,7 @@ func (a *API) PaymentCreate(w http.ResponseWriter, r *http.Request) error {
100
100
if provider == nil {
101
101
return badRequestError ("Payment provider '%s' not configured" , params .ProviderType )
102
102
}
103
- charge , err := provider .NewCharger (ctx , r )
103
+ charge , err := provider .NewCharger (ctx , r , log . WithField ( "component" , "payment_provider" ) )
104
104
if err != nil {
105
105
return badRequestError ("Error creating payment provider: %v" , err )
106
106
}
@@ -167,6 +167,14 @@ func (a *API) PaymentCreate(w http.ResponseWriter, r *http.Request) error {
167
167
tr .ProcessorID = processorID
168
168
tr .InvoiceNumber = invoiceNumber
169
169
170
+ if pendingErr , ok := err .(* payments.PaymentPendingError ); ok {
171
+ tr .Status = models .PendingState
172
+ tr .ProviderMetadata = pendingErr .Metadata ()
173
+ tx .Create (tr )
174
+ tx .Commit ()
175
+ return sendJSON (w , 200 , tr )
176
+ }
177
+
170
178
if err != nil {
171
179
tr .FailureCode = strconv .FormatInt (http .StatusInternalServerError , 10 )
172
180
tr .FailureDescription = err .Error ()
@@ -206,6 +214,75 @@ func (a *API) PaymentCreate(w http.ResponseWriter, r *http.Request) error {
206
214
return sendJSON (w , http .StatusOK , tr )
207
215
}
208
216
217
+ // PaymentConfirm allows client to confirm if a pending transaction has been completed. Updates transaction and order
218
+ func (a * API ) PaymentConfirm (w http.ResponseWriter , r * http.Request ) error {
219
+ ctx := r .Context ()
220
+
221
+ payID := chi .URLParam (r , "payment_id" )
222
+ trans , httpErr := a .getTransaction (payID )
223
+ if httpErr != nil {
224
+ return httpErr
225
+ }
226
+
227
+ if trans .UserID != "" {
228
+ token := gcontext .GetToken (ctx )
229
+ if token == nil {
230
+ return unauthorizedError ("You must be logged in to confirm this payment" )
231
+ }
232
+ claims := token .Claims .(* claims.JWTClaims )
233
+ if trans .UserID != claims .Subject {
234
+ return unauthorizedError ("You must be logged in to confirm this payment" )
235
+ }
236
+ }
237
+
238
+ log := getLogEntry (r )
239
+ order , httpErr := queryForOrder (a .db , trans .OrderID , log )
240
+ if httpErr != nil {
241
+ return httpErr
242
+ }
243
+ if order .PaymentProcessor == "" {
244
+ return badRequestError ("Order does not specify a payment provider" )
245
+ }
246
+
247
+ provider := gcontext .GetPaymentProviders (ctx )[order .PaymentProcessor ]
248
+ if provider == nil {
249
+ return badRequestError ("Payment provider '%s' not configured" , order .PaymentProcessor )
250
+ }
251
+ confirm , err := provider .NewConfirmer (ctx , r , log .WithField ("component" , "payment_provider" ))
252
+ if err != nil {
253
+ return badRequestError ("Error creating payment provider: %v" , err )
254
+ }
255
+
256
+ if err := confirm (trans .ProcessorID ); err != nil {
257
+ if confirmFail , ok := err .(* payments.PaymentConfirmFailError ); ok {
258
+ return badRequestError ("Error confirming payment: %s" , confirmFail .Error ())
259
+ }
260
+ return internalServerError ("Error on provider while trying to confirm: %v. Try again later." , err )
261
+ }
262
+
263
+ tx := a .db .Begin ()
264
+
265
+ if trans .InvoiceNumber == 0 {
266
+ invoiceNumber , err := models .NextInvoiceNumber (tx , order .InstanceID )
267
+ if err != nil {
268
+ tx .Rollback ()
269
+ return internalServerError ("We failed to generate a valid invoice ID, please try again later: %v" , err )
270
+ }
271
+ trans .InvoiceNumber = invoiceNumber
272
+ }
273
+
274
+ trans .Status = models .PaidState
275
+ tx .Save (trans )
276
+ order .State = models .PaidState
277
+ order .InvoiceNumber = trans .InvoiceNumber
278
+ tx .Save (order )
279
+ if err := tx .Commit ().Error ; err != nil {
280
+ return internalServerError ("Saving payment failed" ).WithInternalError (err )
281
+ }
282
+
283
+ return sendJSON (w , 200 , trans )
284
+ }
285
+
209
286
// PaymentList will list all the payments that meet the criteria. It is only available to admins.
210
287
func (a * API ) PaymentList (w http.ResponseWriter , r * http.Request ) error {
211
288
log := getLogEntry (r )
@@ -280,7 +357,7 @@ func (a *API) PaymentRefund(w http.ResponseWriter, r *http.Request) error {
280
357
if provider == nil {
281
358
return badRequestError ("Payment provider '%s' not configured" , order .PaymentProcessor )
282
359
}
283
- refund , err := provider .NewRefunder (ctx , r )
360
+ refund , err := provider .NewRefunder (ctx , r , log . WithField ( "component" , "payment_provider" ) )
284
361
if err != nil {
285
362
return badRequestError ("Error creating payment provider: %v" , err )
286
363
}
@@ -328,6 +405,7 @@ func (a *API) PaymentRefund(w http.ResponseWriter, r *http.Request) error {
328
405
// PreauthorizePayment creates a new payment that can be authorized in the browser
329
406
func (a * API ) PreauthorizePayment (w http.ResponseWriter , r * http.Request ) error {
330
407
ctx := r .Context ()
408
+ log := getLogEntry (r )
331
409
params := PaymentParams {}
332
410
ct := r .Header .Get ("Content-Type" )
333
411
mediaType , _ , err := mime .ParseMediaType (ct )
@@ -362,7 +440,7 @@ func (a *API) PreauthorizePayment(w http.ResponseWriter, r *http.Request) error
362
440
if provider == nil {
363
441
return badRequestError ("Payment provider '%s' not configured" , providerType )
364
442
}
365
- preauthorize , err := provider .NewPreauthorizer (ctx , r )
443
+ preauthorize , err := provider .NewPreauthorizer (ctx , r , log . WithField ( "component" , "payment_provider" ) )
366
444
if err != nil {
367
445
return badRequestError ("Error creating payment provider: %v" , err )
368
446
}
@@ -426,7 +504,8 @@ func createPaymentProviders(c *conf.Configuration) (map[string]payments.Provider
426
504
provs := map [string ]payments.Provider {}
427
505
if c .Payment .Stripe .Enabled {
428
506
p , err := stripe .NewPaymentProvider (stripe.Config {
429
- SecretKey : c .Payment .Stripe .SecretKey ,
507
+ SecretKey : c .Payment .Stripe .SecretKey ,
508
+ UsePaymentIntents : c .Payment .Stripe .UsePaymentIntents ,
430
509
})
431
510
if err != nil {
432
511
return nil , err
0 commit comments