###Jsp+Servlet购物商城day04.5:支付:订单支付遇到的问题总结。

编程入门 行业动态 更新时间:2024-10-26 23:29:32

###Jsp+Servlet<a href=https://www.elefans.com/category/jswz/34/1769408.html style=购物商城day04.5:支付:订单支付遇到的问题总结。"/>

###Jsp+Servlet购物商城day04.5:支付:订单支付遇到的问题总结。

订单支付遇到的问题总结。

实战中遇到的问题如下(遇到顺序):

①首先遇到:易宝支付提示:“易宝支付,订单失败! 失败原因: 抱歉,交易签名无效。”。

百度说是:易宝只支持GBK编码。以为是页面编码问题。

改了:访问易宝支付的JSP页面编码为GBK。

结果问题更糟:报错,连"我的订单" ,去order_list.jsp都去不了。

错误提示:JSP 页面之间的编码不同。


卡在这里。。。


===这个问题,第二天同学帮我修改了pay()的代码:

整个web页面 保持原来的UTF-8。

===这时发现:【JSP对対编码检查十分严格:刚开始把GBK改回“utf-8”,结果还是报同样的错误:

错误提示:JSP 页面之间的编码不同。===必须改为“UTF-8”。】


②还有就是:支持的银行。不全。

这里的测试账号:

易宝支付不再支持 交通银行,

农业银行页面可以进去,支付密码都输入完毕后。

提示:“没有合适的支付方式”。老师说是易宝支付还是农行的问题。和代码无关。所以农行也不行,别费劲了。

同学 有建行卡的支付成功了。我就是用他的卡支付,测试的。。。。O(∩_∩)O哈哈~


③整个OrderServlet:pay()和paySuccess()是这里 支付流程的逻辑。

package cn.itcast.servlet;import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.apache.naming.factory.BeanFactory;import cn.itcast.domain.Cart;
import cn.itcast.domain.CartItem;
import cn.itcast.domain.OrderItem;
import cn.itcast.domain.Orders;
import cn.itcast.domain.PageBean;
import cn.itcast.domain.User;
import cn.itcast.service.OrderService;
import cn.itcast.service.impl.OrderServiceImpl;
import cn.itcast.utils.MyBeanUtils;
import cn.itcast.utils.PaymentUtil;
import cn.itcast.utils.UUIDUtils;public class OrderServlet extends BaseServlet {private static final long serialVersionUID = 1L;public String paySuccess(HttpServletRequest request,HttpServletResponse response) throws Exception{/*String msg = request.getParameter("msg");response.getWriter().write(msg);*///获取返回的所有参数String p1_MerId = request.getParameter("p1_MerId");String r0_Cmd = request.getParameter("r0_Cmd");String r1_Code = request.getParameter("r1_Code");String r2_TrxId = request.getParameter("r2_TrxId");String r3_Amt = request.getParameter("r3_Amt");String r4_Cur = request.getParameter("r4_Cur");String r5_Pid = request.getParameter("r5_Pid");String r6_Order = request.getParameter("r6_Order");String r7_Uid = request.getParameter("r7_Uid");String r8_MP = request.getParameter("r8_MP");String r9_BType = request.getParameter("r9_BType");String rb_BankId = request.getParameter("rb_BankId");String ro_BankOrderId = request.getParameter("ro_BankOrderId");String rp_PayDate = request.getParameter("rp_PayDate");String rq_CardNo = request.getParameter("rq_CardNo");String ru_Trxtime = request.getParameter("ru_Trxtime");String hmac = request.getParameter("hmac");//校验数据是否正确boolean flag = PaymentUtil.verifyCallback(hmac, p1_MerId, r0_Cmd, r1_Code, r2_TrxId, r3_Amt, r4_Cur, r5_Pid, r6_Order, r7_Uid, r8_MP, r9_BType, "69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl");if(flag){//数据正确,修改订单状态OrderService service = new OrderServiceImpl();try{
//					Orders order = service.searchByOid(r6_Order);//Orders order = service.findOrderByOid(r6_Order);//order.setState(1);//service.modify(order);service.setState(r6_Order);//==######=r6_Order是易宝支付生成的oid,不是数据库的oid。修改订单状态失败。request.setAttribute("msg","订单付款成功,订单号为:"+r6_Order+"///付款金额为:"+r3_Amt);}catch(Exception e){throw new RuntimeException(e);}}else{throw new RuntimeException("数据遭篡改");}return "/showMsg.jsp";}public String pay(HttpServletRequest request, HttpServletResponse response){Map<String, String[]> map = request.getParameterMap();Orders orders = new Orders();MyBeanUtils.setObject(orders, map);
//		System.out.println(orders.getOid());OrderService os = new OrderServiceImpl();try {//===######===支付前更新 收货人信息。os.upt(orders);} catch (SQLException e1) {e1.printStackTrace();}String p0_Cmd = "Buy";String p1_MerId = "10001126856";//===商家账号:测试的:红十字会。//==######=不填的话,数据库oid传不过去,支付成功后,订单状态修改不了。//String p2_Order = "";//==商户订单号(可不填,可随意填)。===查看 API都有解释。String p2_Order = orders.getOid();//商户订单号不填,数据库oid传不过去,支付成功后,订单状态修改不了。String p3_Amt = "0.01";//测试用1分钱,真正开发中用order.getTotal();String p4_Cur = "CNY";String p5_Pid = "";String p6_Pcat = "";String p7_Pdesc = "";//===支付成功返回提示信息,不在这里。在method=paySuccess。//String p8_Url = "http://localhost:8080"+request.getContextPath()+"/OrderServlet?method=paySuccess&msg='支付成功'";//String p8_Url = "http://localhost:8080"+request.getContextPath()+"/OrderServlet?method=paySuccess";String p9_SAF = "0";String pa_MP = "";String pd_FrpId = request.getParameter("pd_FrpId");String pr_NeedResponse = "1";//===签名机制。最后一个参数是:密钥。String hmac = PaymentUtil.buildHmac(p0_Cmd, p1_MerId, p2_Order, p3_Amt, p4_Cur, p5_Pid, p6_Pcat, p7_Pdesc, p8_Url, p9_SAF, pa_MP, pd_FrpId, pr_NeedResponse, "69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl");StringBuffer buffer = new StringBuffer("?");buffer.append("p0_Cmd="+p0_Cmd);buffer.append("&p1_MerId="+p1_MerId);buffer.append("&p2_Order="+p2_Order);buffer.append("&p3_Amt="+p3_Amt);buffer.append("&p4_Cur="+p4_Cur);buffer.append("&p5_Pid="+p5_Pid);buffer.append("&p6_Pcat="+p6_Pcat);buffer.append("&p7_Pdesc="+p7_Pdesc);buffer.append("&p8_Url="+p8_Url);buffer.append("&p9_SAF="+p9_SAF);buffer.append("&pa_MP="+pa_MP);buffer.append("&pd_FrpId="+pd_FrpId);buffer.append("&pr_NeedResponse="+pr_NeedResponse);buffer.append("&hmac="+hmac);//==跳到易宝支付服务器。//==###=【servlet里只能try 不能抛】try {response.sendRedirect(buffer.toString());} catch (IOException e) {e.printStackTrace();}return null;}public String findByOid(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {String oid = request.getParameter("oid");try {OrderService os = new OrderServiceImpl();Orders order = null;if (oid!=null) {order = os.findByOid(oid);}//===OrderDaoImpl的findByOid(oid),BeanUtils封装不了User。//===但支付页面:也就是order_info.jsp不需要显示 “订单所属用户”//order.setUser(  (User) request.getSession().getAttribute("logingUser")  );request.setAttribute("order", order);} catch (SQLException e) {e.printStackTrace();}return "/order_info.jsp";}public String findByPage(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {//===分页查询当前用户订单,需要的参数。String pageNumStr = request.getParameter("pageNum");if (pageNumStr==null) {pageNumStr="1";}int pageNum = Integer.parseInt(pageNumStr);User user = (User) request.getSession().getAttribute("logingUser");//===开始查询:OrderService os = new OrderServiceImpl();try {PageBean pb = os.findByPage(pageNum,user);request.setAttribute("pb", pb);} catch (SQLException e) {e.printStackTrace();}return "order_list.jsp";}//====多层数据的封装,必须自己总结一套 套路。思路清晰熟练。?下面public String save(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {User user = (User) request.getSession().getAttribute("logingUser");if (user==null) {
//				response.sendRedirect("/login.jsp");//==###=重定向,后面代码不会再执行。return "/login.jsp";}Cart cart = (Cart) request.getSession().getAttribute("cart");/*===######==数据封装。购物项==订单项,购物车==Order。对应数据关系。【总体思想:把session里的cart信息,取出来封装到 order里】①cartItem信息和OrderItem页面信息基本完全一样,只是个别表字段多加了几个特有外键属性。表结构不同, 因此OrderItem不能直接使用 CartItem的Bean类。②cart和Order相似。都对内容进行封装。都有总价。很相似。====总结===Cart.jsp到OrderInfo.jsp的过渡:本质就是:Session购物车数据 Cart取出来重新封装在Order里,再在页面显示重新Order信息。=====难点也就是逐层封装的具体过程。需要非常熟练。*/Orders order = new Orders();//order.setOid(UUIDUtils.getUUID());order.setOrdertime(new Date());order.setState(0);order.setTotal(cart.getTotalMoney());order.setUser(user);////OrderItem orderItem = new OrderItem();//===放在外面,Map永远只存了最后一个OrderItem//LinkedHashMap<String, OrderItem> map = new LinkedHashMap<String, OrderItem>();List<OrderItem> list = new ArrayList<OrderItem>();Collection<CartItem> items = cart.getItems();for (CartItem cartItem : items) {OrderItem orderItem = new OrderItem();//===放在外面,Map永远只存了最后一个OrderItem//System.out.println("cartItem:"+cartItem.getPro().getPname()+"="+cartItem.getTotal());orderItem.setCount(cartItem.getCount());//orderItem.setItemid(cartItem.getPro().getPid());//==######=【pid做orderItem主键,从表orderItem插入相同商品时,报错:主键重复。】//===CartItem可以把pid作为 CartItem的标记,因为不需要存在表里。orderItem.setItemid(UUIDUtils.getUUID());orderItem.setOrder(order);orderItem.setPro(cartItem.getPro());//map.put(cartItem.getPro().getPid(), orderItem);list.add(orderItem);}//System.out.println("===map"+map);//===ok===
//			System.out.println("===list"+list);//===ok===order.setOrderItems(list);/*//===测试。Collection<OrderItem> orderItems = order.getOrderItems();for (OrderItem item : orderItems) {System.out.println("一个orderItem:【");System.out.println("==="+item.getItemid());System.out.println("==="+item.getCount());System.out.println("==="+item.getSubtotal());System.out.println("==="+item.getPro().getPname());System.out.println("】");}System.out.println();//===重写toString()*/			OrderService os = new OrderServiceImpl();try {	/*boolean b = os.save(order);if(b){request.getSession().removeAttribute("cart");}//==######=dao 一般不会保存失败。出错,肯定是sql语句语法问题。返回值是void就行,不用判断是否保存成功。代码简写即可*/				os.save(order);request.getSession().removeAttribute("cart");//===request.setAttribute("order", order);} catch (Exception e) {e.printStackTrace();}return "order_info.jsp";}}


====最后:上一张 人生第一次支付成功,并且成功返回提示信息的图片。以作纪念。

(虽然大学自己支付成功过,钱扣了,但是返回“支付成功”提示信息总是失败,一直未解决,还是很不舒服的。)



--------------------#######------这里返回的订单号是 易宝支付 自动为我生成的。因为当时没有填写 订单编号参数:

//String p2_Order = "";//==商户订单号(可不填,可随意填)。===查看 API都有解释。

String p2_Order = orders.getOid();//商户订单号不填,数据库oid传不过去,支付成功后,订单状态修改不了。

====【setState(oid),拿到的是易宝支付给生成的oid,当然在数据库 查不到 当前订单的信息。也就无从谈起:支付成功后修改订单状态了。

==###==这个问题对于新手很难找,因为,setState()没找到Order信息,竟然不报错!!!】


当然,“order_info.jsp”添加完毕 收货人信息,地址这些资料后,点击“确认订单”按钮,

请求易宝支付(调用OrderServlet的pay())时,必须要记得传递oid(使用隐藏表单域:name属性,value属性一个都不能少!)。

pay():使用request.getParameterMap()接收所有参数,BeanUtils封装Order信息,传给upt(Order order),更新Order 收货人信息。

==###==这个问题更难找!如果忘了页面传递oid,封装的oid就是null。

导致“确认订单” 前去支付时,易宝支付 提示一个很迷惑人的信息:“已经支付成功,请不要重复支付!”


-------------------------------------------------好了,以上就是所有遇到的问题。

【业务逻辑总思路:】===【支付前,更新数据库,Order收货人信息;支付成功后,修改订单状态(这个容易想到)】




----------------------------------------------支付需要的3个工具。

①PaymentUtil.java

package cn.itheima.store.order.utils;import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;public class PaymentUtil {private static String encodingCharset = "UTF-8";/*** 生成hmac方法* * @param p0_Cmd 业务类型* @param p1_MerId 商户编号* @param p2_Order 商户订单号* @param p3_Amt 支付金额* @param p4_Cur 交易币种* @param p5_Pid 商品名称* @param p6_Pcat 商品种类* @param p7_Pdesc 商品描述* @param p8_Url 商户接收支付成功数据的地址* @param p9_SAF 送货地址* @param pa_MP 商户扩展信息* @param pd_FrpId 银行编码* @param pr_NeedResponse 应答机制* @param keyValue 商户密钥* @return*/public static String buildHmac(String p0_Cmd,String p1_MerId,String p2_Order, String p3_Amt, String p4_Cur,String p5_Pid, String p6_Pcat,String p7_Pdesc,String p8_Url, String p9_SAF,String pa_MP,String pd_FrpId,String pr_NeedResponse,String keyValue) {StringBuilder sValue = new StringBuilder();// 业务类型sValue.append(p0_Cmd);// 商户编号sValue.append(p1_MerId);// 商户订单号sValue.append(p2_Order);// 支付金额sValue.append(p3_Amt);// 交易币种sValue.append(p4_Cur);// 商品名称sValue.append(p5_Pid);// 商品种类sValue.append(p6_Pcat);// 商品描述sValue.append(p7_Pdesc);// 商户接收支付成功数据的地址sValue.append(p8_Url);// 送货地址sValue.append(p9_SAF);// 商户扩展信息sValue.append(pa_MP);// 银行编码sValue.append(pd_FrpId);// 应答机制sValue.append(pr_NeedResponse);return PaymentUtil.hmacSign(sValue.toString(), keyValue);}/*** 返回校验hmac方法* * @param hmac 支付网关发来的加密验证码* @param p1_MerId 商户编号* @param r0_Cmd 业务类型* @param r1_Code 支付结果* @param r2_TrxId 易宝支付交易流水号* @param r3_Amt 支付金额* @param r4_Cur 交易币种* @param r5_Pid 商品名称* @param r6_Order 商户订单号* @param r7_Uid 易宝支付会员ID* @param r8_MP 商户扩展信息* @param r9_BType 交易结果返回类型* @param keyValue 密钥* @return*/public static boolean verifyCallback(String hmac, String p1_MerId,String r0_Cmd, String r1_Code, String r2_TrxId, String r3_Amt,String r4_Cur, String r5_Pid, String r6_Order, String r7_Uid,String r8_MP, String r9_BType, String keyValue) {StringBuilder sValue = new StringBuilder();// 商户编号sValue.append(p1_MerId);// 业务类型sValue.append(r0_Cmd);// 支付结果sValue.append(r1_Code);// 易宝支付交易流水号sValue.append(r2_TrxId);// 支付金额sValue.append(r3_Amt);// 交易币种sValue.append(r4_Cur);// 商品名称sValue.append(r5_Pid);// 商户订单号sValue.append(r6_Order);// 易宝支付会员IDsValue.append(r7_Uid);// 商户扩展信息sValue.append(r8_MP);// 交易结果返回类型sValue.append(r9_BType);String sNewString = PaymentUtil.hmacSign(sValue.toString(), keyValue);return sNewString.equals(hmac);}/*** @param aValue* @param aKey* @return*/public static String hmacSign(String aValue, String aKey) {byte k_ipad[] = new byte[64];byte k_opad[] = new byte[64];byte keyb[];byte value[];try {keyb = aKey.getBytes(encodingCharset);value = aValue.getBytes(encodingCharset);} catch (UnsupportedEncodingException e) {keyb = aKey.getBytes();value = aValue.getBytes();}Arrays.fill(k_ipad, keyb.length, 64, (byte) 54);Arrays.fill(k_opad, keyb.length, 64, (byte) 92);for (int i = 0; i < keyb.length; i++) {k_ipad[i] = (byte) (keyb[i] ^ 0x36);k_opad[i] = (byte) (keyb[i] ^ 0x5c);}MessageDigest md = null;try {md = MessageDigest.getInstance("MD5");} catch (NoSuchAlgorithmException e) {return null;}md.update(k_ipad);md.update(value);byte dg[] = md.digest();md.reset();md.update(k_opad);md.update(dg, 0, 16);dg = md.digest();return toHex(dg);}public static String toHex(byte input[]) {if (input == null)return null;StringBuffer output = new StringBuffer(input.length * 2);for (int i = 0; i < input.length; i++) {int current = input[i] & 0xff;if (current < 16)output.append("0");output.append(Integer.toString(current, 16));}return output.toString();}/*** * @param args* @param key* @return*/public static String getHmac(String[] args, String key) {if (args == null || args.length == 0) {return (null);}StringBuffer str = new StringBuffer();for (int i = 0; i < args.length; i++) {str.append(args[i]);}return (hmacSign(str.toString(), key));}/*** @param aValue* @return*/public static String digest(String aValue) {aValue = aValue.trim();byte value[];try {value = aValue.getBytes(encodingCharset);} catch (UnsupportedEncodingException e) {value = aValue.getBytes();}MessageDigest md = null;try {md = MessageDigest.getInstance("SHA");} catch (NoSuchAlgorithmException e) {e.printStackTrace();return null;}return toHex(md.digest(value));}//	public static void main(String[] args) {
//		System.out.println(hmacSign("AnnulCard1000043252120080620160450.0http://localhost/SZXpro/callback.asp杩?4564868265473632445648682654736324511","8UPp0KE8sq73zVP370vko7C39403rtK1YwX40Td6irH216036H27Eb12792t"));
//	}
}


②支付接口:写在pay()方法体里。

(通用代码:需要根据业务修改:)

【比如这里我需要改的:

①接收 封装 收货人信息,更新数据库;

②oid要修改为当前订单oid(不能乱写)===这个所有业务都得这样吧。。。】

====具体改动 看上面的最终完整的OrderServlet的pay()。

String p0_Cmd = "Buy";String p1_MerId = "10001126856";String p2_Order = order.getOid();String p3_Amt = "0.01";//测试用1分钱,真正开发中用order.getTotal();String p4_Cur = "CNY";String p5_Pid = "";String p6_Pcat = "";String p7_Pdesc = "";String p8_Url = "http://localhost:8080"+request.getContextPath()+"/order?methodName=payOrderSuccess";String p9_SAF = "0";String pa_MP = "";String pd_FrpId = request.getParameter("pd_FrpId");String pr_NeedResponse = "1";String hmac = PaymentUtil.buildHmac(p0_Cmd, p1_MerId, p2_Order, p3_Amt, p4_Cur, p5_Pid, p6_Pcat, p7_Pdesc, p8_Url, p9_SAF, pa_MP, pd_FrpId, pr_NeedResponse, "69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl");StringBuffer buffer = new StringBuffer("?");buffer.append("p0_Cmd="+p0_Cmd);buffer.append("&p1_MerId="+p1_MerId);buffer.append("&p2_Order="+p2_Order);buffer.append("&p3_Amt="+p3_Amt);buffer.append("&p4_Cur="+p4_Cur);buffer.append("&p5_Pid="+p5_Pid);buffer.append("&p6_Pcat="+p6_Pcat);buffer.append("&p7_Pdesc="+p7_Pdesc);buffer.append("&p8_Url="+p8_Url);buffer.append("&p9_SAF="+p9_SAF);buffer.append("&pa_MP="+pa_MP);buffer.append("&pd_FrpId="+pd_FrpId);buffer.append("&pr_NeedResponse="+pr_NeedResponse);buffer.append("&hmac="+hmac);response.sendRedirect(buffer.toString());

③回调接口(paySuccess()方法体里)。(这个老师说不是必须的。但是有,才是最常见的)

【当然也需要根据业务修改。】

//获取返回的所有参数String p1_MerId = request.getParameter("p1_MerId");String r0_Cmd = request.getParameter("r0_Cmd");String r1_Code = request.getParameter("r1_Code");String r2_TrxId = request.getParameter("r2_TrxId");String r3_Amt = request.getParameter("r3_Amt");String r4_Cur = request.getParameter("r4_Cur");String r5_Pid = request.getParameter("r5_Pid");String r6_Order = request.getParameter("r6_Order");String r7_Uid = request.getParameter("r7_Uid");String r8_MP = request.getParameter("r8_MP");String r9_BType = request.getParameter("r9_BType");String rb_BankId = request.getParameter("rb_BankId");String ro_BankOrderId = request.getParameter("ro_BankOrderId");String rp_PayDate = request.getParameter("rp_PayDate");String rq_CardNo = request.getParameter("rq_CardNo");String ru_Trxtime = request.getParameter("ru_Trxtime");String hmac = request.getParameter("hmac");//校验数据是否正确boolean flag = PaymentUtil.verifyCallback(hmac, p1_MerId, r0_Cmd, r1_Code, r2_TrxId, r3_Amt, r4_Cur, r5_Pid, r6_Order, r7_Uid, r8_MP, r9_BType, "69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl");if(flag){//数据正确,修改订单状态OrderService service = new OrderServiceImpl();try{Order order = service.searchByOid(r6_Order);order.setState(1);service.modify(order);request.setAttribute("msg","订单付款成功,订单号为:"+r6_Order+"///付款金额为:"+r3_Amt);}catch(Exception e){throw new RuntimeException(e);}}else{throw new RuntimeException("数据遭篡改");}return "/msg.jsp";



更多推荐

###Jsp+Servlet购物商城day04.5:支付:订单支付遇到的问题总结。

本文发布于:2024-02-25 02:36:14,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1697500.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:购物商城   订单   Jsp   Servlet

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!