How to create an order for a booking in the backend

I’m trying to create a backend function that creates a new booking for a contact for a particular session, and create an order for that booking. I haven’t found any great documentation for how the bookings and ecommerce APIs interact. What I have so far will create the booking, but I can’t figure out how to create the order. The code actually creates an order, but if I go to the Manage Participants section of the Wix Dashboard it says there is no order for the booking. This is what I have so far:

import { bookings as v2Bookings } from 'wix-bookings.v2';
import { checkout, orders as ecomOrders } from 'wix-ecom-backend';
import { elevate } from 'wix-auth';

export async function newBookingConfirm(bookingContact, bookingSession, bookingName, bookingEmail, bookingPayment, bookingSubscription) {
// bookingContact is the contactId of the contact for which to create the booking
// bookingSession is the sessionId to book
// bookingName is the name of the contact
// bookingEmail is the email address of the contact
// bookingPayment is the amount paid (offline) for the booking (if there is no pricing plan to charge)
// bookingSubscription is the orderId for the pricing plan subscription to charge for the booking

    try {
        const bookingParams = {
            bookedEntity: { slot: { sessionId: bookingSession } },
            contactDetails: {
                contactId: bookingContact,
                email: bookingEmail,
                firstName: bookingName,
            },
            selectedPaymentOption: "MEMBERSHIP",
            paymentStatus: "PAID",
            totalParticipants: 1
        };
        const bookingOptions = {
            flowControlSettings: { skipAvailabilityValidation: true, ignoreBookingWindow: true },
            participantNotification: { notifyParticipants: false },
            sendSmsReminder: false
        };

        const elevatedCreateBooking = elevate(v2Bookings.createBooking);
        let newBooking = await elevatedCreateBooking(bookingParams, bookingOptions);
        console.log(newBooking);

        const confirmOrDenyOptions = {
            paymentStatus: "PAID"
        };
        const elevatedConfirmOrDeclineBooking = elevate(v2Bookings.confirmOrDeclineBooking);
        newBooking = await elevatedConfirmOrDeclineBooking(newBooking.booking._id, confirmOrDenyOptions)
        console.log(newBooking);

        const checkoutOptions = {
            lineItems: [{
                quantity: 1,
                catalogReference: {
                    appId: "13d21c63-b5ec-5912-8397-c3a5ddb27a97",
                    /* Wix Bookings */
                    catalogItemId: newBooking.booking._id
                }
            }],
            checkoutInfo: {
                billingInfo: {
                    contactDetails: {
                        firstName: bookingName.split(" ")[0],
                        lastName: bookingName.split(" ")[1]
                    }
                },
                buyerInfo: {
                    email: bookingEmail,
                    contactId: bookingContact
                }
            },
            channelType: "WEB"
        }
        const elevatedCreateCheckout = elevate(checkout.createCheckout);
        let newCheckout = await elevatedCreateCheckout(checkoutOptions);
        console.log(newCheckout);

        let paymentOptionString = "FULL_PAYMENT_OFFLINE";
        let paymentStatusString = "NOT_PAID";
        if (bookingPayment > 0) {
            paymentOptionString = "FULL_PAYMENT_OFFLINE";
            paymentStatusString = "PAID";
        } else if (bookingSubscription) {
            paymentOptionString = "MEMBERSHIP";
            paymentStatusString = "PAID";
        }
        const orderOptions = {
            buyerInfo: {
                contactId: bookingContact,
                email: bookingEmail,
                memberId: bookingContact
            },
            checkoutId: newCheckout._id,
            channelInfo: {},
            paymentStatus: paymentStatusString,
            lineItems: [{
                quantity: 1,
                catalogReference: {
                    appId: "13d21c63-b5ec-5912-8397-c3a5ddb27a97",
                    /* Wix Bookings */
                    catalogItemId: newBooking.booking._id
                },
                itemType: newCheckout.lineItems[0].itemType,
                price: newCheckout.lineItems[0].price,
                productName: newCheckout.lineItems[0].productName,
                paymentOption: paymentOptionString,
                subscriptionInfo: { _id: bookingSubscription},
                taxDetails: newCheckout.lineItems[0].taxDetails,
            }],
            priceSummary: newCheckout.priceSummary,
            checkoutInfo: {
                billingInfo: {
                    contactDetails: {
                        firstName: bookingName.split(" ")[0],
                        lastName: bookingName.split(" ")[1]
                    }
                },
                buyerInfo: {
                    email: bookingEmail,
                    contactId: bookingContact
                }
            },
            channelType: "WEB"
        }
        const elevatedCreateOrder = elevate(ecomOrders.createOrder);
        let newOrder = await elevatedCreateOrder(orderOptions);
        console.log(newOrder);

        return newBooking;
    } catch (error) {
        console.log('customBackend.jsw > newBooking error - details -' + error.message)
        Promise.reject(
            new Error('customBackend.jsw > newBooking error - details -' + error.message));

    }

}

If anyone can point me to documentation on how to interact the ecommerce APIs with the bookings and pricing plan APIs, that would be most help.

If it helps, here are the returns from this backend function when I pass in a member with an unlimited pricing plan. I’m sure there’s a clue in there somewhere about what I’m doing wrong. The booking I create looks ok to me. The checkout is marked with completed:false, and the order is marked with status:“INITIALIZED”. This seems to tell me that the payment wasn’t correctly processed. Somehow I’m not linking the checkout/order to the payment method (a pricing plan subscription or an offline payment).

The return from createBooking():

{
  "booking": {
    "bookedEntity": {
      "slot": {
        "sessionId": "193ZPR9ppP9emJUCLevcLf6orynNEIDt5nc0520xjGQILnPPaF5s62yK3BWz7ExgIRM1UqYb3zip0gGSkrD3kXi5LrKQsRw2o5APKDooD6BekAYrTbVf1DT1fC12cL2IWq7ygiKkY1CtVj29TbGO5OybjHVDGqveEPoMi7DSceY8AQSYSCzxu3ZAN8YcM2EtObGk2AyqKByV8Oieayft4f4ayPELMBd36yTdsSL55TnbJ4a3HzJuRhTwbIdJSfH1YK5xOEcIH7Do9nxNB9oJGUbHrx1p1QUmDZ9pP8VuzLCRhJPCNWe9lqybMsR2IEna9z2VvMf3eu83vZ",
        "serviceId": "fd83b06d-4e24-4fe1-b9f9-c748e8342263",
        "scheduleId": "d5c2a078-d203-46d6-b5e5-746478322d34",
        "eventId": "12GF1tmaZUyN8YmV62fC0nXBb6DrXKQZDh4m6cs6zRCrmCMo1ynh3uRUolAwKcEpgFGofHliVJGNNcaRCUTVPUmpN2vSSDBPqwraARO4CLT5nu1PoNW9U3c",
        "startDate": "2024-04-28T00:30:00.000-06:00",
        "endDate": "2024-04-28T01:30:00.000-06:00",
        "timezone": "America/Denver",
        "resource": {
          "name": "TBD",
          "email": "tbd@someemail.org",
          "scheduleId": "0a0e05f9-94f1-46fb-9ede-1ed6644f2b6c",
          "explicitlyRequested": true,
          "_id": "2a09d034-a277-4759-8687-0aeacdcec41b"
        },
        "location": {
          "name": "Boulder Reservoir",
          "formattedAddress": "5275 Reservoir Rd, Boulder, CO 80301, USA",
          "locationType": "OWNER_BUSINESS",
          "_id": "0c2ee823-a332-4938-9951-6c83346af1c1"
        },
        "additionalResources": []
      },
      "title": "BAM City Open Water Swim",
      "tags": [
        "GROUP"
      ]
    },
    "contactDetails": {
      "contactId": "cd65fab7-7215-48b6-ae1b-2b13842d2cae",
      "firstName": "Ows1 Owstest",
      "email": "ows1@someemail.com"
    },
    "additionalFields": [],
    "numberOfParticipants": 1,
    "status": "CONFIRMED",
    "paymentStatus": "PAID",
    "selectedPaymentOption": "MEMBERSHIP",
    "participantNotification": {
      "notifyParticipants": false
    },
    "sendSmsReminder": false,
    "revision": "2",
    "createdBy": {
      "identityType": "UNKNOWN",
      "memberId": "7246f60f-c346-4f37-9355-9dc16bffd24c"
    },
    "startDate": "2024-04-28T06:30:00.000Z",
    "endDate": "2024-04-28T07:30:00.000Z",
    "flowControlSettings": {
      "ignoreBookingWindow": true,
      "skipAvailabilityValidation": true,
      "skipBusinessConfirmation": false,
      "skipSelectedPaymentOptionValidation": false,
      "withRefund": false
    },
    "totalParticipants": 1,
    "v2Availability": false,
    "_id": "2f74eb83-655b-4d1b-8ed9-a54f9c3b7fe8",
    "_createdDate": "2024-04-27T18:44:10.496Z",
    "_updatedDate": "2024-04-27T18:44:10.879Z"
  }
}

The return from createOrDeclineBooking():

{
  "booking": {
    "bookedEntity": {
      "slot": {
        "sessionId": "193ZPR9ppP9emJUCLevcLf6orynNEIDt5nc0520xjGQILnPPaF5s62yK3BWz7ExgIRM1UqYb3zip0gGSkrD3kXi5LrKQsRw2o5APKDooD6BekAYrTbVf1DT1fC12cL2IWq7ygiKkY1CtVj29TbGO5OybjHVDGqveEPoMi7DSceY8AQSYSCzxu3ZAN8YcM2EtObGk2AyqKByV8Oieayft4f4ayPELMBd36yTdsSL55TnbJ4a3HzJuRhTwbIdJSfH1YK5xOEcIH7Do9nxNB9oJGUbHrx1p1QUmDZ9pP8VuzLCRhJPCNWe9lqybMsR2IEna9z2VvMf3eu83vZ",
        "serviceId": "fd83b06d-4e24-4fe1-b9f9-c748e8342263",
        "scheduleId": "d5c2a078-d203-46d6-b5e5-746478322d34",
        "eventId": "12GF1tmaZUyN8YmV62fC0nXBb6DrXKQZDh4m6cs6zRCrmCMo1ynh3uRUolAwKcEpgFGofHliVJGNNcaRCUTVPUmpN2vSSDBPqwraARO4CLT5nu1PoNW9U3c",
        "startDate": "2024-04-28T00:30:00.000-06:00",
        "endDate": "2024-04-28T01:30:00.000-06:00",
        "timezone": "America/Denver",
        "resource": {
          "name": "TBD",
          "email": "tbd@someemail.org",
          "scheduleId": "0a0e05f9-94f1-46fb-9ede-1ed6644f2b6c",
          "explicitlyRequested": true,
          "_id": "2a09d034-a277-4759-8687-0aeacdcec41b"
        },
        "location": {
          "name": "Boulder Reservoir",
          "formattedAddress": "5275 Reservoir Rd, Boulder, CO 80301, USA",
          "locationType": "OWNER_BUSINESS",
          "_id": "0c2ee823-a332-4938-9951-6c83346af1c1"
        },
        "additionalResources": []
      },
      "title": "BAM City Open Water Swim",
      "tags": [
        "GROUP"
      ]
    },
    "contactDetails": {
      "contactId": "cd65fab7-7215-48b6-ae1b-2b13842d2cae",
      "firstName": "Ows1 Owstest",
      "email": "ows1@someemail.com"
    },
    "additionalFields": [],
    "numberOfParticipants": 1,
    "status": "CONFIRMED",
    "paymentStatus": "PAID",
    "selectedPaymentOption": "MEMBERSHIP",
    "participantNotification": {
      "notifyParticipants": false
    },
    "sendSmsReminder": false,
    "revision": "2",
    "createdBy": {
      "identityType": "UNKNOWN",
      "memberId": "7246f60f-c346-4f37-9355-9dc16bffd24c"
    },
    "startDate": "Sun Apr 28 2024 00:30:00 GMT-0600 (Mountain Daylight Time)",
    "endDate": "Sun Apr 28 2024 01:30:00 GMT-0600 (Mountain Daylight Time)",
    "flowControlSettings": {
      "ignoreBookingWindow": true,
      "skipAvailabilityValidation": true,
      "skipBusinessConfirmation": false,
      "skipSelectedPaymentOptionValidation": false,
      "withRefund": false
    },
    "totalParticipants": 1,
    "v2Availability": false,
    "_id": "2f74eb83-655b-4d1b-8ed9-a54f9c3b7fe8",
    "_createdDate": "Sat Apr 27 2024 12:44:10 GMT-0600 (Mountain Daylight Time)",
    "_updatedDate": "Sat Apr 27 2024 12:44:10 GMT-0600 (Mountain Daylight Time)"
  }
}

The return from createCheckout():

{
  "lineItems": [
    {
      "quantity": 1,
      "catalogReference": {
        "catalogItemId": "2f74eb83-655b-4d1b-8ed9-a54f9c3b7fe8",
        "appId": "13d21c63-b5ec-5912-8397-c3a5ddb27a97"
      },
      "productName": {
        "original": "BAM City Open Water Swim",
        "translated": "BAM City Open Water Swim"
      },
      "price": {
        "amount": "0",
        "convertedAmount": "0",
        "formattedAmount": "$0.00",
        "formattedConvertedAmount": "$0.00"
      },
      "lineItemPrice": {
        "amount": "0",
        "convertedAmount": "0",
        "formattedAmount": "$0.00",
        "formattedConvertedAmount": "$0.00"
      },
      "fullPrice": {
        "amount": "0",
        "convertedAmount": "0",
        "formattedAmount": "$0.00",
        "formattedConvertedAmount": "$0.00"
      },
      "priceBeforeDiscounts": {
        "amount": "0",
        "convertedAmount": "0",
        "formattedAmount": "$0.00",
        "formattedConvertedAmount": "$0.00"
      },
      "totalPriceAfterTax": {
        "amount": "0",
        "convertedAmount": "0",
        "formattedAmount": "$0.00",
        "formattedConvertedAmount": "$0.00"
      },
      "totalPriceBeforeTax": {
        "amount": "0",
        "convertedAmount": "0",
        "formattedAmount": "$0.00",
        "formattedConvertedAmount": "$0.00"
      },
      "taxDetails": {
        "taxableAmount": {
          "amount": "0",
          "convertedAmount": "0",
          "formattedAmount": "$0.00",
          "formattedConvertedAmount": "$0.00"
        },
        "taxRate": "0",
        "totalTax": {
          "amount": "0",
          "convertedAmount": "0",
          "formattedAmount": "$0.00",
          "formattedConvertedAmount": "$0.00"
        },
        "rateBreakdown": [],
        "isItemTaxable": false,
        "isTaxIncluded": false,
        "taxBreakdown": []
      },
      "discount": {
        "amount": "0",
        "convertedAmount": "0",
        "formattedAmount": "$0.00",
        "formattedConvertedAmount": "$0.00"
      },
      "descriptionLines": [],
      "media": "wix:image://v1/156f8a_af84e195b3e64afe804393f3619de193~mv2.png/156f8a_af84e195b3e64afe804393f3619de193~mv2.png#originWidth=4032&originHeight=3024",
      "availability": {
        "status": "AVAILABLE",
        "quantityAvailable": 1
      },
      "couponScopes": [
        {
          "namespace": "bookings"
        },
        {
          "namespace": "bookings",
          "group": {
            "name": "service",
            "entityId": "fd83b06d-4e24-4fe1-b9f9-c748e8342263"
          }
        }
      ],
      "itemType": {
        "preset": "SERVICE"
      },
      "paymentOption": "MEMBERSHIP",
      "serviceProperties": {
        "scheduledDate": "2024-04-28T06:30:00.000Z",
        "numberOfParticipants": 1
      },
      "rootCatalogItemId": "fd83b06d-4e24-4fe1-b9f9-c748e8342263",
      "customLineItem": false,
      "_id": "00000000-0000-0000-0000-000000000001"
    }
  ],
  "billingInfo": {
    "contactDetails": {
      "firstName": "Ows1",
      "lastName": "Owstest"
    }
  },
  "shippingInfo": {
    "carrierServiceOptions": []
  },
  "buyerInfo": {
    "contactId": "cd65fab7-7215-48b6-ae1b-2b13842d2cae",
    "email": "ows1@someemail.com"
  },
  "conversionCurrency": "USD",
  "priceSummary": {
    "subtotal": {
      "amount": "0",
      "convertedAmount": "0",
      "formattedAmount": "$0.00",
      "formattedConvertedAmount": "$0.00"
    },
    "shipping": {
      "amount": "0",
      "convertedAmount": "0",
      "formattedAmount": "$0.00",
      "formattedConvertedAmount": "$0.00"
    },
    "tax": {
      "amount": "0",
      "convertedAmount": "0",
      "formattedAmount": "$0.00",
      "formattedConvertedAmount": "$0.00"
    },
    "discount": {
      "amount": "0",
      "convertedAmount": "0",
      "formattedAmount": "$0.00",
      "formattedConvertedAmount": "$0.00"
    },
    "total": {
      "amount": "0",
      "convertedAmount": "0",
      "formattedAmount": "$0.00",
      "formattedConvertedAmount": "$0.00"
    },
    "additionalFees": {
      "amount": "0",
      "convertedAmount": "0",
      "formattedAmount": "$0.00",
      "formattedConvertedAmount": "$0.00"
    }
  },
  "calculationErrors": {
    "orderValidationErrors": []
  },
  "appliedDiscounts": [],
  "customFields": [],
  "weightUnit": "LB",
  "taxSummary": {
    "taxableAmount": {
      "amount": "0",
      "convertedAmount": "0",
      "formattedAmount": "$0.00",
      "formattedConvertedAmount": "$0.00"
    },
    "totalTax": {
      "amount": "0",
      "convertedAmount": "0",
      "formattedAmount": "$0.00",
      "formattedConvertedAmount": "$0.00"
    },
    "manualTaxRate": "0",
    "aggregatedTaxBreakdown": []
  },
  "currency": "USD",
  "channelType": "WEB",
  "siteLanguage": "en",
  "buyerLanguage": "en",
  "completed": false,
  "taxIncludedInPrice": false,
  "createdBy": {
    "appId": "151e476a-715e-ec33-db9a-a7ff4d51f70a"
  },
  "payNow": {
    "subtotal": {
      "amount": "0",
      "convertedAmount": "0",
      "formattedAmount": "$0.00",
      "formattedConvertedAmount": "$0.00"
    },
    "shipping": {
      "amount": "0",
      "convertedAmount": "0",
      "formattedAmount": "$0.00",
      "formattedConvertedAmount": "$0.00"
    },
    "tax": {
      "amount": "0",
      "convertedAmount": "0",
      "formattedAmount": "$0.00",
      "formattedConvertedAmount": "$0.00"
    },
    "discount": {
      "amount": "0",
      "convertedAmount": "0",
      "formattedAmount": "$0.00",
      "formattedConvertedAmount": "$0.00"
    },
    "total": {
      "amount": "0",
      "convertedAmount": "0",
      "formattedAmount": "$0.00",
      "formattedConvertedAmount": "$0.00"
    },
    "additionalFees": {
      "amount": "0",
      "convertedAmount": "0",
      "formattedAmount": "$0.00",
      "formattedConvertedAmount": "$0.00"
    }
  },
  "payLater": {
    "subtotal": {
      "amount": "0",
      "convertedAmount": "0",
      "formattedAmount": "$0.00",
      "formattedConvertedAmount": "$0.00"
    },
    "shipping": {
      "amount": "0",
      "convertedAmount": "0",
      "formattedAmount": "$0.00",
      "formattedConvertedAmount": "$0.00"
    },
    "tax": {
      "amount": "0",
      "convertedAmount": "0",
      "formattedAmount": "$0.00",
      "formattedConvertedAmount": "$0.00"
    },
    "discount": {
      "amount": "0",
      "convertedAmount": "0",
      "formattedAmount": "$0.00",
      "formattedConvertedAmount": "$0.00"
    },
    "total": {
      "amount": "0",
      "convertedAmount": "0",
      "formattedAmount": "$0.00",
      "formattedConvertedAmount": "$0.00"
    },
    "additionalFees": {
      "amount": "0",
      "convertedAmount": "0",
      "formattedAmount": "$0.00",
      "formattedConvertedAmount": "$0.00"
    }
  },
  "membershipOptions": {
    "eligibleMemberships": [],
    "invalidMemberships": [],
    "selectedMemberships": {
      "memberships": []
    }
  },
  "additionalFees": [],
  "payNowTotalAfterGiftCard": {
    "amount": "0",
    "convertedAmount": "0",
    "formattedAmount": "$0.00",
    "formattedConvertedAmount": "$0.00"
  },
  "ecomId": "711a1843-1652-48cd-ac31-eb6839b7f463",
  "violations": [],
  "totalAfterGiftCard": {
    "amount": "0",
    "convertedAmount": "0",
    "formattedAmount": "$0.00",
    "formattedConvertedAmount": "$0.00"
  },
  "purchaseFlowId": "a19c8566-8e2b-4e29-95f8-613da9bf747d",
  "_id": "94daa618-c711-45dd-8182-61bc24c417dc",
  "_createdDate": "2024-04-27T18:44:11.722Z",
  "_updatedDate": "2024-04-27T18:44:11.722Z"
}

The return from createOrder():

{
  "number": "0",
  "lineItems": [
    {
      "productName": {
        "original": "BAM City Open Water Swim",
        "translated": "BAM City Open Water Swim"
      },
      "catalogReference": {
        "catalogItemId": "2f74eb83-655b-4d1b-8ed9-a54f9c3b7fe8",
        "appId": "13d21c63-b5ec-5912-8397-c3a5ddb27a97"
      },
      "quantity": 1,
      "descriptionLines": [],
      "itemType": {
        "preset": "SERVICE"
      },
      "price": {
        "amount": "0",
        "formattedAmount": "$0.00"
      },
      "totalPriceBeforeTax": {
        "amount": "0",
        "formattedAmount": "$0.00"
      },
      "totalPriceAfterTax": {
        "amount": "0",
        "formattedAmount": "$0.00"
      },
      "paymentOption": "MEMBERSHIP",
      "taxDetails": {
        "taxableAmount": {
          "amount": "0",
          "formattedAmount": "$0.00"
        },
        "taxRate": "0",
        "totalTax": {
          "amount": "0",
          "formattedAmount": "$0.00"
        }
      },
      "taxInfo": {
        "taxAmount": {
          "amount": "0",
          "formattedAmount": "$0.00"
        },
        "taxableAmount": {
          "amount": "0",
          "formattedAmount": "$0.00"
        },
        "taxRate": "0",
        "taxIncludedInPrice": false,
        "taxBreakdown": []
      },
      "subscriptionInfo": {
        "cycleNumber": 0,
        "subscriptionOptionTitle": "",
        "_id": "2dbf7562-bb1e-4112-8dee-d03d6c33ec09"
      },
      "locations": [],
      "lineItemPrice": {
        "amount": "0",
        "formattedAmount": "$0.00"
      },
      "_id": "00000000-0000-0000-0000-000000000001"
    }
  ],
  "buyerInfo": {
    "contactId": "cd65fab7-7215-48b6-ae1b-2b13842d2cae",
    "email": "ows1@someemail.com",
    "memberId": "cd65fab7-7215-48b6-ae1b-2b13842d2cae"
  },
  "paymentStatus": "PAID",
  "fulfillmentStatus": "FULFILLED",
  "buyerLanguage": "en",
  "weightUnit": "LB",
  "currency": "USD",
  "taxIncludedInPrices": false,
  "priceSummary": {
    "subtotal": {
      "amount": "0",
      "formattedAmount": "$0.00"
    },
    "shipping": {
      "amount": "0",
      "formattedAmount": "$0.00"
    },
    "tax": {
      "amount": "0",
      "formattedAmount": "$0.00"
    },
    "discount": {
      "amount": "0",
      "formattedAmount": "$0.00"
    },
    "totalPrice": {
      "amount": "0",
      "formattedAmount": "$0.00"
    },
    "total": {
      "amount": "0",
      "formattedAmount": "$0.00"
    },
    "totalWithGiftCard": {
      "amount": "0",
      "formattedAmount": "$0.00"
    },
    "totalWithoutGiftCard": {
      "amount": "0",
      "formattedAmount": "$0.00"
    }
  },
  "status": "INITIALIZED",
  "archived": false,
  "appliedDiscounts": [],
  "activities": [
    {
      "type": "ORDER_PLACED",
      "_id": "86289ec1-57e1-4dee-983e-9b999db8940a",
      "_createdDate": "2024-04-27T18:44:12.003Z"
    }
  ],
  "attributionSource": "UNSPECIFIED",
  "channelInfo": {
    "type": "UNSPECIFIED"
  },
  "checkoutId": "94daa618-c711-45dd-8182-61bc24c417dc",
  "customFields": [],
  "isInternalOrderCreate": false,
  "balanceSummary": {
    "balance": {
      "amount": "0",
      "formattedAmount": "$0.00"
    },
    "paid": {
      "amount": "0.00",
      "formattedAmount": "$0.00"
    },
    "refunded": {
      "amount": "0.00",
      "formattedAmount": "$0.00"
    }
  },
  "additionalFees": [],
  "_id": "b8d8cfc8-b9a3-492f-acd7-b101396cd7e7",
  "_createdDate": "2024-04-27T18:44:12.004Z",
  "_updatedDate": "2024-04-27T18:44:12.004Z"
}

I’ve made progress on this, mostly through experimentation. I still haven’t found any documentation that covers any of my remaining issues, and Wix Support has been unhelpful.

The big thing I figured out is to call checkout.createOrder() instead of orders.createOrder() from wix-ecom-backend. After creating the order, call bookings.confirmOrDeclineBooking() from wix-bookings-v2. Using this method I have been able to successfully create a booking with an offline order in my backend process that is marked unpaid.

I still have two open issues. First, if the booking is paid offline, I haven’t figured out a way to attach a payment and mark it as paid. I’ve tried orderTransactions.addPayments from the ecom API and setBookingAsPaid from the bookings backend, but nothing is exactly right.

The second open issue is how to create the checkout/order if someone uses their pricing plan offline. Presumably, you would use the selectedMemberships field in the createBooking() method, but I have tried numerous combinations, scoured the documentation, and asked Wix Support multiple times and not found a clue on how to do this.

Until I resolve these two issues, I can create offline bookings, but I can’t mark them as paid, either with cash or with a membership.

Any clues from anybody would be welcome.

HI silleekim,

Jacob from Wix Bookings here.
The problem you are facing with marking orders as paid is related to ECOM APIs rather than to Bookings APIs because you are aiming to mark the order itself, regardless of its content (Bookings, products, etc…).

Regarding the ECOM’s markOrderAsPaid Velo API, it should be released this year during Q3.

Awesome, Jason, thanks. I’m looking forward to this, and it’s great to know the Wix team is working on it. We launched the class last week for which we use this feature. We had about 100 people drop in, so marking them all as paid manually is an effort but doable for now. We hold the class all summer, so it looks like we should be able to automate this for next year.

Hi, I have re-checked the https://dev.wix.com/docs/velo/api-reference/wix-bookings-backend/bookings/set-attendance and it works!
Can you provide the bookingId for which the API above didn’t work?

Thanks, Jacob, I don’t have any problem with bookings.setAttendance(). I’m actually using attendance.setAttendance() (from wix-bookings.v2) to accomplish the same thing, but I assume these two functions are equivalent. It does exactly what I expect.

I actually use this function as part of my kludgy workaround. I set the attendance record in my code to indicate how payment was made, and then use Manage Participants from the Dashboard afterwards to correct the booking payments manually. In my code, I set attended = true for anyone who paid offline. I set attended = false for anyone who paid with a pricing plan. I don’t set attendance for anyone who didn’t pay either way. After my code runs, I go into Manage Participants and look at each booking. If the booking is marked as Checked In, I mark it as Paid. If the booking is marked as a No Show, I delete the booking record and add it back again manually, and mark it as Charge To Plan Later. Then I choose Redeem Session so I can choose which pricing plan to debit (if the person has more then one) and mark the booking as Checked In. If the booking is marked as neither Checked In nor No Show, I leave it as Unpaid.

This manual workaround, along with being very error prone, adds about 60-90 minutes after every class to get the booking data corrected and people’s passes charged correctly. Manage Participants is difficult to use for this, as it is constantly resorting in the background while you are trying to select a specific booking.

So, I am dealing with two features that either don’t work or are missing in the ecommerce API. One, which you have said is in the product roadmap for Q3, is to mark the bookings order as paid. This will solve the first half of my problem.

The second, the ability to charge a booking to a pricing plan subscription, appears to me to be a flaw in the checkout.createCheckout() method. There appears to be no way to actually tie the order to a pricing plan subscription. I assumed it would be the membershipOptions field in the parameter, but I could not get that to work. It would be great to know if the ecommerce improvements planned for Q3 would also include this fix.

Thanks!
Mike

Wow thank you guys so much for such an amazing and helpful post!
However I have got this message when try to change the selectedPaymentOption
‘Missing required permission BOOKINGS.MANAGE_PAYMENTS: Missing required permission BOOKINGS.MANAGE_PAYMENTS to create booking with MEMBERSHIP_OFFLINE selectedPaymentOption’
My costumers mostly use MEMBERSHIP_OFFLINE (not the Membership Wix Pricing Plan provides, which i believe to be considered as MEMBERSHIP option, not MEMBERSHIP_OFFLINE)
Please help!!!

I also was unable to use the MEMBERSHIP_OFFLINE option. I suspect this is part of the missing Wix support for memberships/pricing plans for bookings in Velo. I have been told by someone in Wix Support that using the use the Wix eCommerce API to charge a booking to a pricing plan is a feature that is scheduled to be released in fourth quarter of this year.

So, the good news is that Wix has now acknowledged that both of my problems are real issues and both of them are on the product roadmap for later this year. I’ll post an update when this is working.

1 Like