Подтвердить что ты не робот

Проверка на стороне сервера версии 3 для покупок в приложении Google Play

Я не могу найти прямой ответ о том, как проверить покупку биллинга в приложении на сервере, прежде чем сделать загружаемый контент доступным для пользователя.

Я использую приложение для биллинга версии 3. Я покупаю управляемые продукты, используя код, основанный на классе IabHelper, из кода примера TrivialDrive. Все в порядке и денди, и покупка успешно завершена, я получаю полный объект Purchase и следующие исходные данные JSON:

{
    "orderId":"12999763169054705758.1364365967744519",
    "packageName":"my package name",
    "productId":"77",
    "purchaseTime":1366217534000,
    "purchaseState":0,
    "purchaseToken":"utfwimslnrrwvglktizikdcd.AO-J1OwZ4l5oXz_3d2SAWAAUgFE3QErKoyIX8WuSEnBW26ntsyDmlLgoUd5lshqIY2p2LnlV4tpH4NITB4mJMX98sCtZizH7wGf6Izw3tfW_GflJDKFyb-g"
}

Как я понимаю, мне нужно передать purchaseToken и что-то, что я вижу, называется подписью на сервере. Затем сервер использует закрытый ключ для подтверждения покупки. Это верно? Если да, то откуда я могу получить подпись и действительно ли нет достойной документации относительно проверки покупки на стороне сервера?

4b9b3361

Ответ 1

where do I get the signature from ?

Взгляните на официальные документы,

В нем говорится, что внутри вашего onActivityResult() вы можете получить следующие данные, как показано в примере,

    @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
   if (requestCode == 1001) {           
      int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
      String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
      String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");//this is the signature which you want

      if (resultCode == RESULT_OK) {
         try {
            JSONObject jo = new JSONObject(purchaseData);//this is the JSONObject which you have included in Your Question right now
            String sku = jo.getString("productId");
            String purchaseToken = jo.getString("purchaseToken");
           //you need to send sku and purchaseToken to server for verification
          }
          catch (JSONException e) {
             alert("Failed to parse purchase data.");
             e.printStackTrace();
          }
      }
   }
}

Для проверки на сервере, ознакомьтесь с официальными документами

Как упоминалось ранее, клиентское приложение отправит sku и purchaseToken на сервер API. Сервер должен будет получить эти значения и должен будет выполнить проверку с помощью android publish api для проверки покупки:

Сервер может вызывать следующий запрос GET, добавляя необходимые параметры:

https://www.googleapis.com/androidpublisher/v2/applications/ packageName/purchase/products/productId/tokens/token

Вот,
packageName = packageName клиентского приложения
productId = sku, полученное из клиентского приложения
token = purchaseToken, полученное от клиентского приложения

Это приведет к JSONObject как упомянутый формат:

{
  "kind": "androidpublisher#productPurchase",
  "purchaseTimeMillis": long,
  "purchaseState": integer,
  "consumptionState": integer,
  "developerPayload": string,
  "orderId": string,
  "purchaseType": integer
}

здесь, purchaseState = 0 означает действительную покупку

Надеюсь, это будет полезно!

Ответ 2

Мой небольшой вклад в снижение количества мошенничества при покупке приложений

Проверка подписи на внешнем сервере на вашем Android-коде:

verifySignatureOnServer()

  private boolean verifySignatureOnServer(String data, String signature) {
        String retFromServer = "";
        URL url;
        HttpsURLConnection urlConnection = null;
        try {
            String urlStr = "https://www.example.com/verify.php?data=" + URLEncoder.encode(data, "UTF-8") + "&signature=" + URLEncoder.encode(signature, "UTF-8");

            url = new URL(urlStr);
            urlConnection = (HttpsURLConnection) url.openConnection();
            InputStream in = urlConnection.getInputStream();
            InputStreamReader inRead = new InputStreamReader(in);
            retFromServer = convertStreamToString(inRead);

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
        }

        return retFromServer.equals("good");
    }

convertStreamToString()

 private static String convertStreamToString(java.io.InputStreamReader is) {
        java.util.Scanner s = new java.util.Scanner(is).useDelimiter("\\A");
        return s.hasNext() ? s.next() : "";
    }

verify.php в корневом каталоге веб-хостинга

<?php
// get data param
$data = $_GET['data'];

// get signature param
$signature = $_GET['signature'];

// get key
$key_64 = ".... put here the base64 encoded pub key from google play console , all in one row !! ....";



$key =  "-----BEGIN PUBLIC KEY-----\n".
        chunk_split($key_64, 64,"\n").
       '-----END PUBLIC KEY-----';   
//using PHP to create an RSA key
$key = openssl_get_publickey($key);


// state whether signature is okay or not
$ok = openssl_verify($data, base64_decode($signature), $key, OPENSSL_ALGO_SHA1);
if ($ok == 1) {
    echo "good";
} elseif ($ok == 0) {
    echo "bad";
} else {
    die ("fault, error checking signature");
}

// free the key from memory
openssl_free_key($key);

?>

ЗАМЕТКИ:

  • Вы должны зашифровать URL-адрес в вашем Java-коде, если URL-адрес не может быть легко найден с помощью простого текстового поиска в вашем распакованном приложении apk

  • Также лучше изменить имя файла php, аргументы url, хорошие/плохие ответы на что-то без смысла.

  • verifySignatureOnServer() следует запускать в отдельном потоке, если не будет выбрана сеть с исключением основного потока.

Надеюсь, это поможет...

Ответ 3

Это слишком старый вопрос, но я надеюсь, что мой ответ может помочь кому-то.

Вы должны проверить подпись на стороне клиента, а затем вам нужно передать purchaseToken на серверную сторону, а затем сервер свяжется с сервером Google и получить всю необходимую информацию о покупке, например purchaseState и consumptionState.

https://developers.google.com/android-publisher/api-ref/purchases/products

Ответ 4

Это очень старый вопрос, но я думаю, что он все еще актуален.

Мой маленький вклад. Объект покупки расширен на один новый параметр "подтвержден", и теперь он выглядит так:

{
  "orderId":"12999763169054705758.1364365967744519",
  "packageName":"my package name",
  "productId":"77",
  "purchaseTime":1366217534000,
  "purchaseState":0,
  "purchaseToken":"utfwimslnrrwvglktizikdcd.AO-J1OwZ4l5oXz_3d2SAWAAUgFE3QErKoyIX8WuSEnBW26ntsyDmlLgoUd5lshqIY2p2LnlV4tpH4NITB4mJMX98sCtZizH7wGf6Izw3tfW_GflJDKFyb-g",
  "acknowledged":true
}

Поэтому будьте осторожны при проверке подписи, чтобы добавить этот дополнительный параметр.