We found that the getOrder() function of Velo in thankYouPage sometimes fail, either we get an undefined object or an error with message "missing order id".
In order to find out why our code doesn't work in a random pattern, we recorded logs for about 30 orders which were placed within 14 hours last Friday, and there're 11 out 30 orders that getOrder() failed (to be more precise, 7 getOrder() threw "missing order id" error and 4 getOrders() returned undefined).
Is there any reasons why the getOrder() function sometimes failed but sometimes worked? Or perhaps we use the function in a wrong way. Please let us know if there's any solutions or recommendations we can improve our code to prevent this random error happening again.
Here we attached our code snippets of thankYouPage and logs we recorded.
Looking forward to hearing from you soon
thank-you-page.js code
---
import { getTokenByTrade, createPayment } from 'backend/payment';
import { getPaymentCompleteSubDir } from 'backend/constants';
import wixLocation from 'wix-location';
import { session } from 'wix-storage';
const thankYouPageId = '#thankYouPage1';
const iframeId = '#html1';
const paybtnId = '#button1';
const spinnerId = '#spinner1';
const loadingTextId = '#text1';
const errorTextId = '#text2';
// Variables for setting inverval that improve waiting UI experience
const WAITING_ORDER_INFO = 'WAITING_ORDER_INFO';
const WAITING_PAYMENT = 'WAITING_PAYMENT';
let loadingInterval;
let loadingCounter = 0;
// Variable for preventing from creating payment twice
let hasCreatedPayment = false;
const enableSpinner = (waitFor) => {
console.log('Enable spinner');
const loadingOrderTextArr = ['訂單資訊處理中,請您稍候...', '取得付款資訊...'];
const loadingPaymentTextArr = ['交易資訊處理中,請您稍候...', '取得付款憑證...', '即將完成確認...'];
try {
$w(spinnerId).show();
$w(loadingTextId).show();
switch (waitFor) {
case WAITING_ORDER_INFO:
$w(loadingTextId).text = loadingOrderTextArr[loadingCounter];
loadingInterval = setInterval(() => {
if (loadingCounter + 1 < loadingOrderTextArr.length) loadingCounter += 1;
$w(loadingTextId).text = loadingOrderTextArr[loadingCounter];
}, 3000);
break;
case WAITING_PAYMENT:
$w(loadingTextId).text = loadingPaymentTextArr[loadingCounter];
loadingInterval = setInterval(() => {
if (loadingCounter + 1 < loadingPaymentTextArr.length) loadingCounter += 1;
$w(loadingTextId).text = loadingPaymentTextArr[loadingCounter];
}, 3500);
break;
}
} catch (err) {
console.error(err);
}
};
const disableSpinner = () => {
console.log('Disable spinner');
try {
clearInterval(loadingInterval);
loadingCounter = 0;
$w(spinnerId).hide();
$w(loadingTextId).hide();
} catch (err) {
console.error(err);
}
};
const disableSpinnerAndShowError = (errMsg) => {
console.log('Disable spinner and show error');
disableSpinner();
$w(errorTextId).show();
$w(errorTextId).text = errMsg;
};
$w.onReady(async () => {
const PAYMENT_COMPLETE_SUB_DIR = await getPaymentCompleteSubDir();
enableSpinner(WAITING_ORDER_INFO);
$w(thankYouPageId)
.getOrder()
.then((order) => {
console.log('Order detail', order);
const orderInfo = {
orderNumber: order && order.number,
// orderNumber: '10001', // For testing
orderItems: order && order.lineItems.map((e) => `${e.name} x ${e.quantity}`).join(', '),
orderTotal: order && order.totals.total,
// orderTotal: 100, // For testing
firstName: order && order.billingInfo.firstName,
email: order && order.billingInfo.email,
};
session.setItem('orderInfo', JSON.stringify(orderInfo));
getTokenByTrade(orderInfo.orderNumber, orderInfo.orderTotal)
.then(({ token, merchantTradeNo }) => {
console.log('Get token', token);
disableSpinner();
$w(iframeId).onMessage(async (messageEvent) => {
try {
const { event, data } = JSON.parse(messageEvent.data);
switch (event) {
case 'iframe_has_init':
console.log('iframe_has_init');
$w(iframeId).postMessage(JSON.stringify({ event: 'wix_init_ecpay_payment', data: { token } }));
break;
case 'iframe_get_paytoken':
console.log('iframe_get_paytoken', data);
// data is null when pay token hasn't obtained
if (data && !hasCreatedPayment) {
hasCreatedPayment = true; // Prevent from creating payment twice
const { ThreeDInfo, ATMInfo, CVSInfo, BarcodeInfo } = await createPayment(
data.PayToken,
merchantTradeNo,
orderInfo
);
let queryString;
switch (data.PaymentType) {
case 'CreditCard':
console.log('ThreeDInfo', ThreeDInfo);
wixLocation.to(ThreeDInfo.ThreeDURL);
break;
case 'ATM':
console.log('ATMInfo', ATMInfo);
queryString = `paymentType=ATM&result=${encodeURIComponent(JSON.stringify(ATMInfo))}`;
wixLocation.to(`${PAYMENT_COMPLETE_SUB_DIR}?${queryString}`);
break;
case 'CVS':
console.log('CVSInfo', CVSInfo);
queryString = `paymentType=CVS&result=${encodeURIComponent(JSON.stringify(CVSInfo))}`;
wixLocation.to(`${PAYMENT_COMPLETE_SUB_DIR}?${queryString}`);
break;
case 'Barcode':
console.log('BarcodeInfo', BarcodeInfo);
queryString = `paymentType=Barcode&result=${encodeURIComponent(JSON.stringify(BarcodeInfo))}`;
wixLocation.to(`${PAYMENT_COMPLETE_SUB_DIR}?${queryString}`);
break;
}
}
// Paid failed, enable pay button to be clicked
$w(paybtnId).enable();
disableSpinner();
break;
}
} catch (err) {
console.log('Error when parsing messageEvent.data', err);
disableSpinnerAndShowError(`未預期錯誤:${err.message}`);
}
});
$w(iframeId).postMessage(JSON.stringify({ event: 'wix_init_ecpay_payment', data: { token } }));
})
.catch((err) => {
console.log(err);
if (err.RtnCode && err.RtnCode === 5100012) {
// Repeated order number
disableSpinnerAndShowError('該筆交易資訊重複,請勿重複下單');
} else {
disableSpinnerAndShowError(`未預期錯誤:${err.message}`);
}
});
})
.catch((err) => {
console.log(err);
disableSpinnerAndShowError('取得訂單資訊失敗');
});
$w(paybtnId).onClick(() => {
$w(iframeId).postMessage(JSON.stringify({ event: 'wix_click_pay' }));
$w(paybtnId).disable();
enableSpinner(WAITING_PAYMENT);
});
});
hey wix support will setup a call for us
hey @Brian Chien,
seems your code has some race condition, altho we don't see it anywhere else.
possible solutions: 1.add a return statement to return the promise like that:
return $w(thankYouPageId) .getOrder() .then((order) => { console.log('Order detail', order); //............ })
2.wrap your code with setTimeout
setTimeout(() => { console.log('1') $w("#thankYouPage1").getOrder().then((order) => { console.log('order', order) }).catch(e => { console.log('e111', e) }) }, 3000)
I think #1 will do the trick
also, what is your site url?
You've got over 160 lines of code and a 1.8MB log file. Understand that we are unable to debug or rewrite complex code and page configurations. If you feel that there is a bug in Velo, then please try to create a test page with the minimum scenario in which the problem appears to help us investigate the issue properly.
@Yisrael (Wix) Would you help to check with your Velo Team? That is shouldn't occured from your API. My clients are pushing me now, thank you.