支付宝支付之App支付

时间:2022-08-20 16:17:32

与微信支付对比,支付宝支付就没有那么多坑了,毕竟支付宝开放平台的文档还是描述的很详细的。

支付宝开放平台地址:https://docs.open.alipay.com/204/105297/

支付宝支付的流程如下图所示:

支付宝支付之App支付

项目中接入支付宝支付的步骤:

在这里分为了三个文件进行整理:

  1. 基础信息配置文件:AlipayConfig.java
  2. 调用API接口:AliPayUtil.java
  3. 对外接口:AlipayController.java

AlipayConfig.java

此文件中主要是配置了应用ID、支付宝公钥、应用密钥等基础信息,以及支付宝支付API提供的对外接口地址信息。

 package com.xhgx.web.pay.aliPay;

 import com.erenju.util.GlobleConfig;

 /**
* 支付宝支付基础信息配置
* @author rxn
* @date 2018/04/25
*/
public class AlipayConfig { /**
* 合作身份者ID,签约账号,16位纯数字
*/
public static String partner = "2088******";
/**
* 收款支付宝账号,一般情况下收款账号是签约账号
*/
public static String seller_id = partner;
/**
* appid
*/
public static String app_id = "2018*****";//正式
// public static String app_id = "2016*****";//沙箱
/**
* MD5密钥,32位字符串
*/
public static String key = "******";
/**
* 支付宝公钥 (使用工具生成)
*/
public static String public_key = "";//正式
/**
* 应用密钥 (特别长)
*/
public static String private_key = ""; /**
* 服务器异步通知页面路径,需http://格式的完整路径,不能加自定义参数,必须外网可以正常访问
* 异步通知页面,就是接受支付宝支付结果返回信息的Contrller,可以处理自己的支付后的逻辑
*/
public static String notify_url = GlobleConfig.getProperty("PayNotifyUrl")+"/alipay/notify.json";
/**
* 服务器同步通知页面路径,需http://格式的完整路径,不能加自定义参数,必须外网可以正常访问
* 同步通知页面,就是支付宝支付成功后页面跳转的url
*/
public static String return_url = GlobleConfig.getProperty("PayNotifyUrl")+"/alipay/return.json";
/**
* 签名方式 ,(必须与生成密钥的签名方式一致)
*/
// public static String sign_type = "MD5";
public static String sign_type = "RSA2";
/**
* 日志文件
*/
public static String log_path = "";
/**
* 字符编码格式
*/
public static String charset = "utf-8";
/**
* 返回格式
*/
public static String format = "json";
/**
* 支付类型
*/
public static String payment_type = "1";
/**
* 支付宝网关(app支付接口)
*/
public static String AppPayUrl = "https://openapi.alipay.com/gateway.do";//线上
// public static String AppPayUrl = "https://openapi.alipaydev.com/gateway.do";//调试
}

AliPayUtil.java

此文件为工具类文件,实现了调用支付宝API提供的一些接口,下面的代码中主要包含了调用支付的接口和统一查询支付结果的接口。

 package com.xhgx.web.pay.aliPay;

 import java.net.URLEncoder;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import org.activiti.engine.repository.Model;
import org.springframework.security.web.header.writers.frameoptions.StaticAllowFromStrategy;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse; /**
* 支付宝支付调用API接口
* @author rxn
* @date 2018/04/28
*
*/
public class AliPayUtil { /**
* 创建订单
* @param orderId 订单id
* @param total_amount 付款金额(单位:元)
* @return
* @throws AlipayApiException
*/
public static Map<String, Object> createOrder(String orderId,String total_amount) throws AlipayApiException{ String orderStr = "";
Map<String,Object> m = new HashMap<String, Object>();
try {
//封装订单
Map<String, String> orderMap = new LinkedHashMap<String,String>();
//公共参数
Map<String, String> bizModel = new LinkedHashMap<String,String>(); //商品参数封装
orderMap.put("out_trade_no",orderId);//商户订单号,必填
orderMap.put("subject", "*****");//订单名称,必填
// orderMap.put("total_amount", total_amount);//付款金额,必填
orderMap.put("total_amount", 0.01+"");//付款金额,必填
orderMap.put("body", "");//商品描述,选填
orderMap.put("timeout_express", "30m");//超时时间,选填
orderMap.put("prodect_code", "QUICK_MSECURITY_PAY");//销售产品码 //公共参数封装
bizModel.put("app_id", AlipayConfig.app_id);//appId
bizModel.put("method", AlipayConfig.AppPayUrl);//请求网关地址
bizModel.put("format", AlipayConfig.format);//返回格式
bizModel.put("private_key", AlipayConfig.private_key);//密钥 //实例化客户端,只需要实例化一次即可
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.AppPayUrl, AlipayConfig.app_id, AlipayConfig.private_key, "json", AlipayConfig.charset, AlipayConfig.public_key, AlipayConfig.sign_type);
//实例化具体API对应的request类,类名称和接口名称对应
AlipayTradeAppPayRequest ali_request = new AlipayTradeAppPayRequest(); //传入参数,sdk已经封装了公共参数,这里只需传入业务参数。
//以下方法是sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
// model.setPassbackParams(URLEncoder.encode(orderMap.get("body")));//公用回传参数,选填,UrlEncode之后才可以发送给支付宝。
model.setBody(orderMap.get("body"));//商品信息
model.setSubject(orderMap.get("subject"));//商品名称
model.setOutTradeNo(orderMap.get("out_trade_no"));//商品订单号
model.setTimeoutExpress(orderMap.get("timeout_express"));//交易超出时间
model.setTotalAmount(orderMap.get("total_amount"));//总金额
model.setProductCode(orderMap.get("prodect_code"));//销售产品码
model.setSellerId(AlipayConfig.seller_id);//支付宝用户id
ali_request.setBizModel(model);
ali_request.setNotifyUrl(AlipayConfig.notify_url);//回调地址 AlipayTradeAppPayResponse response = alipayClient.sdkExecute(ali_request);
orderStr = response.getBody(); if(response.isSuccess()){
m.put("result", orderStr);
m.put("code", 0);
m.put("msg", "订单生成成功");
}else{
m.put("code", 1);
m.put("msg", "订单生成失败");
} } catch (Exception e) {
// TODO: handle exception
m.put("code", 1);
e.printStackTrace();
m.put("msg", "订单生成失败");
} return m;
}
/**
* 查询订单
* @param orderId 订单id
* @return
* @throws AlipayApiException
*/
public static Map<String, Object> getOrder(String orderId) throws AlipayApiException{
System.out.println("查询支付结果");
Map<String,Object> m = new HashMap<String, Object>();
try {
//封装订单
Map<String, String> orderMap = new LinkedHashMap<String,String>();
//商品参数封装
orderMap.put("out_trade_no",orderId);//商户订单号,必填 //实例化客户端
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.AppPayUrl, AlipayConfig.app_id, AlipayConfig.private_key, "json", AlipayConfig.charset, AlipayConfig.public_key, AlipayConfig.sign_type);
//实例化具体API对应的request类,类名称和接口名称对应
AlipayTradeQueryRequest ali_request = new AlipayTradeQueryRequest(); //传入参数,sdk已经封装了公共参数,这里只需传入业务参数。
//以下方法是sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
model.setOutTradeNo(orderMap.get("out_trade_no"));//商品订单号
ali_request.setBizModel(model);
ali_request.setNotifyUrl(AlipayConfig.notify_url);//回调地址 AlipayTradeQueryResponse response = alipayClient.execute(ali_request);
System.out.println(response.getCode()+"---"+response.getMsg());
if(response.isSuccess()){
System.out.println(response.getTradeStatus());
switch (response.getTradeStatus()) {
case "TRADE_FINISHED"://交易结束并不可退款
m.put("status", "OK");
break;
case "TRADE_SUCCESS"://交易支付成功
m.put("status", "OK");
break;
case "TRADE_CLOSED"://未付款交易超时关闭或支付完成后全额退款
m.put("status", "ERROR");
break;
case "WAIT_BUYER_PAY"://交易创建并等待买家付款
m.put("status", "ERROR");
break;
default:
m.put("status", "ERROR");
break;
} m.put("code", 0);
m.put("msg", "订单生成成功");
}else{
m.put("code", 1);
m.put("msg", "订单生成失败");
} } catch (Exception e) {
m.put("code", 1);
e.printStackTrace();
m.put("msg", "订单生成失败");
} return m;
}
}

AlipayController.java

此文件中主要是对外的异步通知接口,异步通知接口和同步通知接口性质是一样的,都是为了接收支付后平台返回的信息,下面的代码中只实现了异步通知接口。

 package com.xhgx.web.pay.aliPay;

 import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.xhgx.service.PayNotifyTblService;
import com.xhgx.service.domain.PayNotifyTbl;
import com.xhgx.web.SpringContextUtil;
import common.Logger; @Controller
public class AlipayController { public static Logger log = Logger.getLogger(AlipayController.class); /**
* 支付宝支付成功后,异步通知,回调该接口
* @param request
* @param response
* @return
*/
@ResponseBody
@RequestMapping("/alipay/notify.json")
public static String notifyUrl(HttpServletRequest request,HttpServletResponse response){
log.info("支付宝支付:"+"异步通知");
Map<String, String> params = new HashMap<String, String>(); //1.从支付宝回调的request中取值
Map<String, String[]> requestParams = request.getParameterMap(); for(Iterator<String> iter = requestParams.keySet().iterator();iter.hasNext();){
String name = iter.next();
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] + ",";
}
//乱码解决
// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
params.put(name, valueStr);
} //2.封装必须的参数
String out_trade_no = request.getParameter("out_trade_no");
String orderType = request.getParameter("body");
String tradeStatus = request.getParameter("trade_status");
String app_id = request.getParameter("app_id");
String trade_no = request.getParameter("trade_no");//支付宝交易号
String notify_time = request.getParameter("notify_time");//通知时间
String total_amount = request.getParameter("total_amount");//订单金额,单位元 //3.签名验证(对支付宝返回的数据验证,确定是支付宝返回的)
boolean signVerified = false;
//3.1调用SDK验证签名
try {
signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.public_key, AlipayConfig.charset,AlipayConfig.sign_type);
} catch (AlipayApiException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} if(payNotifyTblService==null){
payNotifyTblService= (PayNotifyTblService) SpringContextUtil.getBean(PayNotifyTblService.class);
} //创建有一个对象,保存通知信息,根据业务需求来决定
PayNotifyTbl payNotifyTbl = new PayNotifyTbl();
payNotifyTbl.setPay_type(2);//支付类型:2支付宝
payNotifyTbl.setCreate_dt(new Date()); payNotifyTbl.setReturn_code(tradeStatus);
payNotifyTbl.setResult_code(tradeStatus); //4.对验签进行处理
if(signVerified){
if(tradeStatus.equals("TRADE_SUCCESS")){ //支付成功,进行业务处理 payNotifyTbl.setAppid(app_id);
payNotifyTbl.setOrder_id(out_trade_no);
payNotifyTbl.setTotal_fee(Double.parseDouble(total_amount));
payNotifyTbl.setTransaction_id(trade_no);
payNotifyTbl.setTime_end(notify_time);
payNotifyTbl.setPay_result("交易成功"); payNotifyTbl = payNotifyTblService.save(payNotifyTbl); return "success";
}else{
payNotifyTbl.setPay_result("参数有误");
payNotifyTbl = payNotifyTblService.save(payNotifyTbl);
log.info("参数有误");
return "fail";
}
}else{
payNotifyTbl.setPay_result("交易失败");
payNotifyTbl = payNotifyTblService.save(payNotifyTbl);
log.info("交易失败");
return "fail";
}
}else{
payNotifyTbl.setPay_result("验签失败");
payNotifyTbl = payNotifyTblService.save(payNotifyTbl);
log.info("验签失败");
return "fail";
}
} /**
* 支付宝支付成功后,同步通知
* @param request
* @param response
* @return
*/
@ResponseBody
@RequestMapping("/alipay/return.json")
public static String returnUrl(HttpServletRequest request,HttpServletResponse response){
log.info("支付宝支付:"+"同步通知"); return null;
}
}

开发中用到的工具包:https://files.cnblogs.com/files/ning0628/alipay-sdk-JAVA-3.0.0.zip;https://files.cnblogs.com/files/ning0628/alipaytradeapppay.zip