Aller au contenu principal

Order Manager for POS - Webview Plug-in

Overview

Order Manager for Point of Sale allows partners to manage DoorDash orders more efficiently. With a single, low-touch build, you will be able to enable stores with more than 10 features that help them reduce the need to contact support, and help them avoid costly cancellations and order defects. This document provides more detail on the benefits of Order Manager for POS and step-by-step guidance on how to integrate with this plug-in.

Features

  • Dasher Management: Call, rate/block, and track Dashers
  • Order Management: Refund/substitute items, adjust prep times, mark orders as ready for pickup
  • Customer Management: Call customer
  • More to come! – DoorDash will push new features directly to the plug-in as they’re developed, without requiring additional build

Benefits

For Restaurants:

  • Reduce quality defects & reliance on support – Empower operators to self-serve when issues arise, freeing up more time to focus on growing their business
  • Fewer “Incorrect Order” reports, Fewer Cancellations & less time spent on the phone with support

For Providers:

  • Build once; get multiple features – DoorDash can add new features as we build them without requiring additional API calls, and provider engineering work
  • Low Tech Lift – ~2 weeks development work for partners to implement

Prerequisites

To start integrating with the plug-in, you should have either a certified DoorDash Marketplace integration, or be approved by DoorDash to develop a Marketplace integration.

Get Started

Step 1: Confirm receiving Live Order Management URL in the Doordash order payload.

  • Ask DoorDash to add your provider name to our allowlist to start receiving the URL. Staging and production provider names will be allowlisted separately. Note: If you selectively want to enable the URL for specific stores, please share the store-id. DoorDash can send the URL only for those stores before rolling the change to all stores linked to your provider.
  • All staging/sandbox providers currently in the process of developing a new Marketplace integration have already been allowlisted.
  • A new live_order_management_url field will be added on top of the original order payload (sampleorder). Note that the URL will initially be valid for 1-hour from the time it is sent.
{
"categories": [],
// other fields ...
"tip_amount": 0,
"live_order_management_url": "https://www.doordash.com/merchant/live-order-management/ddd52465-1f9f-4746-8529-xxxxxxxxxxx#token=abcdc65e-dbsd-4234-455a-xxxxxxxxxxx"
}

Verify receiving the url through webhook in the Developer Portal. Navigate to the ‘Event log’ tab and search for your order. The order payload will have the field live_order_management_url.

Step 2: Get the authentication secret key from DoorDash and store it securely.

  • For each provider DoorDash will provide a unique secret key which is needed to access the URL. Staging and production each have separate secret keys. Please store these keys securely.
  • Set the secret key as a Bearer token in the Authentication header when initializing the webview.

Authorization: Bearer [secret key]

Step 3: Build the webview on your POS device.

Android webview solution code example

  • Initialize the clicking button
posOrderButton = findViewById(R.id.pos_order_bn_1)
posOrderButton.clicksThrottleFirstTwoSecs().subscribe {
openPOSOrderManagementPage()
}
  • Optional: complete clicksThrottleFirstTwoSecs method
fun View.clicksThrottleFirstTwoSecs(): Observable<Unit> {
return this.clicks().throttleFirst(
Constants.TWO_SECONDS,
TimeUnit.SECONDS
)
}
  • Open POS Order Management Webview Page by URL method
private fun openPOSOrderManagementPage() {
orderModel?.let { order ->
val url = order.live_order_management_url // url from order payload
val intent = Intent(context, WebViewActivity::class.java).apply {
putExtra("url", url)
putExtra("Authorization",
"Bearer [Secret key provided by Doordash]") // set the secret
}
context.startActivity(intent)
}
}
  • Create webViewActivity
class WebViewActivity : BaseActivity(R.layout.web_view) {
// … other implementation
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.web_view)
val url = intent.getStringExtra("url")
val authHeader = intent.getStringExtra("Authorization")
// set cookie, we strongly recommend you set the Secret key provided by Doordash in the cookie for our WebView
val cookieManager = CookieManager.getInstance()
cookieManager.setAcceptCookie(true)
if (url != null && !authHeader.isNullOrEmpty()) {
cookieManager.setCookie(url, "Authorization=$authHeader")
cookieManager.flush()
}
Timber.i("Url: $url")
// Log.d("cookie", "cookie: ${cookieManager.getCookie(url)}")
val headers = hashMapOf<String, String>()
val closeWebViewButton = findViewById<ImageButton>(R.id.closeWebViewButton)
closeWebViewButton.setOnClickListener {
finish()
}
authHeader?.let {
headers["Authorization"] = it
}
when {
url.isNullOrEmpty() -> throw NullPointerException("Url can not be null or empty")
else -> {
binding.webView.apply {
settings.javaScriptEnabled = true
applyWindowInsetsToMargin(top = true, bottom = true)
webViewClient = webClient
settings.apply {
// make sure you enabled JS for webview
javaScriptEnabled = true
domStorageEnabled = true
}
}
binding.webView.loadUrl(url, headers)
}
}
}
// …
}
  • web_view.xml example
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/black">

<FrameLayout
android:id="@+id/webViewContainer"
android:layout_width="800dp"
android:layout_height="500dp"
android:layout_margin="2dp"
android:background="@android:color/black"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">

// Webview content
<com.doordash.android.core.network.view.DDWebView
android:id="@+id/web_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />

// Close Button
<ImageButton
android:id="@+id/closeWebViewButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|top"
android:layout_margin="8dp"
android:src="@drawable/icon_close" />

</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

Recommendations

  1. It is better to preload behavior when you do binding order modal:
fun bindOrderModel(order: OrderPresentationModel) {
this.orderModel = order
preloadWebView(order)
}
  1. For the preload implementation, make sure that you enabled domStorageEnabled = true for the webview caching
private fun preloadWebView(order: OrderPresentationModel) {
if (preloadedWebView == null) {
preloadedWebView = WebView(context).apply {
settings.apply {
javaScriptEnabled = true
domStorageEnabled = true
cacheMode = WebSettings.LOAD_DEFAULT
}
}
}
val preloadUrl = buildPreloadUrl(order)
CookieManager.getInstance().apply {
setAcceptCookie(true)
setCookie(preloadUrl, "Authorization=Bearer $AUTHORIZATION_TOKEN")
flush()
}
preloadedWebView?.loadUrl(preloadUrl)
}
  1. Based on Google's Android Help doc some specific webview versions will face a webview loading slowly issue, make sure that you update to the latest webview version

Web Application - iframe (HTML/Javascript)

Below is the example to set the secret key as cookie using ‘postMessage’ and embed the plugin (url) in an iframe:

NOTE: We only allow certain domains to embed the plugin as an iFrame, ask DoorDash to allowlist if your domain is not already enabled.

<script>
function sendPostMessage() {
var iframe = document.getElementById("iframeId");
var iframeWindow = iframe.contentWindow;


var cookieData = {
type: "setCookie",
value: "Bearer <your secret key>",
};


iframeWindow.postMessage(cookieData, "https://www.doordash.com");
}
</script>
<iframe
id="iframeId"
width="560"
height="315"
src="https://doordash.com/merchant/live-order-management?id=26405c3d-4819-3001-83bc-12345d94b991#token=abc"
title="Test"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
allowfullscreen
onload="sendPostMessage()"
>
</iframe>

Step 4: Test and verify

  1. Click the button that will open the POS Webview app Webview Example
  2. A webView window will pop up after clicking Webview Example

Step 5: Done and ready for merchants to manage DoorDash orders on your device!

Receiving order adjustment notifications via Order Adjustment webhook

Providers can receive notifications for order adjustments made via POS-plugin by subscribing to our Order Adjustment webhook. This webhook payload includes complete order payload along with the delta on specific items adjusted. Please follow below steps to set up the webhook.

Sample format of order-adjustment webhook:

{
{
"event": {
"type": "OrderAdjust",
"event_time": "2024-05-06T19:50:43+00:00"
},
"order": {
"id": "dc268e73-824a-4a23-8730-02c41eb6393a",
"store_order_cart_id": "2000005000762452",
"tax": 68,
"subtotal": 1080,
"estimated_pickup_time": "2024-05-06T19:50:43+00:00",
"is_pickup": false,
"order_special_instructions": "",
"delivery_address": "REDACTED",
"consumer": {
"id": "REDACTED",
"first_name": "REDACTED",
"last_name": "REDACTED",
"email": "REDACTED",
"phone": "REDACTED"
},
"store": {
"merchant_supplied_id": "3944",
"provider_type": "crisp",
"timezone": "US/Central",
"store_business": {
"auto_release_enabled": false
},
"id": "24913498"
},
"categories": [
{
"merchant_supplied_id": "c_1255",
"name": "Sodas",
"items": [
{
"name": "Unlucky Ducky",
"quantity": 1,
"price": 280,
"merchant_supplied_id": "p_1553",
"consumer_name": "Alec",
"extras": [
{
"merchant_supplied_id": "m_4343",
"name": "Splashes",
"options": [
{
"name": "Mountain Dew Splash",
"quantity": 1,
"price": 0,
"merchant_supplied_id": "m_4491",
"extras": [],
"line_option_id": "eb050156-832d-4e30-ba05-285ba0ad0065"
}
]
}
]
}
]
],
"delivery_short_code": "2ff901b3",
"tax_transaction_id": "",
"is_demand_gen": false,
"commission_type": "regular",
"is_tax_remitted_by_doordash": false,
"tax_amount_remitted_by_doordash": 0,
"fulfillment_type": "dx_delivery",
"merchant_tip_amount": 0,
"experience": "DOORDASH"
},
"order_adjustment_metadata" : {
"adjusted_source" : "MERCHANT",
"adjusted_at" : "2024-05-06T19:50:43+00:00"
"adjusted_items" : [
{
"line_item_id": "94b653e4-e394-4330-a714-43e764aergjn",
"adjustment_type": "ITEM_UPDATE",
"quantity": 2,
"substituted_item": { }
},
{
"line_item_id": "94b653e4-e394-4330-a714-43e764a223",
"adjustment_type": "ITEM_REMOVE",
"substituted_item": { },
"options": [ ]
},
{
"line_item_id": "94b653e4-e394-4330-a714-43e764ab113",
"adjustment_type": "ITEM_SUBSTITUTE",
"substituted_item": {
"name": "Diet Coke",
"merchant_supplied_id": "179",
"price": 2,
"quantity": 1
}
}
]
}
}

}

Step 1: Configure order adjustment webhook via the Developer portal for your provider.

Login to the developer portal and go to Webhook Subscription page to set this up. This set up is similar to setting up any other webhooks you currently have.

Step 2: Make order adjustments via open-api or pos-plugin to test the webhook integration

You can adjust test orders either via the API or the plugin to test. You can also verify webhooks being received via Developer Portal event logs here.

Communication and Support

  • If you have any questions, then you can submit a ticket via the Developer Portal Support with a category type of 'API Functionality'

Appendix

  • How to integrate DoorDash Marketplace - More details here
  • Receiving orders from DoorDash - More details here
  • Marketplace API order model - More details here
  • Sample order payload - More details here
  • Create a webhook subscription More details here
  • Create or view a Provider Type - More details here