You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

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