如何在humble Bundle上用支付宝还信用卡流程支付以及支付流程

支付宝APP支付——支付流程说明及示例 - CSDN博客
支付宝APP支付——支付流程说明及示例
支付宝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;
本文已收录于以下专栏:
相关文章推荐
前言,梦想是需要坚持的,在路上,一路前行。加油。这两天软件需要集成支付宝了,第一次集成,过程还是挺简单的,不过由于支付宝官方文档写的不够清晰,也是走了一些弯路,下面把过程写出来分享给大家一、申请移动支...
微信APP支付——支付流程说明及示例
支付涉及的3个重要数据:订单数据;用户账号,密码数据;电商服务器的支付宝账号
支付宝支付和微信支付区别:
  支付流程:商户服务器需要将订单信息通过统一下单api到微信服务器请求预支付交易单
支付宝APP支付服务端详解前面接了微信支付,相比微信支付,支付宝APP支付提供了支付分装类,下面将实现支付宝APP支付、订单查询、支付结果异步通知、APP支付申请参数说明,以及服务端返回APP端发起支...
demo: /zhonggaorong/alipayDemo
支付宝支付大致流程为
公司与支付宝进行签约 , 获得商户ID(partner)和账号ID(s...
在iOS应用里集成支付宝支付,需要公司和支付宝签约,然后生成相应的密钥。密钥的生成支付宝的开发文档里已经说的非常清楚。
官方的文档和SDK:
https://doc./d...
一、配置applicationContext-redis.xml
&beans xmlns=&http://www.springframework.org/schema/beans&
xmlns:x...
官方文档:点击打开链接
下载服务器端DEMO
导入项目中
// 实例化客户端
AlipayClient alipayClient = new DefaultAlipayClien...
Chapter 8 Styles 8.3 Using Styles for Good, Not Evil 8.3.1 Build Themes, Not Styles Consequently, ge...
他的最新文章
讲师:吴岸城
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)

我要回帖

更多关于 支付宝的使用流程 的文章

 

随机推荐