`

java 对接支付宝支付

阅读更多

对接支付宝支付的前提:

1,商户开通支付能力

登录蚂蚁金服 开放平台:https://open.alipay.com/platform/home.htm

需要开通 的功能选项有:

创建应用,类型是:网页&移动应用

设置应用的RSA 等各项参数,界面如下:

支付宝推荐使用RSA2 加密方式,老版的加密方式只有RSA 和md5,没有RSA2.

本项目使用RSA2 加密方式

2,对接支付宝依赖的jar包

 <!-- https://mvnrepository.com/artifact/net.guerlab/sdk-alipay-core -->
        <dependency>
            <groupId>net.guerlab</groupId>
            <artifactId>sdk-alipay-core</artifactId>
            <version>1.0.3</version>
        </dependency>

 

我写了一个专门封装对接支付宝的Service 层

见代码:https://gitee.com/kunlunsoft/pay_service.git

项目结构:

发起支付 控制器(需根据实际情况修改):

下面的"/order/startPay"接口

package com.girltest.web.controller.pay;

import com.common.annotation.NoLogin;
import com.common.bean.BaseResponseDto;
import com.common.dict.Constant2;
import com.common.util.RedisHelper;
import com.common.util.SystemHWUtil;
import com.girltest.dao.AlipayNotifySuccessDao;
import com.girltest.dao.BusinessOrderDao;
import com.girltest.entity.BusinessOrder;
import com.house.ujiayigou.thirdpart.alipay.config.AlipayConfig;
import com.house.ujiayigou.thirdpart.alipay.info.PayFormInfo;
import com.string.widget.util.RandomUtils;
import com.string.widget.util.ValueWidget;
import com.time.util.TimeHWUtil;
import com.yunmasoft.service.pay.AlipayNotifySuccessService;
import com.yunmasoft.service.pay.alipay.AliPayService;
import com.yunmasoft.service.pay.alipay.PayOperation;
import com.yunmasoft.service.pay.alipay.PayService;
import oa.entity.AlipayNotifySuccess;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.math.BigDecimal;
import java.util.Date;

/**
 * Created by tonyjiang on 15/8/28.
 */

@Controller
public class PayOrderController {

    @Resource(name = "alipay")
    private AliPayService aliPayService;
    public static org.slf4j.Logger HttpClientRestLogger = LoggerFactory.getLogger("pay_log");
    //    @Resource
//    private OrderDetailViewModel orderDetailViewModel;
    @Resource
    private AlipayNotifySuccessDao alipayNotifySuccessDao;
    @Resource
    private AlipayNotifySuccessService alipayNotifySuccessService;
    @Resource
    private BusinessOrderDao businessOrderDao;

    /***
     * 抹掉小数点后面的零头
     *
     * @param orderPrice
     * @return
     */
    private static String removeDecimalPoint(BigDecimal orderPrice) {
        String formatPrice = ValueWidget.formatBigDecimal(orderPrice);

        return formatPrice;
    }

    private static void checkOrderStatus(int orderStatus) {
        if (orderStatus == Constant2.ORDERSTATUS_PAID_ALREADY) {
            //支付完成,调到支付成功页
//            LogicBusinessException.throwException("alreadyPaid");
        } else if (orderStatus == Constant2.ORDERSTATUS_CANCELLED) {
            //已经取消了订单
//            LogicBusinessException.throwException("alreadyCancel");
        }
    }


    /***
     * 通过redis 获取订单的支付结果:是否支付成功
     * @param request
     * @param response
     * @param httpSession
     * @param model
     * @param orderNo
     * @return
     */
    @RequestMapping("/order/payOrderResult")
    @ResponseBody
    public String getOrderPayResult(HttpServletRequest request, HttpServletResponse response, HttpSession httpSession, Model model,
                                    @RequestParam(value = "orderNo", required = true) String orderNo) {
        BaseResponseDto baseResponseDto = new BaseResponseDto(PayService.isPaySuccess(orderNo));
        return baseResponseDto.toJson();
    }


    /***
     * 下单页
     * @param model
     * @param request
     * @param response
     * @param release
     * @return
     */
    @RequestMapping(value = "/order/place", produces = SystemHWUtil.RESPONSE_CONTENTTYPE_JSON_UTF)
    public String json2(Model model, HttpServletRequest request, HttpServletResponse response
            , @RequestParam(required = false, defaultValue = "true") Boolean release) {
        String orderNo = "Xr20001" + RandomUtils.getNextInt();
        model.addAttribute("orderNo", orderNo);
        return "pay/wap/placeorder";
    }

    /***
     * 步骤:
     * 1,获取当前用户信息
     * 2,根据订单号查询订单详情
     * 3,校验订单状态和支付方式
     * 4,跳转到第三方支付
     * @param request
     * @param response
     * @param httpSession
     * @param model
     * @param orderNo
     * @param callback
     * @return
     * @throws Exception
     */
    @RequestMapping("/order/startPay")
    @NoLogin
    public String startPay(HttpServletRequest request, HttpServletResponse response, HttpSession httpSession, Model model,
                           @RequestParam(value = "orderNo", required = true) String orderNo,
                           @RequestParam(value = "callback", required = false) String callback
            , BigDecimal shouldPay) throws Exception {


        //p判断该订单号是否已经存在
        AlipayNotifySuccess alipayNotifySuccess = this.alipayNotifySuccessService.getAlipayNotifySuccess(orderNo);
        if (null != alipayNotifySuccess) {
            model.addAttribute("errorMessage", "该订单号已经存在,orderNo:" + orderNo);
            return "pay/alipay";
        }

        // 判断订单号是否存在
        BusinessOrder businessOrder = this.businessOrderDao.get("orderNo", orderNo);
        if (null == businessOrder) {
            model.addAttribute("errorMessage", "该订单号不存在,orderNo:" + orderNo);
            return "pay/alipay";
        }
/*
        //保存订单
        businessOrder = new BusinessOrder();
        businessOrder.setOrderNo(orderNo);
        businessOrder.setTotalPrice(shouldPay);

        CreateTimeUtil.fillTime(businessOrder);
        this.businessOrderDao.add(businessOrder);*/
        //获取当前用户信息

        //7.应付金额
        String strShouldPay = null;
        if (ValueWidget.isNullOrEmpty(shouldPay)) {
            shouldPay=businessOrder.getPrice();
        }
        strShouldPay = ValueWidget.formatBigDecimal(shouldPay);
        //8. 账户
        String sellerAccount = AlipayConfig.seller_email;

        //9.其它
//        RedisHelper.getInstance().saveKeyCache(PayService.REDIS_KEY_STORE_ORDER_PAY_TIME, orderNo, TimeHWUtil.formatDate(new Date(), TimeHWUtil.YYYYMMDD_NO_LINE));
        String orderName = businessOrder.getProductBaseInfo().getDisplayName();
        //10.
        com.house.ujiayigou.thirdpart.alipay.info.PayFormInfo payFormInfo = new PayFormInfo();
        payFormInfo.setOut_trade_no(orderNo);
        payFormInfo.setSubject(orderName);
        payFormInfo.setBody(orderName);
        payFormInfo.setTotal_amount(strShouldPay);
        payFormInfo.setSeller_id(sellerAccount);
        String form = aliPayService.preparePostRequest(payFormInfo);
        HttpClientRestLogger.error("form:" + form);
        model.addAttribute("form", form);

        return "pay/alipay";


    }

    /**
     * 1,获取订单;
     * 2,价格;
     * 3,Identify;
     * 4,第三方支付相关接口service;
     * 5,callback
     * 6,coupon
     * 7,应付金额
     * 8,账户
     * 9,其它
     * 10,
     *
     * @param access_token
     * @param orderNo
     * @param payType
     * @param callback
     * @return
     */
    public String postThirdPayAction(String access_token, String orderNo, String payType, String callback) {
        //订单
       /* OrderInfoBean orderInfo = orderBusiness.getOrderInfoByOrderNo(access_token, orderNo);
        if (orderInfo == null || orderInfo.getItems().size()==0) {
            LogicBusinessException.throwException("cannotMatchOrder");
        }
        checkOrderStatus(orderInfo.orderStatus);
        if (orderInfo.orderStatus != Constant.ORDERSTATUS_ORDERS_SUBMITTED) {
            LogicBusinessException.throwException("20506");
        }*/
        //2.价格
        BigDecimal price = null;//orderBusiness.getOrderMoney(orderInfo);
        if (price == null) {
//            LogicBusinessException.throwException("cannotPay");
        }
        //3.Identify
        String identifier = null;//orderBusiness.getPayIdentify(orderNo, access_token, userInfo, price);


        PayOperation service = null;//(PayOperation) SpringMVCUtil.getBean( payType);
        if (service == null) {
//            LogicBusinessException.throwException("service is null");
        }

        //5.callback
        if (ValueWidget.isNullOrEmpty(callback)) {
            callback = "https:/order/view?orderNo=" + orderNo /*+ "&orgId=" + orgId*/;//千万不要URL转码
        }
        //6.coupon
        BigDecimal coupon = null;
        /*if (Constant.useDebugCouponValue) {
            coupon = new BigDecimal(Constant.couponValue);
        } else {*/
        coupon = new BigDecimal(0);
//        }

        //7.应付金额
        BigDecimal shouldPay = price.subtract(coupon.compareTo(price) < 0 ? coupon : new BigDecimal(0));//
        String strShouldPay = ValueWidget.formatBigDecimal(shouldPay);
        //8. 账户
        String sellerAccount = AlipayConfig.seller_email;

        //9.其它
        RedisHelper.getInstance().saveKeyCache(PayService.REDIS_KEY_STORE_ORDER_PAY_TIME, orderNo, TimeHWUtil.formatDate(new Date(), TimeHWUtil.YYYYMMDD_NO_LINE));
        String orderName = "xxx服务";
        //10.
        com.house.ujiayigou.thirdpart.alipay.info.PayFormInfo payFormInfo = new PayFormInfo();
        payFormInfo.setOut_trade_no(orderNo);
        payFormInfo.setSubject(orderName);
        payFormInfo.setBody(orderName);
        payFormInfo.setTotal_amount(strShouldPay);
        payFormInfo.setSeller_id(sellerAccount);
        String form = service.preparePostRequest(payFormInfo);

        return form;

    }


}

 

支付回调控制器(需根据实际情况修改):

下面的"/notify"接口

import com.common.dict.Constant2;
import com.common.util.*;
import com.yunmasoft.service.pay.alipay.PayOperation;
import com.io.hw.json.HWJacksonUtils;
import com.string.widget.util.ValueWidget;
import oa.util.SpringMVCUtil;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

@Controller
@RequestMapping("/pay")
public class PayController {
    public static Logger logger = Logger.getRootLogger();

    @RequestMapping(value = "notify", produces = {SystemHWUtil.RESPONSE_CONTENTTYPE_JSON_UTF})
    @ResponseBody
    public String callback(
            @RequestParam(required = false) String method,
            @RequestParam(required = false) String out_trade_no/*订单号*/,
            @RequestParam(required = false) String trade_no,
            @RequestParam(required = false) String trade_status,
            @RequestParam(required = false) String extra_common_param,
            @RequestParam(required = false) String notifyUrl,
            @RequestParam(required = false) String body/*只有支付宝手机网站支付才有*/,
            HttpServletResponse response,
            HttpServletRequest request) {
        //userIdAndLoginnameAndOrgId 在请求参数中
        // 1.获取订单号
        if (ValueWidget.isNullOrEmpty(out_trade_no)) {
            out_trade_no = request.getParameter("outer_trade_no");
        }

        // 2.畅捷支付没有extra_common_param,兼容畅捷支付
        if (ValueWidget.isNullOrEmpty(extra_common_param) && !ValueWidget.isNullOrEmpty(notifyUrl)) {//added by huangweii
            Map argMap = RequestUtil.parseQueryString(notifyUrl);
            extra_common_param = (String) argMap.get("chanpay");
        }

        logger.info(HWJacksonUtils.getJsonP(request.getParameterMap()));


        // 3.兼容extra_common_param为空的情况
        boolean isAlipayMobile = false;
        if (ValueWidget.isNullOrEmpty(extra_common_param)) {//added by huangweii,extra_common_param为空,说明是xx支付
            String extra_common_paramSuffix = RedisHelper.getInstance().getCache("store_" + out_trade_no + "_Identifier") +
                    "::" + RedisHelper.getInstance().getCache("store_" + out_trade_no + "_userinfo");
            if (ValueWidget.isNullOrEmpty(request.getParameter("out_trade_no"))) {
                extra_common_param = "chanpay::" + extra_common_paramSuffix;
            } else {
                isAlipayMobile = true;
                extra_common_param = "alipay::" + extra_common_paramSuffix;
            }

        }

        // 4. 缓存日志
//        String currentCache = RedisHelper.getInstance().getKeyCache(Constant.REDIS_ID_STORE, out_trade_no) + "<br>";
//        RedisHelper.getInstance().saveKeyCacheAndExpire(Constant.REDIS_ID_STORE, out_trade_no, currentCache +request.getRequestURI()+ extra_common_param + ",notifyUrl:" + notifyUrl);

        logger.info("extra_common_param:" + extra_common_param);
        // 获取支付宝POST过来反馈信息

        Map requestParams = request.getParameterMap();

        Map<String, String> params = WebServletUtil.getParamMap(requestParams);
//        params.put("userIdAndLoginnameAndOrgId", userIdAndLoginnameAndOrgId);


        // 5.获取service
        PayOperation service = null;
        if (extra_common_param != null && extra_common_param.contains("::")) {

            String[] info = extra_common_param.split("::");
            service = (PayOperation) SpringMVCUtil.getBean(request, info[0]);
        }

        if (service == null) {
            return "fail";
        }


        // 6.验签
        String verity_ok = service.verify(WebServletUtil.getParamMap(requestParams));

        if (!verity_ok.equals("success")) {
            logger.error(params.toString());
            logger.error("verify fail");
            return verity_ok;
        }

        // 7. 缓存日志
//        currentCache = RedisHelper.getInstance().getKeyCache(Constant.REDIS_ID_STORE, out_trade_no) + "<br>";
//        RedisHelper.getInstance().saveKeyCacheAndExpire(Constant.REDIS_ID_STORE, out_trade_no, currentCache + "verity->" + verity_ok);

        

        // 8.回调,调用确认订单接口
        try {
            String pay_ok = service.payNotify(out_trade_no, trade_no, trade_status, params);
            if (pay_ok != null) {
                logger.debug(pay_ok + "");
                return pay_ok; // 请不要修改或删除
            }
        } catch (Exception ex) {
            logger.error("payNOtify error:", ex);
            return "fail";
        }


        return "fail";

    }


    @RequestMapping(value = "payResult")
    public String getPaymentResult(@RequestParam(required = false) String orderid,
                                   @RequestParam(required = false) String userid,
                                   HttpServletRequest request,
                                   HttpServletResponse response,
                                   Model model) throws IOException {
        logger.info("payResult orderid:" + orderid);
        // 获取支付宝POST过来反馈信息
        Map requestParams = request.getParameterMap();

        Map<String, String> params = WebServletUtil.getParamMap(requestParams);
        String orderId = orderid;
        if (ValueWidget.isNullOrEmpty(orderId)) {
            orderId = params.get("orderid");
        }
        if (orderId == null) {
            orderId = params.get("out_trade_no");
        }
        //畅捷支付点击[返回商家] TODO
        if (orderId == null) {
            orderId = params.get("orderId");
        }
        logger.info("payResult params:" + params);
        String payResult = params.get("payResult");
        String extra_common_param = params.get("extra_common_param");
        logger.info("payResult extra_common_param:" + extra_common_param);

        if (!Constant2.CHANPAY_ORDER_RESULT_SUCCESS.equals(payResult)) {
            response.sendRedirect("/order/payOrder?orderId=" + orderId /*+ "&orgId=" + service.getOrgId(orderId)*/);
            return null;
        }
        response.sendRedirect("/order/payComplete?orderId=" + orderId /*+ "&orgId=" + service.getOrgId(orderId)*/);
        return null;

    }


}

 实际支付demo:

http://i.yhskyc.com/product/1

各文档:

电脑网站支付快速接入
https://docs.open.alipay.com/270/105899/
API 详细说明:
https://docs.open.alipay.com/270/alipay.trade.page.pay/

服务端SDK
https://docs.open.alipay.com/54/103419

RSA私钥及公钥生成
https://docs.open.alipay.com/58/103242/
 

RSA私钥及公钥生成 工具:

https://gitee.com/kunlunsoft/http_request_tool

上图中2048 对应RSA2

相关项目:

https://github.com/liuyu520/io0007

https://gitee.com/kunlunsoft/oa_framework

注意:

1,本项目使用新版支付宝支付

即时到账新老版本接口对比
https://docs.open.alipay.com/270/106759

2,新版支付宝支付,就算仅使用PC端网页支付,也需要创建一个应用,老版不需要.

3,电脑端网页支付应该使用:
AlipayTradePagePayRequest,而不是AlipayTradePayRequest;

4,对业务参数(非公共参数),进行 json 序列化时,
一定使用阿里自己的类:
JSONWriter writer = new JSONWriter();
String body=writer.write(model, true);

 

 

 

0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics