PayPal API 错误 - 尝试检索 Paypal 电子邮件地址和验证状态 |错误 400

问题描述 投票:0回答:1

我试图让我的应用程序使用 React,尝试检索用户的 PayPal 电子邮件地址,但我所做的一切都会返回“错误 400 - 错误请求 - 无法获取详细信息来服务请求”。

知道为什么吗?我已经仔细检查了 PayPal 中的返回 URI,以及我的客户/秘密 ID。

我的后端:

export const handlePaypalOAuthCallback = async (req, res) => {
  try {
    const { code, state } = req.query;
    console.log('PayPal callback received:', { 
      code: code ? 'present' : 'missing',
      state: state ? 'present' : 'missing',
      fullQuery: req.query 
    });
    
    if (!code) {
      throw new Error('Authorization code not received');
    }

    if (!state) {
      throw new Error('User ID not received in state parameter');
    }

    const CLIENT_ID = "xxx";
    const CLIENT_SECRET = "xxx";
    
    if (!CLIENT_ID || !CLIENT_SECRET) {
      console.error('Missing PayPal credentials');
      throw new Error('Server configuration error');
    }

    const auth = Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString('base64');

    console.log('Preparing token request:', {
      url: 'https://api-m.sandbox.paypal.com/v1/oauth2/token',
      grantType: 'authorization_code',
      hasCode: !!code,
      hasAuth: !!auth,
      redirectUri: '<my return uri>/api/paypal/oauth/callback'
    });

    const params = new URLSearchParams();
    params.append('grant_type', 'authorization_code');
    params.append('code', code);
    params.append('redirect_uri', 'http://dev.gotasker.com.au:4000/api/paypal/oauth/callback');
    // Add these additional parameters
    params.append('scope', 'openid email');
    params.append('client_id', CLIENT_ID);
    params.append('client_secret', CLIENT_SECRET);

    try {
      // Get access token
      const tokenResponse = await axios.post(
        'https://api-m.sandbox.paypal.com/v1/oauth2/token', 
        params,
        {
          headers: {
            'Authorization': `Basic ${auth}`,
            'Content-Type': 'application/x-www-form-urlencoded',
            'PayPal-Request-Id': `${Date.now()}`,
            'Accept': 'application/json',
            'Accept-Language': 'en_US'
          }
        }
      );

      console.log('Token response received:', {
        hasAccessToken: !!tokenResponse.data.access_token,
        tokenType: tokenResponse.data.token_type,
        scope: tokenResponse.data.scope,
        status: tokenResponse.status,
        headers: tokenResponse.headers
      });

      const accessToken = tokenResponse.data.access_token;

      // Log token details for debugging (first few chars only)
      console.log('Access token details:', {
        prefix: accessToken.substring(0, 10),
        length: accessToken.length,
        tokenType: tokenResponse.data.token_type
      });

      if (!accessToken || typeof accessToken !== 'string') {
        throw new Error('Invalid access token received from PayPal');
      }

      // Make the userInfo request with proper authorization header
      const userInfoResponse = await axios.get(
        'https://api-m.sandbox.paypal.com/v1/identity/oauth2/userinfo',  // Changed URL
        {
          headers: {
            'Authorization': `Bearer ${accessToken}`,
            'Content-Type': 'application/json',
            'Accept': 'application/json',
            'PayPal-Request-Id': `${Date.now()}`,
          },
        }
      );

      // Log successful userInfo response
      console.log('User info response received:', {
        status: userInfoResponse.status,
        hasData: !!userInfoResponse.data,
        dataKeys: Object.keys(userInfoResponse.data)
      });

      const paypalEmail = userInfoResponse.data.email;
      
      if (!paypalEmail) {
        throw new Error('PayPal email not received in user info response');
      }

      // Update user with PayPal email
      const userId = state;
      const user = await UserModel.findById(userId);
      if (!user) {
        throw new Error('User not found');
      }

      user.paypalEmail = paypalEmail;
      user.paypalVerified = true;
      await user.save();

      console.log('User PayPal email updated successfully:', {
        userId: user._id,
        verified: true
      });

      // Redirect back to frontend with success
      res.redirect(`${process.env.FRONTEND_URL}/account?paypal=success`);
      
    } catch (error) {
      // Enhanced error logging
      console.error('API request failed:', {
        status: error.response?.status,
        statusText: error.response?.statusText,
        data: error.response?.data,
        message: error.message,
        headers: error.response?.headers,
        config: {
          url: error.config?.url,
          method: error.config?.method,
          headers: {
            ...error.config?.headers,
            Authorization: error.config?.headers?.Authorization 
              ? `${error.config.headers.Authorization.substring(0, 10)}...` 
              : 'missing'
          }
        },
        wwwAuthenticate: error.response?.headers?.['www-authenticate']
      });
      throw error;
    }

  } catch (error) {
    console.error('PayPal OAuth error:', {
      message: error.message,
      response: error.response?.data,
      status: error.response?.status,
      statusText: error.response?.statusText
    });
    res.redirect(`${process.env.FRONTEND_URL}/account?paypal=error&message=${encodeURIComponent(error.message)}`);
  }
};

我的前端:

const PayPalLoginCard = () => {
  const { user, updateUserProfile } = useContext(AuthContext);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState('');
  const [successMessage, setSuccessMessage] = useState('');
  const location = useLocation();
  const navigate = useNavigate();

  useEffect(() => {
    // Handle OAuth response
    const searchParams = new URLSearchParams(location.search);
    const paypalStatus = searchParams.get('paypal');
    
    if (paypalStatus === 'success') {
      setSuccessMessage('PayPal account connected successfully');
      // Remove query params
      navigate('/account', { replace: true });
    } else if (paypalStatus === 'error') {
      setError(searchParams.get('message') || 'Failed to connect PayPal account');
      navigate('/account', { replace: true });
    }
  }, [location, navigate]);
 
  const handlePayPalLogin = () => {
    try {
      const PAYPAL_CLIENT_ID = "xx";
      const REDIRECT_URI = 'http://dev.gotasker.com.au:4000/api/paypal/oauth/callback';
      
      const userId = user?.id;
      if (!userId) {
        throw new Error('User ID not available');
      }
  
      // Updated scopes and parameters
      const scopes = 'openid email';
      const authUrl = `https://www.sandbox.paypal.com/signin/authorize?client_id=${PAYPAL_CLIENT_ID}&response_type=code&scope=${scopes}&redirect_uri=${encodeURIComponent(REDIRECT_URI)}&state=${userId}&nonce=${Date.now()}`;
      
      window.location.href = authUrl;
    } catch (error) {
      console.error('Error initiating PayPal login:', error);
      setError(error.message || 'Failed to initiate PayPal login');
    }
  };

  const handleDisconnect = async () => {
    setIsLoading(true);
    setError('');
    setSuccessMessage('');
    
    try {
      const response = await axios.post(
        'http://dev.gotasker.com.au:4000/api/paypal/disconnect',
        {},
        {
          headers: {
            Authorization: `Bearer ${localStorage.getItem('token')}`,
          },
        }
      );
      
      if (response.data.success) {
        await updateUserProfile({ paypalEmail: null });
        setSuccessMessage('PayPal account disconnected successfully');
      }
    } catch (error) {
      setError('Failed to disconnect PayPal account');
    } finally {
      setIsLoading(false);
    }
  };

我已经验证了我的客户端/秘密 ID,我已经三次检查了我的返回 URI。

javascript reactjs paypal
1个回答
0
投票

<[电子邮件受保护] ><4180068332><01783438295><

© www.soinside.com 2019 - 2024. All rights reserved.