package com.ssbusy.controller.alipay;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.broadleafcommerce.core.checkout.service.exception.CheckoutException;
import org.broadleafcommerce.core.order.domain.Order;
import org.broadleafcommerce.core.order.service.OrderService;
import org.broadleafcommerce.core.order.service.type.OrderStatus;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alipay.config.AlipayConfig;
import com.alipay.util.AlipayNotify;
import com.alipay.util.AlipaySubmit;
import com.ssbusy.controller.checkout.CheckoutController;
import com.ssbusy.site.myshippingform.MyBillingInfoForm;
/**
* 支付宝即时到帐
*
* @author Ju
*/
@Controller
public class AlipayDirectPayController implements InitializingBean {
private static final String RETURN_INFO_KEY = "return_info";
private final static Log LOG = LogFactory
.getLog(AlipayDirectPayController.class);
/**
* 支付类型
*/
private final String payment_type = "1";
/**
* 必填,不能修改 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数
*/
private final static String notify_url = "/extern/alipay/notify_url";
/**
* 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,不能写成http://localhost/
*/
private final static String return_url = "/extern/alipay/return_url";
/**
* 卖家支付宝帐户
*/
@Value("${alipay.clientId}")
private String seller_email = "onxiao@gmail.com";
@Value("${alipay.partner}")
private String partner;
@Value("${alipay.key}")
private String key;
@Resource(name = "checkoutController")
private CheckoutController checkoutController;
@Resource(name = "blOrderService")
protected OrderService orderService;
@Override
public void afterPropertiesSet() throws Exception {
AlipayConfig.partner = partner;
AlipayConfig.key = key;
}
/**
*
* @param tradeNo
* 商户网站订单系统中唯一订单号,必填
* @param subject
* 订单名称 必填
* @param description
* 订单描述
* @param tradeUrl
* 商品展示地址 需以http://开头的完整路径,例如:http://www.xxx.com/myorder.html
* @param totalFee
* 付款金额 必填
* @return 直接返回response body整个内容
* @throws IOException
*/
@RequestMapping("/alipay/direct_pay")
public void requestDirectPay(HttpServletResponse resp,
@RequestParam("tradeNo") String tradeNo,
@RequestParam("subject") String subject,
@RequestParam("description") String description,
@RequestParam("tradeUrl") String tradeUrl,
@RequestParam("totalFee") BigDecimal totalFee) throws IOException {
// 把请求参数打包成数组
Map<String, String> sParaTemp = new HashMap<String, String>(14);
sParaTemp.put("service", "create_direct_pay_by_user");
sParaTemp.put("partner", AlipayConfig.partner);
sParaTemp.put("_input_charset", AlipayConfig.input_charset);
sParaTemp.put("payment_type", payment_type);
sParaTemp.put("notify_url", "http://www.onxiao.com" + notify_url);
sParaTemp.put("return_url", "http://www.onxiao.com" + return_url);
sParaTemp.put("seller_email", seller_email);
sParaTemp.put("out_trade_no", tradeNo);
sParaTemp.put("subject", subject);
sParaTemp.put("total_fee", totalFee.toPlainString());
sParaTemp.put("body", description);
sParaTemp.put("show_url", tradeUrl);
// TODO 防钓鱼时间戳
String anti_phishing_key = "";
// 若要使用请调用类文件submit中的query_timestamp函数
sParaTemp.put("anti_phishing_key", anti_phishing_key);
// TODO 客户端的IP地址
String exter_invoke_ip = "";
// 非局域网的外网IP地址,如:221.0.0.1
sParaTemp.put("exter_invoke_ip", exter_invoke_ip);
// 直接返回页面内容
resp.setContentType("text/html");
String html = AlipaySubmit.buildRequest(sParaTemp, "get", "确认");
PrintWriter writer = resp.getWriter();
try {
writer.print(html);
writer.flush();
} finally {
writer.close();
}
}
/**
* 支付宝服务器异步通知页面
*
* @param request
* @param shopTradeNo
* 商户订单号
* @param alipayTradeNo
* @param tradeStatus
* 交易状态
* @throws CheckoutException
*/
@RequestMapping(notify_url)
@ResponseBody
public String notifyPayed(
Model model,
HttpServletRequest request,
HttpServletResponse response, MyBillingInfoForm billingForm,
BindingResult result,
@RequestParam(required = false, value = "out_trade_no") String shopTradeNo,
@RequestParam(required = false, value = "trade_no") String alipayTradeNo,
@RequestParam(required = false, value = "trade_status") String tradeStatus,
@RequestParam(required = false, value = "total_fee") String totalFee)
throws CheckoutException {
LOG.info("=============================================");
LOG.info("alipay notifyPayed");
LOG.info(" shopTradeNo(orderNum) is " + shopTradeNo
+ ", alipayTradeNo(alipay) is " + alipayTradeNo);
LOG.info("tradeStatus is " + tradeStatus + ", totalFee is " + totalFee
+ ";");
paymentCallback(model, request, response, billingForm, result, shopTradeNo,
alipayTradeNo, tradeStatus, totalFee);
LOG.warn("alipay notifyPayed over,But it is not back to our checkoutController");
return (String) request.getAttribute(RETURN_INFO_KEY);
}
/**
* 支付宝页面跳转同步通知页面
*
* @param model
* @param request
* @param shopTradeNo
* @param alipayTradeNo
* @param tradeStatus
* @throws CheckoutException
*/
@RequestMapping(return_url)
public String returnPayed(Model model, HttpServletRequest request,
HttpServletResponse response, MyBillingInfoForm billingForm, BindingResult result,
@RequestParam("out_trade_no") String shopTradeNo,
@RequestParam("trade_no") String alipayTradeNo,
@RequestParam("trade_status") String tradeStatus,
@RequestParam("total_fee") String totalFee)
throws CheckoutException {
LOG.info("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
LOG.info("alipay returnPayed");
LOG.info(" shopTradeNo(orderNum) is " + shopTradeNo
+ ", alipayTradeNo(alipay) is " + alipayTradeNo);
LOG.info("tradeStatus is " + tradeStatus + ", totalFee is " + totalFee
+ ";");
Long orderId;
try {
orderId = Long.parseLong(shopTradeNo.substring(12));
} catch (NumberFormatException e) {
LOG.error("substring orderNum throws an exception" + shopTradeNo, e);
return "redirect:/checkout";
}
Order cart = orderService.findOrderById(orderId);
if(cart!=null&& OrderStatus.SUBMITTED.equals(cart.getStatus())){
return "redirect:/confirmation/"+cart.getOrderNumber();
}
return paymentCallback(model, request, response, billingForm, result, shopTradeNo,
alipayTradeNo, tradeStatus, totalFee);
}
@SuppressWarnings("rawtypes")
private String paymentCallback(Model model, HttpServletRequest request,
HttpServletResponse response, MyBillingInfoForm billingForm, BindingResult result,
String shopTradeNo, String alipayTradeNo, String tradeStatus,
String totalFee) throws CheckoutException {
String retutn_message = "";
// 获取支付宝POST过来反馈信息
Map requestParams = request.getParameterMap();
Map<String, String> params = new HashMap<String, String>(
requestParams.size());
StringBuilder sb = new StringBuilder();
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
sb.setLength(0);
String name = (String) iter.next();
String[] values = (String[]) requestParams.get(name);
for (int i = 0; i < values.length; i++) {
sb.append(values[i]).append(',');
}
// 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
params.put(name,
values.length > 0 ? sb.substring(0, sb.length() - 1) : "");
}
LOG.info("alipay paymentCallback:");
if (AlipayNotify.verify(params)) {// 验证成功
if ("TRADE_FINISHED".equals(tradeStatus)
|| "TRADE_SUCCESS".equals(tradeStatus)) {
LOG.info("TradeStatus is :" + tradeStatus + " Trade Fee is "
+ totalFee);
retutn_message = "success";
} else {
LOG.info("TradeStatus is :" + tradeStatus + " Trade Fee is "
+ totalFee);
retutn_message = "failed";
}
} else {// 验证失败
LOG.info("AlipayNotify.verify(params) is false");
// model.addAttribute("erorr", "invalid");
// model.addAttribute("returnInfo", "failed");
retutn_message = "failed";
}
request.setAttribute(RETURN_INFO_KEY, retutn_message);
LOG.info("use our alipayCheckout");
return checkoutController.alipayCheckout(request,
response, model, billingForm, result,
shopTradeNo, retutn_message, totalFee);
}
}