Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 124 additions & 0 deletions business.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// Copyright (c) 2025 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package whatsmeow

import (
"context"
"fmt"
"strconv"

waBinary "go.mau.fi/whatsmeow/binary"
"go.mau.fi/whatsmeow/types"
)

// GetOrderDetails fetches the details of a specific order using its ID and token.
// Both token and orderID is found in the OrderMessage.
func (cli *Client) GetOrderDetails(ctx context.Context, orderID, tokenBase64 string) (*types.OrderDetails, error) {
resp, err := cli.sendIQ(infoQuery{

Check failure on line 21 in business.go

View workflow job for this annotation

GitHub Actions / Build (old)

not enough arguments in call to cli.sendIQ

Check failure on line 21 in business.go

View workflow job for this annotation

GitHub Actions / Build (latest)

not enough arguments in call to cli.sendIQ
Namespace: "fb:thrift_iq",
Type: iqGet,
SMaxID: "5",
To: types.ServerJID,
Content: []waBinary.Node{{
Tag: "order",
Attrs: waBinary.Attrs{
"op": "get",
"id": orderID,
},
Content: []waBinary.Node{
{
Tag: "image_dimensions",
Content: []waBinary.Node{
{Tag: "width", Content: []byte("100")},
{Tag: "height", Content: []byte("100")},
},
},
{Tag: "token", Content: []byte(tokenBase64)},
},
}},
Context: ctx,

Check failure on line 43 in business.go

View workflow job for this annotation

GitHub Actions / Build (old)

unknown field Context in struct literal of type infoQuery

Check failure on line 43 in business.go

View workflow job for this annotation

GitHub Actions / Build (latest)

unknown field Context in struct literal of type infoQuery
})
if err != nil {
return nil, fmt.Errorf("failed to send order IQ: %w", err)
}

orderNode, ok := resp.GetOptionalChildByTag("order")
if !ok {
return nil, &ElementMissingError{Tag: "order", In: "response to order query"}
}

return parseOrderDetailsNode(orderNode)
}

// Helper to get the string content of a child node.
func getStringChild(node waBinary.Node, tag string) string {
child, ok := node.GetOptionalChildByTag(tag)
if !ok {
return ""
}
content, _ := child.Content.([]byte)
return string(content)
}

func parseOrderDetailsNode(orderNode waBinary.Node) (*types.OrderDetails, error) {
ag := orderNode.AttrGetter()
details := &types.OrderDetails{
ID: ag.String("id"),
CreatedAt: ag.UnixTime("creation_ts"),
}
if err := ag.Error(); err != nil {
return nil, err
}

// Parse Price
priceNode, ok := orderNode.GetOptionalChildByTag("price")
if ok {
subtotal, _ := strconv.ParseInt(getStringChild(priceNode, "subtotal"), 10, 64)
total, _ := strconv.ParseInt(getStringChild(priceNode, "total"), 10, 64)
details.Price = types.OrderPrice{
Subtotal: subtotal,
Total: total,
Currency: getStringChild(priceNode, "currency"),
PriceStatus: getStringChild(priceNode, "price_status"),
}
}

// Parse Catalog ID
catalogNode, ok := orderNode.GetOptionalChildByTag("catalog")
if ok {
details.CatalogID = getStringChild(catalogNode, "id")
}

// Parse Products
for _, productNode := range orderNode.GetChildrenByTag("product") {
price, _ := strconv.ParseInt(getStringChild(productNode, "price"), 10, 64)
quantity, _ := strconv.Atoi(getStringChild(productNode, "quantity"))

product := types.OrderProduct{
ID: getStringChild(productNode, "id"),
Price: price,
Currency: getStringChild(productNode, "currency"),
Name: getStringChild(productNode, "name"),
Quantity: quantity,
}

// Parse Product Image
if imageNode, ok := productNode.GetOptionalChildByTag("image"); ok {
product.ImageID = getStringChild(imageNode, "id")
product.ImageURL = getStringChild(imageNode, "url")
}

// Parse Variant Info
if variantNode, ok := productNode.GetOptionalChildByTag("variant_info"); ok {
product.VariantInfo.Properties = getStringChild(variantNode, "properties")
}

details.Products = append(details.Products, product)
}

return details, nil
}
39 changes: 39 additions & 0 deletions types/business.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) 2025 Tulir Asokan
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package types

import "time"

type OrderDetails struct {
ID string `json:"id"`
CreatedAt time.Time `json:"created_at"`
CatalogID string `json:"catalog_id,omitempty"`
Price OrderPrice `json:"price"`
Products []OrderProduct `json:"products"`
}

type OrderProduct struct {
ID string `json:"id"`
ImageID string `json:"image_id,omitempty"`
ImageURL string `json:"image_url,omitempty"`
Price int64 `json:"price"`
Currency string `json:"currency"`
Name string `json:"name"`
Quantity int `json:"quantity"`
VariantInfo VariantInfo `json:"variant_info,omitempty"`
}

type VariantInfo struct {
Properties string `json:"properties,omitempty"`
}

type OrderPrice struct {
Subtotal int64 `json:"subtotal"`
Total int64 `json:"total"`
Currency string `json:"currency"`
PriceStatus string `json:"price_status,omitempty"`
}
Loading