Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 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
52 changes: 50 additions & 2 deletions src/main/java/org/prebid/server/bidder/openx/OpenxBidder.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.prebid.server.bidder.model.HttpRequest;
import org.prebid.server.bidder.model.Result;
import org.prebid.server.bidder.openx.model.OpenxImpType;
import org.prebid.server.bidder.openx.proto.OpenxBidExt;
import org.prebid.server.bidder.openx.proto.OpenxBidResponse;
import org.prebid.server.bidder.openx.proto.OpenxBidResponseExt;
import org.prebid.server.bidder.openx.proto.OpenxRequestExt;
Expand All @@ -29,6 +30,8 @@
import org.prebid.server.proto.openrtb.ext.request.ExtRequest;
import org.prebid.server.proto.openrtb.ext.request.openx.ExtImpOpenx;
import org.prebid.server.proto.openrtb.ext.response.BidType;
import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebid;
import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidMeta;
import org.prebid.server.proto.openrtb.ext.response.ExtBidPrebidVideo;
import org.prebid.server.proto.openrtb.ext.response.ExtIgi;
import org.prebid.server.proto.openrtb.ext.response.ExtIgiIgs;
Expand Down Expand Up @@ -270,13 +273,13 @@ private ObjectNode makeImpExt(ObjectNode impExt, boolean addCustomParams) {
return openxImpExt;
}

private static List<BidderBid> extractBids(BidRequest bidRequest, OpenxBidResponse bidResponse) {
private List<BidderBid> extractBids(BidRequest bidRequest, OpenxBidResponse bidResponse) {
return bidResponse == null || CollectionUtils.isEmpty(bidResponse.getSeatbid())
? Collections.emptyList()
: bidsFromResponse(bidRequest, bidResponse);
}

private static List<BidderBid> bidsFromResponse(BidRequest bidRequest, OpenxBidResponse bidResponse) {
private List<BidderBid> bidsFromResponse(BidRequest bidRequest, OpenxBidResponse bidResponse) {
final Map<String, BidType> impIdToBidType = impIdToBidType(bidRequest);

final String bidCurrency = StringUtils.isNotBlank(bidResponse.getCur())
Expand All @@ -288,6 +291,7 @@ private static List<BidderBid> bidsFromResponse(BidRequest bidRequest, OpenxBidR
.map(SeatBid::getBid)
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.map(bid -> bid.toBuilder().ext(updateBidMeta(bid)).build())
.map(bid -> toBidderBid(bid, impIdToBidType, bidCurrency))
.toList();
}
Expand Down Expand Up @@ -334,4 +338,48 @@ private static List<ExtIgi> extractIgi(OpenxBidResponse bidResponse) {

return igs.isEmpty() ? null : Collections.singletonList(ExtIgi.builder().igs(igs).build());
}

private ObjectNode updateBidMeta(Bid bid) {
final ObjectNode ext = bid.getExt();
if (ext == null) {
return null;
}

final OpenxBidExt openxBidExt = parseOpenxBidExt(ext);
final int buyerId = parseStringToInt(openxBidExt.getBuyerId());
final int dspId = parseStringToInt(openxBidExt.getDspId());
final int brandId = parseStringToInt(openxBidExt.getBrandId());

if (buyerId == 0 && dspId == 0 && brandId == 0) {
return ext;
}

final ExtBidPrebidMeta updatedMeta = ExtBidPrebidMeta.builder()
.networkId(dspId)
.advertiserId(buyerId)
.brandId(brandId)
.build();

final ExtBidPrebid modifiedExtBidPrebid = ExtBidPrebid.builder().meta(updatedMeta).build();

ext.set(PREBID_EXT, mapper.mapper().valueToTree(modifiedExtBidPrebid));

return ext;
}

private OpenxBidExt parseOpenxBidExt(ObjectNode ext) {
try {
return mapper.mapper().convertValue(ext, OpenxBidExt.class);
} catch (IllegalArgumentException e) {
return new OpenxBidExt();
}
}

private int parseStringToInt(String value) {
try {
return value != null ? Integer.parseInt(value) : 0;
} catch (NumberFormatException e) {
return 0;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.prebid.server.bidder.openx.proto;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;

@Getter
public class OpenxBidExt {

@JsonProperty("dsp_id")
String dspId;
@JsonProperty("buyer_id")
String buyerId;
@JsonProperty("brand_id")
String brandId;
}
106 changes: 106 additions & 0 deletions src/test/java/org/prebid/server/bidder/openx/OpenxBidderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.iab.openrtb.request.Audio;
import com.iab.openrtb.request.Banner;
Expand Down Expand Up @@ -990,4 +991,109 @@ private static Map<String, JsonNode> givenCustomParams(String key, Object values
private static BidderCall<BidRequest> givenHttpCall(String body) {
return BidderCall.succeededHttp(null, HttpResponse.of(200, null, body), null);
}

@Test
public void makeBidsShouldReturnBidMeta() throws JsonProcessingException {
// given
final ObjectNode allBuyerExt = new ObjectNode(JsonNodeFactory.instance);
final ObjectNode onlyBrandExt = new ObjectNode(JsonNodeFactory.instance);
final ObjectNode badExt = new ObjectNode(JsonNodeFactory.instance);

allBuyerExt.put("dsp_id", "1").put("buyer_id", "2").put("brand_id", "3");
onlyBrandExt.put("brand_id", "4");
badExt.put("dsp_id", "abc").put("brand_id", "cba");

final String allBuyerExpectedExtJson = "{\"dsp_id\":\"1\",\"buyer_id\":\"2\",\"brand_id\":\"3\",\"prebid\":"
+ "{\"meta\":{\"advertiserId\":2,\"brandId\":3,\"networkId\":1}}}";
final String onlyBrandExpectedExtJson = "{\"brand_id\":\"4\",\"prebid\":{\"meta\":{\"advertiserId\":0,"
+ "\"brandId\":4,\"networkId\":0}}}";
final String badExpectedExtJson = "{\"dsp_id\":\"abc\",\"brand_id\":\"cba\"}";

final ObjectNode allBuyerExpectedExt = (ObjectNode) mapper.readTree(allBuyerExpectedExtJson);
final ObjectNode onlyBrandExpectedExt = (ObjectNode) mapper.readTree(onlyBrandExpectedExtJson);
final ObjectNode badExpectedExt = (ObjectNode) mapper.readTree(badExpectedExtJson);

final BidderCall<BidRequest> httpCall = givenHttpCall(mapper.writeValueAsString(BidResponse.builder()
.seatbid(singletonList(SeatBid.builder()
.bid(List.of(
Bid.builder()
.w(200)
.h(150)
.price(BigDecimal.ONE)
.impid("impId1")
.dealid("dealid")
.adm("<div>This is an Ad</div>")
.ext(allBuyerExt)
.build(),
Bid.builder()
.w(200)
.h(150)
.price(BigDecimal.ONE)
.impid("impId1")
.dealid("dealid2")
.adm("<div>This is an Ad</div>")
.ext(onlyBrandExt)
.build(),
Bid.builder()
.w(200)
.h(150)
.price(BigDecimal.ONE)
.impid("impId1")
.dealid("dealid3")
.adm("<div>This is an Ad</div>")
.ext(badExt)
.build()))
.build()))
.build()));

final BidRequest bidRequest = BidRequest.builder()
.id("bidRequestId")
.imp(List.of(
Imp.builder()
.id("impId1")
.banner(Banner.builder().build())
.build()))
.build();

// when
final CompositeBidderResponse result = target.makeBidderResponse(httpCall, bidRequest);

// then
assertThat(result.getErrors()).isEmpty();
assertThat(result.getBids()).hasSize(3).containsExactlyInAnyOrder(
BidderBid.of(
Bid.builder()
.impid("impId1")
.price(BigDecimal.ONE)
.dealid("dealid")
.w(200)
.h(150)
.adm("<div>This is an Ad</div>")
.ext(allBuyerExpectedExt)
.build(),
BidType.banner, "USD"),
BidderBid.of(
Bid.builder()
.impid("impId1")
.price(BigDecimal.ONE)
.dealid("dealid2")
.w(200)
.h(150)
.adm("<div>This is an Ad</div>")
.ext(onlyBrandExpectedExt)
.build(),
BidType.banner, "USD"),
BidderBid.of(
Bid.builder()
.impid("impId1")
.price(BigDecimal.ONE)
.dealid("dealid3")
.w(200)
.h(150)
.adm("<div>This is an Ad</div>")
.ext(badExpectedExt)
.build(),
BidType.banner, "USD")
);
}
}
Loading