真实环境支付宝第三方支付demo,整合进SpringBoot项目全过程(电脑网站支付)
一、准备阶段
我是小白,第一次做第三方支付,出了很多问题,网上文档都看得有点懵,所以做完后自己做了一个全过程第三方支付。
这是真实环境下的第三方支付,需要公司或商家的账号,营业执照等。不是真实环境需要沙箱。
该步骤可根据官方文档来写(文档跳转有点多,第一次做的话可能要绕晕,慢慢来就好)
网址:[电脑网站支付准备工作链接](https://opendocs.alipay.com/open/01didh) 根据文档把准备工作做完即可,做第三方支付之前最好把流程搞清楚。
这是流程图:
二、下载demo测试第三方支付
下载demo地址:[电脑网站支付demo](https://opendocs.alipay.com/open/270/106291)
我下的java版本,因为用的时idea,所以下载过来转换了一下(Eclipse直接跳过)。自己先创建一个web项目
创建好后,用idea把Eclipse版本的打开,然后复制到新创建的项目中。结果如下:
pom如下
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.10.159.ALL</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
</dependency>
配置AlipayConfig:
public class AlipayConfig {
//↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
// 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
public static String app_id = "";
// 商户私钥,您的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://工程公网访问地址/alipay.trade.page.pay-JAVA-UTF-8/notify_url.jsp";
// 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
public static String return_url = "http://工程公网访问地址/alipay.trade.page.pay-JAVA-UTF-8/return_url.jsp";
// 签名方式
public static String sign_type = "RSA2";
// 字符编码格式
public static String charset = "utf-8";
// 支付宝网关(这是真实环境网关,沙箱请百度搜索)
public static String gatewayUrl = "https://openapi.alipay.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();
}
}
}
}
}
现在还运行不了,需要配置tomcat服务器:
现在可以运行了,但是会出现一个bug,当时没截图,找不到了。出问题了可以用这个解决办法,要是不行就百度吧。方法如下:
换成GBK,点击Convert键;再换回UTF-8,点击Convert键。开启服务器,成功:
如果点击支付后显示什么权限不足,可能是没有添加能力电脑网站支付并且要生效。demo测试完成,接下来完成整合进SpringBoot项目。
三、整合第三方支付进SpringBoot项目
直接在web下创建applicaliton.yml配置文件,并添加如下:
alipay:
appid: 202100133239687044
gatewayUrl: https://openapi.alipay.com/gateway.do
format: JSON
charset: utf-8
signType: RSA2
notifyUrl: http://地址/notify
returnUrl: 自己想支付完成后返回的地址
app-private-key:
alipay-public-key:
根据自己之前配置的配置就行,returnUrl可以写自己想返回的页面地址。
pom依赖:
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.10.159.ALL</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
如果有多的或者少的,见谅。
工具层:
package com.md.common;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.Resource;
@Configuration
public class AlipayConfig {
@Resource
private AlipayProperties alipayProperties;
@Bean
public AlipayClient initAlipayClient(){
return new DefaultAlipayClient(alipayProperties.getGatewayUrl(),
alipayProperties.getAppId(),alipayProperties.getAppPrivateKey(),
alipayProperties.getFormat(),alipayProperties.getCharset(),
alipayProperties.getAlipayPublicKey(),alipayProperties.getSignType());
}
}
package com.md.common;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties("alipay")
public class AlipayProperties {
private String appId;
private String gatewayUrl;
private String format;
private String charset;
private String signType;
private String appPrivateKey;
private String alipayPublicKey;
private String returnUrl;
private String notifyUrl;
}
这两个类我是写在common下的
Controller层:(因能力有限,这层代码只能去别人那搬过来的,见谅。我小改了一下)
package com.md.controller;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.domain.*;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.*;
import com.alipay.api.response.AlipayDataDataserviceBillDownloadurlQueryResponse;
import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.md.common.AlipayProperties;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
@RestController
public class AlipayController {
@Resource
private AlipayClient alipayClient;
@Resource
private AlipayProperties alipayProperties;
@RequestMapping("/pay")
public String pagePay() throws AlipayApiException {
AlipayTradePagePayModel model=new AlipayTradePagePayModel();
Random random = new Random();
Integer i = random.nextInt(1000000000);
model.setOutTradeNo(i.toString()); //商户订单号(订单号是唯一的,所以推荐使用不会与下一次重复的字符串)
model.setProductCode("FAST_INSTANT_TRADE_PAY"); //电脑网站支付销售产品码,不同的支付方式productCode不同
model.setSubject("测试"); //订单标题
model.setTotalAmount("0.01"); //订单总金额
model.setTimeoutExpress("1h"); //支付超市时间,1h后关闭
AlipayTradePagePayRequest request=new AlipayTradePagePayRequest();
request.setBizModel(model);
request.setReturnUrl(alipayProperties.getReturnUrl()); //支付成功后同步返回的url地址
request.setNotifyUrl(alipayProperties.getNotifyUrl()); //trade_success、trade_closed触发
AlipayTradePagePayResponse response= alipayClient.pageExecute(request);
return response.getBody();
}
@RequestMapping("/query")
public String query() throws Exception{
AlipayTradeQueryModel model=new AlipayTradeQueryModel();
model.setOutTradeNo("3000");
AlipayTradeQueryRequest request=new AlipayTradeQueryRequest();
request.setBizModel(model);
return alipayClient.execute(request).getTradeStatus();
}
@RequestMapping("/close")
public String close() throws Exception{
AlipayTradeCloseModel model=new AlipayTradeCloseModel();
model.setOutTradeNo("3000");
AlipayTradeCloseRequest request=new AlipayTradeCloseRequest();
request.setBizModel(model);
return alipayClient.execute(request).getBody();
}
@RequestMapping("/refund")
public String refund() throws Exception{
AlipayTradeRefundModel model=new AlipayTradeRefundModel();
model.setOutTradeNo("3000");
model.setRefundAmount("20");
model.setOutRequestNo("100"); //分批次退款时,对应的每一次退款请求号,同一订单该值不能相同
AlipayTradeRefundRequest refundRequest=new AlipayTradeRefundRequest();
refundRequest.setBizModel(model);
AlipayTradeRefundResponse refundResponse=alipayClient.execute(refundRequest);
return "退款总金额:"+refundResponse.getRefundFee();
}
@RequestMapping("/refundQuery")
public String refundQuery() throws Exception{
AlipayTradeFastpayRefundQueryModel model=new AlipayTradeFastpayRefundQueryModel();
model.setOutTradeNo("3000"); //商户订单号
model.setOutRequestNo("100"); //退款请求号
AlipayTradeFastpayRefundQueryRequest refundQueryRequest=new AlipayTradeFastpayRefundQueryRequest();
refundQueryRequest.setBizModel(model);
AlipayTradeFastpayRefundQueryResponse refundQueryResponse=alipayClient.execute(refundQueryRequest);
return "本次退款金额为:"+refundQueryResponse.getRefundAmount()+
"\n订单总金额为:"+refundQueryResponse.getTotalAmount();
}
@RequestMapping("/queryDownload")
public String downloadUrl() throws Exception{ //对账单下载地址
AlipayDataDataserviceBillDownloadurlQueryModel model=new AlipayDataDataserviceBillDownloadurlQueryModel();
model.setBillType("trade");
model.setBillDate("2020-04-06");
AlipayDataDataserviceBillDownloadurlQueryRequest request=new AlipayDataDataserviceBillDownloadurlQueryRequest();
request.setBizModel(model);
AlipayDataDataserviceBillDownloadurlQueryResponse response=alipayClient.execute(request);
return response.getBillDownloadUrl();
}
@RequestMapping("/notify")
public void notify(HttpServletRequest request) throws Exception{ //异步通知接口
if (check(request.getParameterMap())){
System.out.println("异步通知");
}else {
System.out.println("验签失败");
}
}
@RequestMapping("/return")
public String returnUrl(HttpServletRequest request) throws Exception{ //同步跳转接口
if (check(request.getParameterMap())){
return "success";
}else {
return "false";
}
}
private boolean check(Map<String,String[]> requestParams) throws Exception{
Map<String,String> params = new HashMap<>();
for (String name : requestParams.keySet()) {
String[] values = requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]
: valueStr + values[i] + ",";
}
params.put(name, valueStr);
}
return AlipaySignature.rsaCheckV1(params, alipayProperties.getAlipayPublicKey(),
alipayProperties.getCharset(), alipayProperties.getSignType()); //调用SDK验证签名
}
}
配置完毕,不用在idea写任何前端代码。只需要在前端页面写个支付链接跳转到"/pay"下即可。至此大功告成。感谢观看!