支付宝APP支付——支付流程说明及示例

原创 2017年02月06日 11:59:15

支付宝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来完成,详细验签规则参考异步通知验签。

个人实际应用后的理解及实现

  1. 生成订单信息

  2. app调用支付宝支付接口,服务端会返回支付信息

  3. 支付宝服务端调用异步通知接口,根据返回信息处理自己的业务逻辑,比如记入本地台账,修改订单状态等

生成订单信息

1. 创建本地订单并保存, 商品,价格,订单号


/**

 * 添加一条支付宝的订单

 * @param user

 * @param vipPrice

 * @return

 */

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()));//商品id

    vo.setGoodsName(vipPrice.getTypeName()+vipPrice.getName());//商品名称

    vo.setPayMode(VipOrder.PAYMODE_ALIPAY);//支付宝

    vo.setPayState(VipOrder.PAYSTATE_CREATE);//支付状态

    vo.setVipId(String.valueOf(vipPrice.getVipId()));//vipId

    vo.setVipName(vipPrice.getTypeName());//vip名称

    vo.setTimesNum(vipPrice.getTimesNum());//时长

    vo.setUserId(user.getUid());//用户id

    vo.setUserName(user.getUsername());//用户名称

    vo.setOrderNum(OrderInfoUtil2_0.getOutTradeNo(user.getUid()))//订单号,自定义随机码就可以建议32;

    vo.setComId(String.valueOf(user.getCom_id()));//公司id

    vo.setComName(user.getCom_name());//公司名称

    vo.setIsClaim(2);//初始化账单为未索取

    vipOrderMapper.add(vo);//新增一条数据

    return vo;

}

订单实体


/**

 * vip_order 实体类

 * 

 * @author pzr

 */

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;

    /**

     * 套餐id

     */

    private Integer goodsId = -1;

    /**

     * 原价

     */

    private String costPrice;

    /**

     * 备注

     */

    private String remark;

    /**

     * 商品时长 单位(月)

     */

    private Integer timesNum = -1;

    /**

     * vip编号

     */

    private String orderNum;

    /**

     * 现价

     */

    private String currentPrice;

    /**

     * 

     */

    private String id;

    /**

     * 订单创建时间

     */

    private String createtime;

    /**

     * 支付状态

     */

    private String payState;

    /**

     * 处理对象,包含【处理时间】【处理类型】

     */

    private Integer handId = -1;

    /**

     * 支付方式

     */

    private String payMode;

    /**

     * 用户id

     */

    private Integer userId = -1;

    /**

     * 用户名称

     */

    private String userName;

    /**

     * 商品名称

     */

    private String goodsName;



    /**

     * 企业id

     */

    private String comId;



    /**

     * 企业名称

     */

    private String comName;



    /**

     * 会员名称

     */

    private String vipName;



    /**

     * 会员id

     */

    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 vipName;

    }



    public void setVipName(String vipName) {

        this.vipName = vipName;

    }



    public String getComId() {

        return comId;

    }



    public void setComId(String comId) {

        this.comId = comId;

    }



    public String getComName() {

        return comName;

    }



    public void setComName(String comName) {

        this.comName = comName;

    }



    public void setGoodsId(Integer goodsId) {

        this.goodsId = goodsId;

    }



    public Integer getGoodsId() {

        return goodsId;

    }



    public void setCostPrice(String costPrice) {

        this.costPrice = costPrice;

    }



    public String getCostPrice() {

        return costPrice;

    }



    public void setRemark(String remark) {

        this.remark = remark;

    }



    public String getRemark() {

        return remark;

    }



    public void setTimesNum(Integer timesNum) {

        this.timesNum = timesNum;

    }



    public Integer getTimesNum() {

        return timesNum;

    }



    public void setOrderNum(String orderNum) {

        this.orderNum = orderNum;

    }



    public String getOrderNum() {

        return orderNum;

    }



    public void setCurrentPrice(String currentPrice) {

        this.currentPrice = currentPrice;

    }



    public String getCurrentPrice() {

        return currentPrice;

    }



    public void setId(String id) {

        this.id = id;

    }



    public String getId() {

        return id;

    }



    public void setCreatetime(String createtime) {

        this.createtime = createtime;

    }



    public String getCreatetime() {

        return createtime;

    }



    public void setPayState(String payState) {

        this.payState = payState;

    }



    public String getPayState() {

        return payState;

    }



    public void setHandId(Integer handId) {

        this.handId = handId;

    }



    public Integer getHandId() {

        return handId;

    }



    public void setPayMode(String payMode) {

        this.payMode = payMode;

    }



    public String getPayMode() {

        return payMode;

    }



    public void setUserId(Integer userId) {

        this.userId = userId;

    }



    public Integer getUserId() {

        return userId;

    }



    public void setUserName(String userName) {

        this.userName = userName;

    }



    public String getUserName() {

        return userName;

    }



    public void setGoodsName(String goodsName) {

        this.goodsName = goodsName;

    }



    public String getGoodsName() {

        return goodsName;

    }



    public Integer getIsClaim() {

        return isClaim;

    }



    public void setIsClaim(Integer isClaim) {

        this.isClaim = isClaim;

    }



    public Integer getIsMail() {

        return isMail;

    }



    public void setIsMail(Integer isMail) {

        this.isMail = isMail;

    }



    // 重写Object对象的equals方法

    @Override

    public boolean equals(Object obj) {

        if (this == obj) {

            return true;

        } else {

            if (obj == null) {

                return false;

            }

            final VipOrder vipOrder = (VipOrder) obj;

            if (this.getId().equals(vipOrder.getId())) {

                return true;

            } else {

                return false;

            }

        }

    }

}

2. 根据订单,结合支付宝业务对象,生成订单信息字符串,并返回


/**

 * 支付宝生成订单信息

 * @param vipPrice

 * @param vo

 * @return

 */

private String aliPayHandle(VipPrice vipPrice, VipOrder vo) {

    String subject = vo.getGoodsName(); //商品标题

    String out_trade_no = vo.getOrderNum(); //商品网站唯一订单号 32位

    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();

    try {

        passback_params = URLEncoder.encode(passback_params, "UTF-8");

    } catch (UnsupportedEncodingException e) {

        e.printStackTrace();

    }//URL编码,支付宝需要以这样的方式传递参数

    wp.setPassback_params(passback_params);//公用回传参数

    String orderInfo = OrderInfoUtil2_0.getOrderInfo(wp);//生成返回字符串

    return orderInfo;

}

OrderInfoUtil2_0工具类


import java.io.IOException;

import java.io.InputStream;

import java.io.UnsupportedEncodingException;

import java.net.URLEncoder;

import java.text.SimpleDateFormat;

import java.util.ArrayList;

import java.util.Collections;

import java.util.Date;

import java.util.HashMap;

import java.util.List;

import java.util.Locale;

import java.util.Map;

import java.util.Properties;

import java.util.Random;



import com.fasterxml.jackson.annotation.JsonInclude.Include;

import com.fasterxml.jackson.core.JsonProcessingException;

import com.fasterxml.jackson.databind.ObjectMapper;



public class OrderInfoUtil2_0 {



    /**

     * 构造授权参数列表

     * 

     * @param pid

     * @param app_id

     * @param target_id

     * @return

     */

    public static Map<String, String> buildAuthInfoMap(String pid,

            String app_id, String target_id) {

        Map<String, String> keyValues = new HashMap<String, String>();



        // 商户签约拿到的app_id,如:2013081700024223

        keyValues.put("app_id", app_id);



        // 商户签约拿到的pid,如:2088102123816631

        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");



        // 商户唯一标识,如:kkkkk091125

        keyValues.put("target_id", target_id);



        // 授权类型, 固定值

        keyValues.put("auth_type", "AUTHACCOUNT");



        // 签名类型

        keyValues.put("sign_type", "RSA");



        return keyValues;

    }



    /**

     * 构造支付订单参数列表

     * 

     * @param pid

     * @param app_id

     * @param target_id

     * @return

     */

    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 = "";

        try {

            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 keyValues;

    }



    /**

     * 构造支付订单参数信息

     * 

     * @param map

     *            支付订单参数

     * @return

     */

    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();

    }



    /**

     * 拼接键值对

     * 

     * @param key

     * @param value

     * @param isEncode

     * @return

     */

    private static String buildKeyValue(String key, String value,

            boolean isEncode) {

        StringBuilder sb = new StringBuilder();

        sb.append(key);

        sb.append("=");

        if (isEncode) {

            try {

                sb.append(URLEncoder.encode(value, "UTF-8"));

            } catch (UnsupportedEncodingException e) {

                sb.append(value);

            }

        } else {

            sb.append(value);

        }

        return sb.toString();

    }



    /**

     * 对支付参数信息进行签名

     * 

     * @param map

     *            待签名授权信息

     * 

     * @return

     */

    public static String getSign(Map<String, String> map, String rsaKey) {

        List<String> keys = new ArrayList<String>(map.keySet());

        // key排序

        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 = "";



        try {

            encodedSign = URLEncoder.encode(oriSign, "UTF-8");

        } catch (UnsupportedEncodingException e) {

            e.printStackTrace();

        }

        return "sign=" + encodedSign;

    }



    /**

     * 要求外部订单号必须唯一。

     * 

     * @return

     */

    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();

        // 5位随机码

        int i = r.nextInt(100000) % (100000 - 10000 + 1) + 10000;

        // id补0

        String idStr = getIdStr(id);

        key = idStr + key + i;

        key = key.substring(0, 32);

        return key;

    }



    /**

     * id补0 字符串长度12位 id不够的补0

     * 

     * @param id

     * @return

     */

    private static String getIdStr(int id) {

        String str = "";

        if (0 < id && id < 10) {

            str = "00000000000" + id;

        }

        if (10 <= id && id < 100) {

            str = "0000000000" + id;

        }

        if (100 <= id && id < 1000) {

            str = "000000000" + id;

        }

        if (1000 <= id && id < 10000) {

            str = "00000000" + id;

        }

        if (10000 <= id && id < 100000) {

            str = "0000000" + id;

        }

        if (100000 <= id && id < 1000000) {

            str = "000000" + id;

        }

        if (1000000 <= id && id < 10000000) {

            str = "00000" + id;

        }

        return str;

    }



    /**

     * 获取订单信息

     * 

     * @param wp

     *            订单基础信息对象

     * @return

     */

    public static String getOrderInfo(WorkParameter wp) {

        Properties prop = new Properties();

        String appid = "";

        String private_key = "";

        InputStream in = OrderInfoUtil2_0.class

                .getResourceAsStream("zfbinfo.properties");



        try {

            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,

                wp);

        String orderParam = OrderInfoUtil2_0.buildOrderParam(params);

        // 添加签名

        String sign = OrderInfoUtil2_0.getSign(params, private_key);

        // 组装参数

        String orderInfo = orderParam + "&" + sign;

        return orderInfo;

    }



}

zfbinfo.properties配置文件(支付宝参数配置文件)

可下载支付宝官方密钥生成工具

地址:https://doc.open.alipay.com/docs/doc.htm?treeId=291&articleId=105971&docType=1


open_api_domain =   https://openapi.alipaydev.com/gateway.do

mcloud_api_domain = http://mcloudmonitor.com/gateway.do

pid = pid

appid =  appid



private_key = 私钥

public_key = 公钥

alipay_public_key = 公钥

业务对象


/**

 * 业务参数对象

 * @author pzr

 *

 */

public class WorkParameter {

    /**

     * 【非必填】

     * 对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。

     */

    private String body;

    /**

     * 【必填】

     * 商品的标题/交易标题/订单标题/订单关键字等。

     */

    private String subject;

    /**

     * 【必填】

     * 商户网站唯一订单号

     */

    private String out_trade_no;

    /**

     * 【非必填】

     * 该笔订单允许的最晚付款时间,逾期将关闭交易。

     * 取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。

     *  该参数数值不接受小数点, 如 1.5h,可转换为 90m。

     */

    private String timeout_express;

    /**

     * 【必填】

     * 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]

     */

    private String total_amount;

    /**

     * 【非必填】

     * 收款支付宝用户ID。 如果该值为空,则默认为商户签约账号对应的支付宝用户ID

     */

    private String seller_id;

    /**

     * 【必填】

     * 销售产品码,商家和支付宝签约的产品码,为固定值QUICK_MSECURITY_PAY

     */

    private String product_code = "QUICK_MSECURITY_PAY";

    /**

     * 【非必填】

     * 商品主类型:0—虚拟类商品,1—实物类商品

     * 注:虚拟类商品不支持使用花呗渠道

     */

    private String goods_type;

    /**

     * 【非必填】

     * 公用回传参数,如果请求时传递了该参数,则返回给商户时会回传该参数。

     * 支付宝会在异步通知时将该参数原样返回。本参数必须进行UrlEncode之后才可以发送给支付宝

     */

    private String passback_params;

    /**

     * 【非必填】

     * 优惠参数

     * 注:仅与支付宝协商后可用

     */

    private String promo_params;

    /**

     * 【非必填】

     * 业务扩展参数,详见下面的“业务扩展参数说明”

     */

    private String extend_params;

    /**

     * 【非必填】

     * 可用渠道,用户只能在指定渠道范围内支付

     * 当有多个渠道时用“,”分隔

     * 注:与disable_pay_channels互斥

     */

    private String enable_pay_channels;

    /**

     * 【非必填】

     * 禁用渠道,用户不可用指定渠道支付

     * 当有多个渠道时用“,”分隔

     * 注:与enable_pay_channels互斥

     */

    private String disable_pay_channels;



    public WorkParameter(){



    }



    /**

     * 必填项构造方法

     * @param subject  商品的标题/交易标题/订单标题/订单关键字等。

     * @param out_trade_no 商户网站唯一订单号

     * @param total_amount 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]

     */

    public WorkParameter(String subject,String out_trade_no,String total_amount){

        this.subject = subject;

        this.out_trade_no = out_trade_no;

        this.total_amount = total_amount;

    }



    public String getBody() {

        return body;

    }

    public void setBody(String body) {

        this.body = body;

    }

    public String getSubject() {

        return subject;

    }

    public void setSubject(String subject) {

        this.subject = subject;

    }

    public String getOut_trade_no() {

        return out_trade_no;

    }

    public void setOut_trade_no(String out_trade_no) {

        this.out_trade_no = out_trade_no;

    }

    public String getTimeout_express() {

        return timeout_express;

    }

    public void setTimeout_express(String timeout_express) {

        this.timeout_express = timeout_express;

    }

    public String getTotal_amount() {

        return total_amount;

    }

    public void setTotal_amount(String total_amount) {

        this.total_amount = total_amount;

    }

    public String getSeller_id() {

        return seller_id;

    }

    public void setSeller_id(String seller_id) {

        this.seller_id = seller_id;

    }

    public String getProduct_code() {

        return product_code;

    }

    public void setProduct_code(String product_code) {

        this.product_code = product_code;

    }

    public String getGoods_type() {

        return goods_type;

    }

    public void setGoods_type(String goods_type) {

        this.goods_type = goods_type;

    }

    public String getPassback_params() {

        return passback_params;

    }

    public void setPassback_params(String passback_params) {

        this.passback_params = passback_params;

    }

    public String getPromo_params() {

        return promo_params;

    }

    public void setPromo_params(String promo_params) {

        this.promo_params = promo_params;

    }

    public String getExtend_params() {

        return extend_params;

    }

    public void setExtend_params(String extend_params) {

        this.extend_params = extend_params;

    }

    public String getEnable_pay_channels() {

        return enable_pay_channels;

    }

    public void setEnable_pay_channels(String enable_pay_channels) {

        this.enable_pay_channels = enable_pay_channels;

    }

    public String getDisable_pay_channels() {

        return disable_pay_channels;

    }

    public void setDisable_pay_channels(String disable_pay_channels) {

        this.disable_pay_channels = disable_pay_channels;

    }

}

app调用支付宝支付接口,服务端会返回支付信息

参考:https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.DO5i9o&treeId=204&articleId=105296&docType=1

关键代码:其中orderInfo就是服务端返回的订单信息


final String orderInfo = info;   // 订单信息

Runnable payRunnable = new Runnable() {



    @Override

    public void run() {

        PayTask alipay = new PayTask(DemoActivity.this);

        String result = alipay.payV2(orderInfo,true);



        Message msg = new Message();

        msg.what = SDK_PAY_FLAG;

        msg.obj = result;

        mHandler.sendMessage(msg);

    }

};

 // 必须异步调用

Thread payThread = new Thread(payRunnable);

payThread.start();

支付宝服务端调用异步通知接口处理

支付宝服务端调用异步通知接口,根据返回信息处理自己的业务逻辑,比如记入本地台账,修改订单状态等

支付宝回调是要进行验签的,验证通过后在进行操作

关键代码:


/**

 * 支付宝异步回调

 * 

 * @return

 * @throws UnsupportedEncodingException

 */

@RequestMapping(value = "/vipBuy.do", method = RequestMethod.POST)

@ResponseBody

public void vipBuy(HttpServletRequest request,HttpServletResponse response)

        throws UnsupportedEncodingException {

    String str = "";

    // 获取支付宝POST过来反馈信息

    Map<String, String> params = getReqParam(request);

    // 异步通知ID

    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) {// //判断接受的post通知中有无notify_id,如果有则是异步通知。

        boolean signVerified = false;//验签标志

        try {

            signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, "UTF-8");

        } catch (AlipayApiException e) {

            e.printStackTrace();

        }

        // 使用支付宝公钥验签

        if (signVerified){

            //获取回传参数passback_params,即是订单id

            String orderNum = vaan.getOut_trade_no();//订单号

            String orderId = vaan.getPassback_params();//订单id

            //通过订单id和订单编号获取指定的订单信息

            VipOrder vo = new VipOrder();

            vo.setId(orderId);

            vo.setOrderNum(orderNum);

            vo = vipOrderMapper.findByIdOrderNum(vo);

            //验证请求真实性

            boolean flag = checkTrue(vaan,vo);

            if(flag){

                //各状态处理

                if (trade_status.equals("TRADE_FINISHED")) {

                    //没有涉及退款流程,支付完成即是交易结束

                } else if (trade_status.equals("TRADE_SUCCESS")) {

                    //交易成功的逻辑处理

                }

                str = "success";

            }else{

                str = "failure";

            }

        } else{

            // 验证签名失败

            str = "failure";

        }

    } 

    //返回给支付宝,以免导致重复发送数据

    //程序执行完后必须打印输出“success”(不包含引号)。

    //如果商户反馈给支付宝的字符不是success这7个字符,支付宝服务器会不断重发通知,直到超过24小时22分钟。

    //一般情况下,25小时以内完成8次通知(通知的间隔频率一般是:4m,10m,10m,1h,2h,6h,15h);

    try {

        response.getWriter().print(str);

        System.out.println(str);

    } catch (IOException e) {

        e.printStackTrace();

    }

}



/**

 * 获取支付宝回调传入的参数,包含订单的所有信息

 * @param request

 * @return

 */

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.length; i++) {

            valueStr = (i == values.length - 1) ? valueStr + values[i]

                    : valueStr + values[i] + ",";

        }

        // 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化

        // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");

        params.put(name, valueStr);

    }

    return params;

}



/**

 * 通过支付类型和支付返回结果,获取支付状态 1-支付成功 2-支付失败

 * @param return_code

 * @param string

 * @return

 */

private Integer getPayState(String returnCode, String payType) {

    if(payType.equals(VipOrder.PAYMODE_WX)){

        if(returnCode.equals("SUCCESS")){

            return 1;

        }else{

            return 2;

        }

    }else if(payType.equals(VipOrder.PAYMODE_ALIPAY)){

        if(returnCode.equals("TRADE_SUCCESS") || returnCode.equals("TRADE_FINISHED")){

            return 1;

        }else{

            return 2;

        }

    }

    return 2;

}



/**

 * 验证数据真实性

 * 一、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号

 * 二、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额)

 * 三、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)

 * 四、验证app_id是否为该商户本身

 * 五、验证本地订单状态是否是已经成功的,避免重复购买会员

 * 上面验证都通过,才可以进行后续工作

 * @param vaan

 * @return

 */

private boolean checkTrue(VipAlipayAsynNotify vaan,VipOrder vo) {

    //一、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号

    //如果不存在则说明反馈的订单号和订单id对不上

    if(vo == null){

        return false;

    }

    //支付完成,也不在进行业务处理

    if(vo.getPayState().equals(VipOrder.PAYSTATE_SUCCESS) || vo.getPayState().equals(VipOrder.PAYSTATE_FINISHED)){

        return false;

    }

    //二、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额)

    if(!vo.getCurrentPrice().equals(vaan.getTotal_amount())){

        return false;

    }

    //三、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)

    //四、验证app_id是否为该商户本身

    //上面四步验证都通过,才可以进行后续工作

    return true;

}


版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/flygoa/article/details/54891473

对接支付宝支付接口开发详细步骤

对接支付宝支付接口,官方文档已经写的很清楚了,但是也有很多像我一样的小白,第一次对接支付宝支付接口,会有些迷茫,所以我在此写下这篇文章,给我和我一样的同学,一点思路吧。 第一步:(先要在支付宝进行操...
  • cdszdd8
  • cdszdd8
  • 2017-08-07 10:25:28
  • 14992

支付宝支付流程详解

demo: https://github.com/zhonggaorong/alipayDemo 支付宝支付大致流程为 : 1. 公司与支付宝进行签约 , 获得商户ID(partner)和账号ID(s...
  • Liuwx_CSDN
  • Liuwx_CSDN
  • 2017-01-19 10:17:07
  • 3216

Android支付宝支付开发流程

Android支付宝支付开发流程 需要内容: 账号信息:商户号、商户收款账号、商户私钥、支付宝公钥、 支付回调地址(支付宝请求服务器地址) aliPaySDK.jar包、 Base64.jav...
  • jiashuai94
  • jiashuai94
  • 2017-07-05 19:56:08
  • 1954

支付宝支付流程

在iOS应用里集成支付宝支付,需要公司和支付宝签约,然后生成相应的密钥。密钥的生成支付宝的开发文档里已经说的非常清楚。 官方的文档和SDK: https://doc.open.alipay.com/d...
  • lvchaman
  • lvchaman
  • 2016-05-26 18:07:16
  • 5753

支付宝支付-APP支付服务端详解

支付宝APP支付服务端详解前面接了微信支付,相比微信支付,支付宝APP支付提供了支付分装类,下面将实现支付宝APP支付、订单查询、支付结果异步通知、APP支付申请参数说明,以及服务端返回APP端发起支...
  • fengshizty
  • fengshizty
  • 2016-11-18 13:58:57
  • 32936

支付宝支付——app支付服务端详解

【背景】 我们公司需要在自己的app应用中集成支付宝支付功能,当前,我们已有的材料是:经过实名认证的支付宝账户,暂无别的资料。当然,当前的支付宝账户已满足app支付的准入条件。具体请参考:app支付—...
  • u012788601
  • u012788601
  • 2017-12-26 21:13:15
  • 2909

支付宝APP支付开始遇到的一个小坑

支付宝APP支付的第一步是需要由服务端调用支付宝接口(类似预创建),获得一个orderInfo(这个orderInfo包含了订单数据)返回给客户端,客户端调用支付宝SDK发起支付时需要这个orderI...
  • sinat_26007509
  • sinat_26007509
  • 2017-07-16 15:42:37
  • 1440

一步步教你如何为你的app接入支付宝

官方接口文档步骤链接: https://doc.open.alipay.com/doc2/detail?treeId=59&articleId=103563&docType=1 1首先,你的要有一...
  • u013424496
  • u013424496
  • 2016-08-02 09:51:51
  • 16720

支付宝APP支付和扫码支付

  • 2017年09月17日 15:50
  • 6KB
  • 下载
收藏助手
不良信息举报
您举报文章:支付宝APP支付——支付流程说明及示例
举报原因:
原因补充:

(最多只允许输入30个字)