jQuery(function ($){
let wcAddToCartButton=$('.single_add_to_cart_button')
let orderSelectedShippingOption=null
let paymentRequestType=null
let paymentRequest=null
let address_info=null
let wc_order_id=null
const POLLING_TIMEOUT=3000
const MAX_POLLING_COUNT=10
function handleError(message){
$.blockUI({ message: null, overlayCSS: { background: '#fff', opacity: 0.6 }})
if(paymentRequest){
paymentRequest.destroy()
}
sendRequest(getAjaxURL('set_error_message'), {
security: wc_revolut_payment_request_params.nonce.set_error_message,
revolut_payment_request_error: message,
})
.then(response=> {
window.location.reload()
})
.catch(error=> {
window.location.reload()
})
}
function logError(message){
sendRequest(
getAjaxURL('log_error'),
{
security: wc_revolut_payment_request_params.nonce.log_errors,
revolut_payment_request_error: message,
},
false,
)
}
function getAjaxURL(endpoint, controller='revolut_payment_request_'){
return wc_revolut_payment_request_params.ajax_url
.toString()
.replace('%%wc_revolut_gateway_ajax_endpoint%%', `${controller}${endpoint}`)
}
function getProductAttributes(){
const select=$('.variations_form').find('.variations select'),
data={}
select.each(function (){
const attribute_name=$(this).data('attribute_name')||$(this).attr('name')
data[attribute_name]=$(this).val()||''
})
return data
}
function checkCartCreateErrors(){
if(!wcAddToCartButton.is('.disabled')){
return false
}
if(wcAddToCartButton.is('.wc-variation-is-unavailable')){
return wc_add_to_cart_variation_params.i18n_unavailable_text
}
if(wcAddToCartButton.is('.wc-variation-selection-needed')){
return wc_add_to_cart_variation_params.i18n_make_a_selection_text
}
return wc_revolut_payment_request_params.error_messages.cart_create_failed
}
function createCart({ add_to_cart=0, revpay=false }){
return new Promise((resolve, reject)=> {
if(checkCartCreateErrors()){
let errorMsg=checkCartCreateErrors()
if(revpay){
return reject(errorMsg)
}
handleError(errorMsg)
return resolve(false)
}
if(wc_revolut_payment_request_params.is_cart_page){
return resolve({ success: true })
}
let product_data={}
product_data['add_to_cart']=add_to_cart ? 1:0
product_data['is_revolut_pay']=revpay ? 1:0
product_data['security']=wc_revolut_payment_request_params.nonce.add_to_cart
product_data['product_id']=$('.single_add_to_cart_button').val()
product_data['qty']=$('.quantity .qty').val()
product_data['attributes']=[]
if($('.single_variation_wrap').length){
product_data['product_id']=$('.single_variation_wrap')
.find('input[name="product_id"]')
.val()
}
if($('.variations_form').length){
product_data['attributes']=getProductAttributes()
}
sendRequest(getAjaxURL('add_to_cart'), product_data).then(response=> {
if(!response.success){
if(revpay){
displayErrorMessage(
wc_revolut_payment_request_params.error_messages.cart_create_failed,
)
return resolve(false)
}
handleError(wc_revolut_payment_request_params.error_messages.cart_create_failed)
return resolve(false)
}
wc_revolut_payment_request_params.total=response.total.amount
wc_revolut_payment_request_params.nonce.checkout=response.checkout_nonce
resolve(response)
})
})
}
function getShippingOptions(address){
let address_data={
security: wc_revolut_payment_request_params.nonce.shipping,
country: address.country,
state: address.region,
postcode: address.postalCode,
city: address.city,
address: '',
address_2: '',
is_product_page: wc_revolut_payment_request_params.is_product_page,
require_shipping: wc_revolut_payment_request_params.shipping_required,
}
return new Promise((resolve, reject)=> {
sendRequest(getAjaxURL('get_shipping_options'), address_data)
.then(response=> {
if(response['shippingOptions']&&response['shippingOptions'].length!==0){
orderSelectedShippingOption=response['shippingOptions'][0]['id']
}
resolve(response)
})
.catch(error=> {
reject(error)
})
})
}
function updateShippingOptions(shippingOption){
let shipping_option_data={
security: wc_revolut_payment_request_params.nonce.update_shipping,
shipping_method: [shippingOption.id],
is_product_page: wc_revolut_payment_request_params.is_product_page,
}
return new Promise((resolve, reject)=> {
sendRequest(getAjaxURL('update_shipping_method'), shipping_option_data)
.then(response=> {
resolve(response)
})
.catch(error=> {
reject(error)
})
})
}
function updatePaymentTotal(){
let shipping_option_data={
revolut_public_id: wc_revolut_payment_request_params.revolut_public_id,
security: wc_revolut_payment_request_params.nonce.update_order_total,
}
return new Promise((resolve, reject)=> {
sendRequest(getAjaxURL('update_payment_total'), shipping_option_data)
.then(response=> {
resolve(response)
})
.catch(error=> {
reject(error)
})
})
}
function loadOrderData(){
return new Promise((resolve, reject)=> {
sendRequest(getAjaxURL('load_order_data'), {
revolut_public_id: wc_revolut_payment_request_params.revolut_public_id,
security: wc_revolut_payment_request_params.nonce.load_order_data,
})
.then(response=> {
resolve(response)
})
.catch(error=> {
reject(error)
})
})
}
function cancelOrder(messages){
$.blockUI({ message: null, overlayCSS: { background: '#fff', opacity: 0.6 }})
return new Promise((resolve, reject)=> {
sendRequest(getAjaxURL('cancel_order'), {
revolut_public_id: wc_revolut_payment_request_params.revolut_public_id,
security: wc_revolut_payment_request_params.nonce.cancel_order,
}).then(response=> {
handleError(messages)
})
})
}
function pollPaymentResult(publicId, hasError, captured=true){
return new Promise((resolve, reject)=> {
if(hasError){
return resolve()
}
let pollingCount=0
const interval=setInterval(()=> {
if(pollingCount > MAX_POLLING_COUNT){
clearInterval(interval)
resolve()
}
$.ajax({
type: 'POST',
url: getAjaxURL('check_payment', 'wc_revolut_'),
data: {
revolut_public_id: publicId,
is_captured: captured ? 1:0,
security: wc_revolut_payment_request_params.nonce.wc_revolut_check_payment,
},
success: function (response){
if(response&&response.payment_completed){
clearInterval(interval)
resolve()
}
pollingCount++
},
})
}, POLLING_TIMEOUT)
})
}
function capturePayment(publicId, hasError, { totalRetry=3, delay=300 }={}){
return new Promise((resolve, reject)=> {
if(hasError){
return resolve()
}
const tryToCapturePayment=retryCount=> {
$.ajax({
type: 'POST',
url: getAjaxURL('capture_payment', 'wc_revolut_'),
data: {
revolut_public_id: publicId,
security: wc_revolut_payment_request_params.nonce.wc_revolut_capture_payment,
},
success: function (response){
if(response&&response.is_captured){
resolve()
}else{
retryOrFail(new Error('failed to capture payment'), retryCount)
}},
error: function (jqXHR, textStatus, errorThrown){
retryOrFail(new Error('failed to capture payment'), retryCount)
},
})
}
const retryOrFail=(error, retryCount)=> {
if(retryCount > 0){
setTimeout(()=> tryToCapturePayment(retryCount - 1), delay)
}else{
reject(error)
}}
tryToCapturePayment(totalRetry)
})
}
function stopProcessing(){
$.unblockUI()
$('.blockUI.blockOverlay').hide()
}
function submitOrder(errorMessage='', revolut_gateway='revolut_payment_request'){
$.blockUI({ message: null, overlayCSS: { background: '#fff', opacity: 0.6 }})
let data={}
data['is_express_checkout']=1
data['revolut_gateway']=revolut_gateway
data['revolut_public_id']=wc_revolut_payment_request_params.revolut_public_id
data['security']=wc_revolut_payment_request_params.nonce.process_payment_result
data['revolut_payment_error']=errorMessage
data['wc_order_id']=wc_order_id
data['reload_checkout']=0
data['revolut_save_payment_method']=0
data['wc-revolut_cc-payment-token']=''
pollPaymentResult(
wc_revolut_payment_request_params.revolut_public_id,
errorMessage,
false,
).then(()=> {
sendRequest(getAjaxURL('process_payment_result', 'wc_revolut_'), data).then(response=> {
if(response.result==='success'){
window.location.href=response.redirect
return
}
$.unblockUI()
$('.blockUI.blockOverlay').hide()
if(!response.messages||typeof response.messages=='undefined'){
response.messages=`<div class="woocommerce-error">${wc_revolut_payment_request_params.error_messages.checkout_general}</div>`
}
cancelOrder(response.messages)
},
)
})
}
function submitWooCommerceOrder(payment_method='revolut_payment_request'){
return new Promise((resolve, reject)=> {
sendRequest(getAjaxURL('create_order'), {
payment_method: payment_method,
_wpnonce: wc_revolut_payment_request_params.nonce.checkout,
security: wc_revolut_payment_request_params.nonce.create_order,
shipping_method: [orderSelectedShippingOption],
payment_request_type: paymentRequestType,
revolut_public_id: wc_revolut_payment_request_params.revolut_public_id,
shipping_required: wc_revolut_payment_request_params.shipping_required ? 1:0,
address_info: address_info,
revolut_create_wc_order: 1,
is_express_checkout: 1,
})
.then(response=> {
if(true===response.reload){
window.location.reload()
return
}
if(response.result==='revolut_wc_order_created'){
wc_order_id=response['wc_order_id']
return resolve(true)
}
if(typeof response.messages=='undefined'){
response.messages=`<div class="woocommerce-error">${wc_revolut_payment_request_params.error_messages.checkout_general}</div>`
}
logError('submitWooCommerceOrder failed: ' + JSON.stringify(response))
return cancelOrder($(response.messages).text())
})
.catch(error=> {
cancelOrder(error)
})
})
}
function displayErrorMessage(message){
if(message&&!message.includes('woocommerce-error')){
message=`<div class="woocommerce-error">${message}</div>`
}
$('.woocommerce-error').remove()
if(wc_revolut_payment_request_params.is_product_page){
var element=$('.product').first()
element.before(message)
$('html, body').animate({
scrollTop: element.prev('.woocommerce-error').offset().top,
},
600,
)
}else{
var $form=$('.shop_table.cart').closest('form')
$form.before(message)
$('html, body').animate({
scrollTop: $form.prev('.woocommerce-error').offset().top,
},
600,
)
}}
function initPaymentRequestButton(){
if($('#revolut-payment-request-button').length < 1){
return false
}
const { paymentRequest }=RevolutCheckout.payments({
locale: wc_revolut_payment_request_params.locale,
publicToken: wc_revolut_payment_request_params.publicToken,
})
let paymentRequestButton=document.getElementById('revolut-payment-request-button')
const request=paymentRequest.mount(paymentRequestButton, {
currency: wc_revolut_payment_request_params.currency,
amount: 0,
requestShipping: wc_revolut_payment_request_params.shipping_required,
shippingOptions: wc_revolut_payment_request_params.free_shipping_option,
onClick(){
if(!wc_revolut_payment_request_params.shipping_required){
return createCart({ add_to_cart: true })
}},
onShippingOptionChange: selectedShippingOption=> {
orderSelectedShippingOption=selectedShippingOption['id']
return updateShippingOptions(selectedShippingOption)
},
onShippingAddressChange: selectedShippingAddress=> {
return createCart({ add_to_cart: true }).then(function (){
return getShippingOptions(selectedShippingAddress)
})
},
onSuccess(){
submitOrder()
},
validate(address){
address_info=address
return getRevolutOrderPublicId().then(()=> {
return submitWooCommerceOrder()
})
},
createOrder: ()=> {
return {
publicId: wc_revolut_payment_request_params.revolut_public_id,
}},
onError(error){
let errorMessage=error
if(error['message']){
errorMessage=error['message']
}
if(errorMessage=='Unknown'){
errorMessage=wc_revolut_payment_request_params.error_messages.checkout_general
}
if(wc_order_id){
return submitOrder(errorMessage)
}
displayErrorMessage(errorMessage)
},
buttonStyle: {
action: revolut_payment_request_button_style.payment_request_button_type,
height: revolut_payment_request_button_style.payment_request_button_height,
variant: revolut_payment_request_button_style.payment_request_button_theme,
radius: revolut_payment_request_button_style.payment_request_button_radius,
},
})
request.canMakePayment().then(result=> {
if(result){
request.render()
}else{
request.destroy()
}})
}
function initRevolutPayExpressCheckoutButton(){
if($('#revolut-pay-express-checkout-button').length < 1){
return false
}
const { revolutPay }=RevolutCheckout.payments({
locale: wc_revolut_payment_request_params.locale,
publicToken: wc_revolut_payment_request_params.publicToken,
})
const { revCashbackLabelEnabled }=typeof wc_revolut_pay_banner_data!=='undefined' ? wc_revolut_pay_banner_data:{}
revolutPay.mount('#revolut-pay-express-checkout-button', {
currency: wc_revolut_payment_request_params.currency,
totalAmount: 0,
requestShipping: true,
createOrder: ()=>
createCart({ add_to_cart: true, revpay: true }).then(result=> {
if(!result||!result.success){
displayErrorMessage(
wc_revolut_payment_request_params.error_messages.checkout_general,
)
throw new Error(
wc_revolut_payment_request_params.error_messages.checkout_general,
)
}
return getRevolutOrderPublicId().then(publicId=> ({ publicId }))
}),
buttonStyle: {
cashback: Boolean(Number(revCashbackLabelEnabled)),
cashbackCurrency: wc_revolut_payment_request_params.currency,
variant: revolut_pay_button_style.revolut_pay_button_theme,
height: revolut_pay_button_style.revolut_pay_button_height,
radius: revolut_pay_button_style.revolut_pay_button_radius,
},
mobileRedirectUrls: {
success: wc_revolut_payment_request_params.redirect_url,
failure: wc_revolut_payment_request_params.redirect_url,
cancel: wc_revolut_payment_request_params.redirect_url,
},
__metadata: {
environment: 'woocommerce',
context: wc_revolut_payment_request_params.is_cart_page ? 'cart':'product',
origin_url: wc_revolut_payment_request_params.revolut_pay_origin_url,
},
})
revolutPay.on('payment', function (event){
switch (event.type){
case 'success':
$.blockUI({ message: null, overlayCSS: { background: '#fff', opacity: 0.6 }})
loadOrderData()
.then(function (order_data){
address_info=order_data.address_info
orderSelectedShippingOption=order_data.selected_shipping_option
submitWooCommerceOrder('revolut_pay')
.then(function (){
submitOrder('', 'revolut_pay')
})
.catch(error=> {
displayErrorMessage([error])
$.unblockUI()
$('.blockUI.blockOverlay').hide()
})
})
.catch(error=> {
displayErrorMessage([error])
$.unblockUI()
$('.blockUI.blockOverlay').hide()
})
break
case 'error':
displayErrorMessage(event.error.message)
break
}})
}
$('.quantity').on('input', '.qty', function (){
if(!paymentRequest ||
wcAddToCartButton.is('.disabled') ||
wc_revolut_payment_request_params.is_cart_page
){
return
}
paymentRequest.updateWith(createCart())
})
$(document.body).on('woocommerce_variation_has_changed', function (){
if(!paymentRequest ||
wcAddToCartButton.is('.disabled') ||
wc_revolut_payment_request_params.is_cart_page
){
return
}
paymentRequest.updateWith(createCart())
})
$(document.body).on('updated_cart_totals', function (){
initPaymentRequestButton()
initRevolutPayExpressCheckoutButton()
})
initPaymentRequestButton()
initRevolutPayExpressCheckoutButton()
function buildFormData(formData, data, parentKey){
if(data&&typeof data==='object'){
Object.keys(data).forEach(key=> {
buildFormData(formData, data[key], parentKey ? `${parentKey}[${key}]`:key)
})
}else{
const value=data==null ? '':data
formData.append(parentKey, value)
}}
function sendRequest(url, data, shouldLogError=true){
const requestData=new FormData()
buildFormData(requestData, data)
return fetch(url, {
method: 'POST',
body: requestData,
})
.then(response=> response.json())
.catch(error=> {
if(shouldLogError){
logError(error)
}
throw error
})
}
function getRevolutOrderPublicId(){
return new Promise((resolve, reject)=> {
sendRequest(getAjaxURL('get_express_checkout_params'), {
security: wc_revolut_payment_request_params.nonce.get_express_checkout_params,
}).then(order=> {
if(order.success){
wc_revolut_payment_request_params.revolut_public_id=order.revolut_public_id
return resolve(order.revolut_public_id)
}
displayErrorMessage(
wc_revolut_payment_request_params.error_messages.checkout_general,
)
})
})
}});