25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 

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