I am designing an app with Paypal integration. Essentially, I want to charge $1.00 to access some data, and then allow a download after it confirms. I've gotten the sandbox test to work using the example from https://forum.posit.co/t/incorporate-online-payment-in-a-shiny-application/20242. However, I can't figure out how to keep the download either hidden or allow it to occur once the payment is confirmed (Right now it just allows you to download it whenever but I want that ability to be paywalled). Any help would be appreciated. Current Code Block below.
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(quantmod)
library(dygraphs)
library(dashboardthemes)
library(DT)
library(shinyjs)
options(stringsAsFactors = FALSE)
stockList <- readRDS('./data/stockList.rds') %>% filter(symbol %in% names(readRDS('./data/xbrlData.rds')))
shinyApp(
ui = dashboardPagePlus(
header = dashboardHeaderPlus(
enable_rightsidebar = FALSE,
left_menu = tagList(
selectizeInput('ticker', 'Company',
choices = sort(unique(stockList$company)),
selected = 'Whiting Petroleum Corporation', multiple=FALSE)
)
),
sidebar = dashboardSidebar(
),
body = dashboardBody(
shinyDashboardThemes(
theme = "grey_light"
),
shinyjs::useShinyjs(),
# infoBoxes
fluidRow(
column(width = 12,
boxPlus(
title = "Candlestick Chart",
closable = FALSE,
width = 12,
status = "info",
solidHeader = FALSE,
collapsible = TRUE,
enable_dropdown = FALSE,
dygraphs::dygraphOutput('stonks'),
h6('Source: Quantmod/Yahoo Finance')
)
)
),
fluidRow(
column(width = 12,
boxPlus(
title = 'Bulk Financial Download - By Ticker',
closable = FALSE,
width = 12,
status = "info",
solidHeader = FALSE,
collapsible = TRUE,
enable_dropdown = FALSE,
actionButton("Calculate",
label = ui <- fluidPage(
tags$script(src = "https://www.paypalobjects.com/api/checkout.js "),
tags$script("paypal.Button.render({
// Configure environment
env: 'sandbox',
client: {
sandbox: 'hidden',
production: 'demo_production_client_id'
},
// Customize button (optional)
locale: 'en_US',
style: {
size: 'small',
color: 'gold',
shape: 'pill',
},
// Set up a payment
payment: function (data, actions) {
return actions.payment.create({
transactions: [{
amount: {
total: '0.01',
currency: 'USD'
}
}]
});
},
// Execute the payment
onAuthorize: function (data, actions) {
return actions.payment.execute()
.then(function () {
// Show a confirmation message to the buyer
window.alert('Thank you for your purchase!');
});
}
}, '#Calculate');"),
tags$div(id = "Calculate"))),
hidden(div(
id='actions',
downloadButton("downloadData", "Download")
))
)
)
),
fluidRow(
column(width = 12,
boxPlus(
title = "Financial Statement Data",
closable = FALSE,
width = 12,
status = "info",
solidHeader = FALSE,
collapsible = TRUE,
enable_dropdown = FALSE,
fluidRow(
column(width = 2,
selectizeInput('period', 'Filing Period', choices = '')
),
column(width = 2,
selectizeInput('type', 'Statement Type', choices = '')
),
column(width = 4,
selectizeInput('table', 'Table', choices = '')
),
column(width = 2,
selectizeInput('endDate', 'Date', choices = '')
),
column(width = 2,
selectizeInput('duration', 'Months', choices = '')
)
),
fluidRow(
column(width =12,
DT::dataTableOutput('financials')
)
)
)
)
)
),
rightsidebar = rightSidebar(),
title = "EnFinExplorer"
),
server = function(input, output, session) {
values <- reactiveValues()
#shinyjs::hide('actions')
stockInfo <- reactive(
(stockList %>% filter(company%in% input$ticker))
)
#observeEvent(input$Calculate, {
# shinyjs::show('actions')
#})
#observeEvent(input$ticker, {
# shinyjs::hide('actions')
#})
observe({
if(is.null(input$ticker)||input$ticker == ''){
values$stock <- NULL
} else {
stock <- NULL
rm(stock)
#ticker <- input$operator
ticker <- stockInfo()$symbol
#print(ticker)
stock <- getSymbols(ticker, src='yahoo', auto.assign = FALSE, setSymbolLookup('stock'))
names(stock) <- c('Open', 'High', 'Low', 'Close', 'Volume', 'Adjusted')
values$stock <- stock
}
})
output$stonks <- dygraphs::renderDygraph({
#print(input$dateRange)
if(is.null(values$stock)){
NULL
} else {
#print(head(tables()))
dygraph(values$stock[,1:4]) %>%
dyCandlestick()%>%
dyAxis("y", label = "Share Price, US$") %>%
dyRangeSelector(height = 20)
}
})
tables <- reactive(readRDS('./data/xbrlData.rds')[[stockInfo()$symbol]] %>% mutate(Period = replace(Period, is.na(Period), 0)))
observe(updateSelectizeInput(session, 'period', choices = unique(tables()$PERIOD)))
observe(updateSelectizeInput(session, 'type', choices = unique((tables() %>% filter(PERIOD %in% input$period))$Type)))
observe(updateSelectizeInput(session, 'table', choices = unique((tables() %>% filter(PERIOD %in% input$period) %>%
filter(Type %in% input$type) )$Table)))
observe(updateSelectizeInput(session, 'endDate', choices = unique((tables() %>% filter(PERIOD %in% input$period)%>%
filter(Type %in% input$type) %>%
filter(Table %in% input$table))$endDate)))
observe(updateSelectizeInput(session, 'duration', choices = unique((tables() %>% filter(PERIOD %in% input$period)%>%
filter(Type %in% input$type) %>%
filter(Table %in% input$table) %>%
filter(endDate %in% input$endDate))$Period)))
tables1 <- reactive(tables() %>% filter(PERIOD %in% input$period) %>%
filter(Type %in% input$type) %>%
filter(Table %in% input$table) %>% filter(endDate %in% input$endDate) %>%
filter(Period %in% input$duration))
output$financials <- DT::renderDataTable({
if(is.null(input$duration)||input$duration == ''||
is.null(input$period)||input$period == ''||
is.null(input$table)||input$table == ''||
is.null(input$type)||input$type == ''||
is.null(input$endDate)||input$endDate == ''){
NULL
} else {
DT::datatable(tables1() %>% arrange(Order) %>% select(Order, Label, Value = fact, Units) %>%
mutate(Order = seq(1, n(), 1)), rownames = FALSE,
extensions = c('Buttons', 'Scroller'),
options = list(
dom = 'Bfrtip',
scrollX = TRUE,
scrollY = TRUE,
deferRender = TRUE,
paging = FALSE,
searching = FALSE,
buttons = c('copy', 'csv', 'excel')
))
}
})
output$downloadData <- downloadHandler(
filename = function() {
paste(stockInfo()$symbol, "financials.csv", sep = "")
},
content = function(file) {
write.csv(tables(), file, row.names = FALSE)
}
)
}
)