2023-07-26 07:51:29 +00:00
|
|
|
package stripe
|
|
|
|
|
|
|
|
import (
|
2023-07-27 20:46:37 +00:00
|
|
|
"github.com/gin-gonic/gin"
|
2023-07-26 07:51:29 +00:00
|
|
|
"github.com/google/uuid"
|
2023-07-27 20:46:37 +00:00
|
|
|
"github.com/stripe/stripe-go/v72"
|
|
|
|
"github.com/stripe/stripe-go/v72/checkout/session"
|
|
|
|
"github.com/stripe/stripe-go/v72/paymentintent"
|
|
|
|
"log"
|
|
|
|
"payment-poc/database"
|
2023-07-26 07:51:29 +00:00
|
|
|
"payment-poc/state"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Service struct {
|
2023-07-27 20:46:37 +00:00
|
|
|
Provider *database.PaymentEntryProvider
|
|
|
|
ApiKey string
|
|
|
|
BackendUrl string
|
2023-07-26 07:51:29 +00:00
|
|
|
}
|
|
|
|
|
2023-07-27 20:46:37 +00:00
|
|
|
func (s *Service) CreatePaymentUrl(amount int64) (url string, err error) {
|
|
|
|
entry, err := s.Provider.CreateEntry(database.PaymentEntry{
|
2023-07-30 10:14:05 +00:00
|
|
|
Gateway: state.GatewayStripe,
|
2023-07-26 07:51:29 +00:00
|
|
|
State: state.StateInitialized,
|
2023-07-27 20:46:37 +00:00
|
|
|
TotalAmount: amount,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
entry, url, err = s.InitializePayment(entry)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
entry, err = s.Provider.UpdateEntry(entry)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
return url, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *Service) InitializePayment(entry database.PaymentEntry) (database.PaymentEntry, string, error) {
|
|
|
|
|
|
|
|
currency := string(stripe.CurrencyEUR)
|
|
|
|
productName := "Example product"
|
|
|
|
productDescription := "Simple example product"
|
|
|
|
|
|
|
|
params := &stripe.CheckoutSessionParams{
|
|
|
|
LineItems: []*stripe.CheckoutSessionLineItemParams{
|
|
|
|
{
|
|
|
|
PriceData: &stripe.CheckoutSessionLineItemPriceDataParams{
|
|
|
|
Currency: ¤cy,
|
|
|
|
ProductData: &stripe.CheckoutSessionLineItemPriceDataProductDataParams{
|
|
|
|
Name: &productName,
|
|
|
|
Description: &productDescription,
|
|
|
|
},
|
|
|
|
UnitAmount: &entry.TotalAmount,
|
|
|
|
},
|
|
|
|
Quantity: stripe.Int64(1),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Mode: stripe.String(string(stripe.CheckoutSessionModePayment)),
|
|
|
|
PaymentIntentData: &stripe.CheckoutSessionPaymentIntentDataParams{
|
|
|
|
CaptureMethod: stripe.String("manual"),
|
|
|
|
},
|
|
|
|
SuccessURL: stripe.String(s.BackendUrl + "/stripe/success?token=" + entry.Id.String()),
|
|
|
|
CancelURL: stripe.String(s.BackendUrl + "/stripe/cancel?token=" + entry.Id.String()),
|
2023-07-26 07:51:29 +00:00
|
|
|
}
|
2023-07-27 20:46:37 +00:00
|
|
|
result, err := session.New(params)
|
2023-07-26 07:51:29 +00:00
|
|
|
if err != nil {
|
2023-07-27 20:46:37 +00:00
|
|
|
return database.PaymentEntry{}, "", err
|
2023-07-26 07:51:29 +00:00
|
|
|
}
|
2023-07-27 20:46:37 +00:00
|
|
|
entry.PaymentIntentId = &result.PaymentIntent.ID
|
|
|
|
|
|
|
|
return entry, result.URL, nil
|
2023-07-26 07:51:29 +00:00
|
|
|
}
|
|
|
|
|
2023-07-27 20:46:37 +00:00
|
|
|
func (s *Service) CompleteTransaction(entry database.PaymentEntry, amount int64) (database.PaymentEntry, error) {
|
|
|
|
params := &stripe.PaymentIntentCaptureParams{
|
|
|
|
AmountToCapture: stripe.Int64(amount),
|
|
|
|
}
|
|
|
|
pi, err := paymentintent.Capture(*entry.PaymentIntentId, params)
|
|
|
|
if err != nil {
|
|
|
|
return database.PaymentEntry{}, err
|
|
|
|
}
|
|
|
|
log.Printf("received state on completion: %v", pi.Status)
|
|
|
|
if pi.Status == stripe.PaymentIntentStatusSucceeded || pi.Status == stripe.PaymentIntentStatusProcessing {
|
2023-07-30 10:14:05 +00:00
|
|
|
entry.Amount = &pi.AmountReceived
|
2023-07-27 20:46:37 +00:00
|
|
|
entry.State = state.StateCompleted
|
|
|
|
}
|
|
|
|
return entry, nil
|
2023-07-26 07:51:29 +00:00
|
|
|
}
|
|
|
|
|
2023-07-27 20:46:37 +00:00
|
|
|
func (s *Service) CancelTransaction(entry database.PaymentEntry) (database.PaymentEntry, error) {
|
|
|
|
params := &stripe.PaymentIntentCancelParams{}
|
|
|
|
pi, err := paymentintent.Cancel(*entry.PaymentIntentId, params)
|
|
|
|
if err != nil {
|
|
|
|
return database.PaymentEntry{}, err
|
|
|
|
}
|
|
|
|
log.Printf("received state on completion: %v", pi.Status)
|
|
|
|
if pi.Status == stripe.PaymentIntentStatusCanceled {
|
|
|
|
entry.State = state.StateCanceled
|
|
|
|
}
|
|
|
|
return entry, nil
|
2023-07-26 07:51:29 +00:00
|
|
|
}
|
|
|
|
|
2023-07-27 20:46:37 +00:00
|
|
|
func (s *Service) HandleResponse(c *gin.Context, paymentState state.PaymentState) (string, error) {
|
|
|
|
id := uuid.MustParse(c.Query("token"))
|
|
|
|
entry, err := s.Provider.FetchById(id)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
entry.State = paymentState
|
|
|
|
s.Provider.UpdateEntry(entry)
|
|
|
|
return "/entries/" + entry.Id.String(), nil
|
2023-07-26 07:51:29 +00:00
|
|
|
}
|