4.alipay 页面跳转同步通知处理数据库
4.1 页面跳转同步通知安全
当买家完成了支付流程后,会出现成功支付的页面,该页面作短暂停留后,会跳转到咱们AlipayConfig.xml中的 return_url 属性所指定的页面,这称为页面跳转同步通知。服务器
咱们须要在该页面请求中,作相应的商业逻辑处理,如判断并更改订单状态,增长数据库中表示money的字段,注意:判断状态是十分必要的,避免重复进行操做。异步
4.2 returnURLjsp
1 /** 2 * 功能:付完款后跳转的页面(页面跳转同步通知页面) 3 * WAIT_SELLER_SEND_GOODS(表示买家已在支付宝交易管理中产生了交易记录且付款成功,但卖家没有发货); 4 * TRADE_FINISHED(表示买家已经确认收货,这笔交易完成); 5 * 6 * @return 7 */ 8 public String returnURL() { 9 String key = AlipayConfig.key; 10 // 获取支付宝GET过来反馈信息 11 Map params = new HashMap(); 12 13 // MyServletContext 为自定义的类,可无视,换成以下写法: 14 // HttpServletRequet request = ServletActionContext.getRequest(); 15 HttpServletRequest request = MyServletContext.getRequest(); 16 17 Map requestParams = request.getParameterMap(); 18 for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) { 19 String name = (String) iter.next(); 20 String[] values = (String[]) requestParams.get(name); 21 String valueStr = ""; 22 for (int i = 0; i < values.length; i++) { 23 valueStr = (i == values.length - 1) ? valueStr + values[i] 24 : valueStr + values[i] + ","; 25 } 26 // 乱码解决,这段代码在出现乱码时使用。若是mysign和sign不相等也能够使用这段代码转化 27 try { 28 valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8"); 29 } catch (UnsupportedEncodingException e) { 30 e.printStackTrace(); 31 } 32 params.put(name, valueStr); 33 } 34 35 // 判断responsetTxt是否为ture,生成的签名结果mysign与得到的签名结果sign是否一致 36 // responsetTxt的结果不是true,与服务器设置问题、合做身份者ID、notify_id一分钟失效有关 37 // mysign与sign不等,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关 38 String mysign = AlipayNotify.GetMysign(params, key); 39 String responseTxt = AlipayNotify.Verify(request 40 .getParameter("notify_id")); 41 String sign = request.getParameter("sign"); 42 43 // 写日志记录(若要调试,请取消下面两行注释) 44 // String sWord = "responseTxt=" + responseTxt + 45 // "\n return_url_log:sign=" + sign + "&mysign=" + mysign + 46 // "\n return回来的参数:" + AlipayFunction.CreateLinkString(params); 47 // AlipayFunction.LogResult(sWord); 48 49 // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(如下仅供参考)// 50 String trade_no = request.getParameter("trade_no"); // 支付宝交易号 51 String order_no = request.getParameter("out_trade_no"); // 获取订单号 52 String total_fee = request.getParameter("price"); // 获取总金额 53 String subject = ""; 54 try { 55 subject = new String(request.getParameter("subject").getBytes( 56 "ISO-8859-1"), "UTF-8"); 57 } catch (UnsupportedEncodingException e1) { 58 // TODO Auto-generated catch block 59 e1.printStackTrace(); 60 }// 商品名称、订单名称 61 62 String body = ""; 63 if (request.getParameter("body") != null) { 64 try { 65 body = new String(request.getParameter("body").getBytes( 66 "ISO-8859-1"), "UTF-8"); 67 } catch (UnsupportedEncodingException e) { 68 e.printStackTrace(); 69 }// 商品描述、订单备注、描述 70 } 71 String buyer_email = request.getParameter("buyer_email"); // 买家支付宝帐号 72 String receive_name = "";// 收货人姓名 73 if (request.getParameter("receive_name") != null) { 74 try { 75 receive_name = new String(request.getParameter("receive_name") 76 .getBytes("ISO-8859-1"), "UTF-8"); 77 } catch (UnsupportedEncodingException e) { 78 e.printStackTrace(); 79 } 80 } 81 String receive_address = "";// 收货人地址 82 if (request.getParameter("receive_address") != null) { 83 try { 84 receive_address = new String(request.getParameter( 85 "receive_address").getBytes("ISO-8859-1"), "UTF-8"); 86 } catch (UnsupportedEncodingException e) { 87 e.printStackTrace(); 88 } 89 } 90 String receive_zip = "";// 收货人邮编 91 if (request.getParameter("receive_zip") != null) { 92 try { 93 receive_zip = new String(request.getParameter("receive_zip") 94 .getBytes("ISO-8859-1"), "UTF-8"); 95 } catch (UnsupportedEncodingException e) { 96 e.printStackTrace(); 97 } 98 } 99 String receive_phone = "";// 收货人电话 100 if (request.getParameter("receive_phone") != null) { 101 try { 102 receive_phone = new String(request 103 .getParameter("receive_phone").getBytes("ISO-8859-1"), 104 "UTF-8"); 105 } catch (UnsupportedEncodingException e) { 106 // TODO Auto-generated catch block 107 e.printStackTrace(); 108 } 109 } 110 String receive_mobile = "";// 收货人手机 111 if (request.getParameter("receive_mobile") != null) { 112 try { 113 receive_mobile = new String(request.getParameter( 114 "receive_mobile").getBytes("ISO-8859-1"), "UTF-8"); 115 } catch (UnsupportedEncodingException e) { 116 e.printStackTrace(); 117 } 118 } 119 String trade_status = request.getParameter("trade_status"); // 交易状态 120 // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)// 121 122 String verifyStatus = ""; 123 if (mysign.equals(sign) && responseTxt.equals("true")) { 124 // //////////////////////////////////////////////////////////////////////////////////////// 125 // 请在这里加上商户的业务逻辑程序代码 126 127 // ——请根据您的业务逻辑来编写程序(如下代码仅做参考)—— 128 if (trade_status.equals("WAIT_SELLER_SEND_GOODS")) { 129 // 判断该笔订单是否在商户网站中已经作过处理(可参考“集成教程”中“3.4返回数据处理”) 130 // 若是没有作过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 131 // 若是有作过处理,不执行商户的业务程序 132 133 // if ("WAIT_BUYER_PAY".equals(memberMoney.getRemark()) 134 // && mMoney == Double.parseDouble(total_fee)) { 135 // memberMoney.setRemark("WAIT_BUYER_CONFIRM_GOODS"); 136 // memberMoneyService.saveOrUpdate(memberMoney); 137 // Members member = memberService.get(mid); 138 // if(member.getIdealMoney()==null){ // 这里是前人的数据库设置不合理,没给金钱这字段默认值,故判断其是否为空 139 // member.setIdealMoney(mMoney); 140 // }else{ 141 // member.setIdealMoney(member.getIdealMoney() + mMoney); 142 // } 143 // memberService.saveOrUpdate(member); // 若是订单状态为默认状态,则添加金钱 144 // } 145 // try { 146 // // 这里是发货信息同步 147 // String xmlResult = AlipayService.PostXml( 148 // AlipayConfig.partner, trade_no, "直接充值", 149 // "请到我的中心-个人钱包查看充值货币", "EXPRESS", "", 150 // AlipayConfig.input_charset, AlipayConfig.key, 151 // AlipayConfig.sign_type); 152 // } catch (Exception e) { 153 // e.printStackTrace(); 154 // } 155 156 } 157 158 // ——请根据您的业务逻辑来编写程序(如下代码仅做参考)—— 159 if (trade_status.equals("TRADE_FINISHED")) { 160 // 判断该笔订单是否在商户网站中已经作过处理(可参考“集成教程”中“3.4返回数据处理”) 161 // 若是没有作过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 162 // 若是有作过处理,不执行商户的业务程序 163 164 // if ("WAIT_BUYER_PAY".equals(memberMoney.getRemark()) 165 // && mMoney == Double.parseDouble(total_fee)) { 166 // memberMoney.setRemark("TRADE_FINISHED"); 167 // memberMoneyService.saveOrUpdate(memberMoney); 168 // Members member = memberService.get(mid); 169 // if(member.getIdealMoney()==null){ 170 // member.setIdealMoney(mMoney); 171 // }else{ 172 // member.setIdealMoney(member.getIdealMoney() + mMoney); 173 // } 174 // memberService.saveOrUpdate(member); // 若是订单状态为默认状态,则添加金钱 175 // 176 // try { 177 // // 这里是发货信息同步 178 179 // String xmlResult = AlipayService.PostXml( 180 // AlipayConfig.partner, trade_no, "直接充值", 181 // "我的中心请查看充值货币", "EXPRESS", "", 182 // AlipayConfig.input_charset, AlipayConfig.key, 183 // AlipayConfig.sign_type); 184 // } catch (Exception e) { 185 // e.printStackTrace(); 186 // } 187 // } else if ("WAIT_BUYER_CONFIRM_GOODS".equals(memberMoney 188 // .getRemark()) 189 // && mMoney == Double.parseDouble(total_fee)) { 190 // memberMoney.setRemark("TRADE_FINISHED"); 191 // memberMoneyService.saveOrUpdate(memberMoney); 192 // } 193 // 194 } 195 196 verifyStatus = "验证成功"; 197 // ——请根据您的业务逻辑来编写程序(以上代码仅做参考)—— 198 199 // //////////////////////////////////////////////////////////////////////////////////////// 200 } else { 201 verifyStatus = "验证失败"; 202 } 203 return SUCCESS; 204 }
4.3 struts.xml网站
1 <!-- 上面略,该action用于页面跳转同步通知 --> 2 <action name="payMoney" class="AlipayAction" method="payMoney"> 3 <result name="success">alipayto.jsp</result> 4 <result name="input">exception.jsp</result> 5 </action>
====================== 华丽丽的分割线 ======================编码
5.alipay 服务器异步通知处理url
5.1 服务器异步通知spa
买家在支付宝中完成交易,付了款后,会出现以下页面:调试
该页面作数秒停留后,会跳转到 AlipayConfig.xml 中的 return_url 属性所指定的页面,这称为页面跳转同步通知(如前所述),而商业网站便在被调用的页面中,作业务逻辑处理。
可是,买家可能在 Alipay 还没有跳转前,便把上面那页面关闭,这时怎么办?
为解决这问题 ,支付宝便有了服务器异步通知。即每当交易状态发生变化,Alipay 都会主动通知AlipayConfig.xml 中的 notify_url 属性所指定的页面(该action不能有返回值,也不能跳转)。这样作确实解决了该问题,但也带来了可能重复调用,故,咱们须要判断alipay传过来的状态是否被处理过,若处理过,则不重复执行。
5.2 notifyURL
逻辑处理语句略!!!
1 /** 2 * 功能:支付宝主动通知调用的页面(服务器异步通知页面) 3 * 4 * @return 5 */ 6 public void notifyURL() { 7 String key = AlipayConfig.key; 8 // 获取支付宝POST过来反馈信息 9 Map params = new HashMap(); 10 //HttpServletRequest request = ServletActionContext.getRequest(); 11 HttpServletRequest request = MyServletContext.getRequest(); 12 PrintWriter out = null; 13 try { 14 // out = ServletActionContext.getResponse().getWriter(); 15 out = MyServletContext.getResponse().getWriter(); 16 } catch (IOException e) { 17 e.printStackTrace(); 18 } 19 Map requestParams = request.getParameterMap(); 20 for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) { 21 String name = (String) iter.next(); 22 String[] values = (String[]) requestParams.get(name); 23 String valueStr = ""; 24 for (int i = 0; i < values.length; i++) { 25 valueStr = (i == values.length - 1) ? valueStr + values[i] 26 : valueStr + values[i] + ","; 27 } 28 // 乱码解决,这段代码在出现乱码时使用。若是mysign和sign不相等也能够使用这段代码转化 29 // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8"); 30 params.put(name, valueStr); 31 } 32 33 // 判断responsetTxt是否为ture,生成的签名结果mysign与得到的签名结果sign是否一致 34 // responsetTxt的结果不是true,与服务器设置问题、合做身份者ID、notify_id一分钟失效有关 35 // mysign与sign不等,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关 36 String mysign = AlipayNotify.GetMysign(params, key); 37 String responseTxt = AlipayNotify.Verify(request 38 .getParameter("notify_id")); 39 String sign = request.getParameter("sign"); 40 41 // 写日志记录(若要调试,请取消下面两行注释) 42 String sWord = "responseTxt=" + responseTxt + "\n notify_url_log:sign=" 43 + sign + "&mysign=" + mysign + "\n notify回来的参数:" 44 + AlipayFunction.CreateLinkString(params); 45 AlipayFunction.LogResult(sWord); 46 47 // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(如下仅供参考)// 48 String trade_no = request.getParameter("trade_no"); // 支付宝交易号 49 String order_no = request.getParameter("out_trade_no"); // 获取订单号 50 String total_fee = request.getParameter("price"); // 获取总金额 51 String subject = ""; 52 try { 53 subject = new String(request.getParameter("subject").getBytes( 54 "ISO-8859-1"), "UTF-8"); 55 } catch (UnsupportedEncodingException e) { 56 e.printStackTrace(); 57 }// 商品名称、订单名称 58 String body = ""; 59 if (request.getParameter("body") != null) { 60 try { 61 body = new String(request.getParameter("body").getBytes( 62 "ISO-8859-1"), "UTF-8"); 63 } catch (UnsupportedEncodingException e) { 64 e.printStackTrace(); 65 }// 商品描述、订单备注、描述 66 } 67 String buyer_email = request.getParameter("buyer_email"); // 买家支付宝帐号 68 String receive_name = "";// 收货人姓名 69 if (request.getParameter("receive_name") != null) { 70 try { 71 receive_name = new String(request.getParameter("receive_name") 72 .getBytes("ISO-8859-1"), "UTF-8"); 73 } catch (UnsupportedEncodingException e) { 74 e.printStackTrace(); 75 } 76 } 77 String receive_address = "";// 收货人地址 78 if (request.getParameter("receive_address") != null) { 79 try { 80 receive_address = new String(request.getParameter( 81 "receive_address").getBytes("ISO-8859-1"), "UTF-8"); 82 } catch (UnsupportedEncodingException e) { 83 e.printStackTrace(); 84 } 85 } 86 String receive_zip = "";// 收货人邮编 87 if (request.getParameter("receive_zip") != null) { 88 try { 89 receive_zip = new String(request.getParameter("receive_zip") 90 .getBytes("ISO-8859-1"), "UTF-8"); 91 } catch (UnsupportedEncodingException e) { 92 e.printStackTrace(); 93 } 94 } 95 String receive_phone = "";// 收货人电话 96 if (request.getParameter("receive_phone") != null) { 97 try { 98 receive_phone = new String(request 99 .getParameter("receive_phone").getBytes("ISO-8859-1"), 100 "UTF-8"); 101 } catch (UnsupportedEncodingException e) { 102 e.printStackTrace(); 103 } 104 } 105 String receive_mobile = "";// 收货人手机 106 if (request.getParameter("receive_mobile") != null) { 107 try { 108 receive_mobile = new String(request.getParameter( 109 "receive_mobile").getBytes("ISO-8859-1"), "UTF-8"); 110 } catch (UnsupportedEncodingException e) { 111 e.printStackTrace(); 112 } 113 } 114 String trade_status = request.getParameter("trade_status"); // 交易状态 115 // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)// 116 117 if (mysign.equals(sign) && responseTxt.equals("true")) {// 验证成功 118 // //////////////////////////////////////////////////////////////////////////////////////// 119 // 请在这里加上商户的业务逻辑程序代码 120 121 122 // —— 请根据您的业务逻辑来编写程序(如下代码仅做参考)—— 123 if (trade_status.equals("WAIT_BUYER_PAY")) { 124 // 该判断表示买家已在支付宝交易管理中产生了交易记录,但没有付款 125 126 // 判断该笔订单是否在商户网站中已经作过处理(可参考“集成教程”中“3.4返回数据处理”) 127 // 若是没有作过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 128 // 若是有作过处理,不执行商户的业务程序 129 // 不作处理 130 out.println("success"); // 请不要修改或删除 131 } else if (trade_status.equals("WAIT_SELLER_SEND_GOODS")) { 132 // 该判断表示买家已在支付宝交易管理中产生了交易记录且付款成功,但卖家没有发货 133 134 // 判断该笔订单是否在商户网站中已经作过处理(可参考“集成教程”中“3.4返回数据处理”) 135 // 若是没有作过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 136 // 若是有作过处理,不执行商户的业务程序 137 138 139 out.println("success"); // 请不要修改或删除 140 } else if (trade_status.equals("WAIT_BUYER_CONFIRM_GOODS")) { 141 // 该判断表示卖家已经发了货,但买家尚未作确认收货的操做 142 143 // 判断该笔订单是否在商户网站中已经作过处理(可参考“集成教程”中“3.4返回数据处理”) 144 // 若是没有作过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 145 // 若是有作过处理,不执行商户的业务程序 146 147 out.println("success"); // 请不要修改或删除 148 } else if (trade_status.equals("TRADE_FINISHED")) { 149 // 该判断表示买家已经确认收货,这笔交易完成 150 151 // 判断该笔订单是否在商户网站中已经作过处理(可参考“集成教程”中“3.4返回数据处理”) 152 // 若是没有作过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 153 // 若是有作过处理,不执行商户的业务程序 154 155 156 out.println("success"); // 请不要修改或删除 157 } else { 158 out.println("success"); // 请不要修改或删除 159 } 160 // ——请根据您的业务逻辑来编写程序(以上代码仅做参考)—— 161 162 // //////////////////////////////////////////////////////////////////////////////////////// 163 }else {// 验证失败 164 out.println("fail"); 165 } 166 }
5.3 struts.xml
1 <!-- 上面略,该action不能执行任何跳转 --> 2 <action name="notifyURL" class="AlipayAction" method="notifyURL" />