klarna and checkouts
Build and Publish / BuildAndDeployAmd64 (push) Failing after 4s
Build and Publish / BuildAndDeployArm64 (push) Failing after 6s

This commit is contained in:
2026-06-26 15:41:55 +02:00
parent c0c5a8bc0f
commit 0252893de5
3 changed files with 71 additions and 24 deletions
+47 -17
View File
@@ -4,6 +4,8 @@ import (
"encoding/json"
"fmt"
"net/http"
"os"
"strings"
"git.k6n.net/mats/go-cart-actor/pkg/cart"
"git.k6n.net/mats/go-cart-actor/pkg/checkout"
@@ -11,18 +13,41 @@ import (
"github.com/adyen/adyen-go-api-library/v21/src/common"
)
// defaultCallbackBaseURL is where Klarna's server-to-server callbacks
// (push/notification/validate) are sent when CHECKOUT_CALLBACK_BASE_URL is unset.
// These must be a publicly reachable https origin for the checkout service.
const defaultCallbackBaseURL = "https://cart.k6n.net"
var (
// checkoutPublicURL overrides the request-derived site base for the
// shopper-facing Klarna URLs (terms/checkout/confirmation). Set this to a
// public https origin (e.g. a tunnel or shop-test.tornberg.me) for local
// KCO testing, since Klarna rejects non-https merchant_urls. Empty = derive
// from the request (X-Forwarded-Host + https).
checkoutPublicURL = strings.TrimRight(os.Getenv("CHECKOUT_PUBLIC_URL"), "/")
// checkoutCallbackBaseURL is the base for Klarna's server-to-server
// callbacks. Defaults to defaultCallbackBaseURL.
checkoutCallbackBaseURL = func() string {
if v := strings.TrimRight(os.Getenv("CHECKOUT_CALLBACK_BASE_URL"), "/"); v != "" {
return v
}
return defaultCallbackBaseURL
}()
)
// CheckoutMeta carries the external / URL metadata required to build a
// Klarna CheckoutOrder from a CartGrain snapshot. It deliberately excludes
// any Klarna-specific response fields (HTML snippet, client token, etc.).
type CheckoutMeta struct {
SiteUrl string
// Terms string
// Checkout string
// Confirmation string
ClientIp string
Country string
Currency string // optional override (defaults to "SEK" if empty)
Locale string // optional override (defaults to "sv-se" if empty)
// CallbackBaseUrl is the base for Klarna server-to-server callbacks
// (push/notification/validate); may differ from SiteUrl in prod where the
// checkout service and storefront are on different hosts.
CallbackBaseUrl string
ClientIp string
Country string
Currency string // optional override (defaults to "SEK" if empty)
Locale string // optional override (defaults to "sv-se" if empty)
}
// BuildCheckoutOrderPayload converts the current cart grain + meta information
@@ -113,11 +138,11 @@ func BuildCheckoutOrderPayload(grain *checkout.CheckoutGrain, meta *CheckoutMeta
MerchantReference1: grain.Id.String(),
MerchantURLS: &CheckoutMerchantURLS{
Terms: fmt.Sprintf("%s/terms", meta.SiteUrl),
Checkout: fmt.Sprintf("%s/checkout?order_id={checkout.order.id}&provider=klarna", meta.SiteUrl),
Confirmation: fmt.Sprintf("%s/checkout?order_id={checkout.order.id}&provider=klarna", meta.SiteUrl),
Notification: "https://cart.k6n.net/payment/klarna/notification",
Validation: "https://cart.k6n.net/payment/klarna/validate",
Push: "https://cart.k6n.net/payment/klarna/push?order_id={checkout.order.id}",
Checkout: fmt.Sprintf("%s/kassa?order_id={checkout.order.id}&provider=klarna", meta.SiteUrl),
Confirmation: fmt.Sprintf("%s/kassa?order_id={checkout.order.id}&provider=klarna", meta.SiteUrl),
Notification: fmt.Sprintf("%s/payment/klarna/notification", meta.CallbackBaseUrl),
Validation: fmt.Sprintf("%s/payment/klarna/validate", meta.CallbackBaseUrl),
Push: fmt.Sprintf("%s/payment/klarna/push?order_id={checkout.order.id}", meta.CallbackBaseUrl),
},
}
@@ -132,12 +157,17 @@ func BuildCheckoutOrderPayload(grain *checkout.CheckoutGrain, meta *CheckoutMeta
func GetCheckoutMetaFromRequest(r *http.Request) *CheckoutMeta {
host := getOriginalHost(r)
country := getCountryFromHost(host)
siteUrl := fmt.Sprintf("%s://%s", getScheme(r), host)
if checkoutPublicURL != "" {
siteUrl = checkoutPublicURL
}
return &CheckoutMeta{
ClientIp: getClientIp(r),
SiteUrl: fmt.Sprintf("https://%s", host),
Country: country,
Currency: getCurrency(country),
Locale: getLocale(country),
ClientIp: getClientIp(r),
SiteUrl: siteUrl,
CallbackBaseUrl: checkoutCallbackBaseURL,
Country: country,
Currency: getCurrency(country),
Locale: getLocale(country),
}
}