Android studio Android Studio应用内计费如何验证设备上的购买?

Android studio Android Studio应用内计费如何验证设备上的购买?,android-studio,in-app-purchase,signature,verification,Android Studio,In App Purchase,Signature,Verification,我在安卓工作室工作了很短时间,这是我的第一个项目。我不知道很多要点,我为我复杂的代码道歉。我的应用程序中只有1个消费品,给用户20条生命。经过长期努力,我成功地将应用程序内购买添加到我的应用程序中。在我的应用程序中,我可以用自己的产品ID使用谷歌测试卡进行购买。到目前为止,我没有遇到任何问题。由于我没有服务器,我必须在设备上进行购买验证。我在一个活动中编写了所有购买和验证代码。我想这听起来可能有点傻,但我不知道在哪里确认购买。即使签名不正确,我的应用程序也会接受验证。我在代码中遗漏了什么 pub

我在安卓工作室工作了很短时间,这是我的第一个项目。我不知道很多要点,我为我复杂的代码道歉。我的应用程序中只有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();


 }

 }
公共类MagazaActivity扩展了AppCompatActivity{
按钮baslik,购买按钮;
坎克;
int can;
私人计费客户mBillingClient;
private final List mpources=new ArrayList();
私有静态最终字符串BASE_64_ENCODED_PUBLIC_KEY=“XXXXX”;
私有静态最终字符串TAG=“IABUtil/Security”;
私有静态最终字符串密钥\u工厂\u算法=“RSA”;
私有静态最终字符串签名\u算法=“SHA1withRSA”;
弦坎菲亚特;
mBillingClient=BillingClient.newBuilder(magazactivity.this)。
setListener(新的PurchasesUpdatedListener(){
@凌驾
购买时公共无效(内部响应代码,
@可为空的列表(购买){
if(responseCode==BillingClient.BillingResponse.OK
&&购买!=空){
用于(最终采购:采购){
ConsumerResponseListener侦听器=新建
消费主义者(){
@凌驾
公共空间
onConsumerResponse(@BillingClient.BillingResponse int-responseCode,字符串
outToken){
如果(响应代码==
BillingClient.BillingResponse.OK){
手工采购(采购);
}
}
};
mBillingClient.ConsumeAncy(purchase.getPurchaseToken(),侦听器);
}
}else if(responseCode==
BillingClient.BillingResponse.USER\u已取消){
BillingCancelled();
}  
否则{
AlertDialog.builder2=新建
AlertDialog.Builder(MagazaActivity.this,R.style.AlertDialogCustom);
builder2.setMessage(“计费系统”sİnvalid);
builder2.setCancelable(true);
平整机厂=
Layoutiner.from(MagazaActivity.this);
最终视图=工厂充气(R.layout.sample4,
无效);
builder2.setView(视图);
builder2.setPositiveButton(
“好的”,
新建DialogInterface.OnClickListener(){
公共void onClick(对话框接口对话框,
int id){
dialog.cancel();
}
});
AlertDialog alert11=builder2.create();
alert11.show();
}
}
}).
build();
buy_button.setOnClickListener(新视图.OnClickListener(){
@凌驾
公共void onClick(视图v){
mBillingClient.startConnection(新的BillingClientStateListener()
{
@凌驾
公共空间
onBillingSetupFinished(@BillingClient.BillingResponse int
billingResponseCode){
如果(billingResponseCode==
BillingClient.BillingResponse.OK){
最终列表skuList=新的ArrayList();
skuList。添加(“XXX”);
SkuDetailsParams SkuDetailsParams=
sku.sparams.newBuilder()
.setSkusList(skuList).setType(BillingClient.SkuType.INAPP).build();
mBillingClient.queryskuedetailsasync(skuedetailsparams,
新SkuDetailsResponseListener(){
@凌驾
公共无效详细信息响应(int)
响应代码,
列表(详细信息列表){
BillingFlowParams flowParams=
BillingFlowParams.newBuilder()
.setsku详细信息(skuDetailsList.get(0))
.build();
int billingResponseCode=
mBillingClient.launchBillingFlow(MagazaActivity.this,flowParams);
如果(billingResponseCode==
BillingClient.BillingResponse.OK){
对于(SKU详细信息)SKU详细信息:
SKU(详细信息列表){
字符串sku=
skuDetails.getSku();
字符串价格=
skuedetails.getPrice();
如果(“XXX”。等于(sku)){
canfiyat=价格;
}
}
}
}
});
}
}
@凌驾
公共无效onBillingServiceDisconnected(){
AlertDialog.Builder=新建
AlertDialog.Builder(MagazaActivity.this);
builder.setMessage(“连接错误”)
.setCancelable(错误)
.setPositiveButton(“重试”,新建
DialogInterface.OnClickListener(){
公共空隙(直径