diff --git a/cmd/cart/checkout_builder.go b/cmd/cart/checkout_builder.go index def5eda..b1119bd 100644 --- a/cmd/cart/checkout_builder.go +++ b/cmd/cart/checkout_builder.go @@ -194,7 +194,7 @@ func BuildAdyenCheckoutSession(grain *cart.CartGrain, meta *CheckoutMeta) (*chec MerchantAccount: "ElgigantenECOM", Channel: common.PtrString("Web"), ShopperIP: common.PtrString(meta.ClientIp), - ReturnUrl: fmt.Sprintf("%s/adyen-return", meta.SiteUrl), + ReturnUrl: "https://cart.tornberg.ne/adyen-return", LineItems: lineItems, }, nil diff --git a/cmd/cart/pool-server.go b/cmd/cart/pool-server.go index e15b01a..b3decaa 100644 --- a/cmd/cart/pool-server.go +++ b/cmd/cart/pool-server.go @@ -4,8 +4,10 @@ import ( "bytes" "context" "encoding/json" + "fmt" "log" "net/http" + "net/url" "os" "strconv" "sync" @@ -18,6 +20,7 @@ import ( "git.k6n.net/go-cart-actor/pkg/voucher" "github.com/adyen/adyen-go-api-library/v21/src/adyen" "github.com/adyen/adyen-go-api-library/v21/src/checkout" + "github.com/adyen/adyen-go-api-library/v21/src/common" "github.com/adyen/adyen-go-api-library/v21/src/hmacvalidator" "github.com/adyen/adyen-go-api-library/v21/src/webhook" "github.com/google/uuid" @@ -755,7 +758,7 @@ func (s *PoolServer) AdyenHookHandler(w http.ResponseWriter, r *http.Request) { cartHostMap := make(map[actor.Host][]webhook.NotificationItem) for _, notificationItem := range *notificationRequest.NotificationItems { item := notificationItem.NotificationRequestItem - log.Printf("Recieved notification event code: %s, %v", item.EventCode, item) + log.Printf("Recieved notification event code: %s, %+v", item.EventCode, item) isValid := hmacvalidator.ValidateHmac(item, hmacKey) if !isValid { @@ -818,14 +821,14 @@ func (s *PoolServer) AdyenHookHandler(w http.ResponseWriter, r *http.Request) { notificationRequest.NotificationItems = &items bodyBytes, err := json.Marshal(notificationRequest) if err != nil { - log.Printf("error marshaling notification: %v", err) + log.Printf("error marshaling notification: %+v", err) continue } customBody := bytes.NewReader(bodyBytes) mockW := proxy.NewMockResponseWriter() handled, err := host.Proxy(0, mockW, r, customBody) if err != nil { - log.Printf("proxy failed for %s: %v", host.Name(), err) + log.Printf("proxy failed for %s: %+v", host.Name(), err) failed = true lastMock = mockW } else if handled { @@ -840,6 +843,60 @@ func (s *PoolServer) AdyenHookHandler(w http.ResponseWriter, r *http.Request) { } } +func (s *PoolServer) AdyenReturnHandler(w http.ResponseWriter, r *http.Request) { + log.Println("Redirect received") + + service := s.adyenClient.Checkout() + + req := service.PaymentsApi.GetResultOfPaymentSessionInput(r.URL.Query().Get("sessionId")) + + res, httpRes, err := service.PaymentsApi.GetResultOfPaymentSession(r.Context(), req) + log.Printf("got payment session %+v", res) + + dreq := service.PaymentsApi.PaymentsDetailsInput() + dreq = dreq.PaymentDetailsRequest(checkout.PaymentDetailsRequest{ + Details: checkout.PaymentCompletionDetails{ + RedirectResult: common.PtrString(r.URL.Query().Get("redirectResult")), + Payload: common.PtrString(r.URL.Query().Get("payload")), + }, + }) + log.Printf("Request for %s API:\n%+v\n", "PaymentDetails", dreq) + dres, httpRes, err := service.PaymentsApi.PaymentsDetails(r.Context(), dreq) + + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + log.Printf("Response for %s API::\n%+v\n", "PaymentDetails", res) + + if !common.IsNil(dres.PspReference) && *dres.PspReference != "" { + var redirectURL string + // Conditionally handle different result codes for the shopper + switch *dres.ResultCode { + case "Authorised": + redirectURL = "/result/success" + case "Pending", "Received": + redirectURL = "/result/pending" + case "Refused": + redirectURL = "/result/failed" + default: + reason := "" + if dres.RefusalReason != nil { + reason = *dres.RefusalReason + } else { + reason = *dres.ResultCode + } + log.Printf("Payment failed: %s", reason) + redirectURL = fmt.Sprintf("/result/error?reason=%s", url.QueryEscape(reason)) + } + http.Redirect(w, r, redirectURL, http.StatusFound) + return + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(httpRes.StatusCode) + json.NewEncoder(w).Encode(httpRes.Status) +} + func (s *PoolServer) Serve(mux *http.ServeMux) { // mux.HandleFunc("OPTIONS /cart", func(w http.ResponseWriter, r *http.Request) { @@ -864,6 +921,7 @@ func (s *PoolServer) Serve(mux *http.ServeMux) { } handleFunc("/adyen_hook", s.AdyenHookHandler) + handleFunc("/adyen-return", s.AdyenReturnHandler) handleFunc("GET /cart", CookieCartIdHandler(s.ProxyHandler(s.GetCartHandler))) handleFunc("GET /cart/add/{sku}", CookieCartIdHandler(s.ProxyHandler(s.AddSkuToCartHandler)))