package com.cn.servlet; // 定义Servlet所在的包名

import java.io.IOException; // 导入IOException，用于处理输入输出异常
import java.util.Date; // 导入Date类，用于处理日期

import javax.servlet.ServletException; // 导入ServletException，用于处理Servlet运行时的异常
import javax.servlet.http.HttpServlet; // 导入HttpServlet，是所有HTTP servlet的父类
import javax.servlet.http.HttpServletRequest; // 导入HttpServletRequest，代表客户端的请求信息
import javax.servlet.http.HttpServletResponse; // 导入HttpServletResponse，代表服务器对客户端的响应

import com.alipay.api.AlipayApiException; // 导入AlipayApiException，用于处理支付宝API异常
import com.alipay.api.AlipayClient; // 导入AlipayClient，支付宝API客户端
import com.alipay.api.DefaultAlipayClient; // 导入DefaultAlipayClient，支付宝API客户端默认实现
import com.alipay.api.request.AlipayTradePagePayRequest; // 导入AlipayTradePagePayRequest，支付宝电脑网站支付请求
import com.cn.domain.Prep; // 导入Prep类，该类定义了订单的数据结构

/**
 * AlipayServlet类，用于处理支付宝支付接口的请求。
 * @ClassName: AlipayServlet 类名：AlipayServlet
 * @Description: 支付宝支付接口，PC端
 * @author: ljy Servlet的作者
 * @date: 2019年11月14日 上午1:10:23 Servlet创建的日期和时间
 */
public class AlipayServlet extends HttpServlet {
	private static final long serialVersionUID = 1L; // 用于序列化

    /**
     * 默认构造函数。
     */
    public AlipayServlet() {
        super(); // 调用父类的构造函数
        // TODO Auto-generated constructor stub
    }

	/**
	 * 处理GET请求的方法。
	 * @param request HttpServletRequest对象，包含客户端的请求信息
	 * @param response HttpServletResponse对象，包含服务器对客户端的响应信息
	 * @throws ServletException 抛出Servlet异常
	 * @throws IOException 抛出输入输出异常
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 支付宝网关地址，沙箱环境和外网真实环境使用不同的URL
		String URL = "https://openapi.alipaydev.com/gateway.do"; 	// 沙箱环境使用
		//String URL = "https://openapi.alipay.com/gateway.do";  	// 外网真实环境使用
		String APP_ID = "2016101400683589";  // 支付宝分配给开发者的应用ID
		String APP_PRIVATE_KEY = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQ..."; // 开发者私钥，由开发者自己生成
		String FORMAT = "json"; // 参数返回格式，只支持 json
		String CHARSET = "UTF-8"; // 编码集，支持 GBK/UTF-8
		String ALIPAY_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvjme..."; // 支付宝公钥，由支付宝生成
		String SIGN_TYPE = "RSA2"; // 商户生成签名字符串所使用的签名算法类型，目前支持 RSA2 和 RSA，推荐使用 RSA2

		// 从PayServlet获取的订单信息
		Prep prep = (Prep) request.getAttribute("prep"); // 从请求中获取订单对象
		
		// 构造商户订单号，确保唯一性
		String out_trade_no = String.valueOf(new Date()) + String.valueOf(prep.getPrepId());  
		String total_amount = String.valueOf(prep.getPrice())+".00";  // 付款金额，必填
		String subject = prep.getStartStation()+"站 - "+prep.getEndStation() + "站    火车票";  // 商品名称
		// 回跳地址，用户支付完成后跳转的地址
		String returnUrl = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+"/ticketing/PayServlet?temp=1&prepId="+prep.getPrepId()+"";
		
		// 初始化AlipayClient
		AlipayClient alipayClient = new DefaultAlipayClient(URL, APP_ID, APP_PRIVATE_KEY, FORMAT, CHARSET, ALIPAY_PUBLIC_KEY, SIGN_TYPE);
		// 创建支付请求
		AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
		alipayRequest.setReturnUrl(returnUrl); // 设置回跳地址
		alipayRequest.setNotifyUrl("http://domain.com/CallBack/notify_url.jsp"); // 设置异步通知地址
		// 填充业务参数
		alipayRequest.setBizContent("{" + 
				"    \"out_trade_no\":\""+out_trade_no+"\"," +
				"    \"product_code\":\"FAST_INSTANT_TRADE_PAY\"," + 
				"    \"total_amount\":"+total_amount+"," +
				"    \"subject\":\""+subject+"\"," + 
				"    \"body\":\""+subject+"\"," +
				"    \"passback_params\":\"merchantBizType%3d3C%26merchantBizNo%3d2016010101111\"," +
				"    \"extend_params\":{" + 
				"    \"sys_service_provider_id\":\"2088511833207846\"" + 
				"    }" + 
				"  }");// 填充业务参数
		
		String form = ""; // 用于存放生成的表单HTML代码
		try {
			form = alipayClient.pageExecute(alipayRequest).getBody(); // 调用SDK生成表单
		} catch (AlipayApiException e) {
			e.printStackTrace(); // 异常处理
		}
		
		// 设置响应内容类型
		response.setContentType("text/html;charset=" + CHARSET);
		// 输出表单HTML代码到页面
		response.getWriter().write(form);
		// 刷新和关闭PrintWriter
		response.getWriter().flush();
		response.getWriter().close();
	}

	/**
	 * 处理POST请求的方法，此实现中直接调用doGet方法。
	 * @param request HttpServletRequest对象，包含客户端的请求信息
	 * @param response HttpServletResponse对象，包含服务器对客户端的响应信息
	 * @throws ServletException 抛出Servlet异常
	 * @throws IOException 抛出输入输出异常
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response); // 直接调用doGet方法处理
	}

}