电脑网站支付宝支付


前期工作准备如下:

支付宝AppId
支付宝公钥、应用公钥、私钥
这些信息可以在蚂蚁金服平台获取到,具体怎么获取可以查看搜索教程。然后配置好之后,就可以在自己的代码中进行实现.

注意这些
支付流程为 :
1.支付宝支付
2.异步回调
3.同步回调 不能返回JSON格式
这里应该会问 “异步回调” 和 “同步回调” 的区别,用白话来讲

异步回调: 其实是处理业务逻辑,比如说修改客户的支付状态
 同步回调: 用户在支付宝页面付款完毕后自动跳转

代码中需要在配置类中引入,自己生成的公私钥

这一步中生成的公钥和私钥,私钥自己一定要保存好,要配置到 AlipayConfig 配置类中

支付宝异步如何返回success 支付宝异步回调怎么写_支付宝异步如何返回success


把生成的公钥配置支付宝平台上,会自动带有 应用公钥支付宝公钥

AlipayConfig 实体类中:配置为支付宝公钥 私钥就是生成唯一的一个私钥

支付宝异步如何返回success 支付宝异步回调怎么写_java_02


下面上代码

<dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-easysdk</artifactId>
            <version>2.1.2</version>
        </dependency>
@Configuration
public class AlipayConfig {
    // 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号,开发时使用沙箱提供的APPID,生产环境改成自己的APPID
    public static String app_id="2021002104675003";

    //私钥,您的PKCS8格式RSA2私钥
    public static String merchant_private_key = "生成的私钥";
    
    //查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
    public static String alipay_public_key = "支付宝公钥,支付宝公钥,支付宝公钥";
    
    // 服务器异步通知页面路径  需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问(可以使用natapp内容穿透完成外网设置)
    public static String notify_url="http://XXX/dev/member/v1/aliPayCallBack";
    
    //页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
    public static String return_url="http://XXX/return/v1/returnUrl";

    //签名方式
    public static String sign_type="RSA2";

    //字符编码格式
    public static String charset="utf-8";

    //支付宝网关
    public static String gatewayUrl="https://openapi.alipay.com/gateway.do";

    public static String log_path = "E:\\";

    /**
     * 写日志,方便测试(看网站需求,也可以改成把记录存入数据库)
     * @param sWord 要写入日志里的文本内容
     */
    public static void logResult(String sWord) {
        FileWriter writer = null;
        try {
            writer = new FileWriter(log_path + "alipay_log_" + System.currentTimeMillis()+".txt");
            writer.write(sWord);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

入参实体类,注意必填项

@Data
public class AliPayReq {
    /**
     * 商户订单号,必填
     */
    // private String out_trade_no;    我是在代码中生成的唯一订单编号,所以没传,注意是必填项
    /**
     * 订单名称,必填
     */
    private String subject;
    /**
     * 付款金额,必填
     */
    private String total_amount;
    /**
     * 商品描述,可空
     */
    private String body;
    /**
     * 超时时间参数
     */
   // private  String timeout_express; 在代码中进行设置的需要注意哦
    
    private String product_code="FAST_INSTANT_TRADE_PAY";

    /**
     * 这两个参数为:自己需要做业务逻辑处理,传入的参数
     */
    private Long userId;
    private Long vipInfoId;
}

支付宝支付代码, 该方法的返回值,是HTML页面,返回给前端,交给前端进行解析

/**
     * 支付宝支付
     */
    @PostMapping("/v1/alipay")
    public Object alipayLine(AliPayReq req) throws AlipayApiException {
        return CommSuccessDataResp.create(aliPayService.aliPayLine(req.getSubject(), req.getBody(), req.getTotal_amount(),req.getUserId(),req.getVipInfoId()));
    }

ServiceImpl 因为在异步回调时我需要用到自己的参数所以,使用以下方式进行封装参数,并没有使用setBizContent()这个方法进行封装发,使用setBizModel()进行封装参数,注意看代码

public Object aliPayLine(String subject, String body, String total_amount, Long userId, Long vipInfoId) throws AlipayApiException {
   		 // 创建实体类封装自己的参数
        ModelReq modelReq = new ModelReq();
        modelReq.setUserId(userId);
        modelReq.setVipInfoId(vipInfoId);
        
        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);
        // 生成订单编号
        String out_trade_no = String.valueOf(ClientTool.randomNumber());
        // 设置请求参数
        String timeout_express = "30m";
        
        AlipayTradePagePayRequest aliRequest = new AlipayTradePagePayRequest();
        // 封装参数,以及自己需要的参数 如果请求时传递了该参数,则返回给商户时会回传该参数。支付宝会在异步通知时将该参数原样返回
        AlipayTradePagePayModel model = new AlipayTradePagePayModel();
        model.setOutTradeNo(out_trade_no);
        model.setTotalAmount(total_amount);
        model.setSubject(subject);
        model.setBody(body);
        model.setTimeoutExpress(timeout_express);
        model.setProductCode("FAST_INSTANT_TRADE_PAY");
        
        // 创建转换对象,用于转换数据格式
        Gson gson = new Gson();
        // 转换为json
        String param = gson.toJson(modelReq);
        model.setPassbackParams(param);
        
        // 设置回调地址
        aliRequest.setReturnUrl(AlipayConfig.return_url);
        aliRequest.setNotifyUrl(AlipayConfig.notify_url);

        aliRequest.setBizModel(model);
//            aliRequest.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\"}");

        //请求,返回的数据由前端进行解析
        return alipayClient.pageExecute(aliRequest).getBody();
    }


 	/**
     * 获取阿里支付回调的数据拼装 验签,该方法在同步回调,异步回调时,必须要用到的
     */
    public Map<String, String> getAliParams(Map requestParams) {
        Map<String, String> params = new HashMap<String, String>();
        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);
        }
        System.out.println("============支付回调=============" + params);
        System.out.println(params.get("out_trade_no"));
        return params;
    }

这样支付功能就已经搞定,接下来要进行 异步回调 和 同步回调 的代码编写

/**
     * 异步回调
     */
    @PostMapping("/v1/aliPayCallBack")
    public Object notify_url(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //获取支付宝POST过来反馈信息
        Map<String, String> params = aliPayService.getAliParams(request.getParameterMap());
        System.out.println("回调返回值======="+params);
        
        //验证签名
        boolean flag = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, "UTF-8", "RSA2");
        
        // 创建自定义的参数对象
        ModelReq modelReq = new ModelReq();
        
        // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表
        String orderNo = request.getParameter("out_trade_no"); // 获取订单编号
        String trade_status = request.getParameter("trade_status"); // 交易状态
        System.out.println("交易状态======="+trade_status);
        
        // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表
        if (flag) {// 验证成功
            if (trade_status.equals("TRADE_SUCCESS")) {
                System.out.println("支付宝订单支付成功!");
                Gson gson = new Gson();
                
                //在支付接口中传入自己的参数
                ModelReq passBack = gson.fromJson(params.get("passback_params"), modelReq.getClass());
                
                // TODO 在这里进行自己的业务逻辑处理,修改会员状态
                memberService.openMemberSuccess(passBack.getUserId(),passBack.getVipInfoId(), "支付宝支付");
            }
            //这里通知支付宝回调成功,不然一直回调
            return "success";
        } else {
            System.out.println("签名验证不通过");
            return "failure";
        }
    }

同步回调代码,懒得更改注解,就直接创建了一个类

@Controller
@RequestMapping("/return")
public class ReturnUrlController {

    @Autowired
    private AliPayServiceImpl aliPayService;
    /**
     * 同步回调, 注意get请求
     */
    @RequestMapping("/v1/returnUrl")
    public void return_url(HttpServletRequest request, HttpServletResponse response) throws AlipayApiException {
        // 调用方法进行验签
        Map<String, String> paramsMap = aliPayService.getAliParams(request.getParameterMap());
        boolean flag = AlipaySignature.rsaCheckV1(paramsMap, AlipayConfig.alipay_public_key, "UTF-8", "RSA2");
        if(flag){
            //跳转支付成功界面
            try {
                response.sendRedirect("https://www.baidu.com");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else {
            System.out.println("flag=====验签失败");
            //跳转支付失败界面

        }
    }
}

这样就是PC端支付宝支付的完整流程和代码,如有疑问就请留言哦,代码中注释已经写清楚,注意看啊