From 49cebad8618448e498aa4edfd3f1c74ee7bb7947 Mon Sep 17 00:00:00 2001 From: matst80 Date: Fri, 18 Apr 2025 17:27:50 +0200 Subject: [PATCH] update push to update the cart --- klarna-push-type.go | 165 +++++++++++++------------------------------ main.go | 46 ++++++++++-- message-types.go | 1 + proto/messages.pb.go | 66 +++++++++++++++-- proto/messages.proto | 5 ++ 5 files changed, 159 insertions(+), 124 deletions(-) diff --git a/klarna-push-type.go b/klarna-push-type.go index b2b58a1..f0a575e 100644 --- a/klarna-push-type.go +++ b/klarna-push-type.go @@ -2,134 +2,69 @@ package main import "time" -type OrderValidationBody struct { +type KlarnaOrderResponse struct { + OrderID string `json:"order_id"` + Status string `json:"status"` PurchaseCountry string `json:"purchase_country"` PurchaseCurrency string `json:"purchase_currency"` Locale string `json:"locale"` - Status string `json:"status"` BillingAddress struct { - GivenName string `json:"given_name"` - FamilyName string `json:"family_name"` - Email string `json:"email"` - Title string `json:"title"` - StreetAddress string `json:"street_address"` - StreetAddress2 string `json:"street_address2"` - StreetName string `json:"street_name"` - StreetNumber string `json:"street_number"` - HouseExtension string `json:"house_extension"` - PostalCode string `json:"postal_code"` - City string `json:"city"` - Region string `json:"region"` - Phone string `json:"phone"` - Country string `json:"country"` - CareOf string `json:"care_of"` + GivenName string `json:"given_name"` + FamilyName string `json:"family_name"` + Email string `json:"email"` + StreetAddress string `json:"street_address"` + PostalCode string `json:"postal_code"` + City string `json:"city"` + Phone string `json:"phone"` + Country string `json:"country"` } `json:"billing_address"` + Customer struct { + DateOfBirth string `json:"date_of_birth"` + Type string `json:"type"` + Gender string `json:"gender"` + } `json:"customer"` ShippingAddress struct { - GivenName string `json:"given_name"` - FamilyName string `json:"family_name"` - Email string `json:"email"` - Title string `json:"title"` - StreetAddress string `json:"street_address"` - StreetAddress2 string `json:"street_address2"` - StreetName string `json:"street_name"` - StreetNumber string `json:"street_number"` - HouseExtension string `json:"house_extension"` - PostalCode string `json:"postal_code"` - City string `json:"city"` - Region string `json:"region"` - Phone string `json:"phone"` - Country string `json:"country"` - CareOf string `json:"care_of"` + GivenName string `json:"given_name"` + FamilyName string `json:"family_name"` + Email string `json:"email"` + StreetAddress string `json:"street_address"` + PostalCode string `json:"postal_code"` + City string `json:"city"` + Phone string `json:"phone"` + Country string `json:"country"` } `json:"shipping_address"` OrderAmount int `json:"order_amount"` OrderTaxAmount int `json:"order_tax_amount"` OrderLines []struct { + Type string `json:"type"` + Reference string `json:"reference"` + Name string `json:"name"` + Quantity int `json:"quantity"` + QuantityUnit string `json:"quantity_unit"` + UnitPrice int `json:"unit_price"` + TaxRate int `json:"tax_rate"` + TotalAmount int `json:"total_amount"` + TotalDiscountAmount int `json:"total_discount_amount"` + TotalTaxAmount int `json:"total_tax_amount"` + ImageURL string `json:"image_url"` } `json:"order_lines"` - Customer struct { - Type string `json:"type"` - Gender string `json:"gender"` - DateOfBirth string `json:"date_of_birth"` - OrganizationRegistrationID string `json:"organization_registration_id"` - VatID string `json:"vat_id"` - } `json:"customer"` MerchantUrls struct { - Terms string `json:"terms"` - Checkout string `json:"checkout"` - Confirmation string `json:"confirmation"` - Push string `json:"push"` - Validation string `json:"validation"` - Notification string `json:"notification"` - CancellationTerms string `json:"cancellation_terms"` - ShippingOptionUpdate string `json:"shipping_option_update"` - AddressUpdate string `json:"address_update"` - CountryChange string `json:"country_change"` + Terms string `json:"terms"` + Checkout string `json:"checkout"` + Confirmation string `json:"confirmation"` + Push string `json:"push"` } `json:"merchant_urls"` - MerchantReference1 string `json:"merchant_reference1"` - MerchantReference2 string `json:"merchant_reference2"` + MerchantReference1 string `json:"merchant_reference1"` + HTMLSnippet string `json:"html_snippet"` + StartedAt time.Time `json:"started_at"` + CompletedAt time.Time `json:"completed_at"` + LastModifiedAt time.Time `json:"last_modified_at"` Options struct { - RequireValidateCallbackSuccess bool `json:"require_validate_callback_success"` - AcquiringChannel string `json:"acquiring_channel"` - VatRemoved bool `json:"vat_removed"` - AllowSeparateShippingAddress bool `json:"allow_separate_shipping_address"` - ColorButton string `json:"color_button"` - ColorButtonText string `json:"color_button_text"` - ColorCheckbox string `json:"color_checkbox"` - ColorCheckboxCheckmark string `json:"color_checkbox_checkmark"` - ColorHeader string `json:"color_header"` - ColorLink string `json:"color_link"` - DateOfBirthMandatory bool `json:"date_of_birth_mandatory"` - ShippingDetails string `json:"shipping_details"` - TitleMandatory bool `json:"title_mandatory"` - AdditionalCheckbox struct { - } `json:"additional_checkbox"` - NationalIdentificationNumberMandatory bool `json:"national_identification_number_mandatory"` - AdditionalMerchantTerms string `json:"additional_merchant_terms"` - PhoneMandatory bool `json:"phone_mandatory"` - RadiusBorder string `json:"radius_border"` - AllowedCustomerTypes []interface{} `json:"allowed_customer_types"` - ShowSubtotalDetail bool `json:"show_subtotal_detail"` - AdditionalCheckboxes []interface{} `json:"additional_checkboxes"` - VerifyNationalIdentificationNumber bool `json:"verify_national_identification_number"` - AutoCapture bool `json:"auto_capture"` - RequireClientValidation bool `json:"require_client_validation"` - EnableDiscountModule bool `json:"enable_discount_module"` - ShowVatRegistrationNumberField bool `json:"show_vat_registration_number_field"` + AllowSeparateShippingAddress bool `json:"allow_separate_shipping_address"` + DateOfBirthMandatory bool `json:"date_of_birth_mandatory"` + RequireValidateCallbackSuccess bool `json:"require_validate_callback_success"` } `json:"options"` - Attachment struct { - Body time.Time `json:"body"` - ContentType string `json:"content_type"` - } `json:"attachment"` - ExternalPaymentMethods []struct { - } `json:"external_payment_methods"` - ExternalCheckouts []struct { - } `json:"external_checkouts"` - ShippingCountries []string `json:"shipping_countries"` - ShippingOptions []struct { - } `json:"shipping_options"` - MerchantData string `json:"merchant_data"` - Gui struct { - Options []interface{} `json:"options"` - } `json:"gui"` - MerchantRequested struct { - } `json:"merchant_requested"` - SelectedShippingOption struct { - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - Promo string `json:"promo"` - Price int `json:"price"` - Preselected bool `json:"preselected"` - TaxAmount int `json:"tax_amount"` - TaxRate int `json:"tax_rate"` - ShippingMethod string `json:"shipping_method"` - DeliveryDetails struct { - } `json:"delivery_details"` - TmsReference string `json:"tms_reference"` - SelectedAddons []interface{} `json:"selected_addons"` - } `json:"selected_shipping_option"` - Recurring bool `json:"recurring"` - BillingCountries []string `json:"billing_countries"` - Tags []string `json:"tags"` - DiscountLines []struct { - } `json:"discount_lines"` + ExternalPaymentMethods []interface{} `json:"external_payment_methods"` + ExternalCheckouts []interface{} `json:"external_checkouts"` + PaymentTypeAllowsIncrease bool `json:"payment_type_allows_increase"` } diff --git a/main.go b/main.go index bcd0eb8..f8b69ff 100644 --- a/main.go +++ b/main.go @@ -13,6 +13,7 @@ import ( "syscall" "time" + messages "git.tornberg.me/go-cart-actor/proto" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/client_golang/prometheus/promhttp" @@ -187,11 +188,46 @@ func main() { w.WriteHeader(http.StatusMethodNotAllowed) return } - var data OrderValidationBody - err := json.NewDecoder(r.Body).Decode(&data) - if err == nil { - cartId := data.MerchantReference1 - log.Printf("Received push for cart %s, status: %s", cartId, data.Status) + orderId := r.URL.Query().Get("order_id") + req, err := http.NewRequest("GET", fmt.Sprintf("https://api.playground.klarna.com/checkout/v3/orders/%s", orderId), nil) + if err != nil { + log.Printf("Error creating request: %v\n", err) + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + + req.Header.Add("Content-Type", "application/json") + req.SetBasicAuth(APIUsername, APIPassword) + + res, err := http.DefaultClient.Do(req) + + if nil != err { + log.Printf("Error making request: %v\n", err) + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + defer res.Body.Close() + var klarnaOrderResponse KlarnaOrderResponse + err = json.NewDecoder(res.Body).Decode(&klarnaOrderResponse) + if err != nil { + log.Printf("Error decoding response: %v\n", err) + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return + } + _, err = syncedServer.pool.Process(ToCartId(klarnaOrderResponse.MerchantReference1), Message{ + Type: OrderCompletedType, + Content: messages.OrderCreated{ + OrderId: klarnaOrderResponse.OrderID, + Status: klarnaOrderResponse.Status}, + }) + if err != nil { + log.Printf("Error processing message: %v\n", err) + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte(err.Error())) + return } w.WriteHeader(http.StatusOK) diff --git a/message-types.go b/message-types.go index b47b8eb..28b11fc 100644 --- a/message-types.go +++ b/message-types.go @@ -11,4 +11,5 @@ const ( SetPickupPointType = 8 CreateCheckoutOrderType = 9 SetCartItemsType = 10 + OrderCompletedType = 11 ) diff --git a/proto/messages.pb.go b/proto/messages.pb.go index d17bd73..54001e3 100644 --- a/proto/messages.pb.go +++ b/proto/messages.pb.go @@ -717,6 +717,58 @@ func (x *CreateCheckoutOrder) GetPush() string { return "" } +type OrderCreated struct { + state protoimpl.MessageState `protogen:"open.v1"` + OrderId string `protobuf:"bytes,1,opt,name=orderId,proto3" json:"orderId,omitempty"` + Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *OrderCreated) Reset() { + *x = OrderCreated{} + mi := &file_messages_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *OrderCreated) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*OrderCreated) ProtoMessage() {} + +func (x *OrderCreated) ProtoReflect() protoreflect.Message { + mi := &file_messages_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use OrderCreated.ProtoReflect.Descriptor instead. +func (*OrderCreated) Descriptor() ([]byte, []int) { + return file_messages_proto_rawDescGZIP(), []int{10} +} + +func (x *OrderCreated) GetOrderId() string { + if x != nil { + return x.OrderId + } + return "" +} + +func (x *OrderCreated) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + var File_messages_proto protoreflect.FileDescriptor var file_messages_proto_rawDesc = string([]byte{ @@ -809,8 +861,13 @@ var file_messages_proto_rawDesc = string([]byte{ 0x74, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x75, 0x73, 0x68, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x75, 0x73, 0x68, 0x42, 0x0c, 0x5a, 0x0a, 0x2e, 0x3b, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x75, 0x73, 0x68, 0x22, 0x40, 0x0a, 0x0c, 0x4f, 0x72, 0x64, + 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x72, 0x64, + 0x65, 0x72, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, + 0x72, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x0c, 0x5a, 0x0a, 0x2e, + 0x3b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, }) var ( @@ -825,7 +882,7 @@ func file_messages_proto_rawDescGZIP() []byte { return file_messages_proto_rawDescData } -var file_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 11) var file_messages_proto_goTypes = []any{ (*AddRequest)(nil), // 0: messages.AddRequest (*SetCartRequest)(nil), // 1: messages.SetCartRequest @@ -837,6 +894,7 @@ var file_messages_proto_goTypes = []any{ (*PickupPoint)(nil), // 7: messages.PickupPoint (*RemoveDelivery)(nil), // 8: messages.RemoveDelivery (*CreateCheckoutOrder)(nil), // 9: messages.CreateCheckoutOrder + (*OrderCreated)(nil), // 10: messages.OrderCreated } var file_messages_proto_depIdxs = []int32{ 0, // 0: messages.SetCartRequest.items:type_name -> messages.AddRequest @@ -863,7 +921,7 @@ func file_messages_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_messages_proto_rawDesc), len(file_messages_proto_rawDesc)), NumEnums: 0, - NumMessages: 10, + NumMessages: 11, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/messages.proto b/proto/messages.proto index 977f89d..4e43901 100644 --- a/proto/messages.proto +++ b/proto/messages.proto @@ -72,4 +72,9 @@ message CreateCheckoutOrder { string checkout = 2; string confirmation = 3; string push = 4; +} + +message OrderCreated { + string orderId = 1; + string status = 2; } \ No newline at end of file