支付宝沙箱支付
前言
最近项目中用到了支付业务,由于项目还没有上线,这里使用支付宝沙箱环境模拟支付操作。
支付宝沙箱-手机网页支付
- 4.下载SDK搭建支付宝沙箱环境
- 4.把下载好的沙箱的源码放到IDE中
这里使用eclipse测试一下,这里需要商户的私钥和支付宝的公钥,可以去刚刚的页面获取
- 5.运行起来,测试支付
运行成功出现手机网页支付页面,我们点击跳转。
由于这里是沙箱环境,所以我们可以用测试的支付宝账号进行支付
测试结果支付成功!!!!
- 6.设置支付结果的跳转页
可以看到我们支付成功,跳转到是这个鬼url
可以通过,配置更改。
支付宝沙箱-电脑网页支付
-
在API 集成工具集一览表中找到电脑网页支付url
-
找到开发文档url
-
找到sdk和demo下载
配置公钥私钥和支付成功跳转的链接
测试启动成功与否
整合到项目
先来分析一下前面的操作,首先我们把DEMO源码和SDK下载了下来,然后我们配置了一下AlipayConfig
就能跑了,然后我们看一下逻辑。
1)、找到项目启动后进入的index页面,推测一下是否和源码中的index.jsp一致。
对比发现其实是一样的。
2)、我们再来分析一下是怎么付款的,为什么我们配置了AlipayConfig
就能用了呢。
可以看到这其实就是一个表单,提交了一堆的数据,其实就是页面上的表单信息,最终会到达alipay.trade.page.pay.jsp
这个页面
3)、分析alipay.trade.page.pay.jsp
逻辑
可以看到上面的操作就是读取了AlipayConfig
的配置,然后就是把index.jsp
提交的表单的数据构建成了请求体,最终去发起请求,然后返回一个result,result里面其实就包含了真正去支付的一个操作的url。
下面模仿一下怎么做!
- 导入支付宝支付SDK的依赖
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.34.0.ALL</version>
</dependency>
- 编写AlipayTemplate工具类和PayVo
这么做是模仿index.jsp
提交的表单数据(订单号、订单名称)等---PayVo
和alipay.trade.page.pay.jsp
封装成了一个支付的方法pay()
---AlipayTemplate
PayVo
import lombok.Data;
@Data
public class PayVo {
private String out_trade_no; // 商户订单号 必填
private String subject; // 订单名称 必填
private String total_amount; // 付款金额 必填
private String body; // 商品描述 可空
}
AlipayTemplate
package com.atguigu.order.config;
/**
* description: AlipayTemplate
* date: 2023/1/1 15:07
* author: MR.孙
*/
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.atguigu.order.vo.PayVo;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@ConfigurationProperties(prefix = "alipay")
@Component
@Data
public class AlipayTemplate {
//在支付宝创建的应用的id
@Value("${alipay.app_id}")
private String app_id;
// 商户私钥,您的PKCS8格式RSA2私钥
@Value("${alipay.merchant_private_key}")
private String merchant_private_key;
@Value("${alipay.alipay_public_key}")
private String alipay_public_key;
// 服务器[异步通知]页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
// 支付宝会悄悄的给我们发送一个请求,告诉我们支付成功的信息
@Value("${alipay.notify_url}")
private String notify_url;
// 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
//同步通知,支付成功,一般跳转到成功页
@Value("${alipay.return_url}")
private String return_url;
// 签名方式
private String sign_type = "RSA2";
// 字符编码格式
private String charset = "utf-8";
// 支付宝网关; https://openapi.alipaydev.com/gateway.do
private String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";
public String pay(PayVo vo) throws AlipayApiException {
//AlipayClient alipayClient = new DefaultAlipayClient(AlipayTemplate.gatewayUrl, AlipayTemplate.app_id, AlipayTemplate.merchant_private_key, "json", AlipayTemplate.charset, AlipayTemplate.alipay_public_key, AlipayTemplate.sign_type);
//1、根据支付宝的配置生成一个支付客户端
AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl,
app_id, merchant_private_key, "json",
charset, alipay_public_key, sign_type);
//2、创建一个支付请求 //设置请求参数
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
alipayRequest.setReturnUrl(return_url);
alipayRequest.setNotifyUrl(notify_url);
//商户订单号,商户网站订单系统中唯一订单号,必填
String out_trade_no = vo.getOut_trade_no();
//付款金额,必填
String total_amount = vo.getTotal_amount();
//订单名称,必填
String subject = vo.getSubject();
//商品描述,可空
String body = vo.getBody();
alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
+ "\"total_amount\":\""+ total_amount +"\","
+ "\"subject\":\""+ subject +"\","
+ "\"body\":\""+ body +"\","
+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
String result = alipayClient.pageExecute(alipayRequest).getBody();
//会收到支付宝的响应,响应的是一个页面,只要浏览器显示这个页面,就会自动来到支付宝的收银台页面
System.out.println("支付宝的响应:"+result);
return result;
}
}
读取yml中的自定义配置
- 通过提交
PayVo
数据,AlipayTemplate
的pay
方法放回result,拿到支付的页面url。
编写Controller PayWebController
@GetMapping("/payOrder")
@ResponseBody
public String payOrder(@RequestParam("orderSn") String orderSn) throws AlipayApiException {
PayVo payVo = orderService.getOrderPay(orderSn);
String result = alipayTemplate.pay(payVo);
System.out.println(result);
return "ok";
}
访问接口,发现支付宝的响应
这里的响应内容其实就是个html文件,新建一个html,打开运行发现,其实是支付页面。
既然知道这个result就是个html也就是支付页面,那么我们可以优化一下代码逻辑,让我们接口直接跳转到支付页。
/**
* 1.将支付页让浏览器展示
* 2.支付成功以后,我们要调到用户的订单列表页
* @param orderSn
* @return
* @throws AlipayApiException
*/
@GetMapping(value = "/payOrder", produces = MediaType.TEXT_HTML_VALUE)
@ResponseBody
public String payOrder(@RequestParam("orderSn") String orderSn) throws AlipayApiException {
PayVo payVo = orderService.getOrderPay(orderSn);
String result = alipayTemplate.pay(payVo);
return result;
}
付款成功后会调到之前下载的SDK和DEMO源码中配置的支付成功回调地址return_url
,可以根据实际业务需求改变。