1. 程式人生 > >網上商城專案總結

網上商城專案總結

經過三週的學習,網上商城專案的所有功能在今天都全部完成了,寫這個專案我學到了不少新的知識,為了以後方便回顧,把這個專案實現的功能都寫在這裡,專案是jsp+servlet+javabean實現的。

一,商城後臺

1.登入,

獲取到前臺頁面輸入的管理員使用者名稱和密碼,到資料庫進行查詢,dao層對資料庫操作,用到了QueryRunner類,建立物件時,以c3p0連線池為引數QueryRunner runner=new QueryRunner(DataSourceUtils.getDataSource());對資料庫查詢時,用runner的query(sql,ResultSetHandler,Object...params

)方法,引數sql為sql語句,ResultSetHandler,為返回值,Object...params為sql語句中所需要的值,更新資料庫時,用update(sql,Object...params)方法,引數意思和query方法中的一樣。登入成功後,可以看到三個選單,分別為分類管理,商品管理和訂單管理

2.分類管理,

這個模組實現了對商場所賣商品的所有類別的增刪改查,和分頁查詢,因為後續很多模組也需要用到分頁查詢,於是我們就通過反射來進行了提取,建立了PageUtil類,裡面有4個屬性private int pageSize;每頁顯示條數,private int nowPage;當前頁碼號,private int maxPage;最大頁碼號,private int totalCount;資料總條數,生成他們的get,set方法,主要程式碼為

public  List<T> getList(Class name,String sql,int nowpage,int pagesize) {
		
		QueryRunner query=new QueryRunner(DataSourceUtils.getDataSource());
		try {
			return query.query(sql, new BeanListHandler<T>(name), (nowpage-1)*pagesize,pagesize);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
public int getMaxPage(String sql,int pagesize) {
		int count=0;
		QueryRunner query=new QueryRunner(DataSourceUtils.getDataSource());
		try {
		    count=((Long)query.query(sql, new ScalarHandler())).intValue();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		this.totalCount=count;
		int max=(count%pagesize)==0?count/pagesize:(count/pagesize)+1;
		this.maxPage=max;
		return maxPage;
	}
只需要呼叫者兩個方法,傳入相應的引數即可得到分頁所顯示的資料,

3.商品管理

這裡主要是對商品的增刪改查操作,新增商品時,因為要顯示所有的商品類別,所以採用自定函式標籤來實現這一功能,在WEB-INF下新建資料夾,在資料夾裡新建一個.tld結尾的檔案,可根據standard.jar包下的META-INF/fn.tld裡面的內容來編寫自定義函式,寫完後如下

<?xml version="1.0" encoding="UTF-8" ?>

<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
  version="2.0">
  
  <description>JSTL 1.1 functions library</description>
  <display-name>JSTL functions</display-name>
  <tlib-version>1.1</tlib-version>
  <short-name>myfn</short-name>
  <uri>http://lsk.com</uri>//引入自定義函式地址
  
   <function>
    <description>
     select all category
    </description>
    <name>findAllCategories</name>//自定義方法名
    <function-class>com.yinhe.dao.CategoryDao</function-class>//類的路徑
    <function-signature>java.util.List findAllCategories()</function-signature>//返回型別 和類所呼叫的方法
  
  </function>
 </taglib>
前臺呼叫${myfn:findAllCategories() },這裡需要注意的是CategoryDao類中的findAllCategories方法必須為static的,不然前臺呼叫會報錯。
商品圖片上傳,用到了兩個jar包commons-fileupload-1.2.1.jar 和commons-io-1.4.jar,主要實現程式碼為
//建立檔案專案工廠
		DiskFileItemFactory factory=new DiskFileItemFactory();
		//建立一個檔案上傳解析器
		ServletFileUpload upload=new ServletFileUpload(factory);
		//判斷表單enctype為否為mutipart-data
		
		if(upload.isMultipartContent(request)){
			//解析request物件,並把表單中的每一個輸入項包裝成一個fileItem 物件,並返回一個儲存了所有FileItem的list集合。
			List<FileItem> list=upload.parseRequest(request);
			for (FileItem fileItem : list) {
				if (fileItem.isFormField()) {//普通表單處理
					map.put(fileItem.getFieldName(), fileItem.getString("UTF-8"));
				}else {
					//檔案上傳
					if (fileItem.getSize()>0) {
					String fileName=fileItem.getName();
					InputStream is=fileItem.getInputStream();
					FileOutputStream out=new FileOutputStream(new File(path, fileName));
					IOUtils.copy(is, out);
					IOUtils.closeQuietly(is);
					IOUtils.closeQuietly(out);
					fileItem.delete();
				}
				}
			}
商品編輯,對商品資訊進行修改,用到了回顯,修改時要判斷是否上傳了新的商品圖片,如果是則把新圖片上傳到伺服器,並修改各個欄位,然後把原來的圖片刪除了,如果否,不用進行圖片的上傳,直接修改其他欄位即可。

3.訂單管理

這裡是顯示使用者所購買過的訂單,所以只要顯示出來即可,不需要進行修改,同時也要把每個訂單下的商品通過點選訂單詳情彈出一個彈出框,將商品資訊顯示在彈出框裡,這樣就需要我們進行手動的對資料進行封裝,每個訂單含有一個訂單子項集合,每個訂單集合中又有商品物件等資訊,所以就需要對查出來的資料進行兩層封裝,

public List<Orders> getOrders(int nowpage,int pagesize) throws SQLException{
		String sql="select * from orders limit ?,?";
		QueryRunner qr=new QueryRunner(DataSourceUtils.getDataSource());
		List<Orders> orders=qr.query(sql, new BeanListHandler<Orders>(Orders.class),(nowpage-1)*pagesize,pagesize);
		for (Orders orders2 : orders) {
			String sql2="select * from orderitem where oid=?";
			List<Orderitem> orderitems=qr.query(sql2, new BeanListHandler<Orderitem>(Orderitem.class),orders2.getOid());
			orders2.setItems((ArrayList)orderitems);
			for (Orderitem orderitem : orderitems) {
				String sql3="select * from product where pid=?";
				Product p=qr.query(sql3, new BeanHandler<Product>(Product.class),orderitem.getPid());
				orderitem.setProduct(p);
			}
		}
		
		
		
		return orders;
	}
前臺顯示遍歷集合,建立當前所有訂單的彈出框並隱藏,以每個訂單號給彈出框及按鈕定義類和id,點選按鈕呼叫外掛定義的方法,通過不同訂單號,來顯示當前點選訂單下的訂單詳情。
<script type="text/javascript">
			$(function(){
				//彈出層外掛呼叫
				<c:forEach items="${list }" var="order" varStatus="vs">
				new PopupLayer({
					trigger:".clickedElement_${order.oid }",
					popupBlk:"#showDiv_${order.oid }",
					closeBtn:"#closeBtn_${order.oid }",
					useOverlay:true
				});
				</c:forEach>
				
			});
		</script>

BaseServlet的抽取,如果一個請求對應一個servlet類那麼一個網站將會有成百上千個請求,也將對應這些類,於是我們就用到了BaseServlet的抽取,原理是反射,每個servlet類繼承BaseServlet類,請求後加入引數method和值,就會自動找到該類中的方法進行處理

package com.yinhe.web.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class BaseServlet extends HttpServlet {

	
	@Override
	protected void service(HttpServletRequest arg0, HttpServletResponse arg1)
			throws ServletException, IOException {
		arg0.setCharacterEncoding("UTF-8");
		arg1.setCharacterEncoding("UTF-8");
		String method=arg0.getParameter("method");
		Class clazz=this.getClass();
		try {
			Method m=clazz.getMethod(method, HttpServletRequest.class,HttpServletResponse.class);
			m.invoke(this, arg0,arg1);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	



}


二,商城前臺

1.使用者註冊

註冊頁面的表單採用了validate外掛進行了相應的驗證,同時使用者名稱也用了validate自定義方法來驗證使用者名稱是否存在,前臺通過ajax來發送請求,後臺根據使用者填寫的使用者名稱去資料庫查詢,根據查詢的結果向前臺輸出一個json型別的字串,前臺根據這個json字串來判斷使用者名稱是否存在

$.validator.addMethod("checkUN",function(){
		var flag = false;
		$.ajax({
			url:"${pageContext.request.contextPath}/user?method=checkUser",
			data:{"username":$("#username").val()},
			dataType:"json",
			type:"post",
			//true 非同步
			//false 同步
			async:false,
			//T2
			success:function(data){
				if (data=='0')
					flag = true;
			},error:function(e){
				alert(e.responseText);
			}
		});
		return flag;
	},"使用者名稱已存在");
當用戶正確輸入所有資訊後,點選註冊,servlet處理請求,封裝user物件,由於屬性較多,我們用BeanUtils類中的populate(object, map)方法來進行封裝,需要注意的是前臺表單name值要和物件屬性名一致,封裝好後對資料庫進行插入資料然後傳送郵件
if (us.addUser(user)) {
			String emailMsg = "恭喜您註冊成功,請點選下面的連線進行啟用賬戶"
					+ "<a href='http://localhost:8080/Shopping/user?method=activation&&activation="+user.getCode()+"'>啟用</a>";

			try {
				MailUtils.sendMail(user.getEmail(), emailMsg);
				response.sendRedirect("/Shopping/registerSuccess.jsp");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				response.sendRedirect("/Shopping/registerFail.jsp");
			}
			//response.sendRedirect("/Shopping/login.jsp");
		}

這時會向用戶所填的郵箱了傳送啟用郵件,使用者點選郵箱中的啟用連結即可啟用,在資料庫中state欄位來判斷使用者是否啟用,不啟用則不能登入,實現郵箱驗證需要傳送者郵箱開通SMTP協議,還要用到工具類MailUtils.java和jar包mail.jar

package com.yinhe.utils;

import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;

public class MailUtils {

	public static void sendMail(String email, String emailMsg)
			throws AddressException, MessagingException {
		// 1.建立一個程式與郵件伺服器會話物件 Session

		Properties props = new Properties();
		props.setProperty("mail.transport.protocol", "SMTP");
		props.setProperty("mail.host", "smtp.163.com");
		props.setProperty("mail.smtp.auth", "true");// 指定驗證為true

		// 建立驗證器
		Authenticator auth = new Authenticator() {
			public PasswordAuthentication getPasswordAuthentication() {
				return new PasswordAuthentication("[email protected]", "peiyifei888");
			}
		};

		Session session = Session.getInstance(props, auth);

		// 2.建立一個Message,它相當於是郵件內容
		Message message = new MimeMessage(session);

		message.setFrom(new InternetAddress("[email protected]")); // 設定傳送者

		message.setRecipient(RecipientType.TO, new InternetAddress(email)); // 設定傳送方式與接收者

		message.setSubject("使用者啟用");
		// message.setText("這是一封啟用郵件,請<a href='#'>點選</a>");

		message.setContent(emailMsg, "text/html;charset=utf-8");

		// 3.建立 Transport用於將郵件傳送

		Transport.send(message);
	}
}

使用者點選連結後再對user表中state欄位值進行修改,然後跳轉到登入介面。

2.使用者登入,登出

就是獲取使用者從前臺輸入的使用者名稱和密碼,對user表進行查詢,如果資訊存在則將user物件存到session中,跳轉到首頁,這裡有個功能是自動登入,如果使用者點過自動登入後,關閉瀏覽器下次再開啟此網站就不用再登入了,這個功能使用了過濾器,首先判斷使用者是否選擇了自動登入,如果是就將使用者名稱和密碼存到cookie中,

String uname=request.getParameter("username");
		String psw=request.getParameter("password");
		String auto=request.getParameter("auto");
		
		if ("on".equals(auto)) {
			Cookie cookie=new Cookie("uname", uname);
			Cookie cookie2=new Cookie("psw", psw);
			cookie.setMaxAge(60*60);
			cookie2.setMaxAge(60*60);
			response.addCookie(cookie2);
			response.addCookie(cookie);
		}
		User u=us.login(uname,psw);
		if (u!=null) {
			
			request.getSession().setAttribute("user", u);
			response.sendRedirect("index.jsp");
		}else {
			request.setAttribute("message", "使用者名稱或密碼錯誤");
			request.getRequestDispatcher("login.jsp").forward(request, response);
		}
建立過濾器AutoLogin.java,然後在web.xml配置 表示每個請求都要來到這個過濾器處理
 <filter>
  		<filter-name>auto</filter-name>
  		<filter-class>com.yinhe.fiter.AutoLogin</filter-class>
  </filter>
  <filter-mapping>
  		<filter-name>auto</filter-name>
  		<url-pattern>/*</url-pattern>
  </filter-mapping>

package com.yinhe.fiter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.yinhe.bean.User;
import com.yinhe.service.UserService;
import com.yinhe.web.servlet.UserServlet;

public class AutoLogin implements Filter{

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void doFilter(ServletRequest arg0, ServletResponse arg1,
			FilterChain arg2) throws IOException, ServletException {
		// TODO Auto-generated method stub
		HttpServletRequest request=(HttpServletRequest) arg0;
		HttpServletResponse response=(HttpServletResponse)arg1;
		if (request.getSession().getAttribute("user")==null) {
			
		
		Cookie cookie[]=request.getCookies();
		if (cookie!=null) {
			String uname="";
			String psw="";
			for (Cookie cookie2 : cookie) {
				if (cookie2.getName().equals("uname")) {
					uname=cookie2.getValue();
				}
				if (cookie2.getName().equals("psw")) {
					psw=cookie2.getValue();
				}
			}
			UserService us=new UserService();
			User user=us.login(uname, psw);
			request.getSession().setAttribute("user", user);
		}
		}
		arg2.doFilter(request, response);
		
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub
		
	}

}

在過濾器中遍歷cookie,如果找到登入時儲存的cookie則進行自動登入。

登出就是將我們儲存在session中的user和儲存在cookie中的使用者名稱和密碼進行刪除

		Cookie[] cookies = request.getCookies();
		if (cookies != null){
			for (Cookie cookie : cookies) {
				if (cookie.getName().equals("username") || cookie.getName().equals("password")){
					//刪除cookie 
					cookie.setMaxAge(0);
					response.addCookie(cookie);
				}	
			}
		}
		request.getSession().removeAttribute("user");


3.主頁資訊

主頁主要資訊有商品分類標題,最熱商品和最新商品,我們要把它們從資料庫中查詢出來,首先是商品分類標題,因為這個是不經常改變的,所以我們用redis伺服器來將這些資訊儲存在快取中,這樣不用每次重新整理頁面都去資料庫中查詢,同時首次查詢也採用了ajax傳送請求來進行查詢,後臺將查詢到的List<Category>集合轉換成json字串,因為手動將集合轉為json字串比較複雜,所以我們用Gson類中的toJson方法來進行轉換,使用前需要先匯入jar包gson-2.2.4.jar,也可以使用JSONArray.fromObject(list).toString()方法轉換,前提也需要匯入jar包json-lib-2.4-jdk15.jar,當管理員修改這些標題後,我們要重新查詢和儲存,所以我們用儲存在application域中的flag進行判斷,預設值為0,修改後則為1

	Jedis jedis=JedisPoolUtils.getJedis();
		String json_list ="";
		if (jedis.get("json_list")==null||"1".equals(request.getServletContext().getAttribute("flag"))) {
			
			request.getServletContext().setAttribute("flag", "0");
			List<Category> list=cs.findAllCategories();
			request.setAttribute("list", list);
			
			//json格式轉換
			Gson gson = new Gson();
			json_list = gson.toJson(list);
			System.out.println("資料庫查詢");
			
			jedis.set("json_list", json_list);
			
		}else {
			json_list=jedis.get("json_list");
		}
		
		response.getWriter().println(json_list);
			
		

	
	}
最熱商品和最新商品根據資料庫中的is_hot和pdate欄位進行查詢即可。

4.分類列表商品展示

使用者點選商品分類標籤後,傳送請求,根據標籤id來進行顯示此分類下的商品,此頁面也有分頁查詢,原理都一樣,在此不再過多介紹,

5.商品詳情展示

根據商品id查詢資料庫,然後在前臺顯示。

6.瀏覽記錄

將點選過商品的id以!連結成字串儲存在cookie中,儲存的時候要判斷是不是第一次點選該商品,如果是就將該商品id新增到字串首位,否則就移除原來的pid,再將pid新增到首位,顯示的時候,找到儲存在cookie中的字串,以!分割成陣列,遍歷陣列進行查詢,將這些商品儲存在list集合中,供前臺使用

儲存商品id

	//瀏覽記錄
		String pids=pid;
		Cookie[] cookies=request.getCookies();
		if (cookies!=null) {
			for (Cookie cookie : cookies) {
				if ("pids".equals(cookie.getName())) {//尋找儲存name為pid的cookie
					//以!分割字串為陣列
					String[] pidStrings=cookie.getValue().split("!");
					//將字串轉化為LinkedList
					List<String> list=Arrays.asList(pidStrings);
					LinkedList<String> pidList=new LinkedList<String>(list);
					//如果不是第一次點選
					if (pidList.contains(pid)) {
						//移除原來的,把這次放在首位
						pidList.remove(pid);
						pidList.addFirst(pid);
					}else {
						pidList.addFirst(pid);
					}
					if (pidList.size()>5) {
						pidList.subList(5, pidList.size()).clear();
					}
					pids=StringUtils.join(pidList,"!");
				}
			}
		}
	
		Cookie cookie=new Cookie("pids", pids);
		response.addCookie(cookie);
顯示瀏覽記錄
List<Product> list2=new ArrayList<Product>();
		Cookie[] cookies=request.getCookies();
		if (cookies!=null) {
			for (Cookie cookie : cookies) {
				if (cookie.getName().equals("pids")) {
					String pid[]=cookie.getValue().split("!");
					for (String string : pid) {
						
						Product p=ss.getProduct(string);
						list2.add(p);
					}
				}
			}
		}
		request.setAttribute("list2", list2);

7.購物車

由於資料庫中沒有購物車表,所以我們將購物車內的商品資訊儲存在session作用域中,為了更方便操作,我們需要對購物車進行封裝,建立cart類和cartitem類,cart類中有HashMap<String,CartItem> cartItems和總計,cartitem類種有商品物件,數量和小計。

加入購物車

String pid=request.getParameter("pid");
		int buyNum=Integer.parseInt(request.getParameter("buyNum"));
		Product product=ss.getProduct(pid);
		
		Cart cart=(Cart) request.getSession().getAttribute("cart");
		//如果cart為空,初始化cart
		if (cart==null) {
			cart=new Cart();
		}
		//判斷cart中有沒有當前商品
		if (cart.getCartItems().containsKey(pid)) {
			//如果有更新數量和小計
			CartItem c=cart.getCartItems().get(pid);
			c.setBuyNum(c.getBuyNum()+buyNum);
			c.setSubTotal(c.getSubTotal()+product.getShop_price()*buyNum);
			cart.setTotal(cart.getTotal()+product.getShop_price()*buyNum);
		}else {
			//如果沒有,將商品加入購物車
			CartItem cartItem=new CartItem();
			cartItem.setProduct(product);
			cartItem.setBuyNum(buyNum);
			cartItem.setSubTotal(product.getShop_price()*buyNum);
			cart.getCartItems().put(pid, cartItem);
			cart.setTotal(cart.getTotal()+product.getShop_price()*buyNum);
		}
		request.getSession().setAttribute("cart", cart);

刪除購物車內某個商品

String pid=request.getParameter("pid");
		int buyNum=Integer.parseInt(request.getParameter("buyNum"));
		Product product=ss.getProduct(pid);
		Cart cart=(Cart) request.getSession().getAttribute("cart");
		HashMap<String, CartItem> m=cart.getCartItems();
		m.remove(pid);
		cart.setCartItems(m);
		cart.setTotal(cart.getTotal()-product.getShop_price()*buyNum);
		request.getSession().setAttribute("cart", cart);

修改某個商品的數量,前臺用到了ajax,用每個商品id給數量input標籤的id賦值,用來判斷修改的是哪個商品

String pid=request.getParameter("pid");
		int buyNum=1;
		if (!request.getParameter("buyNum").equals("") ){
			buyNum=Integer.parseInt(request.getParameter("buyNum"));
		}
		
		if (buyNum<=0) {
			buyNum=1;
		}
		Product product=ss.getProduct(pid);
		Cart cart=(Cart) request.getSession().getAttribute("cart");
		HashMap<String, CartItem> m=cart.getCartItems();
		CartItem item=m.get(pid);
		//獲得原來的數量
		int num=item.getBuyNum();
		//設定新的小計
		item.setSubTotal(product.getShop_price()*buyNum);
		item.setBuyNum(buyNum);
		m.put(pid, item);
		
		//設定新的總價
		cart.setTotal(cart.getTotal()-product.getShop_price()*num+product.getShop_price()*buyNum);
		
		cart.setCartItems(m);
		
		request.getSession().setAttribute("cart", cart);
		
		//小計
		double subTotal=product.getShop_price()*buyNum;
		//總價
		
		double total=cart.getTotal();
		double[] d=new double[2];
		d[0]=subTotal;
		d[1]=total;
		String jsona="";
		Gson gson=new Gson();
		jsona=gson.toJson(d);
		response.getWriter().println(jsona);
清空購物車

從session域中清除cart即可。

8.提交訂單
點選訂單提交後,把訂單資訊存到order表中,來到提交訂單頁面,輸入收貨人,地址,電話並選擇支付銀行後點擊確認訂單,首先對資料庫order表中的資料進行修改,之後付款,這裡用到了易寶支付,匯入相應的jar包

servlet程式碼
	Map<String, String[]> map=request.getParameterMap();
		Orders orders=new Orders();
		BeanUtils.populate(orders, map);
		//更新資料庫
		os.updateOrders(orders);
		
		//跳轉到第三方支付頁面
		//獲得支付所需資料
		String oid=request.getParameter("oid");
		String money="0.01";//支付金額
		//銀行
		String pd_FrpId=request.getParameter("pd_FrpId");
		// 發給支付公司需要哪些資料
				String p0_Cmd = "Buy";
				String p1_MerId = ResourceBundle.getBundle("merchantInfo").getString("p1_MerId");
				String p2_Order = oid;
				String p3_Amt = money;
				String p4_Cur = "CNY";
				String p5_Pid = "";
				String p6_Pcat = "";
				String p7_Pdesc = "";
				// 支付成功回撥地址 ---- 第三方支付公司會訪問、使用者訪問
				// 第三方支付可以訪問網址
				String p8_Url = ResourceBundle.getBundle("merchantInfo").getString("callback");
				String p9_SAF = "";
				String pa_MP = "";
				String pr_NeedResponse = "1";
				// 加密hmac 需要金鑰
				String keyValue = ResourceBundle.getBundle("merchantInfo").getString(
						"keyValue");
				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);


				String url = "https://www.yeepay.com/app-merchant-proxy/node?pd_FrpId="+pd_FrpId+
						"&p0_Cmd="+p0_Cmd+
						"&p1_MerId="+p1_MerId+
						"&p2_Order="+p2_Order+
						"&p3_Amt="+p3_Amt+
						"&p4_Cur="+p4_Cur+
						"&p5_Pid="+p5_Pid+
						"&p6_Pcat="+p6_Pcat+
						"&p7_Pdesc="+p7_Pdesc+
						"&p8_Url="+p8_Url+
						"&p9_SAF="+p9_SAF+
						"&pa_MP="+pa_MP+
						"&pr_NeedResponse="+pr_NeedResponse+
						"&hmac="+hmac;

				//重定向到第三方支付平臺
				response.sendRedirect(url);

merchantInfo.properties檔案

p1_MerId=10001126856#易寶使用者id
keyValue=cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl#祕鑰
callback=http://localhost:8080/callback#支付成功後回撥

回撥

CallbackServlet.java

package com.yinhe.web.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ResourceBundle;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.yinhe.service.OrderService;
import com.yinhe.utils.PaymentUtil;

public class CallbackServlet extends BaseServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		this.doPost(request, response);
	}

	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	
		// 獲得回撥所有資料
		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");
		String keyValue = ResourceBundle.getBundle("merchantInfo").getString(
				"keyValue");

		// 自己對上面資料進行加密 --- 比較支付公司發過來hamc
		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 OrderService();
				orderService.updateState(r6_Order);
				// 瀏覽器重定向
				response.setContentType("text/html;charset=utf-8");
				response.getWriter().println("<h1>付款成功!等待商城進一步操作!等待收貨...</h1>");
			} else if (r9_BType.equals("2")) {
				// 伺服器點對點 --- 支付公司通知你
				System.out.println("付款成功!");
				// 修改訂單狀態 為已付款
				// 回覆支付公司
				response.getWriter().print("success");
			}
		} else {
			// 資料無效
			System.out.println("資料被篡改!");
		}
	}

}
支付成功後修改訂單狀態為已付款

9.我的訂單

顯示當前使用者以購買過的訂單,從資料庫查詢即可,這裡也要進行資料封裝,和後臺管理員查詢訂單原理相同。

10.登入驗證過濾器

訂單的相關操作必須進行登入才可以,如果沒登入,則自動跳轉到登入介面

自定義過濾器Login.java

package com.yinhe.fiter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.yinhe.bean.User;

public class Login implements Filter{

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		// TODO Auto-generated method stub
		HttpServletRequest req=(HttpServletRequest) request;
		HttpServletResponse resp=(HttpServletResponse)response;
		
		User user=(User) req.getSession().getAttribute("user");
		System.out.println(user);
		if (user==null) {
			resp.sendRedirect("login.jsp");
		}else {
			
		
		chain.doFilter(request, response);
		}
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub
		
	}

}
web.xml配置,表示對訂單的相關操作必須進行登入才可以。
 <filter>
  		<filter-name>login</filter-name>
  		<filter-class>com.yinhe.fiter.Login</filter-class>
  </filter>
  <filter-mapping>
  		<filter-name>login</filter-name>
  		<url-pattern>/ordersservlet</url-pattern>
  </filter-mapping>

到此這個專案的所有功能都結束了,溫故而知新。