3

私たちのアプリでは、アプリ内購入があります。クライアントは Google Play からの購入を要求し、Google Play から受け取ったすべての情報 (領収書、ナンス付き、注文など、および署名) をサーバーに送信し、検証のために C# で記述します。この投稿のコード例を使用しています

問題は、検証が失敗することです。

注: クライアントはすべてのデータを JSON 形式で送信します。それを機能させるために、Google Play から返された文字列を次のように操作します。

クライアント側で

data = data.replace("\"", "\\\"");

サーバー側で

data = data.Replace("\\", "");

編集: JSON コード例、アプリからサーバーへ

{
    "data": "{\\\"nonce\\\":3768004882572571381,\\\"orders\\\":[{\\\"notificationId\\\":\\\"android.test.purchased\\\",\\\"packageName\\\":\\\"com.company.appname\\\",\\\"orderId\\\":\\\"transactionId.android.test.purchased\\\",\\\"purchaseState\\\":0,\\\"productId\\\":\\\"android.test.purchased\\\",\\\"purchaseTime\\\":1335790350398}]}",
    "signature": "ML6ocr89x3+oT3ZKnQBEE2mNEVj6LHwt+L4I/bnhl+xCpJcjhsAIhfAumeCKwXonJV4Oh9n3Sa7SVT0F7S9XcgE2xGcf2zOZmxHB1wQcyM7fQiGj39Cyb2zuYf3T6Cs1eerDzHaO1teVQZyIhBPJf4cszD/WikSpHcF8zBTvV58FkRVwl2NR4CEvI2FrKFek8Xq2O4CsclCpS5UJorMKRAer9pcSD1BkFzynQJffbaDcRLFZ7i9vABV+GZ/xWxMGPuYYE77GYk8Q2fejgmwiZ3ysY0VjEfGRCpSA==",
    "userId": 1
}

編集済み: そのテストは失敗します。検証済みはブール変数であり、true であると想定されています

using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
            {
                RSAParameters rsaKeyInfo = new RSAParameters()
                {
                    Exponent = Convert.FromBase64String(ConfigurationManager.AppSettings["RsaKeyInfo.Exponent"]),
                    Modulus = Convert.FromBase64String(ConfigurationManager.AppSettings["RsaKeyInfo.Modulus"])
                };
                rsa.ImportParameters(rsaKeyInfo);
                verified = rsa.VerifyData(Encoding.ASCII.GetBytes(data), "SHA1", Convert.FromBase64String(signature));
            }
4

1 に答える 1

2

問題は、クライアントが Google から受け取った JSON 文字列を JSONObject に変換し、それを String() に変換したことでした。これにより、一部の json アイテムの位置が文字列内で変更され、署名用に別のバイト オブジェクトが作成され、失敗しました。

たとえば、これは Google から受け取った JSON です。

{
    "nonce": 1165723044405495300,
    "orders": [
        {
            "notificationId": "android.test.purchased",
            "orderId": "transactionId.android.test.purchased",
            "packageName": "com.company.appname",
            "productId": "android.test.purchased",
            "purchaseTime": 1335874740360,
            "purchaseState": 0
        }
    ]
}

それを JSONObject ( new JSONObject(json)) に操作してから文字列 ( json.toString()) に戻すと、たとえば、一部の json アイテムの位置が変更される可能性があります (orderId が orders 配列の 2 番目ではないことに注意してください)。

{
        "nonce": 1165723044405495300,
        "orders": [
            {
                "notificationId": "android.test.purchased",
                "packageName": "com.company.appname",
                "productId": "android.test.purchased",
                "purchaseTime": 1335874740360,
                "orderId": "transactionId.android.test.purchased",
                "purchaseState": 0
            }
        ]
    }

GetBytes(data) は同じ結果を返さないため、検証は失敗します。

解決策はもちろん、Google から受け取った json 文字列を操作しないようにすることです。構築している JSONObject に入れるだけです。jsonObj.put("データ", jsonStringFromGoogle).

于 2012-05-01T12:32:23.933 に答える