reactjsnext.jspaypalvercelpaypal-sandbox

PayPal SDK Next.js cant change to EUR, but working fine in USD


Why isn't it working whenever I change from USD to EUR ?

I changed both:

script.src = `https://www.paypal.com/sdk/js?client-id=${clientId}&currency=EUR`;

and

currency_code: 'USD',

I get this error

Error: Unexpected currency: EUR passed to order.create. Please ensure you are passing /sdk/js?currency=EUR in the paypal script tag. at Object.onError (page.tsx:90:27) at js?client-id=AcU71Ma…kxnSNffvep:3:112468 at js?client-id=AcU71Ma…2kxnSNffvep:3:31136 at n.try (js?client-id=AcU71Ma…2kxnSNffvep:3:17031) at u (js?client-id=AcU71Ma…2kxnSNffvep:3:31114) at Object.trigger (js?client-id=AcU71Ma…2kxnSNffvep:3:31176) at js?client-id=AcU71Ma…kxnSNffvep:3:107739 at n.try (js?client-id=AcU71Ma…2kxnSNffvep:3:17031) at Object.qn (js?client-id=AcU71Ma…kxnSNffvep:3:107669) at js?client-id=AcU71Ma…2kxnSNffvep:3:83158 at e.dispatch (js?client-id=AcU71Ma…2kxnSNffvep:3:14426) at e.then (js?client-id=AcU71Ma…2kxnSNffvep:3:15189) at Object.handler (js?client-id=AcU71Ma…2kxnSNffvep:3:83132) at js?client-id=AcU71Ma…2kxnSNffvep:3:88051 at n.try (js?client-id=AcU71Ma…2kxnSNffvep:3:17031) at bo (js?client-id=AcU71Ma…2kxnSNffvep:3:87867) at Oo (js?client-id=AcU71Ma…2kxnSNffvep:3:89886) at js?client-id=AcU71Ma…2kxnSNffvep:3:95971 at n.try (js?client-id=AcU71Ma…2kxnSNffvep:3:17031) at js?client-id=AcU71Ma…2kxnSNffvep:3:95768 at js?client-id=AcU71Ma…2kxnSNffvep:3:96020

my /app/paypal/page.tsx file with USD :

'use client'

import { useEffect, useState } from 'react';
import { PayPalScriptProvider, PayPalButtons } from '@paypal/react-paypal-js';

const PayPalPage = () => {
  const [scriptLoaded, setScriptLoaded] = useState(false);
  const [paymentSuccess, setPaymentSuccess] = useState(false);
  const [errorMessage, setErrorMessage] = useState('');
  const clientId = process.env.NEXT_PUBLIC_PAYPAL_CLIENT_ID;

  useEffect(() => {
    if (!clientId) {
      console.error('PayPal client ID fehlt');
      return;
    }

    const addPaypalScript = () => {
      const script = document.createElement('script');
      script.src = `https://www.paypal.com/sdk/js?client-id=${clientId}&currency=USD`;
      script.async = true;
      script.onload = () => setScriptLoaded(true);
      document.body.appendChild(script);
    };
    addPaypalScript();
  }, [clientId]);

  if (!clientId) {
    return (
      <div className="bg-gray-100 min-h-screen flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
        <div className="max-w-xl w-full bg-white p-8 rounded-lg shadow-lg">
          <h1 className="text-3xl font-bold text-center text-gray-800 mb-6">
            PayPal client ID fehlt
          </h1>
          <p className="text-center text-gray-600 mb-8">
            Bitte überprüfen Sie die Umgebungsvariable für die PayPal-Client-ID.
          </p>
        </div>
      </div>
    );
  }

  return (
    <div className="bg-gray-100 min-h-screen flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
      <div className="max-w-xl w-full bg-white p-8 rounded-lg shadow-lg">
        <h1 className="text-3xl font-bold text-center text-gray-800 mb-6">
          Test PayPal Kauf
        </h1>
        <p className="text-center text-gray-600 mb-8">
          Bitte tätigen Sie einen Testkauf von 100$ über PayPal.
        </p>

        {/* Erfolgsnachricht */}
        {paymentSuccess && (
          <div className="bg-green-100 text-green-800 p-4 mb-4 rounded-lg text-center">
            <h2 className="text-lg font-bold">Vielen Dank für Ihren Testkauf!</h2>
            <p>Ihre Zahlung von 100$ wurde erfolgreich abgeschlossen. Vielen Dank!</p>
          </div>
        )}

        {/* Fehlermeldung */}
        {errorMessage && (
          <div className="bg-red-100 text-red-800 p-4 mb-4 rounded-lg text-center">
            <h2 className="text-lg font-bold">Ups! Etwas ist schiefgelaufen.</h2>
            <p>{errorMessage}</p>
          </div>
        )}

        {scriptLoaded ? (
          <PayPalScriptProvider options={{ clientId }}>
            <div className="flex justify-center">
              <PayPalButtons
                style={{
                  layout: 'vertical',
                  color: 'blue',
                  shape: 'rect',
                  label: 'paypal',
                }}
                createOrder={(data, actions) => {
                  if (!actions || !actions.order) {
                    console.error('Fehler: actions.order ist nicht definiert');
                    return Promise.reject('Fehler bei der Erstellung der Bestellung');
                  }

                  return actions.order.create({
                    purchase_units: [
                      {
                        amount: {
                          currency_code: 'USD',
                          value: '100.00',
                        },
                      },
                    ],
                    intent: 'CAPTURE'
                  });
                }}
                onApprove={(data, actions) => {
                  if (!actions || !actions.order) {
                    console.error('Fehler: actions.order ist nicht definiert');
                    return Promise.reject('Fehler bei der Genehmigung der Bestellung');
                  }

                  return actions.order.capture().then((details) => {
                    console.log('Zahlung erfolgreich abgeschlossen:', details);
                    setPaymentSuccess(true);  // Zeigt die Erfolgsmeldung an
                    setErrorMessage('');  // Setzt die Fehlermeldung zurück
                    return Promise.resolve();
                  });
                }}
                onError={(err) => {
                  console.error('Fehler bei der PayPal-Zahlung:', err);
                  setErrorMessage('Es gab ein Problem bei Ihrer Zahlung. Bitte versuchen Sie es erneut.'); // Zeigt die Fehlermeldung an
                  setPaymentSuccess(false); // Setzt den Zahlungserfolgsstatus zurück
                }}
              />
            </div>
          </PayPalScriptProvider>
        ) : (
          <div className="text-center text-gray-500">Loading PayPal...</div>
        )}
      </div>
    </div>
  );
};

export default PayPalPage;

my .env file is set

NEXT_PUBLIC_PAYPAL_CLIENT_ID = "12345"
PAYPAL_CLIENT_ID = "12345"
PAYPAL_CLIENT_SECRET = "ABCDEF"

PAYPAL_WEBHOOK_SECRET="XYZ123"

NEXT_PUBLIC_PAYPAL_CLIENT_ID is the same as PAYPAL_CLIENT_ID I'm not sure if its the same because PayPal Dashboard just shows 2 Keys 1 Public 1 Secret and they're both public so doesn't matter. And it is working completely fine with a test account and USD

PayPal tells me on this site https://developer.paypal.com/api/rest/reference/currency-codes/ that EUR is the correct Currency Code so i dont know where my error is

I use Next.js 15 and Downgraded to react 18 because React 19 doesn't support '@paypal/react-paypal-js'; but that doesn't matter either

The User region is Germany in the Sandbox,and shouldnt matter if the customers are in america they should still see the EUR price and the exchange rate to dollar. Not the opposite like now that europeans see dollar price and then see exchange rate


Solution

  • Why are you using both addPayPalScript and <PayPalScriptProvider> ? This is redundant. Only load the script once. If you do it with <PayPalScriptProvider>, as is the react-paypal-js way, its options need the currency EUR to be set correctly matching the backend.

    Furthermore, actions.order.create and related actions.order.* functions are deprecated. These functions should not occur anywhere in your code. Instead, have createOrder fetch from a backend that creates (and from onApprove captures) the order.

    See the standard integration guide for sample code using react and node.js for a backend.