diff --git a/src/layout/MainLayout/Header/index.js b/src/layout/MainLayout/Header/index.js index c2755ef..255e1ff 100644 --- a/src/layout/MainLayout/Header/index.js +++ b/src/layout/MainLayout/Header/index.js @@ -516,6 +516,20 @@ function Header(props) { {isGranted("MAINTAIN_SETTING") ? ( <> +
  • + + + HKID Key Migration + + +
  • +
  • + + + User PII Encryption + + +
  • diff --git a/src/pages/Payment/Details_GLD/PaymentDetails.js b/src/pages/Payment/Details_GLD/PaymentDetails.js index 2c7cd0e..7282f51 100644 --- a/src/pages/Payment/Details_GLD/PaymentDetails.js +++ b/src/pages/Payment/Details_GLD/PaymentDetails.js @@ -3,24 +3,33 @@ import { Grid, Typography, FormLabel, - Button + Button, + Dialog, + DialogTitle, + DialogContent, + DialogActions, + Box } from '@mui/material'; import * as React from "react"; import * as FormatUtils from "utils/FormatUtils"; import * as PaymentStatus from "utils/statusUtils/PaymentStatus"; import * as DateUtils from "utils/DateUtils"; +import * as HttpUtils from "utils/HttpUtils"; +import { PAYMENT_MARK_AS_PAID } from "utils/ApiPathConst"; import Loadable from 'components/Loadable'; const MainCard = Loadable(React.lazy(() => import('components/MainCard'))); const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); import DownloadIcon from '@mui/icons-material/Download'; import {useIntl} from "react-intl"; // ==============================|| DASHBOARD - DEFAULT ||============================== // -const PaymentDetails = ({ formData,doPrint,onDownload }) => { +const PaymentDetails = ({ formData, doPrint, onDownload, onRefresh }) => { const intl = useIntl(); const [data, setData] = React.useState({}); const [onReady, setOnReady] = React.useState(false); + const [confirmOpen, setConfirmOpen] = React.useState(false); + const [markingPaid, setMarkingPaid] = React.useState(false); // const { locale } = intl; React.useEffect(() => { @@ -40,9 +49,29 @@ const PaymentDetails = ({ formData,doPrint,onDownload }) => { if("01" == paymentmethod) return "PPS"; if("02" == paymentmethod || "03" == paymentmethod) return "Credit Card"; if("04" == paymentmethod) return "FPS"; + if (data.payMethod === "04,BCFP,FPS") return "FPS"; return paymentmethod; } + const showMarkAsPaid = data.status === "REJT" && getPaymentMethod() === "FPS"; + + const handleMarkAsPaid = () => { + setMarkingPaid(true); + HttpUtils.post({ + url: PAYMENT_MARK_AS_PAID + "/" + data.id, + onSuccess: () => { + setConfirmOpen(false); + setMarkingPaid(false); + if (onRefresh) { + onRefresh(); + } + }, + onError: () => { + setMarkingPaid(false); + } + }); + }; + return ( !onReady ? @@ -51,9 +80,21 @@ const PaymentDetails = ({ formData,doPrint,onDownload }) => { border={false} content={false} > - - Payment Details - + + + Payment Details + + {showMarkAsPaid && ( + + )} +
    @@ -116,7 +157,7 @@ const PaymentDetails = ({ formData,doPrint,onDownload }) => { - EGIS Reference No.: + Payment Reference No.: @@ -176,6 +217,25 @@ const PaymentDetails = ({ formData,doPrint,onDownload }) => { } + !markingPaid && setConfirmOpen(false)} + > + Confirm + + + {`Are you sure to mark as paid for Payment No. ${data.transNo || data.payload?.transactionid} ?`} + + + + + + + ); }; diff --git a/src/pages/Payment/Details_GLD/index.js b/src/pages/Payment/Details_GLD/index.js index b51a182..2934748 100644 --- a/src/pages/Payment/Details_GLD/index.js +++ b/src/pages/Payment/Details_GLD/index.js @@ -35,6 +35,9 @@ const Index = () => { const params = useParams(); const navigate = useNavigate() + const [responeData, setResponeData] = React.useState({}); + const [transactionData, setTransactionData] = React.useState({}); + const [record, setRecord] = React.useState(); const [itemList, setItemList] = React.useState([]); const [onReady, setOnReady] = React.useState(false); @@ -47,8 +50,16 @@ const Index = () => { }, []); React.useEffect(() => { - setOnReady(true); - }, [record]); + if (Object.keys(responeData).length > 0) { + setTransactionData(responeData); + } + }, [responeData]); + + React.useEffect(() => { + if (Object.keys(transactionData).length > 0) { + setOnReady(true); + } + }, [transactionData]); // const handleResize = () => { // setDetailsOrder(window.innerWidth > 1023 ? 2 : -1); @@ -70,17 +81,40 @@ const Index = () => { const loadForm = () => { if (params.id > 0) { - HttpUtils.get({ url: UrlUtils.PAYMENT_LOAD + "/" + params.id, onSuccess: (responseData) => { if (!responseData.data?.id) { navigate("/paymentPage/search"); } - responseData.data["transDateStr"] = responseData.data.transDateTime; - responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss"); - setItemList(responseData.paymentItemList) - setRecord(responseData.data); + if (responseData.data.status == null || responseData.data.status == "INPR") { + HttpUtils.post({ + url: UrlUtils.PAYMENT_RETRY_STATUS_API, + params: { + "paymentId": params.id + }, + onSuccess: function (responseData2) { + responseData2.data["transDateStr"] = responseData2.data.transDateTime; + responseData2.data["transTimeStr"] = DateUtils.dateFormat(responseData2.data.transDateTime, "HH:mm:ss"); + setResponeData(responseData2.transactionData); + setItemList(responseData2.paymentItemList); + setRecord(responseData2.data); + }, + onError: function () { + responseData.data["transDateStr"] = responseData.data.transDateTime; + responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss"); + setResponeData(responseData); + setItemList(responseData.paymentItemList); + setRecord(responseData.data); + } + }); + } else { + responseData.data["transDateStr"] = responseData.data.transDateTime; + responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss"); + setResponeData(responseData); + setItemList(responseData.paymentItemList); + setRecord(responseData.data); + } } }); } @@ -125,6 +159,7 @@ const Index = () => { formData={record} doPrint={doPrint} onDownload={onDownload} + onRefresh={loadForm} style={{ display: "flex", height: "100%", diff --git a/src/pages/Payment/Search_GLD/DataGrid.js b/src/pages/Payment/Search_GLD/DataGrid.js index d24fed0..f1d9891 100644 --- a/src/pages/Payment/Search_GLD/DataGrid.js +++ b/src/pages/Payment/Search_GLD/DataGrid.js @@ -87,7 +87,7 @@ export default function SearchPaymentTable({ searchCriteria, applyGridOnReady, a }, { field: 'actions', - headerName: 'Transaction No.', + headerName: 'Payment No.', flex: 1, minWidth: 200, cellClassName: 'actions', @@ -95,6 +95,12 @@ export default function SearchPaymentTable({ searchCriteria, applyGridOnReady, a return clickableLink('/paymentPage/details/' + params.row.id, params.row.transNo); }, }, + { + field: 'egisRefNo', + headerName: 'Payment Reference No.', + flex: 1, + minWidth: 200, + }, { field: 'payMethod', headerName: 'Payment Method', @@ -107,7 +113,7 @@ export default function SearchPaymentTable({ searchCriteria, applyGridOnReady, a { id: 'transDateTime', field: 'transDateTime', - headerName: 'Transaction Date', + headerName: 'Payment Date', flex: 1, minWidth: 150, diff --git a/src/pages/Payment/Search_Public/DataGrid.js b/src/pages/Payment/Search_Public/DataGrid.js index 1e16572..c606e43 100644 --- a/src/pages/Payment/Search_Public/DataGrid.js +++ b/src/pages/Payment/Search_Public/DataGrid.js @@ -11,6 +11,7 @@ import { FiDataGrid } from "components/FiDataGrid"; import {useTheme} from "@emotion/react"; import {useIntl} from "react-intl"; import { clickableLink } from 'utils/CommonFunction'; +import { getPaymentMethodByCode } from "auth/utils"; import {PAYMENT_LIST} from "utils/ApiPathConst"; // ==============================|| EVENT TABLE ||============================== // @@ -58,6 +59,12 @@ export default function SearchPublicNoticeTable({ searchCriteria, applyGridOnRea return clickableLink('/paymentPage/details/' + params.row.id, params.row.transNo); }, }, + { + field: 'egisRefNo', + headerName: intl.formatMessage({id: 'paymentRefCode'}), + width: isMdOrLg ? 'auto' : 160, + flex: isMdOrLg ? 1 : undefined, + }, { id: 'appNos', field: 'appNos', @@ -69,6 +76,13 @@ export default function SearchPublicNoticeTable({ searchCriteria, applyGridOnRea return
    {appNo}
    }, }, + { + field: 'payMethod', + headerName: intl.formatMessage({id: 'paymentMethod'}), + width: isMdOrLg ? 'auto' : 160, + flex: isMdOrLg ? 1 : undefined, + renderCell: (params) => getPaymentMethodByCode(params?.value), + }, { id: 'transDateTime', field: 'transDateTime', diff --git a/src/pages/Setting/HkidKeyMigration/index.js b/src/pages/Setting/HkidKeyMigration/index.js new file mode 100644 index 0000000..15d091f --- /dev/null +++ b/src/pages/Setting/HkidKeyMigration/index.js @@ -0,0 +1,101 @@ +import * as React from "react"; +import * as HttpUtils from "utils/HttpUtils"; +import * as DateUtils from "utils/DateUtils"; +import * as UrlUtils from "utils/ApiPathConst"; + +import { + Grid, Typography, Button, + Stack, Box, CircularProgress, +} from '@mui/material'; +import { notifyActionError } from 'utils/CommonFunction'; + +import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' + +const formatLog = (responData) => { + if (responData?.msg && !responData?.log) { + return <>{DateUtils.datetimeStr(new Date())}
    Error
    {responData.msg}; + } + const statusColor = responData?.success ? "green" : "red"; + const statusText = responData?.success ? "Success" : "Completed with errors"; + const logText = (responData?.log || []).join("\n"); + return ( + <> + {DateUtils.datetimeStr(new Date())}
    + {responData?.dryRun ? "Dry-run " : ""}{statusText}
    + Total: {responData?.total ?? 0}, OK: {responData?.successCount ?? 0}, Skipped: {responData?.skipped ?? 0}, Failed: {responData?.failed ?? 0}
    + {logText} + + ); +}; + +const HkidKeyMigration = () => { + const [resultStr, setResultStr] = React.useState(""); + const [wait, setWait] = React.useState(false); + + const BackgroundHead = { + backgroundImage: `url(${titleBackgroundImg})`, + width: 'auto', + height: 'auto', + backgroundSize: 'contain', + backgroundRepeat: 'no-repeat', + backgroundColor: '#0C489E', + backgroundPosition: 'right' + }; + + const runMigration = (dryRun) => { + setWait(true); + HttpUtils.post({ + url: `${UrlUtils.HKID_REKEY_MIGRATION}?dryRun=${dryRun}&batchSize=100`, + params: {}, + onSuccess: function (responData) { + setWait(false); + setResultStr(formatLog(responData)); + }, + onError: function () { + setWait(false); + notifyActionError("HKID re-key migration failed"); + } + }); + }; + + return ( + + +
    + + + HKID Key Migration + + +
    +
    + + + + + Re-encrypt identification and checkDigit from the legacy key to the new key. + Ensure Tomcat has both security.hkid-secret and security.hkid-secret-legacy configured before running. + + + + + {wait ? : null} + + + + + + + Result: + {resultStr} + + +
    + ); +}; + +export default HkidKeyMigration; diff --git a/src/pages/Setting/UserPiiEncryption/index.js b/src/pages/Setting/UserPiiEncryption/index.js new file mode 100644 index 0000000..e1e17b9 --- /dev/null +++ b/src/pages/Setting/UserPiiEncryption/index.js @@ -0,0 +1,133 @@ +import * as React from "react"; +import * as HttpUtils from "utils/HttpUtils"; +import * as DateUtils from "utils/DateUtils"; +import * as UrlUtils from "utils/ApiPathConst"; + +import { + Grid, Typography, Button, + Stack, Box, CircularProgress, +} from '@mui/material'; +import { notifyActionError } from 'utils/CommonFunction'; + +import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' + +const formatEncryptLog = (responData) => { + if (responData?.msg && !responData?.log) { + return <>{DateUtils.datetimeStr(new Date())}
    Error
    {responData.msg}; + } + const statusColor = responData?.success ? "green" : "red"; + const statusText = responData?.success ? "Success" : "Completed with errors"; + const logText = (responData?.log || []).join("\n"); + return ( + <> + {DateUtils.datetimeStr(new Date())}
    + {responData?.dryRun ? "Dry-run " : ""}{statusText}
    + Total: {responData?.total ?? 0}, OK: {responData?.successCount ?? 0}, Skipped: {responData?.skipped ?? 0}, Failed: {responData?.failed ?? 0}
    + {logText} + + ); +}; + +const formatVerifyLog = (responData) => { + const tests = responData?.tests || []; + const logText = tests.map(t => `${t.passed ? "PASS" : "FAIL"} - ${t.name}: ${t.message}`).join("\n"); + const statusColor = responData?.success ? "green" : "red"; + return ( + <> + {DateUtils.datetimeStr(new Date())}
    + {responData?.success ? "All tests passed" : "Some tests failed"}
    + Passed: {responData?.passed ?? 0}, Failed: {responData?.failed ?? 0}
    + {logText} + + ); +}; + +const UserPiiEncryption = () => { + const [resultStr, setResultStr] = React.useState(""); + const [wait, setWait] = React.useState(false); + + const BackgroundHead = { + backgroundImage: `url(${titleBackgroundImg})`, + width: 'auto', + height: 'auto', + backgroundSize: 'contain', + backgroundRepeat: 'no-repeat', + backgroundColor: '#0C489E', + backgroundPosition: 'right' + }; + + const runEncrypt = (dryRun) => { + setWait(true); + HttpUtils.post({ + url: `${UrlUtils.USER_PII_ENCRYPT_MIGRATION}?dryRun=${dryRun}&batchSize=100`, + params: {}, + onSuccess: function (responData) { + setWait(false); + setResultStr(formatEncryptLog(responData)); + }, + onError: function () { + setWait(false); + notifyActionError("User PII encryption failed"); + } + }); + }; + + const runVerify = () => { + setWait(true); + HttpUtils.post({ + url: UrlUtils.USER_PII_VERIFY_MIGRATION, + params: {}, + onSuccess: function (responData) { + setWait(false); + setResultStr(formatVerifyLog(responData)); + }, + onError: function () { + setWait(false); + notifyActionError("User PII verification failed"); + } + }); + }; + + return ( + + +
    + + + User PII Encryption + + +
    +
    + + + + + Encrypt enName, chName, mobileNumber, and address for existing user records, then verify data retrieval. + + + + + + {wait ? : null} + + + + + + + Result: + {resultStr} + + +
    + ); +}; + +export default UserPiiEncryption; diff --git a/src/pages/User/DetailsPage_Individual/UserInformationCard_Individual.js b/src/pages/User/DetailsPage_Individual/UserInformationCard_Individual.js index 9512edd..0e4fbe8 100644 --- a/src/pages/User/DetailsPage_Individual/UserInformationCard_Individual.js +++ b/src/pages/User/DetailsPage_Individual/UserInformationCard_Individual.js @@ -81,7 +81,10 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => { addressLine3: yup.string().max(40, getMaxErrStr(40)).nullable(), emailAddress: yup.string().email(intl.formatMessage({ id: 'validEmailFormat' })).max(255).required(intl.formatMessage({ id: 'requireEmail' })), idDocType: yup.string().max(255, getMaxErrStr(255)).required(intl.formatMessage({ id: 'requireIdDocType' })), - identification: yup.string().required(getRequiredErrStr('number')) + identification: yup.string().when('verifiedBy', { + is: (verifiedBy) => verifiedBy != null, + then: (schema) => schema.notRequired(), + otherwise: (schema) => schema.required(getRequiredErrStr('number')) .matches(/^[aA-zZ0-9\s]+$/, { message: displayErrorMsg(`${selectedIdDocInputType}${intl.formatMessage({ id: 'noSpecialCharacter' })}`) }) .matches(/^\S*$/, { message: displayErrorMsg(`${selectedIdDocInputType}${intl.formatMessage({ id: 'noSpace' })}`) }) .test('checkIDCardFormat', displayErrorMsg(`${intl.formatMessage({ id: 'requiredValid' })}${selectedIdDocInputType}${intl.formatMessage({ id: 'number' })}`), function (value) { @@ -133,8 +136,12 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => { break; } } + }) }), - checkDigit: yup.string().max(1, getMaxErrStr(1)).nullable() + checkDigit: yup.string().when('verifiedBy', { + is: (verifiedBy) => verifiedBy != null, + then: (schema) => schema.notRequired(), + otherwise: (schema) => schema.max(1, getMaxErrStr(1)).nullable() .matches(/^[A-Z0-9\s]+$/, { message: displayErrorMsg(`${selectedIdDocInputType}${intl.formatMessage({ id: 'noSpecialCharacter' })}`) }) .test('checkIDCardFormat', displayErrorMsg(`${intl.formatMessage({ id: 'requiredNumberInQuote' })}`), function (value) { // console.log(selectedIdDocInputType) @@ -162,7 +169,8 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => { return false } } - }), + }) + }), tel_countryCode: yup.string().min(3, intl.formatMessage({ id: 'require3Number' })).required(intl.formatMessage({ id: 'requireDialingCode' })), fax_countryCode: yup.string().min(3, intl.formatMessage({ id: 'require3Number' })), phoneNumber: yup.string().min(8, intl.formatMessage({ id: 'require8Number' })).required(intl.formatMessage({ id: 'requireContactNumber' })), @@ -186,8 +194,10 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => { countryCode: values.tel_countryCode, phoneNumber: values.phoneNumber }, - identification: values.identification, - checkDigit: values.checkDigit, + ...(values.verifiedBy == null ? { + identification: values.identification, + checkDigit: values.checkDigit, + } : {}), faxNo: { countryCode: values.fax_countryCode, faxNumber: values.faxNumber @@ -471,6 +481,11 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => {
    + {currentUserData.verifiedBy ? + + Hidden for security purpose + + : {formik.values.idDocType === "HKID" ? editMode ? @@ -549,6 +564,7 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => { } + }
    diff --git a/src/pages/User/DetailsPage_Individual/UserInformationCard_Individual_Pub.js b/src/pages/User/DetailsPage_Individual/UserInformationCard_Individual_Pub.js index ca2b791..b350319 100644 --- a/src/pages/User/DetailsPage_Individual/UserInformationCard_Individual_Pub.js +++ b/src/pages/User/DetailsPage_Individual/UserInformationCard_Individual_Pub.js @@ -2,8 +2,6 @@ import { Grid, Button, Typography, FormHelperText, - Stack, - IconButton } from '@mui/material'; import MainCard from "components/MainCard"; import * as React from "react"; @@ -23,7 +21,6 @@ import { PRIMARY_CONTAINED_BUTTON_SX } from 'themes/colorConst'; import {FormattedMessage, useIntl} from "react-intl"; import {PNSPS_BUTTON_THEME} from "../../../themes/buttonConst"; import {ThemeProvider} from "@emotion/react"; -import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons'; // ==============================|| DASHBOARD - DEFAULT ||============================== // @@ -34,15 +31,6 @@ const UserInformationCard_Individual_Pub = ({ formData, loadDataFun }) => { const [editMode, setEditMode] = useState(false); const [onReady, setOnReady] = useState(false); const [errorMsg, setErrorMsg] = useState(""); - const [showId, setshowId] = useState(false); - - const handleClickShowId = () => { - setshowId(!showId); - }; - - const handleMouseDownId = (event) => { - event.preventDefault(); - }; useEffect(() => { if (Object.keys(formData).length > 0) { @@ -252,79 +240,9 @@ const UserInformationCard_Individual_Pub = ({ formData, loadDataFun }) => { - - {formik.values.idDocType === "HKID" ? - // <> - // - // {FieldUtils.initField({ - // valueName: "identification", - // disabled: true, - // form: formik, - // placeholder: intl.formatMessage({id: 'idDocNumber'}), - // inputProps: { - // maxLength: 7, - // onKeyDown: (e) => { - // if (e.key === 'Enter') { - // e.preventDefault(); - // } - // }, - // } - // })} - - // - // - // {FieldUtils.initField({ - // valueName: "checkDigit", - // disabled: true, - // form: formik, - // })} - // - // - - - {formik.values.identification?.slice(0, 4)} - - - {/* {showId ?formik.values.identification.slice(4):"****"}{showId ? '(' + formik.values.checkDigit + ')' :null} */} - {showId ? formik.values.identification?.slice(4) : "****"}{showId ? formik.values.checkDigit?'(' +formik.values.checkDigit+ ')': "()" : ""} - - - {showId ? : } - - - : - // - // {FieldUtils.initField({ - // valueName: "identification", - // disabled: true, - // form: formik - // })} - // - - - {formik.values.identification?.slice(0, 4)} - - - {showId ?formik.values.identification?.slice(4):"****"} - - - {showId ? : } - - - } - + + {formik.values.identification?.slice(0, 4)} + diff --git a/src/routes/GLDUserRoutes.js b/src/routes/GLDUserRoutes.js index a4a059c..3f893ef 100644 --- a/src/routes/GLDUserRoutes.js +++ b/src/routes/GLDUserRoutes.js @@ -30,6 +30,8 @@ const EmailTemplateDetailPage = Loadable(lazy(() => import('pages/EmailTemplate/ const HolidayPage = Loadable(lazy(() => import('pages/Holiday'))); const GazetteIssuePage = Loadable(lazy(() => import('pages/GazetteIssue/index'))); const DrImport = Loadable(lazy(() => import('pages/Setting/DrImport'))); +const HkidKeyMigration = Loadable(lazy(() => import('pages/Setting/HkidKeyMigration'))); +const UserPiiEncryption = Loadable(lazy(() => import('pages/Setting/UserPiiEncryption'))); const AuditLogPage = Loadable(lazy(() => import('pages/AuditLog/index'))); const ReconReportPage = Loadable(lazy(() => import('pages/Recon'))); const ChangePasswordPage = Loadable(lazy(() => import('pages/User/ChangePasswordPage'))); @@ -190,6 +192,18 @@ const GLDUserRoutes = { element: }:{}, + isGranted("MAINTAIN_SETTING")? + { + path: '/setting/hkidKeyMigration', + element: + }:{}, + + isGranted("MAINTAIN_SETTING")? + { + path: '/setting/userPiiEncryption', + element: + }:{}, + isGranted("MAINTAIN_SETTING")? { path: '/setting/auditLog', diff --git a/src/translations/en.json b/src/translations/en.json index a873714..2173830 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -421,7 +421,7 @@ "payTotal": "Total Payment Amount", "payDetail": "Payment Details", "payMethod": "Payment methods", - "epayMethod": " e-Payment Method", + "epayMethod": " Payment Method", "selectPaymentMethod": "Please select a payment method", "selectPaymentMethodBtn": "Select payment method", "payReceipt": "Payment Receipt", @@ -448,7 +448,7 @@ "paymentLimitPrice2":" is only applicable when minimum amount is HK$0.10 and maximum amount is HK$9,999,999.99", "paymentLimitPPS":" Payment could not be made via mobile device browsers, please use desktop computers to make payment.", "paymentMethod": "Payment Method", - "paymentProcessLimited":"Payment process must be completed within 30 minutes and return to this system.", + "paymentProcessLimited":"Please complete the payment process within 15 minutes. Note: For FPS payments, scanning, payment and all necessary approvals must be finished within 3 minutes due to security-related QR code expiry.", "publicNoticeDetailTitle": "Public Notice Application Information", "applyPerson": "Applicant", diff --git a/src/translations/zh-CN.json b/src/translations/zh-CN.json index 163fd83..a8aea4b 100644 --- a/src/translations/zh-CN.json +++ b/src/translations/zh-CN.json @@ -454,7 +454,7 @@ "payTotal": "付款总额", "payDetail": "付款详情", "payMethod": "付款方式", - "epayMethod": "电子付款方法", + "epayMethod": "付款方法", "selectPaymentMethod": "请选择付款方法", "selectPaymentMethodBtn": "选择付款方法", "payReceipt": "付款收据", @@ -482,7 +482,7 @@ "paymentLimitPrice2":"只适用于最小金额为 0.10 港元及最高金额为 9,999,999.99港元", "paymentLimitPPS":"付款不适用于流动装置的浏览器,请使用桌面电脑。", "paymentMethod": "付款方式", - "paymentProcessLimited":"付款过程必须在 30 分钟内完成及返回本系统。", + "paymentProcessLimited":"请于15分钟内完成付款程序。 注意:使用转数快(FPS)时,因二维码具安全时效限制,须于3分钟内完成扫码、付款及所有相关审核程序。", "publicNoticeDetailTitle": "公共启事申请资料", "applyPerson": "申请人", diff --git a/src/translations/zh-HK.json b/src/translations/zh-HK.json index c8cbe54..9124f64 100644 --- a/src/translations/zh-HK.json +++ b/src/translations/zh-HK.json @@ -455,7 +455,7 @@ "payTotal": "付款總額", "payDetail": "付款詳情", "payMethod": "付款方式", - "epayMethod": "電子付款方法", + "epayMethod": "付款方法", "selectPaymentMethod": "請選擇付款方法", "selectPaymentMethodBtn": "選擇付款方法", "payReceipt": "付款收據", @@ -483,7 +483,7 @@ "paymentLimitPrice2":"只適用於最小金額為 0.10 港元及最高金額為 9,999,999.99港元", "paymentLimitPPS":"付款不適用於流動裝置的瀏覽器,請使用桌面電腦。", "paymentMethod": "付款方法", - "paymentProcessLimited":"付款程序必須在 30 分鐘內完成及返回本系统。", + "paymentProcessLimited":"請於15分鐘內完成付款程序。 注意:使用轉數快(FPS)時,因二維碼具安全時效限制,須於3分鐘內完成掃碼、付款及所有相關審核程序。", "publicNoticeDetailTitle": "公共啟事申請資料", "applyPerson": "申請人", diff --git a/src/utils/ApiPathConst.js b/src/utils/ApiPathConst.js index 38daac3..161dff9 100644 --- a/src/utils/ApiPathConst.js +++ b/src/utils/ApiPathConst.js @@ -84,6 +84,9 @@ export const GET_FILE_DELETE = apiPath+'/file/delete'; export const DR_EXPORT = apiPath+'/settings/dr/export'; export const DR_IMPORT = apiPath+'/settings/dr/import'; export const OFFLINE_IMPORT = apiPath+'/settings/dr/importOffline'; +export const HKID_REKEY_MIGRATION = apiPath+'/settings/migration/hkid-rekey'; +export const USER_PII_ENCRYPT_MIGRATION = apiPath+'/settings/migration/user-pii-encrypt'; +export const USER_PII_VERIFY_MIGRATION = apiPath+'/settings/migration/user-pii-verify'; export const AUDIT_LOG_EXPORT = apiPath+'/settings/auditLog-export'; @@ -180,6 +183,7 @@ export const PAYMENT_LOAD = apiPath+'/payment/load';//GET export const PAYMENT_APP_LIST = apiPath+'/payment/applist';//POST export const PAYMENT_CHECK = apiPath+'/payment/check-payment';//GET export const PAYMENT_BIB = apiPath+'/payment/set-bib';//POST +export const PAYMENT_MARK_AS_PAID = apiPath+'/payment/mark-as-paid';//POST export const PAYMENT_GFMIS_LIST = apiPath+'/payment/listGFMIS';//GET export const PAYMENT_LIMIT_SETTING_LIST = apiPath+'/settings/payment';//GET