如何确认android计费通知?
我正试图通过示例应用程序实现应用内购买。 我正在使用web服务器验证购买,并在那里进行验证。问题在于,无论交易结果如何,购买状态更改通知从未停止。 也就是说,在我关闭应用程序之前,我每分钟都会收到购买状态更改通知,无论我的购买成功、失败或被用户取消 下面是我正在使用的一些示例代码:如何确认android计费通知?,android,in-app-purchase,in-app-billing,Android,In App Purchase,In App Billing,我正试图通过示例应用程序实现应用内购买。 我正在使用web服务器验证购买,并在那里进行验证。问题在于,无论交易结果如何,购买状态更改通知从未停止。 也就是说,在我关闭应用程序之前,我每分钟都会收到购买状态更改通知,无论我的购买成功、失败或被用户取消 下面是我正在使用的一些示例代码: public class BillingReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, I
public class BillingReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.i(TAG, "Received action: " + action);
if (ACTION_PURCHASE_STATE_CHANGED.equals(action)) {
String signedData = intent.getStringExtra(INAPP_SIGNED_DATA);
String signature = intent.getStringExtra(INAPP_SIGNATURE);
purchaseStateChanged(context, signedData, signature);
} else if (ACTION_NOTIFY.equals(action)) {
String notifyId = intent.getStringExtra(NOTIFICATION_ID);
notify(context, notifyId);
} else if (ACTION_RESPONSE_CODE.equals(action)) {
long requestId = intent.getLongExtra(INAPP_REQUEST_ID, -1);
int responseCodeIndex = intent.getIntExtra(INAPP_RESPONSE_CODE, C.ResponseCode.RESULT_ERROR.ordinal());
checkResponseCode(context, requestId, responseCodeIndex);
} else {
Log.e(TAG, "unexpected action: " + action);
}
}
private void purchaseStateChanged(Context context, String signedData, String signature) {
Log.i(TAG, "purchaseStateChanged got signedData: " + signedData);
Log.i(TAG, "purchaseStateChanged got signature: " + signature);
BillingHelper.verifyPurchase(signedData, signature);
}
}
BillingHelper:
ArrayList<VerifiedPurchase> purchases = BillingSecurity.verifyPurchase(mApp, signedData, signature);
if(purchases != null && purchases.size() > 0)
{
latestPurchase = purchases.get(0);
confirmTransaction(new String[]{latestPurchase.notificationId});
}
if(mCompletedHandler != null){
mCompletedHandler.sendEmptyMessage(0);
} else {
Log.e(TAG, "verifyPurchase error. Handler not instantiated. Have you called setCompletedHandler()?");
}
ArrayList purchases=BillingSecurity.VerifyPurchases(mApp,signedData,signature);
if(purchases!=null&&purchases.size()>0)
{
latestPurchase=purchases.get(0);
confirmTransaction(新字符串[]{latestPurchase.notificationId});
}
如果(mCompletedHandler!=null){
McCompletedHandler.sendEmptyMessage(0);
}否则{
Log.e(标记“verifyPurchase error.Handler未实例化。是否调用了setCompletedHandler()?”;
}
计费安全:
public static ArrayList<VerifiedPurchase> verifyPurchase(Context context, String signedData, String signature) {
if (signedData == null) {
Log.e(TAG, "data is null");
}
Log.i(TAG, "signedData: " + signedData);
boolean verified = false;
if (!TextUtils.isEmpty(signature)) {
try
{
boolean result = Server.verifyAndroidPurchase( signedData, signature);
if(!result)
{
Log.d("VERIFY RESULT", "verification failed");
return null;
}
verified = true;
}
}
JSONObject jObject;
JSONArray jTransactionsArray = null;
int numTransactions = 0;
long nonce = 0L;
try {
jObject = new JSONObject(signedData);
// The nonce might be null if the user backed out of the buy page.
nonce = jObject.optLong("nonce");
jTransactionsArray = jObject.optJSONArray("orders");
if (jTransactionsArray != null) {
numTransactions = jTransactionsArray.length();
}
} catch (JSONException e) {
}
if (!BillingSecurity.isNonceKnown(nonce)) {
Log.w(TAG, "Nonce not found: " + nonce);
return null;
}
ArrayList<VerifiedPurchase> purchases = new ArrayList<VerifiedPurchase>();
try {
for (int i = 0; i < numTransactions; i++) {
JSONObject jElement = jTransactionsArray.getJSONObject(i);
int response = jElement.getInt("purchaseState");
PurchaseState purchaseState = PurchaseState.valueOf(response);
String productId = jElement.getString("productId");
String packageName = jElement.getString("packageName");
long purchaseTime = jElement.getLong("purchaseTime");
String orderId = jElement.optString("orderId", "");
String notifyId = null;
if (jElement.has("notificationId")) {
notifyId = jElement.getString("notificationId");
}
String developerPayload = jElement.optString("developerPayload", null);
// If the purchase state is PURCHASED, then we require a
// verified nonce.
if (purchaseState == PurchaseState.PURCHASED && !verified) {
continue;
}
purchases.add(new VerifiedPurchase(purchaseState, notifyId, productId, orderId, purchaseTime, developerPayload));
}
} catch (JSONException e) {
Log.e(TAG, "JSON exception: ", e);
return null;
}
removeNonce(nonce);
return purchases;
}
publicstaticarraylistverifypurchase(上下文上下文、字符串签名数据、字符串签名){
如果(signedData==null){
Log.e(标记“数据为空”);
}
Log.i(标记“signedData:+signedData”);
布尔验证=假;
如果(!TextUtils.isEmpty(签名)){
尝试
{
布尔结果=Server.verifyandridpurchase(signedData,signature);
如果(!结果)
{
Log.d(“验证结果”、“验证失败”);
返回null;
}
验证=真实;
}
}
JSONObject jObject;
JSONArray jTransactionsArray=null;
int numTransactions=0;
长nonce=0L;
试一试{
jObject=新的JSONObject(signedData);
//如果用户退出购买页面,nonce可能为null。
nonce=jObject.optLong(“nonce”);
jTransactionsArray=jObject.optJSONArray(“订单”);
if(jTransactionsArray!=null){
numTransactions=jTransactionsArray.length();
}
}捕获(JSONException e){
}
如果(!BillingSecurity.isNonceKnown(nonce)){
Log.w(标记“未找到当前值:”+Nonce);
返回null;
}
ArrayList购买=新建ArrayList();
试一试{
for(int i=0;i
我假设您没有在应用程序中包含公钥,因为您正在远程服务器上进行验证。在这种情况下,行BillingSecurity.verifyPurchase(mApp,signedData,signature)代码>
将返回一个空数组列表。那你就没什么可确认的了。换句话说,你永远不会确认任何事情,谷歌会继续在APP中发送通知消息给你 确保当Intent.getAction为Const.ACTION\u CONFIRM\u通知(“com.android.vending.billing.CONFIRM\u通知”)时,您的BillingService.handleCommand(Intent Intent,int startId)发送并运行ConfirmNotification请求
您可以通过触发确认通知意图来启动BillingService:
public void confirmPurchases( int intentId, String[] notificationIds ) {
Intent intent = new Intent( Consts.ACTION_CONFIRM_NOTIFICATION );
intent.setClass( context, BillingService.class );
intent.putExtra(Consts.NOTIFICATION_ID, notificationIds);
context.startService( intent );
}