Android Google Play 服務(wù)器驗(yàn)證

概要:Google 建議在完成支付后依據(jù)服務(wù)器返回訂單結(jié)果為準(zhǔn)所以才有了這篇文章。本文針對訂單支付完成后 驗(yàn)證購買交易 過程锨侯、踩坑記錄嫩海。開始前,先有一個(gè)大致的過程囚痴,流程圖大概說明了 向Google服務(wù)器驗(yàn)證訂單的過程叁怪,其中具體的過程下文會(huì)詳細(xì)解釋:

GooglePlay 訂單校驗(yàn)過程.png

官方地址:https://developer.android.com/google/play/billing/billing_library_overview .png

前提

  • Google Api
  • Google Play Console
  • 測試App程序
  • 最好使用自己應(yīng)用內(nèi)創(chuàng)建的商品(不建議使用Google提供的測試商品)

Google 文檔:Google Play Developer APIApi使用入門

Google Api

由于這里是向Google服務(wù)器驗(yàn)證深滚,需要使用調(diào)用相關(guān)的 Google Api 進(jìn)行相關(guān)操作 :


Google Play Developer API使用.png

這里我選擇的是 OAuth客戶端 奕谭,OAuth客戶端需要在Google Play Console ---> 設(shè)置 -----> 開發(fā)者賬號 -----> Api 權(quán)限 進(jìn)行創(chuàng)建,如下圖:

OAuth客戶端.png

創(chuàng)建完成后成箫,點(diǎn)擊 在Google Developers Console中查看 展箱, 進(jìn)入到 Api 控制臺(tái) ,需要新建項(xiàng)目蹬昌,創(chuàng)建項(xiàng)目完成混驰,點(diǎn)擊 OAuth同意屏幕 配置驗(yàn)證信息,比如:我使用到了../androidpublisher Api添加即可如下圖:

OAuth同意屏幕.png

添加憑據(jù)皂贩,并添加


image.png

注意栖榨,右側(cè)下載按鈕,下載出來的json明刷,包含后續(xù)所需要的參數(shù)婴栽,如下圖:


下載的json包含憑據(jù)全部信息json.png
1,獲取授權(quán) Api 調(diào)用

OAuth 2.0 for Mobile & Desktop Apps 官網(wǎng)地址

授權(quán)接口:https://accounts.google.com/o/oauth2/v2/auth 調(diào)用辈末,這里解釋一下 必填 參數(shù)(全部可以參考上面鏈接查看)

參數(shù) 解釋
client_id api控制臺(tái)獲取愚争,上圖也有
redirect_uri api控制臺(tái)獲取,上圖也有,比如:urn:ietf:wg:oauth:2.0:oob
response_type 固定值:code 挤聘。(確定Google OAuth 2.0端點(diǎn)是否返回授權(quán)碼轰枝。code為已安裝的應(yīng)用程序設(shè)置參數(shù)值。)
scope 我這里填入的是:https://www.googleapis.com/auth/androidpublisher组去。范圍指的是應(yīng)用程序可以訪問的Api范圍鞍陨,附:OAuth2.0 Api范圍

這里的的接口,需要在瀏覽器調(diào)用 (需要你的Google賬號進(jìn)行授權(quán)) 从隆,例如我在瀏覽器調(diào)用下面的接口(需要將里面的id參數(shù)替換為自己的參數(shù)):

https://accounts.google.com/o/oauth2/v2/auth?client_id=你的id&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&scope=https://www.googleapis.com/auth/androidpublisher

  1. 頁面訪問url后诚撵,首先需要進(jìn)行授權(quán):


    授權(quán)頁面.png
  2. 確認(rèn)選擇、結(jié)果頁面

    確認(rèn)選擇頁面.png

    結(jié)果頁面.png

    上面的結(jié)果键闺,就是下面所需要的 code 值寿烟,注意,這里調(diào)用一次辛燥,保存在項(xiàng)目即可韧衣,不需要每次都進(jìn)行該步驟V言濉9荷!3┟!坑2硕噩!

2,獲取access_token api調(diào)用

post 請求: https://www.googleapis.com/oauth2/v4/token

參數(shù) 解釋
code https://accounts.google.com/o/oauth2/v2/auth接口返回的值缭贡,就是上面授權(quán)后獲得的值
client_id api控制臺(tái)獲取炉擅,上面也有
client_secret api控制臺(tái)獲取,上面json中也有
redirect_uri api控制臺(tái)獲取阳惹,上面也有,比如:urn:ietf:wg:oauth:2.0:oob
grant_type 固定值:authorization_code

比如我的網(wǎng)絡(luò)請求谍失,請求成功返回結(jié)果如下:

/**
         * 獲取access_token : 每個(gè)請求,都需要拼接到后面莹汤,例如:?access_token=xxxxx
         */
        String tokenUrl = "https://accounts.google.com/o/oauth2/token";
        String code = "4/qQFrmvbxm5hEnXPxiBz-LYoFAf4kIqHhHvmn2CfaeI_2kq3bqtPYnUs";
        String client_secret = "rlCm_3T2zOitkOA6cS4TDR_P";
        OkHttpUtils.post().url(tokenUrl)
                .addParams("client_id",cliendId) //GoogleApi后臺(tái)拿到
                .addParams("redirect_uri",redirect_uri) //GoogleApi后臺(tái)拿到
                .addParams("grant_type","authorization_code")//固定值
                .addParams("code",code)//上面獲取快鱼,只需要調(diào)用一次
                .addParams("client_secret",client_secret)////GoogleApi后臺(tái)拿到
                .build().execute(new StringCallback() {
            @Override
            public void onError(Call call, Exception e, int id) {
                Log.d(TAG, "onError: ");
            }

            @Override
            public void onResponse(String response, int id) {
                //返回的結(jié)果都在 response 包含
                Log.d(TAG, "onResponse: ");//返回,GoogleAccsessTokenBean.java 相關(guān)內(nèi)容
            }
        });


********************** 返回結(jié)果 ***********************************
    /**
     * access_token : ya29.GltyB1aAtM7QEz0T0GVtNZk64bXldamoCWU32us0fe2zD8HvBNW3LMig4-T2p3EAc4oDfozqa6ZHIaNfCC19KFk4qFhPwAniSzy2r7OeunPHx8P6tzCwjKA1_H4F
     * expires_in : 3600
     * refresh_token : 1/ZSenrx4IL5iUnyA_P0TjDG9GpY6xENpEIv4LeQeo3mg
     * scope : https://www.googleapis.com/auth/androidpublisher
     * token_type : Bearer
     */

注意:

  • 這里需要保存 access_token纲岭、refresh_token抹竹,下面會(huì)解釋refresh_token用途
  • 這里返回的 access_token 就是每次調(diào)用Api,需要拼接的參數(shù)V钩薄G耘小!坑喇闸,這個(gè)access_token 必須正確(不然會(huì)報(bào)400 401錯(cuò)誤)0懒铡!
refresh_token

測試階段過了一會(huì)發(fā)現(xiàn)接口無法調(diào)通燃乍,排查發(fā)現(xiàn)原因是Token過期了(應(yīng)該沒到token過期時(shí)間,返回的過期時(shí)間是3600s不知道怎么回事~~有點(diǎn)懵逼-_- )唆樊,重新查閱文檔發(fā)現(xiàn),上面調(diào)用https://www.googleapis.com/oauth2/v4/token接口返回的 refresh_token 是調(diào)用 刷新Token 接口(兩個(gè)是同一個(gè)接口只不過傳參不同)橘沥。

具體解釋見下圖(網(wǎng)頁翻譯了一下)具體說明了傳參以及示例窗轩。

refresh_token.png

注意:參數(shù)grant_type的值變成了refresh_token

小結(jié):

上面通過Google Play Console、Google API 控制臺(tái)座咆,生成OAuth2客戶端痢艺,主要是為了驗(yàn)證授權(quán)用戶,對于我們來說就是為了獲取 code介陶、access_token堤舒、refresh_token ,為調(diào)用下面的 校驗(yàn)接口 做鋪墊哺呜。
注意舌缤,坑!!9臁A晡:

  • code:獲取需要網(wǎng)頁打開,需用戶登錄Google賬號授權(quán)介牙,code值生成一次壮虫,保存在項(xiàng)目即可!
  • access_token :獲取需要使用上面獲得的code环础,不然各種401 404錯(cuò)誤囚似。
  • 接口請求如果出現(xiàn)問題,請認(rèn)真仔細(xì)對比 接口參數(shù) 是否有誤线得!

Google Play 校驗(yàn)接口

Api - Purchases.products官方地址

到這里饶唤,才是真正的調(diào)用 校驗(yàn)接口,這個(gè)接口提供了兩個(gè)方法贯钩,不過返回值都一樣募狂,先說一下返回值代表意義

{
  "kind": "androidpublisher#productPurchase",
  "purchaseTimeMillis": long,
  "purchaseState": integer,
  "consumptionState": integer,
  "developerPayload": string,
  "orderId": string,
  "purchaseType": integer,
  "acknowledgementState": integer
}
參數(shù) 類型 解釋
kind String 這種類型代表androidpublisher服務(wù)中的inappPurchase對象。
purchaseTimeMillis long 購買產(chǎn)品的時(shí)間魏保,自紀(jì)元(1970年1月1日)以來的毫秒數(shù)熬尺。
purchaseState integer 訂單的購買狀態(tài); 0:購買 1:取消 2:掛起(待支付)
developerPayload String 開發(fā)人員指定的字符串,包含有關(guān)訂單的補(bǔ)充信息谓罗。
orderId String 與購買inapp產(chǎn)品相關(guān)聯(lián)的訂單ID粱哼。
purchaseType integer 購買inapp產(chǎn)品的類型。僅當(dāng)未使用標(biāo)準(zhǔn)應(yīng)用內(nèi)結(jié)算流程進(jìn)行此購買時(shí)檩咱,才會(huì)設(shè)置此字段揭措。可能的值是:0. 測試(即從許可證測試帳戶購買)1. 促銷(即使用促銷代碼購買)2. 獎(jiǎng)勵(lì)(即觀看視頻廣告而非付費(fèi))
acknowledgementState integer inapp產(chǎn)品的確認(rèn)狀態(tài)刻蚯。0:待確認(rèn) 1:已確認(rèn)
consumptionState integer inapp消費(fèi)狀態(tài)绊含。0:未消費(fèi) 1:已消費(fèi)

Acknowledge - 確認(rèn)購買了一個(gè)inapp項(xiàng)目。
1炊汹,調(diào)用確認(rèn)接口前躬充,需要調(diào)用授權(quán)接口(其實(shí)就是需要傳入授權(quán)的access_token)

post 請求: https://www.googleapis.com/auth/androidpublisher

該接口需要傳遞參數(shù)

參數(shù) 類型 解釋
developerPayload String 有效負(fù)載附加到購買,該值在 商品詳情 會(huì)有返回
access_token String 授權(quán)token,上面獲得的token

2讨便,然后調(diào)用 確認(rèn)授權(quán)接口

POST https://www.googleapis.com/androidpublisher/v3/applications/你的應(yīng)用包名/purchases/products/商品id/tokens/商品token:acknowledge

這個(gè)請求充甚,需要注意替換三個(gè)地方,上面我也標(biāo)記出來了霸褒, 包名伴找、商品的productId、token(這里指的是商品購買返回的商品token) 注意后面有一個(gè):acknowledge 废菱, 還需要加上 參數(shù):access_token

Get - 檢查inapp項(xiàng)目購買和消費(fèi)狀態(tài)
1技矮,需要調(diào)用授權(quán)接口(其實(shí)就是需要傳入授權(quán)的access_token)

https://www.googleapis.com/auth/androidpublisher

2抖誉,Get方法調(diào)用 ,檢查inapp項(xiàng)目的購買和消費(fèi)狀態(tài)接口

Get方法 https://www.googleapis.com/androidpublisher/v3/applications/你的應(yīng)用包名/purchases/products/商品id/tokens/商品token

這個(gè)請求衰倦,需要注意替換三個(gè)地方袒炉,上面我也標(biāo)記出來了, 包名耿币、商品的productId梳杏、token(這里指的是商品購買返回的商品token) 注意不同于上面,后面沒acknowledge淹接, 還需要加上參數(shù): access_token

總結(jié):

服務(wù)器驗(yàn)證這步驟叛溢,折騰了好久塑悼,開始一直是接口調(diào)用不通(400 401錯(cuò)誤),中間也是沒少踩坑楷掉,如果出問題請仔細(xì)檢查下面幾項(xiàng)

  • 配置檢測厢蒜,如:自己的應(yīng)用包名是否跟Google Play Console 一致、Google Api Oauth創(chuàng)建等配置是否有誤烹植。
  • 接口參數(shù)斑鸦,如:Google Api 后臺(tái)獲取的client_id、secret_id是否正確草雕,是否授權(quán)獲取到code(僅調(diào)一次巷屿,保存即可),接口調(diào)用是否傳遞了access_token以及是否過期
  • 如果校驗(yàn)步驟遇到400(接口返回信息: Invalid Value)墩虹,建議去查一下購買的商品在Google Play Console 上是否處于 有效 狀態(tài)嘱巾,不要使用Google提供的訂單測試商品。

附:https://github.com/paihuai00/GooglePayTest

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末诫钓,一起剝皮案震驚了整個(gè)濱河市旬昭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌菌湃,老刑警劉巖问拘,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異惧所,居然都是意外死亡骤坐,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進(jìn)店門纯路,熙熙樓的掌柜王于貴愁眉苦臉地迎上來或油,“玉大人,你說我怎么就攤上這事驰唬《グ叮” “怎么了腔彰?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長辖佣。 經(jīng)常有香客問我霹抛,道長,這世上最難降的妖魔是什么卷谈? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任杯拐,我火速辦了婚禮,結(jié)果婚禮上世蔗,老公的妹妹穿的比我還像新娘端逼。我一直安慰自己,他們只是感情好污淋,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布顶滩。 她就那樣靜靜地躺著,像睡著了一般寸爆。 火紅的嫁衣襯著肌膚如雪礁鲁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天赁豆,我揣著相機(jī)與錄音仅醇,去河邊找鬼。 笑死魔种,一個(gè)胖子當(dāng)著我的面吹牛析二,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播务嫡,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼甲抖,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了心铃?” 一聲冷哼從身側(cè)響起准谚,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎去扣,沒想到半個(gè)月后柱衔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡愉棱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年唆铐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片艾岂。...
    茶點(diǎn)故事閱讀 40,488評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖王浴,靈堂內(nèi)的尸體忽然破棺而出脆炎,到底是詐尸還是另有隱情氓辣,我是刑警寧澤,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布钞啸,位于F島的核電站,受9級特大地震影響体斩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜硕勿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望源武。 院中可真熱鬧想幻,春花似錦、人聲如沸脏毯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽渣淤。三九已至,卻和暖如春吉嫩,著一層夾襖步出監(jiān)牢的瞬間价认,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工自娩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留用踩,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓忙迁,卻偏偏與公主長得像脐彩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子姊扔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評論 2 359

推薦閱讀更多精彩內(nèi)容