java 支付宝-沙箱支付测试
一、支付宝开放平台配置
1、登录平台:
https://open.alipay.com/develop/sandbox/app
平台分为沙箱应用,沙箱账号,沙箱工具三个模块,我们这里测试阶段仅关注前两个即可
2、获取平台必要的配置
(1)、appid:上图基本信息中的APPID
上图中,基本信息–开发信息–开启公钥模式–点击查看–获取应用私钥和支付宝公钥
(2)、appPrivateKey:
(3)、alipayPublicKey:
(4)、回调地址:notifyUrl
这个是支付宝后台调用我们支付的服务的回调接口,告诉我们实际的支付结果。需要我们自己开发,必须是post类型接口。
需要互联网环境,如果服务器已经映射了互联网的域名可以直接使用互联网域名配置接口。这里仅测试,需要本地环境打通互联网的服务,可以参考使用natapp:https://blog.csdn.net/qq_34207422/article/details/86666161
二、代码测试
1、集成pom
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-easysdk</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.22.113.ALL</version>
</dependency>
2、添加配置application
即上面说的获取的四个配置
3、环境映射
参考上面回调地址的natapp方法,将本地127.0.0.1:8000的地址映射到互联网
4、支付宝配置类
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;
@Data
@Component
@ConfigurationProperties(prefix = "alipay")
public class AliPayConfig {
private String appId;
private String appPrivateKey;
private String alipayPublicKey;
private String notifyUrl;
@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初始化成功=======");
}
}
5、支付请求实体对象
import lombok.Data;
@Data
public class AliPay {
/**
* 商户订单号
*/
private String traceNo;
/**
* 订单金额
*/
private double totalAmount;
/**
* 订单标题
*/
private String subject;
private String alipayTraceNo;
}
6、测试控制类
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.easysdk.factory.Factory;
import com.zw.base.BaseController;
import com.zw.study.alipay.config.AliPayConfig;
import com.zw.study.alipay.dto.AliPay;
import io.swagger.annotations.ApiOperation;
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 javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("alipay")
@Transactional(rollbackFor = Exception.class)
public class AliPayController extends BaseController {
@Resource
AliPayConfig aliPayConfig;
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
@ApiOperation("支付宝支付")
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.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 {
System.out.println("=========支付宝异步回调========");
if (request.getParameter("trade_status").equals("TRADE_SUCCESS")) {
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";
}
}
7、测试支付
(1)、调用支付接口
(2)、请求会自动调起支付宝支付,这里是沙箱环境所以如下:
(3)、官方平台提供了一个买家账号,这里我们可以直接拿来使用
(4)、登录后,输入支付密码
(5)、支付完成的提示
(6)、查看回调接口
这里的回调接口我仅打印了一下基本信息,如果真实系统这里还需要处理自身的保存业务。
三、总结
沙箱环境是支付宝官方提供给我们测试用的一个环境,相对而言使用也比较简单。注意有几个点,回调必须是post接口,订单号traceNo必须唯一不可随意创建等。
学海无涯苦作舟!!!
原文地址:https://blog.csdn.net/qq_34207422/article/details/140267922
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!