forked from prebid/prebid-server-java
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
952 additions
and
0 deletions.
There are no files selected for viewing
181 changes: 181 additions & 0 deletions
181
src/main/java/org/prebid/server/bidder/mgid/MgidBidder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
package org.prebid.server.bidder.mgid; | ||
|
||
import com.fasterxml.jackson.databind.node.ObjectNode; | ||
import com.iab.openrtb.request.BidRequest; | ||
import com.iab.openrtb.request.Imp; | ||
import com.iab.openrtb.request.Imp.ImpBuilder; | ||
import com.iab.openrtb.response.Bid; | ||
import com.iab.openrtb.response.BidResponse; | ||
import com.iab.openrtb.response.SeatBid; | ||
import io.vertx.core.http.HttpMethod; | ||
import io.vertx.core.json.DecodeException; | ||
import io.vertx.core.json.Json; | ||
import org.apache.commons.lang3.ObjectUtils; | ||
import org.apache.commons.lang3.StringUtils; | ||
import org.prebid.server.bidder.Bidder; | ||
import org.prebid.server.bidder.BidderUtil; | ||
import org.prebid.server.bidder.mgid.model.ExtBidMgid; | ||
import org.prebid.server.bidder.model.BidderBid; | ||
import org.prebid.server.bidder.model.BidderError; | ||
import org.prebid.server.bidder.model.HttpCall; | ||
import org.prebid.server.bidder.model.HttpRequest; | ||
import org.prebid.server.bidder.model.Result; | ||
import org.prebid.server.exception.PreBidException; | ||
import org.prebid.server.proto.openrtb.ext.request.mgid.ExtImpMgid; | ||
import org.prebid.server.proto.openrtb.ext.response.BidType; | ||
import org.prebid.server.util.HttpUtil; | ||
|
||
import java.math.BigDecimal; | ||
import java.util.ArrayList; | ||
import java.util.Collection; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
import java.util.stream.Collectors; | ||
|
||
public class MgidBidder implements Bidder<BidRequest> { | ||
|
||
private static final String DEFAULT_BID_CURRENCY = "USD"; | ||
private final String endpointUrl; | ||
|
||
public MgidBidder(String endpoint) { | ||
endpointUrl = HttpUtil.validateUrl(Objects.requireNonNull(endpoint)); | ||
} | ||
|
||
@Override | ||
public final Result<List<HttpRequest<BidRequest>>> makeHttpRequests(BidRequest bidRequest) { | ||
final List<Imp> imps = new ArrayList<>(); | ||
String accountId = null; | ||
for (Imp imp : bidRequest.getImp()) { | ||
try { | ||
final ExtImpMgid impExt = parseImpExt(imp); | ||
|
||
if (StringUtils.isBlank(accountId) && StringUtils.isNotBlank(impExt.getAccountId())) { | ||
accountId = impExt.getAccountId(); | ||
} | ||
|
||
final Imp modifiedImp = modifyImp(imp, impExt); | ||
imps.add(modifiedImp); | ||
} catch (PreBidException e) { | ||
return Result.emptyWithError(BidderError.badInput(e.getMessage())); | ||
} | ||
} | ||
|
||
if (StringUtils.isBlank(accountId)) { | ||
return Result.emptyWithError(BidderError.badInput("accountId is not set")); | ||
} | ||
|
||
final BidRequest outgoingRequest = bidRequest.toBuilder() | ||
.tmax(bidRequest.getTmax()) | ||
.imp(imps) | ||
.build(); | ||
|
||
final String body = Json.encode(outgoingRequest); | ||
|
||
return Result.of(Collections.singletonList(HttpRequest.<BidRequest>builder() | ||
.method(HttpMethod.POST) | ||
.uri(endpointUrl + accountId) | ||
.body(body) | ||
.headers(BidderUtil.headers()) | ||
.payload(outgoingRequest) | ||
.build()), Collections.emptyList()); | ||
} | ||
|
||
private static ExtImpMgid parseImpExt(Imp imp) { | ||
try { | ||
return Json.mapper.convertValue(imp.getExt().get("bidder"), ExtImpMgid.class); | ||
} catch (IllegalArgumentException e) { | ||
throw new PreBidException(e.getMessage(), e); | ||
} | ||
} | ||
|
||
private static Imp modifyImp(Imp imp, ExtImpMgid impExt) throws PreBidException { | ||
final ImpBuilder impBuilder = imp.toBuilder(); | ||
|
||
final String cur = getCur(impExt); | ||
if (StringUtils.isNotBlank(cur)) { | ||
impBuilder.bidfloorcur(cur); | ||
} | ||
|
||
final BigDecimal bidFloor = getBidFloor(impExt); | ||
if (bidFloor != null) { | ||
impBuilder.bidfloor(bidFloor); | ||
} | ||
|
||
return impBuilder | ||
.tagid(impExt.getPlacementId()) | ||
.build(); | ||
} | ||
|
||
private static String getCur(ExtImpMgid impMgid) { | ||
return ObjectUtils.defaultIfNull( | ||
currencyValueOrNull(impMgid.getCurrency()), currencyValueOrNull(impMgid.getCur())); | ||
} | ||
|
||
private static BigDecimal getBidFloor(ExtImpMgid impMgid) { | ||
return ObjectUtils.defaultIfNull( | ||
bidFloorValueOrNull(impMgid.getBidfloor()), bidFloorValueOrNull(impMgid.getBidFloorSecond())); | ||
} | ||
|
||
private static String currencyValueOrNull(String value) { | ||
return StringUtils.isNotBlank(value) && !value.equals("USD") ? value : null; | ||
} | ||
|
||
private static BigDecimal bidFloorValueOrNull(BigDecimal value) { | ||
return value != null && value.compareTo(BigDecimal.ZERO) > 0 ? value : null; | ||
} | ||
|
||
@Override | ||
public final Result<List<BidderBid>> makeBids(HttpCall<BidRequest> httpCall, | ||
BidRequest bidRequest) { | ||
try { | ||
final BidResponse bidResponse = Json | ||
.decodeValue(httpCall.getResponse().getBody(), BidResponse.class); | ||
return Result.of(extractBids(bidResponse), | ||
Collections.emptyList()); | ||
} catch (DecodeException | PreBidException e) { | ||
return Result.emptyWithError(BidderError.badServerResponse(e.getMessage())); | ||
} | ||
} | ||
|
||
private static List<BidderBid> extractBids(BidResponse bidResponse) { | ||
if (bidResponse == null || bidResponse.getSeatbid() == null) { | ||
return Collections.emptyList(); | ||
} | ||
return bidsFromResponse(bidResponse); | ||
} | ||
|
||
private static List<BidderBid> bidsFromResponse(BidResponse bidResponse) { | ||
return bidResponse.getSeatbid().stream() | ||
.filter(Objects::nonNull) | ||
.map(SeatBid::getBid) | ||
.filter(Objects::nonNull) | ||
.flatMap(Collection::stream) | ||
.map(bid -> BidderBid.of(bid, getBidType(bid), DEFAULT_BID_CURRENCY)) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
private static BidType getBidType(Bid bid) { | ||
final ExtBidMgid bidExt = getBidExt(bid); | ||
if (bidExt == null) { | ||
return BidType.banner; | ||
} | ||
|
||
final BidType crtype = bidExt.getCrtype(); | ||
return crtype == null ? BidType.banner : crtype; | ||
} | ||
|
||
private static ExtBidMgid getBidExt(Bid bid) { | ||
try { | ||
return Json.mapper.convertValue(bid.getExt(), ExtBidMgid.class); | ||
} catch (IllegalArgumentException e) { | ||
return null; | ||
} | ||
} | ||
|
||
@Override | ||
public final Map<String, String> extractTargeting(ObjectNode ext) { | ||
return Collections.emptyMap(); | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
src/main/java/org/prebid/server/bidder/mgid/model/ExtBidMgid.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package org.prebid.server.bidder.mgid.model; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Value; | ||
import org.prebid.server.proto.openrtb.ext.response.BidType; | ||
|
||
@Value | ||
@AllArgsConstructor(staticName = "of") | ||
public class ExtBidMgid { | ||
|
||
BidType crtype; | ||
} |
31 changes: 31 additions & 0 deletions
31
src/main/java/org/prebid/server/proto/openrtb/ext/request/mgid/ExtImpMgid.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package org.prebid.server.proto.openrtb.ext.request.mgid; | ||
|
||
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Value; | ||
|
||
import java.math.BigDecimal; | ||
|
||
/** | ||
* Defines the contract for bidRequest.imp[i].ext.mgid | ||
*/ | ||
@AllArgsConstructor( | ||
staticName = "of" | ||
) | ||
@Value | ||
public class ExtImpMgid { | ||
@JsonProperty("accountId") | ||
String accountId; | ||
|
||
@JsonProperty("placementId") | ||
String placementId; | ||
|
||
String cur; | ||
|
||
String currency; | ||
|
||
BigDecimal bidfloor; | ||
|
||
@JsonProperty("bidFloor") | ||
BigDecimal bidFloorSecond; | ||
} |
49 changes: 49 additions & 0 deletions
49
src/main/java/org/prebid/server/spring/config/bidder/MgidConfiguration.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package org.prebid.server.spring.config.bidder; | ||
|
||
import org.prebid.server.bidder.BidderDeps; | ||
import org.prebid.server.bidder.mgid.MgidBidder; | ||
import org.prebid.server.spring.config.bidder.model.BidderConfigurationProperties; | ||
import org.prebid.server.spring.config.bidder.util.BidderDepsAssembler; | ||
import org.prebid.server.spring.config.bidder.util.BidderInfoCreator; | ||
import org.prebid.server.spring.config.bidder.util.UsersyncerCreator; | ||
import org.prebid.server.spring.env.YamlPropertySourceFactory; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.beans.factory.annotation.Qualifier; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.boot.context.properties.ConfigurationProperties; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.context.annotation.PropertySource; | ||
|
||
import javax.validation.constraints.NotBlank; | ||
|
||
@Configuration | ||
@PropertySource(value = "classpath:/bidder-config/mgid.yaml", factory = YamlPropertySourceFactory.class) | ||
public class MgidConfiguration { | ||
|
||
private static final String BIDDER_NAME = "mgid"; | ||
|
||
@Value("${external-url}") | ||
@NotBlank | ||
private String externalUrl; | ||
|
||
@Autowired | ||
@Qualifier("mgidConfigurationProperties") | ||
private BidderConfigurationProperties configProperties; | ||
|
||
@Bean("mgidConfigurationProperties") | ||
@ConfigurationProperties("adapters.mgid") | ||
BidderConfigurationProperties configurationProperties() { | ||
return new BidderConfigurationProperties(); | ||
} | ||
|
||
@Bean | ||
BidderDeps mgidBidderDeps() { | ||
return BidderDepsAssembler.forBidder(BIDDER_NAME) | ||
.withConfig(configProperties) | ||
.bidderInfo(BidderInfoCreator.create(configProperties)) | ||
.usersyncerCreator(UsersyncerCreator.create(configProperties.getUsersync(), externalUrl)) | ||
.bidderCreator(() -> new MgidBidder(configProperties.getEndpoint())) | ||
.assemble(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
adapters: | ||
mgid: | ||
enabled: false | ||
endpoint: https://prebid.mgid.com/prebid/ | ||
pbs-enforces-gdpr: true | ||
deprecated-names: | ||
aliases: | ||
meta-info: | ||
maintainer-email: [email protected] | ||
app-media-types: | ||
- banner | ||
- native | ||
site-media-types: | ||
- banner | ||
- native | ||
supported-vendors: | ||
vendor-id: 358 | ||
usersync: | ||
url: https://cm.mgid.com/m?cdsp=363893&adu= | ||
redirect-url: /setuid?bidder=mgid&gdpr={{gdpr}}&gdpr_consent={{gdpr_consent}}&uid={muidn} | ||
cookie-family-name: mgid | ||
type: redirect | ||
support-cors: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
{ | ||
"$schema": "http://json-schema.org/draft-04/schema#", | ||
"title": "Mgid Params", | ||
"description": "A schema which validates params accepted by the Mgid", | ||
"type": "object", | ||
"properties": { | ||
"accountId": { | ||
"type": "string", | ||
"description": "Internal Mgid account ID" | ||
}, | ||
"placementId": { | ||
"type": "string", | ||
"description": "Internal Mgid Placement ID" | ||
}, | ||
"cur": { | ||
"type": "string", | ||
"description": "optional bidfloor currency" | ||
}, | ||
"currency": { | ||
"type": "string", | ||
"description": "optional bidfloor currency" | ||
}, | ||
"bidfloor": { | ||
"type": "number", | ||
"description": "optional minimum acceptable bid, in CPM, USD by default" | ||
}, | ||
"bidFloor": { | ||
"type": "number", | ||
"description": "optional minimum acceptable bid, in CPM, USD by default" | ||
} | ||
}, | ||
"required": ["accountId","placementId"] | ||
} |
Oops, something went wrong.