Google Pay и проверка на стороне сервера
Google Pay и проверка на стороне сервера

В связи с деловыми потребностями компании требуется вход в систему Google и оплата. Платеж Google делится на два типа: подписка и покупка в приложении. Автор использует покупку в приложении. Здесь записывается весь процесс оплаты и проверки платежа Google.

Импортировать библиотеку расчетов Google

Адрес доступа к платежной службе Google

Язык кода:javascript
копировать
def billing_version = "4.0.0"
implementation "com.android.billingclient:billing-ktx:$billing_version"

Оплата доступа

процесс:

  1. Инициализируйте ссылку на платежный сервис Google. Если ее невозможно привязать, значит, проблема в среде устройства. Либо нет FQ, либо не полностью установлен пакет Google (google pay, сервер). все кастрированы, поэтому вам нужно переустановить пакет Google.
  2. Запросите последние неизрасходованные продукты, уведомите сервер, если есть неизрасходованные продукты, а затем употребите их. Поскольку платежная среда за границей отличается от китайской, они могут разместить заказ онлайн, а затем пойти в магазин, чтобы оплатить его, поэтому возникает ситуация, когда потребления нет.

На данный момент работа по подготовке к платежу Google завершена, и платеж можно инициировать ниже.

  1. Используйте серверную часть Google, чтобы настроить идентификатор продукта для оплаты.
  2. После завершения оплаты сервер получает уведомление для проверки законности заказа и его отправки.
  3. Клиентские товары народного потребления

Как насчет того, чтобы разместить код ниже?

step1

Инициализируйте и подключитесь к сервисам Google

Язык кода:javascript
копировать
    // метод инициализации
    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 неизрасходованные продукты нельзя приобрести снова)

Язык кода:javascript
копировать
    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

Инициировать платеж

Язык кода:javascript
копировать
    /**
     * 
     * @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

потребительские товары

Язык кода:javascript
копировать
    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);
    }

Проверка на стороне сервера

Прежде чем проводить проверку на стороне сервера, вам необходимо выполнить некоторые приготовления.

  1. Создать проект APIЭто не тот же элемент, который использовался для входа в систему.
  2. включатьGoogle Play Android Developer API
  3. настраиватьэкран согласия oauth(Это страница входа, когда вы открываете авторизованную учетную запись разработчика для входа в систему.)
  4. создаватьИдентификатор клиента oauth веб-приложения.
  5. серверная часть разработчика Google Play,Разрешения APIАссоциация в меню только что появилась.создаватьизпроект,одинgoogle Учетная запись play должна быть связана только с одним проектом API. Этот проект может запрашивать заказы всех приложений в связанной учетной записи.
  6. Поднимите страницу авторизации,Авторизуйте проект, используя свою учетную запись разработчика Google.,получатьcode
  7. по коду,получатьrefreshToken,этотtokenтолькопервыйвернет необходимоепостоянное хранилище(этотrefreshtokenочень важно,надо сохранить),если потеряно,Воссоздать только идентификатор клиента oauth,Затем повторите шаг 6,7,Получить новый токен обновления
  8. ОбновитеrefreToken и получите accessToken. Вы можете проверить статус заказа с помощью accessToken. Срок действия accessToken обычно составляет около 5 минут. Через 5 минут вам необходимо обменять RefreshToken на новый accessToken.

Вот несколько скриншотов операции:

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

Получить код

адрес:https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/androidpublisher&response_type=code&access_type=offline&redirect_uri={填写из重定向адрес}&client_id={создаватьизclientId}

Замените {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: токен доступа, который мы получили выше.

Метод запроса: получить

Возвращаемое значение:

Язык кода:javascript
копировать
{
  "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 должны находиться в статусе закрытого тестирования и должны быть одобрены перед осуществлением оплаты. В документе говорится, что автору необходимо каждый раз находиться в статусе закрытого тестирования, прежде чем можно будет произвести оплату.
  • Когда вы создаете проект в Firebase, он автоматически синхронизируется с серверной частью Google API. Нет необходимости создавать отдельный проект для входа в систему.
  • Проект API, используемый для входа в систему, и проект API, используемый для оплаты запроса, представляют собой два разных проекта, которые не мешают друг другу. Проект API, используемый для оплаты запроса, соответствует одной учетной записи Google Play. Все приложения в этой учетной записи Google Play можно оплачивать. через этот запрос API для запроса.
  • При получении проекта API авторизации кода необходимо использовать авторизацию учетной записи разработчика в фоновом режиме Google Play.

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

  • проект API — экран согласия, статус выпуска — тестирование (действителен в течение 7 дней)
  • RefreshToken не использовался в течение 6 месяцев. Это необходимо для поддержания действительности accessToken и не должно учитываться.
  • Был изменен пароль авторизованной учетной записи (автор не проверял, приведет ли изменение пароля учетной записи разработчика к истечению его срока действия)
  • Если авторизовано более 50 токенов обновления, первый токен обновления станет недействительным (50 здесь должно быть достаточно, за исключением тестирования, когда может быть авторизовано более одного)
  • Авторизация отменена
  • Принадлежите к организации Google Cloud Platform с действующей политикой управления сеансами.

Запрещено воспроизведение без разрешения:блог толстого кота » Google Pay и проверка на стороне сервера

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose