Springboot+Vue整合支付宝沙箱模拟支付以及退款
第一步打开支付宝开放平台并登录
查看AppId 应用公钥 应用私钥 支付宝公钥
第二步准备内网穿透工具
内网穿透工具是将本地的服务映射到公网上面,因为支付宝在支付成功后会回调本地的方法,自己可以在这个方法当中编写支付成功后的逻辑。
https://natapp.cn/login natapp内网穿透地址,注册登录后购买免费隧道
在我的隧道当中进行配置
修改项目的端口号 自己本地的项目在哪个端口就配置哪个端口,我的项目是9090端口,所以这边我配置的就是9090端口
根据自己的电脑下载对应的客户端
解压后创建一个satrt.bat
natapp.exe -authtoken=你自己隧道的token
双击启动后就可以看到穿透的url,将这个url配置到application.yml当中即可
第三步编写后端代码
引入依赖
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.35.79.ALL</version>
</dependency>
配置application.yml
alipay:
appId:
#应用私钥
appPrivateKey:
#应用公钥
appPublicKey:
#支付宝公钥
alipayPublicKey:
#启动nata内网穿透后命令提示框中的http地址,上面启动后保留的地址
notifyUrl: http://tzqse7.natappfree.cc/policy/notify
注意appId、应用私钥、应用公钥、支付宝公钥均要与自己的对应,notifyUrl是在支付成功后支付宝回调的url,使用内网穿透的地址拼接自己项目当中的地址
AliPayConfig.java
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "alipay")
public class AliPayConfig {
private String appId;
private String appPrivateKey;
private String alipayPublicKey;
private String notifyUrl;
private String appPublicKey;
}
付款代码、退款、回调代码
//付款
@GetMapping("/pay")
public void pay(String orderNumber, HttpServletResponse httpServletResponse) throws IOException {
//查询保单信息 这个地方换成自己的业务逻辑
LambdaQueryWrapper<InsurancePolicyEntity> insurancePolicyLambdaQueryWrapper = new LambdaQueryWrapper<>();
insurancePolicyLambdaQueryWrapper.eq(InsurancePolicyEntity::getOrderNumber, orderNumber);
InsurancePolicyEntity insurancePolicyEntity = insurancePolicyService.getOne(insurancePolicyLambdaQueryWrapper);
//创建Client,调用通用SDK提到的Client,用来调用支付宝的API 固定
AlipayClient alipayClient = new DefaultAlipayClient(GAETWAY_URL, aliPayConfig.getAppId(), aliPayConfig.getAppPrivateKey(), FORMAT, CHARSET, aliPayConfig.getAppPublicKey(), SIGN_TYPE);
//创建Request并设置参数 固定参数,要传递其他参数可去查阅帮助文档
AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
request.setNotifyUrl(aliPayConfig.getNotifyUrl());
JSONObject jsonObject = new JSONObject();
jsonObject.put("out_trade_no", insurancePolicyEntity.getOrderNumber());
jsonObject.put("total_amount", insurancePolicyEntity.getAmount());
jsonObject.put("subject", insurancePolicyEntity.getProductName());
jsonObject.put("product_code", "FAST_INSTANT_TRADE_PAY");
request.setBizContent(jsonObject.toString());
//支付成功后前端跳转的url
request.setReturnUrl("http://localhost:90/#/mall");
String form = "";
try {
form = alipayClient.pageExecute(request).getBody();
} catch (AlipayApiException e) {
e.printStackTrace();
}
httpServletResponse.setContentType("text/html;charset="+CHARSET);
httpServletResponse.getWriter().write(form);
httpServletResponse.getWriter().flush();
httpServletResponse.getWriter().close();
}
//支付成功回调
@PostMapping("/notify")
public void payNotify(HttpServletRequest request) throws AlipayApiException {
if ("TRADE_SUCCESS".equals(request.getParameter("trade_status"))) {
System.out.println("支付宝异步回调");
HashMap<String, String> params = new HashMap<>();
Map<String, String[]> parameterMap = request.getParameterMap();
for (String name : parameterMap.keySet()) {
params.put(name, request.getParameter(name));
}
OrderInfoEntity orderInfoEntity = new OrderInfoEntity();
orderInfoEntity.setSubject(params.get("subject"));
orderInfoEntity.setTradeStatus(params.get("trade_status"));
orderInfoEntity.setTradeNo(params.get("trade_no"));
orderInfoEntity.setOutTradeNo(params.get("out_trade_no"));
orderInfoEntity.setTotalAmount(params.get("total_amount"));
orderInfoEntity.setBuyerId(params.get("buyer_id"));
orderInfoEntity.setGmtPayment(params.get("gmt_payment"));
orderInfoEntity.setBuyerPayAmount(params.get("buyer_pay_amount"));
String refundAmount = params.get("refund_fee");
if ("".equals(refundAmount) || refundAmount == null) {
//退款与付款回调同一个函数,所以在这判断是否存在退款金额,此处用来处理退款后业务逻辑
}
}
}
@GetMapping("/refund")
public AjaxResult refund(String orderNumber,String refundAmount) throws IOException, AlipayApiException {
//获取保单信息
LambdaQueryWrapper<InsurancePolicyEntity> insurancePolicyEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
insurancePolicyEntityLambdaQueryWrapper.eq(InsurancePolicyEntity::getOrderNumber, orderNumber);
InsurancePolicyEntity insurancePolicyEntity = insurancePolicyService.getOne(insurancePolicyEntityLambdaQueryWrapper);
//查询订单信息
LambdaQueryWrapper<OrderInfoEntity> orderInfoEntityLambdaQueryWrapper = new LambdaQueryWrapper<>();
orderInfoEntityLambdaQueryWrapper.eq(OrderInfoEntity::getOutTradeNo, insurancePolicyEntity.getOrderNumber());
OrderInfoEntity orderInfoEntity = orderInfoService.getOne(orderInfoEntityLambdaQueryWrapper);
//创建Client,调用通用SDK提到的Client,用来调用支付宝的API
AlipayClient alipayClient = new DefaultAlipayClient(GAETWAY_URL, aliPayConfig.getAppId(), aliPayConfig.getAppPrivateKey(), FORMAT, CHARSET, aliPayConfig.getAlipayPublicKey(), SIGN_TYPE);
//创建Request并设置参数
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
JSONObject jsonObject = new JSONObject();
jsonObject.put("out_trade_no", insurancePolicyEntity.getOrderNumber()); //我的单号
jsonObject.put("refund_amount", refundAmount);//订单金额
jsonObject.put("trade_no", orderInfoEntity.getTradeNo());//支付宝本身的订单流水号
jsonObject.put("out_request_no", UUIDGenerator.generateId()); //这个参数需要注意,如果想要实现部分退款逻辑这个参数是必须的
request.setBizContent(jsonObject.toString());
request.setBizContent(jsonObject.toJSONString());
//执行请求
AlipayTradeRefundResponse response = alipayClient.execute(request);
if(response.isSuccess()){
System.out.println("退款成功:"+refundAmount);
//这里用来编写退款成功后的业务逻辑
}
前端请求付款退款
前端调用付款注意必须使用window.open来进行调用,后面根据自己的业务逻辑传递参数即可
window.open('http://localhost:9090/policy/pay?orderNumber=' + res.data);
退款直接调用就可以,参数也是看具体的业务逻辑
return request(
'/api/policy/refund?orderNumber='+data.orderNumber+'&refundAmount='+data.refundAmount,
METHOD.GET,
)
如有任何疑问加Q771828475 免费帮忙解答