首页 > 代码库 > 如何在微信中接入支付宝支付

如何在微信中接入支付宝支付

前提:需要一台nginx服务器做反向代理

前言:支付宝支付手机支付一共分4个页面分别为1、输入手机号页面,2、输入验证码页面,3、输入支付密码页面,4、支付结果页面

1、配置nginx服务器为 https://mclient.alipay.com做反向代理,对app和支付宝做反向代理如下,要求支付宝的反向代理后的域名与app的域名为同域。

server {
    listen 80;
    server_name app.domin.com;
    access_log /var/website/app/logs/access.log;
    error_log /var/website/app/logs/error.log;

    location /app {
        proxy_pass http://xxx.xx.xxx.xxx:8080/app;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header REMOTE-HOST $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        client_max_body_size 100m;
    }
    location / {
        proxy_pass https://mclient.alipay.com/;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header REMOTE-HOST $remote_addr;
        client_max_body_size 100m;
    }
}

2、前端需要嵌套一个iframe链接支付宝的反向代理地址,看js部分,对第1、2个页面做前端域名替换因为不涉及到js问题,所以没有做处理,第3、4个页面涉及到js的调用,因为支付宝js的写法导致原本绑定的事件不能执行,第3个页面包含了【确认付款】这几个字,所以以此为判断条件,如果是第三个页面就把一个表单插入到iframe的body中,用js把页面的html提交到本文第5节的地址中去,又这个方法处理后增加一个chuliguo的标志重新返回html,使输入密码的js可以正常执行,第4步同理。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="ctx" value="${ pageContext.request.contextPath }" /> 
<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>支付</title>
    <script src="//cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>
    <style>
        .scroll-wrapper{   
          position: fixed;    
          right: 0;    
          bottom: 0;    
          left: 0;   
          top: 0;   
          -webkit-overflow-scrolling: touch;   
          overflow-y: scroll;   
        }   
           
        .scroll-wrapper {   
          height: 100%;   
          width: 100%;   
              border: none;
        }   
        </style>
</head>
<body>
<iframe class="scroll-wrapper" src="${ ctx }/alipay/pay?id=${ id }&type=${ type }">
    
</iframe>
<script>

    var form = "<form id=‘sbform‘ action=‘${ ctx }/alipay/rerender‘ method=‘post‘><input type=‘hidden‘ id=‘submit_html‘ value=http://www.mamicode.com/‘‘ name=‘html‘>";

    function buildRegex() {
        var op = "g";
        return new RegExp("https://mclient.alipay.com", op);
    }


    $(".scroll-wrapper").get(0).onload = function(){
        
        var docuemnt = $("iframe").get(0).contentWindow.document;
        var html = $(docuemnt).find("html").html();
        
        if(html.indexOf("确认付款") > 0 ){            
            if(html.indexOf("chuliguo") < 0){
                $(docuemnt).find("html").find(body).append($(form));
                $(docuemnt).find("html").find(body).find(#sbform).find(#submit_html).val($(docuemnt).find("html").html());
                $(docuemnt).find("html").find(body).find(#sbform).submit();
            }
            
        }else if(html.indexOf("付款结果") > 0 ){
            if(html.indexOf("chuliguo") < 0){
                
                $(docuemnt).find("html").find(body).append($(form));
                $(docuemnt).find("html").find(body).find(#sbform).find(#submit_html).val($(docuemnt).find("html").html());
                $(docuemnt).find("html").find(body).find(#sbform).submit();
                
            }else{
                location.href = $(docuemnt).find("html").find(body).find(".J-return-link").find("a").attr("href");
            }
        }else{
            html = html.replace(buildRegex(), "http://app.domin.com")
            $(docuemnt).find("html").html(html);
        }
        $("iframe").show();
    }
</script>
</body>
</html>

3、生成支付宝订单的时候把openapi的地址替换成项目中的一个action,其中urlService.getUrl返回的是http://app.domin.com/alipay/middle/

form = form.replace("https://openapi.alipay.com", urlService.getUrl("alipay", "middle", request))

4、表单提交到的本地方法如下,因为上一步中支付宝生成的表单中的地址是https://openapi.alipay.com/gateway.do,上一步替换完了就是app.domin.com/alipay/middle/gateway.do。或者上一步连gateway.do一起替换。不清楚可以此处打断点调试。此方法就是对原本的openapi.alipay的请求做一个中转,返回支付宝给的表单html。这一步不能直接对openapi域名反向代理,因为提交以后支付宝端直接跳转到mclient地址,没有替换域名的机会。此处把mclient.alipay.com替换成项目域名也就是app.domin.com,项目域名根目录第一节中反向代理了mclient.alipay.com

@RequestMapping(value = "http://www.mamicode.com/middle/gateway.do")
    public void middle(HttpServletRequest request,HttpServletResponse response) throws IOException{
        String queryString = request.getQueryString();
        String biz_content = request.getParameter("biz_content");
        Map<String, String> param = new HashMap<>();
        param.put("biz_content", biz_content);
        String res = HttpUtil.http("https://openapi.alipay.com/gateway.do?" + queryString, param,null);
        res = res.replaceAll("https://mclient.alipay.com", urlService.serverPath(request, ""));
        response.getWriter().write(res);
    }

5、后台需要一个重新渲染支付宝html的方法,把支付宝的地址换成我们反向代理支付宝的地址 ,此代码在输完手机号验证码输入支付密码的页面调用见第2节的说明,因为有的步骤是前台做html中域名替换,导致这一步输入不了密码。处理完成后拼接一个chuliguo的input作为前台判断的标志,防止循环重载此页面。可结合前台代码一起理解这一步的作用。

@RequestMapping(value = "http://www.mamicode.com/rerender")
    public void rerender(HttpServletRequest request,HttpServletResponse response) throws IOException{
        String html = request.getParameter("html");
        html = html.replaceAll("https://mclient.alipay.com", "http://app.domin.com");
        html += "<input type=‘hidden‘ value=http://www.mamicode.com/‘chuliguo‘>";
        response.setHeader("X-XSS-Protection", "0");
        
        response.getWriter().write(html);
    }

 

如何在微信中接入支付宝支付