All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.mingsoft.pay.action.web.AlipayAction Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (c) 2012-present 铭软科技(mingsoft.net)
 * 本软件及相关文档文件(以下简称“软件”)的版权归 铭软科技 所有
 * 遵循 铭软科技《服务协议》中的《保密条款》
 */

package net.mingsoft.pay.action.web;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.alipay.api.*;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import net.mingsoft.base.entity.ResultData;
import net.mingsoft.basic.util.BasicUtil;
import net.mingsoft.mdiy.util.ConfigUtil;
import net.mingsoft.pay.action.BaseAction;
import net.mingsoft.pay.bean.PayBean;
import net.mingsoft.pay.biz.IPayLogBiz;
import net.mingsoft.pay.constant.Const;
import net.mingsoft.pay.entity.PayLogEntity;
import net.mingsoft.pay.entity.PayLogEntity.LogStatusEnum;
import net.mingsoft.pay.entity.PayLogEntity.LogTypeEnum;
import net.mingsoft.pay.util.PayUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 支付宝支付接口
 */
@Api(tags = {"前端-支付模块接口"})
@Controller
@RequestMapping("/mpay/alipay")
public class AlipayAction extends BaseAction {


    /**
     * 交易记录
     */
    @Autowired
    private IPayLogBiz payLogBiz;

    @ApiOperation(value = "支付宝回调接口")
    @SuppressWarnings("rawtypes")
    @PostMapping("/notify")
    @ResponseBody
    public ResultData notify(HttpServletRequest request, HttpServletResponse response) throws IOException, AlipayApiException {
        // 获取支付宝POST过来反馈信息
        Map params = new HashMap();
        Map requestParams = request.getParameterMap();
        LOG.info("requestParams {}",JSONUtil.toJsonStr(requestParams));
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = (String) iter.next();
            LOG.info("name {}",JSONUtil.toJsonStr(requestParams.get(name)));
            String valueStr = "";
            if (requestParams.get(name) instanceof String[]) {
                String[] values = (String[]) requestParams.get(name);
                for (int i = 0; i < values.length; i++) {
                    valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
                }
            }else {
                valueStr = (String) requestParams.get(name);
            }
            // 乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
            params.put(name, valueStr);
        }
        // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
        // 商户订单号
        String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");

        String price = request.getParameter("total_amount");
        String logTitle = request.getParameter("subject");
        //公用回传参数
        String passextraCommonParamback = request.getParameter("passback_params");
        // 支付宝交易号
        String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");
        // 交易状态
        String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
        // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
        LOG.debug("支付回调");
        Map alipayConfig = ConfigUtil.getMap(Const.ALIPAY_PAY_CONFIG_NAME);

        //app支付验证标记
        //网站支付验证标记
        boolean flag = false;
        //验证一次就会消耗sign
        flag = AlipaySignature.rsaCheckV1(params, alipayConfig.get("payAlipayPublicKey"), "utf-8", "RSA2");
        if (flag) {
            // 验证成功
            // ////////////////////////////////////////////////////////////////////////////////////////
            // 请在这里加上商户的业务逻辑程序代码

            // ——请根据您的业务逻辑来编写程序(以下代码仅作参考)——
            LOG.debug("支付回调成功");
            PayLogEntity payLog = new PayLogEntity();
            payLog.setOrderNo(out_trade_no);
            PayLogEntity newPayLog = (PayLogEntity) payLogBiz.getEntity(payLog);
            //TRADE_SUCCESS :交易支付成功、TRADE_FINISHED :交易结束,不可退款
            if ("TRADE_FINISHED".equals(trade_status) || "TRADE_SUCCESS".equals(trade_status)) {
                // 判断该笔订单是否在商户网站中已经做过处理
                // 如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                // 如果有做过处理,不执行商户的业务程序
                LOG.debug("支付回调订单:" + out_trade_no);
                //回写日志,修改支付状态
                if (newPayLog != null) {
                    if (StringUtils.equals(newPayLog.getLogStatus(), LogStatusEnum.UN_PAY.toString())) {

                        HashMap map = JSONUtil.toBean(URLDecoder.decode(passextraCommonParamback), HashMap.class);
                        newPayLog.setLogStatus(LogStatusEnum.PAY.toString());
                        newPayLog.setLogPayType(PayBean.Type.ALIPAY);
                        newPayLog.setLogDate(new Date());
                        newPayLog.setUpdateDate(new Date());
                        newPayLog.setLogTransactionId(trade_no);
                        newPayLog.setLogType(LogTypeEnum.OUTCOME.toString());
                        newPayLog.setPeopleId(map.get(Const.Attach.USER_ID).toString());
                        payLogBiz.updateEntity(newPayLog);
                        LOG.info("附加参数attach:{}会员编号{}", passextraCommonParamback, newPayLog.getPeopleId());
                        //根据扩展字段回调执行方法
                        if (StringUtils.isNotBlank(passextraCommonParamback)) {
                            PayUtil.callPayNotfiy(newPayLog, URLDecoder.decode(passextraCommonParamback));
                        }

                    }
                }
                return ResultData.build().success(newPayLog);
                // 注意:
                // 该种交易状态只在两种情况下出现
                // 1、开通了普通即时到账,买家付款成功后。
                // 2、开通了高级即时到账,从该笔交易成功时间算起,过了签约时的可退款时限(如:三个月以内可退款、一年以内可退款等)后。
            }
            LOG.debug("支付回调成功,支付状态trade_status:{}验证失败", trade_status);
            return ResultData.build().error(this.getResString("pay.notify.fail"));
        } else {// 验证失败
            LOG.debug("支付回调订单失败:");
            return ResultData.build().error(this.getResString("pay.notify.verification.fail"));
        }
    }

    @ApiOperation(value = "支付宝支付接口,只提供网关调用/mpay/pay/gateway")
    @RequestMapping(value = "/pay", method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public ResultData pay(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
        //https://docs.open.alipay.com/62/104744/  即时到账文档
        PayBean pay = (PayBean) request.getAttribute("pay");
        String notifyUrl = pay.getNotifyUrl();
        // 把请求参数打包成数组
        Map sParaTemp = new HashMap();
        if (StringUtils.isBlank(notifyUrl)) {
            notifyUrl = BasicUtil.getApp().getAppHostUrl() + net.mingsoft.pay.constant.Const.ALIPAY_NOTIFY_URL;
        }
        AlipayRequest pagePayRequest;
        AlipayTradePagePayModel model = new AlipayTradePagePayModel();
        if (this.isMobileDevice(request)) {// 判断是否是手机端
            pagePayRequest = new AlipayTradeWapPayRequest();
            model.setProductCode("QUICK_WAP_PAY");
        } else {
            pagePayRequest = new AlipayTradePagePayRequest();
            model.setProductCode("FAST_INSTANT_TRADE_PAY");
        }
        pagePayRequest.setNotifyUrl(notifyUrl);
        pagePayRequest.setReturnUrl(pay.getReturnUrl());
        model.setOutTradeNo(pay.getOrderNo());
        LOG.info("pay支付订单:{}", pay.getOrderNo());
        model.setBody(pay.getOrderDesc());
        model.setSubject(pay.getOrderName());
        model.setTotalAmount(pay.getOrderPrice());
        //该笔订单允许的最晚付款时间
        model.setTimeoutExpress("100m");
        if (StringUtils.isNotEmpty(pay.getAttach())) {
            //公用回传参数
            model.setPassbackParams(URLEncoder.encode(pay.getAttach(), "UTF-8"));
        }
        pagePayRequest.setBizModel(model);
        LOG.debug("model参数:{}", JSONUtil.toJsonStr(model));
        Map alipayConfig = ConfigUtil.getMap(Const.ALIPAY_PAY_CONFIG_NAME);
        if (CollUtil.isEmpty(alipayConfig)) {
            return ResultData.build().error(this.getResString("err.not.exist", this.getResString("bank.pay")));
        }
        //实例化客户端
        AlipayClient alipayClient = new DefaultAlipayClient(net.mingsoft.pay.constant.Const.ALIPAY_GATEWAY_URL,
                alipayConfig.get("payAppId"),
                alipayConfig.get("payAppPrivateKey"),
                AlipayConstants.FORMAT_JSON, AlipayConstants.CHARSET_UTF8,
                alipayConfig.get("payAlipayPublicKey"), AlipayConstants.SIGN_TYPE_RSA2);
        try {
            String body = alipayClient.pageExecute(pagePayRequest).getBody();
            return ResultData.build().success(body);
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return ResultData.build().error(this.getResString("pay.notify.verification.fail"));
        }
    }


    /**
     * 支付宝app支付,只提供网关调用/mpay/pay/gateway
     *
     * @param request
     * @param response
     */
    @ApiOperation(value = "支付宝APP支付接口,只提供网关调用/mpay/pay/gateway")
    @RequestMapping(value = "/appPay", method = {RequestMethod.GET, RequestMethod.POST})
    @ResponseBody
    public ResultData appPay(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
        // 支付所有参数通过网关传递过来
        PayBean pay = (PayBean) request.getAttribute("pay");
        Map alipayConfig = ConfigUtil.getMap(Const.ALIPAY_PAY_CONFIG_NAME);
        if (CollUtil.isEmpty(alipayConfig)) {
            return ResultData.build().error(getResString("err.empty", this.getResString("pay.config")));
        }
        //实例化客户端
        AlipayClient alipayClient = new DefaultAlipayClient(net.mingsoft.pay.constant.Const.ALIPAY_APP_PAY_URL,
                alipayConfig.get("payAppId"),
                alipayConfig.get("payAppPrivateKey"),
                "json", "UTF-8",
                alipayConfig.get("payAlipayPublicKey"), "RSA2");
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
        AlipayTradeAppPayRequest payRequest = new AlipayTradeAppPayRequest();
        //SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();

        //需要配合前端传递参数

        model.setBody(pay.getOrderDesc());
        //订单标题
        model.setSubject(pay.getOrderName());
        //订单号
        model.setOutTradeNo(pay.getOrderNo());
        //该笔订单允许的最晚付款时间
        model.setTimeoutExpress("100m");
        //支付金额
        model.setTotalAmount(pay.getOrderPrice());
        //销售产品码,商家和支付宝签约的产品码,为固定值
        model.setProductCode("QUICK_MSECURITY_PAY");
        //判断是否有其他信息参数
        if (StringUtils.isNotEmpty(pay.getAttach())) {
            //公用回传参数
            model.setPassbackParams(URLDecoder.decode(pay.getAttach(), "UTF-8"));
        }
        payRequest.setBizModel(model);
        if (StringUtils.isEmpty(pay.getNotifyUrl())) {
            pay.setNotifyUrl(BasicUtil.getApp().getAppHostUrl() + net.mingsoft.pay.constant.Const.ALIPAY_NOTIFY_URL);
        }
        //支付回调
        payRequest.setNotifyUrl(BasicUtil.getUrl() + pay.getNotifyUrl());
        try {
            //这里和普通的接口调用不同,使用的是sdkExecute
            AlipayTradeAppPayResponse alipayTradeAppPayResponse = alipayClient.sdkExecute(payRequest);
            return ResultData.build().success(alipayTradeAppPayResponse.getBody());
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return ResultData.build().error(this.getResString("pay.notify.verification.fail"));
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy