Layer Messaging Experiences

Layer’s XDK provides a framework for building and rendering rich and interactive Messaging Experiences. Each message that is sent/received by an application built using Layer consists of a collection of Message Parts that have MIME Types that define what type of message it is. Each type of message can have its own custom rendering, interactions and operations. Layer’s XDK provides the tools for providing these Message Types and rendering them; it also comes with a small library of these built in.

The tools for building these Messaging Experiences are:

  • LYRUIMessageTypeSerializing protocol : A serializer conforming to this protocol accepts a LYRMessage as input and from it, instantiates a Message Type Model (a subclass of LYRUIMessageType)
  • LYRUIMessageItemContentPresenting protocol : A presenter conforming to this protocol accepts a Message Type Model as input and instantiates a view representing this model
  • LYRUIMessageItemContentContainerPresenting protocol : A presenter conforming to this protocol accepts a Message Type Model as input and instantiates a message container view for this model
  • LYRUIMessageType : Represents a specific type of Message such as an Image Message, exposing properties, methods and operations for interacting with that type of message
  • LYRUIMessageViewContainer protocol : A container that lays out the view representing an Message Type with respect to other relevant information or widgets related to the Message

Examples of these include:

  • LYRUITextMessageSerializer + LYRUITextMessage model + LYRUITextMessageContentViewPresenter + LYRUIStandardMessageContainerViewPresenter combined to create the Text Message View with title, description and footer
  • LYRUIReceiptMessageSerializer + LYRUIReceiptMessage model + LYRUIReceiptMessageCompositeViewPresenter combined to create the Receipt Message View

Messages Hierarchy

An Experience can exist as a child component of another Experience. This happens when the LYRUIMessageType Model generated for this Experienve contains Submodels. For example, consider a Carousel Message contains a collection of Sub Models such as Product Message Models. In the case of the Carousel, each Product Message Model is rendered with its own Presenter that is used within the main Carousel’s Presenter.

The Message Serializer

Every Message is sent or received in a form of LYRMessage object with one or more LYRMessagePart instances. To present the message with proper component, it needs to be deserialized into LYRUIMessageType . When a LYRUIMessageType should be sent, it needs to be serialized into LYRMessage.

The LYRUIMessageSerializer object performs the following actions:

  1. Identify what MIME Type the Message represents.
  2. Based on the MIME Type, Instantiate an appropriate LYRUIMessageTypeSerializing implementation for the Message.
  3. Secialize or deserialize Message into LYRMessage or LYRUIMessageType respectively.

The Message Presenter

Every Message Type that is rendered within the LYRUIMessageListView into an Experience is handled via a LYRUIMessageItemContentPresenting, and LYRUIMessageItemContentContainerPresenting implementations.

  • LYRUIMessageItemContentPresenting : knows how to render content of the Message Type, such as image for LYRUIImageMessage
  • LYRUIMessageItemContentContainerPresenting : knows how to render common properties such as titles, subtitles, etc, and where they go with respect to the Message content.

Note Not every Message Type has a Content Container Presenter assigned, and may be rendered without a Container View.

The LYRUIMessageItemView component performs the following actions to use proper content view for Message Type:

  1. Using LYRUIMessageItemContentPresentersProvider, retrieves an implementation of LYRUIMessageItemContentPresenting, or LYRUIMessageItemContentContainerPresenting (if applicable) that knows how to render data for that Model.
  2. Using the Presenter’s viewForMessage: method, creates an instance of view used to represent the message.
  3. Sets proper background color of message bubble, using backgroundColorForMessage: method of Presenter.
  4. Calculates proper height of the message, within given width constraints, using Presenter’s viewHeightForMessage:minWidth:maxWidth: method.

Note The Content Container Presenter, when calculating height of the message, needs to include the height of Content View, contained in it.

What is a Message Type Model?

Messages and Message Parts transported using Layer protocol are abstract concepts containing a custom MIME Type such as text/plain, some body such as hello world, and what you do with these is entirely unspecified. As part of providing a system of Messaging Experiences, the definitions and expectations of what goes in the Message Parts has become a lot more specific; these LYRMessagePart instances are expected to match a specific format and set of rules, so they can be deserialized into specific Message Type (a subclass of LYRUIMessageType ).

The following Message represents a Carousel of Maps; this example is presented here so that you can see a hint of what Messages and Message Parts underlying this will look like. You will not need to really work with Messages and Message Parts directly until you start creating Custom Messaging Experiences.

LYRMessage contains four LYRMessagePart objects:

  1. Root Message Part

    MIME Type: application/vnd.layer.carousel+json; role=root; node-id=6307b011-e0e9-4bb5-8b97-99309e49cbfc Empty Body

  2. First Map Message Part

    MIME Type: application/vnd.layer.location+json; role=carousel-item; parent-node-id=6307b011-e0e9-4bb5-8b97-99309e49cbfc; item-order=1
    Body:

    {
        "title": "Layer HQ 2017",
        "street": "655 4th st",
        "city": "San Francisco",
        "administrative_area": "CA",
        "postal_code": "91447"
    }
    
  3. Second Map Message Part

    MIME Type: application/vnd.layer.location+json; role=carousel-item; parent-node-id=6307b011-e0e9-4bb5-8b97-99309e49cbfc; item-order=2
    Body:

    {
        "title": "Near Layer HQ 2017",
        "street": "650 4th st",
        "city": "San Francisco",
        "administrative_area": "CA",
        "postal_code": "91447"
    }
    
  4. Third Map Message Part

    MIME Type: application/vnd.layer.location+json; role=carousel-item; parent-node-id=6307b011-e0e9-4bb5-8b97-99309e49cbfc; item-order=3
    Body:

    {
        "title": "Less Near Layer HQ 2017",
        "street": "645 4th st",
        "city": "San Francisco",
        "administrative_area": "CA",
        "postal_code": "91447"
    }
    

So… thats a lot of raw data, all of it burried in JSON, and all of it spread across a bunch of LYRMessageParts objects with different MIME Types. Rather than have that as what developers interact with to create unique Messaging Experiences, we instead provide a LYRUIMessageType Models.

Each LYRUIMessageType subclass provides the following:

  1. Understands and abstracts all of the complexities of the Message and its Message Parts into properties
  2. Manages Message Actions assigned to the Message
  3. Maps values of the model to a Title, Description and Footer (for Message Type Views that use Message View Containers) formed into an LYRUIMessageMetadata object

A LYRUIMessageType is used in two common contexts:

  1. The Message List is iterating over each Message Type and generating a Cell containing a LYRUIMessageItemView.
    Each Message Item instantiates a Presenter for the Message Type and a renders a View representing that Model.
  2. An application can create and send a properly structured message by instantiating a Model Type, and serializing it into a LYRMessage to send.

Developers using prebuilt Layer Messages should only care about how to use a Model to send Messages of various types. To learn more about how to create new Model Types, see Customizing Messaging Experiences.

All Models will have these properties:

Name Required Type Description
MIMEType Yes NSString MIME Type of message contents
sender No LYRIdentity Identity of a message sender
sentAt No NSDate Date of message sending
status No LYRUIMessageTypeStatus Formatted recipients status of message
action No LYRUIMessageAction Contains data used when the user taps a Message rendered from this Model
summary Yes NSString Summary of message contents, used for example in Conversations List to describe last message
metadata No LYRUIMessageMetadata Properties of the model mapped to a Title, Description and Footer

Message Status

LYRUIMessageTypeStatus contains:

Name Required Type Description
status Yes LYRUIMessageStatus Status of the message: New, Pending, Sent, Delivered, or Read
statusDescription Yes NSString Description of the message status, used for example to display status below the message

Message Metadata

LYRUIMessageMetadata contains:

Name Required Type Description
title No NSString Title of the message content
footer No NSString Footer with additional information about the message content
messageDescription No NSString Message content description

Message Actions

LYRUIMessageAction contains:

Name Required Type Description
event No NSString A string naming the event to trigger
data No NSDictionary Custom data used to handle the event

Note Data commonly comes from the Model directly; a Location Message has a location, a Link Message has a url, a File Message has a source_url; but suppose you wanted to override that behavior… or to have an open-url action on a Text Message? You can put a url into data property of action and this url will take precedence over any other url for the open-url action.

Typically one might create a Model as follows:

CLLocation *location = [[CLLocation alloc] initWithLatitude:37.7777405
                                                  longitude:-122.3959881];
LYRUILocationMessage *locationMessage = [[LYRUILocationMessage alloc] initWithLocation:location];

and then send the message as follows:

LYRUIMessageSender *messageSender = [[LYRUIMessageSender alloc] initWithConfiguration:self.layerUIConfiguration];
messageSender.conversation = conversation;
[messageSender sendMessage:locationMessage];

This will cause a properly structured message to be sent, and all participants will see this Location Message; clicking on it will perform the default action.event for the LYRUILocationMessage of open-map. It will find the latitude and longitude from the Message location property and show it.

You can, however, provide a custom event:

CLLocation *location = [[CLLocation alloc] initWithLatitude:37.7777405
                                                  longitude:-122.3959881];
LYRUIMessageAction *action = [[LYRUIMessageAction alloc] initWithEvent:@"open-url"
                                                                  data:@{ @"url" : @"https://example.com" }];
LYRUILocationMessage *llocationMessage = [[LYRUILocationMessage alloc] initWithLocation:location
                                                                                   zoom:17
                                                                                  title:nil
                                                                     contentDescription:nil
                                                                                street1:nil
                                                                                street2:nil
                                                                                   city:nil
                                                                     administrativeArea:nil
                                                                                country:nil
                                                                             postalCode:nil
                                                                                 action:action
                                                                                 sender:nil
                                                                                 sentAt:nil
                                                                                 status:nil];

Providing your own event names and your own event handlers is an easy way to customize behaviors and add interactions to your application without having to building your own Custom Message Types.

Registering a New Action Handler

If defining a custom action for your application’s messages, you should register an Action Handler to process any message that has that action. This example assumes a custom Message Type Model has been defined that contains a bill property and a processBill method.

Adding custom Action handlers is out of 4.0.0 scope

Text Messages

A Text Message has a few uses:

  • A standard conversational message containing messages users type to one another
  • A framed and titled Message for quoted text. For example, a quote from a product manual or a product page might be rendered, and attribution given as to where it came from so that it does not look like something that the sender just typed in.
Text Message with Details
Text Message without Details

The above illustrates the difference between a Text Message that is rendered as a conversational message, and a Text Message that renders quoted text with a title and footer.

A Text Message can be instantiated using:

NSString *messageText = @"...";
LYRUITextMessage *textMessage = [[LYRUITextMessage alloc] initWithText:messageText];

The Text Model supports the following properties:

Name Required Type Description
text Yes NSString This is the core data rendered by the Core UI for this Message
title No NSString Title for the Text Message
subtitle No NSString Rendered below the title
author No NSString Rendered below the subtitle
textMIMEType No NSString MIME Type of the text; Currently only text/plain is supported

Note

If text is provided, but no title, subtitle or author then this Text Message will render as a regular chat bubble rather than look like a quoted message with metadata shown below it.

A Link Message has a few uses:

  • A simple way to send a link to users
  • A framed summary of a web page, article or other online content consisting of a picture, title, description and the url itself.

Note

URLs sent within a Text Message will be hyperlinked; this means that links can be sent as part of a Text Message. The Link Message provides a richer experience, and clicking anywhere on the message will open the link, and Link Messages will not truncate the rendering of the URL the way that a Text Message will do.

Example of a Link Message without any Details
Example of a Link Message showing an Article with Details

A Link Message can be instantiated using:

The Link Model supports the following properties:

Name Required Type Description
url Yes NSString The URL to open; used by the open-url action, and by the URL Enrichment Integration (optional)
title No NSString Title for the Link Message
contentDescription No NSString Rendered below the title
author No NSString Rendered below the description
imageUrl No NSString URL to an image to render over the title
imageSize No NSString URL to an image to render over the title

Note

If url is provided, but no title, description, author or imageUrl then this Link Message will render as a conversational message and show the url value directly.

An optional URL Enrichment Integration Service will be made available to customers that looks for any Link Message that contains only the URL, and updates the Message to have a title, description, author and imageUrl based on data it reads off of the web page loaded from that URL.

File Messages

A File Message has a few uses:

  • Allow a user to drag and drop one or more files from their desktop and send them as Messages that recipients can open
  • Allow an application to send a reference to a file in its library, with accompanying descriptions

A File Message can be instantiated using:

// NOTE: Sending this message on mobile clients is not currently supported; this Javascript example can be used to create test messages from a web browser

const FileModel = Layer.Core.Client.getMessageTypeModelClass('FileModel');

// Send the raw file
const model = new FileModel({
  source: FileObj, // Javascript File object
  title: "expense-report.pdf",
  author: layerClient.user.displayName
});
model.send({ conversation });

// Send a reference to a file
const model = new FileModel({
  sourceUrl: "https://raw.githubusercontent.com/layerhq/web-xdk/master/README.md",
  title: "WebSDK README file",
  author: "Layer"
});
model.send({ conversation });

The File Model supports the following properties:

Name Required Type Description
title No NSString Title for the File Message
author No NSString Rendered below the title
fileMIMEType No NSString MIME Type of the file
size No NSUInteger Represents the size of the file in number of Bytes
createdAt No NSDate Date of file creation
updatedAt No NSDate Date of file last update
sourceUrl No NSURL URL to a remote file
sourceLocalUrl No NSURL URL to a local file

Note

  • source or sourceUrl must be provided for this to be a valid File Message.
  • Do not use both source and sourceUrl.

Image Messages

An Image Message has a few uses:

  • Allow a user to drag and drop one or more Images from their desktop and send them as Messages that just show the image and nothing more
  • Allow an application to send images with titles, subtitles and other annotations. For example, one might send a product picture with the name and description of the product associated with it.
Basic Image Message
Image with Details

A Image Message can be instantiated using:

LYRUIImageMessage *imageMessage = [[LYRUIImageMessage alloc] initWithImage:image
                                                              previewImage:image.lyr_thumbnail];
});

The Image Model supports the following properties:

Name Required Type Description
title No NSString Title for the Image Message
subtitle No NSString Rendered below the title
artist No NSString Rendered below the subtitle
fileName No NSString Name of the image file
imageMIMEType No NSString MIME Type of the image
size No CGSize Width and height of the source image
previewSize No CGSize Width and height of the preview image
createdAt No NSDate Date of image creation
orientation No NSUInteger EXIF orientation of the image
previewImageUrl No NSURL URL to a remote preview image
previewImageLocalUrl No NSURL URL to a local preview image file
sourceImageUrl No NSURL URL to a remote source image
sourceImageLocalUrl No NSURL URL to a local source image file

Note

  • source or sourceUrl must be provided for this to be a valid Image Message.
  • Do not use both source and sourceUrl.
  • If using sourceUrl, you should provide a width and height value. width and height will be added automatically if providing an File/Blob representing an Image.

Location Messages

A Location Message has a few uses:

  • Show a map of a location; perhaps a restaurant to meet at? A house to sell? Or just your current position in the world
  • Show an address, for example, as a sub-message-view of a Receipt Message

Just the map:

Just a Map
Map with Details
Map with Address

A Location Message can be instantiated using:

CLLocation *location = [[CLLocation alloc] initWithLatitude:37.7777405
                                                  longitude:-122.3959881];
LYRUILocationMessage *locationMessage = [[LYRUILocationMessage alloc] initWithLocation:location];

The Location Model supports the following properties:

Name Required Type Description
location Yes CLLocation Latitude and longitude of the location
zoom No NSUInteger Zoom level from 1 - 18; defaults to 17; see Google Maps API
title No NSString Title for the Location Message
contentDescription No NSString Rendered below the title. If present, will be rendered instead of an Address.
street1 No NSString String address line 1
street2 No NSString String address line 2
city No NSString City that the location is within
administrativeArea No NSString Name of the state or comparable unit of region
postalCode No NSString Zipcode or some regionally comparable concept
country No NSString Country code or name

Note

  • To only show the map, and no other information, include latitude and longitude, and leave out titles, addresses and descriptions.
  • If you want to render an Address instead of the description, leave the description empty.

Status Messages

A Status Message is a Message within the Message List that:

  • Does not have an avatar, nor indicate any sender
  • Is centered rather than right or left aligned as though it came from one or the other participant
  • Does not have a timestamp
  • Supports only textual information
A simple Status Message

A Status Message can be instantiated using:

NSString *statusMessageText = @"...";
LYRUIStatusMessage *statusMessage = [[LYRUIStatusMessage alloc] initWithText:statusMessageText];

The Status Model supports the following properties:

Name Required Type Description
text Yes NSString This is the core data rendered by the Core UI for this Message

The Carousel Message presents an arbitrary collection of sub-message-views in a left-right scrolling view.

While one can create a Carousel that contains a mix of Image Messages, Text Messages, Product Messages, Button Messages, etc… for best results, the Caroursel items:

  1. Should all be of the same type
  2. Should all contain similar sizes and quantities of content
Carousel of File Messages

A Carousel Message can be created using:

Its important to understand that a Carousel Message’s action.event and action.data will override all of the Carousel Item’s default actions. In the above example, the default action on each FileModel is open-file. We can change that as follows:

When the user clicks on ANY of the Messages specified in items, it will invoke the delete-file action on the Carousel Item, and will NOT trigger an open-file action. NOTE: If any of the items specifies its own action.event, this will not be overwritten; only default values for action.event are overwritten.

Futher, you can add custom action data:

If your custom delete-file event handler checks for the evt.detail.data.confirm_deletion it will know whether to directly delete the file or ask for confirmation. action.data will be mixed into any existing action.data on each Carousel Item, and will not overwrite any action.data values explicitly entered for a given sub-message within the carousel; this means that individual Carousel Items could have their own value for evt.detail.data.confirm_deletion.

The Carousel Model supports the following properties:

Name Required Type Description
carouselItemMessages Yes NSArray<LYRUIMessageType *> Array of Message Type Models representing the Items the Carousel will scroll through

Choice Messages

The Choice Message presents the user with a set of choices to make, and when the user has made their selection, it updates the message’s state for all participants in the Conversation.

Note

This Message, unlike others, depends upon a Message Response Integration Service which you will need to install.

Choice with No Selection
Choice with Selection and allowReselect: false

A Choice Message, configured to not allow Reselection:

The above Choice Message will ask the user the specified question, and provide the specified choices for the user to choose from. When the recipient selects an answer, the following actions will be performed:

  1. A Response Message is sent indicating what the user selected, and providing a textual description of that selection
  2. A Response Message is rendered for all participants, representing that Response Message, and informing all users of the change in the state of the Message. It might say something like “User X has selected Are we using Imperial or Metric units?”.
  3. The Message’s local state is promptly updated for the user who made the selection, providing quick feedback to the user that the selection was accepted.
  4. The Message Response Integration Service receives the Response Message, and updates the original Choice Message with the user’s Selection
  5. All other participants receive the update to the Choice Message, and now all users see the selection.

The choices array is designed to have an id so that edits to the text values may eventually be supported, while leaving the id values unchanged. This would leave the user’s selections intact, while allowing for tweaks to the text.

The Buttons Model supports the following properties:

Name Required Type Description
title No NSString The default title of Choose One can be replaced by providing your own title
label No NSString A question to ask the user
contentMessage No NSString Currently, a question to ask the user converted into LYRUITextMessage, used to display as Choice Message content view
type No LYRUIChoiceMessageType Display type: Default or Label. Label is currently used only to present just the selected choice in form of label in Product Message
expandedType No NSString A display type, used when viewing choice message in an expanded/zoomed view.
choices Yes NSArray<LYRUIChoice *> Available choices
allowReselect No BOOL Allow the user to change selection
allowDeselect No BOOL Allow the user to click a selected item to deselect it
allowMultiselect No BOOL Allow the user to select multiple choices
responseName No NSString The name of the response field that will be set by selecting any of the choices in the Choices Button.
customResponseData No NSDictionary Dictionary of custom data to add to the response when any choice is selected
preselectedChoice No NSString Default selected choice id
selectedChoices No NSOrderedSet<NSString *> Id’s of choices selected by users
responseMessageId No NSString Id of the LYRMessage to which the Response Message with selections should be sent
responseNodeId No NSString Id of the LYRMessagePart to which the Response Message with selections should be sent

LYRUIChoice properties:

Name Required Type Description
identifier Yes NSString Identifier of the choice
text Yes NSString Title for the Choice
customResponseData No NSDictionary Dictionary of custom data to add to the response when the choice is selected
selectedStateProperties.text No NSString Title for the Choice when selected

Note

  • allowReselect is enforced client side, not server side, and should not be treated as securely enforced at this time.
  • Failure to set a responseName to a unique name could cause different message interactions to overwrite one another. This should not matter for simple messages, but for complicated messages with multiple types of state and interactions it can easily cause errors.
  • Default responseName is selection.

Button Messages

Most of the messages described up above are minimally interactive. Except for the Choice Message, the only action they provide is that if you click/select them, they try to open something or trigger an event. The Buttons Message allows you to take any other Message and add Actions to it.

Product Message wrapped in a Button Message. Button Message provides all buttons shown above.

For a button with an event of open-url, one of the following will occur:

  • Your button’s data.url will be opened if present
  • Your Button Model’s contentModel.url will be opened if present
  • No action will occur

Typically, your event will either be open-url (or other Layer provided event) or a custom action that will be triggered on the DOM for your event handler to listen for.

The Buttons Model supports the following properties:

Name Required Type Description
contentMessage No LYRUIMessageType A Message Type Model for a a sub-message-model that will have buttons attached to it; however, buttons can be sent without any content.
buttons Yes NSArray<LYRUIButtonsMessageActionButton *> Array of objects describing the buttons to add

LYRUIButtonsMessageActionButton properties:

Name Required Type Description
type Yes NSString “action”
title Yes NSString Title for the Button
action No LYRUIMessageAction Action to trigger when the button is clicked

Button Message with Choice Buttons

The Choice Buttons within the Button Message enables an app to persist a user’s selection and share it with all participants. These selections are designed for a single user only to perform the selection, and for that selection to become a permanent part of that Message. Only a single state name can be set by a given Button Set; you can not set multiple types of state in a single Button Set.

Button Message that does not wrap another message, and which provides 3 choices

The following properties can be used with the ButtonModel constructor to setup your Choice Buttons:

Name Required Type Description
type Yes NSString “choice”
choices Yes NSArray<LYRUIChoice *> Available choices
allowReselect No BOOL Allow the user to change selection
allowDeselect No BOOL Allow the user to click a selected item to deselect it
allowMultiselect No BOOL Allow the user to select multiple choices
responseName No NSString The name of the response field that will be set by selecting any of the choices in the Choices Button.
customResponseData No NSDictionary Dictionary of custom data to add to the response when any choice is selected
preselectedChoice No NSString Default selected choice id
selectedChoices No NSOrderedSet<NSString *> Id’s of choices selected by users
responseMessageId No NSString Id of the LYRMessage to which the Response Message with selections should be sent
responseNodeId No NSString Id of the LYRMessagePart to which the Response Message with selections should be sent

LYRUIChoice properties:

Name Required Type Description
identifier Yes NSString Identifier of the choice
text Yes NSString Title for the Choice
customResponseData No NSDictionary Dictionary of custom data to add to the response when the choice is selected
selectedStateProperties.text No NSString Title for the Choice when selected

Note

  • Failure to set a data.responseName to a unique name could cause different Message Response interactions to overwrite one another.
  • Default responseName is selection.
  • A Button Message may contain both Action buttons and Choice Buttons

Product Messages

The Product Message represents a product for sale. Unlike many other informational Messaging Experiences, this does not depend upon the Standard Message Container which provides a standard layout of information. There is a lot of custom information about a product that needs to be shown. Typically this Message would be used to allow a user to purchase, bookmark or perhaps return a Product. Such actions are attached using the Buttons Message.

Standard Product Message

The Product Model supports the following properties:

Name Required Type Description
brand No NSString Brand of your product
name No NSString Name of your product
productDescription No NSString One or more lines of product description
imageURLs No NSArray<NSURL *> Array of URLs to a product pictures. Currently only the first is rendered.
price No double Cost per unit of this product
quantity No NSUInteger Number of units of the product; defaults to 1
currency No NSString ISO 4217 currency codes; default is USD
options No NSArray<LYRUIChoiceMessage *> Array of Choice models representing options for this product (clothing size, CPU speed, etc…). At this time, only Choice with type Label is supported

Note

Currently, only a ChoiceModel with type='label' is supported. Future versions may allow type values that allow users to select a choice and update the state of the Message.

Receipt Messages

The Receipt Message is a Message that renders:

  • a list of Products
  • a shipping address
  • a total price
  • payment info
Standard Receipt Message

The Receipt Model supports the following properties:

Name Required Type Description
createdAt No NSDate Date of creation
currency No NSString ISO 4217 currency codes; default is USD
paymentMethod Yes String Arbitrary string, often of the form “Visa ****-XXXX”
discounts No NSArray<LYRUIReceiptDiscount *> List of discounts added to the receipt; not in the basic Receipt Message View
order No LYRUIReceiptOrder Object describing the Order
summary Yes LYRUIReceiptSummary Summary of the order
shippingAddress No LYRUILocationMessage The shipping address; rendered in the basic Receipt Message View
billingAddress No LYRUILocationMessage A billing address; not rendered in the basic Receipt Message View
products Yes NSArray<LYRUIProductMessage *> Array of products that are to be displayed as part of the purchase

LYRUIReceiptDiscount properties:

Name Required Type Description
name No NSString Name describing the discount
amount Yes double Ammount substracted from the starting price

LYRUIReceiptOrder properties:

Name Required Type Description
number Yes NSString Order Number / Order ID
URL No NSURL Order URL

LYRUIReceiptSummary properties:

Name Required Type Description
shippingCost No double Shipping charges for the purchase (not currently rendered)
subtotal No double Sum of costs of all products (Not currently rendered)
totalCost No double Sum of all costs including shipping price; this is always rendered
totalTax No double Total taxes for the purchase (not currently rendered)
Misc Components Custom Message Types