4.alipay 页面跳转同步通知处理
4.1 页面跳转同步通知
当买家完成了支付流程后,会出现成功支付的页面,该页面做短暂停留后,会跳转到我们AlipayConfig.xml中的 return_url 属性所指定的页面,这称为页面跳转同步通知。
我们需要在该页面请求中,做相应的商业逻辑处理,如判断并更改订单状态,增加数据库中表示money的字段,注意:判断状态是十分必要的,避免重复进行操作。
4.2 returnURL
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(request103 .getParameter("receive_phone").getBytes("ISO-8859-1"),104 "UTF-8");105 } catch (UnsupportedEncodingException e) {106 // TODO Auto-generated catch block107 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(memberMoney188 // .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 23 alipayto.jsp 4exception.jsp 5
====================== 华丽丽的分割线 ======================
5.alipay 服务器异步通知处理
5.1 服务器异步通知
买家在支付宝中完成交易,付了款后,会出现如下页面:
该页面做数秒停留后,会跳转到 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 2