网上的文章都有点杂乱无章,翻了好久整合一下
1.先导入所需要的依赖
2.application-alipay.properties 配置文件
# APPID
alipay.appId:902100013
# 商户私钥, 即PKCS8格式RSA2私钥
alipay.privateKey:
# 支付宝公钥, 即对应APPID下的支付宝公钥
alipay.publicKey:
# 服务器异步通知页面路径, 需http://格式的完整路径
# 踩坑:不能加?type=abc这类自定义参数
alipay.notifyUrl:https://1000-240a1-75df-cbd6.ngrok-free.app/alipay/pay
# 页面跳转同步通知页面路径, 需http://格式的完整路径
# 踩坑:不能加?type=abc这类自定义参数
alipay.returnUrl:http://192.100.10.1:8080/list/itemOrders
# 签名方式
alipay.signType:RSA2
# 字符编码格式
alipay.charset:utf-8
# 支付宝网关
alipay.gatewayUrl:https://openapi-sandbox.dl.alipaydev.com/gateway.do
# 日志打印地址
注意:
alipay.returnUrl:http://192.100.10.1:8080/list/itemOrders 这是同步调用,代表支付成功后过几秒会刷新到/list/itemOrders界面
alipay.notifyUrl:https://1000-275df-cbd6.ngrok-free.app/alipay/pay这是异步调用,要加内网穿透,异步其实就是一个双保险,如果同步没有跳转你的网址,可能是关机了,或者网速慢,无法完成数据更新的状态,这时候异步就发挥作用了,先判断是否支付,支付了就不必更新了,只返回支付宝 success 就行了,不然会一直异步通知
3.添加AliPayConfig
package cn.jiyun.common;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource("classpath:application-alipay.properties")
@ConfigurationProperties(prefix = "alipay")
@Data
public class AliPayConfig {
/**
* APPID
*/
private String appId;
/**
* 商户私钥, 即PKCS8格式RSA2私钥
*/
private String privateKey;
/**
* 支付宝公钥
*/
private String publicKey;
/**
* 服务器异步通知页面路径,需http://格式的完整路径
* 踩坑:不能加?type=abc这类自定义参数
*/
private String notifyUrl;
/**
* 页面跳转同步通知页面路径,需http://格式的完整路径
* 踩坑:不能加?type=abc这类自定义参数
*/
private String returnUrl;
/**
* 签名方式
*/
private String signType;
/**
* 字符编码格式
*/
private String charset;
/**
* 支付宝网关
*/
private String gatewayUrl;
/**
* 日志打印地址
*/
private String logPath;
}
4.添加Alipay
package cn.jiyun.common;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Alipay {
@Autowired
private AliPayConfig alipayConfig;
/**
* 支付接口
*
* @param order
* @retur
*/
public String pay(Order order) throws AlipayApiException {
// 支付宝网关
String serverUrl = alipayConfig.getGatewayUrl();
// APPID
String appId = alipayConfig.getAppId();
// 商户私钥, 即PKCS8格式RSA2私钥
String privateKey = alipayConfig.getPrivateKey();
// 格式化为 json 格式
String format = "json";
// 字符编码格式
String charset = alipayConfig.getCharset();
// 支付宝公钥, 即对应APPID下的支付宝公钥
String alipayPublicKey = alipayConfig.getPublicKey();
// 签名方式
String signType = alipayConfig.getSignType();
// 页面跳转同步通知页面路径
String returnUrl = alipayConfig.getReturnUrl();
// 服务器异步通知页面路径
String notifyUrl = alipayConfig.getNotifyUrl();
// 1、获得初始化的AlipayClient
AlipayClient alipayClient = new DefaultAlipayClient(
serverUrl, appId, privateKey, format, charset, alipayPublicKey, signType);
// 2、设置请求参数
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
// 页面跳转同步通知页面路径
alipayRequest.setReturnUrl(returnUrl);
// 服务器异步通知页面路径
alipayRequest.setNotifyUrl(notifyUrl);
// 封装参数(以json格式封装)
alipayRequest.setBizContent(JSON.toJSONString(order));
// 3、请求支付宝进行付款,并获取支付结果
String result = alipayClient.pageExecute(alipayRequest).getBody();
// 返回付款信息
return result;
}
}
5.添加实体类,不需要往数据库添加表
package cn.jiyun.common;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class Order {
/**
* 商户订单号,必填
*/
private String out_trade_no;
/**
* 订单名称,必填
*/
private String subject;
/**
* 付款金额,必填
* 根据支付宝接口协议,必须使用下划线
*/
private String total_amount;
/**
* 商品描述,可空
*/
private String description;
/**
* 超时时间参数
*/
private String timeout_express = "10m";
/**
* 产品编号
*/
private String product_code = "FAST_INSTANT_TRADE_PAY";
}
6. 网关拦截器一定要放白名单
7.开始写controller层
package cn.jiyun.controller;
import cn.hutool.core.util.IdUtil;
import cn.jiyun.common.AliPayConfig;
import cn.jiyun.common.Order;
import cn.jiyun.pojo.Itemorders;
import cn.jiyun.service.AliPayService;
import com.alipay.api.AlipayApiException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigInteger;
@RestController
@RequestMapping("alipay")
public class PayController {
//不加可能会导致进入付款界面乱码
@Autowired
AliPayConfig aliPayConfig;
private static final String GATEWAY_URL ="https://openapi.alipaydev.com/gateway.do";
private static final String FORMAT ="JSON";
private static final String CHARSET ="utf-8";
private static final String SIGN_TYPE ="RSA2";
@Autowired
AliPayService aliPayService;
/**
* 支付宝支付 api
*
// * @param outTradeNo
* @return
// * @throws AlipayApiException
*/
@RequestMapping( "pay")
public String alipay(String outTradeNo, String subject,
String totalAmount, String description) throws AlipayApiException {
Order order = new Order();
// 订单编号
order.setOut_trade_no(outTradeNo);
// 订单名称
order.setSubject(subject);
//付款金额,必填
order.setTotal_amount(totalAmount);
//电脑网站支付产品,product_code为:FAST_INSTANT_TRADE_PAY
order.setProduct_code("FAST_INSTANT_TRADE_PAY");
System.out.println(order);
return aliPayService.aliPay(order);
}
}
8.service
package cn.jiyun.service;
import cn.jiyun.common.Order;
import com.alipay.api.AlipayApiException;
public interface AliPayService {
String aliPay(Order order) throws AlipayApiException;
}
package cn.jiyun.service.impl;
import cn.jiyun.common.Alipay;
import cn.jiyun.common.Order;
import cn.jiyun.service.AliPayService;
import com.alipay.api.AlipayApiException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AliPayServiceImpl implements AliPayService {
@Autowired
private Alipay alipay;
@Override
public String aliPay(Order order) throws AlipayApiException {
return alipay.pay(order);
}
}
9.前端
window.open(`http://localhost:1002/alipay/pay?subject=${this.itemOrders.name}&traceNo=${this.outTradeNo}&totalAmount=${this.itemOrders.price}`)
前端传值传到后端我没有传完整,但是不影响使用,缺了个商品描述,可空,但是产品编号product_code是不能为空的,要不然就会出现订单信息无法识别
10.启动!!!
支付完自动跳转页面
11.内网穿透工具 访问网址 https://ngrok.com/
注册账号、登录,需要绑定邮箱,可以注册阿里云个人邮箱,向你邮箱发送一个链接,在一个新网页复制地址即可访问,这是登录后的页面,点击这个
在ngrok运行这行命令
再设置内网穿透,后面是服务端口号
ngrok http 8090