package services import ( "bytes" "context" "encoding/json" "errors" "fmt" "io" "net/http" "time" "gitea.urkob.com/urko/btc-pay-checker/internal/domain" "gitea.urkob.com/urko/btc-pay-checker/internal/platform/mongodb/order" "go.mongodb.org/mongo-driver/bson/primitive" ) const defaultExpirationTime = time.Minute * 30 type Order struct { repo *order.Repo expiration time.Duration client *http.Client } func NewOrder(repo *order.Repo) *Order { return &Order{ repo: repo, expiration: defaultExpirationTime, client: &http.Client{}, } } func (o *Order) WithExpiration(expiration time.Duration) *Order { o.expiration = expiration return o } func (o *Order) NewOrder(ctx context.Context, orderID, clientID, email string, amount float64) (*domain.Order, error) { order := domain.Order{ ID: primitive.NewObjectID(), OrderID: orderID, ClientID: clientID, Amount: amount, PaidAt: time.Time{}, CreatedAt: time.Now(), ExpiresAt: time.Now().Add(o.expiration), Email: email, } _, err := o.repo.Insert(ctx, &order) if err != nil { return nil, err } return &order, err } func (o *Order) FromAmount(ctx context.Context, amount float64, timestamp time.Time) (*domain.Order, error) { return o.repo.FromAmount(ctx, amount, timestamp) } func (o *Order) OrderCompleted(ctx context.Context, order *domain.Order) (*domain.Order, error) { return o.repo.OrderCompleted(ctx, order) } func (o *Order) Webhook(ctx context.Context, webhookUrl string, order *domain.Order) error { if webhookUrl == "" { return nil } reqBody, err := json.Marshal(order) if err != nil { fmt.Println(err) return err } payload := bytes.NewReader(reqBody) client := &http.Client{} req, err := http.NewRequest(http.MethodPost, webhookUrl, payload) if err != nil { fmt.Println(err) return err } req.Header.Add("Accept", "application/json") req.Header.Add("Content-Type", "application/json") res, err := client.Do(req) if err != nil { return fmt.Errorf("client.Do: %w", err) } if res.StatusCode != http.StatusOK { defer res.Body.Close() body, err := io.ReadAll(res.Body) if err != nil { return errors.Join(fmt.Errorf("response status code is: %d", res.StatusCode), err) } return fmt.Errorf("response status code is: %d | response body %s body", res.StatusCode, string(body)) } return nil }