|
| 1 | +import { Tab, Tabs } from 'nextra-theme-docs' |
| 2 | +import { Callout } from 'nextra-theme-docs' |
| 3 | + |
| 4 | +# Tebex Module |
| 5 | + |
| 6 | +## Overview |
| 7 | + |
| 8 | +The Tebex module allows Lunar Client users to complete purchases directly within the game, providing a faster, more seamless checkout experience. |
| 9 | + |
| 10 | +**Overlay Mode** |
| 11 | + |
| 12 | +This mode displays the Tebex checkout flow as an overlay on the Minecraft window, similar to opening an inventory. It provides the most seamless experience and is the preferred method. Overlay mode is only available on **Windows**. |
| 13 | + |
| 14 | + |
| 15 | + |
| 16 | +**Window Mode** |
| 17 | + |
| 18 | +As a fallback, and for **macOS** and **Linux** users, a separate window opens to display the Tebex checkout flow. While not as seamless as overlay mode, this ensures compatibility across all operating systems. |
| 19 | + |
| 20 | + |
| 21 | + |
| 22 | +## Usage Guidelines |
| 23 | + |
| 24 | +To ensure a smooth user experience, servers must only open checkout windows from user-initiated actions. Examples include, but aren't limited to: |
| 25 | + |
| 26 | +**Allowed (User-Initiated Actions):** |
| 27 | +- Clicking a link in chat |
| 28 | +- Running a command |
| 29 | +- Clicking a button in a GUI |
| 30 | + |
| 31 | +**Not Allowed (Automated/Intrusive Actions):** |
| 32 | +- Triggering on login |
| 33 | +- Automatically opening at set intervals (e.g., every 30 minutes) |
| 34 | +- Automatically opening during flash sales, events, or other promotions without user interaction |
| 35 | + |
| 36 | +This feature is designed to enhance the user experience by providing a seamless checkout process, misuse of this module, such as creating a disruptive or intrusive purchase flow, will result in restricted access in the future. |
| 37 | + |
| 38 | +## Integration |
| 39 | + |
| 40 | +The only piece of information sent from the server to the client to trigger a checkout window is the **Tebex basket ident**. This unique identifier represents an in-progress basket and later converts into a **Tebex transaction ID (tbx-...)** upon purchase. |
| 41 | + |
| 42 | +Optionally, a **locale** value can also be sent to specify the language and regional formatting used when rendering the checkout window (e.g., `en-US`). If no locale is provided, the default locale settings will be used. |
| 43 | + |
| 44 | +If a player is not using Lunar Client, the same Tebex basket can be used on the web at: `https://pay.tebex.io/<basket>` |
| 45 | + |
| 46 | +**Example flow** |
| 47 | +1. Create a basket using the Tebex Headless API. |
| 48 | +2. Add package(s) to basket with Tebex Headless API |
| 49 | +3. If the player is using Lunar Client: Send an Apollo packet to open the checkout modal. |
| 50 | +4. If the player is not using Lunar Client: Send a chat message with a Tebex payment link. |
| 51 | + |
| 52 | +**Tebex Headless API** |
| 53 | + |
| 54 | +Basket idents are created via the [Tebex Headless API](https://docs.tebex.io/developers/headless-api/overview). This API allows programmatic basket creation, package additions, coupon applications, and more. The [Lunar Client Store](https://store.lunarclient.com/) is built on this API, and it is enabled by default for all Tebex stores. |
| 55 | + |
| 56 | +**Getting started with the Tebex Headless API** |
| 57 | + |
| 58 | +🔗 [Documentation](https://docs.tebex.io/developers/headless-api/overview)<br/> |
| 59 | +🔗 [Java SDK](https://github.com/tebexio/TebexHeadless-OpenAPI/tree/main/sdks/java)<br/> |
| 60 | + |
| 61 | +Most implementations of Embedded Checkout only require two API endpoints: |
| 62 | +1. Creating a basket |
| 63 | +2. Adding packages to a basket |
| 64 | + |
| 65 | +For simplicity, you may opt to handle these requests manually rather than using the SDK. |
| 66 | + |
| 67 | +**API Authentication** |
| 68 | + |
| 69 | +You’ll need your **public token** and **private key** from: [Tebex API Keys](https://creator.tebex.io/developers/api-keys) |
| 70 | + |
| 71 | +<Callout type="warning" emoji="⚠️"> |
| 72 | + Never share these credentials with Lunar Client or external servers. They should only be used while communicating with Tebex Headless. |
| 73 | +</Callout> |
| 74 | + |
| 75 | +### Sample Code |
| 76 | +Explore each integration by cycling through each tab to find the best fit for your requirements and needs. |
| 77 | + |
| 78 | +<Tabs items={['Apollo API', 'apollo-protos library', 'Manual JSON Object Construction']}> |
| 79 | + |
| 80 | +<Tab> |
| 81 | + |
| 82 | +**Display Tebex Embedded Checkout** |
| 83 | + |
| 84 | +```java |
| 85 | +public void displayTebexEmbeddedCheckoutExample(Player viewer, String basketIdent, String locale) { |
| 86 | + Optional<ApolloPlayer> apolloPlayerOpt = Apollo.getPlayerManager().getPlayer(viewer.getUniqueId()); |
| 87 | + |
| 88 | + if (!apolloPlayerOpt.isPresent()) { |
| 89 | + viewer.sendMessage("Complete your purchase at https://pay.tebex.io/" + basketIdent); |
| 90 | + return; |
| 91 | + } |
| 92 | + |
| 93 | + ApolloPlayer apolloPlayer = apolloPlayerOpt.get(); |
| 94 | + TebexEmbeddedCheckoutSupport embeddedCheckoutSupport = apolloPlayer.getTebexEmbeddedCheckoutSupport(); |
| 95 | + |
| 96 | + if (embeddedCheckoutSupport == TebexEmbeddedCheckoutSupport.UNSUPPORTED) { |
| 97 | + viewer.sendMessage("Complete your purchase at https://pay.tebex.io/" + basketIdent); |
| 98 | + return; |
| 99 | + } |
| 100 | + |
| 101 | + this.tebexModule.displayTebexEmbeddedCheckout(apolloPlayerOpt.get(), basketIdent, locale); |
| 102 | + |
| 103 | + if (embeddedCheckoutSupport == TebexEmbeddedCheckoutSupport.OVERLAY) { |
| 104 | + viewer.sendMessage("Opening checkout as game overlay!"); |
| 105 | + } else { |
| 106 | + viewer.sendMessage("Opening checkout in an external window!"); |
| 107 | + } |
| 108 | +} |
| 109 | +``` |
| 110 | + |
| 111 | +</Tab> |
| 112 | + |
| 113 | +<Tab> |
| 114 | + |
| 115 | +**Display Tebex Embedded Checkout** |
| 116 | + |
| 117 | +<Callout type="info"> |
| 118 | + To detect embedded checkout support type visit [Apollo Serverbound packets](/apollo/developers/lightweight/protobuf/serverbound-packets) |
| 119 | +</Callout> |
| 120 | + |
| 121 | +```java |
| 122 | +public void displayTebexEmbeddedCheckoutExample(Player viewer, String basketIdent, String locale) { |
| 123 | + OpenTebexEmbeddedCheckoutMessage.Builder builder = OpenTebexEmbeddedCheckoutMessage.newBuilder() |
| 124 | + .setBasketIdent(basketIdent); |
| 125 | + |
| 126 | + if (locale != null) { |
| 127 | + builder.setLocale(locale); |
| 128 | + } |
| 129 | + |
| 130 | + OpenTebexEmbeddedCheckoutMessage message = builder.build(); |
| 131 | + ProtobufPacketUtil.sendPacket(viewer, message); |
| 132 | +} |
| 133 | +``` |
| 134 | + |
| 135 | +</Tab> |
| 136 | + |
| 137 | +<Tab> |
| 138 | + |
| 139 | +**Display Tebex Embedded Checkout** |
| 140 | + |
| 141 | +```java |
| 142 | +public void displayTebexEmbeddedCheckoutExample(Player viewer, String basketIdent, String locale) { |
| 143 | + JsonObject message = new JsonObject(); |
| 144 | + message.addProperty("@type", "type.googleapis.com/lunarclient.apollo.tebex.v1.OpenTebexEmbeddedCheckoutMessage"); |
| 145 | + message.addProperty("basket_ident", basketIdent); |
| 146 | + |
| 147 | + if (locale != null) { |
| 148 | + message.addProperty("locale", locale); |
| 149 | + } |
| 150 | + |
| 151 | + JsonPacketUtil.sendPacket(viewer, message); |
| 152 | +} |
| 153 | +``` |
| 154 | + |
| 155 | +</Tab> |
| 156 | + |
| 157 | +</Tabs> |
0 commit comments