Skip to content

Commit

Permalink
New Adapter: TPMN (#2947)
Browse files Browse the repository at this point in the history
Co-authored-by: changjun <changjun@tpmn.io>
  • Loading branch information
tpmn-admin and changjun authored Jul 28, 2023
1 parent 555c0a1 commit 462bb1d
Show file tree
Hide file tree
Showing 19 changed files with 1,398 additions and 0 deletions.
44 changes: 44 additions & 0 deletions adapters/tpmn/params_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package tpmn

import (
"encoding/json"
"github.com/prebid/prebid-server/openrtb_ext"
"testing"
)

var validParams = []string{
`{"inventoryId": 10000001}`,
}

var invalidParams = []string{
`{"inventoryId": "00000001"}`,
`{"inventoryid": 100000000}`,
}

// TestValidParams makes sure that the tpmn schema accepts all imp.ext fields which we intend to support.
func TestValidParams(t *testing.T) {
validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
if err != nil {
t.Fatalf("Failed to fetch the json-schemas. %v", err)
}

for _, validParam := range validParams {
if err := validator.Validate(openrtb_ext.BidderTpmn, json.RawMessage(validParam)); err != nil {
t.Errorf("Schema rejected TPMN params: %s", validParam)
}
}
}

// TestInvalidParams makes sure that the tpmn schema rejects all the imp.ext fields we don't support.
func TestInvalidParams(t *testing.T) {
validator, err := openrtb_ext.NewBidderParamsValidator("../../static/bidder-params")
if err != nil {
t.Fatalf("Failed to fetch the json-schemas. %v", err)
}

for _, invalidParam := range invalidParams {
if err := validator.Validate(openrtb_ext.BidderTpmn, json.RawMessage(invalidParam)); err == nil {
t.Errorf("Schema allowed unexpected params: %s", invalidParam)
}
}
}
126 changes: 126 additions & 0 deletions adapters/tpmn/tpmn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package tpmn

import (
"encoding/json"
"fmt"
"net/http"
"strings"

"github.com/prebid/openrtb/v19/openrtb2"
"github.com/prebid/prebid-server/adapters"
"github.com/prebid/prebid-server/config"
"github.com/prebid/prebid-server/openrtb_ext"
)

// TpmnAdapter struct
type adapter struct {
uri string
}

// MakeRequests makes the HTTP requests which should be made to fetch bids from TpmnBidder.
func (rcv *adapter) MakeRequests(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]*adapters.RequestData, []error) {
validImps, errs := getValidImpressions(request, reqInfo)
if len(validImps) == 0 {
return nil, errs
}

request.Imp = validImps

requestBodyJSON, err := json.Marshal(request)
if err != nil {
errs = append(errs, err)
return nil, errs
}

headers := http.Header{}
headers.Add("Content-Type", "application/json;charset=utf-8")
headers.Add("Accept", "application/json")

return []*adapters.RequestData{{
Method: http.MethodPost,
Uri: rcv.uri,
Body: requestBodyJSON,
Headers: headers,
}}, errs
}

// getValidImpressions validate imps and check for bid floor currency. Convert to EUR if necessary
func getValidImpressions(request *openrtb2.BidRequest, reqInfo *adapters.ExtraRequestInfo) ([]openrtb2.Imp, []error) {
var errs []error
var validImps []openrtb2.Imp

for _, imp := range request.Imp {
if err := preprocessBidFloorCurrency(&imp, reqInfo); err != nil {
errs = append(errs, err)
continue
}
validImps = append(validImps, imp)
}
return validImps, errs
}

func preprocessBidFloorCurrency(imp *openrtb2.Imp, reqInfo *adapters.ExtraRequestInfo) error {
// we expect every currency related data to be EUR
if imp.BidFloor > 0 && strings.ToUpper(imp.BidFloorCur) != "USD" && imp.BidFloorCur != "" {
if convertedValue, err := reqInfo.ConvertCurrency(imp.BidFloor, imp.BidFloorCur, "USD"); err != nil {
return err
} else {
imp.BidFloor = convertedValue
}
}
imp.BidFloorCur = "USD"
return nil
}

func (a *adapter) MakeBids(request *openrtb2.BidRequest, _ *adapters.RequestData, responseData *adapters.ResponseData) (*adapters.BidderResponse, []error) {
if adapters.IsResponseStatusCodeNoContent(responseData) {
return nil, nil
}

if err := adapters.CheckResponseStatusCodeForErrors(responseData); err != nil {
return nil, []error{err}
}

var response openrtb2.BidResponse
if err := json.Unmarshal(responseData.Body, &response); err != nil {
return nil, []error{fmt.Errorf("bid response unmarshal: %v", err)}
}

bidResponse := adapters.NewBidderResponseWithBidsCapacity(len(request.Imp))
bidResponse.Currency = response.Cur
for _, seatBid := range response.SeatBid {
for i, bid := range seatBid.Bid {
bidType, err := getMediaTypeForImp(bid)
if err != nil {
return nil, []error{err}
}
b := &adapters.TypedBid{
Bid: &seatBid.Bid[i],
BidType: bidType,
}
bidResponse.Bids = append(bidResponse.Bids, b)
}
}
return bidResponse, nil
}

func getMediaTypeForImp(bid openrtb2.Bid) (openrtb_ext.BidType, error) {
switch bid.MType {
case openrtb2.MarkupBanner:
return openrtb_ext.BidTypeBanner, nil
case openrtb2.MarkupVideo:
return openrtb_ext.BidTypeVideo, nil
case openrtb2.MarkupNative:
return openrtb_ext.BidTypeNative, nil
default:
return "", fmt.Errorf("unsupported MType %d", bid.MType)
}
}

// Builder builds a new instance of the TpmnBidder adapter for the given bidder with the given config.
func Builder(_ openrtb_ext.BidderName, config config.Adapter, server config.Server) (adapters.Bidder, error) {
bidder := &adapter{
uri: config.Endpoint,
}
return bidder, nil
}
20 changes: 20 additions & 0 deletions adapters/tpmn/tpmn_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package tpmn

import (
"testing"

"github.com/prebid/prebid-server/adapters/adapterstest"
"github.com/prebid/prebid-server/config"
"github.com/prebid/prebid-server/openrtb_ext"
)

func TestJsonSamples(t *testing.T) {
bidder, buildErr := Builder(openrtb_ext.BidderTpmn, config.Adapter{
Endpoint: "https://gat.tpmn.io/ortb/pbs_bidder"}, config.Server{ExternalUrl: "http://hosturl.com", GvlID: 1, DataCenter: "2"})

if buildErr != nil {
t.Fatalf("Builder returned unexpected error %v", buildErr)
}

adapterstest.RunJSONBidderTest(t, "tpmntest", bidder)
}
135 changes: 135 additions & 0 deletions adapters/tpmn/tpmntest/exemplary/simple-banner.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
{
"mockBidRequest": {
"id": "test-request-id",
"imp": [
{
"id": "test-imp-id",
"banner": {
"format": [
{
"w": 300,
"h": 250
},
{
"w": 300,
"h": 600
}
]
},
"tagid": "00000001",
"ext": {
"bidder": {
"inventoryId": 10000001
}
}
}
],
"app": {
"id": "1",
"bundle": "com.wls.testwlsapplication"
},
"device": {
"ip": "123.123.123.123",
"ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
}
},
"httpCalls": [
{
"expectedRequest": {
"uri": "https://gat.tpmn.io/ortb/pbs_bidder",
"body": {
"id": "test-request-id",
"imp": [
{
"id": "test-imp-id",
"banner": {
"format": [
{
"w": 300,
"h": 250
},
{
"w": 300,
"h": 600
}
]
},
"tagid": "00000001",
"bidfloorcur": "USD",
"ext": {
"bidder": {
"inventoryId": 10000001
}
}
}
],
"app": {
"id": "1",
"bundle": "com.wls.testwlsapplication"
},
"device": {
"ip": "123.123.123.123",
"ifa": "zxcjbzxmc-zxcbmz-zxbcz-zxczx"
}
}
},
"mockResponse": {
"status": 200,
"body": {
"id": "test-request-id",
"seatbid": [
{
"bid": [
{
"id": "test_bid_id",
"impid": "test-imp-id",
"price": 0.27543,
"adm": "<iframe id=\"adm-banner-16\" width=\"300\" height=\"250\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"https://gat.tpmn.io/ortb/pbs_bidder&k=882b2510ed6d6c94fa69c99aa522a708\"></iframe>",
"cid": "test_cid",
"crid": "test_crid",
"dealid": "test_dealid",
"w": 300,
"h": 250,
"mtype": 1,
"ext": {
"prebid": {
"type": "banner"
}
}
}
],
"seat": "tpmn"
}
],
"cur": "USD"
}
}
}
],
"expectedBidResponses": [
{
"bids": [
{
"bid": {
"id": "test_bid_id",
"impid": "test-imp-id",
"price": 0.27543,
"adm": "<iframe id=\"adm-banner-16\" width=\"300\" height=\"250\" frameborder=\"0\" marginheight=\"0\" marginwidth=\"0\" style=\"{overflow:hidden}\" src=\"https://gat.tpmn.io/ortb/pbs_bidder&k=882b2510ed6d6c94fa69c99aa522a708\"></iframe>",
"cid": "test_cid",
"crid": "test_crid",
"dealid": "test_dealid",
"w": 300,
"h": 250,
"mtype": 1,
"ext": {
"prebid": {
"type": "banner"
}
}
},
"type": "banner"
}
]
}
]
}
Loading

0 comments on commit 462bb1d

Please sign in to comment.