@@ -12,6 +12,8 @@ export const hostPath = `http://${hostname}:${hostPort}`; | |||||
//export const apiPath = `http://192.168.0.112:8090/api`; | //export const apiPath = `http://192.168.0.112:8090/api`; | ||||
export const apiPath = `${hostPath}/api`; | export const apiPath = `${hostPath}/api`; | ||||
//export const apiPath = `/api`; | //export const apiPath = `/api`; | ||||
export const paymentPath = `https://pnspsdev.gld.gov.hk/payment`; | |||||
export const isUserLoggedIn = () => { | export const isUserLoggedIn = () => { | ||||
return localStorage.getItem('userData') && localStorage.getItem(useJwt.jwtConfig.storageTokenKeyName); | return localStorage.getItem('userData') && localStorage.getItem(useJwt.jwtConfig.storageTokenKeyName); | ||||
@@ -9,6 +9,9 @@ import * as React from "react"; | |||||
import * as HttpUtils from "utils/HttpUtils"; | import * as HttpUtils from "utils/HttpUtils"; | ||||
import { useNavigate } from "react-router-dom"; | import { useNavigate } from "react-router-dom"; | ||||
import FpsIcon from "assets/images/icons/fps.svg"; | 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'; | import Loadable from 'components/Loadable'; | ||||
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); | const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); | ||||
@@ -28,53 +31,56 @@ const BackgroundHead = { | |||||
const Index = () => { | const Index = () => { | ||||
const navigate = useNavigate() | const navigate = useNavigate() | ||||
const location = useLocation(); | |||||
const [fpsqrcodeimgUrl, setFpsqrcodeimgUrl] = React.useState(); | |||||
const [paymentData, setPaymentData] = React.useState({}); | |||||
const [onReady, setOnReady] = React.useState(false); | 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 loadPaymentUrl = "/api/payment/wallet/fps"; | ||||
const cancelPaymentUrl = "/api/payment/cancelpayment"; | const cancelPaymentUrl = "/api/payment/cancelpayment"; | ||||
const paymentStatusApi = "/api/payment/status/"; | |||||
// const payloadUrl = "/api/payment/wallet/fps/enquiryfpspayload/"; | // const payloadUrl = "/api/payment/wallet/fps/enquiryfpspayload/"; | ||||
// const receiverUrl = "/noti-api/payment/payment-notification"; | // const receiverUrl = "/noti-api/payment/payment-notification"; | ||||
React.useEffect(() => { | React.useEffect(() => { | ||||
setFpsqrcodeimgbase64("") | |||||
if(location.state != undefined){ | |||||
setPaymentData(location.state) | |||||
} | |||||
loadForm(); | loadForm(); | ||||
}, []); | }, []); | ||||
React.useEffect(() => { | React.useEffect(() => { | ||||
setOnReady(true); | setOnReady(true); | ||||
}, [fpsqrcodeimgUrl]); | |||||
}, [fpsqrcodeimgbase64]); | |||||
const loadForm = () => { | const loadForm = () => { | ||||
HttpUtils.post({ | HttpUtils.post({ | ||||
url: loadPaymentUrl, | |||||
url: paymentPath+loadPaymentUrl, | |||||
params:{ | params:{ | ||||
"transactionid": "<transactionid>", | |||||
"webtoken": "<webtoken>", | |||||
"paymentmethod": "<paymentmethodcode>", | |||||
"transactionid": paymentData.transactionid, | |||||
"webtoken": paymentData.webtoken, | |||||
"paymentmethod":"04,BCFP,FPS", | |||||
"order": { | "order": { | ||||
"totalamount":"<totalamount>", | |||||
"currency":"<currency>", | |||||
"totalamount":paymentData.amount, | |||||
"currency":"HKD", | |||||
"orderdetail": | "orderdetail": | ||||
[ | [ | ||||
{ | { | ||||
"itemid": "<itemid>", | |||||
"qty":"<qty>", | |||||
"unitprice":"<unitprice>", | |||||
"amount":"<amount>" | |||||
}, | |||||
{ | |||||
"itemid": "<itemid>", | |||||
"qty":"<qty>", | |||||
"unitprice":"<unitprice>", | |||||
"amount":"<amount>" | |||||
"itemid": "1", | |||||
"qty":"1", | |||||
"unitprice":paymentData.amount, | |||||
"amount":paymentData.amount | |||||
}, | }, | ||||
] | ] | ||||
}, | }, | ||||
"locale":"<locale>", | |||||
"eserviceid":"<eserviceid>" | |||||
// "locale":"<locale>", | |||||
// "eserviceid":"<eserviceid>" | |||||
}, | }, | ||||
onSuccess: function(responseData){ | onSuccess: function(responseData){ | ||||
/* | /* | ||||
@@ -86,27 +92,60 @@ const Index = () => { | |||||
"fpsqrcodeurl": "<fpsqrcodeurl>" | "fpsqrcodeurl": "<fpsqrcodeurl>" | ||||
} | } | ||||
*/ | */ | ||||
setFpsqrcodeimgUrl(responseData.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() | |||||
} | |||||
}); | |||||
}; | |||||
useEffect(() => { | |||||
const timeOut = fpsmerchanttimeoutdatetime=now()?500:null; | |||||
const interval = setInterval(() => { | |||||
getPaymentStatus(); | |||||
console.log("test"); | |||||
}, timeOut); | |||||
return () => clearInterval(interval); | |||||
}, []); | |||||
const cancelPayment = ()=>{ | const cancelPayment = ()=>{ | ||||
HttpUtils.post({ | HttpUtils.post({ | ||||
url: cancelPaymentUrl, | |||||
url: paymentPath+cancelPaymentUrl, | |||||
params:{ | params:{ | ||||
"transactionid": "<transactionid>", | |||||
"webtoken": "<webtoken>", | |||||
"paymentid": "<paymentid>" | |||||
"transactionid": paymentData.transactionid, | |||||
"webtoken": paymentData.webtoken, | |||||
"paymentid": paymentid | |||||
}, | }, | ||||
onSuccess: function(){ | onSuccess: function(){ | ||||
/* | |||||
{ | |||||
"resultcode": "<resultcode>", | |||||
"reason": "<reason>" | |||||
} | |||||
*/ | |||||
navigate("/dashboard"); | navigate("/dashboard"); | ||||
} | } | ||||
}); | }); | ||||
@@ -165,13 +204,13 @@ const Index = () => { | |||||
<br /> | <br /> | ||||
支付金額 | 支付金額 | ||||
<br /> | <br /> | ||||
$ | |||||
{"$HK " + paymentData.amount} | |||||
</Typography> | </Typography> | ||||
<Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}> | <Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}> | ||||
請掃描以下二維碼 | 請掃描以下二維碼 | ||||
<br /> | <br /> | ||||
<img src={fpsqrcodeimgUrl} alt="QR Code"/> | |||||
<img src={fpsqrcodeimgbase64} alt="QR Code"/> | |||||
<br /> | <br /> | ||||
二維碼有效期限10分鐘 | 二維碼有效期限10分鐘 | ||||
<br /> | <br /> | ||||
@@ -24,12 +24,27 @@ const MultiPaymentWindow = (props) => { | |||||
const windowTitle = "請選擇付款方式"; | const windowTitle = "請選擇付款方式"; | ||||
const [content, setContent] = useState(); | const [content, setContent] = useState(); | ||||
const [paymentMethod, setPaymentMethod] = useState(""); | |||||
useEffect(() => { | useEffect(() => { | ||||
console.log(props.fpsStatus) | |||||
console.log(props.creditCardStatus) | |||||
console.log(props.unionPayStatus) | |||||
console.log(props.ppsStatus) | |||||
console.log(paymentMethod) | |||||
}, [paymentMethod]); | |||||
const selectedPaymentMethodHandle = (method) => () =>{ | |||||
setPaymentMethod(method) | |||||
props.setSelectedPaymentMethod(method); | |||||
}; | |||||
const confirmPaymentHandle = () => () =>{ | |||||
props.setConfirmPayment(true); | |||||
}; | |||||
useEffect(() => { | |||||
if(props.selectedPaymentMethod === ""){ | |||||
setPaymentMethod("") | |||||
} | |||||
setPaymentMethod | |||||
if(props.availableMethods.length > 0){ | if(props.availableMethods.length > 0){ | ||||
setContent( | setContent( | ||||
<Grid container spacing={2} direction="column" justifyContent="space-between" alignItems="flex-start"> | <Grid container spacing={2} direction="column" justifyContent="space-between" alignItems="flex-start"> | ||||
@@ -69,27 +84,48 @@ const MultiPaymentWindow = (props) => { | |||||
</FormLabel> | </FormLabel> | ||||
</Grid> | </Grid> | ||||
<Grid item> | <Grid item> | ||||
<Button variant="contained" color="success" disabled={props.fpsStatus.active === "N"}> | |||||
<Button variant="contained" color="success" onClick={selectedPaymentMethodHandle("FPS")} disabled={props.fpsStatus.active === "N"}> | |||||
FPS | FPS | ||||
</Button> | </Button> | ||||
</Grid> | </Grid> | ||||
<Grid item> | <Grid item> | ||||
<Button variant="contained" color="success" disabled={props.creditCardStatus.active === "N"}> | |||||
<Button variant="contained" color="success" onClick={selectedPaymentMethodHandle("Visa")} disabled={props.creditCardStatus.active === "N"}> | |||||
Visa | Visa | ||||
</Button> | </Button> | ||||
</Grid> | </Grid> | ||||
<Grid item> | <Grid item> | ||||
<Button variant="contained" color="success" disabled={props.unionPayStatus.active === "N"}> | |||||
<Button variant="contained" color="success" onClick={selectedPaymentMethodHandle("Mastercard")} disabled={props.creditCardStatus.active === "N"}> | |||||
Mastercard | Mastercard | ||||
</Button> | </Button> | ||||
</Grid> | </Grid> | ||||
<Grid item> | <Grid item> | ||||
<Button variant="contained" color="success" disabled={props.ppsStatus.active === "N"}> | |||||
<Button variant="contained" color="success" onClick={selectedPaymentMethodHandle("UnionPay")} disabled={props.unionPayStatus.active === "N"}> | |||||
UnionPay | |||||
</Button> | |||||
</Grid> | |||||
<Grid item> | |||||
<Button variant="contained" color="success" onClick={selectedPaymentMethodHandle("PPS")} disabled={props.ppsStatus.active === "N"}> | |||||
PPS | PPS | ||||
</Button> | </Button> | ||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
{paymentMethod !=""? | |||||
<Grid item xs={12} md={12}> | |||||
<Grid container direction="row" justifyContent="flex-start" alignItems="center"> | |||||
<Grid item> | |||||
<FormLabel sx={{ fontSize: "16px", color: "#000000", textAlign: "center" }}> | |||||
已選擇付款方式: | |||||
</FormLabel> | |||||
</Grid> | |||||
<Grid item> | |||||
<FormLabel sx={{ fontSize: "16px", color: "#000000", textAlign: "center" }}> | |||||
{paymentMethod} | |||||
</FormLabel> | |||||
</Grid> | |||||
</Grid> | |||||
</Grid> | |||||
: null} | |||||
</Grid> | </Grid> | ||||
) | ) | ||||
}else{ | }else{ | ||||
@@ -101,7 +137,7 @@ const MultiPaymentWindow = (props) => { | |||||
</Grid> | </Grid> | ||||
) | ) | ||||
} | } | ||||
}, [props.open]); | |||||
}, [props.open,paymentMethod]); | |||||
const formik = useFormik({ | const formik = useFormik({ | ||||
initialValues: ({ | initialValues: ({ | ||||
@@ -145,7 +181,7 @@ const MultiPaymentWindow = (props) => { | |||||
</Button> | </Button> | ||||
</DialogActions> | </DialogActions> | ||||
<DialogActions> | <DialogActions> | ||||
<Button variant="contained" color="success" > | |||||
<Button variant="contained" color="success" onClick={confirmPaymentHandle()} disabled={paymentMethod === ""}> | |||||
確認 | 確認 | ||||
</Button> | </Button> | ||||
</DialogActions> | </DialogActions> | ||||
@@ -5,6 +5,8 @@ import Loadable from 'components/Loadable'; | |||||
const MultiPaymentWindow = Loadable(lazy(() => import('./MultiPaymentWindow'))); | const MultiPaymentWindow = Loadable(lazy(() => import('./MultiPaymentWindow'))); | ||||
// const FPS = Loadable(React.lazy(() => import('./FPS'))); | // const FPS = Loadable(React.lazy(() => import('./FPS'))); | ||||
import {useEffect, useState} from "react"; | import {useEffect, useState} from "react"; | ||||
import {useNavigate} from "react-router-dom"; | |||||
import {paymentPath} from "auth/utils"; | |||||
import { | import { | ||||
Button, | Button, | ||||
@@ -27,20 +29,24 @@ const BackgroundHead = { | |||||
const Index = () => { | const Index = () => { | ||||
// const getAvailablePaymentUrl = "/payment/api/payment/availability"; | // const getAvailablePaymentUrl = "/payment/api/payment/availability"; | ||||
const getTransactionIdUrl = "/payment/api/payment/transaction"; | const getTransactionIdUrl = "/payment/api/payment/transaction"; | ||||
const navigate = useNavigate() | |||||
// const local = {en:"en-us", zh:"zh-hk", cn:"zh-cn"}; | // const local = {en:"en-us", zh:"zh-hk", cn:"zh-cn"}; | ||||
// const preferpaymentmethods = ['visa','mastercard','pps','creditcard','fps']; | // const preferpaymentmethods = ['visa','mastercard','pps','creditcard','fps']; | ||||
const [totalAmount,setTotalAmount] = useState(0); | const [totalAmount,setTotalAmount] = useState(0); | ||||
const id =1; | const id =1; | ||||
//statusWindow | |||||
const [open, setOpen] = useState(false); | |||||
const [availableMethods,setAvailableMethods] = useState([]); | const [availableMethods,setAvailableMethods] = useState([]); | ||||
const [transactionData,setTransactionData] = useState({}); | const [transactionData,setTransactionData] = useState({}); | ||||
const [fpsStatus,setFPSStatus] = useState({}); | const [fpsStatus,setFPSStatus] = useState({}); | ||||
const [creditCardStatus,setCreditCardStatus] = useState({}); | const [creditCardStatus,setCreditCardStatus] = useState({}); | ||||
const [unionPayStatus,setUnionPayStatus] = useState({}); | const [unionPayStatus,setUnionPayStatus] = useState({}); | ||||
const [ppsStatus,setPPSStatus] = useState({}); | const [ppsStatus,setPPSStatus] = useState({}); | ||||
//statusWindow | |||||
const [open, setOpen] = useState(false); | |||||
const [selectedPaymentMethod, setSelectedPaymentMethod] = useState(""); | |||||
const [confirmPayment, setConfirmPayment] = useState(false); | |||||
useEffect(() => { | useEffect(() => { | ||||
if(id > 0 ){ | if(id > 0 ){ | ||||
@@ -55,12 +61,25 @@ const Index = () => { | |||||
const paymentClick = () => { | const paymentClick = () => { | ||||
setTotalAmount(totalAmount); | setTotalAmount(totalAmount); | ||||
setSelectedPaymentMethod("") | |||||
setConfirmPayment(false) | |||||
if (totalAmount>0){ | if (totalAmount>0){ | ||||
setOpen(true) | setOpen(true) | ||||
getAvailablePayment() | getAvailablePayment() | ||||
getTransactionId() | getTransactionId() | ||||
} | } | ||||
}; | }; | ||||
useEffect(() => { | |||||
if (confirmPayment){ | |||||
setOpen(false); | |||||
if(selectedPaymentMethod === "FPS"){ | |||||
navigate('/payment/fps', {state:{amount:totalAmount,transactionid:"",webtoken:""} }); | |||||
// navigate('/payment/fps', {state:{amount:totalAmount,transactionid:transactionData.transactionid,webtoken:transactionData.webtoken} }); | |||||
} | |||||
} | |||||
}, [confirmPayment]); | |||||
const getAvailablePayment = () => { | const getAvailablePayment = () => { | ||||
const responseData = { | const responseData = { | ||||
@@ -125,7 +144,7 @@ const Index = () => { | |||||
] | ] | ||||
}, | }, | ||||
{ | { | ||||
"active": "N", | |||||
"active": "Y", | |||||
"code": "03,BCMP,CreditCard", | "code": "03,BCMP,CreditCard", | ||||
"pointstonote": [ | "pointstonote": [ | ||||
{ | { | ||||
@@ -211,7 +230,7 @@ const Index = () => { | |||||
} | } | ||||
// HttpUtils.post({ | // HttpUtils.post({ | ||||
// url: getAvailablePaymentUrl, | |||||
// url: paymentPath+getAvailablePaymentUrl, | |||||
// params: { | // params: { | ||||
// // "locale": local.zh,; | // // "locale": local.zh,; | ||||
// "amount": totalAmount, | // "amount": totalAmount, | ||||
@@ -248,7 +267,7 @@ const Index = () => { | |||||
const getTransactionId = () => { | const getTransactionId = () => { | ||||
HttpUtils.get({ | HttpUtils.get({ | ||||
url: getTransactionIdUrl, | |||||
url: paymentPath+getTransactionIdUrl, | |||||
onSuccess: (responseData)=>{ | onSuccess: (responseData)=>{ | ||||
const transactionData = responseData; | const transactionData = responseData; | ||||
setTransactionData(transactionData) | setTransactionData(transactionData) | ||||
@@ -256,43 +275,6 @@ const Index = () => { | |||||
}); | }); | ||||
} | } | ||||
// const startFPSTransaction = () => { | |||||
// HttpUtils.post({ | |||||
// url: getAvailablePaymentUrl, | |||||
// params: { | |||||
// // "locale": local.zh,; | |||||
// "amount": totalAmount, | |||||
// // "eserviceids": [ | |||||
// // "<eserviceid>", "<eserviceid>" | |||||
// // ], | |||||
// "preferpaymentmethods": preferpaymentmethods | |||||
// }, | |||||
// onSuccess: (responseData)=>{ | |||||
// let availableMethods = responseData.availablepaymentmethods; | |||||
// setAvailableMethods(availableMethods); | |||||
// if (availableMethods.length>0){ | |||||
// availableMethods.forEach((method)=>{ | |||||
// if(method.subtype === "FPS" ){ | |||||
// setFPSStatus(method) | |||||
// }else if (method.subtype === "CreditCard"){ | |||||
// method.supportedcard.forEach((supportedcard)=>{ | |||||
// if (supportedcard === "JCB" || supportedcard === "MasterCard" || supportedcard === "Visa"){ | |||||
// setCreditCardStatus(method) | |||||
// } else { | |||||
// if (supportedcard === "UnionPay"){ | |||||
// setUnionPayStatus(method) | |||||
// } | |||||
// } | |||||
// }) | |||||
// }else if (method.subtype === "PPS" ){ | |||||
// setPPSStatus(method) | |||||
// } | |||||
// }); | |||||
// } | |||||
// } | |||||
// }); | |||||
// } | |||||
return ( | return ( | ||||
<Grid container sx={{ minHeight: '110vh', backgroundColor: '#fff' }} direction="column" justifyContent="flex-start" alignItems="center" > | <Grid container sx={{ minHeight: '110vh', backgroundColor: '#fff' }} direction="column" justifyContent="flex-start" alignItems="center" > | ||||
<Grid item xs={12} width="100%"> | <Grid item xs={12} width="100%"> | ||||
@@ -337,6 +319,9 @@ const Index = () => { | |||||
creditCardStatus={creditCardStatus} | creditCardStatus={creditCardStatus} | ||||
unionPayStatus={unionPayStatus} | unionPayStatus={unionPayStatus} | ||||
ppsStatus={ppsStatus} | ppsStatus={ppsStatus} | ||||
setSelectedPaymentMethod={setSelectedPaymentMethod} | |||||
selectedPaymentMethod={selectedPaymentMethod} | |||||
setConfirmPayment={setConfirmPayment} | |||||
/> | /> | ||||
</Grid> | </Grid> | ||||
{/*row 2*/} | {/*row 2*/} | ||||