|
|
@@ -0,0 +1,340 @@ |
|
|
|
// material-ui |
|
|
|
import { |
|
|
|
Grid, |
|
|
|
Typography, |
|
|
|
Stack, |
|
|
|
Button, |
|
|
|
} from '@mui/material'; |
|
|
|
import * as React from "react"; |
|
|
|
import * as HttpUtils from "utils/HttpUtils"; |
|
|
|
import { useNavigate } from "react-router-dom"; |
|
|
|
import FpsIcon from "assets/images/icons/fps.svg"; |
|
|
|
import { useLocation } from 'react-router-dom'; |
|
|
|
import {paymentPath} from "auth/utils"; |
|
|
|
// import {poll} from "utils/Utils"; |
|
|
|
|
|
|
|
import Loadable from 'components/Loadable'; |
|
|
|
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); |
|
|
|
|
|
|
|
import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' |
|
|
|
const BackgroundHead = { |
|
|
|
backgroundImage: `url(${titleBackgroundImg})`, |
|
|
|
width: '100%', |
|
|
|
height: '100%', |
|
|
|
backgroundSize: 'contain', |
|
|
|
backgroundRepeat: 'no-repeat', |
|
|
|
backgroundColor: '#0C489E', |
|
|
|
backgroundPosition: 'right' |
|
|
|
} |
|
|
|
|
|
|
|
// ==============================|| DASHBOARD - DEFAULT ||============================== // |
|
|
|
|
|
|
|
const Index = () => { |
|
|
|
const navigate = useNavigate() |
|
|
|
const location = useLocation(); |
|
|
|
|
|
|
|
const [locationData, setLocationData] = React.useState({}); |
|
|
|
const [paymentData, setPaymentData] = React.useState({}); |
|
|
|
const [onReady, setOnReady] = React.useState(true); |
|
|
|
|
|
|
|
const [responeData, setResponeDataData] = React.useState({}); |
|
|
|
const [fpsTransctionData, setFpsTransctionData] = React.useState({}); |
|
|
|
const [fpsmerchanttimeoutdatetime, setFpsmerchanttimeoutdatetime] = React.useState(""); |
|
|
|
const [timeDownCount, setTimeDownCount] = React.useState(0); |
|
|
|
const [paymentId, setPaymentId] = React.useState(""); |
|
|
|
const [fpsqrcodeurl, setFpsqrcodeurl] = React.useState(""); |
|
|
|
const [browserType, setBrowserType] = React.useState(""); |
|
|
|
const mobileBrowser = "Mobile"; |
|
|
|
// const desktopBrowser = "Desktop"; |
|
|
|
// const pasgPath = 'https://fps.payapps.hkicl.com.hk'; //PRD |
|
|
|
// const pasgPath = 'https://sim.fps.payapps.hkicl.com.hk'; //Testing |
|
|
|
// const loadPaymentUrl = "/api/payment/wallet/fps"; |
|
|
|
const cancelPaymentUrl = "/api/payment/cancelpayment"; |
|
|
|
const paymentStatusApi = "/api/payment/status/"; |
|
|
|
// const payloadUrl = "/api/payment/wallet/fps/enquiryfpspayload/"; |
|
|
|
// const receiverUrl = "/noti-api/payment/payment-notification"; |
|
|
|
const pasgPath = 'https://sim.fps.payapps.hkicl.com.hk'; //Testing |
|
|
|
// const pasgPath = 'https://fps.payapps.hkicl.com.hk'; //PRD |
|
|
|
//timer |
|
|
|
const openPASGUrl = pasgPath + '?pay_req_obj=' + encodeURIComponent("http://127.0.0.1:8080/api/payment/wallet/fps/enquiryfpspayload/vm.JKDDlTOavR3ASviSwUnS1Lw4-") + '&callback=' |
|
|
|
+ encodeURIComponent("https://"+window.location.hostname+ '/paymentPage/fps/ackpage'); |
|
|
|
|
|
|
|
const currentTimer = React.useRef(); |
|
|
|
const [time, setTime] = React.useState(0); |
|
|
|
|
|
|
|
React.useEffect(() => { |
|
|
|
// console.log (location.state) |
|
|
|
if (/Android|webOS|iPhone|iPad|iPod|Opera Mini/i.test(navigator.userAgent)) { |
|
|
|
console.log('Mobile web browser'); |
|
|
|
setBrowserType(mobileBrowser) |
|
|
|
console.log(openPASGUrl) |
|
|
|
// renderOpenFPSPaymentAppTemplate(openPASGUrl, $('#openFPSPaymentAppTemplate').html()); |
|
|
|
} else { |
|
|
|
console.log('Desktop web browser'); |
|
|
|
setBrowserType(mobileBrowser) |
|
|
|
const parsedUrl = new URL("http://127.0.0.1:8080/api/payment/wallet/fps/enquiryfpspayload/vm.JKDDlTOavR3ASviSwUnS1Lw4-"); |
|
|
|
console.log(parsedUrl) |
|
|
|
const fpsqrcodeurl = parsedUrl.pathname; |
|
|
|
console.log(fpsqrcodeurl) |
|
|
|
console.log(openPASGUrl) |
|
|
|
setFpsqrcodeurl(openPASGUrl) |
|
|
|
} |
|
|
|
if (location.state!=null){ |
|
|
|
if(Object.keys(location.state).length > 0){ |
|
|
|
console.log (location.state) |
|
|
|
setLocationData(location.state) |
|
|
|
} |
|
|
|
} |
|
|
|
}, []); |
|
|
|
|
|
|
|
React.useEffect(() => { |
|
|
|
// console.log (locationData) |
|
|
|
if (Object.keys(locationData).length > 0){ |
|
|
|
setPaymentData(locationData) |
|
|
|
// loadForm(); |
|
|
|
} |
|
|
|
}, [locationData]); |
|
|
|
|
|
|
|
React.useEffect(() => { |
|
|
|
// console.log (paymentData) |
|
|
|
if (Object.keys(paymentData).length > 0){ |
|
|
|
loadForm(); |
|
|
|
} |
|
|
|
}, [paymentData]); |
|
|
|
|
|
|
|
React.useEffect(() => { |
|
|
|
// console.log(responeData) |
|
|
|
if(Object.keys(responeData).length > 0 && fpsmerchanttimeoutdatetime!=""){ |
|
|
|
setFpsTransctionData(responeData) |
|
|
|
} |
|
|
|
}, [responeData]); |
|
|
|
|
|
|
|
React.useEffect(() => { |
|
|
|
// console.log(fpsTransctionData) |
|
|
|
if(Object.keys(fpsTransctionData).length > 0 ){ |
|
|
|
setOnReady(true); |
|
|
|
setPaymentId(fpsTransctionData.paymentid) |
|
|
|
currentTimer.current = setInterval(() => { |
|
|
|
setTime((prevTime) => prevTime + 1); |
|
|
|
}, 1000); |
|
|
|
return () => clearInterval(currentTimer.current); |
|
|
|
} |
|
|
|
}, [fpsTransctionData]); |
|
|
|
|
|
|
|
|
|
|
|
const loadForm = () => { |
|
|
|
const timeoutdatetime = "2023-12-07T09:04:30Z[UTC]" |
|
|
|
const convertedDateString = timeoutdatetime.replace("[UTC]", ""); |
|
|
|
setFpsmerchanttimeoutdatetime(convertedDateString) |
|
|
|
setPaymentid("C202310268000681") |
|
|
|
setPaymentstatuscode("INPR") |
|
|
|
const responseData= |
|
|
|
{ |
|
|
|
"paymentid": "<paymentid>", |
|
|
|
"paymentstatus": "<paymentstatus>", |
|
|
|
"fpsmerchanttimeoutdatetime": "<fpsmerchanttimeoutdatetime>", |
|
|
|
"fpsqrcodeimgbase64": "<fpsqrcodeimgbase64>", |
|
|
|
"fpsqrcodeurl": "<fpsqrcodeurl>" |
|
|
|
} |
|
|
|
setResponeDataData(responseData) |
|
|
|
// localStorage.removeItem("transactionid") |
|
|
|
// localStorage.removeItem("webtoken") |
|
|
|
// localStorage.setItem("transactionid", paymentData.transactionid) |
|
|
|
// localStorage.setItem("webtoken", paymentData.webtoken) |
|
|
|
|
|
|
|
// HttpUtils.post({ |
|
|
|
// url: paymentPath+loadPaymentUrl, |
|
|
|
// params:{ |
|
|
|
// "transactionid": paymentData.transactionid, |
|
|
|
// "webtoken": paymentData.webtoken, |
|
|
|
// "paymentmethod":"04,BCFP,FPS", |
|
|
|
// "order": { |
|
|
|
// "totalamount":paymentData.amount, |
|
|
|
// "currency":"HKD", |
|
|
|
// "orderdetail": |
|
|
|
// [ |
|
|
|
// { |
|
|
|
// "itemid": "1", |
|
|
|
// "qty":"1", |
|
|
|
// "unitprice":paymentData.amount, |
|
|
|
// "amount":paymentData.amount |
|
|
|
// }, |
|
|
|
// ] |
|
|
|
// }, |
|
|
|
// // "locale":"<locale>", |
|
|
|
// // "eserviceid":"<eserviceid>" |
|
|
|
// }, |
|
|
|
// onSuccess: function(responseData){ |
|
|
|
// /* |
|
|
|
// { |
|
|
|
// "paymentid": "<paymentid>", |
|
|
|
// "paymentstatus": "<paymentstatus>", |
|
|
|
// "fpsmerchanttimeoutdatetime": <fpsmerchanttimeoutdatetime>, |
|
|
|
// "fpsqrcodeimgbase64": "<fpsqrcodeimgbase64>", |
|
|
|
// "fpsqrcodeurl": "<fpsqrcodeurl>" |
|
|
|
// } |
|
|
|
// */ |
|
|
|
// setResponeDataData(responseData) |
|
|
|
// const timeoutdatetime = responseData.fpsmerchanttimeoutdatetime |
|
|
|
// const convertedDateString = timeoutdatetime.replace("[UTC]", ""); |
|
|
|
// setFpsmerchanttimeoutdatetime(convertedDateString) |
|
|
|
// // const parsedUrl = new URL(responseData.fpsqrcodeurl); |
|
|
|
// // const fpsqrcodeurl = parsedUrl.pathname; |
|
|
|
// // const openPASGUrl = pasgPath + '?pay_req_obj=' + encodeURIComponent(responseData.fpsqrcodeurl) + '&callback=' |
|
|
|
// // + encodeURIComponent(paymentPath + payment.config.fpscallbackPage); |
|
|
|
// // setFpsqrcodeurl(openPASGUrl) |
|
|
|
|
|
|
|
|
|
|
|
// } |
|
|
|
// }); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
const getPaymentStatus = () => { |
|
|
|
if(Object.keys(paymentData).length > 0){ |
|
|
|
HttpUtils.post({ |
|
|
|
url: paymentPath+paymentStatusApi+paymentData.transactionid, |
|
|
|
params:{ |
|
|
|
"apprefid": paymentData.transactionid, |
|
|
|
"webtoken": paymentData.webtoken, |
|
|
|
}, |
|
|
|
onSuccess: function(responseData){ |
|
|
|
const paymentstatuscode = responseData.paymentdetail.result.paymentstatuscode; |
|
|
|
if (paymentstatuscode != "" && paymentstatuscode != "INPR" ){ |
|
|
|
if (paymentstatuscode === 'APPR') { |
|
|
|
// const timestamp = Date.now(); |
|
|
|
navigate('/paymentPage/fps/ackpage'); |
|
|
|
} else if (paymentstatuscode === 'CANC') { |
|
|
|
// const timestamp = Date.now(); |
|
|
|
navigate('/paymentPage/fps/ackpage'); |
|
|
|
} else { |
|
|
|
// window.top.location.href = paymentPath + payment.config.errPagePath; |
|
|
|
alert("ERROR") |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
onError: function(){ |
|
|
|
cancelPayment() |
|
|
|
// clearInterval(currentTimer.current); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
React.useEffect(() => { |
|
|
|
const timeOutDate = new Date(fpsmerchanttimeoutdatetime); |
|
|
|
const currentTime = new Date; |
|
|
|
const timedowncount = Math.round((timeOutDate.getTime() - currentTime.getTime()) / 1000); |
|
|
|
setTimeDownCount(timedowncount); |
|
|
|
// console.log(time) |
|
|
|
// console.log(timeOutDate) |
|
|
|
// console.log(currentTime) |
|
|
|
// console.log(timeOutDate.getTime()-currentTime.getTime()) |
|
|
|
getPaymentStatus(); |
|
|
|
if (timeOutDate.getTime()<currentTime.getTime()){ |
|
|
|
console.log("stop"); |
|
|
|
clearInterval(currentTimer.current); |
|
|
|
cancelPayment() |
|
|
|
} |
|
|
|
},[time]) |
|
|
|
|
|
|
|
const cancelPayment = ()=>{ |
|
|
|
if (Object.keys(paymentData).length>0){ |
|
|
|
HttpUtils.post({ |
|
|
|
url: paymentPath+cancelPaymentUrl, |
|
|
|
params:{ |
|
|
|
"transactionid": paymentData.transactionid, |
|
|
|
"webtoken": paymentData.webtoken, |
|
|
|
"paymentid": fpsTransctionData.paymentid |
|
|
|
}, |
|
|
|
onSuccess: function(){ |
|
|
|
navigate('/paymentPage/fps/ackpage'); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
const mobliePayment = ()=>{ |
|
|
|
window.location.assign(fpsqrcodeurl); |
|
|
|
} |
|
|
|
|
|
|
|
return ( |
|
|
|
!onReady ? |
|
|
|
<LoadingComponent /> |
|
|
|
: |
|
|
|
( |
|
|
|
<Grid container sx={{ minHeight: '110vh', backgroundColor: '#fff' }} direction="column" justifyContent="flex-start" alignItems="center" > |
|
|
|
<Grid item xs={12} width="100%"> |
|
|
|
<div style={BackgroundHead} width="100%"> |
|
|
|
<Stack direction="row" height='70px'> |
|
|
|
<Typography ml={15} color='#FFF' variant="h4" sx={{ pt: 2 }}>公共啟事:FPS付款</Typography> |
|
|
|
</Stack> |
|
|
|
</div> |
|
|
|
</Grid> |
|
|
|
{/*row 1*/} |
|
|
|
<Grid item xs={12} md={12} > |
|
|
|
<Grid container justifyContent="flex-start" alignItems="center" > |
|
|
|
<center> |
|
|
|
<Grid item xs={12} md={12} > |
|
|
|
|
|
|
|
<Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}> |
|
|
|
<img src={FpsIcon} width="80" height="80" alt="FPS"></img> |
|
|
|
<br /> |
|
|
|
支付金額 |
|
|
|
<br /> |
|
|
|
{"$HK " + paymentData.amount} |
|
|
|
</Typography> |
|
|
|
|
|
|
|
|
|
|
|
{browserType==mobileBrowser? |
|
|
|
<Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}> |
|
|
|
<Button |
|
|
|
component="span" |
|
|
|
variant="contained" |
|
|
|
size="large" |
|
|
|
color="primary" |
|
|
|
onClick={()=>{ |
|
|
|
mobliePayment(); |
|
|
|
}} |
|
|
|
sx={{ m: 4 }} |
|
|
|
>請選擇支付程式付款</Button> |
|
|
|
</Typography>: |
|
|
|
<Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}> |
|
|
|
請掃描以下二維碼 |
|
|
|
<br /> |
|
|
|
<img src={fpsTransctionData.fpsqrcodeimgbase64} alt="QR Code"/> |
|
|
|
<br /> |
|
|
|
{paymentId} |
|
|
|
<br/> |
|
|
|
二維碼有效期限3分鐘 |
|
|
|
<br /> |
|
|
|
請在規定時間內完成付款流程 |
|
|
|
<br /> |
|
|
|
{"剩餘時間:"+timeDownCount} |
|
|
|
</Typography> |
|
|
|
} |
|
|
|
<Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}> |
|
|
|
<Button |
|
|
|
component="span" |
|
|
|
variant="contained" |
|
|
|
size="large" |
|
|
|
color="error" |
|
|
|
onClick={()=>{ |
|
|
|
cancelPayment(); |
|
|
|
}} |
|
|
|
sx={{ m: 4 }} |
|
|
|
>取消付款</Button> |
|
|
|
</Typography> |
|
|
|
</Grid> |
|
|
|
</center> |
|
|
|
</Grid> |
|
|
|
</Grid> |
|
|
|
{/*row 2*/} |
|
|
|
</Grid > |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
); |
|
|
|
}; |
|
|
|
|
|
|
|
export default Index; |