Javaweb网上商城项目实战(25)实现支付功能

基础概念

银行接口:

优点:资金没有延时。

缺点:银行API如果发生变化,支付功能需要更改。

第三方支付api:

缺点:资金延时,收费。

优点:银行API如果发生变化,支付功能不需要更改。

支付数据执行过程

如何保证数据传输有效性

张三和李四传输数据:

原文:ABCDE

算法:对原文中的每个字符的ASC码增加一个数字(公开)

秘钥:增加的3(只有张三和李四知道)

密文:CDEFG

张三向李四传递数据: ABCDE&CDEFG

李四获取到张三的数据之后:ABCDE利用算法和秘钥3对原文再次加密得到密文

比较得到的密文和获取到的密文是否一致,一致数据是合法的。

加密算法

对称加密: 原文<====>密文

非对称加密:原文<====>密文

本项目支付原理分析

具体实现

[v_notice]本节只是做个演示,看懂支付原理即可,不必实际进行支付操作。[/v_notice]

修改商品详情页

在商品详情页order_info.jsp中增加一个form表单,上一节已经提前做了,如果没做的这里补上。

为地址、收货人、电话添加name属性

设置隐藏域,传递订单oid


OrderServlet中创建payOrder方法

// payOrder
public String payOrder(HttpServletRequest req, HttpServletResponse resp) throws Exception {
	// 获取订单oid,收货人地址,姓名,电话,银行
	String oid = req.getParameter("oid");
	String address = req.getParameter("address");
	String name = req.getParameter("name");
	String telephone = req.getParameter("telephone");
	String pd_FrpId = req.getParameter("pd_FrpId");
	// 更新订单上收货人的地址,姓名,电话
	OrderService OrderService = new OrderServiceImp();
	Order order = OrderService.findOrderByOid(oid);
	order.setName(name);
	order.setTelephone(telephone);
	order.setAddress(address);
	OrderService.updateOrder(order);
	// 向易宝支付发送参数
	// 把付款所需要的参数准备好:
	String p0_Cmd = "Buy";
	// 商户编号
	String p1_MerId = "10001126856";
	// 订单编号
	String p2_Order = oid;
	// 金额
	String p3_Amt = "0.01";
	String p4_Cur = "CNY";
	String p5_Pid = "";
	String p6_Pcat = "";
	String p7_Pdesc = "";
	// 接受响应参数的Servlet
	String p8_Url = "http://localhost:8080/store_v1/OrderServlet?method=callBack";
	String p9_SAF = "";
	String pa_MP = "";
	String pr_NeedResponse = "1";
	// 公司的秘钥
	String keyValue = "69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl";

	// 调用易宝的加密算法,对所有数据进行加密,返回电子签名
	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, keyValue);

	StringBuffer sb = new StringBuffer("https://www.yeepay.com/app-merchant-proxy/node?");
	sb.append("p0_Cmd=").append(p0_Cmd).append("&");
	sb.append("p1_MerId=").append(p1_MerId).append("&");
	sb.append("p2_Order=").append(p2_Order).append("&");
	sb.append("p3_Amt=").append(p3_Amt).append("&");
	sb.append("p4_Cur=").append(p4_Cur).append("&");
	sb.append("p5_Pid=").append(p5_Pid).append("&");
	sb.append("p6_Pcat=").append(p6_Pcat).append("&");
	sb.append("p7_Pdesc=").append(p7_Pdesc).append("&");
	sb.append("p8_Url=").append(p8_Url).append("&");
	sb.append("p9_SAF=").append(p9_SAF).append("&");
	sb.append("pa_MP=").append(pa_MP).append("&");
	sb.append("pd_FrpId=").append(pd_FrpId).append("&");
	sb.append("pr_NeedResponse=").append(pr_NeedResponse).append("&");
	sb.append("hmac=").append(hmac);

	System.out.println(sb.toString());
	//
	// 使用重定向:
	resp.sendRedirect(sb.toString());
	return null;
}

[v_error]注意:这里要引入易宝支付PaymentUtil工具类放到utils包下[/v_error]

OrderServlet中创建callBack方法

// callBack
public String callBack(HttpServletRequest request, HttpServletResponse resp) throws Exception {
	// 接收易宝支付的数据
	// 验证请求来源和数据有效性
	// 阅读支付结果参数说明
	// System.out.println("==============================================");
	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");

	// hmac
	String hmac = request.getParameter("hmac");
	// 利用本地密钥和加密算法 加密数据
	String keyValue = "69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl";

	// 保证数据合法性
	boolean isValid = 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, keyValue);
	if (isValid) {
		// 有效
		if (r9_BType.equals("1")) {
			// 浏览器重定向

			// 如果支付成功,更新订单状态
			OrderService OrderService = new OrderServiceImp();
			Order order = OrderService.findOrderByOid(r6_Order);
			order.setState(2);
			OrderService.updateOrder(order);
			// 向request放入提示信息
			request.setAttribute("msg", "支付成功!订单号:" + r6_Order + "金额:" + r3_Amt);
			// 转发到/jsp/info.jsp
			return "/jsp/info.jsp";

		} else if (r9_BType.equals("2")) {
			// 修改订单状态:
			// 服务器点对点,来自于易宝的通知
			System.out.println("收到易宝通知,修改订单状态!");//
			// 回复给易宝success,如果不回复,易宝会一直通知
			resp.getWriter().print("success");
		}

	} else {
		throw new RuntimeException("数据被篡改!");
	}
	return null;
}

OrderService中创建updateOrder方法

void updateOrder(Order order)throws Exception;

OrderServiceImp中实现该方法

@Override
public void updateOrder(Order order) throws Exception {
	orderDao.updateOrder(order);
	
}

OrderDao中创建该方法

void updateOrder(Order order)throws Exception;

OrderDaoImp中实现该方法

@Override
public void updateOrder(Order order) throws Exception {
	String sql="UPDATE orders SET ordertime=? ,total=? ,state= ?, address=?,NAME=?, telephone =? WHERE oid=?";
	QueryRunner qr=new QueryRunner(JDBCUtils.getDataSource());
	Object[] params={order.getOrdertime(),order.getTotal(),order.getState(),order.getAddress(),order.getName(),order.getTelephone(),order.getOid()};
	qr.update(sql,params);
	
}

效果演示

订单详情中,填写信息,点击确认订单。理论上会跳到支付页面。

[v_notice]本节只是做个演示,看懂支付原理即可。[/v_notice]

源码下载

[dm href=’https://www.jikewenku.com/product/1700.html’]下载地址[/dm]

导航目录

[dm href=’https://www.jikewenku.com/project/2786.html’]查看导航[/dm]

本站所有文章均由网友分享,仅用于参考学习用,请勿直接转载,如有侵权,请联系网站客服删除相关文章。若由于商用引起版权纠纷,一切责任均由使用者承担
极客文库 » Javaweb网上商城项目实战(25)实现支付功能

Leave a Reply

欢迎加入「极客文库」,成为原创作者从这里开始!

立即加入 了解更多