場景描述:在與前端對接口,該請求須要調用別的渠道的業務,流程以下html
一、前端頁面->Controller->調用健康險頁面->Controller->前端頁面前端
該請求經過get請求進行傳參數,請求樣例web
https://test1-life.pingan.com/health/healthNotify?failBackUrl=https://test1-life.pingan.com/ilifecore/productMall/loading.html?productId=8000000241&channelCode=XCX00001&productCode=00001&actionType=underwrite&actionResult=2&successBackUrl=https://test1-life.pingan.com/ilifecore/productMall/loading.html?channelCode=XCX00001&productCode=00001&productId=8000000241&actionType=underwrite&actionResult=1&outChannelOrderId=30180000000001226447&productId=8000000241&platformSerialNo=20180820092030575
瀏覽器
前端進行encodeURIComponent 進行編碼:服務器
https://test1-life.pingan.com/health/healthNotify?failBackUrl=https%3A%2F%2Ftest1-life.pingan.com%2Filifecore%2FproductMall%2Floading.html%3FproductId%3D8000000241%26channelCode%3DXCX00001%26productCode%3D00001%26actionType%3Dunderwrite%26actionResult%3D2&successBackUrl=https%3A%2F%2Ftest1-life.pingan.com%2Filifecore%2FproductMall%2Floading.html%3FchannelCode%3DXCX00001%26productCode%3D00001%26productId%3D8000000241%26actionType%3Dunderwrite%26actionResult%3D1&outChannelOrderId=30180000000001226447&productId=8000000241&platformSerialNo=20180820092030575app
轉碼發送到後臺,後臺web服務器自己對其進行解碼,Controller對參數進行處理ide
@RequestMapping("/health/healthNotify") public void toHealthNotify(final HttpServletRequest request, final HttpServletResponse response) throws Exception { log.info("HealthNotifyController---------toHealthNotify---------start"); String productId = LifeUtil.fixHttpRSAndTrim(request.getParameter("productId")); String failBackUrl = LifeUtil.fixHttpRSAndTrim(request.getParameter("failBackUrl")); String successBackUrl = LifeUtil.fixHttpRSAndTrim(request.getParameter("successBackUrl")); String outChannelOrderId = LifeUtil.fixHttpRSAndTrim(request.getParameter("outChannelOrderId")); String platformSerialNo = LifeUtil.fixHttpRSAndTrim(request.getParameter("platformSerialNo")); log.info("HealthNotifyController---sent------"+failBackUrl); log.info("轉碼後的"+URLEncoder.encode(failBackUrl,"UTF-8")); //入參校驗(platformSerialNo) if (LifeUtil.isNull(platformSerialNo)) throw new OuterMessageException(ExReturnMeg.EUD0019); //查詢平臺來源信息 ServiceRequest serviceRequest = new ServiceRequest(); serviceRequest.setParameter("thId", outChannelOrderId); serviceRequest.setParameter("platformSerialNo", platformSerialNo); serviceRequest.setRequestedServiceID("queryRelationInfoAction"); ServiceResponse serviceResponse = new ServiceResponse(); serviceResponse = ACDispatcher.dispatchService(serviceRequest, "pafaAC"); Map model = serviceResponse.getModel(); String productID = (String) model.get("productId"); // 校驗(productId) if(!productId.equals(productID)) throw new OuterMessageException(ExReturnMeg.EUD0020); /** 注意:下面的這些參數請根據實際狀況參考收銀臺接口文檔替換 **/ Map<String, String> params = new TreeMap<String, String>(); params.put("outChannelOrderId", outChannelOrderId); params.put("channelId", channelId); params.put("productId", getHealthProductId(productId)); params.put("successBackUrl", URLEncoder.encode(request.getScheme()+"://"+request.getServerName()+"/health/backUrl?result=1&callBack="(URLEncoder.encode(successBackUrl,"UTF-8"), "UTF-8")); params.put("failBackUrl", URLEncoder.encode(request.getScheme()+"://"+request.getServerName()+"/health/backUrl?result=0&callBack="+ URLEncoder.encode(failBackUrl,"UTF-8"),"UTF-8")); params.put("signMethod", signMethod); params.put("signature", encryptRequest(createLinkString(params), cyberarkV9Service.getPassword("ilife.health.signKey"))); log.info("HealthNotifyController----" + aitestURL + "?" + createLinkString(params)); //跳轉至智能健告接口 response.sendRedirect(aitestURL + "?" + createLinkString(params)); }
關鍵的地方來了 ,但咱們組裝好參數,發送到健康險 ,健康險頁面處理後,會經過health/backUrl 的Controller 把successBackUrl和failBackUrl返回回來,而後咱們經過successBackUrl和failBackUrl 調用前端的接口 。編碼
public void healthNotityCallBack(final HttpServletRequest request, final HttpServletResponse response) throws Exception{ log .info("HealthNotifyController---------callBack---------start"); String outChannelOrderId = LifeUtil.fixHttpRSAndTrim(request.getParameter("outChannelOrderId")); String uwMedicalId = LifeUtil.fixHttpRSAndTrim(request.getParameter("uwMedicalId")); String undwrtDecideType = LifeUtil.fixHttpRSAndTrim(request.getParameter("undwrtDecideType")); String exclusiveAgreement = LifeUtil.fixHttpRSAndTrim(request.getParameter("exclusiveAgreement")); String signature = LifeUtil.fixHttpRSAndTrim(request.getParameter("signature")); String signMethod = LifeUtil.fixHttpRSAndTrim(request.getParameter("signMethod")); String callBack = LifeUtil.fixHttpRSAndTrim(request.getParameter("callBack")); log.info("HealthNotifyController---cb----"+callBack); //根據thId獲取保單信息 ServiceRequest serviceRequest1 = new ServiceRequest(); serviceRequest1.setParameter("thId", outChannelOrderId); serviceRequest1.setRequestedServiceID("findAppPolicyByThIdAction"); ServiceResponse response1 = new ServiceResponse(); response1 = ACDispatcher.dispatchService(serviceRequest1, "pafaAC"); @SuppressWarnings("rawtypes") Map model = response1.getModel(); AppPolicyDTO appPolicyDTO = (AppPolicyDTO) model.get("appPolicyDTO"); //保單 if(appPolicyDTO==null) throw new OuterMessageException(ExReturnMeg.EUD0000); appPolicyDTO.setResultID(uwMedicalId); appPolicyDTO.setUdwDecide(undwrtDecideType); //更新th表 ServiceRequest serviceRequest2 = new ServiceRequest(); serviceRequest2.setCurrentRequestObject(appPolicyDTO); serviceRequest2.setRequestedServiceID("updateAppPolicyAction"); ServiceResponse response2 = new ServiceResponse(); response2 = ACDispatcher.dispatchService(serviceRequest2, "pafaAC"); Map<String, String> params = new TreeMap<String, String>(); params.put("outChannelOrderId", outChannelOrderId ); params.put("uwMedicalId", uwMedicalId ); params.put("undwrtDecideType", undwrtDecideType ); params.put("exclusiveAgreement", exclusiveAgreement ); params.put("signature", signature ); params.put("signMethod", signMethod ); log .info("HealthNotifyController----" + callBack + "?" + createLinkString(params)); //跳轉至小雨傘結果界面 if(callBack.contains("?")){ response.sendRedirect(callBack+"&"+createLinkString(params)); }else{ response.sendRedirect(callBack+"?"+createLinkString(params)); } }
當咱們 拿出回調的successBackUrl和failBackUrl的結果的時候,以下:url
/wls/applogs/rtlog/ilife-core-stg1DMZ35021/ilife-core-stg1DMZ35021.out:2018-08-20 14:46:00.774 [INFO ] [HealthNotifyController] [215.128.194.20] {T=J0MLM5Kiv3x1ZSaB} HealthNotifyController---cb----https://test1-life.pingan.com/ilifecore/productMall/loading.html?channelCode=XCX00001
successBackUrl和failBackUrl 只是渠道的第一個參數,其餘的參數都被kill掉了。spa
通過分析終於找到緣由
在咱們進行調用健康險的智能覈保的過程當中,健康險出了web服務器會進行一次解碼的過程,本省的程序應該也會改url進行一次解碼,這樣就通過了兩次解碼
而咱們也是進行兩個編碼
params.put("failBackUrl", URLEncoder.encode(request.getScheme()+"://"+request.getServerName()+"/health/backUrl?result=0&callBack="+URLEncoder.encode(failBackUrl,"UTF-8"),"UTF-8"));
通過兩次編碼後的報文是這樣的
https%3a%2f%2ftest1-life.pingan.com%2fhealth%2fhealthNotify%3ffailBackUrl%253dhttps%253a%252f%252ftest1-life.pingan.com%252filifecore%252fproductMall%252floading.html%253fproductId%253d8000000241 %2526channelCode%253dXCX00001%2526productCode%253d00001%2526actionType%253dunderwrite%2526actionResult%253d2
而在智能覈保系統通過兩次解碼的結果
https://test1-life.pingan.com/health/backUrl?failBackUrl=https://test1-life.pingan.com/ilifecore/productMall/loading.html?productId=8000000241&channelCode=XCX00001&productCode=00001&actionType=underwrite&actionResult=2
在按照如何的結果返回給咱們系統的時候 ,咱們在去 failBackUrl 的值的時候 https://test1-life.pingan.com/ilifecore/productMall/loading.html?productId=8000000241
致使返回給前端的內容一致不正確,仍是對瀏覽器的機制不夠熟練,但願小夥伴引覺得戒