欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java 对接支付宝支付

程序员文章站 2022-07-04 08:10:48
...

对接支付宝支付的前提:

1,商户开通支付能力

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

java 对接支付宝支付
            
    
    博客分类: IDEAspring MVC 支付宝支付对接支付宝alipay 

需要开通 的功能选项有:

java 对接支付宝支付
            
    
    博客分类: IDEAspring MVC 支付宝支付对接支付宝alipay 

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

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

java 对接支付宝支付
            
    
    博客分类: IDEAspring MVC 支付宝支付对接支付宝alipay 

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

本项目使用RSA2 加密方式

java 对接支付宝支付
            
    
    博客分类: IDEAspring MVC 支付宝支付对接支付宝alipay 

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

项目结构:

java 对接支付宝支付
            
    
    博客分类: IDEAspring MVC 支付宝支付对接支付宝alipay 

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

下面的"/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

java 对接支付宝支付
            
    
    博客分类: IDEAspring MVC 支付宝支付对接支付宝alipay 

各文档:

电脑网站支付快速接入
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

java 对接支付宝支付
            
    
    博客分类: IDEAspring MVC 支付宝支付对接支付宝alipay 

上图中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);