首页 > 解决方案 > Android Studio In App Billing 如何在设备上验证购买?

问题描述

我使用 Android Studio 已经有一段时间了,这是我的第一个项目。我不知道很多点,我为我的复杂代码道歉。我的应用程序中只有 1 个消耗品,并为用户提供 20 条生命。经过长期努力,我成功地将应用内购买添加到我的应用程序中。在我的应用程序中,我可以使用带有我自己的产品 ID 的谷歌测试卡进行购买。到目前为止,我没有任何问题。由于我没有服务器,所以我必须在设备上进行购买验证。我在活动中编写了所有购买和验证码。我认为这听起来可能有点傻,但我不知道在哪里确认购买。即使签名不正确,我的应用程序也接受验证。我在代码中遗漏了什么?

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


 }

 }

标签: android-studioin-app-purchasesignatureverification

解决方案


推荐阅读