支付宝支付之App支付
与微信支付对比,支付宝支付就没有那么多坑了,毕竟支付宝开放平台的文档还是描述的很详细的。
支付宝开放平台地址:https://docs.open.alipay.com/204/105297/
支付宝支付的流程如下图所示:

项目中接入支付宝支付的步骤:
在这里分为了三个文件进行整理:
- 基础信息配置文件:AlipayConfig.java
- 调用API接口:AliPayUtil.java
- 对外接口: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支付的更多相关文章
- 支付宝H5、APP支付服务端的区别(php)
php支付宝H5和APP支付1.准备工作需要前往 蚂蚁金服开放平台申请https://openhome.alipay.com/developmentDocument.htm 2.大致流程1.用户添加商 ...
- asp.net core 微信扫码支付(扫码支付,H5支付,公众号支付,app支付)之1
2018-08-13更新生成二维码的方法 在做微信支付前,首先要了解你需要什么方式的微信支付,目前本人做过的支付包含扫码支付.H5支付.公众号支付.App支付等,本人使用的是asp.net mvc c ...
- 微信支付(APP支付)-服务端开发(一)
微信支付,首先需要注册一个商户平台公众账号,(网址:https://pay.weixin.qq.com/index.php/home/d_login) 目前微信支付的接入方式有四种方式:公众号支付,A ...
- 支付宝支付接口-app支付沙箱环境
说明 开发阶段 需要验证自己的app支付加签是否正确,这里使用沙箱环境来进行模拟,使用ali的沙箱测试app和沙箱钱包app进行校验 准备阶段 1.进入沙箱页面 2.找到app支付文档 https:/ ...
- 微信支付之App支付
项目接入微信支付的准备工作: 注册成为开发者,进行资质认证,这里是需要300元的审核费用的: 在微信商户平台创建应用,提交等待审核(大致需要5-7个工作日): 应用审核通过之后,进入应用,开通微信支付 ...
- uni-app - 支付(app支付、小程序支付、h5(微信端)支付)
App支付.小程序支付.h5(微信端)支付 APP支付(内置) appPay.js /** * 5+App支付,仅支持支付宝以及微信支付 * * 支付宝Sdk集成,微信sdk未集成 * * @para ...
- php支付走过的坑(微信篇 包含h5支付和app支付 注册 秘钥 环境等等配置)
支付这东西,说容易也容易,说难也难 代码这玩意还比较好说 但是 如果没有demo 直接去看官方文档 十有八九一脸懵逼 今天就整理一下 支付这块走过的坑 涉及 微信h5支付 支付宝h5支付 (api文档 ...
- asp.net core 微信APP支付(扫码支付,H5支付,公众号支付,app支付)之4
微信app支付需要以下参数,类封装如下 public class WxPayModel { /// <summary> /// 应用ID /// </summary> publ ...
- php 微信支付V3 APP支付
前言:微信支付现在分为v2版和v3版,2014年9月10号之前申请的为v2版,之后申请的为v3版.V3版的微信支付没有paySignKey参数. php 微信支付类 <?php class We ...
随机推荐
- 【托业】【全真题库】TEST1-语法题
TEST01 103. delivery date 交货日期 delivery n.传送,投递; [法](正式)交付; 分娩; 讲演; 104. net revenue 净收入,纯收入 105. re ...
- 【托业】【怪兽】TEST01
101. respectable 值得尊敬的(形容人或事物) respectful 态度恭敬的(形容人) respecting 关于…… respective 各自的 102. hardly 几乎没有 ...
- 编程填空:第i位替换
编程填空:第i位替换 OpenJudge 总时间限制:1000ms 内存限制:1024kB 描述:写出函数中缺失的部分,使得函数返回值为一个整数,该整数的第i位和m的第i位相同,其他位和n相同. 请使 ...
- Google word/sheets 常见的使用:
Google Sheets: 1, sheets 里面的单元格设置自动换行: 选中单元格: --> Format --> Text Wrapping --> Wrap(自动换行)/C ...
- static 关键字的作用
在C语言中,关键字static有三个明显的作用: 1)在函数体内,一个被声明为静态的变量在这一函数被调用过程中维持其值不变(该变量存放在静态变量区). 2) 在模块内(但在函数体外),一个被声明为静态 ...
- PHP获取汉字首字母函数
<?php function getFirstCharter($str) { if (empty($str)) { return ''; } $fchar = ord($str{0}); if ...
- hdu4780 最小费用最大流
提交 题意: 给了M个机器,N个糖果要被生产,每个糖果有一个Si和Ti的时间,只能在Si或者在Si<=t<Ti的时间开始生产 每个机器进行转化生产产品的时候都会产生一个代价,然后求最小的代 ...
- (转)sql 违反了 PRIMARY KEY 约束,不能在对象 中插入重复键
说明你的数据里面有重复记录 两种情况 1.已存在的表中和要导入数据之间的重复 这个时候可以通过在两个表之间建立关联,将主键级联找出重复记录 2.要导入的表中存在重复记录 可通过类似如下的语句将表中的重 ...
- maven中target不能访问
原因是maven clean的时候已经把target文件夹删除 但是文件夹还存在页面中 所以我们看得到但是不能打开.正常操作是获得管理员权限删除后再重新clean,但是我电脑有360,直接360 ...
- (Review cs231n) Object Detection
目标:我们有几个类别,然后我们要在这张图中找到这些类的所有实例 解决思路:是否可以按照回归的思路进行求解呢? 但是受限制于确定的种类输出问题. 方法:分类和回归是解决问题的两个套路,我们现在对于目标的 ...