第一步.配置Google實時開發者通知
具體流程可以參考Google實時開發者通知或者中文文檔(備份)
一、網域驗證
登錄對應的Google賬號去https://search.google.com/search-console/驗證,使用域名前綴-html驗證的方式,下載對應html文件給放到自己域名對應的服務器上
二、添加網域到Google Console
三、創建對應的Google Pub/Subs
- 創建一個主題
- 添加[email protected]爲該主題的Pub/Sub發佈者
- 創建一個訂閱
四、在Google Play添加對應的主題名稱
各步驟所需參數及網址
Google實時開發者通知賬戶:
[email protected]
Google Search Console(網域驗證):
https://search.google.com/search-console/
Google Cloud Console(Google雲-訂閱):
https://console.cloud.google.com/cloudpubsub
Google Console(Google控制檯)
https://console.developers.google.com/apis
Google Play Console(Google Play控制檯)
https://play.google.com/apps/publish
第二步.開發Google實時開發者通知(訂閱回調)接口
對應回調接收接口開發參考Google實時開發者通知(訂閱回調)接口開發
回調接口:
@RequestMapping(value = "/googleNotify")
public String googleNotify(@RequestBody(required = false) byte[] body,HttpServletRequest request, HttpServletResponse response) {
Map<String, String> params = new HashMap<String, String>();
JSONObject paramJson = null;
try {
String paramStr = null;
String bodyStr = null;
try {
bodyStr = new String(body, "utf-8");
paramStr = bodyStr;
//回調具體內容見下方
log.debug("googleNotify params :{}",paramStr);
} catch (Exception e) {
e.printStackTrace();
}
if (!CStr.isEmpty(paramStr)){
paramJson = JSON.parseObject(URLDecoder.decode(paramStr,"utf-8"));
try {
JSONObject msgJson = paramJson.getJSONObject("message");
String data = msgJson.getString("data");
log.debug("googleNotify data :{}",paramStr);
String developerNotificationStr = new String(Base64.getDecoder().decode(data), "UTF-8");
JSONObject developerNotificationJson = JSON.parseObject(developerNotificationStr);
String packageName = developerNotificationJson.getString("packageName");
String eventTimeMillis = developerNotificationJson.getString("eventTimeMillis");
JSONObject subscriptionNotificationJson = developerNotificationJson.getJSONObject("subscriptionNotification");
String purchaseToken = subscriptionNotificationJson.getString("purchaseToken");
String subscriptionId = subscriptionNotificationJson.getString("subscriptionId");
/**
* notificationType int
* 通知的類型。它可以具有以下值:
* (1) SUBSCRIPTION_RECOVERED - 從帳號保留狀態恢復了訂閱。
* (2) SUBSCRIPTION_RENEWED - 續訂了處於活動狀態的訂閱。
* (3) SUBSCRIPTION_CANCELED - 自願或非自願地取消了訂閱。如果是自願取消,在用戶取消時發送。
* (4) SUBSCRIPTION_PURCHASED - 購買了新的訂閱。
* (5) SUBSCRIPTION_ON_HOLD - 訂閱已進入帳號保留狀態(如已啓用)。
* (6) SUBSCRIPTION_IN_GRACE_PERIOD - 訂閱已進入寬限期(如已啓用)。
* (7) SUBSCRIPTION_RESTARTED - 用戶已通過“Play”>“帳號”>“訂閱”重新激活其訂閱(需要選擇使用訂閱恢復功能)。
* (8) SUBSCRIPTION_PRICE_CHANGE_CONFIRMED - 用戶已成功確認訂閱價格變動。
* (9) SUBSCRIPTION_DEFERRED - 訂閱的續訂時間點已延期。
* (10) SUBSCRIPTION_PAUSED - 訂閱已暫停。
* (11) SUBSCRIPTION_PAUSE_SCHEDULE_CHANGED - 訂閱暫停計劃已更改。
* (12) SUBSCRIPTION_REVOKED - 用戶在有效時間結束前已撤消訂閱。
* (13) SUBSCRIPTION_EXPIRED - 訂閱已過期。
*/
int notificationType = subscriptionNotificationJson.getIntValue("notificationType");
JSONObject resultJson = googleNotify(notificationType,packageName,subscriptionId,purchaseToken,CNum.longVal(eventTimeMillis));
if(resultJson != null){
//===========================================
/** 回調後對應的購買流程 **/
//===========================================
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
回調內容(data內容爲base64加密後內容,使用 new String(Base64.getDecoder().decode(data), “UTF-8”) 解密即可):
{
"message": {
"data": "ewogICAgInZlcnNpb24iOiAiMS4wIiwKICAgICJwYWNrYWdlTmFtZSI6ICLljIXlkI0iLAogICAgImV2ZW50VGltZU1pbGxpcyI6ICLml7bpl7TmiLMo5q+r56eSKSIsCiAgICAic3Vic2NyaXB0aW9uTm90aWZpY2F0aW9uIjogewogICAgICAgICJ2ZXJzaW9uIjogIjEuMCIsCiAgICAgICAgIm5vdGlmaWNhdGlvblR5cGUiOiA0LAogICAgICAgICJwdXJjaGFzZVRva2VuIjogIuaUr+S7mOS7pOeJjCIsCiAgICAgICAgInN1YnNjcmlwdGlvbklkIjogIuiuoumYheeahOWVhuWTgWlkIgogICAgfQp9",
"messageId": "消息id",
"message_id": "消息id",
"publishTime": "2019-11-14T03:58:43.608Z",
"publish_time": "2019-11-14T03:58:43.608Z"
},
"subscription": "projects/{project_id}/topics/{topic_name}"
}
data內容:
{
"version": "1.0",
"packageName": "包名",
"eventTimeMillis": "時間戳(毫秒)",
"subscriptionNotification": {
"version": "1.0",
"notificationType": 4,
"purchaseToken": "支付令牌",
"subscriptionId": "訂閱的商品id"
}
}
googleNotify方法(處理谷歌訂單流程這裏,普通支付和訂閱是一樣的,普通支付時查詢訂單狀態的api地址subscriptions需要替換爲products):
public JSONObject googleNotify(int notificationType, String packageName, String subscriptionId, String purchaseToken, long eventTimeMillis, int appId) {
JSONObject resultJson = null
try {
if (notificationType > 0) {
//獲取查詢令牌
JSONObject refreshJson = new JSONObject();
//grant_type固定爲refresh_token
refreshJson.put("grant_type", "refresh_token");
//client_id、client_secret、refresh_token爲創建時獲取的固定內容,具體見《GooglePay訂閱支付訂單校驗配置流程》
refreshJson.put("client_id", '你的client_id');
refreshJson.put("client_secret", '你的client_secret');
refreshJson.put("refresh_token", '你的refreshToken');
JSONObject refreshTokenJson = CHttpsUtil.postJsonData("https://accounts.google.com/o/oauth2/token", refreshJson.toJSONString());
if (refreshTokenJson.getString("access_token") == null) {
return null;
}
String googleAccessToken = refreshTokenJson.getString("access_token");
if (googleAccessToken == null) {
log.error("googleNotify googleAccessToken==null");
break;
}
//查詢谷歌訂單狀態
//查詢地址爲:https://www.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/subscriptions/{subscriptionId}/tokens/{purchaseToken}?access_token={googleAccessToken}
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("https://www.googleapis.com/androidpublisher/v3/applications/")
.append(packageName)
//.append("/purchases/products/")
.append("/purchases/subscriptions/")
.append(subscriptionId).append("/tokens/")
.append(purchaseToken)
.append("?access_token=")
.append(googleAccessToken);
JSONObject resultJson = CHttpsUtil.getJsonData(stringBuilder.toString());
if (resultJson == null) {
log.error("googleNotify resultJson==null");
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return resultJson;
}