目录
支付宝支付介绍
一、沙箱环境_介绍
(一)简介
沙箱环境 (Beta) 是支付宝开放平台为开发者提供的与线上环境完全隔离的联调测试环境,在沙箱环境中完成的调用不会对线上数据造成任何影响,尤其适合涉及资金链路的能力的调试。
注意:
- 由于沙箱为模拟环境,在沙箱完成接口开发及主要功能调试后,请务必在正式环境进行完整的功能验收测试。所有返回码及业务逻辑以正式环境为准。
- 为保证沙箱稳定,沙箱环境测试数据会进行定期数据清理。Beta 测试阶段每周日中午 12 点至每周一中午 12 点为维护时间,在此时间内沙箱环境部分功能可能不可用,敬请谅解。
- 请勿在沙箱进行压力测试,以免触发相应的限流措施,导致无法正常使用沙箱环境。
**网址:**https://opendocs.alipay.com/common/02kkv7
(二)沙箱账号和沙箱应用
https://open.alipay.com/develop/sandbox/app
(三)支付宝客户端沙箱版
实时效果反馈
1.支付宝支付提供沙箱环境主要作用是*__**__*___。
A 娱乐使用
B 解决线上支付环境安全性
C 与线上环境完全隔离的测试环境
D 以上都是错误
2.支付宝客户端沙箱版,目前沙箱钱包仅提供*__**__*___版本。
A Android
B IOS
C APP
D 以上都是错误
答案
1=>C 2=>A
(四)沙箱秘钥
在沙箱进行调试前需要确保已经配置密钥/证书用于加签,支付宝提供了 系统默认密钥 及 自定义密钥 两种方式进行配置。
设置沙箱应用的公钥和私钥
开发者如需使用系统默认密钥/证书,可在 开发信息 中选择 系统默认密钥。
安装支付宝开放平台助手
下载支付宝开放平台助手https://opendocs.alipay.com/common/02khjo
生成密钥
详细步骤:
会自动生成商户应用公钥和应用私钥。
点击“打开密钥文件路径”,即可找到生成的公私钥。
注意:
生成的私钥需妥善保管,避免遗失,不要泄露。应用私钥需填写到代码中供签名时使用。应用公钥需提供给支付宝账号管理者上传到支付宝开放平台。
保存设置
二、沙箱支付
1、支付环境准备
1)沙箱环境准备
登录支付宝开放平台:https://open.alipay.com/
在支付宝开放平台左上角点击“控制台”,会出现如下界面:
在最下方有个沙箱,点进去,就进入沙箱环境了:
在支付宝沙箱环境中能找到APPID和网关和秘钥配置(这里选择自定义秘钥)
2)秘钥生成及配置
下载地址:https://opendocs.alipay.com/common/02kipk?pathHash=0d20b438
选择自己的操作系统下载即可,我这里是 Windows
下载完成后,生成密钥
生成应用公钥和应用私钥
应用公钥:用于在下方生成支付宝公钥。
配置接口加签方式
按步骤 查看 -> 复制刚刚生成的应用公钥到下图 -> 保存
然后我们就接入了支付宝开放平台
点击确定即可
2、内网穿透环境准备
NATAPP:https://natapp.cn/
1)创建隧道
先在注册一个新的账号
然后购买一个免费隧道
在 我的隧道 里面有刚刚购买的隧道
记住这里有个 authtoken,等下有用
2)修改隧道配置
修改端口为:8081
3)下载客户端
点击右上角客户端,下载对应的版本
下载完成之后为下图的 natapp.exe
运行 natapp.exe
**注意:**这里面不是点击运行。
通过在地址栏里面输入cmd命令,回车,打开命令提示窗口:
输入以下命令:
natapp.exe -authtoken=你的authtoken
启动成功如下图:
3、后端开发
1)引入阿里Maven坐标
<!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-easysdk -->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.9.28.ALL</version>
</dependency>
2)服务端代码配置
参数配置:
需要准备如下代码配置:
- 支付宝网关地址:https://openapi-sandbox.dl.alipaydev.com/gateway.do
- APPID:支付宝开发平台中的APPID
- 签名方式:RSA2
- 应用公钥、应用私钥:存在于 密钥工具中
创建沙箱支付配置文件 application.yaml
alipay:
appId: 你的APPID
merchantPrivateKey: 你的应用私钥
alipayPublicKey: 你的应用公钥
notifyUrl: http://内网穿透地址/api/alipay/notify
returnUrl: http://member.zyz.com/memberOrder.html
signType: RSA2
charset: utf-8
# 我的支付宝网关地址
gatewayUrl: https://openapi-sandbox.dl.alipaydev.com/gateway.do
创建订单实体类:
package com.student.Pojo;
//import com.baomidou.mybatisplus.annotation.IdType;
//import com.baomidou.mybatisplus.annotation.TableField;
//import com.baomidou.mybatisplus.annotation.TableId;
//import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.ToString;
import java.io.Serializable;
import java.util.Date;
/**
* 接口次数订单表
* @TableName order
*/
@ToString
//@TableName(value ="`order`")
@Data
public class Order implements Serializable {
/**
* 订单Id
*/
// @TableId(type = IdType.ASSIGN_UUID)
private Long id;
/**
* 用户Id
*/
private Long userId;
/**
* 接口Id
*/
private Long interfaceInfoId;
/**
* 支付金额
*/
private Double money;
/**
* 支付方式
*/
private String paymentMethod;
/**
* 0 - 未支付 1 - 已支付
*/
private Integer status;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
/**
* 是否删除
*/
private Integer isDelete;
// @TableField(exist = false)
private static final long serialVersionUID = 1L;
}
支付模板
这里PC端网页支付模板,我准备了两个,1是输入账号密码支付,2是沙箱支付宝扫码支付。两种
账号密码支付模板
创建支付配置类,使用@Value
注解将配置文件中的属性值映射到对应的属性中
package com.wei.project.manager;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.wei.weiapicommon.model.entity.Order;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@ConfigurationProperties(prefix = "alipay")
@Component
@Data
public class AlipayTemplate {
// 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
@Value("{alipay.appId}")
public String appId;
// 应用私钥,就是工具生成的应用私钥
@Value("{alipay.merchantPrivateKey}")
public String merchantPrivateKey;
// 支付宝公钥,对应APPID下的支付宝公钥。
@Value("{alipay.alipayPublicKey}")
public String alipayPublicKey;
// 支付宝会悄悄的给我们发送一个请求,告诉我们支付成功的信息
@Value("{alipay.notifyUrl}")
public String notifyUrl;
//同步通知,支付成功,一般跳转到成功页
@Value("{alipay.returnUrl}")
public String returnUrl;
// 签名方式
@Value("{alipay.signType}")
private String signType;
// 字符编码格式
@Value("{alipay.charset}")
private String charset;
//订单超时时间
private String timeout = "1m";
// 支付宝网关;https://openapi-sandbox.dl.alipaydev.com/gateway.do
@Value("{alipay.gatewayUrl}")
public String gatewayUrl;
public String pay(Order order) throws
AlipayApiException {
//1、根据支付宝的配置生成一个支付客户端
AlipayClient alipayClient = new
DefaultAlipayClient(gatewayUrl, appId, merchantPrivateKey,
"json", charset, alipayPublicKey, signType);
//2、创建一个支付请求,并设置请求参数
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
alipayRequest.setReturnUrl(returnUrl);
alipayRequest.setNotifyUrl(notifyUrl);
Long id = order.getId();
Long interfaceInfoId = order.getInterfaceInfoId();
Double money = order.getMoney();
String paymentMethod = order.getPaymentMethod();
alipayRequest.setBizContent(" {\"out_trade_no\":\"" + id + "\","
+ "\"total_amount\":\"" + money + "\","
+ "\"subject\":\"" + interfaceInfoId
+ "\","
+ "\"body\":\"" + paymentMethod + "\","
+
"\"timeout_express\":\"" + timeout + "\","
+
"\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
String result = alipayClient.pageExecute(alipayRequest).getBody();
//会收到支付宝的响应,响应的是一个页面,只要浏览器显示这个页面,就会自动来到支付宝的收银台页面
System.out.println("支付宝的响应:" + result);
return result;
}
}
扫码支付模板
package com.student.config;
import cn.hutool.json.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.student.Pojo.Order;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
//输入账号密码支付
@ConfigurationProperties(prefix = "alipay")
@Component
@Data
public class AlipayTemplate2 {
// 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
@Value("{alipay.appId}")
public String appId;
// 应用私钥,就是工具生成的应用私钥
@Value("{alipay.merchantPrivateKey}")
public String merchantPrivateKey;
// 支付宝公钥,对应APPID下的支付宝公钥。
@Value("{alipay.alipayPublicKey}")
public String alipayPublicKey;
// 支付宝会悄悄的给我们发送一个请求,告诉我们支付成功的信息
@Value("{alipay.notifyUrl}")
public String notifyUrl;
//同步通知,支付成功,一般跳转到成功页
@Value("{alipay.returnUrl}")
public String returnUrl;
// 签名方式
@Value("{alipay.signType}")
private String signType;
// 字符编码格式
@Value("{alipay.charset}")
private String charset;
//订单超时时间
private String timeout = "1m";
// 支付宝网关;https://openapi-sandbox.dl.alipaydev.com/gateway.do
@Value("{alipay.gatewayUrl}")
public String gatewayUrl;
public String pay(Order order) throws
AlipayApiException {
//1、根据支付宝的配置生成一个支付客户端
AlipayClient alipayClient = new
DefaultAlipayClient(gatewayUrl, appId, merchantPrivateKey,
"json", charset, alipayPublicKey, signType);
//2、创建一个支付请求,并设置请求参数
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
alipayRequest.setReturnUrl(returnUrl);
alipayRequest.setNotifyUrl(notifyUrl);
JSONObject bizContent = new JSONObject();
bizContent.set("out_trade_no", order.getId()); // 我们自己生成的订单编号
bizContent.set("total_amount", order.getMoney()); // 订单的总金额
bizContent.set("subject", "XXX医院支付"); // 支付的名称
bizContent.set("product_code", "FAST_INSTANT_TRADE_PAY"); // 固定配置
bizContent.set("body", "XXX医院收费单");
bizContent.set("timeout_express", "30m"); // 订单的超时时间
alipayRequest.setBizContent(bizContent.toString());
String result = alipayClient.pageExecute(alipayRequest).getBody();
//会收到支付宝的响应,响应的是一个页面,只要浏览器显示这个页面,就会自动来到支付宝的收银台页面
// System.out.println("支付宝的响应:" + result);
return result;
}
}
控制层代码
package com.student.controller;
import cn.hutool.core.bean.BeanUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.student.Pojo.Order;
import com.student.config.AlipayTemplate;
import com.student.config.AlipayTemplate2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
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.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* 支付宝接口
*/
@RestController
@RequestMapping("/alipay")
public class AliPayController {
//扫码支付模板
// @Resource
// AlipayTemplate alipayTemplate;
//账号密码支付模板
@Autowired
AlipayTemplate2 alipayTemplate;
@GetMapping(value = "/pay", produces = "text/html;charset=utf-8")
public String pay(@RequestParam("id") long id) throws AlipayApiException, IOException {
Order order = new Order();
order.setId(120948759374234L);//每次请求一定要不一致
order.setUserId(129905052947L);
order.setInterfaceInfoId(294389572235L);
order.setMoney(65.0);
order.setPaymentMethod("支付宝");
return alipayTemplate.pay(order);
}
@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));
// System.out.println(name + " = " + request.getParameter(name));
}
String tradeNo = params.get("out_trade_no");
String gmtPayment = params.get("gmt_payment");
String alipayTradeNo = params.get("trade_no");
// 支付宝验签
boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayTemplate.alipayPublicKey, alipayTemplate.getCharset(), alipayTemplate.getSignType()); //调用SDK验证签名
System.out.println(signVerified);
if (signVerified) {
// 验签通过
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";
}
}
启动类
package com.student.alipay;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan("com.student.*")
@SpringBootApplication
public class AliPayApplication {
public static void main(String[] args) {
SpringApplication.run(AliPayApplication.class, args);
}
}
3)前端测试
前端通过传入订单 id 的方式去支付订单
在浏览器输入:http://localhost:8081/alipay/pay?id=167,如果页面成功跳转,则配置成功。
**注意:**如果出现订单参数错误,请将订单ID修改一下,务必保证每次请求订单号不一致。
页面跳转成功后会出现如下界面: