PayPal

PayPal

PayPal is a platform that acts as an intermediary in online payment transactions, allowing users to make and receive payments securely and quickly.

In essence, PayPal simplifies the digital payment process by providing a secure, global, and convenient experience for buyers and sellers.


Supported operations

OperationDescription
✅ Payment authorizationBlocks funds on the customer's card.
✅ Payment captureCompletes the transaction and transfers the funds.
✅ Direct paymentCombines authorization and capture in one step.
✅ RefundReturns the full amount of a transaction.
✅ Partial refundReturns part of the captured amount.
✅ Authorization cancellationReverses an authorization that was not captured.

Integration

1. Configure PayPal as a payment method

To integrate PayPal, you must first perform a series of configurations from the OrkestaPay portal. Visit our Providers configuration guide and find the PayPal payment method.


2. Implement payment button

To tokenize the payment data, follow these steps:

  1. Include OrkestaPay scripts: Use the OrkestaPay scripts in your web application.
  2. Initialize parameters: Define the OrkestaPay credentials here, as well as data related to the payment to be processed.
  3. Render the payment button: Place the PayPal button in your frontend.

Required resources:

CSS

<link
  rel="stylesheet"
  href="https://resources.orkestapay.com/payment-methods/styles.css"
  integrity="sha384-5/NLomvLQk75JVAmEdaNkdkgLavuAlRS256szA++bmuw6Zph/wFYlWFHz9Fss7JF"
  crossorigin="anonymous"
/>

JS

<script
  src="https://resources.orkestapay.com/js/orkestapay.js"
  integrity="sha384-lQoLMYDY2Cz/Y+8BLiNbhfLVHWawqsA/gE/8WRTpF6ZS3EABNKXhrq/0bBu4M1aI"
  crossorigin="anonymous"
></script>

<script
  src="https://resources.orkestapay.com/payment-methods/main.js"
  integrity="sha384-hvoIO7IyazX+Cc2LqBdHXx7Z3tq766248YzywLTN+D6f41Lub/VHUh2Pe5Q7WKfA"
  crossorigin="anonymous"
></script>

Code example

In the following code snippet there are certain parameters that need to be replaced with your merchant data:

  • public_key : Public key; these credentials can be obtained from the OrkestaPay portal.
  • merchant_id: Merchant ID; these credentials can be obtained from the OrkestaPay portal.
  • is_sandbox: Defines whether the credentials you are about to use are for testing or production.

In this example, sensitive credentials are captured in a form. These credentials must be handled from the backend.

  • client_id : This key, together with the secret key, will allow authentication to communicate with the OrkestaPay API. It is used on the server.
  • client_secret: This key, together with the access key, will allow authentication to communicate with the OrkestaPay API. It is used on the server.
📘

INFORMATION

To consult OrkestaPay credentials, you can visit our guide Get API keys.


<!DOCTYPE html>
<html lang="en">
  <head>
    <base href="/" />
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="apple-touch-icon" type="image/x-icon" href="favicon.ico" />
    <link rel="icon" type="image/x-icon" href="favicon.ico" />
    <title>PayPal web component</title>
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
      integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"
      crossorigin="anonymous"
    />
    <link rel="stylesheet" href="https://resources.orkestapay.com/payment-methods/styles.css" />
    <style>
      .code {
        color: inherit;
        overflow-wrap: break-word;
        white-space: pre-wrap;
      }
    </style>
  </head>
  <body>
    <main class="container">
      <section class="row mt-5">
        <h1 id="card-title" class="col-12 text-center">OrkestaPay payment method PayPal web component</h1>
      </section>

      <section class="row">
        <article class="col-12 col-md-6 offset-md-3">
          <div class="row">
            <section class="pt-3 col-12 col-md-6">
              <label for="client-id" class="form-label"> OrkestaPay client ID&nbsp;<span class="text-danger">*</span> </label>
              <input type="text" id="client-id" class="form-control" />
              <small id="client-id-error" class="text-danger">&nbsp;</small>
            </section>

            <section class="pt-3 col-12 col-md-6">
              <label for="client-secret" class="form-label"> OrkestaPay client secret&nbsp;<span class="text-danger">*</span> </label>
              <input type="password" id="client-secret" class="form-control" />
              <small id="client-secret-error" class="text-danger">&nbsp;</small>
            </section>
          </div>
        </article>
        <article id="button-container" class="col-12 col-md-6 offset-md-3"></article>
        <article class="pt-3 col-12">
          <div id="payment-details" class="w-100 alert" role="alert"></div>
        </article>
      </section>
    </main>

    <noscript> Please enable JavaScript to continue using this application. </noscript>

    <script type="text/javascript" src="https://resources.orkestapay.com/js/orkestapay.js"></script>
    <script type="text/javascript" src="https://resources.orkestapay.com/payment-methods/main.js"></script>
    <script type="text/javascript">
      //#region FRONTEND

      let orkestaPay;
      let paymentId = null;

      const clientId = document.getElementById("client-id");
      const clientSecret = document.getElementById("client-secret");

      const { public_key, merchant_id, is_sandbox, country_code, currency, amount } = initValues();

      (async function main() {
        orkestaPay = initOrkestaPay({ is_sandbox, merchant_id, public_key });

        const payPalButton = document.createElement("orkestapay-paypal-button");
        await customElements.whenDefined("orkestapay-paypal-button");

        payPalButton.params = {
          payment_details: { currency, createPayment, confirmPayment },
          theme: {
            color: "gold",
            height: 48,
            shape: "rect",
          },
        };

        const container = document.getElementById("button-container");
        container.appendChild(payPalButton);
      })();

      function handlePaymentCreated(payment) {
        const code = document.createElement("code");
        code.innerHTML = JSON.stringify(payment, null, 2);
        code.classList.add("code");

        const paymentDetails = document.getElementById("payment-details");
        paymentDetails.classList.add("alert-success");
        paymentDetails.replaceChildren(code);

        paymentId = payment.payment_id;
        return paymentId ?? null;
      }

      function initValues() {
        const url = new URL(window.location.href);
        return {
          public_key: "<REPLACE_WITH_YOUR_PUBLIC_KEY>",
          merchant_id: "<REPLACE_WITH_YOUR_MERCHANT_ID>",
          is_sandbox: true,
          country_code: "MX",
          currency: "MXN",
          amount: "100.00",
        };
      }

      //#endregion FRONTEND

      //#region BACKEND

      async function createPayment(paymentMethod) {
        if (!paymentMethod) return null;
        const { payment_method_id } = paymentMethod;

        const order = await createOrder();
        if (!order) return null;
        const { order_id } = order;

        const deviceInfo = await orkestaPay.getDeviceInfo();
        if (!deviceInfo) return;
        const { device_session_id } = deviceInfo;

        const url = `${orkestaPay.getApiUrl()}/v1/payments`;
        const Authorization = await authenticate();
        const body = JSON.stringify({
          payment_source: { type: "PAYPAL", payment_method_id },
          device_session_id,
          order_id,
        });

        return fetch(url, {
          method: "POST",
          headers: {
            Authorization,
            "Content-Type": "application/json",
            "Idempotency-Key": crypto.randomUUID(),
          },
          body,
        })
          .then(handleFetchResponse)
          .then(handlePaymentCreated)
          .catch(handleFetchError);
      }

      async function confirmPayment() {
        if (!paymentId) return;

        const url = `${orkestaPay.getApiUrl()}/v1/payments/${paymentId}/confirm`;
        const Authorization = await authenticate();
        const body = JSON.stringify({});

        return fetch(url, {
          method: "POST",
          headers: {
            Authorization,
            "Content-Type": "application/json",
            "Idempotency-Key": crypto.randomUUID(),
          },
          body,
        })
          .then(handleFetchResponse)
          .then(handlePaymentCreated)
          .catch(handleFetchError);
      }

      async function createOrder() {
        const url = `${orkestaPay.getApiUrl()}/v1/orders`;
        const Authorization = await authenticate();
        const body = JSON.stringify({
          merchant_order_id: crypto.randomUUID(),
          subtotal_amount: amount,
          total_amount: amount,
          country_code,
          customer: {
            email: "[email protected]",
          },
          currency,
          products: [
            {
              product_id: crypto.randomUUID(),
              quantity: 1,
              unit_price: amount,
              name: "A random product",
            },
          ],
        });

        return fetch(url, {
          method: "POST",
          headers: { Authorization, "Content-Type": "application/json" },
          body,
        })
          .then(handleFetchResponse)
          .catch(handleFetchError);
      }

      async function authenticate() {
        const url = `${orkestaPay.getApiUrl()}/v1/oauth/tokens`;
        const body = JSON.stringify({
          client_id: clientId.value.trim(),
          client_secret: clientSecret.value.trim(),
          grant_type: "client_credentials",
        });

        const response = await fetch(url, {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body,
        })
          .then(handleFetchResponse)
          .catch(handleFetchError);
        if (!response) return null;

        const { token_type, access_token } = response;
        return `${token_type} ${access_token}`;
      }

      function handleFetchResponse(response) {
        return response.ok ? response.json() : Promise.reject(body);
      }

      function handleFetchError(error) {
        console.error(error);
        return null;
      }

      //#endregion BACKEND
    </script>
  </body>
</html>
📘

NOTE

This code is for demonstration purposes only, integrating frontend code and code that should be executed from a backend. Therefore, it is your responsibility to implement with best practices.


Code explanation

Initial Variables and Functions

  • orkestaPay: Main object to interact with the OrkestaPay API.
  • paymentId: Stores the current payment ID.
  • initValues(): Initial configuration, such as keys and transaction details (amount, currency, etc.).

main function

  • Self-executing function that:
    1. Initializes OrkestaPay with initial values.
    2. Creates a PayPal button as a Web Component (<orkestapay-paypal-button>).
    3. Configures button parameters:
      • payment_details: Defines functions to create and confirm payments.
      • theme: Visual customization (color, shape, height).
    4. Adds the button to the container (button-container).

Backend operations

Authentication (authenticate)
  • Generates an access token:
    • Sends the client credentials (client_id and client_secret) to the API.
    • Returns a token used to authorize requests.

Order registration (createOrder)
  • Creates a new order:
    • Includes basic information such as total amount, currency, and products (fictional in this case).

Payment creation (createPayment)
  • Receives a payment method (paymentMethod).
  • Steps:
    1. Registers an order (createOrder).
    2. Obtains device information.
    3. Sends a POST request to the API to create a payment.
    4. Handles the response and updates the payment details (handlePaymentCreated).

Payment confirmation (confirmPayment)
  • Confirms the previously created payment via its paymentId.

Response and error handling

  • handleFetchResponse(response): Returns the response body if successful; otherwise, rejects the promise.
  • handleFetchError(error): Displays errors in the console.

Testing

To complete an integration test you must have a personal PayPal sandbox account.

📘

NOTE

For more information about testing with PayPal, refer to their official documentation: https://developer.paypal.com/tools/sandbox/



Did this page help you?