SpringBoot框架集成沙箱测试环境支付

1.蚂蚁金服账号申请及其配置

蚂蚁金服官网:https://open.alipay.com/platform/home.htm

支付包账号登录就好,然后正常注册就可以

注册完成后会跳到一个页面,选择研发服务

沙箱应用:要设置一个应用公钥

用到一个工具叫RSA签名验签工具windows版本的,这个网上一搜全是,也可以找我要,QQ:3367273643

然后打开是这样子的,我们启动这个bat文件

他会弹出一个东西,直接点击生成密钥就可以了

只用公钥,粘贴复制到网上的设置应用公钥,两个都设置。我这里之前已经粘过了,所以没粘之前的效果看不到,总之有两个让你设置公钥的地方,你全部设置就可以

 

 

 

2.SpringBoot框架整合

先建一个简单的springboot项目,什么都没有。

pom文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.jk</groupId>
    <artifactId>zfb-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>zfb-demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- 沙箱支付 -->
        <dependency>
            <groupId>com.alipay.api</groupId>
            <artifactId>k12-alipay-sdk</artifactId>
            <version>0.0.1-beta</version>
        </dependency>

        <!-- 前台jar -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

需要建三个配置类,代码如下所示,需要改的地方,我已经写好备注,到时候你们肯定是写你们自己的连接信息。

AlipayConfig类:
package com.jk.conf;

import java.io.FileWriter;
import java.io.IOException;

public class AlipayConfig {
    // 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
    public static String app_id = "2016093000627977";

    // 商户私钥,您的PKCS8格式RSA2私钥
    public static String merchant_private_key = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCNOIem6oWNySazObXjHzJCOLGdGMC8RC8SstAd0R8RPPCYx1UX2uZSeNu1r5wJ3m5aAYkGQoKzTF492IRwwXAihNCnw+KAQUNO49jjW1GrfAS+qXyXb5KgxbSL31IxHSSUcnWl9eBBquEIFPqJ7i0rFy8+yDih7X4Lm+W+Qt1I9EqJmnFJiD0bu4p5ycWsdsyqJDdq93g7khR3PdvnrOa29dbgIvaJkkpdxpxVaEC1YJwDZajO8D2mFeLaFNOes83m8s+97GgVcOm5cwPLZlMVlHPdq+t4QxV5UZafwn9Zz0Av+AQSVKUQ58c0pGFQNaEwy0yTnBuqw8U1ijfrIjxVAgMBAAECggEAd3n6GleTwk8KNNuAbLT5+liou/YzKZSuFq29sVw5YoYiL7+E2HfUILYre90ksJzE09U0rl0a4sKbgMtr0VF2o12mgikRudx9K4NM/Z1GzURRZ1VRGXXFoctiYmv/x5mWVxk3O793iVcep43IIWWmRSyKRh1y/FxHJV8x0fQT7yGfb8hCPieR1OC5307YZyE1EeDjI9g0CRHE0y2/f3NFoJOTaqHp2uFSdnBePQ0zhkmhxck8bGXjuDsdNcqrEWus59YDC2yiexYB48Aiz5GC0/ESSZElVOUnL4T3nOMYh/yWAyxXArXj/yGNxseAxSCFkOrvX61FSg/jOk5yRLmNgQKBgQD+ZqnJhbB5SH4SOwFUtzC+a7mnsE+17SHe4MGDY8w6tMC/43h0sCy9b5aL0XzX0ldm0ST0c7cGsKPEGGTPYucYW124NCSfTzqKC2c0lBNWc4Uf188stKJKlhs3FjYKJv+QEuOGDyNDgcfE/ltOyBCRBspj2l3QZQ+TDNhMhb+TEQKBgQCOG8HbMplLquSt57N4wHvFJmhScpEeBiBJqJweGBCOOEJGuhTMylboeGIS6N7bllvmXdVkjlVZzIQS83qe0FjRfX740Y806tn7ITJU+/cWDq6ukhO/zFfLtM9OERziL1Mnx+SQ2soAN3BlwVsgmhJXmj45DvPJuCpsv8cEXCSNBQKBgQDDF1PJWR6WQ8N6k4lXwAw/WzlKoWjfaPR6iP2dluC9fHP8M6LiSWBl/bcDjikhEQs5q9WdKUgId1l/Pf3BFGWIRji+1C3phcasqkYBCjUyLPDAFK2p6PQ0IpzIR941NubxQ6r72Yv/bv0V0sGOztn1fbGjlYgwEfA5orYVKNRbIQKBgE/dibWHWmAMSzjxXwweIXFLhJXRjX0yNDMxb4v6OlOziov1SHtPvEgqX/QArD784ek2ExfQZmdxaUi9TcyzizcxMIrmO3WiB5/7qC3a7aKX3dR+hFrmnPD/TQKy22jC8BkLXomKbLxya9jEMlLARE63gQDQRnK37h/wKAlrP5+BAoGBAM/fjeLkbu+cQBO4KO25U1O9m/iAYkomjMA1kWLBsFUTxKHzgnku1Y0N+xqMjB9VMjY+NkR9nxpEsujMDwNbzCfgyLaKlD2rtkIqP2HBjHXiddUbNOgLWp/z37RQdbE7C7xMn+3o9Kx+s8WhsnRcg0UZiBjtzb15g98ZfbclKd/V";

    // 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
    public static String alipay_public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjTiHpuqFjckmszm14x8yQjixnRjAvEQvErLQHdEfETzwmMdVF9rmUnjbta+cCd5uWgGJBkKCs0xePdiEcMFwIoTQp8PigEFDTuPY41tRq3wEvql8l2+SoMW0i99SMR0klHJ1pfXgQarhCBT6ie4tKxcvPsg4oe1+C5vlvkLdSPRKiZpxSYg9G7uKecnFrHbMqiQ3avd4O5IUdz3b56zmtvXW4CL2iZJKXcacVWhAtWCcA2WozvA9phXi2hTTnrPN5vLPvexoFXDpuXMDy2ZTFZRz3avreEMVeVGWn8J/Wc9AL/gEElSlEOfHNKRhUDWhMMtMk5wbqsPFNYo36yI8VQIDAQAB";

    // 服务器异步通知页面路径  需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
    public static String notify_url = "http://kyd.free.idcfengye.com/notify";

    // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
    public static String return_url = "http://kyd.free.idcfengye.com/returnUrl";

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

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

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

    // 支付宝网关
    public static String log_path = "D:\\";


//↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

    /**
     * 写日志,方便测试(看网站需求,也可以改成把记录存入数据库)
     * @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();
                }
            }
        }
    }
}
AlipayDemoController类:
package com.jk.conf;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;

@Controller
public class AlipayDemoController {

    @RequestMapping(value = "/goAlipay", produces = "text/html; charset=UTF-8")
    @ResponseBody
    public String goAlipay(HttpServletRequest request, HttpServletRequest response,String price) throws Exception {


        //获得初始化的AlipayClient
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);

        //设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(AlipayConfig.return_url);
        alipayRequest.setNotifyUrl(AlipayConfig.notify_url);



        //商户订单号,商户网站订单系统中唯一订单号,必填
        String out_trade_no = UUID.randomUUID().toString();
        //付款金额,必填
        String total_amount = price;
        //订单名称,必填
        String subject = "2016093000627977";
        //商品描述,可空
        String body = "";

        // 该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m。
        String timeout_express = "1c";

        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\"}");

        //请求
        String result = alipayClient.pageExecute(alipayRequest).getBody();
        System.out.println("返回页面"+ result);
        return result;
    }

    @RequestMapping("/returnUrl")
    public String returnUrl(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException, AlipayApiException {
        response.setContentType("text/html;charset=utf-8");

        boolean verifyResult = rsaCheckV1(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");
            String ids = (String) request.getSession().getAttribute("ids");
            if(!StringUtils.isEmpty(ids)){
                String[] split = ids.split(",");
                for (String s : split) {

                }
            }
            return "redirect:view";

        }else{
            return "redirect:error";

        }
    }
    @RequestMapping("toView")
    public String view(String viewName){
        return viewName;
    }
    public boolean rsaCheckV1(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.merchant_private_key,
                    AlipayConfig.charset,
                    AlipayConfig.sign_type);

            return verifyResult;
        } catch (AlipayApiException e) {

            return true;
        }
    }
    @RequestMapping("view")
    public String view(){
        return "hah";
    }

    @RequestMapping("notify")
    public String notify(HttpServletRequest request) throws AlipayApiException, UnsupportedEncodingException {
        // 一定要验签,防止黑客篡改参数
        Map<String, String[]> parameterMap = request.getParameterMap();
        StringBuilder notifyBuild = new StringBuilder("/****************************** alipay notify ******************************/\n");
        parameterMap.forEach((key, value) -> notifyBuild.append(key + "=" + value[0] + "\n") );
//        log.info(notifyBuild.toString());


        boolean flag = this.rsaCheckV1(request);
        if (flag) {
            /**
             * TODO 需要严格按照如下描述校验通知数据的正确性
             *
             * 商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
             * 并判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
             * 同时需要校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email),
             *
             * 上述有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。
             * 在上述验证通过后商户必须根据支付宝不同类型的业务通知,正确的进行不同的业务处理,并且过滤重复的通知结果数据。
             * 在支付宝的业务通知中,只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功。
             */

            //交易状态
            String tradeStatus = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");
            // 商户订单号
            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");
            //付款金额
            String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),"UTF-8");
            // TRADE_FINISHED(表示交易已经成功结束,并不能再对该交易做后续操作);
            // TRADE_SUCCESS(表示交易已经成功结束,可以对该交易做后续操作,如:分润、退款等);
            if(tradeStatus.equals("TRADE_FINISHED")){
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,
                // 并判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),并执行商户的业务程序
                //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
                //如果有做过处理,不执行商户的业务程序

                //注意:
                //如果签约的是可退款协议,退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
                //如果没有签约可退款协议,那么付款完成后,支付宝系统发送该交易状态通知。
            } else if (tradeStatus.equals("TRADE_SUCCESS")){
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,
                // 并判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),并执行商户的业务程序
                //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
                //如果有做过处理,不执行商户的业务程序

                //注意:
                //如果签约的是可退款协议,那么付款完成后,支付宝系统发送该交易状态通知。

            }

            return "redirect:view";
        }

        return "redirect:view";
    }
}
CorsMapping类:
package com.jk.conf;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsMapping implements WebMvcConfigurer {

    @Override
    /**
     * 重新跨域支持方法
     * CorsRegistry  开启跨域注册
     */
    public void addCorsMappings(CorsRegistry registry) {
        //addMapping 添加可跨域的请求地址
        registry.addMapping("/**")
                //设置跨域 域名权限 规定由某一个指定的域名+端口能访问跨域项目
                .allowedOrigins("*")
                //是否开启cookie跨域
                .allowCredentials(false)
                //规定能够跨域访问的方法类型
                .allowedMethods("GET","POST","DELETE","PUT","OPTIONS")
                //添加验证头信息  token
                //.allowedHeaders()
                //预检请求存活时间 在此期间不再次发送预检请求
                .maxAge(3600);
    }
}

前台页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<button onclick="jiesuan()">结算</button>
</body>
<script>
    function jiesuan(){
        location.href="/goAlipay?price="+100;  //这个数字只是为了演示,实际应用肯定是写活的。
    }
</script>
</html>

配置yml文件:

server:
  port: 8080

spring:
  application:
    name: zfb-server
  data:
  thymeleaf:
    encoding: UTF-8
    servlet:
      content-type: text/html

写一个跳转前台页面的PageController类:

package com.jk.conf;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("page")
public class PageController {

    @RequestMapping("toindex")
    public String toindex(){
        return "list";
    }
}

启动项目访问页面:

点击结算:

效果如上:

如果想进行支付操作,需要手机下载沙箱支付宝APP:

下载地址在官网:

直接扫码下载就行,你的登录账号和登录密码是自动生成的,见下图,用这个账号和密码登录就行,支付密码也是自动生成的,无需设置:

扫码支付后:

(余额均为虚假货币,无需担心!)

 

完成!

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

听风动

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值