127 lines
4.2 KiB
Go
127 lines
4.2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"log/slog"
|
|
"net/mail"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
"git.k6n.net/mats/go-cart-actor/internal/ucp"
|
|
"git.k6n.net/mats/go-cart-actor/pkg/order"
|
|
"git.k6n.net/mats/platform/config"
|
|
"git.k6n.net/mats/platform/tax"
|
|
)
|
|
|
|
// selectTaxProvider picks the tax provider from the environment. Default is
|
|
// NordicTaxProvider with SE as the default country (matching the current
|
|
// Nordic-only footprint). Set TAX_PROVIDER=static for dev and tests
|
|
// (no country awareness).
|
|
func selectTaxProvider() tax.Provider {
|
|
provider := os.Getenv("TAX_PROVIDER")
|
|
switch provider {
|
|
case "static":
|
|
return tax.NewStatic()
|
|
case "nordic":
|
|
return tax.NewNordic(config.EnvString("TAX_DEFAULT_COUNTRY", "SE"))
|
|
default:
|
|
return tax.NewNordic(config.EnvString("TAX_DEFAULT_COUNTRY", "SE"))
|
|
}
|
|
}
|
|
|
|
// selectProvider picks the payment provider from the environment. Default is
|
|
// the dependency-free mock; set PAYMENT_PROVIDER=stripe + STRIPE_SECRET_KEY for
|
|
// real Stripe (STRIPE_API_BASE / STRIPE_PAYMENT_METHOD optionally override).
|
|
func selectProvider(logger *slog.Logger) order.PaymentProvider {
|
|
if os.Getenv("PAYMENT_PROVIDER") == "stripe" {
|
|
key := os.Getenv("STRIPE_SECRET_KEY")
|
|
if key == "" {
|
|
logger.Warn("PAYMENT_PROVIDER=stripe but STRIPE_SECRET_KEY is empty; falling back to mock")
|
|
return order.NewMockProvider()
|
|
}
|
|
logger.Info("using stripe payment provider")
|
|
return order.NewStripeProvider(key, os.Getenv("STRIPE_API_BASE"), os.Getenv("STRIPE_PAYMENT_METHOD"))
|
|
}
|
|
return order.NewMockProvider()
|
|
}
|
|
|
|
// selectEmailSender picks the flow-email transport. Supports SMTP and
|
|
// MailerSend. When no sender is configured the hook still exists in
|
|
// capabilities but errors at run time if a flow tries to use it.
|
|
func selectEmailSender(logger *slog.Logger) (order.EmailSender, error) {
|
|
kind := config.EnvString("ORDER_EMAIL_SENDER", "")
|
|
if kind == "" && os.Getenv("ORDER_EMAIL_SMTP_HOST") == "" {
|
|
return nil, nil
|
|
}
|
|
if kind == "" {
|
|
kind = "smtp"
|
|
}
|
|
|
|
fromAddr := strings.TrimSpace(os.Getenv("ORDER_EMAIL_FROM_ADDRESS"))
|
|
if fromAddr == "" {
|
|
return nil, fmt.Errorf("ORDER_EMAIL_FROM_ADDRESS is required when email sender is configured")
|
|
}
|
|
from := mail.Address{
|
|
Name: strings.TrimSpace(os.Getenv("ORDER_EMAIL_FROM_NAME")),
|
|
Address: fromAddr,
|
|
}
|
|
|
|
switch kind {
|
|
case "smtp":
|
|
sender, err := order.NewSMTPEmailSender(order.SMTPEmailSenderConfig{
|
|
Host: config.EnvString("ORDER_EMAIL_SMTP_HOST", ""),
|
|
Port: config.EnvInt("ORDER_EMAIL_SMTP_PORT", 587, func(n int) bool { return n > 0 }),
|
|
Username: os.Getenv("ORDER_EMAIL_SMTP_USERNAME"),
|
|
Password: os.Getenv("ORDER_EMAIL_SMTP_PASSWORD"),
|
|
DefaultFrom: from,
|
|
Timeout: config.EnvDuration("ORDER_EMAIL_SMTP_TIMEOUT", 10*time.Second),
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
logger.Info("email sender enabled", "kind", "smtp", "host", config.EnvString("ORDER_EMAIL_SMTP_HOST", ""), "from", from.Address)
|
|
return sender, nil
|
|
|
|
case "mailersend":
|
|
apiKey := os.Getenv("MAILERSEND_API_KEY")
|
|
if apiKey == "" {
|
|
return nil, fmt.Errorf("MAILERSEND_API_KEY is required for mailersend sender")
|
|
}
|
|
sender, err := order.NewMailerSendEmailSender(apiKey, from)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
logger.Info("email sender enabled", "kind", "mailersend", "from", from.Address)
|
|
return sender, nil
|
|
|
|
default:
|
|
return nil, fmt.Errorf("unsupported ORDER_EMAIL_SENDER %q (supported: smtp, mailersend)", kind)
|
|
}
|
|
}
|
|
|
|
func selectInventoryReservationService() (order.InventoryReservationService, error) {
|
|
return order.NewHTTPInventoryReservationService(config.EnvString("INVENTORY_URL", "http://localhost:8080"), nil)
|
|
}
|
|
|
|
// loadUCPOrderSigner loads the UCP ECDSA signing key from the path specified in
|
|
// the UCP_SIGNING_KEY_PATH environment variable. Returns nil if unset or unreadable.
|
|
func loadUCPOrderSigner() *ucp.SigningConfig {
|
|
path := os.Getenv("UCP_SIGNING_KEY_PATH")
|
|
if path == "" {
|
|
return nil
|
|
}
|
|
pemData, err := os.ReadFile(path)
|
|
if err != nil {
|
|
log.Printf("ucp signing: cannot read key %s: %v", path, err)
|
|
return nil
|
|
}
|
|
cfg, err := ucp.NewSigningConfigFromPEM(pemData, "k6n-ecdsa-2026")
|
|
if err != nil {
|
|
log.Printf("ucp signing: invalid key at %s: %v", path, err)
|
|
return nil
|
|
}
|
|
return cfg
|
|
}
|