Нет DEVELOPER_PAYLOAD при использовании In App Billing в Android

мая
28
2012

Проблема следующая: при тестировании оплаты с использованием in-app billing в Android не приходит свойство DEVELOPER_PAYLOAD от Google-маркета, хоть оно и установлено в REQUEST_PURCHASE запросе.

Свойство DEVELOPER_PAYLOAD необходимо для того чтобы "связать" отправляемый запрос с ответом от маркета так как общение между программой и маркетом происходит асинхронно. Для это в запросе REQUEST_PURCHASE разработчик должен установить свойство DEVELOPER_PAYLOAD, которое вернется вместе с запросом GET_PURCHASE_INFORMATION.

Это происходит при использовании следующих идентификаторов для тестирования:

При использовании в реальных условиях без эмуляции таких проблем не возникает. Поэтому либо искуственно установите это свойство, либо проводите тестирование с живими банковскими картами. Если Вы владеете аккаунтом продавца Google Play, то транзакции можно отменять.

Рассмотрим пример Dungeons от Google, в котором описана работа с In-app billing. В первую очередь, обратите внимание на следующие строки кода в классе Dungeons, именно так присваиваются упомянутые выше идентификаторы:


new CatalogEntry("android.test.purchased", R.string.android_test_purchased,
		Managed.UNMANAGED),
new CatalogEntry("android.test.canceled", R.string.android_test_canceled,
		Managed.UNMANAGED),
new CatalogEntry("android.test.refunded", R.string.android_test_refunded,
		Managed.UNMANAGED),
new CatalogEntry("android.test.item_unavailable", R.string.android_test_item_unavailable,
		Managed.UNMANAGED),

Также в примере есть подкласс RequestPurchase в классе BillingService, с помощью которого происходит отсылка свойства DEVELOPER_PAYLOAD:


class RequestPurchase extends BillingRequest {
	public final String mProductId;
	public final String mDeveloperPayload;

	public RequestPurchase(String itemId) {
		this(itemId, null);
	}

	public RequestPurchase(String itemId, String developerPayload) {
		// This object is never created as a side effect of starting this
		// service so we pass -1 as the startId to indicate that we should
		// not stop this service after executing this request.
		super(-1);
		mProductId = itemId;
		mDeveloperPayload = developerPayload;
	}

	@Override
	protected long run() throws RemoteException {
		Bundle request = makeRequestBundle("REQUEST_PURCHASE");
		request.putString(Consts.BILLING_REQUEST_ITEM_ID, mProductId);
		// Note that the developer payload is optional.
		if (mDeveloperPayload != null) {
			request.putString(Consts.BILLING_REQUEST_DEVELOPER_PAYLOAD, mDeveloperPayload);
		}
		Bundle response = mService.sendBillingRequest(request);
		PendingIntent pendingIntent
				= response.getParcelable(Consts.BILLING_RESPONSE_PURCHASE_INTENT);
		if (pendingIntent == null) {
			Log.e(TAG, "Error with requestPurchase");
			return Consts.BILLING_RESPONSE_INVALID_REQUEST_ID;
		}

		Intent intent = new Intent();
		ResponseHandler.buyPageIntentResponse(pendingIntent, intent);
		return response.getLong(Consts.BILLING_RESPONSE_REQUEST_ID,
				Consts.BILLING_RESPONSE_INVALID_REQUEST_ID);
	}

	@Override
	protected void responseCodeReceived(ResponseCode responseCode) {
		ResponseHandler.responseCodeReceived(BillingService.this, this, responseCode);
	}
}

Обратите внимание на следующие строки кода:


if (mDeveloperPayload != null) {
	request.putString(Consts.BILLING_REQUEST_DEVELOPER_PAYLOAD, mDeveloperPayload);
}

Убедитесь, что в переменную request добавляется свойство DEVELOPER_PAYLOAD, то есть, вызывается конструктор с двумя строковыми параметрами и свойство mDeveloperPayload нигде не переписывается.

Завершающий этап - получение DEVELOPER_PAYLOAD в ответе от сервера. Вся обработка находится в методе onPurchaseStateChange() класса Dungeons:


@Override
public void onPurchaseStateChange(PurchaseState purchaseState, String itemId,
		int quantity, long purchaseTime, String developerPayload) {
	if (Consts.DEBUG) {
		Log.i(TAG, "onPurchaseStateChange() itemId: " + itemId + " " + purchaseState);
	}

	if (developerPayload == null) {
		logProductActivity(itemId, purchaseState.toString());
	} else {
		logProductActivity(itemId, purchaseState + "\n\t" + developerPayload);
	}

	if (purchaseState == PurchaseState.PURCHASED) {
		mOwnedItems.add(itemId);
	}
	mCatalogAdapter.setOwnedItems(mOwnedItems);
	mOwnedItemsCursor.requery();
}

На этом всё, спасибо за внимание! :)

Напишите первое сообщение!

Вы должны войти под своим аккаунтом чтобы оставлять комментарии