Golang server side Android in-app billing verification

Introduction

When developing android application to integrate with purchase or billing, you might headed to Google in-app billing. Normally it is simple, if your application is standalone not connect to any server your android just interact with google play and all of the rest of logic of purchasing will be handled by Google Play/Billing.

If your app need to connect to server for in-app billing items (such as game server, buy item service, database service …), it might have risk that here might be a fake apps (or crack app) to fake the purchase command in your app to get privilege action or items.

In this case, our server have to do a server-to-server side certification with Google Play.

Lets get started

I assumed you have follow previous article to set up credential and grant access of your Google Developer Console in Google Play console. And don’t forget your json file which you got. For the first article let’s make sure you can get result from the google play based on token/signature you have from purchasing process or testing purpose you can get it from order management in your Google play developer console.

package main

import (
    "golang.org/x/oauth2"
    "golang.org/x/oauth2/google"
    "io/ioutil"
    "log"

    "net/http"
    "os"
    "time"
    "strconv"
    "encoding/json"
)

/*
    consumptionState    : The consumption state of the inapp product. Possible values are: (0) Yet to be consumed (1) Consumed
    developerPayload    : A developer-specified string that contains supplemental information about an order.
    kind                : This kind represents an inappPurchase object in the androidpublisher service.
    orderId             : The order id associated with the purchase of the inapp product.
    purchaseState       : The purchase state of the order. Possible values are: (0) Purchased (1) Cancelled
    purchaseTimeMillis  : The time the product was purchased, in milliseconds since the epoch (Jan 1, 1970).
*/

type GoogleIAP struct {
    Kind               string `json:"kind"`
    PurchaseTimeMillis string `json:"purchaseTimeMillis"`
    PurchaseState      string `json:"purchaseState"`
    ConsumptionState   bool   `json:"consumptionState"`
    OrderId            string `json:"orderId"`
    DeveloperPayload   string `json:"developerPayload"`
}

func main() {

    data, err := ioutil.ReadFile("credential.json") // PUT your credential json file 
    if err != nil {
        log.Fatal(err)
    }

    conf, err := google.JWTConfigFromJSON(data, "https://www.googleapis.com/auth/androidpublisher")
    if err != nil {
        log.Fatal("conf", err)
    }

    client := conf.Client(oauth2.NoContext)
    tokenPurchasedProduct := "PUT YOUR TOKEN / SIGNATURE of Product you purchase"
    purchaseType := "products"

    productId := "chat"

    resp, err := client.Get("https://www.googleapis.com/androidpublisher/v2/applications/{put your app package name}/purchases/" + purchaseType + "/" + productId + "/tokens/" + tokenPurchasedProduct)    

    if err != nil {
        log.Println("err:", err)
    }

    body, err := ioutil.ReadAll(resp.Body)
    log.Println("response: ", string(body))

    appResult := &GoogleIAP{}
    err = json.Unmarshal(body, &appResult)

    // to transfer to purchase time millisecond to time.Time
    timeDuration, _ := strconv.ParseInt(appResult.PurchaseTimeMillis, 10, 64)
    log.Println("time duration: ", timeDuration)

    timePurchase := time.Unix(timeDuration/1000, 0)
    log.Println("time purchase: ", timePurchase.Local())
}

run the code above. if success, the source above will return:

{
 "kind": "androidpublisher#productPurchase",
 "purchaseTimeMillis": "1512459492061",
 "purchaseState": 1,
 "consumptionState": 1,
 "developerPayload": "",
 "orderId": "GPA.3305-6706-7701-10158"
}

if you input wrong or invalid signature:

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "invalid",
    "message": "Invalid Value"
   }
  ],
  "code": 400,
  "message": "Invalid Value"
 }

thats all of source code to get information status of purchased token / signature. you can play around with your own signature. in the next article we will trying to explore another method like (create, update, delete) SKU, and so on.


Read more

Share Comments

Linking google developer console to google play console

Preparation: Make sure you are login or have access to both Google Play Console https://play.google.com/apps/publish (you have to access as owner) and Google Developer Console https://console.developers.google.com/apis/dashboard these accounts required for the next step and make sure your accounts are the same google/gmail account for accessing both. Required Step 1. Open Google play console - Developer Account - API Access If you don’t have any project, just Create New Project, and after new project being created the result is shown as below Next, just click the newly created Linked Project “Google Play Android Developer” it will open new tab in your browser for your Google Developer Console 2.

Read more

Share Comments

About

Hello everyone my name is M. Andi Saputra a.k.a moehandi I am software developer

Read more

Share Comments