充支付宝宝充支付宝时业务类型代码为空什么意思

2495人阅读
支付宝APP支付——支付流程说明及示例
官方示例图
蚂蚁金服开放平台文档:
官方流程图:
如图,以Android平台为例:
第4步:调用支付接口:此消息就是本接口所描述的支付宝客户端SDK提供的支付对象PayTask,将商户签名后的订单信息传进payv2方法唤起支付宝收银台,交易数据格式具体参见请求参数说明。
第5步:支付请求:支付宝客户端SDK将会按照商户客户端提供的请求参数发送支付请求。
第8步:接口返回支付结果:商户客户端在第4步中调用的支付接口,会返回最终的支付结果(即同步通知),参见客户端同步返回。
第13步:用户在支付宝APP或H5收银台完成支付后,会根据商户在手机网站支付API中传入的前台回跳地址return_url自动跳转回商户页面,同时在URL请求中附带上支付结果参数。同时,支付宝还会根据原始支付API中传入的异步通知地址notify_url,通过POST请求的形式将支付结果作为参数通知到商户系统,详情见支付结果异步通知。
除了正向支付流程外,支付宝也提供交易查询、关闭、退款、退款查询以及对账等配套API。
特别注意:
构造交易数据并签名必须在商户服务端完成,商户的应用私钥绝对不能保存在商户APP客户端中,也不能从服务端下发。
同步返回的数据,只是一个简单的结果通知,商户确定该笔交易付款是否成功需要依赖服务端收到支付宝异步通知的结果进行判断。
商户系统接收到通知以后,必须通过验签(验证通知中的sign参数)来确保支付通知是由支付宝发送的。建议使用支付宝提供的SDK来完成,详细验签规则参考异步通知验签。
个人实际应用后的理解及实现
生成订单信息
app调用支付宝支付接口,服务端会返回支付信息
支付宝服务端调用异步通知接口,根据返回信息处理自己的业务逻辑,比如记入本地台账,修改订单状态等
生成订单信息
1. 创建本地订单并保存, 商品,价格,订单号
private VipOrder addVipOrder(User user, VipPrice vipPrice) {
//根据业务设置订单参数
VipOrder vo = new VipOrder()
vo.setCostPrice(vipPrice.getCostPrice())
vo.setCurrentPrice(vipPrice.getCurrentPrice())
vo.setGoodsId(Integer.parseInt(vipPrice.getId()))
vo.setGoodsName(vipPrice.getTypeName()+vipPrice.getName())
vo.setPayMode(VipOrder.PAYMODE_ALIPAY)
vo.setPayState(VipOrder.PAYSTATE_CREATE)
vo.setVipId(String.valueOf(vipPrice.getVipId()))
vo.setVipName(vipPrice.getTypeName())
vo.setTimesNum(vipPrice.getTimesNum())
vo.setUserId(user.getUid())
vo.setUserName(user.getUsername())
vo.setOrderNum(OrderInfoUtil2_0.getOutTradeNo(user.getUid()))//订单号,自定义随机码就可以建议32位
vo.setComId(String.valueOf(user.getCom_id()))
vo.setComName(user.getCom_name())
vo.setIsClaim(2)
vipOrderMapper.add(vo)
* vip_order 实体类
public class VipOrder implements Serializable {
* 支付方式 支付宝
public static final String PAYMODE_ALIPAY = "alipay";
* 支付方式 微信
public static final String PAYMODE_WX = "wx";
* 支付状态 创建待付款
public static final String PAYSTATE_CREATE = "create";
* 支付状态 支付成功
public static final String PAYSTATE_SUCCESS = "success";
* 支付状态 支付完成,完成后不可退款
public static final String PAYSTATE_FINISHED = "finished";
* 支付状态 支付失败
public static final String PAYSTATE_FAILURE = "failure";
private static final long serialVersionUID = -1L;
private Integer goodsId = -1;
private String costP
* 商品时长 单位(月)
private Integer timesNum = -1;
private String orderN
private String currentP
* 订单创建时间
* 支付状态
private String payS
* 处理对象,包含【处理时间】【处理类型】
private Integer handId = -1;
* 支付方式
private String payM
private Integer userId = -1;
* 用户名称
private String userN
* 商品名称
private String goodsN
private String comId;
* 企业名称
private String comN
* 会员名称
private String vipN
private String vipId;
* 是否索取发票,【1、已索取,2、未索取,3、索取中】
private Integer isClaim = -1;
* 是否邮寄发票,【1、是,2、否】
private Integer isMail = -1;
public String getVipId() {
return vipId;
public void setVipId(String vipId) {
this.vipId = vipId;
public String getVipName() {
return vipN
public void setVipName(String vipName) {
this.vipName = vipN
public String getComId() {
return comId;
public void setComId(String comId) {
this.comId = comId;
public String getComName() {
return comN
public void setComName(String comName) {
this.comName = comN
public void setGoodsId(Integer goodsId) {
this.goodsId = goodsId;
public Integer getGoodsId() {
return goodsId;
public void setCostPrice(String costPrice) {
this.costPrice = costP
public String getCostPrice() {
return costP
public void setRemark(String remark) {
this.remark =
public String getRemark() {
public void setTimesNum(Integer timesNum) {
this.timesNum = timesN
public Integer getTimesNum() {
return timesN
public void setOrderNum(String orderNum) {
this.orderNum = orderN
public String getOrderNum() {
return orderN
public void setCurrentPrice(String currentPrice) {
this.currentPrice = currentP
public String getCurrentPrice() {
return currentP
public void setId(String id) {
public String getId() {
public void setCreatetime(String createtime) {
this.createtime =
public String getCreatetime() {
public void setPayState(String payState) {
this.payState = payS
public String getPayState() {
return payS
public void setHandId(Integer handId) {
this.handId = handId;
public Integer getHandId() {
return handId;
public void setPayMode(String payMode) {
this.payMode = payM
public String getPayMode() {
return payM
public void setUserId(Integer userId) {
this.userId = userId;
public Integer getUserId() {
return userId;
public void setUserName(String userName) {
this.userName = userN
public String getUserName() {
return userN
public void setGoodsName(String goodsName) {
this.goodsName = goodsN
public String getGoodsName() {
return goodsN
public Integer getIsClaim() {
return isC
public void setIsClaim(Integer isClaim) {
this.isClaim = isC
public Integer getIsMail() {
return isM
public void setIsMail(Integer isMail) {
this.isMail = isM
public boolean equals(Object obj) {
if (this == obj) {
return true;
if (obj == null) {
return false;
final VipOrder vipOrder = (VipOrder)
if (this.getId().equals(vipOrder.getId())) {
return true;
return false;
2. 根据订单,结合支付宝业务对象,生成订单信息字符串,并返回
* 支付宝生成订单信息
* vipPrice
private String aliPayHandle(VipPrice vipPrice, VipOrder vo) {
String subject = vo.getGoodsName();
String out_trade_no = vo.getOrderNum();
String total_amount = vo.getCurrentPrice();
WorkParameter wp = new WorkParameter(subject, out_trade_no, total_amount);
wp.setTimeout_express("30m");
wp.setBody(vipPrice.getName());
String passback_params = vo.getId();
passback_params = URLEncoder.encode(passback_params, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
wp.setPassback_params(passback_params);
String orderInfo = OrderInfoUtil2_0.getOrderInfo(wp);
return orderI
OrderInfoUtil2_0工具类
import java.io.IOE
import java.io.InputS
import java.io.UnsupportedEncodingE
import java.net.URLE
import java.text.SimpleDateF
import java.util.ArrayL
import java.util.C
import java.util.D
import java.util.HashM
import java.util.L
import java.util.L
import java.util.M
import java.util.P
import java.util.R
import com.fasterxml.jackson.annotation.JsonInclude.I
import com.fasterxml.jackson.core.JsonProcessingE
import com.fasterxml.jackson.databind.ObjectM
public class OrderInfoUtil2_0 {
* 构造授权参数列表
* target_id
public static Map&String, String& buildAuthInfoMap(String pid,
String app_id, String target_id) {
Map&String, String& keyValues = new HashMap&String, String&();
keyValues.put("app_id", app_id);
keyValues.put("pid", pid);
keyValues.put("apiname", "com.alipay.account.auth");
keyValues.put("app_name", "mc");
keyValues.put("biz_type", "openservice");
keyValues.put("product_id", "APP_FAST_LOGIN");
keyValues.put("scope", "kuaijie");
keyValues.put("target_id", target_id);
keyValues.put("auth_type", "AUTHACCOUNT");
keyValues.put("sign_type", "RSA");
return keyV
* 构造支付订单参数列表
* target_id
public static Map&String, String& buildOrderParamMap(String app_id,
WorkParameter wp) {
InputStream in = Object.class.getResourceAsStream("/test.properties");
Map&String, String& keyValues = new HashMap&String, String&();
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(Include.NON_EMPTY);
String biz_contentStr = "";
biz_contentStr = objectMapper.writeValueAsString(wp);
} catch (JsonProcessingException e) {
e.printStackTrace();
System.out.println(biz_contentStr);
keyValues.put("app_id", app_id);
keyValues.put("biz_content", biz_contentStr);
keyValues.put("charset", "utf-8");
keyValues.put("method", "alipay.trade.app.pay");
keyValues.put("sign_type", "RSA");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:s");
keyValues.put("timestamp", sdf.format(new Date()));
keyValues.put("notify_url", AlipayConfig.notify_url);
keyValues.put("version", "1.0");
return keyV
* 构造支付订单参数信息
支付订单参数
public static String buildOrderParam(Map&String, String& map) {
List&String& keys = new ArrayList&String&(map.keySet());
StringBuilder sb = new StringBuilder();
for (int i = 0; i & keys.size() - 1; i++) {
String key = keys.get(i);
String value = map.get(key);
sb.append(buildKeyValue(key, value, true));
sb.append("&");
String tailKey = keys.get(keys.size() - 1);
String tailValue = map.get(tailKey);
sb.append(buildKeyValue(tailKey, tailValue, true));
return sb.toString();
* 拼接键值对
* isEncode
private static String buildKeyValue(String key, String value,
boolean isEncode) {
StringBuilder sb = new StringBuilder();
sb.append(key);
sb.append("=");
if (isEncode) {
sb.append(URLEncoder.encode(value, "UTF-8"));
} catch (UnsupportedEncodingException e) {
sb.append(value);
sb.append(value);
return sb.toString();
* 对支付参数信息进行签名
待签名授权信息
public static String getSign(Map&String, String& map, String rsaKey) {
List&String& keys = new ArrayList&String&(map.keySet());
Collections.sort(keys);
StringBuilder authInfo = new StringBuilder();
for (int i = 0; i & keys.size() - 1; i++) {
String key = keys.get(i);
String value = map.get(key);
authInfo.append(buildKeyValue(key, value, false));
authInfo.append("&");
String tailKey = keys.get(keys.size() - 1);
String tailValue = map.get(tailKey);
authInfo.append(buildKeyValue(tailKey, tailValue, false));
String oriSign = SignUtils.sign(authInfo.toString(), rsaKey);
String encodedSign = "";
encodedSign = URLEncoder.encode(oriSign, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return "sign=" + encodedS
* 要求外部订单号必须唯一。
public static String getOutTradeNo(int id) {
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmssS",
Locale.getDefault());
Date date = new Date();
String key = format.format(date);
Random r = new Random();
int i = r.nextInt(100000) % (100000 - 10000 + 1) + 10000;
String idStr = getIdStr(id);
key = idStr + key +
key = key.substring(0, 32);
* id补0 字符串长度12位 id不够的补0
private static String getIdStr(int id) {
String str = "";
if (0 & id && id & 10) {
str = "" +
if (10 &= id && id & 100) {
str = "" +
if (100 &= id && id & 1000) {
str = "" +
if (1000 &= id && id & 10000) {
str = "" +
if (10000 &= id && id & 100000) {
str = "0000000" +
if (100000 &= id && id & 1000000) {
str = "000000" +
if (1000000 &= id && id & ) {
str = "00000" +
* 获取订单信息
订单基础信息对象
public static String getOrderInfo(WorkParameter wp) {
Properties prop = new Properties();
String appid = "";
String private_key = "";
InputStream in = OrderInfoUtil2_0.class
.getResourceAsStream("zfbinfo.properties");
prop.load(in);
appid = prop.getProperty("appid").trim();
private_key = prop.getProperty("private_key").trim();
} catch (IOException e) {
e.printStackTrace();
Map&String, String& params = OrderInfoUtil2_0.buildOrderParamMap(appid,
String orderParam = OrderInfoUtil2_0.buildOrderParam(params);
String sign = OrderInfoUtil2_0.getSign(params, private_key);
String orderInfo = orderParam + "&" +
return orderI
zfbinfo.properties配置文件(支付宝参数配置文件)
可下载支付宝官方密钥生成工具
open_api_domain =
/gateway.do
mcloud_api_domain = /gateway.do
private_key = 私钥
public_key = 公钥
alipay_public_key = 公钥
* 业务参数对象
public class WorkParameter {
* 【非必填】
* 对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。
* 【必填】
* 商品的标题/交易标题/订单标题/订单关键字等。
* 【必填】
* 商户网站唯一订单号
private String out_trade_
* 【非必填】
* 该笔订单允许的最晚付款时间,逾期将关闭交易。
* 取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。
该参数数值不接受小数点, 如 1.5h,可转换为 90m。
private String timeout_
* 【必填】
* 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,]
private String total_
* 【非必填】
* 收款支付宝用户ID。 如果该值为空,则默认为商户签约账号对应的支付宝用户ID
private String seller_
* 【必填】
* 销售产品码,商家和支付宝签约的产品码,为固定值QUICK_MSECURITY_PAY
private String product_code = "QUICK_MSECURITY_PAY";
* 【非必填】
* 商品主类型:0—虚拟类商品,1—实物类商品
* 注:虚拟类商品不支持使用花呗渠道
private String goods_
* 【非必填】
* 公用回传参数,如果请求时传递了该参数,则返回给商户时会回传该参数。
* 支付宝会在异步通知时将该参数原样返回。本参数必须进行UrlEncode之后才可以发送给支付宝
private String passback_
* 【非必填】
* 优惠参数
* 注:仅与支付宝协商后可用
private String promo_
* 【非必填】
* 业务扩展参数,详见下面的“业务扩展参数说明”
private String extend_
* 【非必填】
* 可用渠道,用户只能在指定渠道范围内支付
* 当有多个渠道时用“,”分隔
* 注:与disable_pay_channels互斥
private String enable_pay_
* 【非必填】
* 禁用渠道,用户不可用指定渠道支付
* 当有多个渠道时用“,”分隔
* 注:与enable_pay_channels互斥
private String disable_pay_
public WorkParameter(){
* 必填项构造方法
商品的标题/交易标题/订单标题/订单关键字等。
* out_trade_no 商户网站唯一订单号
* total_amount 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,]
public WorkParameter(String subject,String out_trade_no,String total_amount){
this.subject =
this.out_trade_no = out_trade_
this.total_amount = total_
public String getBody() {
public void setBody(String body) {
this.body =
public String getSubject() {
public void setSubject(String subject) {
this.subject =
public String getOut_trade_no() {
return out_trade_
public void setOut_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_
public String getTimeout_express() {
return timeout_
public void setTimeout_express(String timeout_express) {
this.timeout_express = timeout_
public String getTotal_amount() {
return total_
public void setTotal_amount(String total_amount) {
this.total_amount = total_
public String getSeller_id() {
return seller_
public void setSeller_id(String seller_id) {
this.seller_id = seller_
public String getProduct_code() {
return product_
public void setProduct_code(String product_code) {
this.product_code = product_
public String getGoods_type() {
return goods_
public void setGoods_type(String goods_type) {
this.goods_type = goods_
public String getPassback_params() {
return passback_
public void setPassback_params(String passback_params) {
this.passback_params = passback_
public String getPromo_params() {
return promo_
public void setPromo_params(String promo_params) {
this.promo_params = promo_
public String getExtend_params() {
return extend_
public void setExtend_params(String extend_params) {
this.extend_params = extend_
public String getEnable_pay_channels() {
return enable_pay_
public void setEnable_pay_channels(String enable_pay_channels) {
this.enable_pay_channels = enable_pay_
public String getDisable_pay_channels() {
return disable_pay_
public void setDisable_pay_channels(String disable_pay_channels) {
this.disable_pay_channels = disable_pay_
app调用支付宝支付接口,服务端会返回支付信息
关键代码:其中orderInfo就是服务端返回的订单信息
final String orderInfo =
Runnable payRunnable = new Runnable() {
public void run() {
PayTask alipay = new PayTask(DemoActivity.this);
String result = alipay.payV2(orderInfo,true);
Message msg = new Message();
msg.what = SDK_PAY_FLAG;
mHandler.sendMessage(msg);
Thread payThread = new Thread(payRunnable);
payThread.start();
支付宝服务端调用异步通知接口处理
支付宝服务端调用异步通知接口,根据返回信息处理自己的业务逻辑,比如记入本地台账,修改订单状态等
支付宝回调是要进行验签的,验证通过后在进行操作
关键代码:
* 支付宝异步回调
* UnsupportedEncodingException
@RequestMapping(value = "/vipBuy.do", method = RequestMethod.POST)
@ResponseBody
public void vipBuy(HttpServletRequest request,HttpServletResponse response)
throws UnsupportedEncodingException {
String str = "";
Map&String, String& params = getReqParam(request);
String notify_id = request.getParameter("notify_id");
String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
if (notify_id != "" && notify_id != null) {
boolean signVerified = false;
signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, "UTF-8");
} catch (AlipayApiException e) {
e.printStackTrace();
if (signVerified){
String orderNum = vaan.getOut_trade_no();
String orderId = vaan.getPassback_params();
VipOrder vo = new VipOrder();
vo.setId(orderId);
vo.setOrderNum(orderNum);
vo = vipOrderMapper.findByIdOrderNum(vo);
boolean flag = checkTrue(vaan,vo);
if (trade_status.equals("TRADE_FINISHED")) {
} else if (trade_status.equals("TRADE_SUCCESS")) {
str = "success";
str = "failure";
str = "failure";
response.getWriter().print(str);
System.out.println(str);
} catch (IOException e) {
e.printStackTrace();
* 获取支付宝回调传入的参数,包含订单的所有信息
private Map&String, String& getReqParam(HttpServletRequest request) {
Map&String, String& params = new HashMap&String, String&();
Map&String, String[]& requestParams = request.getParameterMap();
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. i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]
: valueStr + values[i] + ",";
params.put(name, valueStr);
* 通过支付类型和支付返回结果,获取支付状态 1-支付成功 2-支付失败
* return_code
private Integer getPayState(String returnCode, String payType) {
if(payType.equals(VipOrder.PAYMODE_WX)){
if(returnCode.equals("SUCCESS")){
}else if(payType.equals(VipOrder.PAYMODE_ALIPAY)){
if(returnCode.equals("TRADE_SUCCESS") || returnCode.equals("TRADE_FINISHED")){
* 验证数据真实性
* 一、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号
* 二、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额)
* 三、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)
* 四、验证app_id是否为该商户本身
* 五、验证本地订单状态是否是已经成功的,避免重复购买会员
* 上面验证都通过,才可以进行后续工作
private boolean checkTrue(VipAlipayAsynNotify vaan,VipOrder vo) {
if(vo == null){
return false;
if(vo.getPayState().equals(VipOrder.PAYSTATE_SUCCESS) || vo.getPayState().equals(VipOrder.PAYSTATE_FINISHED)){
return false;
if(!vo.getCurrentPrice().equals(vaan.getTotal_amount())){
return false;
return true;
&&相关文章推荐
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:91573次
积分:1474
积分:1474
排名:千里之外
原创:55篇
评论:31条
(1)(3)(5)(2)(6)(5)(8)(9)(1)(1)(2)(4)(1)(1)(4)(2)(1)(1)(4)你正在使用的浏览器版本过低,将不能正常浏览和使用知乎。支付宝接口出现的常见问题_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
支付宝接口出现的常见问题
上传于|0|0|暂无简介
你可能喜欢11491人阅读
支付开发(3)
支付宝APP支付服务端详解
前面接了微信支付,相比微信支付,支付宝APP支付提供了支付分装类,下面将实现支付宝APP支付、订单查询、支付结果异步通知、APP支付申请参数说明,以及服务端返回APP端发起支付的签名、商户私钥、支付宝公钥的配置使用等。
支付注意事项
1、APP支付不能在沙箱测试、只能申请上线测试
2、需要创建RSA密钥,设置后上传rsa_public_key.pem【开发者公钥,上传时需要去掉公钥的头和尾】上传成功后换取支付宝公钥,为项目的alipay_public_key.pem
3、rsa_private_key_pkcs8.pem【开发者私钥】,去掉头和尾为项目的alipay_private_key_pkcs8.pem
4、需要导入所需支付包:alipay-sdk-java.jar 和 commons-logging.jar,具体参考:
支付文档参考:,
APP支付:服务器端按照文档【统一收单交易支付接口】创建支付OrderStr返回APP端——-APP端拿到OrderStr发起支付—–支付宝服务器端回调服务端异步通知接口——-服务器端按照【App支付结果异步通知】校验签名等做业务逻辑处理
APP支付订单查询:服务器端调用【统一收单线下交易查询】查询支付订单
APP支付申请退款:每笔支付可以申请多次退款,但退款总金额不能超过支付金额,调用【统一收单交易退款接口】发起退款申请
APP支付退款查询:服务端调用【
统一收单交易退款查询】查询退款订单信息
支付项目结构
支付项目demo结构如下
支付代码实现
PayController.java :包含支付、支付查询、异步通知、退款申请、退款查询
package org.andy.alipay.controller
import java.util.Date
import java.util.Enumeration
import java.util.HashMap
import java.util.Map
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import org.andy.alipay.model.JsonResult
import org.andy.alipay.model.ResponseData
import org.andy.alipay.util.AlipayUtil
import org.andy.alipay.util.DatetimeUtil
import org.andy.alipay.util.PayUtil
import org.andy.alipay.util.SerializerFeatureUtil
import org.andy.alipay.util.StringUtil
import org.andy.alipay.util.WebUtil
import org.apache.log4j.Logger
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestMethod
import org.springframework.web.bind.annotation.RequestParam
import com.alibaba.fastjson.JSON
import com.alipay.api.AlipayApiException
import com.alipay.api.AlipayConstants
import com.alipay.api.internal.util.AlipaySignature
import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest
import com.alipay.api.request.AlipayTradeQueryRequest
import com.alipay.api.request.AlipayTradeRefundRequest
import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse
import com.alipay.api.response.AlipayTradeQueryResponse
import com.alipay.api.response.AlipayTradeRefundResponse
@Controller
@RequestMapping("/order")
public class PayController {
private static final Logger LOG = Logger.getLogger(PayController.class)
@RequestMapping(value = "/pay", method = RequestMethod.POST)
public void orderPay(HttpServletRequest request, HttpServletResponse response,
@RequestParam(required = false, defaultValue = "0") Double cashnum, String mercid, String callback) {
LOG.info("[/order/pay]")
if (!"001".equals(mercid)) {
WebUtil.response(response, WebUtil.packJsonp(callback, JSON
.toJSONString(new JsonResult(-1, "商品不存在", new ResponseData()), SerializerFeatureUtil.FEATURES)))
Map&String, String& param = new HashMap&&()
// 公共请求参数
param.put("app_id", AlipayUtil.ALIPAY_APPID)
param.put("method", "alipay.trade.app.pay")
param.put("format", AlipayConstants.FORMAT_JSON)
param.put("charset", AlipayConstants.CHARSET_UTF8)
param.put("timestamp", DatetimeUtil.formatDateTime(new Date()))
param.put("version", "1.0")
param.put("notify_url", "https://www.andy.org/alipay/order/pay/notify.shtml")
param.put("sign_type", AlipayConstants.SIGN_TYPE_RSA)
Map&String, Object& pcont = new HashMap&&()
// 支付业务请求参数
pcont.put("out_trade_no", PayUtil.getTradeNo())
pcont.put("total_amount", String.valueOf(cashnum))
pcont.put("subject", "测试支付")
pcont.put("body", "Andy")
pcont.put("product_code", "QUICK_MSECURITY_PAY")
param.put("biz_content", JSON.toJSONString(pcont))
Map&String, String& payMap = new HashMap&&()
param.put("sign", PayUtil.getSign(param, AlipayUtil.APP_PRIVATE_KEY))
payMap.put("orderStr", PayUtil.getSignEncodeUrl(param, true))
} catch (Exception e) {
e.printStackTrace()
WebUtil.response(response, WebUtil.packJsonp(callback, JSON.toJSONString(
new JsonResult(1, "订单获取成功", new ResponseData(null, payMap)), SerializerFeatureUtil.FEATURES)))
@RequestMapping(value = "/pay/query", method = RequestMethod.POST)
public void orderPayQuery(HttpServletRequest request, HttpServletResponse response, String tradeno, String orderno,
String callback) {
LOG.info("[/order/pay/query]")
if (StringUtil.isEmpty(tradeno) && StringUtil.isEmpty(orderno)) {
WebUtil.response(response, WebUtil.packJsonp(callback, JSON
.toJSONString(new JsonResult(-1, "订单号不能为空", new ResponseData()), SerializerFeatureUtil.FEATURES)))
AlipayTradeQueryRequest alipayRequest = new AlipayTradeQueryRequest()
// 只需要传入业务参数
Map&String, Object& param = new HashMap&&()
param.put("out_trade_no", orderno)
param.put("trade_no", tradeno)
alipayRequest.setBizContent(JSON.toJSONString(param))
Map&String, String& restmap = new HashMap&String, String&()
boolean flag = false
AlipayTradeQueryResponse alipayResponse = AlipayUtil.getAlipayClient().execute(alipayRequest)
if (alipayResponse.isSuccess()) {
// 调用成功,则处理业务逻辑
if ("10000".equals(alipayResponse.getCode())) {
// 订单创建成功
flag = true
restmap.put("order_no", alipayResponse.getOutTradeNo())
restmap.put("trade_no", alipayResponse.getTradeNo())
restmap.put("buyer_logon_id", alipayResponse.getBuyerLogonId())
restmap.put("trade_status", alipayResponse.getTradeStatus())
LOG.info("订单查询结果:" + alipayResponse.getTradeStatus())
LOG.info("订单查询失败:" + alipayResponse.getMsg() + ":" + alipayResponse.getSubMsg())
} catch (AlipayApiException e) {
e.printStackTrace()
if (flag) {
// 订单查询成功
WebUtil.response(response,
WebUtil.packJsonp(callback,
JSON.toJSONString(new JsonResult(1, "订单查询成功", new ResponseData(null, restmap)),
SerializerFeatureUtil.FEATURES)))
} else { // 订单查询失败
WebUtil.response(response, WebUtil.packJsonp(callback, JSON
.toJSONString(new JsonResult(-1, "订单查询失败", new ResponseData()), SerializerFeatureUtil.FEATURES)))
@RequestMapping(value = "/pay/notify", method = RequestMethod.POST)
public void orderPayNotify(HttpServletRequest request, HttpServletResponse response) {
LOG.info("[/order/pay/notify]")
// 获取到返回的所有参数 先判断是否交易成功trade_status 再做签名校验
// 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
// 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
// 3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email),
// 4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。在上述验证通过后商户必须根据支付宝不同类型的业务通知,正确的进行不同的业务处理,并且过滤重复的通知结果数据。在支付宝的业务通知中,只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功。
if ("TRADE_SUCCESS".equals(request.getParameter("trade_status"))) {
Enumeration&?& pNames = request.getParameterNames()
Map&String, String& param = new HashMap&String, String&()
while (pNames.hasMoreElements()) {
String pName = (String) pNames.nextElement()
param.put(pName, request.getParameter(pName))
boolean signVerified = AlipaySignature.rsaCheckV1(param, AlipayUtil.ALIPAY_PUBLIC_KEY,
AlipayConstants.CHARSET_UTF8)
if (signVerified) {
// TODO 验签成功后
// 按照支付结果异步通知中的描述,对支付结果中的业务内容进行1\2\3\4二次校验,校验成功后在response中返回success,校验失败返回failure
LOG.info("订单支付成功:" + JSON.toJSONString(param))
// TODO 验签失败则记录异常日志,并在response中返回failure.
} catch (Exception e) {
e.printStackTrace()
@RequestMapping(value = "/pay/refund", method = RequestMethod.POST)
public void orderPayRefund(HttpServletRequest request, HttpServletResponse response, String tradeno, String orderno,
String callback) {
LOG.info("[/pay/refund]")
if (StringUtil.isEmpty(tradeno) && StringUtil.isEmpty(orderno)) {
WebUtil.response(response, WebUtil.packJsonp(callback, JSON
.toJSONString(new JsonResult(-1, "订单号不能为空", new ResponseData()), SerializerFeatureUtil.FEATURES)))
AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest()
// 只需要传入业务参数
Map&String, Object& param = new HashMap&&()
param.put("out_trade_no", orderno)
param.put("trade_no", tradeno)
param.put("refund_amount", 0.01)
param.put("refund_reason", "测试支付退款")
param.put("out_request_no", PayUtil.getRefundNo())
alipayRequest.setBizContent(JSON.toJSONString(param))
Map&String, Object& restmap = new HashMap&&()
boolean flag = false
AlipayTradeRefundResponse alipayResponse = AlipayUtil.getAlipayClient().execute(alipayRequest)
if (alipayResponse.isSuccess()) {
// 调用成功,则处理业务逻辑
if ("10000".equals(alipayResponse.getCode())) {
// 订单创建成功
flag = true
restmap.put("out_trade_no", alipayResponse.getOutTradeNo())
restmap.put("trade_no", alipayResponse.getTradeNo())
restmap.put("buyer_logon_id", alipayResponse.getBuyerLogonId())
restmap.put("gmt_refund_pay", alipayResponse.getGmtRefundPay())
restmap.put("buyer_user_id", alipayResponse.getBuyerUserId())
LOG.info("订单退款结果:退款成功")
LOG.info("订单查询失败:" + alipayResponse.getMsg() + ":" + alipayResponse.getSubMsg())
} catch (AlipayApiException e) {
e.printStackTrace()
if (flag) {
// 订单查询成功
WebUtil.response(response,
WebUtil.packJsonp(callback,
JSON.toJSONString(new JsonResult(1, "订单退款成功", new ResponseData(null, restmap)),
SerializerFeatureUtil.FEATURES)))
} else { // 订单查询失败
WebUtil.response(response, WebUtil.packJsonp(callback, JSON
.toJSONString(new JsonResult(-1, "订单退款失败", new ResponseData()), SerializerFeatureUtil.FEATURES)))
@RequestMapping(value = "/pay/refund/query", method = RequestMethod.POST)
public void orderPayRefundQuery(HttpServletRequest request, HttpServletResponse response, String orderno,
String tradeno, String callback) {
LOG.info("[/pay/refund/query]")
if (StringUtil.isEmpty(orderno) && StringUtil.isEmpty(tradeno)) {
WebUtil.response(response,
WebUtil.packJsonp(callback,
JSON.toJSONString(new JsonResult(-1, "商家订单号或支付宝订单号不能为空", new ResponseData()),
SerializerFeatureUtil.FEATURES)))
AlipayTradeFastpayRefundQueryRequest alipayRequest = new AlipayTradeFastpayRefundQueryRequest()
// 只需要传入业务参数
Map&String, Object& param = new HashMap&&()
param.put("out_trade_no", orderno)
param.put("trade_no", tradeno)
param.put("out_request_no", orderno)
alipayRequest.setBizContent(JSON.toJSONString(param))
Map&String, Object& restmap = new HashMap&&()
boolean flag = false
AlipayTradeFastpayRefundQueryResponse alipayResponse = AlipayUtil.getAlipayClient().execute(alipayRequest)
if (alipayResponse.isSuccess()) {
// 调用成功,则处理业务逻辑
if ("10000".equals(alipayResponse.getCode())) {
// 订单创建成功
flag = true
restmap.put("out_trade_no", alipayResponse.getOutTradeNo())
restmap.put("trade_no", alipayResponse.getTradeNo())
restmap.put("out_request_no", alipayResponse.getOutRequestNo())
restmap.put("refund_reason", alipayResponse.getRefundReason())
restmap.put("total_amount", alipayResponse.getTotalAmount())
restmap.put("refund_amount", alipayResponse.getTotalAmount())
LOG.info("订单退款结果:退款成功")
LOG.info("订单失败:" + alipayResponse.getMsg() + ":" + alipayResponse.getSubMsg())
} catch (AlipayApiException e) {
e.printStackTrace()
if (flag) {
// 订单查询成功
WebUtil.response(response,
WebUtil.packJsonp(callback,
JSON.toJSONString(new JsonResult(1, "订单退款成功", new ResponseData(null, restmap)),
SerializerFeatureUtil.FEATURES)))
} else { // 订单查询失败
WebUtil.response(response, WebUtil.packJsonp(callback, JSON
.toJSONString(new JsonResult(-1, "订单退款失败", new ResponseData()), SerializerFeatureUtil.FEATURES)))
SignUtils.java:支付宝支付签名实现
package org.andy.alipay.
import java.security.KeyF
import java.security.PrivateK
import java.security.spec.PKCS8EncodedKeyS
public class SignUtils {
private static final String ALGORITHM = "RSA";
private static final String SIGN_ALGORITHMS = "SHA1WithRSA";
private static final String DEFAULT_CHARSET = "UTF-8";
public static String sign(String content, String privateKey) {
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
Base64.decode(privateKey));
KeyFactory keyf = KeyFactory.getInstance(ALGORITHM);
PrivateKey priKey = keyf.generatePrivate(priPKCS8);
java.security.Signature signature = java.security.Signature
.getInstance(SIGN_ALGORITHMS);
signature.initSign(priKey);
signature.update(content.getBytes(DEFAULT_CHARSET));
byte[] signed = signature.sign();
return new String(Base64.encode(signed));
} catch (Exception e) {
e.printStackTrace();
return null;
Ali支付工具类
AlipayUtil.java:初始化AlipayClient、开发者私有、支付宝公钥等
package org.andy.alipay.
import org.springframework.core.io.ClassPathR
import org.springframework.core.io.R
import com.alipay.api.AlipayC
import com.alipay.api.AlipayC
import com.alipay.api.DefaultAlipayC
* 创建时间:日 下午7:09:08
* alipay支付
public class AlipayUtil {
public static final String ALIPAY_APPID = ConfigUtil.getProperty("alipay.appid");
public static String APP_PRIVATE_KEY = null;
public static String ALIPAY_PUBLIC_KEY = null;
Resource resource = new ClassPathResource("alipay_private_key_pkcs8.pem");
APP_PRIVATE_KEY = FileUtil.readInputStream2String(resource.getInputStream());
resource = new ClassPathResource("alipay_public_key.pem");
ALIPAY_PUBLIC_KEY = FileUtil.readInputStream2String(resource.getInputStream());
} catch (Exception e) {
e.printStackTrace();
private static AlipayClient alipayClient = null;
public static AlipayClient getAlipayClient() {
if (alipayClient == null) {
synchronized (AlipayUtil.class) {
if (null == alipayClient) {
alipayClient = new DefaultAlipayClient("/gateway.do", ALIPAY_APPID,
APP_PRIVATE_KEY, AlipayConstants.FORMAT_JSON, AlipayConstants.CHARSET_UTF8,
ALIPAY_PUBLIC_KEY);
return alipayC
支付工具类
PayUtil.java:生成签名、订单生成等
package org.andy.alipay.
import java.io.UnsupportedEncodingE
import java.net.URLE
import java.util.ArrayL
import java.util.C
import java.util.D
import java.util.L
import java.util.M
import javax.servlet.http.HttpServletR
import com.alipay.api.AlipayC
* 创建时间:日 下午7:12:44
public class PayUtil {
* 生成订单号
public static String getTradeNo() {
return "TNO" + DatetimeUtil.formatDate(new Date(), DatetimeUtil.TIME_STAMP_PATTERN) + "";
* 退款单号
public static String getRefundNo() {
return "RNO" + DatetimeUtil.formatDate(new Date(), DatetimeUtil.TIME_STAMP_PATTERN) + "";
* 退款单号
public static String getTransferNo() {
return "TNO" + DatetimeUtil.formatDate(new Date(), DatetimeUtil.TIME_STAMP_PATTERN) + "";
* 返回客户端ip
public static String getRemoteAddrIp(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (StringUtil.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
int index = ip.indexOf(",");
if (index != -1) {
return ip.substring(0, index);
ip = request.getHeader("X-Real-IP");
if (StringUtil.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
return request.getRemoteAddr();
* 获取服务器的ip地址
public static String getLocalIp(HttpServletRequest request) {
return request.getLocalAddr();
* 创建支付随机字符串
public static String getNonceStr() {
return RandomUtil.randomString(RandomUtil.LETTER_NUMBER_CHAR, 32);
* 支付时间戳
public static String payTimestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
* 返回签名编码拼接url
* isEncode
public static String getSignEncodeUrl(Map&String, String& map, boolean isEncode) {
String sign = map.get("sign");
String encodedSign = "";
if (CollectionUtil.isNotEmpty(map)) {
map.remove("sign");
List&String& keys = new ArrayList&String&(map.keySet());
Collections.sort(keys);
StringBuilder authInfo = new StringBuilder();
boolean first = true;
for (String key: keys) {
if (first) {
first = false;
authInfo.append("&");
authInfo.append(key).append("=");
if (isEncode) {
authInfo.append(URLEncoder.encode(map.get(key), AlipayConstants.CHARSET_UTF8));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
authInfo.append(map.get(key));
encodedSign = authInfo.toString() + "&sign=" + URLEncoder.encode(sign, AlipayConstants.CHARSET_UTF8);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return encodedSign.replaceAll("\\+", "%20");
* 对支付参数信息进行签名
待签名授权信息
public static String getSign(Map&String, String& map, String rsaKey) {
List&String& keys = new ArrayList&String&(map.keySet());
Collections.sort(keys);
StringBuilder authInfo = new StringBuilder();
boolean first = true;
for (String key : keys) {
if (first) {
first = false;
authInfo.append("&");
authInfo.append(key).append("=").append(map.get(key));
return SignUtils.sign(authInfo.toString(), rsaKey);
以下为支付宝支付和支付宝退款
支付宝App支付测试完成
项目源码地址:
&&相关文章推荐
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:324853次
积分:4234
积分:4234
排名:第6569名
原创:118篇
评论:287条
阅读:63253
阅读:21524
阅读:44822
文章:104篇
阅读:202199}

我要回帖

更多关于 充支付宝 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信