提高网站权重的方法,广州市网站建设报价,网络专业毕业设计,网站优化解决方案第三方支付平台支付接口及回调接口开发 作为开放式的 B/S 架构程序#xff0c;无论所属电商#xff0c;金融#xff0c;机械制造#xff0c;企业 OA #xff0c; ERP #xff0c; CRM #xff0c; CMS 等等行业或系统中#xff0c;第三方支付以及银联支付的业务一定是客… 第三方支付平台支付接口及回调接口开发 作为开放式的 B/S 架构程序无论所属电商金融机械制造企业 OA ERP CRM CMS 等等行业或系统中第三方支付以及银联支付的业务一定是客户关心所在也是保证客户系统盈利运营的一个重要保障。通常这种 B2C 或者 C2C 系统的开发商户用户所关注的支付平台大多离不开 “ 阿里支付宝快钱腾讯财付通易宝支付这种第三方支付平台以及中国银联 UnionPay....等等” 这些方式。 最近某项目中涉及到支付的模块与涉及流程在此和大家分享一下。 1名词释义 商户网站比如淘宝聚美唯品会这种B2C/C2C的网站及后台的管理系统统称为商户网站主要负责对买家订单数据的封装加密 及支付平台回调的订单处理。 支付平台我们需要开发的支付平台支付接口支付模拟的Servlet暴露出来的WebService接口url等主要负责对买家请求来的 加密后的订单数据进行解密构造请求的URL拼接参数对Sign进行加密对支付机构异步或同步请求回调的数据 进行封装解密回传给商户网站。 支付机构比如阿里支付宝快钱腾讯财付通易宝支付这种第三方支付平台等支付机构。 Sign支付机构为商户分配的一把“密钥”与”合作者ID“同时分配用做调用Base64MD5等加密算法在加密解密时的一种私钥通常 与此相关联的还有signType就是加密方式。 回调对上次请求端request中的url或指定的url进行http请求或https请求 支付平台请求响应及回调流程图 2业务流设计(本文只介绍alipay的即时到账接口create_direct_pay_by_user) 2.1 商户网站对数据封装加密调用支付接口 2.1.1商户网站后台对买家的订单进行封装插入商户网站db中的订单表比如xxx_order PayReturnVovo new PayReturnVo(); vo.setOrderId(kuaiqian00232); vo.setOrderAmount(20); vo.setOrderTime(20140504121020); vo.setProductName(3M网线送水晶头); vo.setProductId(2213229319378); vo.setProductNum(2); vo.setPayType(00);*/ // 把模拟的表单数据转成Json StringorderJson PaymentJsonUtil.beanToJson(vo); // 通过db获取商家key密钥 Stringkey dao.getKeyByUserId(userId); // 根据key使用base64加密算法对订单信息进行加密 StringSignedJson CryptUtil.encryptBase64Des(orderJson, key); 2.1.2于此同时调用dao层查询买家用户平台账户余额并进行锁表在SQL的select后加入 forupdate wait n(最好 为1-5秒此处的 数值为httpclient请求超时时长)为防止订单被多用户修改。 2.2 支付平台响应请求及解密调用支付机构接口 2.2.1支付平台响应请求对数据进行解密 //获取输入参数 InputStreamis request.getInputStream(); //把接收的加密流转成String类型 StringpayMsgJson IOUtils.toString(is, utf-8); //base64进行解密 byte[]byteJson CryptUtil.decryptBASE64payMsgJson StringstrJson new String(byteJson,UTF-8); //把解密后的json转换成实体vo try{ pVo (BankPayVo)PaymentJsonUtil.jsonToBean(strJson,BankPayVo.class); }catch (Exception e) { e.printStackTrace(); throw(e) } 2.2.2从db查询商户协议信息构造不同方式的支付机构所需请求的url publicString CreateUrl(PayBankEntity payBankEntity) throws BankpayException,SQLException{ StringwebPartentId payBankEntity.getWebPartentId(); //通过DB获取阿里支付Config信息 AliPayAccountDaoImplaccount new AliPayAccountDaoImpl(); AliPayAccountVoaccVo account.getAccountInfo(webPartentId); //根据订单号区别b2a和b2c对partner参数设置 StringstrOrderNo payBankEntity.getOrderNo(); //阿里支付合作伙伴ID Stringpartner accVo.getPaPartner(); //阿里支付key Stringkey accVo.getPaKey(); //阿里支付接口 Stringpaygateway accVo.getPaPayGateWay(); //阿里支付服务名 Stringservice accVo.getPaService(); //阿里支付签名Sign加密方式 Stringsign_type accVo.getPaSignType(); //卖家账号邮箱 Stringseller_email accVo.getPaSellerEmail(); //###### Form Web ###### 商户网站订单 Stringout_trade_no payBankEntity.getOrderNo(); //###### Form Web ###### 交易总额 Stringtotal_fee payBankEntity.getMoney(); //###### Form Web ###### 商品名称 String subject payBankEntity.getProductId(); //###### Form Web ###### 商品展示地址 StringinputCharset accVo.getPaInputCharset(); //###### Form Web ###### 支付类型 Stringpayment_type payBankEntity.getPaymentType(); //超时时长 Stringit_b_pay accVo.getPaItBBay(); //!!! 在此修改参数为异步notify_url但是vo和db中显示为return_url Stringreturn_url accVo.getPaReturnUrl(); StringItemUrl; 2.2.2.temp PS: 下行代码的CreateUrl()是根据请求参数首字母降序排列把参数重新构造成新的url。 ItemUrl Payment.CreateUrl(paygateway,service,sign_type,inputCharset,payment_type, partner,key,out_trade_no,total_fee,return_url,seller_email,subject,it_b_pay); System.out.println(异步通知返回agbpay地址 return_url); returnItemUrl; } 2.2.3StringBuffer绘制跳转请求的html dom元素把参数请求到支付机构 publicString getBankHtml(PayBankEntity payBankEntity) throws BankpayException { StringBuffer sbHtml new StringBuffer(); try { sbHtml.append(); sbHtml.append( 支付网关 ); sbHtml.append( sbHtml.append( ); }catch (Exception e) { throw new BankpayException(系统异常错误描述 e.getMessage()); } return sbHtml.toString(); } 2.2.4切记不要忘记设置支付机构回调支付平台的回调url大多数支付机构的参数为同步和异步两种设置支付机构的 回调url目的在于它进行了我们的请求。处理之后对订单数据及订单等状态的回写进而支付平台可以封装 加密成json串继续调用商户网站对这次支付的信息进行更改执行具体业务。 下面是阿里的api同步和异步回调路径不能同时为空。 notify_url 服务器异步通知页面路径 String(160) 支付宝服务器主动通知商户网站里指定的页面Http路径 可空 returl_url 服务器同步通知页面路径 String(160) 支付宝完成处理后当前页面自动跳转到商户网站的Http路径 可空 下面是快钱的api同步和异步回调路径不能同时为空。 pageUrl 接受支付结果的页面地址 String(256) 需要是绝对地址与bgUrl不能同时为空当bgUrl为空时生效 可空 bgUrl 接受支付结果后台代码地址 String(256) 需要是绝对地址与pageUrl不能同时为空当pageUrl为空时生效 可空 2.3 支付平台响应支付机构回调被支付机构接收的订单支付成功或失败之后回调我们支付平台的接口。 1把支付宝的请求输入流转成我们需要的vo对象调用2中的performTask()。 //获取输入参数 InputStreamis request.getInputStream(); //转成String类型 String payMsgJson IOUtils.toString(is, utf-8); PayReturnVovos PaymentJsonUtil.jsonToBean(payMsgJson, PayReturnVo.class); request.setAttribute(returnStr,vos); newAliPayReturnBo().performTask(request, response); 2把支付宝的请求输入流转成我们需要的vo对象调用2中的performTask()。 SuppressWarnings(unused) publicstatic String performTask(HttpServletRequest request, HttpServletResponseresponse) throws IOException, ServletException { StringreturnStr ; StringwebPartentId ; try{ Stringsign request.getParameter(sign); //支付状态:TRADE_FINISHED(普通即时到账的交易成功状态)||TRADE_SUCCESS(开通 了高级即时到账或机票分销产品后的交易成功状态) StringtradeStatus request.getParameter(trade_status); //订单编号 StringorderNo request.getParameter(out_trade_no); //通知類型 Stringnotify_type request.getParameter(notify_type); //支付宝交易流水号 Stringtrade_no ; //订单总价 Stringamount request.getParameter(total_fee); if(request.getParameter(trade_no) ! null) { trade_no request.getParameter(trade_no); } StringalipayNotifyURL http://notify.alipay.com/trade/notify_query.do? partner partner ¬ify_id request.getParameter(notify_id); //获取支付宝ATN返回结果true是正确的订单信息false 是无效的 //StringresponseTxt CheckURL.check(alipayNotifyURL); Mapparams new HashMap(); //获得POST 过来参数设置到新的params中 for(Iterator iter requestParams.keySet().iterator(); iter .hasNext();){ Stringname (String) iter.next(); String[]values (String[]) requestParams.get(name); StringvalueStr ; for(int i 0; i values.length; i) { valueStr (i values.length - 1) ? valueStr values[i] :valueStr values[i] ,; } params.put(name,valueStr); } //2、校验支付结果 StringpayStatus 1; Stringmysign com.alipay.util.SignatureHelper.sign(params,privateKey); //验证 booleanverifySuccess mysign.equalsIgnoreCase(sign); //获取支付交易状态 booleantradeFinished tradeStatus .equalsIgnoreCase(TRADE_SUCCESS) ||tradeStatus.equalsIgnoreCase(TRADE_FINISHED); if(verifySuccess tradeFinished) { //TODO 调用agbweb接口告知支付结果 PayReturnVovos (PayReturnVo) request.getAttribute(returnStr); StringwebPartengId vos.getWebPartentId(); //通过DB获取阿里支付Config信息 AliPayAccountDaoImplaccount new AliPayAccountDaoImpl(); AliPayAccountVoaccVo account.getAccountInfo(webPartengId); Stringkey accVo.getWebKey(); vos.setOutTradeNo(vos.getBillNo()); vos.setTotal_free(vos.getTotal_free()); vos.setPrivate_key(key); StringnotifyType vos.getNotifyType(); StringpayStatuss vos.getPay_status(); // 支付银行 if(notifyType.equals(trade_status_sync)) { vos.setBankName(ALIPAY); }else vos.setBankName(QUICKMONEY); // 支付结果 if(payStatuss.equals(TEADE_SUCCESS)|| payStatuss.equals(TEADE_FINISHED)){ // 阿里-支付成功 vos.setTradeFlag(ALIPAY_T); } returnStr PaymentJsonUtil.beanToJson(vos); // 原封Jsonkey StringreturnStrWithKey key returnStr; // MD5加密 StringbyteMD5 MD5Util.MD5Encode(returnStrWithKey); returnMsg(request,response, returnStr , byteMD5); }else if (!verifySuccess) { // AliPay返回的结果信息认证没有通过 //}else if (false) { // AliPay返回的结果信息认证没有通过 thrownew BankpayException(Alipay支付返回失败); }else { // AliPay返回没有TRADE_FINISHED thrownew BankpayException(Alipay支付返回失败); } }catch (Exception e) { e.printStackTrace(); } return returnStr; } 3回调商户网站的接口告知支付状态以及回调的订单信息。 publicstatic void returnMsg(HttpServletRequest request, HttpServletResponseresponse, String strMsg , String strMD5) try{ URLurl new URL( http://10.1.126.10:8080/agb/payResponse.servlet?str strMsg strMD5 strMD5); HttpURLConnectionhttp (HttpURLConnection) url.openConnection(); http.setRequestMethod(POST); http.setDoOutput(true); http.setDoInput(true); System.setProperty(sun.net.client.defaultConnectTimeout,30000);// 连接超时30秒 System.setProperty(sun.net.client.defaultReadTimeout,30000); // 读取超时30秒 http.connect(); //TODO 把数据回写到agbweb OutputStreamos http.getOutputStream(); //os.write(strMsg.getBytes(UTF-8));//传入参数 os.flush(); os.close(); InputStreamis http.getInputStream(); }catch (IOException e) { e.printStackTrace(); throw(e); } } 4被支付机构接收的订单有可能存在回调失败等情况虽然这种情况是百万分之一的机会但为了防止交易过程没有 进行回调也可以通过Spring的定时任务注解Scheduled注解进行“对账接口”的定时对账在此不进行详细 介绍接口名为“Sign_trade_query”。 2.4 商户网站响应支付平台回调 1流获取转换String UTF-8 2解密Json转化为Vo 3执行某个Service/Bo 4更新DB订单表等 5回写页面告知用户支付结果。 本篇日志仅大致描述了支付宝交易的一次请求流程 1商户网站订单加密 2订单解密支付平台构造url 3阿里接口 4封装订单vo -- 支付平台 -- 订单加密模拟请求 5商户网站db操作订单的操作流程。 其中包括其中的4次加密以及2次回调和两次模拟的http请求。其他第三方或银联支付平台与此结构大致一样只是API中的参数或构造URL的方式加密算法有个别差异。 以上。