{"id":58843,"date":"2023-10-06T12:13:52","date_gmt":"2023-10-06T06:43:52","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=58843"},"modified":"2024-01-02T17:37:01","modified_gmt":"2024-01-02T12:07:01","slug":"streamlining-roku-pay-integration-with-channelstorehelper","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/streamlining-roku-pay-integration-with-channelstorehelper\/","title":{"rendered":"Streamlining Roku Pay Integration with ChannelStoreHelper"},"content":{"rendered":"<h2><b>Introduction<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Roku Pay integration can be a daunting task for developers, but fear not! `ChannelStoreHelper` is here for the rescue. Included in the Roku starter kit, this script file is your ticket to hassle-free implementation of Roku Pay on the front-end of your Roku application. With a single function call, you can kickstart Roku Pay, provided you&#8217;ve already set up your channel on the Roku developer dashboard. Read on to get a simple and minimalistic Roku channel setup with Roku pay flow.<\/span><\/p>\n<h2><b>Dashboard Setup<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Before diving into Roku Pay implementation, there are a few crucial steps to complete on the Roku developer dashboard:<\/span><\/p>\n<ol>\n<li><b>Register\/Login<\/b><span style=\"font-weight: 400;\">: Access the [developer dashboard](https:\/\/developer.roku.com\/dev\/dashboard) and create an account.<\/span><\/li>\n<li><b>Add a Channel<\/b><span style=\"font-weight: 400;\">: Navigate to &#8220;My Channels&#8221; and click &#8220;Add Channel&#8221; [here](https:\/\/developer.roku.com\/developer-channels\/channels).<\/span><\/li>\n<li><b>Add Products<\/b><span style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">: After adding your channel, visit &#8220;Products&#8221; [here](https:\/\/developer.roku.com\/channel-products?tab=TAB_SINGLE_PRODUCT) to add the products you intend to offer.<\/span><\/span><\/li>\n<\/ol>\n<p><span style=\"font-weight: 400;\">Once you&#8217;ve successfully added your products, your dashboard setup is complete. <\/span><\/p>\n<p><span style=\"font-weight: 400;\">Note<em>: Any monetization activities on the developer dashboard require your account to be enrolled in the Roku Partner Payouts Programme<\/em>.\u00a0<\/span><\/p>\n<h2><b>Front-end Setup<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">With the dashboard set up and products added, your Roku device must be logged in with the same root account used for the dashboard setup. Roku enforces this limitation for the initial implementation and testing of Roku Pay functionality.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">To import the `ChannelStoreHelper` file into your project, follow these steps:<\/span><\/p>\n<ol>\n<li><b>Add the File<\/b><span style=\"font-weight: 400;\">: Drag and drop `ChannelStoreHelper.brs` or `ChannelStoreHelper.bs` into your project.<\/span><\/li>\n<li><b>Include\/Import<\/b><span style=\"font-weight: 400;\">: Include or import the file in your `MainScene.xml` or `MainScene.bs` as follows:<\/span><\/li>\n<\/ol>\n<ul>\n<li><span style=\"font-weight: 400;\">\u00a0 \u00a0For BrightScript (brs): <\/span><\/li>\n<\/ul>\n<pre><span style=\"font-weight: 400;\">`&lt;script type=\"text\/brightscript\" uri=\"pkg:\/components\/MainScene\/ChannelStoreHelper\/ChannelStoreHelper.brs\" \/&gt;`<\/span><\/pre>\n<ul>\n<li><span style=\"font-weight: 400;\">\u00a0 \u00a0For BrightScript (bs): <\/span><\/li>\n<\/ul>\n<pre><span style=\"font-weight: 400;\">`import \"pkg:\/components\/MainScene\/ChannelStoreHelper\/ChannelStoreHelper.bs\"`<\/span><\/pre>\n<ol start=\"3\">\n<li><b>Global Field<\/b><span style=\"font-weight: 400;\">: Add a global field for the channel store in your `main.brs`:<\/span><\/li>\n<\/ol>\n<blockquote>\n<pre><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0m.global.AddField(\"channelStore\", \"node\", false)<\/span><\/pre>\n<\/blockquote>\n<ol start=\"4\">\n<li><b>Initialize<\/b><span style=\"font-weight: 400;\">: Initialize and assign a value to the global node in `MainScene.brs` or `MainScene.bs`:<\/span><\/li>\n<\/ol>\n<blockquote>\n<pre><span style=\"font-weight: 400;\">\u00a0\u00a0\u00a0m.global.channelStore = CreateObject(\"roSGNode\", \"ChannelStore\")<\/span><\/pre>\n<\/blockquote>\n<p><span style=\"font-weight: 400;\">With these steps, the `ChannelStoreHelper` is now successfully integrated into your project, ready to process the inputs needed for Roku Pay functionality.\u00a0<\/span><\/p>\n<h2><b>Roku Pay Overview<\/b><\/h2>\n<div style=\"width: 2967px\" class=\"wp-caption aligncenter\"><img decoding=\"async\" loading=\"lazy\" class=\"size-medium\" src=\"\/blog\/wp-ttn-blog\/uploads\/2024\/01\/roku-pay-flow-v8.png\" alt=\"Roku Pay Flow Diagram\" width=\"2957\" height=\"2241\" \/><p class=\"wp-caption-text\">Roku Pay Flow Diagram<\/p><\/div>\n<p><span style=\"font-weight: 400;\">Roku Pay&#8217;s payment flow is based on the `ChannelStore` node, an essential component of Roku&#8217;s SceneGraph framework. This framework underpins modern Roku applications and offers simple call-and-observe functionality for executing actions like purchase orders. Key commands included in the `ChannelStore` node are:<\/span><\/p>\n<h3><b>Purchasing<\/b><\/h3>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-59242 size-large\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/10\/Roku2-1024x439.png\" alt=\"\" width=\"625\" height=\"268\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/10\/Roku2-1024x439.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/10\/Roku2-300x129.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/10\/Roku2-768x329.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/10\/Roku2-624x267.png 624w, \/blog\/wp-ttn-blog\/uploads\/2023\/10\/Roku2.png 1500w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><\/p>\n<ul>\n<li><span style=\"font-weight: 400;\"><strong>`getCatalog`<\/strong>: Retrieves subscription and one-time purchase products&#8217; metadata.<\/span><\/li>\n<li><span style=\"font-weight: 400;\"><strong>`getUserData<\/strong>`: Fetches customer&#8217;s Roku account information.<\/span><\/li>\n<li><span style=\"font-weight: 400;\"><strong>`doOrder`<\/strong>: Completes transactions for customer purchases.<\/span><\/li>\n<\/ul>\n<h3><b>Entitlements and Authentication<\/b><\/h3>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-59243 size-large\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/10\/Roku3-1024x407.png\" alt=\"\" width=\"625\" height=\"248\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/10\/Roku3-1024x407.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/10\/Roku3-300x119.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/10\/Roku3-768x305.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/10\/Roku3-624x248.png 624w, \/blog\/wp-ttn-blog\/uploads\/2023\/10\/Roku3.png 1500w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><\/p>\n<ul>\n<li><span style=\"font-weight: 400;\"><strong>`getPurchases`<\/strong>: Gets all active subscriptions for the customer.<\/span><\/li>\n<li><span style=\"font-weight: 400;\"><strong>`getAllPurchases`<\/strong>: Similar to `getPurchases,` but includes expired and canceled subscriptions.<\/span><\/li>\n<li><span style=\"font-weight: 400;\"><strong>`storeChannelCredData`<\/strong>: Stores the publisher&#8217;s access token for in-channel products in the Roku cloud.<\/span><\/li>\n<li><span style=\"font-weight: 400;\"><strong>`getChannelCred`<\/strong>: Retrieves the publisher&#8217;s access token for in-channel products from the Roku cloud.<\/span><\/li>\n<\/ul>\n<h2><b>Functional Specification<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">Now, let&#8217;s delve into the functions implemented in the `ChannelStoreHelper` file:<\/span><\/p>\n<ul>\n<li><span style=\"font-weight: 400;\"><strong>`sub CheckSubscriptionAndStartPlayback()`<\/strong>: Initiates the Roku Pay flow, ideal for checking subscriptions before allowing content playback.<\/span><\/li>\n<li><span style=\"font-weight: 400;\"><strong>`function initiateRFIConsentForUserdata()`<\/strong>: Starts the RFI content screen, requesting the user&#8217;s permission to use their Roku-associated email address.<\/span><\/li>\n<li><span style=\"font-weight: 400;\"><strong>`function onGetUserData()`<\/strong>: Observer function for `getUserData`, receiving the user&#8217;s email address and calling `RunSubscriptionFlow()` on successful output.<\/span><\/li>\n<li><span style=\"font-weight: 400;\"><strong>`sub RunSubscriptionFlow()`<\/strong>: Displays a progress dialog while executing the `getPurchases` command.<\/span><\/li>\n<li><span style=\"font-weight: 400;\"><strong>`sub OnGetPurchases(event as object)`<\/strong>: Observes the output of `getPurchases`, checking and validating active subscriptions. This function provides a resume point for the application flow.<\/span><\/li>\n<li><span style=\"font-weight: 400;\"><strong>`sub OnGetCatalog(event as object)`<\/strong>: Observes the output of `getCatalog`, displaying product options set up in the dashboard.<\/span><\/li>\n<li><span style=\"font-weight: 400;\"><strong>`sub DoSubscriptionOrder(event as object)`<\/strong>: Initiates purchase of selected products.<\/span><\/li>\n<li><span style=\"font-weight: 400;\"><strong>`sub OnOrderStatus(event as object)`<\/strong>: Observer function for purchase output, marking the endpoint of the Roku Pay flow.<\/span><\/li>\n<\/ul>\n<h3><b>Code Snippets<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">Here are snippets from the main.brs and MainScene.xml files:<\/span><\/p>\n<h3><b>main.brs<\/b><span style=\"font-weight: 400;\">:<br \/>\n<\/span><em><span style=\"font-weight: 400;\">brightscript<\/span><\/em><\/h3>\n<blockquote>\n<pre><span style=\"font-weight: 400;\">sub<\/span><span style=\"font-weight: 400;\"> showChannelSGScreen()<\/span>\r\n<span style=\"font-weight: 400;\">screen <\/span><span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">CreateObject<\/span><span style=\"font-weight: 400;\">(<\/span><span style=\"font-weight: 400;\">\"<\/span><span style=\"font-weight: 400;\">roSGScreen<\/span><span style=\"font-weight: 400;\">\"<\/span><span style=\"font-weight: 400;\">)<\/span>\r\n<span style=\"font-weight: 400;\">m.port <\/span><span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">CreateObject<\/span><span style=\"font-weight: 400;\">(<\/span><span style=\"font-weight: 400;\">\"<\/span><span style=\"font-weight: 400;\">roMessagePort<\/span><span style=\"font-weight: 400;\">\"<\/span><span style=\"font-weight: 400;\">)<\/span>\r\n<span style=\"font-weight: 400;\">screen.setMessagePort(m.port)<\/span>\r\n<span style=\"font-weight: 400;\">scene <\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\"> screen.CreateScene(<\/span><span style=\"font-weight: 400;\">\"MainScene\"<\/span><span style=\"font-weight: 400;\">)<\/span>\r\n<span style=\"font-weight: 400;\">m.global <\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\"> screen.getGlobalNode()<\/span>\r\n\r\n<span style=\"font-weight: 400;\">m.global.id <\/span><span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">\"GlobalNode\"<\/span>\r\n<span style=\"font-weight: 400;\">m.global.addFields({ adID : <\/span><span style=\"font-weight: 400;\">\"\"<\/span><span style=\"font-weight: 400;\"> })<\/span>\r\n<span style=\"font-weight: 400;\">m.global.addFields({ deviceName : <\/span><span style=\"font-weight: 400;\">\"\"<\/span><span style=\"font-weight: 400;\"> })<\/span>\r\n<span style=\"font-weight: 400;\">m.global.addFields({ uid : <\/span><span style=\"font-weight: 400;\">\"\"<\/span><span style=\"font-weight: 400;\"> })<\/span>\r\n<span style=\"font-weight: 400;\">m.global.addFields({ locale : <\/span><span style=\"font-weight: 400;\">\"\"<\/span><span style=\"font-weight: 400;\"> })<\/span>\r\n<span style=\"font-weight: 400;\">m.global.addFields({ networkType : <\/span><span style=\"font-weight: 400;\">\"\"<\/span><span style=\"font-weight: 400;\"> })<\/span>\r\n<span style=\"font-weight: 400;\">m.global.addFields({ memoryLevel : <\/span><span style=\"font-weight: 400;\">\"\"<\/span><span style=\"font-weight: 400;\"> })<\/span>\r\n<span style=\"font-weight: 400;\">m.global.addFields({ deviceID : <\/span><span style=\"font-weight: 400;\">\"\"<\/span><span style=\"font-weight: 400;\"> })<\/span>\r\n<span style=\"font-weight: 400;\">m.global.addFields({ osVersion : <\/span><span style=\"font-weight: 400;\">\"\"<\/span><span style=\"font-weight: 400;\"> })<\/span>\r\n<span style=\"font-weight: 400;\">m.global.addFields({ appVersion : <\/span><span style=\"font-weight: 400;\">\"\"<\/span><span style=\"font-weight: 400;\"> })<\/span>\r\n<span style=\"font-weight: 400;\">m.global.addFields({ buildNo : <\/span><span style=\"font-weight: 400;\">\"\"<\/span><span style=\"font-weight: 400;\"> })<\/span>\r\n<span style=\"font-weight: 400;\">m.global.addFields({ uidValue : <\/span><span style=\"font-weight: 400;\">\"\"<\/span><span style=\"font-weight: 400;\"> })<\/span>\r\n<span style=\"font-weight: 400;\">m.global.addFields({ modelName : <\/span><span style=\"font-weight: 400;\">\"\"<\/span><span style=\"font-weight: 400;\"> })<\/span>\r\n<span style=\"font-weight: 400;\">m.global.addFields({ isPaidUser : <\/span><span style=\"font-weight: 400;\">false<\/span><span style=\"font-weight: 400;\"> })<\/span>\r\n<span style=\"font-weight: 400;\">m.global.addField(<\/span><span style=\"font-weight: 400;\">\"channelStore\"<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">\"node\"<\/span><span style=\"font-weight: 400;\">, <\/span><span style=\"font-weight: 400;\">false<\/span><span style=\"font-weight: 400;\">) <\/span><span style=\"font-weight: 400;\">\u2018 add <\/span><b>channelstore<\/b><span style=\"font-weight: 400;\"> node<\/span>\r\n<span style=\"font-weight: 400;\">screen.<\/span><span style=\"font-weight: 400;\">show<\/span><span style=\"font-weight: 400;\">()<\/span>\r\n\r\n<span style=\"font-weight: 400;\">while<\/span><span style=\"font-weight: 400;\">(<\/span><span style=\"font-weight: 400;\">true<\/span><span style=\"font-weight: 400;\">)<\/span>\r\n<span style=\"font-weight: 400;\">msg <\/span><span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">wait<\/span><span style=\"font-weight: 400;\">(<\/span><span style=\"font-weight: 400;\">0<\/span><span style=\"font-weight: 400;\">, m.port)<\/span>\r\n<span style=\"font-weight: 400;\">msgType <\/span><span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">type<\/span><span style=\"font-weight: 400;\">(msg)<\/span>\r\n<span style=\"font-weight: 400;\">if<\/span><span style=\"font-weight: 400;\"> msgType <\/span><span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">\"<\/span><span style=\"font-weight: 400;\">roSGScreenEvent<\/span><span style=\"font-weight: 400;\">\"<\/span>\r\n<span style=\"font-weight: 400;\">if<\/span><span style=\"font-weight: 400;\"> msg.isScreenClosed() <\/span><span style=\"font-weight: 400;\">then<\/span> <span style=\"font-weight: 400;\">return<\/span>\r\n<span style=\"font-weight: 400;\">end if<\/span>\r\n<span style=\"font-weight: 400;\">end while<\/span>\r\n<span style=\"font-weight: 400;\">end sub<\/span><\/pre>\n<\/blockquote>\n<h3><b>MainScene.xml<\/b><span style=\"font-weight: 400;\">:<\/span><\/h3>\n<h3><i><span style=\"font-weight: 400;\">xml<\/span><\/i><\/h3>\n<blockquote>\n<pre><i><span style=\"font-weight: 400;\">&lt;!-- importing main handler --&gt;<\/span><\/i>\r\n<span style=\"font-weight: 400;\">&lt;<\/span><span style=\"font-weight: 400;\">script<\/span> <span style=\"font-weight: 400;\">type<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">\"<\/span><span style=\"font-weight: 400;\">text\/brightscript<\/span><span style=\"font-weight: 400;\">\"<\/span>\r\n<span style=\"font-weight: 400;\">uri<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">\"<\/span><span style=\"font-weight: 400;\">pkg:\/components\/MainScene\/MainScene.brs<\/span><span style=\"font-weight: 400;\">\"<\/span> <span style=\"font-weight: 400;\">\/&gt;<\/span>\r\n<span style=\"font-weight: 400;\">&lt;<\/span><span style=\"font-weight: 400;\">script<\/span> <span style=\"font-weight: 400;\">type<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">\"<\/span><span style=\"font-weight: 400;\">text\/brightscript<\/span><span style=\"font-weight: 400;\">\"<\/span>\r\n<span style=\"font-weight: 400;\">uri<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">\"<\/span><span style=\"font-weight: 400;\">pkg:\/components\/MainScene\/MainSceneExtension.brs<\/span><span style=\"font-weight: 400;\">\"<\/span> <span style=\"font-weight: 400;\">\/&gt;<\/span>\r\n<span style=\"font-weight: 400;\">&lt;!-- importing <\/span><b>ChannelStoreHelper<\/b><span style=\"font-weight: 400;\"> file -\u2014&gt;<\/span>\r\n<span style=\"font-weight: 400;\">&lt;<\/span><span style=\"font-weight: 400;\">script<\/span> <span style=\"font-weight: 400;\">type<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">\"<\/span><span style=\"font-weight: 400;\">text\/brightscript<\/span><span style=\"font-weight: 400;\">\"<\/span>\r\n<span style=\"font-weight: 400;\">uri<\/span><span style=\"font-weight: 400;\">=<\/span><span style=\"font-weight: 400;\">\"<\/span><span style=\"font-weight: 400;\">pkg:\/components\/MainScene\/ChannelStoreHelper\/ChannelStoreHelper.brs<\/span><span style=\"font-weight: 400;\">\"<\/span> <span style=\"font-weight: 400;\">\/&gt;<\/span><\/pre>\n<\/blockquote>\n<h3><b>MainScene.brs<\/b><span style=\"font-weight: 400;\">:<\/span><\/h3>\n<p><i><span style=\"font-weight: 400;\">brightscript<\/span><\/i><\/p>\n<blockquote>\n<pre><span style=\"font-weight: 400;\">function<\/span><span style=\"font-weight: 400;\"> onKeyEvent(key <\/span><span style=\"font-weight: 400;\">as<\/span> <span style=\"font-weight: 400;\">string<\/span><span style=\"font-weight: 400;\">, press <\/span><span style=\"font-weight: 400;\">as<\/span> <span style=\"font-weight: 400;\">boolean<\/span><span style=\"font-weight: 400;\">) <\/span><span style=\"font-weight: 400;\">as<\/span> <span style=\"font-weight: 400;\">boolean<\/span>\r\n<span style=\"font-weight: 400;\">result <\/span><span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">false<\/span>\r\n<span style=\"font-weight: 400;\">if<\/span><span style=\"font-weight: 400;\"> press<\/span>\r\n<span style=\"font-weight: 400;\">if<\/span><span style=\"font-weight: 400;\"> key <\/span><span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">\"OK\"<\/span>\r\n<b>checkSubscription<\/b><span style=\"font-weight: 400;\">() <\/span><span style=\"font-weight: 400;\">\u2018 call to <\/span><b>initiate<\/b><span style=\"font-weight: 400;\"> video playback code<\/span>\r\n<span style=\"font-weight: 400;\">result <\/span><span style=\"font-weight: 400;\">=<\/span> <span style=\"font-weight: 400;\">true<\/span>\r\n<span style=\"font-weight: 400;\">end if<\/span>\r\n<span style=\"font-weight: 400;\">end if<\/span>\r\n<span style=\"font-weight: 400;\">return<\/span><span style=\"font-weight: 400;\"> result<\/span>\r\n<span style=\"font-weight: 400;\">end function<\/span>\r\n\r\n<span style=\"font-weight: 400;\">sub<\/span> <b>checkSubscription<\/b><span style=\"font-weight: 400;\">()<\/span>\r\n<span style=\"font-weight: 400;\">#<\/span><span style=\"font-weight: 400;\">if<\/span><span style=\"font-weight: 400;\"> is_Subscribed<\/span>\r\n<span style=\"font-weight: 400;\">goToPlayerScreen() <\/span><span style=\"font-weight: 400;\">\u2018 goto player screen if user already a subscriber<\/span>\r\n<span style=\"font-weight: 400;\">#<\/span><span style=\"font-weight: 400;\">else<\/span>\r\n<span style=\"font-weight: 400;\">checkSubscriptionAndStartPlayback() <\/span><span style=\"font-weight: 400;\">\u2018 call <\/span><b>helper<\/b><span style=\"font-weight: 400;\"> file starting point method to <\/span><b>initiate<\/b><span style=\"font-weight: 400;\"> subscriptions check<\/span>\r\n<span style=\"font-weight: 400;\">#<\/span><span style=\"font-weight: 400;\">end if<\/span>\r\n<span style=\"font-weight: 400;\">end sub<\/span><\/pre>\n<\/blockquote>\n<h2><b>Conclusion<\/b><\/h2>\n<p><span style=\"font-weight: 400;\">With the `ChannelStoreHelper` at your disposal and the Roku Pay setup on your developer dashboard, you&#8217;re well on your way to simplifying Roku Pay integration in your Roku application. All you need is to call the initiate function of the ChannelStore node at your convenience, and everything else will come into place on its own as all the logic related to presenting, selecting, and purchasing the plan is already implemented. Happy coding!<\/span><\/p>\n<p><strong>Find the ChannelStoreHelper.brs at the below GitHub repo:<\/strong><br \/>\nhttps:\/\/github.com\/tothenew\/RokuStarterKit\/blob\/master\/RokuStarterKit\/components\/MainScene\/ChannelStoreHelper\/ChannelStoreHelper.brs<\/p>\n<div class=\"ap-custom-wrapper\"><\/div><!--ap-custom-wrapper-->","protected":false},"excerpt":{"rendered":"<p>Introduction Roku Pay integration can be a daunting task for developers, but fear not! `ChannelStoreHelper` is here for the rescue. Included in the Roku starter kit, this script file is your ticket to hassle-free implementation of Roku Pay on the front-end of your Roku application. With a single function call, you can kickstart Roku Pay, [&hellip;]<\/p>\n","protected":false},"author":1635,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":11},"categories":[3477],"tags":[5535,5533,5532,5530,5529,5527,5531,5528,5534],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/58843"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/1635"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=58843"}],"version-history":[{"count":5,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/58843\/revisions"}],"predecessor-version":[{"id":59653,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/58843\/revisions\/59653"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=58843"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=58843"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=58843"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}