Android - 通过服务器端验证保护应用内购买

Android - protecting in app purchases with server side verification

我是 android 开发的新手,但我创建了一个应用程序并实施了应用程序内购买以从应用程序中删除广告。我只是做了一个非常基本的实现,我主要检查用户是否购买了 "no_ads" 商品,如果是,则不会显示任何广告。问题是我看到很多 "purchases" 被登录到 firebase 而游戏控制台上什么也没有,这当然意味着我的用户正在使用那些黑客应用程序。所以我的问题是,如何 protect/verify 再次购买服务器以使这些黑客应用程序无用?我已经有我的应用程序使用的服务器,因此为我实现任何服务器端代码都没有问题。如果有人能指出我的教程,那就太好了。谢谢

  1. 当用户进行应用内购买时在数据库中添加条目。
  2. 当用户打开您的应用程序时,检查购买是否有效。
  3. 如果有效则继续下一步activity否则显示错误信息。

我对减少应用内购买欺诈的小小贡献

外部服务器上的签名验证,在您的 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);

?>

备注:

  • 你应该在你的 java 代码中加密 URL,如果不是的话,可以在你解压的应用程序 apk 中通过简单的文本搜索轻松找到 URL

  • 也最好更改 php 文件名、url 参数、good/bad 对毫无意义的内容的响应。

  • verifySignatureOnServer() 应该 运行 在单独的线程中,如果不是主线程上的网络异常将被抛出。另一种方法是使用 Volley。

应用内结算库更新

使用库,待验证数据由Purchase.getOriginalJson()返回,签名由Purchase.getSignature()

希望对您有所帮助...