/** * */ package jframe.pay.alipay.service; import java.net.URL; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alipay.util.OrderUtil; import jframe.core.plugin.annotation.InjectPlugin; import jframe.core.plugin.annotation.InjectService; import jframe.core.plugin.annotation.Injector; import jframe.core.plugin.annotation.Start; import jframe.core.plugin.annotation.Stop; import jframe.httpclient.service.HttpClientService; import jframe.pay.alipay.AlipayConfig; import jframe.pay.alipay.AlipayPlugin; import jframe.pay.alipay.domain.TradeStatus; import jframe.pay.dao.service.PayDaoService; import jframe.pay.domain.Fields; import jframe.pay.domain.PayCurrency; import jframe.pay.domain.PayStatus; import jframe.pay.domain.TransType; import jframe.pay.domain.dao.OrderAlipay; import jframe.pay.domain.http.RspCode; import jframe.pay.domain.util.HttpUtil; import jframe.pay.domain.util.IDUtil; import jframe.pay.domain.util.ObjectUtil; /** * @author dzh * @date Nov 26, 2014 4:39:26 PM * @since 1.0 */ @Injector class AlipayServiceImpl implements AlipayService, Fields { static Logger LOG = LoggerFactory.getLogger(AlipayServiceImpl.class); @InjectService(id = "jframe.pay.service.dao") static PayDaoService PayDao; @InjectPlugin static AlipayPlugin Plugin; @InjectService(id = "jframe.service.httpclient") static HttpClientService HttpClient; static Map<String, String> HTTP_PARAS = new HashMap<String, String>(1, 1); static { HTTP_PARAS.put(HttpClientService.P_MIMETYPE, "application/x-www-form-urlencoded"); // HTTP_PARAS.put(HttpClientService.P_METHOD, "post"); } @Start public void start() { try { AlipayConfig.GroupID = Plugin.getConfig("groupid.alipay", AlipayConfig.GroupID); AlipayConfig.init(Plugin.getConfig("file.alipay")); } catch (Exception e) { LOG.error("Load alipay error {}", e.getMessage()); } } @Stop public void stop() { } @Override public void pay(Map<String, String> req, Map<String, Object> rsp) throws Exception { // check req if (HttpUtil.mustReq(req, F_payType, F_payGroup, F_payNo, F_transType, F_payAmount, F_payDesc).size() > 0) { RspCode.setRspCode(rsp, RspCode.FAIL_HTTP_MISS_PARA); return; } if (PayDao == null) { RspCode.setRspCode(rsp, RspCode.FAIL_DB_Conn); return; } Optional<OrderAlipay> od = Optional.ofNullable(PayDao.selectOrderAlipay(req.get(F_payNo))); if (od.isPresent()) { payUpdate(od.get(), req, rsp); } else { payNew(req, rsp); } } private void payNew(Map<String, String> req, Map<String, Object> rsp) { OrderAlipay od = new OrderAlipay(); if (req.containsKey(F_account)) od.account = req.get(F_account); od.backUrl = req.get(F_backUrl); od.orderCreateTime = new Date().getTime(); od.orderNo = IDUtil.genOrderNo(); od.payAmount = Long.parseLong(req.getOrDefault(F_payAmount, "0")); od.payCurrency = req.getOrDefault(F_payCurrency, PayCurrency.CNY.code); od.payDesc = req.getOrDefault(F_payDesc, ""); od.payGroup = req.getOrDefault(F_payGroup, ""); od.payNo = req.get(F_payNo); od.payTimeout = new Date().getTime() + 3600 * 1000; od.transType = TransType.Consume.code; req.put(F_orderNo, od.orderNo); if (od.payAmount > 0) { od.payStatus = PayStatus.C_PAY_WAIT.code; } else { od.orderFinishTime = new Date().getTime(); od.payStatus = PayStatus.C_PAY_SUC.code; PayDao.insertOrderAlipay(od); return; } // insert order PayDao.insertOrderAlipay(od); // pay info String odinfo = OrderUtil.buildOrderInfo(req); rsp.put(F_od, OrderUtil.genPayInfo(odinfo)); // Map<String, String> map = new HashMap<>(); // map.put("out_trade_no", req.get(F_orderNo)); // insert task TODO // Task t = createTask(TaskType.ALI_QUERY_C_PAY.type, // TaskType.ALI_QUERY_C_PAY.desc, JsonUtil.encode(map), // new Date().getTime()); // TaskDao.insertTask_Order(conn, t); } private void payUpdate(OrderAlipay od, Map<String, String> req, Map<String, Object> rsp) { if (HttpUtil.anyEq(od.payStatus, PayStatus.C_PAY_SUC.code, PayStatus.C_PAY_TIMEOUT.code)) { RspCode.setRspCode(rsp, RspCode.FAIL_ORDER_STATUS); return; } od.backUrl = req.get(F_backUrl); od.orderNo = IDUtil.genOrderNo(); od.payAmount = Long.parseLong(req.getOrDefault(F_payAmount, "0")); od.payCurrency = req.getOrDefault(F_payCurrency, PayCurrency.CNY.code); od.payDesc = req.getOrDefault(F_payDesc, ""); od.payGroup = req.getOrDefault(F_payGroup, ""); od.payNo = req.get(F_payNo); od.payTimeout = new Date().getTime() + 3600 * 1000; od.transType = TransType.Consume.code; req.put(F_orderNo, od.orderNo); if (od.payAmount > 0) { od.payStatus = PayStatus.C_PAY_WAIT.code; } else { od.orderFinishTime = new Date().getTime(); od.payStatus = PayStatus.C_PAY_SUC.code; PayDao.updateOrderAlipay(od); return; } PayDao.updateOrderAlipay(od); // pay info String odinfo = OrderUtil.buildOrderInfo(req); if (LOG.isDebugEnabled()) { LOG.debug("odinfo -> {}", odinfo); } rsp.put(F_od, OrderUtil.genPayInfo(odinfo)); // Map<String, String> map = new HashMap<>(); // map.put("out_trade_no", req.get(F_orderNo)); // insert task TODO } @Override public void payBack(Map<String, String> req, Map<String, Object> rsp) throws Exception { // String out_trade_no = req.get("out_trade_no"); // 支付宝交易号 // String trade_no = req.get("trade_no"); // 交易状态 String trade_status = req.get("trade_status"); // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)// // if (AlipayNotify.verify(req)) {// 验证成功 // Test Code /* * LOG.info("支付宝验签请求:"+JSON.toJSONString(req)); if * (AlipayNotify.verify(req)) { LOG.info("支付宝验签成功"); }else{ * LOG.info("支付宝验签失败"); } */ if (true) { if (trade_status.equals(TradeStatus.TRADE_FINISHED)) { // 判断该笔订单是否在商户网站中已经做过处理 // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 // 如果有做过处理,不执行商户的业务程序 // 注意: // 该种交易状态只在两种情况下出现 // 1、开通了普通即时到账,买家付款成功后。 // 2、开通了高级即时到账,从该笔交易成功时间算起,过了签约时的可退款时限(如:三个月以内可退款、一年以内可退款等)后。 doSuccess(req, rsp); } else if (trade_status.equals(TradeStatus.TRADE_SUCCESS)) { // 判断该笔订单是否在商户网站中已经做过处理 // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序 // 如果有做过处理,不执行商户的业务程序 // 注意: // 该种交易状态只在一种情况下出现——开通了高级即时到账,买家付款成功后。 doSuccess(req, rsp); } else if (trade_status.equals(TradeStatus.WAIT_BUYER_PAY)) { // 交易创建 // doWaitPay(req, resp); } else { RspCode.setRspCode(rsp, RspCode.FAIL_ALIPAY_BACK_UNKOWN_STATUS_ERROR); } return; } RspCode.setRspCode(rsp, RspCode.FAIL_ALIPAY_BACK_SIGN_ERROR); } private void doWaitPay(Map<String, String> req, Map<String, Object> rsp) throws Exception { String orderNo = req.get("out_trade_no"); OrderAlipay od = PayDao.selectOrderAlipayWithOrderNo(req.get("out_trade_no")); if (od == null) throw new Exception("OrderAlipay is not found, orderNo ->" + orderNo); if (PayStatus.C_PAY_PROC.code.equals(od.payStatus)) { RspCode.setRspCode(rsp, RspCode.SUCCESS); return; } // update order od.payStatus = PayStatus.C_PAY_PROC.code; PayDao.updateOrderAlipay(od); // insert flowid // String prevFlowId = order.getOrderFlowId(); // String flowId = IDUtil.genFlowId(); // req.put(UsrFields.F_payNo, order.getPayNo()); // req.put(UsrFields.F_orderStatus, orderStatus); // OrderDao.insertOrderFlow(conn, req, flowId, prevFlowId); // AlipayDao.updateOrder_Back(conn, req, orderStatus, "", flowId); } private void doSuccess(Map<String, String> req, Map<String, Object> rsp) throws Exception { String orderNo = req.get("out_trade_no"); OrderAlipay od = PayDao.selectOrderAlipayWithOrderNo(orderNo); if (od == null) throw new Exception("OrderAlipay is not found, orderNo ->" + orderNo); if (PayStatus.C_PAY_SUC.code.equals(od.payStatus)) { RspCode.setRspCode(rsp, RspCode.SUCCESS); return; } // TODO od.payStatus = PayStatus.C_PAY_SUC.code; od.notifyId = req.get("notify_id"); od.notifyType = req.get("notify_type"); od.tradeStatus = req.get("trade_status"); od.subject = req.get("subject"); od.sellerId = req.get("seller_id"); od.sellerEmail = req.get("seller_email"); od.buyerId = req.get("buyer_id"); od.buyerEmail = req.get("buyer_email"); od.orderFinishTime = new Date().getTime(); od.notifyTime = od.orderFinishTime; PayDao.updateOrderAlipay(od); // insert flowid // String prevFlowId = order.getOrderFlowId(); // String flowId = IDUtil.genFlowId(); // req.put(UsrFields.F_payNo, order.getPayNo()); // req.put(UsrFields.F_orderStatus, orderStatus); // OrderDao.insertOrderFlow(conn, req, flowId, prevFlowId); // String accmount_flowId = null; // insert amount // accmount_flowId = OrderDao.opAccount(conn, order, "alpay"); // update order // AlipayDao.updateOrder_Back(conn, req, orderStatus, accmount_flowId, // flowId); // resp.put(UsrFields.F_respCode, URespCode.SUCCESS.code); if (ObjectUtil.notEmpty(od.backUrl)) { postBack(od); } } /** * TODO * * @param usrid * @param accountid * @return */ public boolean accountExist(String usrid, String accountid) { // MemcachedService memSvc = this.getMemSvc(); // if (memSvc != null) { // Object acc = memSvc.get(ServiceConstants.Key_Account_Prefix // + accountid); // if (acc != null) // return true; // } // AccountService accountServlet = new AccountService(); // Connection conn = null; // try { // conn = _dsSvc.getConnection(); // Account account = accountServlet.getAmountByUserAndId(conn, usrid, // accountid); // if (account != null) { // // if (memSvc != null) { // // memSvc.set(ServiceConstants.Key_Account_Prefix + accountid, // // JsonUtil.toJson(account), // // new Date(12 * 3600 * 1000)); // // } // return true; // } // } catch (Exception e) { // LOG.error(e.getMessage()); // } finally { // if (conn != null && _dsSvc != null) { // try { // _dsSvc.recycleConnection(conn); // } catch (SQLException e) { // } // } // } return true; } public void postBack(OrderAlipay order) { Map<String, String> map = new HashMap<String, String>(); map.put(F_payNo, order.payNo); map.put(F_payStatus, order.payStatus); boolean succ = false; try { URL url = new URL(order.backUrl); int port = url.getPort() == -1 ? 80 : url.getPort(); if (LOG.isDebugEnabled()) LOG.debug("postBack start time->{},req->{}", new Date(), map); Long backtime = System.currentTimeMillis(); Map<String, String> paras = new HashMap<>(HTTP_PARAS); paras.put("ip", url.getHost()); paras.put("port", String.valueOf(port)); Map<String, String> rsp = HttpClient.<HashMap<String, String>> send("payback", url.getPath(), HttpUtil.format(map, "utf-8"), null, paras); if (LOG.isDebugEnabled()) LOG.debug("postback orderNo={}, postBack->{}, use time->{}, rsp->{}", order.orderNo, url.getPath(), (System.currentTimeMillis() - backtime), rsp); if (RspCode.SUCCESS.code.equals(rsp.get(F_rspCode))) { succ = true; } else { LOG.error("payNo=" + order.payNo + "rsp=" + rsp); } } catch (Exception e) { succ = false; LOG.error(e.getMessage()); } if (!succ) { // TODO // map.put(UsrFields.F_backUrl, order.getBackUrl()); // Task t = createTask(TaskType.PAY_BACK.type, // TaskType.PAY_BACK.desc, // JsonUtil.encode(map), new Date().getTime()); // try { // AlipayDao.insertTask_Order(conn, t); // } catch (Exception e1) { // LOG.error(e1.getMessage()); // } } } // Task createTask(int type, String name, String content, long startTime) { // Task t = new TaskImpl(); // t.setType(type); // t.setStartTime(startTime); // t.setName(name); // t.setStatus(TaskStatus.START.status); // t.setContent(content); // return t; // } @Override public void clientPayBack(Map<String, String> req, Map<String, Object> rsp) throws Exception { // check req if (HttpUtil.mustReq(req, F_payNo).size() > 0) { RspCode.setRspCode(rsp, RspCode.FAIL_HTTP_MISS_PARA); return; } if (PayDao == null) { RspCode.setRspCode(rsp, RspCode.FAIL_DB_Conn); return; } OrderAlipay od = PayDao.selectOrderAlipay(req.get(F_payNo)); // req.put("out_trade_no", order.orderNo); // req.put(F_payNo, order.payNo); // req.put(F_payStatus, PayStatus.C_PAY_SUC.code); od.payStatus = req.getOrDefault(F_payStatus, PayStatus.C_PAY_SUC.code); PayDao.updateOrderAlipay(od); String accmount_flowId = null; // TODO insert amount // accmount_flowId = OrderDao.opAccount(conn, order, "alpay"); // update order // AlipayDao.updateOrder_Back(conn, req, orderStatus, accmount_flowId, // flowId); } }