關(guān)于查看google play退款訂單的前提,首先,需要獲取Google API的訪問權(quán)限,從獲取API訪問權(quán)限上來看,大致分為兩種方法,第一種是通過OAuth 客戶端訪問,需要客戶端用戶來授權(quán),才能獲取Google API的訪問權(quán)限,然后進行用戶訂單詳情的查詢,第二種是不需要用戶來授權(quán)的,我相信這種方法也是服務端比較喜歡的,畢竟用戶授權(quán)這種事情你是沒辦法確定能拿到權(quán)限的。對于代表非人類機器人運行的服務器應用(如持續(xù)集成系統(tǒng)),建議使用服務帳號。對于直接代表人類用戶運行的客戶端應用(如 IDE 插件),則可以使用 OAuth 客戶端。我目前的項目比較適合服務賬號,所以,這里我們就只介紹第二種方法,利用google play開發(fā)者賬號建立服務賬號,直接對其授權(quán),然后再進行對Google API的訪問。
前言
這篇文章我們從創(chuàng)建 Google Play 開發(fā)者帳號說起,因為我最近為了google退款訂單詳情的查詢踩了不少的坑,也許是英語太差,所以為了更好的理解和開發(fā)google退款的流程,我盡量詳細介紹,每一個參數(shù)。全憑自己理解,不喜勿噴,歡迎大神指點批評。
1. 創(chuàng)建賬號以及關(guān)聯(lián)API服務
首先我們需要有 Google Play 開發(fā)者帳號,這個賬號首先你要有自己的google賬號,然后到Google Play Console進行開發(fā)者賬號的注冊開通,這里是需要支付 $25 的注冊費用的,注冊完成之后就要創(chuàng)建新的API項目(就是創(chuàng)建一個你的應用項目):
在 Google Play 管理中心轉(zhuǎn)到 API 訪問權(quán)限頁面。
接受服務條款。
點擊創(chuàng)建新項目。
如果您已是 Google Play Developer API 的用戶,則可以執(zhí)行以下這些步驟來關(guān)聯(lián)到您現(xiàn)有的 API 項目。如果您想關(guān)聯(lián)的 API 項目未列出,請確認您的 Google Play 管理中心帳號是否已指定為“所有者”,且 Google Play Developer API 已啟用。
在 Google Play 管理中心轉(zhuǎn)到 API 訪問權(quán)限頁面。
接受 API 服務條款。
選擇您想關(guān)聯(lián)的項目。
點擊關(guān)聯(lián)。
到這里您的 Google Play 管理中心現(xiàn)已關(guān)聯(lián)到 API 項目。一般開始寫退款接口的時候google賬號都已經(jīng)是部署好的了應該,所以前面的步驟這里就不細說了
2. 創(chuàng)建服務賬號
上邊已經(jīng)創(chuàng)建項目并且也關(guān)聯(lián)了API,下面就可以直接
1.在 Google Play 管理中心轉(zhuǎn)到 API 訪問權(quán)限頁面。
2.點擊開發(fā)者賬號
3.點擊API權(quán)限
4.點擊創(chuàng)建服務賬號,按照頁面上的說明創(chuàng)建您的服務帳號。
5.在 Google Developers Console 中創(chuàng)建服務帳號后,請點擊完成。API 訪問權(quán)限頁面會自動刷新,您的服務帳號將隨即列出。
創(chuàng)建服務賬號.jpg
6.創(chuàng)建完服務賬號需要生成一下密鑰,公鑰生成.json格式或者P12文件都行,我這里用的時.json文件,后面代碼中要用到
6.在用戶和權(quán)限頁面可以看到剛創(chuàng)建的服務賬號,接下來只要進行授權(quán)就可以使用了
設置賬號的訪問權(quán)限.jpg
3. 調(diào)用Google API查詢退款訂單詳情
到了這一步就開始寫接口了,我這里用的是Spring boot+cloud的框架,下面就不做解釋了,首先調(diào)用google API需要引入依賴:
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-androidpublisher</artifactId>
<version>v3-rev95-1.25.0</version>
</dependency>
然后就是服務賬號如何獲取訪問google API的權(quán)限,經(jīng)過我的個人理解和google官方文檔總結(jié)了一下,把整個代碼給摘分開來了,第一部分是獲取服務賬號訪問權(quán)限,創(chuàng)建一個訪問谷歌api的GoogleCredential 相當于一個權(quán)限令牌
private GoogleCredential getAndroidPublisherScopesOfGoogleCredential()throws Exception{
//這里是建立服務賬號后生成的.json文件,這里這樣寫需要把.json文件放到相應模塊的resources下,想要換一個目錄可以隨意,但不要忘了改文件路徑
ClassPathResource classPathResource = new ClassPathResource("xxx-xxxx-xxxxxx.json");
GoogleCredential credential = GoogleCredential.fromStream(classPathResource.getInputStream())
.createScoped(AndroidPublisherScopes.all());//createScoped給令牌訪問權(quán)限設置使用的權(quán)限范圍
if(credential!=null){
return credential;
}else{
throw new Exception("Get GoogleCredential fails");
}
}
因為我需要調(diào)用的接口在AndroidPublisher下,所以這里的權(quán)限范圍設置成了AndroidPublisherScopes.all(),這里的具體API權(quán)限范圍需要自己去查閱相關(guān)文檔進行了解,這里不再詳細說明。
上面拿到了令牌,下面就build一個要調(diào)用的google api的對應工具類
private AndroidPublisher getAndroidPublisher()throws Exception{
GoogleCredential credential = this.getAndroidPublisherScopesOfGoogleCredential();
NetHttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();//其中這兩個參數(shù)最終也沒去搞明白,不知道具體的用處,目測可能是調(diào)用googleAPI發(fā)送請求用的
JacksonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();//
return new AndroidPublisher.Builder(httpTransport, JSON_FACTORY, credential).build();
}
拿到了我們要用的工具類后,下面就可以調(diào)用接口了,下面這個接口是我在google官方文檔找的,具體連接是:https://developers.google.com/android-publisher/api-ref/purchases/voidedpurchases/list
下面的代碼中會經(jīng)常用到一個參數(shù)com.cn.aaaa是項目的完全限定軟件包名稱,就是應用名稱下面的灰色小字,根據(jù)自己的設置進行填寫
/**
* 獲取所有退款訂單的PurchaseToken(google 采購成功的唯一標識)
* @return
* @throws Exception
*/
private List<VoidedPurchase> getPurchaseToken()throws Exception{
boolean isExistData = true;
AndroidPublisher publisher = this.getAndroidPublisher();
AndroidPublisher.Purchases.Voidedpurchases voidedpurchases = publisher.purchases().voidedpurchases();
//后面還可以跟.setMaxResults 設置返回結(jié)果最大值默認1000 .setToken查詢更多結(jié)果時設置(下一頁nextPageToken)
AndroidPublisher.Purchases.Voidedpurchases.List refundInfo = voidedpurchases.list("com.cn.aaaa");
VoidedPurchasesListResponse refundList = refundInfo.execute();//執(zhí)行調(diào)用動作,返回結(jié)果
List<VoidedPurchase> voidedPurchases = refundList.getVoidedPurchases();
//獲取分頁token,若退款訂單當前頁沒有傳完,則返回參數(shù)中會有NextPageToken,用來循環(huán)請求下一頁的退款訂單
TokenPagination tokenPagination = refundList.getTokenPagination();
while (isExistData) {
if(tokenPagination!=null){
AndroidPublisher.Purchases.Voidedpurchases.List nextRefundInfo = voidedpurchases.list("com.cn.aaaa").setToken(tokenPagination.getNextPageToken());
VoidedPurchasesListResponse nextRefundLists = nextRefundInfo.execute();
List<VoidedPurchase> nextVoidedPurchasess = nextRefundLists.getVoidedPurchases();
tokenPagination = nextRefundLists.getTokenPagination();
voidedPurchases.addAll(nextVoidedPurchasess);
}else{
isExistData = false;
}
}
return voidedPurchases;
}
這里終于拿到了您的應用中所有的產(chǎn)生退款的訂單的PurchaseToken,具體的返回參數(shù)解釋官方文檔卻比較詳細,可以用上面的連接進行查閱,但是這個返回結(jié)果中除了PurchaseToken并沒有訂單號,而可恨的是我們的庫里面根本沒有存google的這個采購成功的唯一標識PurchaseToken,然后我就繼續(xù)開始翻google的官網(wǎng)文檔終于找到了一個不太方便的方法,目前我只能找到這一個解決辦法。(有那位大神知道其他的簡單的方法的話,求指教,留言)
/**
* 獲取所有退款訂單詳情
* @return
* @throws Exception
*/
public MessageResult getOrder() throws Exception {
List<VoidedPurchase> purchaseTokenList = this.getPurchaseToken();
String pakgeName = "com.cn.aaaa";
List<ProductPurchase> infoList = new ArrayList<>();
for(VoidedPurchase voidedPurchase : purchaseTokenList) {
String purchaseToken = voidedPurchase.getPurchaseToken();
AndroidPublisher publisher = this.getAndroidPublisher();
List<String> list = new ArrayList<>();
list.add("您的應用在google中設置的產(chǎn)品ID");
......
list.add("您的應用在google中設置的產(chǎn)品ID");
//這里之所以寫這個list是因為我們只拿到了PurchaseToken,但調(diào)用GET產(chǎn)品詳情的接口參數(shù)中包括這一訂單的產(chǎn)品ID,
//但是我們并不知道哪個訂單是退款訂單,更不知道是買的那個產(chǎn)品被退款,所以這里只能拿所有產(chǎn)品ID進行輪詢
for (String id : list) {
AndroidPublisher.Purchases.Products.Get products = publisher.purchases().products().get(pakgeName, id, purchaseToken);
try {
//這里的詳細返回參數(shù)解釋查看官方文檔:[https://developers.google.com/android-publisher/api-ref/inappproducts/get](https://developers.google.com/android-publisher/api-ref/inappproducts/get)
ProductPurchase info = products.execute();
if(info!=null){
infoList.add(info);
}
} catch (Exception e) {
//這里在異常中處理是因為當參數(shù)中的product ID與PurchaseToken代表的訂單的product ID不一致時會拋錯,所以在這里捕捉后進行后續(xù)處理
String error = e.getMessage();
if (error.indexOf("The purchase token does not match the product ID") > 0) {
log.warn("產(chǎn)品ID與Token中的不一致");
}else{
log.error("查詢退款訂單詳情異常:{}",error);
}
}
}
}
return MessageResult.success(infoList);
}
到這里就已經(jīng)結(jié)束了,退款訂單的所有詳情已獲取。
注:對于googleAPI的調(diào)用,必須放到國外的服務器進行接口的調(diào)用,否則國內(nèi)的網(wǎng)絡無法聯(lián)通,其他任何方法不適用