项目结构 :
下单核心代码:
package com.alipay.pay.controller; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.internal.util.AlipaySignature; import com.alipay.api.request.AlipayTradePagePayRequest; import com.alipay.api.response.AlipayTradePagePayResponse; import com.alipay.demo.trade.model.builder.AlipayTradeQueryRequestBuilder; import com.alipay.demo.trade.model.result.AlipayF2FQueryResult; import com.alipay.demo.trade.service.AlipayTradeService; import com.alipay.pay.config.AlipayConfig; import com.alipay.pay.model.Order; /** * 支付宝-电脑网站支付. * 注意 下单页面可以加一个ajax轮询进行 订单查询避免长时间等待 * <p> * 电脑网站支付 https://docs.open.alipay.com/270/105898/ * * @author zhourong * @version 1.0 * @since 2018/12/27 */ @Controller @RequestMapping("/alipay/page") public class PayController { @Autowired private AlipayConfig alipayConfig;//支付宝查询接口初始化 @Autowired private AlipayClient alipayClient;//初始化 相关配置 @Autowired private AlipayTradeService tradeService; private final Logger log = LoggerFactory.getLogger(PayController.class); @GetMapping("/gotoPayPage") public void gotoPayPage(HttpServletResponse response,Order order) throws AlipayApiException, IOException { //下单 插入数据库 //一系列业务判断 //insert into order ...... //正常业务流程会把 支付接口抽出来 // 设置请求参数 AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest(); // 同步通知地址:支付成功后页面自动跳转到传值地址中 alipayRequest.setReturnUrl("http://zhouixi.free.idcfengye.com/alipay/page/returnUrl"); // 异步通知地址:支付成功生成之后会post返回订单信息详情到该地址,用于商家做业务逻辑处理 alipayRequest.setNotifyUrl("http://zhouixi.free.idcfengye.com/alipay/page/NotifyUrl"); // 商户订单号,商户网站订单系统中唯一订单号,必填 String out_trade_no = order.getOutTradeNo(); // 付款金额,必填 String total_amount = order.getTotalAmount(); // 订单名称,必填 String subject = order.getSubject(); // 商品描述,可空 String body = "用户订购商品个数:1"; // 该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。 // 该参数数值不接受小数点, 如 1.5h,可转换为 90m。 String timeout_express = "5m"; alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\"," + "\"total_amount\":\"" + total_amount + "\"," + "\"subject\":\"" + subject + "\"," + "\"body\":\"" + body + "\"," + "\"timeout_express\":\"" + timeout_express + "\"," + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}"); /** * BizContent传值模式 alipayRequest.setBizContent("{\"out_trade_no\":\""+ * out_trade_no +"\"," + "\"total_amount\":\""+ total_amount +"\"," + * "\"subject\":\""+ subject +"\"," + "\"qr_pay_mode\":\"4\"," + * "\"timeout_express\":\"1m\"," + "\"passback_params2\":\""+ passback_params2 * +"\"," + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}"); * **/ // get请求方式,返回http链接 // AlipayTradePagePayResponse respose = alipayClient.pageExecute(alipayRequest, // "get"); // post请求方式,返回from表单 AlipayTradePagePayResponse aliResponse = alipayClient.pageExecute(alipayRequest); // 打印请求信息 String html = aliResponse.getBody(); response.setContentType("text/html;charset=" + alipayConfig.getCharset()); response.getWriter().write(html); response.getWriter().flush(); response.getWriter().close(); } @RequestMapping("/returnUrl") public String returnUrl(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException, AlipayApiException { response.setContentType("text/html;charset=" + "utf-8"); boolean verifyResult = this.checkParam(request); if (verifyResult) { // 验证成功 //添加自己的业务。。。进行业务核对 // 商户订单号 String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8"); // 支付宝交易号 String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8"); // (必填) 商户订单号,通过此商户订单号查询当面付的交易状态 AlipayTradeQueryRequestBuilder builder = new AlipayTradeQueryRequestBuilder() .setOutTradeNo(out_trade_no); AlipayF2FQueryResult result = tradeService.queryTradeResult(builder); System.out.println(result.getTradeStatus()); return "success"; } else { return "fail"; } } @RequestMapping("/notifyUrl") public String NotifyUrl(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException, AlipayApiException { response.setContentType("text/html;charset=" + "utf-8"); boolean verifyResult = this.checkParam(request); if (verifyResult) { // 验证成功 //添加自己的业务。。。进行业务核对 // 商户订单号 String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8"); // 支付宝交易号 String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8"); // (必填) 商户订单号,通过此商户订单号查询当面付的交易状态 AlipayTradeQueryRequestBuilder builder = new AlipayTradeQueryRequestBuilder() .setOutTradeNo(out_trade_no); AlipayF2FQueryResult result = tradeService.queryTradeResult(builder); System.out.println(result.getTradeStatus()); return "success"; } else { return "fail"; } } /** * 校验签名 * * @param request * @return */ private boolean checkParam(HttpServletRequest request) { // https://docs.open.alipay.com/54/106370 官方文档 // 获取支付宝POST过来反馈信息 Map<String, String> params = new HashMap<>(); Map requestParams = request.getParameterMap(); for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) { String name = (String) iter.next(); String[] values = (String[]) requestParams.get(name); String valueStr = ""; for (int i = 0; i < values.length; i++) { valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ","; } params.put(name, valueStr); } try { boolean verifyResult = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPublicKey(), alipayConfig.getCharset(), alipayConfig.getSignType()); return verifyResult; } catch (AlipayApiException e) { log.debug("verify sigin error, exception is:{}", e); return false; } } }
效果:
支付只能用支付宝提供的沙箱帐号及沙箱app
不然会提示二维码过期。
问题总结:
1.AlipayTradeServiceImpl gatewayUrl should not be NULL!
支付宝查询接口 AlipayTradeServiceImpl 没有初始化
2.验签失败 :返回false
使用支付宝公钥沙箱应用里面的公钥,不能使用工具生成的公钥
3.支付过程中,一直要做订单号重复过滤。不然。支付宝生成不了二维码页面。
4.支付过程中,支付接口有自动过滤重复支付。尽量把业务处理在自己的接口里面。避免重复支付。
5.支付宝回调接口一定要是外网可以直接访问的。支付成功之后。支付宝会自动回接回调接口推送相关信息过来 。可以做一些业务处理。比如说:支付订单的检验,自己系统的业务检验。入库等