Files
mrktplaats/listing.go
T
Joren 25410749db Initial Marktplaats SDK scaffold
Clone the twdehands SDK into mrktplaats and retarget naming and defaults for app.marktplaats.nl while keeping the same request/response bodies and endpoint behavior.
2026-04-15 23:45:49 +02:00

114 lines
3.7 KiB
Go

package mrktplaats
import (
"context"
"encoding/json"
"fmt"
"net/url"
"strings"
)
// ListingService handles viewing individual listing details (VIP).
type ListingService struct {
t *transport
}
// ListingDetail is the full detail view of a single listing.
type ListingDetail struct {
AdCore AdCore `json:"adCore"`
SellerInformation SellerInformation `json:"sellerInformation"`
Bids []Bid `json:"bids,omitempty"`
CurrentMinimumBid int `json:"currentMinimumBid,omitempty"`
ShowBanner bool `json:"showBanner,omitempty"`
Traits json.RawMessage `json:"traits,omitempty"`
BuyersProtectionAllowed bool `json:"buyersProtectionAllowed,omitempty"`
IsBuyerProtectionApplicableForDefaultOn bool `json:"isBuyerProtectionApplicableForDefaultOn,omitempty"`
LargeItemShippingLogicalAllowed bool `json:"largeItemShippingLogicalAllowed,omitempty"`
}
// DefaultCTATypes is the standard set of CTA types the client declares support for.
var DefaultCTATypes = []string{"bid", "asq", "website", "phone", "buyNow"}
type viewItemRequest struct {
SupportedCTATypes []string `json:"supportedCTATypes"`
SupportsReservedFlag bool `json:"supportsReservedFlag"`
}
// Get retrieves the full details of a listing by its URN.
// An optional correlationID (from a prior search) can be passed for analytics.
func (s *ListingService) Get(ctx context.Context, urn string, correlationID ...string) (*ListingDetail, error) {
path := fmt.Sprintf("/app/vip/v4/item/%s", urn)
var params url.Values
if len(correlationID) > 0 && correlationID[0] != "" {
params = url.Values{"correlation_id": {correlationID[0]}}
}
body := viewItemRequest{
SupportedCTATypes: DefaultCTATypes,
SupportsReservedFlag: true,
}
var resp ListingDetail
if err := s.t.postJSON(ctx, path, params, nil, body, &resp); err != nil {
return nil, err
}
return &resp, nil
}
// VIPDisplayTargetingRequest defines parameters for item page ad targeting.
// Positions is serialized as a comma-separated string; Postcode and SellerID
// are sent as JSON null when empty.
type VIPDisplayTargetingRequest struct {
AdURN string
Attr json.RawMessage
Positions []string
Postcode string
SellerID string
}
// MarshalJSON serializes in the format the marktplaats API expects.
func (r VIPDisplayTargetingRequest) MarshalJSON() ([]byte, error) {
attr := r.Attr
if len(attr) == 0 {
attr = json.RawMessage(`{}`)
}
type wire struct {
AdURN string `json:"adUrn"`
Attr json.RawMessage `json:"attr"`
Positions string `json:"positions"`
Postcode *string `json:"postcode"`
SellerID *string `json:"sellerId"`
}
w := wire{
AdURN: r.AdURN,
Attr: attr,
Positions: strings.Join(r.Positions, ", "),
}
if r.Postcode != "" {
w.Postcode = &r.Postcode
}
if r.SellerID != "" {
w.SellerID = &r.SellerID
}
return json.Marshal(w)
}
// DefaultVIPPositions are the standard ad positions for an item detail page.
var DefaultVIPPositions = []string{
"VIP_LEADERBOARD_MID1",
"vip_native",
"vip_native_2",
"VIP_GALLERY_BANNER",
"VIP_DESCRIPTION_BANNER",
}
// DisplayTargeting retrieves ad targeting configuration for a listing detail page.
func (s *ListingService) DisplayTargeting(ctx context.Context, req *VIPDisplayTargetingRequest) ([]DisplayTargetingResult, error) {
var resp []DisplayTargetingResult
if err := s.t.postJSON(ctx, "/app/vip/v4/display-targeting", nil, nil, req, &resp); err != nil {
return nil, err
}
return resp, nil
}