Android Studio In App Billing Как проверить покупку на устройстве? - PullRequest
0 голосов
/ 09 февраля 2019

Я недолго работал с Android Studio, и это мой первый проект.Я не знаю много пунктов, и я прошу прощения за мой сложный код.В моем приложении всего 1 расходный продукт, который дает пользователю 20 жизней.В результате долгих усилий мне удалось добавить в приложение покупку в приложении.В моем приложении я мог совершать покупки с помощью тестовых карт Google с собственным идентификатором продукта.У меня не было никаких проблем до здесь.Поскольку у меня нет сервера, я должен выполнить проверку покупки на устройстве.Я написал все коды покупки и проверки в действии.Я думаю, это может звучать немного глупо, но я не знаю, где сделать подтверждение покупки.Моя заявка принимает подтверждение, даже если это неверная подпись.Какой смысл я пропустил в своих кодах?

public class MagazaActivity extends AppCompatActivity {

Button baslik, buy_button;
Can hak;
int can;
private BillingClient mBillingClient;
private final List<Purchase> mPurchases = new ArrayList<>();
private static final String BASE_64_ENCODED_PUBLIC_KEY = "XXXXX";
private static final String TAG = "IABUtil/Security";
private static final String KEY_FACTORY_ALGORITHM = "RSA";
private static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
String canfiyat;


        mBillingClient =BillingClient.newBuilder(MagazaActivity.this).

        setListener(new PurchasesUpdatedListener() {
            @Override
            public void onPurchasesUpdated ( int responseCode,
            @Nullable List<Purchase> purchases){

                if (responseCode == BillingClient.BillingResponse.OK
                        && purchases != null) {

                    for (final Purchase purchase : purchases) {

                        ConsumeResponseListener listener = new 
 ConsumeResponseListener() {
                            @Override
                            public void 
onConsumeResponse(@BillingClient.BillingResponse int responseCode, String 
outToken) {
                                if (responseCode == 
BillingClient.BillingResponse.OK) {

                                    handlePurchase(purchase);

                                }
                            }

                        };

mBillingClient.consumeAsync(purchase.getPurchaseToken(), listener);
                    }


                } else if (responseCode == 
BillingClient.BillingResponse.USER_CANCELED) {

                    billingCanceled();

                }  

                else {

                    AlertDialog.Builder builder2 = new 
  AlertDialog.Builder(MagazaActivity.this, R.style.AlertDialogCustom);
                    builder2.setMessage("Billing System İs İnvalid");
                    builder2.setCancelable(true);
                    LayoutInflater factory = 
LayoutInflater.from(MagazaActivity.this);
                    final View view = factory.inflate(R.layout.sample4, 
null);
                    builder2.setView(view);


                    builder2.setPositiveButton(
                            "OK",
                            new DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, 
int id) {


                                    dialog.cancel();
                                }
                            });

                    AlertDialog alert11 = builder2.create();
                    alert11.show();
                }
            }
        }).

        build();


    buy_button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

           mBillingClient.startConnection(new BillingClientStateListener() 
{
                @Override
                public void 
 onBillingSetupFinished(@BillingClient.BillingResponse int 
billingResponseCode) {
                    if (billingResponseCode == 
BillingClient.BillingResponse.OK) {

                        final List<String> skuList = new ArrayList<>();
                        skuList.add("XXX");
                        SkuDetailsParams skuDetailsParams = 
SkuDetailsParams.newBuilder()

.setSkusList(skuList).setType(BillingClient.SkuType.INAPP).build();

mBillingClient.querySkuDetailsAsync(skuDetailsParams,
                                new SkuDetailsResponseListener() {
                                    @Override
                                    public void onSkuDetailsResponse(int 
responseCode,

List<SkuDetails> skuDetailsList) {

                                        BillingFlowParams flowParams = 
BillingFlowParams.newBuilder()

.setSkuDetails(skuDetailsList.get(0))
                                                .build();
                                        int billingResponseCode = 
mBillingClient.launchBillingFlow(MagazaActivity.this, flowParams);
                                        if (billingResponseCode == 
BillingClient.BillingResponse.OK) {

                                            for (SkuDetails skuDetails : 
skuDetailsList) {
                                                String sku = 
skuDetails.getSku();
                                                String price = 
skuDetails.getPrice();
                                                if ("XXX".equals(sku)) {
                                                    canfiyat = price;
                                                }
                                            }


                                        }
                                    }
                                });

                    }
                }

                @Override
                public void onBillingServiceDisconnected() {
                    AlertDialog.Builder builder = new 
AlertDialog.Builder(MagazaActivity.this);
                    builder.setMessage("Connection Error")
                            .setCancelable(false)
                            .setPositiveButton("Retry", new 
 DialogInterface.OnClickListener() {
                                public void onClick(DialogInterface dialog, 
int id) {



                                    dialog.cancel();
                                }

                            });

                    AlertDialog alert = builder.create();
                    alert.show();

                }
            });

        }

    });
}

@Override
public void onBackPressed() {

    Intent intentLayout8 = new Intent(MagazaActivity.this, 
MainActivity.class);
    startActivity(intentLayout8);
    MagazaActivity.this.finish();

}


private void billingCanceled() {
    AlertDialog.Builder builder = new 
AlertDialog.Builder(MagazaActivity.this);
    builder.setMessage("Purchase Canceled")
            .setCancelable(false)
            .setPositiveButton("OK", new DialogInterface.OnClickListener() 
{
                public void onClick(DialogInterface dialog, int id) {

                    dialog.cancel();
                }

            });

    AlertDialog alert = builder.create();
    alert.show();
}


public static PublicKey generatePublicKey(String encodedPublicKey) {
    try {
        byte[] decodedKey = Base64.decode(encodedPublicKey, 
Base64.DEFAULT);
        KeyFactory keyFactory = 
  KeyFactory.getInstance(KEY_FACTORY_ALGORITHM);
        return keyFactory.generatePublic(new 
X509EncodedKeySpec(decodedKey));
    } catch (NoSuchAlgorithmException e) {
        throw new RuntimeException(e);
    } catch (InvalidKeySpecException e) {
        Log.e(TAG, "Invalid key specification.");
        throw new IllegalArgumentException(e);
    }
 }

public static boolean verifyPurchase(String base64PublicKey, String 
signedData, String signature) {
    if (TextUtils.isEmpty(signedData) || TextUtils.isEmpty(base64PublicKey) 
||
            TextUtils.isEmpty(signature)) {
        Log.e("HATA", "Purchase verification failed");
        return false;

    }

    PublicKey key = MagazaActivity.generatePublicKey(base64PublicKey);
    return MagazaActivity.verify(key, signedData, signature);

 }


public static boolean verify(PublicKey publicKey, String signedData, String 
signature) {
    byte[] signatureBytes;
    try {
        signatureBytes = Base64.decode(signature, Base64.DEFAULT);
    } catch (IllegalArgumentException e) {
        Log.e(TAG, "Base64 decoding failed.");
        return false;
    }
    try {
        Signature sig = Signature.getInstance(SIGNATURE_ALGORITHM);
        sig.initVerify(publicKey);
        sig.update(signedData.getBytes());
        if (!sig.verify(signatureBytes)) {
            Log.e(TAG, "Signature verification failed.");
            return false;
        }
        return true;
    } catch (NoSuchAlgorithmException e) {
        Log.e(TAG, "NoSuchAlgorithmException.");
    } catch (InvalidKeyException e) {
        Log.e(TAG, "Invalid key specification.");
    } catch (SignatureException e) {
        Log.e(TAG, "Signature exception.");
    }
    return false;
 }

private boolean verifyValidSignature(String signedData, String signature) {
    try {
        return MagazaActivity.verifyPurchase(BASE_64_ENCODED_PUBLIC_KEY, 
signedData, signature);

    } catch (Exception e) {
        Log.e(TAG, "Got an exception trying to validate a purchase: " + e);
        return false;

    }
 }


public void handlePurchase(Purchase purchase) {
    if (!verifyValidSignature(purchase.getOriginalJson(), 
purchase.getSignature())) {
        Log.i("Warning", "Purchase: " + purchase + "; signature 
failure...");

    return;
    }

    Log.d("MESAJ", "Got a verified purchase: " + purchase);

    hak.cancan = hak.cancan + 20;

    SharedPreferences pref = 
getApplicationContext().getSharedPreferences("MyPref", MODE_PRIVATE);
    SharedPreferences.Editor editor = pref.edit();
    editor.putInt("kalp", hak.cancan);
    editor.apply();

    mPurchases.add(purchase);
 }


 public void onResume() {
    super.onResume();


 }

 }
...