支付宝 接口对接

项目结构 :

下单核心代码:

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.支付宝回调接口一定要是外网可以直接访问的。支付成功之后。支付宝会自动回接回调接口推送相关信息过来 。可以做一些业务处理。比如说:支付订单的检验,自己系统的业务检验。入库等

git:https://gitee.com/xxoo0_297/alipay.git

猜你喜欢

转载自www.cnblogs.com/1-Admin/p/10198070.html