Vérification côté serveur de L'achat de la version 3 de la facturation In-app de Google Play

je suis incapable de trouver une réponse claire quant à la façon dont je vérifie un achat de facturation In-app sur le serveur avant de rendre le contenu téléchargeable disponible à l'utilisateur.

j'utilise en application de facturation de la version 3. J'achète des produits gérés en utilisant du code basé sur la classe IabHelper du code échantillon TrivialDrive. Tout est parfait et épatant et l'achat est terminé avec succès, je récupère un objet D'achat complet et les données originales JSON suivantes:

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

d'après ce que j'ai compris, je dois transmettre au serveur le message d'achat et quelque chose que je vois appelé une signature. Le serveur utilise ensuite une clé privée pour vérifier l'achat. Est-ce correct? Si oui, d'où puis-je obtenir la signature et n'y a-t-il vraiment pas de documentation décente concernant la vérification côté serveur d'un achat?

28
demandé sur britzl 2013-04-17 22:12:31

3 réponses

where do I get the signature from ?

regarder officiel docs ,

il est dit que dans votre méthode onActivityResult() vous pouvez obtenir les données suivantes comme indiqué dans l'exemple,

    @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();
          }
      }
   }
}

Pour la vérification à la fin du serveur, Jetez un oeil à documents officiels

comme mentionné précédemment, l'application client enverra sku et purchaseToken à l'API du serveur. Serveur doivent recevoir ces valeurs et devront effectuer vérifier avec android publier api pour vérifier l'achat:

Serveur peut appeler suivant GET par l'ajout de paramètres nécessaires:

https://www.googleapis.com/androidpublisher/v2/applications/ "1519140920 nomdupaquet 1519150920" /achats/produits/ productId /jetons/ jeton

ici,

packageName = packageName de l'application client

productId = sku reçu du client app

token = purchaseToken reçu du client app

il en résultera une réponse JSONObject tel que mentionné format:

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

ici, purchaseState = 0 signifie valid purchase

j'espère que ce sera utile !!

13
répondu Mehul Joisar 2018-01-17 14:36:08

Ma petite contribution pour réduire la fraude dans les achats " in-app

vérification de Signature sur un serveur externe, sur votre code 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() : "";
    }

vérifier.php sur le répertoire racine de l'hébergement web

<?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);

?>

NOTES:

  • vous devez chiffrer L'URL dans votre code java, sinon L'URL peut être trouvé facilement avec une recherche de texte simple dans votre application décompressée apk

  • aussi mieux de changer le nom de fichier php, les arguments d'url, les bonnes/mauvaises réponses à quelque chose sans sens.

  • verifySignatureOnServer () doit être exécuté en un thread séparé si ce n'est pas un network sur l'exception du thread principal sera lancé.

j'Espère que ça aidera ...

3
répondu Lluis Felisart 2018-02-06 14:22:43

c'est une question trop ancienne, mais j'espère que ma réponse pourra aider quelqu'un.

vous devez valider la signature sur côté client , puis vous devez passer purchaseToken à côté serveur , puis le serveur contactera le serveur de Google et obtenir toutes les informations nécessaires sur l'achat, tels que purchaseState et consumptionState .

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

2
répondu Oleksii K. 2016-03-30 10:14:53