如何将Postman授权POST转为VBA JSON POST并解决invalid_grant错误
我用Postman向Google发送授权请求获取access token,在Authorization选项卡填完所有必填信息并点击Get New Access Token按钮后,成功拿到了返回的access token,说明数据有效且Google项目配置正确。现在要把这个请求转成VBA代码。
查看Postman日志能看到发送给Google的数据和返回的响应。我写了如下VBA代码复现请求(redirect_uri已经设为Google项目中批准的本地地址):
Dim sClient_ID As String Dim sClient_Secret As String Dim sGrant_Type As String Dim sCode As String Dim sRedirect_URI As String sClient_ID = "{the client id that google provided to me}" sClient_Secret = "{the client secret that google provided to me}" sGrant_Type = "authorization_code" sCode = "4/0AWtgzh75ZFps55t9vPx-gm_rm8W_uyWQbZwBF1qTLthpUuPjaAXBr9iywT-RweVvagcGPg" sRedirect_URI = "https://localhost:8080" ' build the json string which will be sent to get the google access token Dim a As New Scripting.Dictionary a.Add "grant_type", sGrant_Type a.Add "code", sCode a.Add "redirect_uri", sRedirect_URI a.Add "client_id", sClient_ID a.Add "client_secret", sClient_Secret Dim Json_Get_Access_Token As String Json_Get_Access_Token = JsonConverter.ConvertToJson(a, Whitespace:=" ") ' send the json string via POST Set httpCall = CreateObject("MSXML2.ServerXMLHTTP") Dim sTokenURL As String sTokenURL = "https://oauth2.googleapis.com/token" httpCall.Open "POST", sTokenURL, False httpCall.setRequestHeader "Content-Type", "application/json;charset=UTF-8" httpCall.Send Json_Get_Access_Token Dim sReturnToken As String sReturnToken = httpCall.responseText
运行代码后,sReturnToken返回错误:
{ "error": "invalid_grant", "error_description": "Bad Request" }
请问哪里配置错了?
出现invalid_grant错误,结合你的场景,主要排查以下几个点:
1. 请求格式不匹配
Google OAuth2的token端点不接受JSON格式的请求体,需要用application/x-www-form-urlencoded(表单键值对)格式。Postman在发送请求时,默认会把Authorization选项卡的参数转成表单格式发送,而你的VBA代码用了JSON格式,这是核心问题。
修改VBA代码,把请求体改成表单格式:
Dim sClient_ID As String Dim sClient_Secret As String Dim sGrant_Type As String Dim sCode As String Dim sRedirect_URI As String sClient_ID = "{the client id that google provided to me}" sClient_Secret = "{the client secret that google provided to me}" sGrant_Type = "authorization_code" sCode = "4/0AWtgzh75ZFps55t9vPx-gm_rm8W_uyWQbZwBF1qTLthpUuPjaAXBr9iywT-RweVvagcGPg" sRedirect_URI = "https://localhost:8080" ' 构建表单格式请求体,需URL编码避免特殊字符问题 Dim formData As String formData = "grant_type=" & URLEncode(sGrant_Type) & _ "&code=" & URLEncode(sCode) & _ "&redirect_uri=" & URLEncode(sRedirect_URI) & _ "&client_id=" & URLEncode(sClient_ID) & _ "&client_secret=" & URLEncode(sClient_Secret) ' 发送POST请求 Set httpCall = CreateObject("MSXML2.ServerXMLHTTP") Dim sTokenURL As String sTokenURL = "https://oauth2.googleapis.com/token" httpCall.Open "POST", sTokenURL, False httpCall.setRequestHeader "Content-Type", "application/x-www-form-urlencoded" httpCall.Send formData Dim sReturnToken As String sReturnToken = httpCall.responseText
添加URL编码函数处理特殊字符:
Function URLEncode(str As String) As String Dim objURL As Object Set objURL = CreateObject("MSXML2.XMLHTTP") URLEncode = objURL.encodeURIComponent(str) Set objURL = Nothing End Function
2. Authorization Code已过期或被使用
Google的Authorization Code是一次性的,只能使用一次。如果Postman已经用过这个code获取过token,VBA再用同一个code就会返回invalid_grant。
- 解决方法:重新生成新的Authorization Code后再用VBA请求。
3. Redirect URI完全匹配问题
确保VBA中的sRedirect_URI和Postman使用的、Google项目中配置的完全一致,包括协议(http/https)、端口、路径,不能有任何差异(比如末尾是否带斜杠)。
4. 系统时间偏差过大
如果本地系统时间和Google服务器时间偏差超过5分钟,也会触发invalid_grant错误。检查并同步本地系统时间即可。
内容的提问来源于stack exchange,提问作者Jonathan Small

