Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 

316 rindas
13 KiB

  1. // material-ui
  2. import {
  3. Grid,
  4. Typography,
  5. Stack,
  6. Button,
  7. } from '@mui/material';
  8. import * as React from "react";
  9. import * as HttpUtils from "utils/HttpUtils";
  10. import { useNavigate } from "react-router-dom";
  11. import FpsIcon from "assets/images/icons/fps.svg";
  12. import { useLocation } from 'react-router-dom';
  13. import {paymentPath} from "auth/utils";
  14. // import {poll} from "utils/Utils";
  15. import Loadable from 'components/Loadable';
  16. const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent')));
  17. import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png'
  18. const BackgroundHead = {
  19. backgroundImage: `url(${titleBackgroundImg})`,
  20. width: '100%',
  21. height: '100%',
  22. backgroundSize: 'contain',
  23. backgroundRepeat: 'no-repeat',
  24. backgroundColor: '#0C489E',
  25. backgroundPosition: 'right'
  26. }
  27. // ==============================|| DASHBOARD - DEFAULT ||============================== //
  28. const Index = () => {
  29. const navigate = useNavigate()
  30. const location = useLocation();
  31. const [locationData, setLocationData] = React.useState({});
  32. const [paymentData, setPaymentData] = React.useState({});
  33. const [onReady, setOnReady] = React.useState(false);
  34. const [responeData, setResponeDataData] = React.useState({});
  35. const [fpsTransctionData, setFpsTransctionData] = React.useState({});
  36. const [fpsmerchanttimeoutdatetime, setFpsmerchanttimeoutdatetime] = React.useState("");
  37. const [timeDownCount, setTimeDownCount] = React.useState(0);
  38. const [paymentId, setPaymentId] = React.useState("");
  39. const [fpsqrcodeurl, setFpsqrcodeurl] = React.useState("");
  40. const [browserType, setBrowserType] = React.useState("");
  41. const mobileBrowser = "Mobile";
  42. const desktopBrowser = "Desktop";
  43. // const pasgPath = 'https://fps.payapps.hkicl.com.hk'; //PRD
  44. const pasgPath = 'https://sim.fps.payapps.hkicl.com.hk'; //Testing
  45. const loadPaymentUrl = "/api/payment/wallet/fps";
  46. const cancelPaymentUrl = "/api/payment/cancelpayment";
  47. const paymentStatusApi = "/api/payment/status/";
  48. // const payloadUrl = "/api/payment/wallet/fps/enquiryfpspayload/";
  49. // const receiverUrl = "/noti-api/payment/payment-notification";
  50. //timer
  51. const currentTimer = React.useRef();
  52. const [time, setTime] = React.useState(0);
  53. React.useEffect(() => {
  54. // console.log (location.state)
  55. if(Object.keys(location.state).length > 0){
  56. console.log (location.state)
  57. setLocationData(location.state)
  58. if (/Android|webOS|iPhone|iPad|iPod|Opera Mini/i.test(navigator.userAgent)) {
  59. console.log('Mobile web browser');
  60. setBrowserType(mobileBrowser)
  61. } else {
  62. console.log('Desktop web browser');
  63. setBrowserType(desktopBrowser)
  64. }
  65. }
  66. }, []);
  67. React.useEffect(() => {
  68. // console.log (locationData)
  69. if (Object.keys(locationData).length > 0){
  70. setPaymentData(locationData)
  71. // loadForm();
  72. }
  73. }, [locationData]);
  74. React.useEffect(() => {
  75. // console.log (paymentData)
  76. if (Object.keys(paymentData).length > 0){
  77. loadForm();
  78. }
  79. }, [paymentData]);
  80. React.useEffect(() => {
  81. // console.log(responeData)
  82. if(Object.keys(responeData).length > 0 && fpsmerchanttimeoutdatetime!=""){
  83. setFpsTransctionData(responeData)
  84. }
  85. }, [responeData]);
  86. React.useEffect(() => {
  87. // console.log(fpsTransctionData)
  88. if(Object.keys(fpsTransctionData).length > 0 ){
  89. setPaymentId(fpsTransctionData.paymentid)
  90. currentTimer.current = setInterval(() => {
  91. setTime((prevTime) => prevTime + 1);
  92. }, 1000);
  93. setOnReady(true);
  94. return () => clearInterval(currentTimer.current);
  95. }
  96. }, [fpsTransctionData]);
  97. const loadForm = () => {
  98. // const timeoutdatetime = "2023-10-26T09:04:30Z[UTC]"
  99. // const convertedDateString = timeoutdatetime.replace("[UTC]", "");
  100. // setFpsmerchanttimeoutdatetime(convertedDateString)
  101. // setPaymentid("C202310268000681")
  102. // setPaymentstatuscode("APPR")
  103. localStorage.removeItem("transactionid")
  104. localStorage.removeItem("webtoken")
  105. localStorage.setItem("transactionid", paymentData.transactionid)
  106. localStorage.setItem("webtoken", paymentData.webtoken)
  107. HttpUtils.post({
  108. url: paymentPath+loadPaymentUrl,
  109. params:{
  110. "transactionid": paymentData.transactionid,
  111. "webtoken": paymentData.webtoken,
  112. "paymentmethod":"04,BCFP,FPS",
  113. "order": {
  114. "totalamount":paymentData.amount,
  115. "currency":"HKD",
  116. "orderdetail":
  117. [
  118. {
  119. "itemid": "1",
  120. "qty":"1",
  121. "unitprice":paymentData.amount,
  122. "amount":paymentData.amount
  123. },
  124. ]
  125. },
  126. // "locale":"<locale>",
  127. // "eserviceid":"<eserviceid>"
  128. },
  129. onSuccess: function(responseData){
  130. /*
  131. {
  132. "paymentid": "<paymentid>",
  133. "paymentstatus": "<paymentstatus>",
  134. "fpsmerchanttimeoutdatetime": <fpsmerchanttimeoutdatetime>,
  135. "fpsqrcodeimgbase64": "<fpsqrcodeimgbase64>",
  136. "fpsqrcodeurl": "<fpsqrcodeurl>"
  137. }
  138. */
  139. setResponeDataData(responseData)
  140. const timeoutdatetime = responseData.fpsmerchanttimeoutdatetime
  141. const convertedDateString = timeoutdatetime.replace("[UTC]", "");
  142. setFpsmerchanttimeoutdatetime(convertedDateString)
  143. // const parsedUrl = new URL(responseData.fpsqrcodeurl);
  144. // const fpsqrcodeurl = parsedUrl.pathname;
  145. const openPASGUrl = pasgPath + '?pay_req_obj=' + encodeURIComponent(responseData.fpsqrcodeurl) + '&callback='
  146. + encodeURIComponent("https://"+window.location.hostname+ '/paymentPage/fps/ackpage');
  147. setFpsqrcodeurl(openPASGUrl)
  148. }
  149. });
  150. }
  151. const getPaymentStatus = () => {
  152. if(Object.keys(paymentData).length > 0){
  153. HttpUtils.post({
  154. url: paymentPath+paymentStatusApi+paymentData.transactionid,
  155. params:{
  156. "apprefid": paymentData.transactionid,
  157. "webtoken": paymentData.webtoken,
  158. },
  159. onSuccess: function(responseData){
  160. const paymentstatuscode = responseData.paymentdetail.result.paymentstatuscode;
  161. if (paymentstatuscode != "" && paymentstatuscode != "INPR" ){
  162. if (paymentstatuscode === 'APPR') {
  163. // const timestamp = Date.now();
  164. navigate('/paymentPage/fps/ackpage');
  165. } else if (paymentstatuscode === 'CANC') {
  166. // const timestamp = Date.now();
  167. navigate('/paymentPage/fps/ackpage');
  168. } else {
  169. // window.top.location.href = paymentPath + payment.config.errPagePath;
  170. alert("ERROR")
  171. }
  172. }
  173. },
  174. onError: function(){
  175. cancelPayment()
  176. // clearInterval(currentTimer.current);
  177. }
  178. });
  179. }
  180. };
  181. React.useEffect(() => {
  182. const timeOutDate = new Date(fpsmerchanttimeoutdatetime);
  183. const currentTime = new Date;
  184. const timedowncount = Math.round((timeOutDate.getTime() - currentTime.getTime()) / 1000);
  185. setTimeDownCount(timedowncount);
  186. // console.log(time)
  187. // console.log(timeOutDate)
  188. // console.log(currentTime)
  189. // console.log(timeOutDate.getTime()-currentTime.getTime())
  190. getPaymentStatus();
  191. if (timeOutDate.getTime()<currentTime.getTime()){
  192. console.log("stop");
  193. clearInterval(currentTimer.current);
  194. cancelPayment()
  195. }
  196. },[time])
  197. const cancelPayment = ()=>{
  198. if (Object.keys(paymentData).length>0){
  199. HttpUtils.post({
  200. url: paymentPath+cancelPaymentUrl,
  201. params:{
  202. "transactionid": paymentData.transactionid,
  203. "webtoken": paymentData.webtoken,
  204. "paymentid": fpsTransctionData.paymentid
  205. },
  206. onSuccess: function(){
  207. navigate('/paymentPage/fps/ackpage');
  208. }
  209. });
  210. }
  211. }
  212. const mobliePayment = ()=>{
  213. window.location.assign(fpsqrcodeurl);
  214. }
  215. return (
  216. !onReady ?
  217. <LoadingComponent />
  218. :
  219. (
  220. <Grid container sx={{ minHeight: '110vh', backgroundColor: '#fff' }} direction="column" justifyContent="flex-start" alignItems="center" >
  221. <Grid item xs={12} width="100%">
  222. <div style={BackgroundHead} width="100%">
  223. <Stack direction="row" height='70px'>
  224. <Typography ml={15} color='#FFF' variant="h4" sx={{ pt: 2 }}>公共啟事:FPS付款</Typography>
  225. </Stack>
  226. </div>
  227. </Grid>
  228. {/*row 1*/}
  229. <Grid item xs={12} md={12} >
  230. <Grid container justifyContent="flex-start" alignItems="center" >
  231. <center>
  232. <Grid item xs={12} md={12} >
  233. <Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}>
  234. <img src={FpsIcon} width="80" height="80" alt="FPS"></img>
  235. <br />
  236. 支付金額
  237. <br />
  238. {"$HK " + paymentData.amount}
  239. </Typography>
  240. {browserType==mobileBrowser?
  241. <Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}>
  242. <Button
  243. component="span"
  244. variant="contained"
  245. size="large"
  246. color="primary"
  247. onClick={()=>{
  248. mobliePayment();
  249. }}
  250. sx={{ m: 4 }}
  251. >請選擇支付程式付款</Button>
  252. </Typography>
  253. :
  254. <Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}>
  255. 請掃描以下二維碼
  256. <br />
  257. <img src={fpsTransctionData.fpsqrcodeimgbase64} alt="QR Code"/>
  258. <br />
  259. {paymentId}
  260. <br/>
  261. 二維碼有效期限3分鐘
  262. <br />
  263. 請在規定時間內完成付款流程
  264. <br />
  265. {"剩餘時間:"+timeDownCount}
  266. </Typography>
  267. }
  268. <Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}>
  269. <Button
  270. component="span"
  271. variant="contained"
  272. size="large"
  273. color="error"
  274. onClick={()=>{
  275. cancelPayment();
  276. }}
  277. sx={{ m: 4 }}
  278. >取消付款</Button>
  279. </Typography>
  280. </Grid>
  281. </center>
  282. </Grid>
  283. </Grid>
  284. {/*row 2*/}
  285. </Grid >
  286. )
  287. );
  288. };
  289. export default Index;