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

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

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

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

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

  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

支付宝支付之App支付的更多相关文章

  1. 支付宝H5、APP支付服务端的区别(php)

    php支付宝H5和APP支付1.准备工作需要前往 蚂蚁金服开放平台申请https://openhome.alipay.com/developmentDocument.htm 2.大致流程1.用户添加商 ...

  2. asp.net core 微信扫码支付(扫码支付,H5支付,公众号支付,app支付)之1

    2018-08-13更新生成二维码的方法 在做微信支付前,首先要了解你需要什么方式的微信支付,目前本人做过的支付包含扫码支付.H5支付.公众号支付.App支付等,本人使用的是asp.net mvc c ...

  3. 微信支付(APP支付)-服务端开发(一)

    微信支付,首先需要注册一个商户平台公众账号,(网址:https://pay.weixin.qq.com/index.php/home/d_login) 目前微信支付的接入方式有四种方式:公众号支付,A ...

  4. 支付宝支付接口-app支付沙箱环境

    说明 开发阶段 需要验证自己的app支付加签是否正确,这里使用沙箱环境来进行模拟,使用ali的沙箱测试app和沙箱钱包app进行校验 准备阶段 1.进入沙箱页面 2.找到app支付文档 https:/ ...

  5. 微信支付之App支付

    项目接入微信支付的准备工作: 注册成为开发者,进行资质认证,这里是需要300元的审核费用的: 在微信商户平台创建应用,提交等待审核(大致需要5-7个工作日): 应用审核通过之后,进入应用,开通微信支付 ...

  6. uni-app - 支付(app支付、小程序支付、h5(微信端)支付)

    App支付.小程序支付.h5(微信端)支付 APP支付(内置) appPay.js /** * 5+App支付,仅支持支付宝以及微信支付 * * 支付宝Sdk集成,微信sdk未集成 * * @para ...

  7. php支付走过的坑(微信篇 包含h5支付和app支付 注册 秘钥 环境等等配置)

    支付这东西,说容易也容易,说难也难 代码这玩意还比较好说 但是 如果没有demo 直接去看官方文档 十有八九一脸懵逼 今天就整理一下 支付这块走过的坑 涉及 微信h5支付 支付宝h5支付 (api文档 ...

  8. asp.net core 微信APP支付(扫码支付,H5支付,公众号支付,app支付)之4

    微信app支付需要以下参数,类封装如下 public class WxPayModel { /// <summary> /// 应用ID /// </summary> publ ...

  9. php 微信支付V3 APP支付

    前言:微信支付现在分为v2版和v3版,2014年9月10号之前申请的为v2版,之后申请的为v3版.V3版的微信支付没有paySignKey参数. php 微信支付类 <?php class We ...

随机推荐

  1. Redis单机多节点集群实验

    第一步:安装Redis 前面已经安装过了 不解释, Reids安装包里有个集群工具,要复制到/usr/local/bin里去 cp redis-3.2.9/src/redis-trib.rb /usr ...

  2. 如何让外网访问自己的本地Web服务

    目前很多网站开发者安装了IIS或者Apache等Web服务器,可以把自己电脑配置成一以路由为中心的内网服务器. 本地服务器在内网测试是绰绰有余的,但是有些项目需要演示给异地的客户验收,而又赶不及把自己 ...

  3. react学习过程中遇到的错误记录

    1.App.js的代码如下: import React, { Component } from 'react'; import Test from './components/Test.jsx'; i ...

  4. Uva 12009 平方数尾数与自身同样 dfs 构造

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/qq574857122/article/details/25166611 题目链接:点击打开链接 题意 ...

  5. MPLS的模拟学习过程

    1.场景拓扑 使用小凡模拟器搭建了如下网络拓扑,使用的镜像为:c3640-jk9o3s-mz.122-15.T9.bin 相关的配置在下方 如果重复实验,需要清空设备的配置,知道路由器的密码,操作步骤 ...

  6. Linux给MySQL创建用户,并分配权限

    //登录MYSQL 使用root账号登录 @>mysql -u root -p @>密码 //创建用户 mysql> insert into mysql.user(Host,User ...

  7. UGUI动态更换精灵图片

    //动态更换精灵图片 m_headimage.overrideSprite = Resources.Load("texture/"+info.HeadPortrait,typeof ...

  8. 030-IHttpModule

    MyHttpModule.cs public class MyHttpModule : IHttpModule { public void Dispose() { } public void Init ...

  9. python爬虫简单的添加代理进行访问

    在使用python对网页进行多次快速爬取的时候,访问次数过于频繁,服务器不会考虑User-Agent的信息,会直接把你视为爬虫,从而过滤掉,拒绝你的访问,在这种时候就需要设置代理,我们可以给proxi ...

  10. ultiple Endpoints may not be deployed to the same path

    @Configurationpublic class WebSocketConfig { //打war包启动需要注释掉此:否则报 :DeploymentException: Multiple Endp ...