目录
1.4 点击启用公钥(有重要作用!springboot整合时会用到)?编辑
? ? ? ? ?2.3 引入支付宝沙箱的配置代码
2.3.1 引入alipay的java配置:AplipayConfig.java?
2.3.3?新建AliPayController.java,定义了支付接口与支付回调接口:
2.3.4 编写AliPay.java? 接收前端传来的参数
3.1 进入natapp官网注册账号,并进行实名认证、与支付宝账号进行绑定。
3.3 配置application.yml中notifyUrl参数
支付宝开发者平台https://openhome.alipay.com/
????????沙箱比较不好找到 沙箱地址在这里:
<!--引入支付宝支付 -->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-easysdk</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.22.113.ALL</version>
</dependency>
#支付宝
alipay:
appId:
appPrivateKey:
alipayPublicKey:
notifyUrl:
returnUrl:
?这五个参数都是什么意思呢?
?appPrivateKey:? 应用私钥与? alipayPublicKey: 支付宝公钥在这里:点击查看
package com.songqiao.waimai.alipay.common;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
* @Author
* @Date Created in 2023/1/13 15:06
* @DESCRIPTION:
* @Version V1.0
*/
@Data
@Component
//读取yml文件中alipay 开头的配置
@ConfigurationProperties(prefix = "alipay")
public class AliPayConfig {
private String appId;
private String appPrivateKey;
private String alipayPublicKey;
//异步通知回调地址(可选)
private String notifyUrl;
//支付成功后的回调地址
private String returnUrl;
@PostConstruct
public void init() {
// 设置参数(全局只需设置一次)
Config config = new Config();
config.protocol = "https";
config.gatewayHost = "openapi.alipaydev.com";
config.signType = "RSA2";
config.appId = this.appId;
config.merchantPrivateKey = this.appPrivateKey;
config.alipayPublicKey = this.alipayPublicKey;
config.notifyUrl = this.notifyUrl;
Factory.setOptions(config);
System.out.println("=======支付宝SDK初始化成功=======");
}
}
package com.songqiao.waimai.alipay.controller;
import com.alipay.easysdk.factory.Factory;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.songqiao.waimai.alipay.common.AliPayConfig;
import com.songqiao.waimai.alipay.payparameter.AliPay;
import com.songqiao.waimai.common.BaseContext;
import com.songqiao.waimai.common.R;
import com.songqiao.waimai.entity.AddressBook;
import com.songqiao.waimai.entity.Orders;
import com.songqiao.waimai.mapper.AddressBookMapper;
import com.songqiao.waimai.mapper.OrderMapper;
import com.songqiao.waimai.service.impl.OrderServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @Author
* @Date Created in 2023/5/5 15:23
* @DESCRIPTION:
* @Version V1.0
*/
@RestController
@RequestMapping("alipay")
@Transactional(rollbackFor = Exception.class)
public class AliPayController {
@Resource
AliPayConfig aliPayConfig;
@Resource
AddressBookMapper addressBookMapper;
@Autowired
OrderServiceImpl orderServiceImpl;
private static final String GATEWAY_URL ="https://openapi-sandbox.dl.alipaydev.com/gateway.do";
private static final String FORMAT ="JSON";
private static final String CHARSET ="utf-8";
private static final String SIGN_TYPE ="RSA2";
@GetMapping("/pay") // 前端路径参数格式?subject=xxx&traceNo=xxx&totalAmount=xxx
public void pay(AliPay aliPay, HttpServletResponse httpResponse) throws Exception {
AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL, aliPayConfig.getAppId(),
aliPayConfig.getAppPrivateKey(), FORMAT, CHARSET, aliPayConfig.getAlipayPublicKey(), SIGN_TYPE);
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
request.setNotifyUrl(aliPayConfig.getNotifyUrl());
request.setReturnUrl(aliPayConfig.getReturnUrl());
request.setBizContent("{\"out_trade_no\":\"" + aliPay.getTraceNo() + "\","
+ "\"total_amount\":\"" + aliPay.getTotalAmount() + "\","
+ "\"subject\":\"" + aliPay.getSubject() + "\","
+ "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
String form = "";
try {
// 调用SDK生成表单
form = alipayClient.pageExecute(request).getBody();
} catch (AlipayApiException e) {
e.printStackTrace();
}
httpResponse.setContentType("text/html;charset=" + CHARSET);
// 直接将完整的表单html输出到页面
httpResponse.getWriter().write(form);
httpResponse.getWriter().flush();
httpResponse.getWriter().close();
}
@PostMapping("/notify") // 注意这里必须是POST接口
public String payNotify(HttpServletRequest request) throws Exception {
if (request.getParameter("trade_status").equals("TRADE_SUCCESS")) {
System.out.println("=========支付宝异步回调========");
Map<String, String> params = new HashMap<>();
Map<String, String[]> requestParams = request.getParameterMap();
for (String name : requestParams.keySet()) {
params.put(name, request.getParameter(name));
}
String tradeNo = params.get("out_trade_no");
String gmtPayment = params.get("gmt_payment");
String alipayTradeNo = params.get("trade_no");
// 支付宝验签
if (Factory.Payment.Common().verifyNotify(params)) {
// 验签通过
System.out.println("交易名称: " + params.get("subject"));
System.out.println("交易状态: " + params.get("trade_status"));
System.out.println("支付宝交易凭证号: " + params.get("trade_no"));
System.out.println("商户订单号: " + params.get("out_trade_no"));
System.out.println("交易金额: " + params.get("total_amount"));
System.out.println("买家在支付宝唯一id: " + params.get("buyer_id"));
System.out.println("买家付款时间: " + params.get("gmt_payment"));
System.out.println("买家付款金额: " + params.get("buyer_pay_amount"));
// 更新订单已支付的逻辑代码
}
}
return "success";
}
}
?注意!在notify接口中的支付宝验签通过后,编写支付成功的逻辑。例如:修改订单状态、更新菜品销量、清空购物车等等。
package com.songqiao.waimai.alipay.payparameter;
import lombok.Data;
/**
* @Author
* @Date Created in 2024/1/13 15:26
* @DESCRIPTION: alipay接口参数
* @Version V1.0
*/
@Data
public class AliPay {
//订单编号
private String traceNo;
//商品金额
private double totalAmount;
//商品名称
private String subject;
//订单追踪号,商户自己生成,可已不使用
private String alipayTraceNo;
}
?所有后端java代码已经over 你的代码结构应该是这样的:
?
????????别忘了!咱们在application.yml中还有一个重要的参数?notifyUrl?没有配置,这个参数是支付成功后支付宝的回调函数访问本地系统的路径,需要以内网穿透的方式让支付宝访问本地系统。
出现以下界面
回到natapp官网,点击购买隧道->免费隧道->创建隧道并配置程序中的端口等信息
创建成功后点击我的隧道->点击配置->点击复制获取authtoken
在natapp.exe启动后的命令行输入natapp -authtoken=刚刚复制的token,就会与本机的8080端口映射成功!
出现如图所示状态后,那么恭喜你!外网即可访问你的本机的8080端口,支付宝api支付成功后即可完成回调!
把图中的代理地址填入即可完成全部后端的准备工作!咱们就可以去专心搞前端部分啦!?
调用后端接口并拼接get请求的参数,完成!
async goToPaySuccess(){
//在这里我选择了window.open(url,'_self')形式,也就是不跳转新的页面,在本页面直接跳转
window.open("http://127.0.0.1:8080/alipay/pay?subject="+"邬先生东北菜,"+this.note+"&traceNo="+Math.floor(Math.random() * 900000) + 100000+"&totalAmount="+this.goodsPrice,'_self')
},
点击支付按钮后跳转支付界面,为了避免被当做违规图片,我把二维码遮盖了。
注意!大坑!此时要求你登录的支付宝账号密码是支付宝沙箱的账号密码!不要混淆!?
?输入账号密码后即可进行付款~
确认付款后会有两种结果:1.付款成功界面 2.付款成功后跳转到你指定的页面(在前面的application.yml的配置中设置)?如果没有配置就会展示成功界面,配置了就会在几秒后跳转到你配置的界面中去!
?大功告成!
?????????创作不易,如果您喜欢这篇文章请点赞关注,如果在跟着博主实操的过程中出现了问题可以在评论区说明,我会第一时间回复你!