相比较微信支付来说,个人感觉支付宝对开发者的友好度要好点,整理了一下之前项目中做的这个功能:
准备工作:
maven需要引入com.alipay.sdk:
com.alipay.sdk
alipay-sdk-java
3.0.0
AlipayConfig:
public class AlipayConfig {
/** 支付宝支付业务:入参app_id */
public static final String APPID = "此处为appid";
/** 支付宝网关*/
public static final String GATE = "https://openapi.alipay.com/gateway.do";
/** (应用私钥)*/
public static final String APP_PRIVATE_KEY = "此处填写应用密钥";
/** (应用公钥)*/
public static final String ALIPAY_PUBLIC_KEY = "此处填写应用公钥";
/** 支付宝公钥 */
public static final String PUBLIC_KEY = "此处为支付宝公钥";
/** 合作伙伴ID(支付宝给定) */
public static final String SELLERID = "此处为sellerid,支付宝针对每个apk都有特定的id";
/** 商户账户 */
public static final String SELLER = "此处为商户账号";
/** 编码方式 */
public static final String CHARSET = "utf-8";
public AlipayConfig() {
}
}
基础的参数配置如上,应该没有什么困难;
这里是实例化支付宝客户端时需要的参数, 可以参考支付宝开发文档:https://docs.open.alipay.com/204/105297/
AlipayUtil:
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
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.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
public class AlipayUtil {
private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(AlipayUtil.class);
/**
* 创建商户订单 请求支付宝
* @param amount
* @param random
* @return
*/
public static String getsign(String amount,String random){
//实例化客户端
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.GATE,
AlipayConfig.APPID,
AlipayConfig.APP_PRIVATE_KEY,
"json", AlipayConfig.CHARSET,
AlipayConfig.ALIPAY_PUBLIC_KEY,
"RSA2");
if (Double.valueOf(amount) <= 0){ // 一些必要的验证,防止抓包恶意修改支付金额
return null;
}
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setBody("我是测试数据");
model.setSubject("祺科信息");
model.setOutTradeNo(random); //订单号
model.setTimeoutExpress("30m"); // 该参数数值不接受小数点, 如 1.5h,可转换为 90m。
model.setTotalAmount(amount); // 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]这里调试每次支付1分钱,在项目上线前应将此处改为订单的总金额
model.setProductCode("QUICK_MSECURITY_PAY");// 销售产品码,商家和支付宝签约的产品码,为固定值QUICK_MSECURITY_PAY
request.setBizModel(model);
// 设置后台异步通知的地址,在手机端支付成功后支付宝会通知后台,手机端的真实支付结果依赖于此地址
request.setNotifyUrl("http://catering.saimark.xusage.com/catering/a/RechargeUpdateFromAlipayNotify.xml");
AlipayTradeAppPayResponse response = new AlipayTradeAppPayResponse();
try {
//这里和普通的接口调用不同,使用的是sdkExecute
response = alipayClient.sdkExecute(request);
System.out.println(response.getBody());//就是orderString 可以直接给客户端请求,无需再做处理。
} catch (Exception e) {
e.printStackTrace();
}
return response.getBody();
}
/**
* 支付宝支付成功后.异步请求该接口
* @param requestParams
* @return
*/
public static String aliPay_notify(Map requestParams){
System.out.println("支付宝支付结果通知"+requestParams.toString());
//获取支付宝POST过来反馈信息
Map params = new HashMap();
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] + ",";
}
//乱码解决,这段代码在出现乱码时使用。
//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
params.put(name, valueStr);
}
//切记alipaypublickey是支付宝的公钥,请去open.alipay.com对应应用下查看。
//boolean AlipaySignature.rsaCheckV1(Map params, String publicKey, String charset, String sign_type)
try {
boolean flag = AlipaySignature.rsaCheckV1(params, AlipayConfig.PUBLIC_KEY, AlipayConfig.CHARSET, "RSA2");
if(flag){
if("TRADE_SUCCESS".equals(params.get("trade_status"))){
//付款金额
String amount = params.get("buyer_pay_amount");
//商户订单号
String out_trade_no = params.get("out_trade_no");
//支付宝交易号
String trade_no = params.get("trade_no");
//附加数据
String passback_params = URLDecoder.decode(params.get("passback_params"));
LOGGER.debug("将要存入数据库的参数"+ amount+","+out_trade_no+","+trade_no+","+passback_params);
}
}
} catch (AlipayApiException e) {
e.printStackTrace();
}
return "success";
}
/**
* 从request中获得参数Map,并返回可读的Map
*
* @param request
* @return
*/
@SuppressWarnings("unchecked")
public static Map getParameterMap(HttpServletRequest request) {
// 参数Map
Map properties = request.getParameterMap();
LOGGER.debug("包装参数:"+properties);
// 返回值Map
Map returnMap = new HashMap();
Iterator entries = properties.entrySet().iterator();
Map.Entry entry;
String name = "";
String value = "";
while (entries.hasNext()) {
entry = (Map.Entry) entries.next();
name = (String) entry.getKey();
Object valueObj = entry.getValue();
if(null == valueObj){
value = "";
}else if(valueObj instanceof String[]){
String[] values = (String[])valueObj;
for(int i=0;i
当app端传入参数请求java服务端时候,调用AlipayUtil.getsign(),获取sign值, getsign()传入的参数可以根据自己需求变化,做相应调整即可,一般来说app端只用后台返回给appid,private_key, orderInfo(即sign)三个参数即可;其他的事情交给Android端处理吧,
支付完成后,支付宝会根据事先定义好的url地址来请求我们服务端,来确认时候订单信息,我们从request中获取到请求的参数即可 request.getParameterMap(); 将map值传入AlipayUtil.aliPay_notify(map); 至此异步请求完成 ,可以再此方法里添加我们对数据库订单操作的逻辑。
根据需求决定是否添加单笔交易查询,来确认订单交易信息和状态,多重保障,如果感觉没有必要,接下来就不用再看啦;
单笔交易查询依旧挺方便:
try {
//实例化客户端(参数:网关地址、商户appid、商户私钥、格式、编码、支付宝公钥、加密类型)
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.GATE, AlipayConfig.APPID,
AlipayConfig.APP_PRIVATE_KEY, "json", AlipayConfig.CHARSET,
AlipayConfig.PUBLIC_KEY,"RSA2"); //注意这里有个坑; 这里实例化客户端的时候用到的参数: AlipayConfig.PUBLIC_KEY; 创建订单时候的实例化客户端:AlipayConfig.ALIPAY_PUBLIC_KEY 两者不一样 注意区分
AlipayTradeQueryRequest alipayTradeQueryRequest = new AlipayTradeQueryRequest();
alipayTradeQueryRequest.setBizContent("{" +
"\"out_trade_no\":\""+parameter.getIndentId()+"\"" +
"}");
AlipayTradeQueryResponse alipayTradeQueryResponse = alipayClient.execute(alipayTradeQueryRequest);
if(alipayTradeQueryResponse.isSuccess()){
//修改数据库支付宝订单表
//如果需要修改除了状态以外的参数;
/* alipaymentOrder.setTradeNo(alipayTradeQueryResponse.getTradeNo());
alipaymentOrder.setBuyerLogonId(alipayTradeQueryResponse.getBuyerLogonId());
alipaymentOrder.setTotalAmount(Double.parseDouble(alipayTradeQueryResponse.getTotalAmount()));
alipaymentOrder.setReceiptAmount(Double.parseDouble(alipayTradeQueryResponse.getReceiptAmount()));
alipaymentOrder.setInvoiceAmount(Double.parseDouble(alipayTradeQueryResponse.getInvoiceAmount()));
alipaymentOrder.setBuyerPayAmount(Double.parseDouble(alipayTradeQueryResponse.getBuyerPayAmount())); */
//更新表记录
} else {
LOGGER.info("==================调用支付宝查询接口失败!");
}
} catch (AlipayApiException e) {
e.printStackTrace();
}
通过alipayTradeQueryResponse.getTradeStatus()的值来判断订单交易状态;
有这几个情况:
TRADE_FINISHED :交易结束并不可退款
TRADE_SUCCESS :交易支付成功
TRADE_CLOSED :未付款交易超时关闭或支付完成后全额退款
WAIT_BUYER_PAY :交易创建并等待买家付款
根据需要来做自己的逻辑处理即可;
因为时间比较久了,可能不是特别详细,不过应该没什么问题,欢迎各位大佬指导。