@@ -1,249 +0,0 @@ | |||
// 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 [paymentData, setPaymentData] = React.useState({}); | |||
const [onReady, setOnReady] = React.useState(false); | |||
const [paymentid, setPaymentid] = React.useState(""); | |||
const [fpsmerchanttimeoutdatetime, setFpsmerchanttimeoutdatetime] = React.useState(""); | |||
const [fpsqrcodeimgbase64, setFpsqrcodeimgbase64] = React.useState(""); | |||
const [fpsqrcodeurl, setFpsqrcodeurl] = React.useState(""); | |||
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"; | |||
React.useEffect(() => { | |||
setFpsqrcodeimgbase64("") | |||
if(location.state != undefined){ | |||
setPaymentData(location.state) | |||
} | |||
loadForm(); | |||
}, []); | |||
React.useEffect(() => { | |||
setOnReady(true); | |||
}, [fpsqrcodeimgbase64]); | |||
const loadForm = () => { | |||
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>" | |||
} | |||
*/ | |||
setFpsqrcodeimgbase64(responseData.fpsqrcodeimgbase64); | |||
setPaymentid(responseData.paymentid); | |||
setFpsmerchanttimeoutdatetime(responseData.fpsmerchanttimeoutdatetime); | |||
const parsedUrl = new URL(responseData.fpsqrcodeurl); | |||
const fpsqrcodeurl = parsedUrl.pathname | |||
setFpsqrcodeurl(fpsqrcodeurl) | |||
polling() | |||
} | |||
}); | |||
} | |||
const getPaymentStatus = () => { | |||
HttpUtils.post({ | |||
url: paymentPath+paymentStatusApi+paymentid, | |||
params:{ | |||
"apprefid": paymentData.transactionid, | |||
"webtoken": paymentData.webtoken, | |||
}, | |||
onSuccess: function(responseData){ | |||
const paymentstatuscode = responseData.paymentdetail.result.paymentstatuscode; | |||
if (paymentstatuscode === 'APPR') { | |||
const timestamp = '?t=' + Date.now(); | |||
window.top.location.href = payment.config.domain + payment.config.ackPagePath + timestamp; | |||
} else if (paymentstatuscode === 'CANC') { | |||
window.top.location.href = payment.config.domain + payment.config.indexPagePath; | |||
} else { | |||
window.top.location.href = payment.config.domain + payment.config.errPagePath; | |||
} | |||
}, | |||
onError: function(){ | |||
cancelPayment() | |||
} | |||
}); | |||
}; | |||
React.useEffect(() => { | |||
//Fake | |||
setFpsmerchanttimeoutdatetime(new Date().now()?500:null); | |||
// | |||
const timeOut = fpsmerchanttimeoutdatetime; | |||
const interval = setInterval(() => { | |||
getPaymentStatus(); | |||
console.log("test"); | |||
}, timeOut); | |||
return () => clearInterval(interval); | |||
}, []); | |||
const cancelPayment = ()=>{ | |||
HttpUtils.post({ | |||
url: paymentPath+cancelPaymentUrl, | |||
params:{ | |||
"transactionid": paymentData.transactionid, | |||
"webtoken": paymentData.webtoken, | |||
"paymentid": paymentid | |||
}, | |||
onSuccess: function(){ | |||
navigate("/dashboard"); | |||
} | |||
}); | |||
} | |||
// const getPayload = ()=>{ | |||
// HttpUtils.get({ | |||
// url: payloadUrl+"<paymenttoken>", | |||
// onSuccess: function(responseData){ | |||
// /* | |||
// { | |||
// "payload": "<payload>" | |||
// } | |||
// */ | |||
// } | |||
// }); | |||
// } | |||
// const getReceiver = ()=>{ | |||
// HttpUtils.get({ | |||
// url: receiverUrl+"<paymenttoken>", | |||
// onSuccess: function(responseData){ | |||
// /* | |||
// { | |||
// "payload": "<payload>" | |||
// } | |||
// */ | |||
// } | |||
// }); | |||
// } | |||
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> | |||
<Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}> | |||
請掃描以下二維碼 | |||
<br /> | |||
<img src={fpsqrcodeimgbase64} alt="QR Code"/> | |||
<img src={fpsqrcodeurl} alt="QR Code"/> | |||
<br /> | |||
二維碼有效期限10分鐘 | |||
<br /> | |||
請在規定時間內完成付款流程 | |||
</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; |
@@ -1,11 +1,242 @@ | |||
// 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 Card = Loadable(React.lazy(() => import('./card'))); | |||
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' | |||
} | |||
const Index = ({ isPopUp, url }) => { | |||
const navigate = useNavigate() | |||
const location = useLocation(); | |||
const [paymentData, setPaymentData] = React.useState({}); | |||
const [onReady, setOnReady] = React.useState(false); | |||
const [paymentid, setPaymentid] = React.useState(""); | |||
const [fpsmerchanttimeoutdatetime, setFpsmerchanttimeoutdatetime] = React.useState(""); | |||
const [redirecturl, setRedirectUrl] = React.useState(""); | |||
// const [paymentstatuscode, setPaymentstatuscode] = React.useState(""); | |||
// const [fpsqrcodeurl, setFpsqrcodeurl] = React.useState(""); | |||
// const pasgPath = 'https://fps.payapps.hkicl.com.hk'; //PRD | |||
// const pasgPath = 'https://sim.fps.payapps.hkicl.com.hk'; //Testing | |||
// const loadPaymentUrl = "/api/payment/web/"; | |||
const cancelPaymentUrl = "/api/payment/cancelpayment"; | |||
// const paymentStatusApi = "/api/payment/status/"; | |||
// const payloadUrl = "/api/payment/wallet/fps/enquiryfpspayload/"; | |||
// const receiverUrl = "/noti-api/payment/payment-notification"; | |||
//timer | |||
const currentTimer = React.useRef(); | |||
const [time, setTime] = React.useState(0); | |||
React.useEffect(() => { | |||
setFpsqrcodeimgbase64("") | |||
if (location.state != undefined) { | |||
setPaymentData(location.state) | |||
} | |||
loadForm(); | |||
currentTimer.current = setInterval(() => { | |||
getPaymentStatus(); | |||
setTime((prevTime) => prevTime + 1); | |||
}, 500); | |||
return () => clearInterval(currentTimer.current); | |||
}, []); | |||
React.useEffect(() => { | |||
setOnReady(true); | |||
}, [redirecturl]); | |||
const loadForm = () => { | |||
const timeoutdatetime = "2023-10-26T09:04:30Z[UTC]" | |||
const convertedDateString = timeoutdatetime.replace("[UTC]", ""); | |||
setFpsmerchanttimeoutdatetime(convertedDateString) | |||
setPaymentid("C202310268000681") | |||
// HttpUtils.post({ | |||
// url: paymentPath+loadPaymentUrl+paymentData.type, | |||
// params:{ | |||
// "transactionid": paymentData.transactionid, | |||
// "apprefid:": paymentData.transactionid, | |||
// "webtoken": paymentData.webtoken, | |||
// "paymentmethod":paymentData.paymentMethod, | |||
// "order": { | |||
// "totalamount":paymentData.amount, | |||
// "currency":"HKD", | |||
// "orderdetail": | |||
// [ | |||
// { | |||
// "itemid": "1", | |||
// "qty":"1", | |||
// "unitprice":paymentData.amount, | |||
// "amount":paymentData.amount | |||
// }, | |||
// ] | |||
// }, | |||
// // "locale":"<locale>", | |||
// // "eserviceid":"<eserviceid>", | |||
// "returnurl": window.location.hostname+"/payment/success" | |||
// }, | |||
// onSuccess: function(responseData){ | |||
// /* | |||
// { | |||
// "transactionid": "<transactionid>", | |||
// "redirecturl": "<redirecturl>" | |||
// } | |||
// */ | |||
// setRedirectUrl(responseData.redirecturl); | |||
// | |||
// } | |||
// }); | |||
} | |||
const getPaymentStatus = () => { | |||
// HttpUtils.post({ | |||
// url: paymentPath+paymentStatusApi+paymentid, | |||
// params:{ | |||
// "apprefid": paymentData.transactionid, | |||
// "webtoken": paymentData.webtoken, | |||
// }, | |||
// onSuccess: function(responseData){ | |||
// const paymentstatuscode = responseData.paymentdetail.result.paymentstatuscode; | |||
// if (paymentstatuscode === 'APPR') { | |||
// const timestamp = '?t=' + Date.now(); | |||
// window.top.location.href = paymentPath + payment.config.ackPagePath + timestamp; | |||
// } else if (paymentstatuscode === 'CANC') { | |||
// window.top.location.href = paymentPath + payment.config.indexPagePath; | |||
// } else { | |||
// window.top.location.href = paymentPath + payment.config.errPagePath; | |||
// } | |||
// }, | |||
// onError: function(){ | |||
// cancelPayment() | |||
// clearInterval(currentTimer.current); | |||
// } | |||
// }); | |||
}; | |||
React.useEffect(() => { | |||
const timeOutDate = new Date(fpsmerchanttimeoutdatetime); | |||
const currentTime = new Date; | |||
if (timeOutDate.getTime() < currentTime.getTime()) { | |||
console.log("stop"); | |||
clearInterval(currentTimer.current); | |||
} | |||
}, [time]) | |||
const cancelPayment = () => { | |||
HttpUtils.post({ | |||
url: paymentPath + cancelPaymentUrl, | |||
params: { | |||
"transactionid": paymentData.transactionid, | |||
"webtoken": paymentData.webtoken, | |||
"paymentid": paymentid | |||
}, | |||
onSuccess: function () { | |||
navigate("/dashboard"); | |||
} | |||
}); | |||
} | |||
// const getPayload = ()=>{ | |||
// HttpUtils.get({ | |||
// url: payloadUrl+"<paymenttoken>", | |||
// onSuccess: function(responseData){ | |||
// /* | |||
// { | |||
// "payload": "<payload>" | |||
// } | |||
// */ | |||
// } | |||
// }); | |||
// } | |||
// const getReceiver = ()=>{ | |||
// HttpUtils.get({ | |||
// url: receiverUrl+"<paymenttoken>", | |||
// onSuccess: function(responseData){ | |||
// /* | |||
// { | |||
// "payload": "<payload>" | |||
// } | |||
// */ | |||
// } | |||
// }); | |||
// } | |||
const Index = () => { | |||
return ( | |||
<Card/> | |||
!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 }}>公共啟事: 信用卡付款</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> | |||
<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 > | |||
) | |||
); | |||
} | |||
@@ -233,7 +233,7 @@ const Index = () => { | |||
<br /> | |||
二維碼有效期限10分鐘 | |||
<br /> | |||
請在規定時間內完成付款流程 ({fpsmerchanttimeoutdatetime}) | |||
請在規定時間內完成付款流程 | |||
</Typography> | |||
<Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}> | |||
@@ -0,0 +1,98 @@ | |||
// material-ui | |||
import { | |||
Grid, | |||
Typography, | |||
Stack, | |||
} from '@mui/material'; | |||
import * as UrlUtils from "utils/ApiPathConst"; | |||
import * as React from "react"; | |||
import * as HttpUtils from "utils/HttpUtils"; | |||
import { useParams } from "react-router-dom"; | |||
import { useNavigate } from "react-router-dom"; | |||
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 params = useParams(); | |||
const navigate = useNavigate() | |||
const [record, setRecord] = React.useState(); | |||
const [onReady, setOnReady] = React.useState(false); | |||
React.useEffect(() => { | |||
loadForm(); | |||
}, []); | |||
React.useEffect(() => { | |||
setOnReady(true); | |||
}, [record]); | |||
const loadForm = () => { | |||
if (params.id > 0) { | |||
HttpUtils.get({ | |||
url: UrlUtils.GET_PROOF_PAY + "/" + params.id, | |||
onSuccess: (responseData) => { | |||
if (!responseData.data?.id) { | |||
navigate("/proof/search"); | |||
} | |||
setRecord(responseData.data); | |||
} | |||
}); | |||
} | |||
} | |||
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 }}>公共啟事: 付款</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={8} > | |||
<Typography variant="h2" sx={{ textAlign: "left", ml: 4, mr: 4, mt: 4, borderBottom: "1px solid black" }}> | |||
公共啟事:完成付款 | |||
</Typography> | |||
<Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}> | |||
付款成功 | |||
</Typography> | |||
</Grid> | |||
</center> | |||
</Grid> | |||
</Grid> | |||
{/*row 2*/} | |||
</Grid > | |||
) | |||
); | |||
}; | |||
export default Index; |
@@ -1,8 +1,7 @@ | |||
import * as React from "react"; | |||
import { lazy } from 'react'; | |||
import * as HttpUtils from "utils/HttpUtils"; | |||
import Loadable from 'components/Loadable'; | |||
const MultiPaymentWindow = Loadable(lazy(() => import('./MultiPaymentWindow'))); | |||
const MultiPaymentWindow = Loadable(React.lazy(() => import('./MultiPaymentWindow'))); | |||
// const FPS = Loadable(React.lazy(() => import('./FPS'))); | |||
import {useEffect, useState} from "react"; | |||
import {useNavigate} from "react-router-dom"; | |||
@@ -73,9 +72,18 @@ const Index = () => { | |||
useEffect(() => { | |||
if (confirmPayment){ | |||
setOpen(false); | |||
let transactionid = ""; | |||
let webtoken = ""; | |||
if(selectedPaymentMethod === "FPS"){ | |||
navigate('/payment/fps', {state:{amount:totalAmount,transactionid:"",webtoken:""} }); | |||
navigate('/payment/fps', {state:{amount:totalAmount,transactionid:transactionid,webtoken:webtoken} }); | |||
// navigate('/payment/fps', {state:{amount:totalAmount,transactionid:transactionData.transactionid,webtoken:transactionData.webtoken} }); | |||
}else if(selectedPaymentMethod ==="Visa" || selectedPaymentMethod ==="Mastercard"){ | |||
navigate('/payment/card', {state:{amount:totalAmount,transactionid:transactionid,webtoken:webtoken, type:"creditcard", paymentMethod:"02,BCMP,CreditCard"} }); | |||
}else if(selectedPaymentMethod ==="UnionPay" || selectedPaymentMethod ==="JCB"){ | |||
navigate('/payment/card', {state:{amount:totalAmount,transactionid:transactionid,webtoken:webtoken, type:"creditcard", paymentMethod:"03,BCMP,CreditCard"} }); | |||
}else if(selectedPaymentMethod ==="PPS"){ | |||
navigate('/payment/card', {state:{amount:totalAmount,transactionid:transactionid,webtoken:webtoken, type:"pps", paymentMethod:"01,PPSB,PPS"} }); | |||
} | |||
} | |||
@@ -17,6 +17,7 @@ const ProofPayment = Loadable(lazy(() => import('pages/Proof/Payment'))); | |||
const Payment_Multi = Loadable(lazy(() => import('pages/Payment'))); | |||
const Payment_FPS = Loadable(lazy(() => import('pages/Payment/FPS'))); | |||
const Payment_Card = Loadable(lazy(() => import('pages/Payment/Card'))); | |||
const Payment_Success = Loadable(lazy(() => import('pages/Payment/PaymentSuccess'))); | |||
// ==============================|| MAIN ROUTING ||============================== // | |||
@@ -75,6 +76,10 @@ const PublicDashboard = { | |||
path: 'payment/card', | |||
element: <Payment_Card/> | |||
}, | |||
{ | |||
path: 'payment/success', | |||
element: <Payment_Success/> | |||
}, | |||
] | |||
}, | |||
] | |||