这篇文章讲什么

小心使用 Google OAuth。
因为调用谷歌翻译 API (Cloud Translation) 会造成意外收费问题。
我作为开发者被扣了95美金。以此为鉴。
你看了这篇文章就知道要怎么做才不会被扣钱了。

这篇文章对谁有用?有什么用?

对谁有用?开发者
有什么用?躲坑

通俗解释一下

  • Google OAuth 就是"使用谷歌账号登录"。这个大家见多了。
    国内是"使用微信登录" "使用QQ登录" "使用新浪微博登录"
    国外是 "使用 Facebook 登录", "使用谷歌账号登录" "使用推特登录"

  • 而 OAuth "scope" 就是给多少权限,比如有的 "微信登录" 之后会要你的电话号码。会弹出一个小框,问给不给权限。

背景信息

我做了一个桌面软件。软件可以调用翻译 API,从而翻译字幕文件 (后缀是 .srt .ass .vtt)

目标是什么

让用户能用自己的账号进行谷歌登录,然后翻译字幕文件
产生的花费是扣用户的钱,不是扣我的钱。
(用户在使用之前就知道是要付费的,所以这不是偷偷扣钱)

遇到什么问题

我收到 $95 美金的账单。
截图如下:

价格细节

用了 5 百万多一点的字符数额度

为什么这个扣钱不对

我们来看谷歌的文档

文档1

记住:我们的目标是,让用户以自己的谷歌账号登录,然后调用翻译 API。

那么,先来看看怎么登录。

https://developers.google.com/identity/choose-auth

"桌面应用"看文档有两种选择。

  1. Google Sign-In
  2. Plain OAuth 2.0。

1. Google Sign-In

由于是桌面应用,没有 server。
所以 Google Sign-In 这种针对 Web 端的用不了。
callback 没有线上地址。我们用的是 Electron.js。

2. Plain OAuth 2.0

我们来看看这个 OAuth

4个选项里,只有 Option 2 是合适的。是给 Desktop 用的。
Option 2: Loopback IP address

(讲个题外话:Electron.js 怎么做 Google OAuth 登录这事情卡了我几天,最后是这样实现的: /electron-js-oauth-google/)

文档继续往下看 (Identify access scopes)

这一段说:你要什么权限就写什么 scope。
登录时用户会看得到,用户同意了就有权限。

再看一段 (Calling Google APIs)

拿到 acccess token 之后,
就可以 on behalf of a given user account (以用户的身份)
去调用谷歌 API

我们再来看看 scopes

https://developers.google.com/identity/protocols/googlescopes

scope 里有 "Google Cloud Translation API"

什么意思呢?

可以 OAuth 登录后,以用户身份调用翻译 API。

目前看起来一切良好,没有问题。

但是实测却是我收到 $95 刀的账单。用户翻译的5百万字符算到我的头上了。

解决方法 1:打电话给客服 (结论:不管用,读者不想看可以跳过)

这里选的是 China。

打通之后是北京那边的 Support,不过是以 billing 为主的支持,
技术支持由于是1月2号过年期间不在。
电话总时长20分钟左右,其中大概15分钟都在等对面查信息。

最后结果:没有解决问题。
客服最后的结论是:"一般来说你创建的资源是扣你的钱"

这我明白。但这个是 OAuth,如果是扣我的钱,那干嘛还要问用户的 scope?既然不拿用户的信息也不需要以用户身份进行操作,那这个 Scope 存在有个毛线意义啊?

我试着打一下 United State 的电话。因为下面写的 toll-free。
结果马上说"如果是国外打过来的,就不是免费了" 所以我就没打。

解决方法2:Chat Support (结论:不管用,读者不想看可以跳过)

这是结束后的截图

聊天内容 Email 给我了:

全文:

This is an automated email from Google Cloud Support. Case #21721271 has been created or updated. Here are some details about your case:

Status: Closed
Subject: OAuth + Google Cloud Translation API
Description:
Chat Started: Fri, 3 Jan 2020 16:29:36 +0800
Chat Subject: OAuth + Google Cloud Translation API

Google Cloud Support, Richard: Thank you for contacting Cloud Support. My name is Richard and I'll be working with you today. While I read over your message, is there anything else you'd like to add?

Zheng Cheng: Hi

Zheng Cheng: I am trying to understand a problem relate to OAuth + Google Cloud Translation API

Zheng Cheng: Is anyone there? hello?

Google Cloud Support, Richard: Hello Zheng. I hope you are doing well today. May I know your concerns about OAuth?

Zheng Cheng: Here is my question: After Google OAuth login (user login to my Desktop App) and then user use the Cloud Translation API, Google should charge their money, for using this API

Zheng Cheng: but in fact, it charge me.

Zheng Cheng: which is confusing

Zheng Cheng: I read through document about OAuth again

Zheng Cheng: https://developers.google.com/identity/protocols/OAuth2

Google Cloud Support, Richard: Let me have this checked on my end. Kindly allow me 3 to 5 minutes.

Zheng Cheng: which say, after OAuth, all the request with user's access token, should be on user's behalf

Zheng Cheng: ok

Zheng Cheng: FYI: Cloud Translation API is in the "sensitive" OAuth scope, which mean it require verification from Google. My App is still under review because I haven't got time to set up "Privacy Policy". is this where things go wrong? before verification sensitive scope like Cloud Translation would charge me, but after verification it would charge user(which is expected behavior) is that right? I haven't found any doc talk about this. so I can't be certain if this is true

Zheng Cheng: Thanks for your time Richard, appreciate!

Google Cloud Support, Richard: No worries. It seems that I need more time in checking this. Can you still allow me about 5 to 10 minutes more?

Zheng Cheng: sure, please do

Zheng Cheng: I want figure out what happen, because this cost me $95 dollar

Zheng Cheng: (5 million char+ being translation using Cloud Translation API) 1 million = 20$ dollar, so total $100 - $10 discount per month. I got charged 95$ dollar

Zheng Cheng: my Google account is guokrfans@gmail.com

Zheng Cheng: my billing account is 010B6A-949786-0BDE9E

Zheng Cheng: Let me provide bit more information see if that help

Zheng Cheng: https://developers.google.com/identity/protocols/OAuth2

Zheng Cheng: (In non-service-account scenarios, your application calls Google APIs on behalf of end-users, and user consent is sometimes required.)

Zheng Cheng: quote from document

Zheng Cheng: "calls Google APIs on behalf of end-users"

Zheng Cheng: I am calling Cloud Translation API on behalf of end users. so base on document, it should charge end-user, not me.

Google Cloud Support, Richard: Thank you for providing me these details Zheng. This surely helps. I did check resources on my end and found out that the billing account associated with the project are billed every time a service such as an API is used. Regardless of the manner it was being called.

Google Cloud Support, Richard: Hence this would be the reason on the charges billed to your account.

Zheng Cheng: ok

Zheng Cheng: let me think about it

Zheng Cheng: basically, my end goal is to ask, is there a way let user login with their google account, and use Cloud Translation API themself. because they are the one who using it, so it just charge them directly, Google charge end-user.

Zheng Cheng: so besically you are saying this is impossible?

Zheng Cheng: I have to charge user myself, and then pay money to google, I need to be the middle man

Google Cloud Support, Richard: In general, the charges for a project are billed to the account associated with it. Hence, it is not possible to end users to get billed on their accounts for using your project.

Zheng Cheng: I see.

Zheng Cheng: make some sense

Zheng Cheng: I still hope Google can clearly say that in Document.

Google Cloud Support, Richard: You will have to let your users pay you the amount and in turn, you will be the ones to pay Google.

Zheng Cheng: I see

Zheng Cheng: new question:

Zheng Cheng: The other 8 Translation Service Provider(Amazon/Azure/Yandex/Baidu/Tencent/Caiyun/Xiaoniu/Sogou), They all have "Token" or "API Key" or whatever they call it to auth user. This Google Cloud Translation API seem like can only be used via access token (Which get from Oauth login).so my question is: Is there a way let user to sign up and get some sort of "API key" or "Token" or whatever. and then use that for Cloud Translation API, so they can be charge by Google directly, I don't have to be the middle man

Google Cloud Support, Richard: I'll check additional resources on my end for this. Kindly allow me 5 minutes more.

Zheng Cheng: sure, Thanks

Zheng Cheng: Question 3: this is very confusing to me, since you said "In general, the charges for a project are billed to the account associated with it. Hence, it is not possible to end users to get billed on their accounts for using your project." if so. Oauth should not have a API scope for Cloud Translation, because, What is the point anyway? it charge the OAuth app author anyway, why even ask for consent from user? it's not gonna use their data or behave on their behalf. no point to have this scope and be "sensitive" scope. it doesn't make sense from this stand point you know.

Zheng Cheng: Customer attached 1231231.jpg: https://storage.googleapis.com/esp-prod.appspot.com/12053944146?Signature=JCNuBjFgWMG%2BCjRGO19NwWByQ3oHdBrBw%2BLS0c0%2BSdJAubMbl2oA2cIGdgBIimff9wf14APv9PY9lDsvtqDGu3c%2B3exgLErLa33Lt9b780shrYfXN%2BxIP7eqnRFKpYO8ln1e6nxVE1Ae9n/G3vbeYeZtaXCn6GSG8PGQrR%2B3wJIhBoo76XEK3lDvHZkVcIdfgC0eo2aU3p3GG%2B8dRGR%2BlhkViWek37baLNyV4psm4VMK2MfyDQKMuBRBhKcfYh2N0F7x/9XZmtTuTT3/gPWOhUiZa9YVffWdvbnP8oAFhgMl9Xixh7uBtgbRep1ePtgoiUbHbVu3Va6SOfaDplrxgA%3D%3D&GoogleAccessId=gts-hoolichat-ui@system.gserviceaccount.com&Expires=1578128805

Zheng Cheng: https://developers.google.com/identity/protocols/googlescopes

Zheng Cheng: that just screenshot from the doc

Zheng Cheng: Again, Thanks for take your time to help me. I really appreciate that. I just want figure out why OAuth even have this "cloud-translation" scope if it just charge OAuth app author anyway

Google Cloud Support, Richard: I appreciate you patience with this Zheng. I did check on my end however I am unable to find any reference where an end user can be directly charged on the Google account using a project linked to someone else's billing account. As such, you may have this feature requested via our feature request tracker. You can utilize this link below:

Google Cloud Support, Richard: https://cloud.google.com/support/docs/issue-trackers#trackers-list

Zheng Cheng: I see

Google Cloud Support, Richard: Under the "AI & Machine Learning" section, kindly look for "Create new Cloud Translation issue"

Google Cloud Support, Richard: This will then be addressed by our technical team Zheng.

Zheng Cheng: Got it.

Zheng Cheng: so that solve one problem (how end user can be directly charged ......)

Zheng Cheng: the other problem, OAuth why even have a Cloud Translation scope, is still unsolved

Zheng Cheng: would you mind check this for me?

Google Cloud Support, Richard: Sure.

Zheng Cheng: because it seem like if OAuth have this scope, mean developer can use this scope on user's behalf

Google Cloud Support, Richard: Let me have this checked for you.

Zheng Cheng: ok, Thank you

Zheng Cheng: OAuth scope basically mean "Hi dear user, do you allow this app use you info or behave on your behalf in these scope?" so It's totally reasonable to assume that. if OAuth have cloud-translate scope, it mean I can use cloud translation on user's behalf.

Zheng Cheng: :)

Zheng Cheng: happy new year by the way

Google Cloud Support, Richard: Happy new year Zheng. :) I did look up to this and it seems that I cannot find any specific resource on my end to address your inquiry as why Translate API was included on OAuth scope. You may also include this inquiry once you file a ticket on our issue tracker (the link I provided earlier).

Zheng Cheng: I see,

Zheng Cheng: ok, I will file a ticket on that issue tracker, and ask same question there,

Zheng Cheng: We are done here, Thanks for helping me

Google Cloud Support, Richard: You're very welcome. Thank you also for working with me. Feel free to chat back in if you have any additional questions. There’s a short survey coming up after this chat and we’d love to hear your feedback about our interaction today. Have a great day.

Zheng Cheng: got it

反正,结论是他也没解决。

唯一有用的就是扔了个 URL
https://cloud.google.com/support/docs/issue-trackers#trackers-list

Under the "AI & Machine Learning" section, kindly look for "Create new Cloud Translation issue"

我按 Chat Support 说的,去论坛提问了(2020年1月3号)

https://issuetracker.google.com/issues/147094769

还有 Github 也提问了

https://github.com/googleapis/google-auth-library-nodejs/issues/863

结论:

  1. 电话支持 (Phone Support) 不管用
  2. 聊天支持 (Chat Support) 不管用
  3. 论坛不管用
  4. Github 不管用

2020-1-8 (5天后更新)

邮件支持(Email Support)管用
谷歌愿意给我退款了。

来回一共15封邮件,耗时 2020年1月4号 到 2020年1月8号。共4天。

那15封邮件的内容我在另一篇文章里贴了,这里就不重复了。
可以直接看这篇文章:
/google-oauth-and-google-cloud-api-may-cost-you-money-instead-of-end-user/

文末到了,讲下结论

还好最后谷歌给我退了这 $95 美金

不过,这锅(谁的错)我依然怪谷歌,理由:

  1. 明明文档里说了 OAuth 可以让用户登录

  2. 然后还说 OAuth scope 里有 Cloud Translation,那么就是征求用户同意使用这个 API。

  3. 然后还说可以把用户的 access token 拿去请求 API,这样就可以以用户身份调用。

  4. 实际却是扣我的钱,仔细邮件问了,原来是要求用户在 Google Cloud 后台里绑定付费账号信息。
    这不扯淡呢吗,用第三方登录就是为了简单,你这样一搞要求 7 steps(具体看另一篇文章里邮件截图) 这一点都不简单。

  5. 而且,如果扣不到用户的钱是直接扣开发者的钱,我勒个去。

正确的做法应该是

  1. 用户登录时,上面写着要求翻译 API 权限(就像现在这样)
    但是补充文字:
    "请注意翻译 API 是要付钱的"
    "您当前没有绑定付费信息,因此无法使用翻译 API "
  2. 带着这个用户的 access_token 去请求 API 时,不应该允许,应该报错。
    说该用户没有绑定付费信息。而不是扣开发者的钱。

全文完

感谢阅读