支付宝APP支付

支付宝支付和微信支付一样,后端只需要关心三个接口,其他的交给前端,前端集成sdk去操作

https://docs.open.alipay.com/204

 

<!-- 支付宝支付官方SDK -->
<dependency>
   <groupId>com.alipay.sdk</groupId>
   <artifactId>alipay-sdk-java</artifactId>
   <version>3.6.0.ALL</version>
</dependency>

 

支付宝APP支付

支付宝APP支付

package com.otcbi.pay.service.impl;

import com.alipay.api.internal.util.AlipaySignature;
import com.otcbi.coin.common.exception.ApiException;
import com.otcbi.coin.common.exception.ApiResponMessage;
import com.otcbi.common.dto.OperateResult;
import com.otcbi.pay.dto.ShopOrder;
import com.otcbi.pay.entity.AliOrder;
import com.otcbi.pay.service.AliPayService;
import com.otcbi.pay.service.IAliOrderService;
import com.otcbi.pay.utils.SignUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

/**
 * Created by linxinchao on 16/5/4.
 */
@Service
public class AliPayServiceImpl implements AliPayService {
    protected Logger logger = LoggerFactory.getLogger(AliPayServiceImpl.class);

    @Value("${ali.aliCallBackUrl}")
    private String aliCallBackUrl;

    @Value("${ali.appId}")
    private String appId;

    @Value("${ali.timeout}")
    private String timeout;

    @Value("${ali.rsaPrivate}")
    private String rsaPrivate;

    @Autowired
    private IAliOrderService iAliOrderService;

    /**
     * 通用支付的订单列表
     */
    private static Set<String> commonIds = new HashSet<String>();

    @Override
    public OperateResult<Map<String, Object>> buildCommonPay(ShopOrder shopOrder) {
        try {
            if (commonIds.add(String.valueOf(shopOrder.getUserId()))) {
                String productName = "支付" + (shopOrder.getMoney()) + "元";
                return buildPayStr(productName, shopOrder.getMoney().multiply(new BigDecimal(100)).intValue(), shopOrder.getOrderId(), aliCallBackUrl, shopOrder);
            } else {
                throw new ApiException(ApiResponMessage.SHOP_GOODS_ORDER_PAYING, null);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new ApiException(ApiResponMessage.SHOP_GOODS_WEIXIN_PAY_ERROR, null);
        } finally {
            commonIds.remove(String.valueOf(shopOrder.getUserId()));
        }
    }


    private OperateResult<Map<String, Object>> buildPayStr(String body, int money, String orderId, String callbackUrl, ShopOrder shopOrder) throws Exception{
        //1.请求参数按照key=value&key=value方式拼接的未签名原始字符串
        HashMap<String,String> map =  createOrderInfo(body, money, orderId, callbackUrl, shopOrder);
        String orderInfo = map.get("orderInfo");
        AliOrder aliPayOrder = iAliOrderService.getById(map.get("id"));
        try {
            //2.再对原始字符串进行签名(RSA),拼接得到完整的符合支付宝参数规范的订单信息
            String sign = AlipaySignature.rsaSign(orderInfo, rsaPrivate, "utf-8", "RSA");
            String payInfo = orderInfo + "&sign=" + sign;

            //3.最后对请求字符串的所有一级value(biz_content作为一个value)进行encode,编码格式按请求串中的charset为准,没传charset按UTF-8处理,获得最终的请求字符串
            payInfo = URLEncoder.encode(payInfo, "UTF-8");

            aliPayOrder.setState(1);
            aliPayOrder.setModifyTime(LocalDateTime.now());
            iAliOrderService.updateById(aliPayOrder);

            HashMap<String, Object> argmap = new HashMap<>();
            argmap.put("msg", payInfo);
            return new OperateResult<>(argmap);
        }catch (Exception e){
            aliPayOrder.setState(2);
            aliPayOrder.setModifyTime(LocalDateTime.now());
            iAliOrderService.updateById(aliPayOrder);
            throw new ApiException(ApiResponMessage.SHOP_GOODS_WEIXIN_PAY_ERROR, null);
        }

    }


    /**
     * create the order info. 创建订单信息
     */
    private HashMap<String,String> createOrderInfo(String body, int money, String orderId, String notifyUrl, ShopOrder shopOrder) {

        AliOrder aliPayOrder = new AliOrder();

        StringBuffer orderInfo = new StringBuffer();
        // 支付宝分配给开发者的应用ID
        orderInfo.append("app_id=" + appId);
        // 接口名称,固定值
        orderInfo.append("&method=alipay.trade.app.pay");
        //请求使用的编码格式,如utf-8,gbk,gb2312等
        orderInfo.append("&charset=utf-8");
        //商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2
        orderInfo.append("&sign_type=RSA");
        // 发送请求的时间,格式"yyyy-MM-dd HH:mm:ss"
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = sdf.format(new Date());
        orderInfo.append("&timestamp=" + time);
        aliPayOrder.setTimestamp(time);
        //调用的接口版本,固定为:1.0
        orderInfo.append("&version=1.0");
        // 支付宝服务器主动通知商户服务器里指定的页面http/https路径。建议商户使用https
        orderInfo.append("&notify_url=" + notifyUrl);

        /**
         * 业务请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递,具体参照各产品快速接入文档
         */
        StringBuffer bizContent = new StringBuffer();
        // 对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。
        bizContent.append("\"body\":\"" + body + "\"").append(",");
        aliPayOrder.setDescribes(body);
        // 商品的标题/交易标题/订单标题/订单关键字等。
        bizContent.append("\"subject\":\"商城线下订单\"").append(",");
        // 商户网站唯一订单号
        bizContent.append("\"out_trade_no\":\"" + orderId + "\"").append(",");
        aliPayOrder.setOrderId(Long.valueOf(orderId));
        // 该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m。
        //注:若为空,则默认为15d。
        bizContent.append("\"timeout_express=\":\"" + timeout + "\"").append(",");
        aliPayOrder.setTimeout(timeout);
        //订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]
        bizContent.append("\"total_amount\"=:\"" + String.valueOf(money) + "\"").append(",");
        aliPayOrder.setMoney(shopOrder.getMoney());
        //销售产品码,商家和支付宝签约的产品码,为固定值QUICK_MSECURITY_PAY
        bizContent.append("\"product_code\"=\"QUICK_MSECURITY_PAY\"");

        orderInfo.append("&biz_content={" + bizContent.toString() + "}");

        aliPayOrder.setCreateTime(LocalDateTime.now());
        aliPayOrder.setState(0);
        aliPayOrder.setUserId(shopOrder.getUserId());
        aliPayOrder.setIsDeleted("N");

        iAliOrderService.save(aliPayOrder);
        HashMap<String,String> map = new HashMap<>();
        map.put("orderInfo",orderInfo.toString());
        map.put("id",aliPayOrder.getId().toString());
        return map;
    }

    @Override
    public String processCallback(Map<String, String> params, String out_trade_no, String trade_no, String trade_status) {

        if (out_trade_no == null || out_trade_no.length() == 0
                || trade_no == null || trade_no == null
                || trade_no.length() == 0) {
            return "fail";
        }

        /*try {
            if (!outTradeNoSet.add(out_trade_no)) {
                return "fail";
            }

            AliPayOrder order = aliPayOrderDao.queryForObject(Criteria.where("out_trade_no").is(out_trade_no));

            System.out.println(order.getProductId());


            if (order == null) {
                return "fail";
            }
            // 将返回的
            //
            //参数 更新到数据库里面
            order.setAliCallbackParams(new JSONObject(
                    mapStringToObject(params)).toJSONString());
            // 更新最后更新时间
            order.setModifyTime(System.currentTimeMillis());

            String notifyUrl = order.getNotifyUrl();

            for (String v : params.keySet()) {
                System.out.println("key="+params.get(v)+";-->value= " + v);
            }

            boolean flag = AlipayNotify.verify(params);
            System.out.println("将入校验环节-->"+flag);
            if (flag) {// 验证成功
                // ////////////////////////////////////////////////////////////////////////////////////////
                // 请在这里加上商户的业务逻辑程序代码

                System.out.println("支付宝《---》支付成功");

                // ——请根据您的业务逻辑来编写程序(以下代码仅作参考)——
                order.setTrade_no(trade_no);// 啊里的订单号

                boolean isdeal = order.isdeal();

                if (isdeal) {
                    // 已经处理过了,不用处理
                    return "success";
                }
                String res = "success";
                order.setStatus(trade_status);
                if (trade_status.equals("TRADE_FINISHED")) {
                    //支付成功后暂不做处理
                    *//*checkOrderSuccess(params, order, res, notifyUrl, crowdService, userService, genTouService,vipTrendService);*//*
                } else if (trade_status.equals("TRADE_SUCCESS")) {
                    //支付成功后暂不做处理
                    *//*checkOrderSuccess(params, order, res, notifyUrl, crowdService, userService, genTouService,vipTrendService);*//*
                } else if (trade_status.equals("WAIT_BUYER_PAY")) {
                    return "success";
                } else {
                    res = "fail";
                }

                GameOrder gameOrder = gameOrderRepository.queryForObject(Criteria.where("orderId").is(order.getProductId()));
                if(gameOrder == null){
                    return "fail";
                }
                int money = (int)(gameOrder.getMoney()/100);
                //TODO 加金币
                GameShop gameShop = gameShopRepository.queryForObject(Criteria.where("shopId").is(gameOrder.getShopId()));
                Criteria criteria = Criteria.where("uid").is(gameOrder.getUserId());
                User winThreeUser = userRepository.queryForObject(criteria);
                if (winThreeUser == null) {
                    return "fail";
                }
                long num = 0;//金币
                long card = 0;//房卡
                long ticket = 0;//参赛券
                long subsidy = 0;//破产补助
                long goldenKey = 0;//金钥匙

                Update update = new Update();
                Date date = DateUtil.getDateYMD();
                if (gameShop.getShopType().equals(ShopType.GOLD)) {//TODO 金币
                    num += gameShop.getShopNum()+gameShop.getSendNum();
                } else if (gameShop.getShopType().equals(ShopType.ROOMCARD)) {//TODO 房卡
                    card += gameShop.getShopNum()+gameShop.getSendNum();
                } else if (gameShop.getShopType().equals(ShopType.GOLDEN_KEY)) {//TODO 金钥匙
                    goldenKey += gameShop.getShopNum()+gameShop.getSendNum();
                }else if(gameShop.getShopType().equals(ShopType.TICKET)){//TODO 参赛券
                    ticket += gameShop.getShopNum()+gameShop.getSendNum();
                }else if(gameShop.getShopType().equals(ShopType.PLANTINA_MONTHCARD)){//TODO 白金月卡

                    for (GiftBag giftBag : gameShop.getGiftBags()) {
                        if (giftBag.getAwardType().equals(ShopType.GOLD)) {
                            num += giftBag.getNum();
                        } else if (giftBag.getAwardType().equals(ShopType.ROOMCARD)) {
                            card += giftBag.getNum();
                        }else if(giftBag.getAwardType().equals(ShopType.TICKET)){
                            ticket += giftBag.getNum();
                        }
                    }
                    TimeSection time = winThreeUser.getPlatina();
                    if(time == null){
                        time = new TimeSection();
                    }
                    if(time.getStartTime() == 0){
                        time.setStartTime(date.getTime());
                        time.setEndTime(DateUtil.getDate(date,30).getTime());
                    }else{
                        time.setEndTime(DateUtil.getDate(new Date(time.getEndTime()),30).getTime());
                    }
                    update.set("platina",time);
                }else if(gameShop.getShopType().equals(ShopType.TYRANT_MONTHCARD)){//TODO 土豪月卡

                    for (GiftBag giftBag : gameShop.getGiftBags()) {
                        if (giftBag.getAwardType().equals(ShopType.GOLD)) {
                            num += giftBag.getNum();
                        } else if (giftBag.getAwardType().equals(ShopType.ROOMCARD)) {
                            card += giftBag.getNum();
                        }else if(giftBag.getAwardType().equals(ShopType.TICKET)){
                            ticket += giftBag.getNum();
                        }
                    }

                    TimeSection time = winThreeUser.getTyrant();
                    if(time == null){
                        time = new TimeSection();
                    }
                    if(time.getStartTime() == 0){
                        time.setStartTime(date.getTime());
                        time.setEndTime(DateUtil.getDate(date,30).getTime());
                    }else{
                        time.setEndTime(DateUtil.getDate(new Date(time.getEndTime()),30).getTime());
                    }
                    update.set("tyrant",time);
                }else if (gameShop.getShopType().equals(ShopType.PLAYDAY)){//TODO 一日畅玩

                    for (GiftBag giftBag : gameShop.getGiftBags()) {
                        if (giftBag.getAwardType().equals(ShopType.GOLD)) {
                            num += giftBag.getNum();
                        } else if (giftBag.getAwardType().equals(ShopType.SUBSIDY)) {
                            subsidy += giftBag.getNum();
                        }
                    }

                } else {//TODO 礼包
                    List<String> listGiftStr = winThreeUser.getGiftFirst();
                    if (CollectionUtils.isEmpty(listGiftStr)) {
                        listGiftStr = new ArrayList<>();
                    }
                    if (!listGiftStr.contains(gameOrder.getShopId())) {//判断是否是首冲
                        List<GiftBag> listGift = gameShop.getGiftBags();
                        if (!CollectionUtils.isEmpty(listGift)) {
                            for (GiftBag giftBag : listGift) {
                                if (giftBag.getAwardType().equals(ShopType.GOLD)) {
                                    num += giftBag.getNum();
                                } else if (giftBag.getAwardType().equals(ShopType.ROOMCARD)) {
                                    card += giftBag.getNum();
                                }else if(giftBag.getAwardType().equals(ShopType.TICKET)){
                                    ticket += giftBag.getNum();
                                }
                            }
                        }
                        listGiftStr.add(gameOrder.getShopId());
                        update.set("giftFirst", listGiftStr);
                    }
                }
                //完成第一次购买商品任务
                if(gameTaskRepository.exist(Criteria.where("tid").is(FIRST_SHOP_ID))){//首冲
                    UserTask userTask = new UserTask();
                    userTask.setTid(FIRST_SHOP_ID);
                    userTask.setUid(winThreeUser.getUid());
                    userTask.setPlan(1);
                    userTaskRepository.executeSave(userTask);
                }
                if(gameTaskRepository.exist(Criteria.where("tid").is(DAY_FIRST_SHOP_ID))){//每天任意冲
                    UserTask userTask = new UserTask();
                    userTask.setTid(DAY_FIRST_SHOP_ID);
                    userTask.setUid(winThreeUser.getUid());
                    userTask.setPlan(1);
                    userTaskRepository.executeSave(userTask);
                }
                if(gameTaskRepository.exist(Criteria.where("tid").is(DN_10GOLD))){//充值10
                    ReqUpdateAward reqUpdateAward = new ReqUpdateAward();
                    reqUpdateAward.setUid(gameOrder.getUserId());
                    reqUpdateAward.setTid(DN_10GOLD);
                    reqUpdateAward.setPlan(money);
                    userTaskService.updateUserTask(reqUpdateAward);
                }
                if(gameTaskRepository.exist(Criteria.where("tid").is(DN_1000GOLD))){//充值1000
                    ReqUpdateAward reqUpdateAward = new ReqUpdateAward();
                    reqUpdateAward.setUid(gameOrder.getUserId());
                    reqUpdateAward.setTid(DN_1000GOLD);
                    reqUpdateAward.setPlan(money);
                    userTaskService.updateUserTask(reqUpdateAward);
                }

                if ((winThreeUser.getFirstCharge() == null || !winThreeUser.getFirstCharge()) && !gameShop.getShopType().equals(ShopType.GIFTBAG)) {//判断是否是首冲
                    update.set("firstCharge", true);
                    num += FIRST_CHANGE_MONEY;
                    if(version == 1){
                        card += 2;
                    }
                    System.out.println("首冲"+num);
                }


                winThreeUser.setRechargePoint(winThreeUser.getRechargePoint()+money);

                update.inc("monthPoint",money);
                update.inc("dialIndex",money);
                update.inc("rechargePoint",money);

                //VIP 处理
                if(winThreeUser.getVipLevel()>0&&gameShop.getShopType().equals(ShopType.GOLD)){//vip金币赠送
                    //购买金币赠送 和超级礼包生效
                    GameVip gameVip = gameVipService.getGameVipByVipLevel(winThreeUser.getVipLevel());

                    //增加贈送金幣
                    long  giveAwayGold = new BigDecimal(gameShop.getShopNum()*gameVip.getGiveAway()).setScale(0,BigDecimal.ROUND_HALF_DOWN).longValue();
                    num += giveAwayGold;
                }

                //修改或添加参赛券
                if(ticket > 0){
                    Criteria criteriaTicket = Criteria.where("uname").is(winThreeUser.getName());
                    if(ticketsRepository.exist(criteriaTicket)){

                        Update updateTicket = new Update();
                        updateTicket.inc("ticket",ticket);
                        ticketsRepository.updateObject(criteriaTicket,updateTicket);
                    }else{
                        Tickets tickets = new Tickets();
                        tickets.setTicket(ticket);
                        tickets.setUname(winThreeUser.getName());
                        ticketsRepository.executeSave(tickets);
                    }
                }


                if(!StringUtils.isEmpty(scoreUrl)){
                    String result = HttpUtil.sendGet(scoreUrl,"uid="+winThreeUser.getUid()+"&score="+num+"&roomCardNum="+card+"&subsidy="+subsidy);
                    JSONObject json = null;
                    try{
                        json = JSON.parseObject(result);
                    }catch (Exception e){
                        return "fail";
                    }

                    if(json == null || json.getIntValue("state")!=200){
                        return "fail";
                    }
                }else{
                    update.inc("score", num);
                    update.inc("roomCardNum", card);
                }
                if(goldenKey > 0){
                    update.set("goldenKey",goldenKey);
                }
                update.set("payState","Y");//修改支付状态
                userRepository.updateObject(criteria, update);//修改金币


                aliPayOrderDao.executeSave(order);

                if(!StringUtils.isEmpty(callBackUrl)){
                    HttpUtil.sendGet(callBackUrl, "uid=" + gameOrder.getOrderId());
                }

                return res; // 请不要修改或删除
            } else {// 验证失败
                return "fail";
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            outTradeNoSet.remove(out_trade_no);
        }*/
        return "fail";
    }


    /*    */

    /**
     * 检查是订单是否成功
     *//*
    private void checkOrderSuccess(Map<String, String> params, AliOrder order, String res, String notifyUrl) {
        String buyerNo = params.get("buyer_email");
        String productId = "";// order.getProductId();
        boolean result = false;
        if (result) {
            order.setIsdeal(true);
            order.setUpdateMsg("支付成功(支付宝)");
        } else {
            res = "fail";
            order.setIsdeal(false);
            order.setUpdateMsg("更新产品状态失败(支付宝)");
        }
    }*/
    private Map<String, Object> mapStringToObject(
            Map<String, String> params) {
        Map<String, Object> newparams = new HashMap<String, Object>();
        Set<String> keys = params.keySet();
        for (String key : keys) {
            newparams.put(key, params.get(key));
        }
        return newparams;
    }

    /**
     * get the out_trade_no for an order. 生成商户订单号,该值在商户端应保持唯一(可自定义格式规范)
     */
    private String getOutTradeNo() {
        SimpleDateFormat format = new SimpleDateFormat("MMddHHmmss",
                Locale.getDefault());
        Date date = new Date();
        String key = format.format(date);
        Random r = new Random();
        key = key + r.nextInt();
        key = key.substring(0, 15);
        return key;
    }

    /**
     * sign the order info. 对订单信息进行签名
     *
     * @param content 待签名订单信息
     */
    private String sign(String content, String rsaPrivate) {
        return SignUtils.sign(content, rsaPrivate);
    }

    /**
     * get the sign type we use. 获取签名方式
     */
    private String getSignType() {
        return "sign_type=\"RSA\"";
    }


}

所有的后端代码差不多都在上面了