# Upgrade to Fastlane (/v5/fastlane/upgrade)



## Know before you code [#know-before-you-code]

> **Info:** ### Get sandbox account information [#get-sandbox-account-information]
>
> Complete the steps in Get started to get the following sandbox account information from the Developer Dashboard:
>
> * Your client ID. Use your client ID when adding payment options to your website.
> * Your personal and business sandbox accounts. Use sandbox accounts to test checkout options.
>
> [Dashboard](/dashboard/)

> **Info:** ### Verify sandbox account setup [#verify-sandbox-account-setup]
>
> This integration requires a sandbox business account. The sandbox account should automatically be set up for Fastlane, but to confirm:
>
> 1. Log into the [PayPal Developer Dashboard](/dashboard/), toggle **Sandbox**, and go to **Apps & Credentials**.
> 2. In **REST API apps**, select or create an app.
> 3. Go to **Features** > **Accept payments**.
> 4. Check if Fastlane and Vault are enabled. If not, select the **Fastlane** and **Vault** checkboxes and select &#x2A;*Save Changes.**

If you have a PayPal or cards integration with the Orders v2 API, you can upgrade to Fastlane.

## Upgrade PayPal [#upgrade-paypal]

## 1. Update existing script [#1-update-existing-script]

The following is the script for the PayPal button:

```javascript lineNumbers
<script src="https://www.paypal.com/sdk/js?components=buttons&client-id=<%= clientId %>"></script>
```

Add the Fastlane option and pass the `data-sdk-client-token` and `data-client-metadata-id` to the `components` section of your script:

```javascript lineNumbers
<script
  src="https://www.paypal.com/sdk/js?client-id=<CLIENT-ID>>&components=buttons,fastlane"
  data-sdk-client-token="<SDK_CLIENT_TOKEN>"
  data-client-metadata-id="<CM_ID>">
</script>
```

## 2. Capture email address [#2-capture-email-address]

In addition to displaying PayPal as an upstream presentment option, be sure to display a field to collect the payer's email address. After collecting the email address, use the following code to determine whether the email is associated with a Fastlane profile or belongs to a PayPal member.

```javascript lineNumbers
const {
  customerContextId
} = await identity.lookupCustomerByEmail(document.getElementById("email").value);
```

## 3. Determine if Fastlane profile is associated with email [#3-determine-if-fastlane-profile-is-associated-with-email]

If the user is determined to have a Fastlane profile, they must authenticate before Fastlane retrieves their saved payment information and address. They are presented with a screen to authenticate themselves by entering an OTP sent to their registered mobile number.

```javascript lineNumbers
const {
  customerContextId
} = await identity.lookupCustomerByEmail(document.getElementById("email").value);
var renderFastlaneMemberExperience = false;
if (customerContextId) {
  // Email is associated with a Fastlane member or a PayPal member,
  // send customerContextId to trigger the authentication flow.
  const {
    authenticationState,
    profileData
  } = await identity.triggerAuthenticationFlow(customerContextId);
  if (authenticationState === "succeeded") {
    // Fastlane member successfully authenticated themselves
    // profileData contains their profile details
    renderFastlaneMemberExperience = true;
    const name = profileData.name;
    const shippingAddress = profileData.shippingAddress;
    const card = profileData.card;
  } else {
    // Member failed or cancelled to authenticate. Treat them as a guest payer
    renderFastlaneMemberExperience = false;
  }
} else {
  // No profile found with this email address. This is a guest payer
  renderFastlaneMemberExperience = false;
}
```

If you want to render a shipping address:

```javascript lineNumbers
if (renderFastlaneMemberExperience) {
  if (profileData.shippingAddress) {
    // render shipping address from the profile
    const changeAddressButton = document.getElementById("your-change-address-button");
    changeAddressButton.addEventListener("click", async () => {
      const {
        selectedAddress,
        selectionChanged
      } = await profile.showShippingAddressSelector();
      if (selectionChanged) {
        // selectedAddress contains the new address
      } else {
        // selection modal was dismissed without selection
      }
    });
  } else {
    // render your shipping address form
  }
} else {
  // render your shipping address form
}
```

## 4. Populate info for Fastlane members [#4-populate-info-for-fastlane-members]

If the user is identified as a Fastlane user, use the following code to prefill the card and shipping address:

```javascript lineNumbers
const shippingAddress = {
  name: {
    firstName: "Jen",
    lastName: "Smith"
  },
  address: {
    addressLine1: "1 E 1st St",
    addressLine2: "5th Floor",
    adminArea1: "Bartlett",
    adminarea2: "IL",
    postalCode: "60103",
    countryCode: "US",
    phone: "16503551233"
  }
};
const options = {
  fields: {
    phoneNumber: {
      // Example of how to prefill the phone number field in the FastlanePaymentComponent
      prefill: "4026607986"
    }
  },
  styles: {
    root: {   //specify styles here
      backgroundColorPrimary: "#ffffff"
    }
  }
};
const fastlanePaymentComponent = await fastlane.FastlanePaymentComponent({
    options,
    shippingAddress
  });
fastlanePaymentComponent.render("#payment-container");
// event listener when the user clicks to place the order
const submitButton = document.getElementById("submit-button");
submitButton.addEventListener("click", async ()=> {
  const { id } = await fastlanePaymentComponent.getPaymentToken();
  // Send the paymentToken and previously captured device data to server
  // to complete checkout
});
```

## 5. Collect info from guest user [#5-collect-info-from-guest-user]

You can use the quick start integration to collect payment and billing information.

Add the `FastlanePaymentComponent` to the div container and create a button to submit the information gathered from `FastlanePaymentComponent` .

```html lineNumbers
<!-- Div container for the Payment Component -->
    <div id="payment-container"></div>
    <!-- Submit Button -->
    <button id="submit-button">Submit Order</button>
```

Collect the shipping address and prefill the phone number field:

```javascript lineNumbers
const shippingAddress = {
      name: {
        firstName: "Jen",
        lastName: "Smith"
      },
      address: {
        addressLine1: "1 E 1st St",
        addressLine2: "5th Floor",
        adminArea1: "Bartlett",
        adminarea2: "IL",
        postalCode: "60103",
        countryCode: "US",
        phone: "16503551233"
      }
    };
    const options = {
      fields: {
        phoneNumber: {
          // Example of how to prefill the phone number field in the FastlanePaymentComponent
          prefill: "4026607986"
        }
      },
      styles: {
        root: {   //specify styles here
          backgroundColorPrimary: "#ffffff"
        }
      }
    };
    const fastlanePaymentComponent = await fastlane.FastlanePaymentComponent({
        options,
        shippingAddress
      });
    fastlanePaymentComponent.render("#payment-container");
    // event listener when the user clicks to place the order
    const submitButton = document.getElementById("submit-button");
    submitButton.addEventListener("click", async ()=> {
      const { id } = await fastlanePaymentComponent.getPaymentToken();
      // Send the paymentToken and previously captured device data to server
      // to complete checkout
    });
```

## 6. Integrate server side [#6-integrate-server-side]

You can use the orders API request that you have built on the server side to pass the payment, billing, and shipping address information to capture the transaction:

```bash lineNumbers
curl -v -k -X POST 'https://api-m.sandbox.paypal.com/v2/checkout/orders' \
 -H 'PayPal-Request-Id: UNIQUE_ID' \
 -H 'Authorization: Bearer PAYPAL_ACCESS_TOKEN' \
 -H 'Content-Type: application/json' \
 -H 'PayPal-Client-Metadata-Id: <CM_ID>' \
 -d '{
      "intent": "CAPTURE",
      "payment_source": {
        "card": {
          "single_use_token": "1h371660pr490622k" //paymentToken from the client
        }
      },
      "purchase_units": [
        {
          "amount": {
            "currency_code": "USD",
            "value": "50.00",
            "breakdown": {
              "item_total": {
                "currency_code": "USD",
                "value": "40.00"
              },
              "shipping": {
                "currency_code": "USD",
                "value": "10.00"
              }
            }
          },
          "items": [
            {
              "name": "Coffee",
              "description": "1 lb Kona Island Beans",
              "sku": "sku03",
              "unit_amount": {
                "currency_code": "USD",
                "value": "40.00"
              },
              "quantity": "1",
              "category": "PHYSICAL_GOODS",
              "image_url": "https://example.com/static/images/items/1/kona_coffee_beans.jpg",
              "url": "https://example.com/items/1/kona_coffee_beans",
              "upc": {
                "type": "UPC-A",
                "code": "987654321015"
              }
            }
          ],
          "shipping": {
            "type": "SHIPPING",
            "name": {
              "full_name": "Lawrence David"
            },
            "address": {
              "address_line_1": "585 Moreno Ave",
              "admin_area_2": "Los Angeles",
              "admin_area_1": "CA", //must be sent in 2-letter format
              "postal_code": "90049",
              "country_code": "US"
            },
            "phone_number": {
              "country_code": "1",
              "national_number": "5555555555"
            }
          }
        }
      ]
    }'
```

## 7. Test your integration [#7-test-your-integration]

After upgrading to Fastlane, test your integration in the [sandbox environment](/sandbox-testing/overview). For information on simulating successful payments and generating card errors, refer to [Card testing](/sandbox-testing/card-testing).

To test your Fastlane integration, refer to the [Fastlane integration testing guide](/platforms/checkout/fastlane/integrate).

## 8. Go live [#8-go-live]

If you have fulfilled the requirements for accepting payments via Fastlane for your business account, you can [Move your app to production](/api/rest/production/).

## Upgrade Card [#upgrade-card]

## 1. Update existing script [#1-update-existing-script-1]

The existing script for card fields for your integration may be similar to the following:

```javascript lineNumbers
<script src="https://www.paypal.com/sdk/js?components=buttons,card-fields&client-id=<%= clientId %>"></script>
```

Add the Fastlane option and pass the `data-sdk-client-token` and `data-client-metadata-id` to the `components` section of your script:

```javascript lineNumbers
<script
  src="https://www.paypal.com/sdk/js?client-id=<CLIENT-ID>>&components=buttons,fastlane"
  data-sdk-client-token="<SDK_CLIENT_TOKEN>"
  data-client-metadata-id="<CM_ID>">
</script>
```

## 2. Capture email address [#2-capture-email-address-1]

Display a field to collect an email address. After collecting the email address, use the following code to determine whether the email is associated with a Fastlane profile or belongs to a PayPal member.

```javascript lineNumbers
const {
  customerContextId
} = await identity.lookupCustomerByEmail(document.getElementById("email").value);
```

## 3. Determine if Fastlane profile is associated with email [#3-determine-if-fastlane-profile-is-associated-with-email-1]

If the user is determined to have a Fastlane profile, they must authenticate before Fastlane retrieves their saved payment information and address associated with their profile. They are presented with a screen to authenticate themselves by entering an OTP sent to their registered mobile number.

```javascript lineNumbers
const {
  customerContextId
} = await identity.lookupCustomerByEmail(document.getElementById("email").value);

var renderFastlaneMemberExperience = false;

if (customerContextId) {
  // Email is associated with a Fastlane member or a PayPal member,
  // send customerContextId to trigger the authentication flow.
  const {
    authenticationState,
    profileData
  } = await identity.triggerAuthenticationFlow(customerContextId);

  if (authenticationState === "succeeded") {
    // Fastlane member successfully authenticated themselves
    // profileData contains their profile details

    renderFastlaneMemberExperience = true;

    const name = profileData.name;
    const shippingAddress = profileData.shippingAddress;
    const card = profileData.card;
  } else {
    // Member failed or cancelled to authenticate. Treat them as a guest payer
    renderFastlaneMemberExperience = false;
  }
} else {
  // No profile found with this email address. This is a guest payer
  renderFastlaneMemberExperience = false;
}
```

If you want to render a shipping address:

```javascript lineNumbers
if (renderFastlaneMemberExperience) {

  if (profileData.shippingAddress) {
    // render shipping address from the profile
    const changeAddressButton = document.getElementById("your-change-address-button");
    changeAddressButton.addEventListener("click", async () => {
      const {
        selectedAddress,
        selectionChanged
      } = await profile.showShippingAddressSelector();
      if (selectionChanged) {
        // selectedAddress contains the new address
      } else {
        // selection modal was dismissed without selection
      }
    });
  } else {
    // render your shipping address form
  }
} else {
  // render your shipping address form
}
```

## 4. Populate info for Fastlane members [#4-populate-info-for-fastlane-members-1]

If the user is identified as a Fastlane user, use the following code to prefill the card and shipping address:

```javascript lineNumbers
const shippingAddress = {
  name: {
    firstName: "Jen",
    lastName: "Smith"
  },
  address: {
    addressLine1: "1 E 1st St",
    addressLine2: "5th Floor",
    adminArea1: "Bartlett",
    adminarea2: "IL",
    postalCode: "60103",
    countryCode: "US",
    phone: "16503551233"
  }
};

const options = {
  fields: {
    phoneNumber: {
      // Example of how to prefill the phone number field in the FastlanePaymentComponent
      prefill: "4026607986"
    }
  },
  styles: {
    root: {   //specify styles here
      backgroundColorPrimary: "#ffffff"
    }
  }
};

const fastlanePaymentComponent = await fastlane.FastlanePaymentComponent({
    options,
    shippingAddress
  });
fastlanePaymentComponent.render("#payment-container");

// event listener when the user clicks to place the order
const submitButton = document.getElementById("submit-button");
submitButton.addEventListener("click", async ()=> {
  const { id } = await fastlanePaymentComponent.getPaymentToken();

  // Send the paymentToken and previously captured device data to server
  // to complete checkout
});
```

## 5. Collect info from guest user [#5-collect-info-from-guest-user-1]

Retrieve the existing card integration that you use to collect payment and billing information.

## 6. Integrate server side [#6-integrate-server-side-1]

You can use the orders API request that you have built on the server side to pass the payment, billing, and shipping address information to capture the transaction:

```bash lineNumbers
curl -v -k -X POST 'https://api-m.sandbox.paypal.com/v2/checkout/orders' \
 -H 'PayPal-Request-Id: UNIQUE_ID' \
 -H 'Authorization: Bearer PAYPAL_ACCESS_TOKEN' \
 -H 'Content-Type: application/json' \
 -H 'PayPal-Client-Metadata-Id: <CM_ID>' \
 -d '{
  "intent": "CAPTURE",
  "payment_source": {
    "card": {
      "single_use_token": "1h371660pr490622k" //paymentToken from the client
    }
  },
  "purchase_units": [
    {
      "amount": {
        "currency_code": "USD",
        "value": "50.00",
        "breakdown": {
          "item_total": {
            "currency_code": "USD",
            "value": "40.00"
          },
          "shipping": {
            "currency_code": "USD",
            "value": "10.00"
          }
        }
      },
      "items": [
        {
          "name": "Coffee",
          "description": "1 lb Kona Island Beans",
          "sku": "sku03",
          "unit_amount": {
            "currency_code": "USD",
            "value": "40.00"
          },
          "quantity": "1",
          "category": "PHYSICAL_GOODS",
          "image_url": "https://example.com/static/images/items/1/kona_coffee_beans.jpg",
          "url": "https://example.com/items/1/kona_coffee_beans",
          "upc": {
            "type": "UPC-A",
            "code": "987654321015"
          }
        }
      ],
      "shipping": {
        "type": "SHIPPING",
        "name": {
          "full_name": "Lawrence David"
        },
        "address": {
          "address_line_1": "585 Moreno Ave",
          "admin_area_2": "Los Angeles",
          "admin_area_1": "CA", //must be sent in 2-letter format
          "postal_code": "90049",
          "country_code": "US"
        },
        "phone_number": {
          "country_code": "1",
          "national_number": "5555555555"
        }
      }
    }
  ]
}'
```

## 7. Test your integration [#7-test-your-integration-1]

After upgrading to Fastlane, test your integration in the [sandbox environment](/sandbox-testing/overview). For information on simulating successful payments and generating card errors, refer to [Card testing](/sandbox-testing/card-testing).

To test your Fastlane integration, refer to the [Fastlane integration testing guide](/platforms/checkout/fastlane/integrate).

## 8.  Go live [#8--go-live]

If you have fulfilled the requirements for accepting payments via Fastlane for your business account, you can [Move your app to production](/api/rest/production/).

## Next steps [#next-steps]

Set up your development environment and integrate Fastlane.

> **Info:** ### Set up your development environment [#set-up-your-development-environment]
>
> Configure your REST account and initialize the SDK.

> **Info:** ### Integrate Fastlane [#integrate-fastlane]
>
> Use our ready-made quickstart integration or customize form fields with our flexible integration.
