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.
 
 

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