我是否正确地验证了用户的Android应用内订阅?

Kal*_*ina 30 service android google-api subscription google-play

我正在制作一个不需要用户帐户/登录的应用程序,并允许用户购买订阅.我想使用Google Play Developer API来验证用户是否有购买/有效订阅.从所有文档中,我收集了以下步骤.

它们是否正确,您能否回答其中的两个问题?

  1. 在Google API控制台中创建服务帐户.
  2. 保存给我的私钥(其中?肯定不在我的代码/设备上,如此示例代码所示)
  3. 使用Google API Client Library for Java使用私钥创建和签署JWT(文档如何给我这个,但这不是Java代码......我该怎么办?)
  4. 构造访问令牌请求,并获得对API的访问权限
  5. 应用程序现在可以向API 发送GET请求,以确定用户是否具有订阅
  6. 当访问令牌过期时,请返回步骤3.

此外,我有一个Web服务,虽然我对Web服务或Web服务编程一无所知......我只知道它可能需要在这里使用.

编辑:这些步骤不正确.请参阅下面的答案,了解正确的步骤.但请注意,这仅适用于使用服务帐户(因为我不想要求用户必须明确允许API访问)

Kal*_*ina 41

事实证明,我的步骤不正确.我花了好几个星期来解决这个问题,似乎没有其他地方记录.别客气:

  1. Google API控制台中创建Web应用程序帐户.将任何网站作为"重定向URI"; 没关系,因为你不会真正使用它.创建帐户时,您将获得客户端ID和客户端密钥.

  2. 在计算机上的浏览器中,转到https://accounts.google.com/o/oauth2/auth?scope=https://www.googleapis.com/auth/androidpublisher&response_type=code&access_type=offline&redirect_uri=[YOUR REDIRECT URI]&client_id=[YOUR CLIENT ID]并在出现提示时允许访问.

  3. 查看地址栏.在您最初输入的URI的末尾将是您的刷新令牌.看起来1/....你将在下一步中需要这个"代码".刷新令牌永不过期.

  4. 转到,将此"代码"转换为"刷新令牌" https://accounts.google.com/o/oauth2/token?client_id=[YOUR CLIENT ID]&client_secret=[YOUR CLIENT SECRET]&code=[CODE FROM PREVIOUS STEP]&grant_type=authorization_code&redirect_uri=[YOUR REDIRECT URI].您可以将结果值保存在程序中; 除非明确撤销,否则它永不过期.(此步骤由@BrianWhite插入 - 请参阅注释)确保您使用的是POST.(由Gintas插入)

  5. 在你的代码,发送HttpPost请求https://accounts.google.com/o/oauth2/token与BasicNameValuePairs "grant_type","refresh_token","client_id",[YOUR CLIENT ID],"client_secret",[YOUR CLIENT SECRET],"refresh_token",[YOUR REFRESH TOKEN].这里有一个例子.您需要在单独的线程中执行此操作,可能使用AsyncTask.这将返回一个JSONObject.

  6. 从返回的JSONObject获取访问令牌.这里有一个例子.您需要获取字符串"access_token".访问令牌在1小时后到期.

  7. 在您的代码中,发送一个HttpGet请求https://www.googleapis.com/androidpublisher/v1/applications/[YOUR APP'S PACKAGE NAME]/subscriptions/[THE ID OF YOUR PUBLISHED SUBSCRIPTION FROM YOUR ANDROID DEVELOPER CONSOLE]/purchases/[THE PURCHASE TOKEN THE USER RECEIVES UPON PURCHASING THE SUBSCRIPTION]?accesstoken="[THE ACCESS TOKEN FROM STEP 4]".这里有一个例子.

  • 顺便说一句 - 您不应该直接从您的应用程序执行此操作,您应该从您的服务器执行此操作.您的应用应该只与您的服务器直接对话. (5认同)
  • @TheBeatlemaniac当我将您对本文档的答案进行比较时,https://developers.google.com/android-publisher/authorization似乎在步骤3和步骤4之间缺少一步,即根据返回的代码获取刷新令牌在浏览器的地址行中.你能详细说明一下吗?另外,请您详细说明"刷新令牌永不过期"的声明,因为其他人似乎认为它在某些情况下会过期.(我希望你在两个方面都是正确的) (3认同)
  • @TheBeatlemaniac感谢您的及时回答.我们正在执行完全相同的过程,直到第2步.我在步骤2中得到的结果是地址行中的URL,其末尾是code = xxxxx.然后我使用这个代码和一个额外的HttpPost请求,它有grant_type = authorization_code,我得到一个JSON响应,我从中获得了我在步骤4中使用的refresh_token.顺便说一下,我得到的代码(代码= xxx)以4开头/ ...我们看到的是同一件事吗?再次感谢.. (2认同)

Ram*_*ose 14

.NET用户:我希望这个答案能让人感到悲伤.

正如@Christophe Fondacci在2015年指出的那样,几年前公认的解决方案非常有效.现在是2017年,这个过程变得更加容易和快捷.

我的用例是验证应用内订阅,我的移动应用会将订阅购买信息发送到我的RESTful服务器,后者又与Google联系以验证订阅购买.

策略是创建一个代表您运营的服务帐户.

  1. 登录您的Google Play开发者控制台,然后点击您正在设置的应用.
  2. 访问设置 - > API访问权限
  3. 在" 服务帐户"下,单击" 创建服务帐户"按钮.
  4. 自2017年1月起,将显示一个对话框,其中包含有关设置服务帐户的说明.该对话框将您带到Google API控制台; 从那里,

    A)单击" 创建服务帐户"

    B)创建有意义的服务帐户名称.由于我们对访问Android Publisher服务感兴趣,因此我选择了"发布者".

    C)对于角色,只需选择一些东西 - 您可以稍后更改.

    D)选择"提供新私钥"并为.Net实施选择P12.不要丢失这个文件!

5)现在你完成#4,你会看到你的新服务帐户列出; 单击"授予访问权限"以启用它.

6)点击"查看权限"链接.您应该根据您的需求和API修改权限.

要验证应用内购买,请访问Cog-> Change Permissions并启用GLOBAL"Visiblity"和"Manage Orders"权限.

好了,此时您已在Google端配置了所有内容.现在设置服务器到服务器的东西.我建议创建一个.Net控制台应用程序来测试你的实现,然后在需要的地方卸载它.

1)从Nuget添加Android Publisher客户端库

PM> Install-Package Google.Apis.AndroidPublisher.v2
Run Code Online (Sandbox Code Playgroud)

2)将P12文件添加到项目根目录

3)更改P12属性,使"构建操作"为"内容","复制到输出目录"为"如果更新则复制".

4)实现这样的东西来测试你的访问和微调.

using System.Threading.Tasks;
using System.Security.Cryptography.X509Certificates;
using Google.Apis.Services;
using Google.Apis.Auth.OAuth2;
using Google.Apis.AndroidPublisher.v2;
...
public Task<SubscriptionPurchase> GetSubscriptionPurchase(string packageName, string productId, string purchaseToken)
{
    var certificate = new X509Certificate2(
                    "{{your p12 file name}}",
                    "{{ your p12 secret }}",
                    X509KeyStorageFlags.Exportable
                );
    var credentials = new ServiceAccountCredential(
            new ServiceAccountCredential.Initializer("{{ your service account email }}")
            {
                Scopes = new[] { AndroidPublisherService.Scope.Androidpublisher }
            }.FromCertificate(certificate))
            ;

    var service = new AndroidPublisherService(new BaseClientService.Initializer()
    {
        HttpClientInitializer = credentials,
        ApplicationName = "my server app name",
    });
    return service.Purchases.Subscriptions.Get(packageName, productId, purchaseToken).ExecuteAsync();
}
Run Code Online (Sandbox Code Playgroud)

祝你好运,希望这有助于某人.

资料来源:

将OAuth 2.0用于服务器到服务器应用程序

适用于Google.Apis.AndroidPublisher.v2的.Net客户端库


Rud*_*fwm 8

如果你像我一样,并希望在PHP中这样做,这里是如何做到的程序...感谢Kalina的回答我花了三天时间才弄清楚它是如何工作的:).

开始:

  1. 转到谷歌开发者控制台https://console.developers.google.com/并创建一个Web应用程序.将'developers.google.com/oauthplayground'设为"重定向URI"; 您将在步骤2中使用它.创建帐户时,您将获得客户端ID和客户端密码.确保添加了Google Play Android Developer API.

  2. 访问Google oauth2游乐场https://developers.google.com/oauthplayground/.这个伟大的工具是你未来几天最好的朋友.现在转到设置:确保已设置使用您自己的OAuth凭据.只有这样,您才能在下面的表格中填写您的客户ID客户机密.

  3. Google oauth2 playground中,转到步骤1 选择并授权API填写输入字段https://www.googleapis.com/auth/androidpublisher中的范围.我无法在列表中找到Google Play Android Developer API,也许他们会在稍后添加一些时间.点击AUTORIZE APIS.做下面的授权事情.

  4. Google oauth2 playground中,转到步骤2 令牌的Exchange授权码.如果一切顺利,您将看到以/ 4开头的授权码.如果某些事情没有顺利,请检查右侧的错误消息.现在你点击'刷新访问令牌'.复制刷新令牌......它将以/ 1开始...

  5. 现在,您始终可以获得访问令牌!这是如何:

    $url ="https://accounts.google.com/o/oauth2/token";
    $fields = array(
       "client_id"=>"{your client id}",
       "client_secret"=>"{your client secret}",
       "refresh_token"=>"{your refresh token 1/.....}",
       "grant_type"=>"refresh_token"
    );
    
    $ch = curl_init($url);
    
    //set the url, number of POST vars, POST data
    curl_setopt($ch, CURLOPT_POST,count($fields));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    
    //execute post
    $lResponse_json = curl_exec($ch);
    
    //close connection
    curl_close($ch);
    
    Run Code Online (Sandbox Code Playgroud)

现在你有一个ACCESS TOKEN万岁... JSON将如下所示:

"access_token" : "{the access token}",  "token_type" : "Bearer",  "expires_in" : 3600
Run Code Online (Sandbox Code Playgroud)

最后你准备问google了!这是怎么做的:

$lAccessToken = "{The access token you got in}" ;
$lPackageNameStr = "{your apps package name com.something.something}";
$lURLStr =  "https://www.googleapis.com/androidpublisher/v1.1/applications/$lPackageNameStr/subscriptions/$pProductIdStr/purchases/$pReceiptStr";

$curl = curl_init($lURLStr);

curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 
$curlheader[0] = "Authorization: Bearer " . $lAccessToken;
curl_setopt($curl, CURLOPT_HTTPHEADER, $curlheader);

$json_response = curl_exec($curl);
curl_close($curl);

$responseObj = json_decode($json_response,true);
Run Code Online (Sandbox Code Playgroud)

该JSON返回包含两个时间戳,该initiationTimestampMsecvalidUntilTimestampMsec时间的订阅是有效的.两者都是将毫秒加到1970年1月1日的毫秒数!


Chr*_*cci 6

我不知道在2012年,但在2015年你不应该手动执行任何这些步骤.我很难找到文档,所以我在这里发帖以防万一.

  1. 出于安全原因,您应该只从服务器中查询应用内购买,否则您无法信任购买过程的两个端点.

现在在服务器端(我认为如果您绝对需要,您仍然可以使用应用程序中的相同代码),请将google-api-services-androidpublisher客户端库包含在您的项目中(请参阅https://developers.google.com/api-client-library/ java/apis/androidpublisher/v1)

如您所述,您需要一个带有P12文件的服务帐户(客户端库只接受P12文件).

然后,以下代码将验证并很好地获取购买信息:

    HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
    JsonFactory jsonFactory = new JacksonFactory();

    List<String> scopes = new ArrayList<String>();
    scopes.add(AndroidPublisherScopes.ANDROIDPUBLISHER);

    Credential credential = new GoogleCredential.Builder().setTransport(httpTransport).setJsonFactory(jsonFactory)
            .setServiceAccountId(googleServiceAccountId)
            .setServiceAccountPrivateKeyFromP12File(new File(googleServicePrivateKeyPath))
            .setServiceAccountScopes(scopes).build();
    AndroidPublisher publisher = new AndroidPublisher.Builder(httpTransport, jsonFactory, credential).build();
    AndroidPublisher.Purchases purchases = publisher.purchases();
    final Get request = purchases.get(packageName, productId, token);
    final SubscriptionPurchase purchase = request.execute();

    // Do whatever you want with the purchase bean
Run Code Online (Sandbox Code Playgroud)

有关Java客户端身份验证的信息,请访问:https: //developers.google.com/identity/protocols/OAuth2ServiceAccount


归档时间:

查看次数:

16828 次

最近记录:

8 年,3 月 前