写在前面
首先,看这篇文章的小伙伴肯定具有Springboot的基础以及更为深刻的技术功底;
其次,这篇文章主要是作为个人笔记学习之用,记录自己从0到1构建出一个完整的支付环境,方便后期个人项目整合的时候用得到。如果有总结的不对的地方,希望技术大佬给予指正,我会马上修改。
默认您有以下的知识或者技术功底:
支付宝开放平台的认知,详见
https://openhome.alipay.com/platform/home.htm知道支付宝沙箱环境是什么Springboot技术基本的前端技术(Thymeleaf、jsp、Freemarker三者任选其一)
前期准备
言归正传,既然我们需要整合支付宝沙箱支付,肯定需要先去看看官方给我们提供了哪些东西。
百度搜索支付宝开放平台,后面带官方俩字的就是
进入首页
点击右上角登录,然后登录你的支付宝账号。放心此步骤没有任何的风险,可以放心操作;
登录完成后,会自己跳转到如下页面:
我们找到下面的开发服务,点击研发服务
进来之后,会给我们如下的界面;
我们需要的其实就是APPID和支付宝网关以及密钥对;
既然官方需要我们去生成一个密钥,那么肯定需要一个密钥工具;
支付宝官方也为我们提供了一个生成密钥的工具,看看文档部分,复制下面链接:
https://opendocs.alipay.com/open/291/106074
我们下载好官方给我们提供的工具,安装打开后是这个样子的。
我们点击生成密钥,然后就会自动给我们生成好我们需要的密钥对;
生成出来的密钥对会自动给我们保存在文件夹下,也可以直接点击打开密钥文件路径查看;
然后我们把刚才生成出来的应用公钥复制一下,回到我们刚才的网站,点击设置密钥:
在弹出来的窗口我们选择公钥:
把刚才复制的放进去,保存设置,就会自动给我们生成;
接下来我们就可以开始撸代码了;
代码部分
首先导入我们必要的依赖环境,根据自己需要自取:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-sdk-java --> <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>4.10.192.ALL</version> </dependency> </dependencies>
最后面那个依赖就是官方给我们提供的整合依赖要用到的sdk;
接着创建一个Config配置类,把我们需要的配置信息放进去:
package com.zxy.config; import java.io.FileWriter; import java.io.IOException; public class AlipayConfig { //↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ // 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号 public static String app_id = "改成你自己的APPID"; // 商户私钥,您的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这类自定义参数,必须外网可以正常访问 public static String notify_url = "http://www.baidu.com"; // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 public static String return_url = "http://www.baidu.com"; // 签名方式 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 = "C:\\"; //↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ /** * 写日志,方便测试(看网站需求,也可以改成把记录存入数据库) * @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(); } } } } }
如果你不想讲这些配置信息写死,那你也可以考虑使用外部配置文件通过注解的形式讲属性注入进去,看个人爱好;
接着创建一个视图层,用来跳转支付:
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form th:action="@{/pay}" method="post"> 订单号:<input type="text" name="WIDout_trade_no" required><br/> 订单名称:<input type="text" name="WIDsubject" required><br/> 付款金额:<input type="text" name="WIDtotal_amount" required><br/> WIDbody:<input type="text" name="WIDbody"><br/> <input type="submit" value="下单"> <input type="reset" value="重置"> </form> </body> </html>
然后创建一个Controller层,用来实现具体的业务控制。(我这儿做的比较简单,没有用数据层以及服务层来分离架构,读者可以根据自行需要调整,道理都差不多)
package com.zxy.controller; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.DefaultAlipayClient; import com.alipay.api.request.AlipayTradePagePayRequest; import com.zxy.config.AlipayConfig; import org.springframework.stereotype.Controller; 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.IOException; /** * @Author Zxy * @Date 2020/11/24 16:39 * @Version 1.0 */ @Controller public class PayController { @RequestMapping("/pay") @ResponseBody public void payController(HttpServletRequest request, HttpServletResponse response) throws IOException, AlipayApiException { // 获取初始化的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 = new String(request.getParameter("WIDout_trade_no").getBytes("ISO-8859-1"),"UTF-8"); //付款金额,必填 String total_amount = new String(request.getParameter("WIDtotal_amount").getBytes("ISO-8859-1"),"UTF-8"); //订单名称,必填 String subject = new String(request.getParameter("WIDsubject").getBytes("ISO-8859-1"),"UTF-8"); //商品描述,可空 String body = new String(request.getParameter("WIDbody").getBytes("ISO-8859-1"),"UTF-8"); alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\"," + "\"total_amount\":\""+ total_amount +"\"," + "\"subject\":\""+ subject +"\"," + "\"body\":\""+ body +"\"," + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}"); //若想给BizContent增加其他可选请求参数,以增加自定义超时时间参数timeout_express来举例说明 //alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\"," // + "\"total_amount\":\""+ total_amount +"\"," // + "\"subject\":\""+ subject +"\"," // + "\"body\":\""+ body +"\"," // + "\"timeout_express\":\"10m\"," // + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}"); //请求参数可查阅【电脑网站支付的API文档-alipay.trade.page.pay-请求参数】章节 //请求 String result = alipayClient.pageExecute(alipayRequest).getBody(); //输出 response.setContentType("text/html;charset="+AlipayConfig.charset); response.getWriter().write(result); response.getWriter().flush(); response.getWriter().close(); } @RequestMapping("/") public String toIndex(){ return "index"; } }
测试
运行写好的案例,访问首页:
如果遇到下面的这样的报错,那么你试试用另一个浏览器打开窗口进行支付测试:
登录刚才我们那个开放平台为我们提供的账号和密码:
当然,这些余额都是自己改的。。。想提现也是不大可能,要是可以的话我就提现了…
输入你的支付密码,然后就可以实现支付功能;
等几秒钟,会自动给我们跳转到我们前面设置的服务通知页面,由于我设置的是百度,所以就自己跳到百度页面了。
至此,整合功能完成;
题外话
我们需要做的其实是电脑端整合网站支付,还有手机端的支付等等,我们可以往下看看给我们提供了哪些功能;
后期会出一些整合其他功能的支付,不过都是不变应万变,原理都一样;
小结
虽然这个做出来很简单,但是,还是有很多的不足之处,例如没有用数据库来保存信息,没有分层等等,拿来练手还勉强可以;
如果有更好的想法,不妨分享给我,我们一起实现。
本文就是愿天堂没有BUG给大家分享的内容,大家有收获的话可以分享下,想学习更多的话可以到微信公众号里找我,我等你哦。