Unity iOS端调用PayPal API OAuth2及获取AccessToken报错排查问询
Hey there! Let's tackle your two questions step by step—first, how to call PayPal's OAuth2 API in a Unity-built iOS app, then how to fix those frustrating -999 and -1012 errors that only pop up on iOS.
一、Unity iOS环境下调用PayPal OAuth2接口的实现步骤
1. 准备PayPal开发者凭证
First off, head to the PayPal Developer Dashboard to create a sandbox/production app. Grab your Client ID and Client Secret—keep these secure (don't hardcode them directly in scripts; use ScriptableObjects or Unity's Player Settings custom fields instead).
2. 构建OAuth2 Token请求
PayPal's OAuth2 token endpoint is:
- Sandbox:
https://api-m.sandbox.paypal.com/v1/oauth2/token - Production:
https://api-m.paypal.com/v1/oauth2/token
Key requirements for the request:
- Method:
POST - Authorization header: Base64-encoded string of
{ClientID}:{ClientSecret}(use ASCII encoding, not UTF-8) - Content-Type:
application/x-www-form-urlencoded - Request body:
grant_type=client_credentials
3. Unity代码实现(用UnityWebRequest,替代过时的WWW)
Here's a working coroutine example:
using UnityEngine; using UnityEngine.Networking; using System.Collections; public class PayPalOAuthHandler : MonoBehaviour { [SerializeField] private string paypalClientId; [SerializeField] private string paypalClientSecret; [SerializeField] private bool useSandbox = true; public void RequestAccessToken() { StartCoroutine(FetchAccessTokenCoroutine()); } private IEnumerator FetchAccessTokenCoroutine() { string tokenEndpoint = useSandbox ? "https://api-m.sandbox.paypal.com/v1/oauth2/token" : "https://api-m.paypal.com/v1/oauth2/token"; // Encode credentials for Authorization header string authString = $"{paypalClientId}:{paypalClientSecret}"; string authBase64 = System.Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(authString)); // Setup request UnityWebRequest request = UnityWebRequest.Post(tokenEndpoint, "grant_type=client_credentials"); request.SetRequestHeader("Authorization", $"Basic {authBase64}"); request.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded"); // Send request yield return request.SendWebRequest(); // Handle response if (request.result != UnityWebRequest.Result.Success) { Debug.LogError($"PayPal Token Request Failed: {request.error} | Status Code: {request.responseCode}"); } else { string responseJson = request.downloadHandler.text; Debug.Log($"Success! Access Token Response: {responseJson}"); // Parse the JSON here (use JsonUtility or Newtonsoft.Json to extract access_token) } } }
4. iOS平台关键配置
You'll need to tweak your iOS Info.plist to allow connections to PayPal's servers:
- Add App Transport Security (ATS) exceptions for PayPal's domains (more on this in the error fix section below)
- Add an internet usage description to avoid permission blocks:
<key>NSInternetUsageDescription</key> <string>需要网络连接以处理PayPal支付相关操作</string>
二、iOS部署时AccessToken请求错误(-999/-1012)的排查与解决
Those errors are specific to iOS network restrictions—since Postman and other environments work, the API itself is fine. Let's fix this:
1. Understand the Errors
- Error -999:
NSURLErrorCancelled— The request was abruptly cancelled, usually due to ATS blocking or permission issues. - Error -1012:
NSURLErrorUserCancelledAuthentication— Often a side effect of ATS misconfiguration, not actual user cancellation.
2. Fix App Transport Security (ATS) Configuration
iOS's ATS blocks unsecure or non-compliant HTTPS requests by default. Add these exceptions to your Unity iOS Info.plist (via Player Settings > iOS > Custom iOS Properties):
<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <false/> <key>NSExceptionDomains</key> <dict> <key>api-m.sandbox.paypal.com</key> <dict> <key>NSIncludesSubdomains</key> <true/> <key>NSExceptionRequiresForwardSecrecy</key> <false/> <!-- PayPal's sandbox doesn't always support forward secrecy --> </dict> <!-- Add production domain if needed --> <key>api-m.paypal.com</key> <dict> <key>NSIncludesSubdomains</key> <true/> </dict> </dict> </dict>
Note: Avoid setting NSAllowsArbitraryLoads to true for production builds—Apple may reject your app.
3. Verify Request Credentials & Headers
Double-check:
- Your Base64-encoded auth string is correct (no extra spaces, uses ASCII encoding)
- The
grant_type=client_credentialsbody is properly formatted (no typos) - You're using the correct endpoint (sandbox vs production) that matches your PayPal app credentials
4. Ensure No Unexpected Request Cancellation
Make sure the coroutine running the request isn't interrupted:
- Don't destroy the
PayPalOAuthHandlerobject mid-request - Avoid scene transitions while the request is in flight
5. Debug with Charles Proxy (Optional)
If you're still stuck, use Charles to capture the request from your iOS device and compare it to your working Postman request. Look for differences in headers, parameters, or redirect behavior. Just remember to trust Charles's root certificate on your iOS device (Settings > General > About > Certificate Trust Settings).
内容的提问来源于stack exchange,提问作者Calleth 'Zion'

