В связи с деловыми потребностями компании требуется вход в систему Google и оплата. Платеж Google делится на два типа: подписка и покупка в приложении. Автор использует покупку в приложении. Здесь записывается весь процесс оплаты и проверки платежа Google.
Адрес доступа к платежной службе Google
def billing_version = "4.0.0"
implementation "com.android.billingclient:billing-ktx:$billing_version"
процесс:
На данный момент работа по подготовке к платежу Google завершена, и платеж можно инициировать ниже.
Как насчет того, чтобы разместить код ниже?
step1
Инициализируйте и подключитесь к сервисам Google
// метод инициализации
public synchronized void init(Activity mActivity){
//Создаем Биллинг Клиент Напротив, запрос Потребление Этот объект будет использоваться для оплаты
this.mBillingClient = BillingClient.newBuilder(mActivity)
.setListener(new PurchasesUpdatedListener() {//Установить обратный вызов платежа. На самом деле это обратный вызов при изменении статуса продукта.
@Override
public void onPurchasesUpdated(BillingResult billingResult, @Nullable List<Purchase> purchases) {
LogUtils.d("call onPurchasesUpdated");
if (billingResult.getResponseCode() == BillingResponseCode.OK && purchases != null) {//Платеж успешен
for (Purchase purchase : purchases) {
if(purchase == null || purchase.getPurchaseState() != Purchase.PurchaseState.PURCHASED) continue;
OrderManager.getInstance().paySuccess(purchase);
//Сообщаем серверу, что платеж прошел успешно, Проверка на стороне сервераназад,потребительские товары
}
//Оплата синхронного обратного вызова клиента TODO успешна
} else if (billingResult.getResponseCode() == BillingResponseCode.USER_CANCELED) {//Отмена платежа
} else {//Оплата не удалась
}
}
})
.enablePendingPurchases()
.build();
//Ссылка на Гугл play
this.connectBillPay();
}
private void connectBillPay(){
mBillingClient.startConnection(new BillConnectListener());
}
class BillConnectListener implements BillingClientStateListener {
@Override
public void onBillingSetupFinished(BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
//Ссылка на Гугл сервис
payEnable = true;
queryPurchases();
}
}
@Override
public void onBillingServiceDisconnected() {
//Не связано с сервисами Google
payEnable = false;
connectBillPay();
}
}
setp2
Запросите платные продукты и уведомите сервер перед их использованием (при оплате Google неизрасходованные продукты нельзя приобрести снова)
private void queryPurchases(){
PurchasesResponseListener mPurchasesResponseListener = new PurchasesResponseListener() {
@Override
public void onQueryPurchasesResponse(@NonNull BillingResult billingResult, @NonNull List<Purchase> purchasesResult) {
if(billingResult.getResponseCode() != BillingClient.BillingResponseCode.OK || purchasesResult == null) return;
for (Purchase purchase : purchasesResult) {
if(purchase == null || purchase.getPurchaseState() != Purchase.PurchaseState.PURCHASED) continue;
OrderManager.getInstance().paySuccess(purchase);
//Обрабатываем оплаченные здесь заказы и уведомляем сервер о необходимости проверки
}
}
};
mBillingClient.queryPurchasesAsync(BillingClient.SkuType.INAPP, mPurchasesResponseListener);
}
setp3
Инициировать платеж
/**
*
* @param cpOrder Ваш собственный номер заказа или идентификатор пользователя используется для связи с соответствующим пользователем и используется при распространении реквизита.
* @param productId Идентификатор продукта фоновой конфигурации Google
*/
public void pay(final String cpOrder, final String productId) {
if(mBillingClient == null || wrActivity.get() == null || !payEnable){
//Оплата обратного вызова синхронизации клиента TODO не удалась, поскольку платежную службу, связанную с Google, или Google невозможно использовать.
return;
}
//Запрос информации о продукте
querySkuDetailsAsync(cpOrder, productId);
}
//Запрос информации о продукте
void querySkuDetailsAsync(final String cpOrder, final String productId){
List<String> skuList = new ArrayList<>();
skuList.add(productId);
SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);
mBillingClient.querySkuDetailsAsync(params.build(),
new SkuDetailsResponseListener() {
@Override
public void onSkuDetailsResponse(BillingResult billingResult,
List<SkuDetails> skuDetailsList) {
if (skuDetailsList != null && billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK){
for(SkuDetails skuDetails : skuDetailsList){
if(productId.equals(skuDetails.getSku())){
//Инициировать платеж
launchBillingFlow(cpOrder, skuDetails);
}
}
}
}
});
}
//Удерживаем страницу оплаты Google
void launchBillingFlow(String cpOrder, SkuDetails skuDetails){
mBillingClient.launchBillingFlow(
wrActivity.get(),
BillingFlowParams
.newBuilder()
.setSkuDetails(skuDetails)
.setObfuscatedAccountId(cpOrder)//Первоначальное значение здесь — хранить информацию о пользователе, что аналогично внутренним параметрам прозрачной передачи. Я передаю здесь номер нашего заказа. В старой версии используется поле DeveloperPayload. Это поле больше не доступно в последней версии.
.build()
);
}
Операция проверки платежа на сервере относительно сложна, поэтому мы предложим ее в виде отдельного раздела ниже.
setp5
потребительские товары
public void consumePurchase(final Purchase purchase){
if(mBillingClient == null || purchase == null || purchase.getPurchaseState() != Purchase.PurchaseState.PURCHASED) return;
LogUtils.d("Потребляемый продукт:\nИдентификатор продукта:" + purchase.getSkus() + "\nИдентификатор заказа продукта:" + purchase.getOrderId() + "\ntoken:" + purchase.getPurchaseToken());
LogUtils.d("Потребляемые товары:" + purchase.getAccountIdentifiers().getObfuscatedAccountId());
ConsumeParams consumeParams = ConsumeParams.newBuilder()
.setPurchaseToken(purchase.getPurchaseToken())
.build();
ConsumeResponseListener listener = new ConsumeResponseListener() {
@Override
public void onConsumeResponse(BillingResult billingResult, String purchaseToken) {
if (billingResult.getResponseCode() == BillingResponseCode.ERROR) {
//Если Потребление не удалось, поместите товар обратно в очередь Потребления
OrderManager.getInstance().consumeFinal(purchase);
return;
}
LogUtils.d("Потреблениеуспех");
}
};
mBillingClient.consumeAsync(consumeParams, listener);
}
Прежде чем проводить проверку на стороне сервера, вам необходимо выполнить некоторые приготовления.
Вот несколько скриншотов операции:
setp1
Создать проект API
setp2
Включить API разработчика Google Play для Android
API и сервисное меню
Меню библиотеки
Найдите «API разработчика Google Play для Android».
image.png
Включите «API разработчика Google Play для Android».
image.png
setp3
Открыть экран согласия
Заполните необходимые поля
здесь Заполните необходимые Просто нажмите на поле, этот экран согласия авторизации открывается при запросе кода и открывается нашим разработчикам. Неважно, что вы заполняете.
setp4
Создать идентификатор клиента oauth2
image.png
ClientId и clientSecret можно получить, создав страницу и изменив ее после успешного создания.
image.png
На данный момент проект API создан.
setp5
google playназадсвязанные с Тайванемapiпроект
image.png
setp6
Получить код
Замените {XX} выше на Создать. проект API时填写из重定向адрес,и идентификатор клиента,Затем откройте соединение в браузере,Интерфейс авторизации будет поднят.,Войдите в систему, используя авторизацию своей учетной записи разработчика.
Способ запроса: Открыть в браузере
Как вы можете видеть здесь, в адресе перенаправления есть два параметра code и область действия. Нам нужен только код. При его использовании требуется код после urlencode.
setp7
Используйте код в обмен наrefreToken
адрес:https://accounts.google.com/o/oauth2/token
Метод запроса: сообщение
Параметр:grant_type=authorization_code
code=полученный код (необходимо проверить, есть ли в коде знак %, если да, то urldecode обязателен)
client_id=Создать проект API — clientId (идентификатор клиента)
client_secret=Создать проект clientSecret (секрет клиента) во время API
redirect_uri=Создать проект Адрес перенаправления API
image.png
Здесь вы получаете обновленный токен,Фокус, фокус, фокус, обновление. Токен сохранен.,Он будет возвращен только в первых запросах.,Последующее использование того же запроса не вернет токен обновления.,Если вы случайно потеряете его,Необходимо заново создать WebClientId
setp8
Используйте обновитьToken, чтобы получить accessToken
адрес:https://accounts.google.com/o/oauth2/token
Метод запроса: сообщение
Параметр:grant_type=refresh_token
обновить_токен = только что полученный RefreshToken
client_id=Создать проект API — clientId (идентификатор клиента)
client_secret=Создать проект clientSecret (секрет клиента) во время API
image.png
setp9
Проверить статус заказа
https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/products/{productId}/tokens/{token}?access_token={access_token}
packageName: имя пакета приложения, должно быть именем пакета, используемым при создании проекта входа в API, создании идентификатора клиента Android.
ProductId: идентификатор продукта, соответствующий приобретенному продукту.
токен: getPurchaseToken() объекта Purchase после успешной покупки
access_token: токен доступа, который мы получили выше.
Метод запроса: получить
Возвращаемое значение:
{
"purchaseTimeMillis": "1623980699933",//Время приобретения товара, начиная с эпохи (1970 г.) Год 1 луна 1 Количество миллисекунд со дня).
"purchaseState": 0, // Статус покупки заказа. Возможные значения: 0. Куплено 1. Отменено 2. Будет определено
"consumptionState": 0, //Статус Потребления продукта. Возможные значения: 0. Еще не израсходовано 1. Потреблено
"developerPayload": "",
"orderId": «GPA.3398-6726-1036-80298», //номер заказа Google
"purchaseType": 0,
"acknowledgementState": 0,
"kind": "androidpublisher#productPurchase",
"obfuscatedExternalAccountId": «SDK2106180944530041», // Вышеуказанное прозрачное поле передачи, когда клиент платит, руководство Google используется для хранения информации о пользователе, оно не может быть слишком длинным, иначе клиент не сможет оплатить
"obfuscatedExternalProfileId": "",
"regionCode": "HK"
}
Весь процесс проверки платежа завершен здесь. Вот краткое изложение некоторых ошибок, с которыми столкнулся автор во время этого испытания:
Запрещено воспроизведение без разрешения:блог толстого кота » Google Pay и проверка на стороне сервера