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

    xiaoxiao2022-07-13  137

    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:

    下载地址在官网:

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

    扫码支付后:

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

     

    完成!

    最新回复(0)