电脑网站支付宝支付
前期工作准备如下:
支付宝AppId
支付宝公钥、应用公钥、私钥
这些信息可以在蚂蚁金服平台获取到,具体怎么获取可以查看搜索教程。然后配置好之后,就可以在自己的代码中进行实现.
注意这些
支付流程为 :
1.支付宝支付
2.异步回调
3.同步回调 不能返回JSON格式
这里应该会问 “异步回调” 和 “同步回调” 的区别,用白话来讲
异步回调: 其实是处理业务逻辑,比如说修改客户的支付状态
同步回调: 用户在支付宝页面付款完毕后自动跳转
代码中需要在配置类中引入,自己生成的公私钥
这一步中生成的公钥和私钥,私钥自己一定要保存好,要配置到 AlipayConfig 配置类中
把生成的公钥配置支付宝平台上,会自动带有 应用公钥 和 支付宝公钥
AlipayConfig 实体类中:配置为支付宝公钥 私钥就是生成唯一的一个私钥
下面上代码
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-easysdk</artifactId>
<version>2.1.2</version>
</dependency>
@Configuration
public class AlipayConfig {
// 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号,开发时使用沙箱提供的APPID,生产环境改成自己的APPID
public static String app_id="2021002104675003";
//私钥,您的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这类自定义参数,必须外网可以正常访问(可以使用natapp内容穿透完成外网设置)
public static String notify_url="http://XXX/dev/member/v1/aliPayCallBack";
//页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
public static String return_url="http://XXX/return/v1/returnUrl";
//签名方式
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 = "E:\\";
/**
* 写日志,方便测试(看网站需求,也可以改成把记录存入数据库)
* @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();
}
}
}
}
入参实体类,注意必填项
@Data
public class AliPayReq {
/**
* 商户订单号,必填
*/
// private String out_trade_no; 我是在代码中生成的唯一订单编号,所以没传,注意是必填项
/**
* 订单名称,必填
*/
private String subject;
/**
* 付款金额,必填
*/
private String total_amount;
/**
* 商品描述,可空
*/
private String body;
/**
* 超时时间参数
*/
// private String timeout_express; 在代码中进行设置的需要注意哦
private String product_code="FAST_INSTANT_TRADE_PAY";
/**
* 这两个参数为:自己需要做业务逻辑处理,传入的参数
*/
private Long userId;
private Long vipInfoId;
}
支付宝支付代码, 该方法的返回值,是HTML页面,返回给前端,交给前端进行解析
/**
* 支付宝支付
*/
@PostMapping("/v1/alipay")
public Object alipayLine(AliPayReq req) throws AlipayApiException {
return CommSuccessDataResp.create(aliPayService.aliPayLine(req.getSubject(), req.getBody(), req.getTotal_amount(),req.getUserId(),req.getVipInfoId()));
}
ServiceImpl 因为在异步回调时我需要用到自己的参数所以,使用以下方式进行封装参数,并没有使用setBizContent()这个方法进行封装发,使用setBizModel()进行封装参数,注意看代码
public Object aliPayLine(String subject, String body, String total_amount, Long userId, Long vipInfoId) throws AlipayApiException {
// 创建实体类封装自己的参数
ModelReq modelReq = new ModelReq();
modelReq.setUserId(userId);
modelReq.setVipInfoId(vipInfoId);
//获得初始化的AlipayClient
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);
// 生成订单编号
String out_trade_no = String.valueOf(ClientTool.randomNumber());
// 设置请求参数
String timeout_express = "30m";
AlipayTradePagePayRequest aliRequest = new AlipayTradePagePayRequest();
// 封装参数,以及自己需要的参数 如果请求时传递了该参数,则返回给商户时会回传该参数。支付宝会在异步通知时将该参数原样返回
AlipayTradePagePayModel model = new AlipayTradePagePayModel();
model.setOutTradeNo(out_trade_no);
model.setTotalAmount(total_amount);
model.setSubject(subject);
model.setBody(body);
model.setTimeoutExpress(timeout_express);
model.setProductCode("FAST_INSTANT_TRADE_PAY");
// 创建转换对象,用于转换数据格式
Gson gson = new Gson();
// 转换为json
String param = gson.toJson(modelReq);
model.setPassbackParams(param);
// 设置回调地址
aliRequest.setReturnUrl(AlipayConfig.return_url);
aliRequest.setNotifyUrl(AlipayConfig.notify_url);
aliRequest.setBizModel(model);
// aliRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
// + "\"total_amount\":\"" + total_amount + "\","
// + "\"subject\":\"" + subject + "\","
// + "\"body\":\"" + body + "\","
// + "\"timeout_express\":\"" + timeout_express + "\","
// + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
//请求,返回的数据由前端进行解析
return alipayClient.pageExecute(aliRequest).getBody();
}
/**
* 获取阿里支付回调的数据拼装 验签,该方法在同步回调,异步回调时,必须要用到的
*/
public Map<String, String> getAliParams(Map requestParams) {
Map<String, String> params = new HashMap<String, String>();
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
String name = (String) iter.next();
String[] values = (String[]) 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);
}
System.out.println("============支付回调=============" + params);
System.out.println(params.get("out_trade_no"));
return params;
}
这样支付功能就已经搞定,接下来要进行 异步回调 和 同步回调 的代码编写
/**
* 异步回调
*/
@PostMapping("/v1/aliPayCallBack")
public Object notify_url(HttpServletRequest request, HttpServletResponse response) throws Exception {
//获取支付宝POST过来反馈信息
Map<String, String> params = aliPayService.getAliParams(request.getParameterMap());
System.out.println("回调返回值======="+params);
//验证签名
boolean flag = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, "UTF-8", "RSA2");
// 创建自定义的参数对象
ModelReq modelReq = new ModelReq();
// 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表
String orderNo = request.getParameter("out_trade_no"); // 获取订单编号
String trade_status = request.getParameter("trade_status"); // 交易状态
System.out.println("交易状态======="+trade_status);
// 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表
if (flag) {// 验证成功
if (trade_status.equals("TRADE_SUCCESS")) {
System.out.println("支付宝订单支付成功!");
Gson gson = new Gson();
//在支付接口中传入自己的参数
ModelReq passBack = gson.fromJson(params.get("passback_params"), modelReq.getClass());
// TODO 在这里进行自己的业务逻辑处理,修改会员状态
memberService.openMemberSuccess(passBack.getUserId(),passBack.getVipInfoId(), "支付宝支付");
}
//这里通知支付宝回调成功,不然一直回调
return "success";
} else {
System.out.println("签名验证不通过");
return "failure";
}
}
同步回调代码,懒得更改注解,就直接创建了一个类
@Controller
@RequestMapping("/return")
public class ReturnUrlController {
@Autowired
private AliPayServiceImpl aliPayService;
/**
* 同步回调, 注意get请求
*/
@RequestMapping("/v1/returnUrl")
public void return_url(HttpServletRequest request, HttpServletResponse response) throws AlipayApiException {
// 调用方法进行验签
Map<String, String> paramsMap = aliPayService.getAliParams(request.getParameterMap());
boolean flag = AlipaySignature.rsaCheckV1(paramsMap, AlipayConfig.alipay_public_key, "UTF-8", "RSA2");
if(flag){
//跳转支付成功界面
try {
response.sendRedirect("https://www.baidu.com");
} catch (IOException e) {
e.printStackTrace();
}
}else {
System.out.println("flag=====验签失败");
//跳转支付失败界面
}
}
}
这样就是PC端支付宝支付的完整流程和代码,如有疑问就请留言哦,代码中注释已经写清楚,注意看啊