Java实现支付宝充值

支付宝SDK依赖

        <!--支付宝-->
        <dependency>
            <groupId>com.alipay.sdk</groupId>
            <artifactId>alipay-sdk-java</artifactId>
            <version>3.3.4.ALL</version>
        </dependency>

支付宝参数配置类

@Component
@Configuration
public class AliDevPayConfig implements Serializable {
    /**
     * 支付宝服务器主动通知商户服务器里指定的页面http/https路径
     * 异步请求,地址必须是公网可以访问的才行,不能有任何参数
     * 例如:项目发布地址/本项目名/接口名
     */
    public static String NOTIFY_URL;

    public static String RETURN_URL;

    @Value("${alipay.aliPayReturnUrl}")
    public void setReturnUrl(String returnUrl) {
        RETURN_URL = returnUrl;
    }
    @Value("${alipay.aliPayNotifyUrl}")
    public void setNotifyUrl(String notifyUrl) {
        NOTIFY_URL = notifyUrl;
    }

    public String getNotifyUrl() {
        return NOTIFY_URL;
    }
    public String getReturnUrl() {
        return RETURN_URL;
    }

    /**支付宝分配给开发者的应用ID*/
    public static String aliPayAppId = "开发者id";
    /**支付宝网关*/
    public static String aliPayGateWay = "https://openapi.alipay.com/gateway.do";

    /**私钥*/
    public static String aliPayPrivateKey = "你的私钥";
    /**支付宝公钥*/
    public static String aliPayPublicKey = "你的公钥";

    /**仅支持JSON*/
    public static String FORMAT = "JSON";
    /**请求使用的编码格式,如utf-8,gbk,gb2312等*/
    public static String CHARSET = "utf-8";
    /**商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2*/
    public static String SIGN_TYPE = "RSA2";
}

因为我的项目有多个环境,会有多个对应的配置文件,所以我选择用@Value注入的方式。
配置文件的url配置如下:

alipay:
  aliPayNotifyUrl: 异步回调url
  aliPayReturnUrl: 同步回调url

Controller

    @Resource
    PayService payService;

    @RequestMapping(value = "/ali", method = RequestMethod.POST)
    @ApiOperation(value="[支付宝]充值")
    public Result<String> alipayTopup(@RequestBody AliPayRechargeDTO aliPayRechargeDTO){
        return Result.getSuccess(payService.saveAliPayRechangeBill(aliPayRechargeDTO));
    }


    @RequestMapping(value = "/alipaynotice", method = RequestMethod.POST)
    @ApiOperation(value="[支付宝专用]支付宝充值接口异步回调接口")
    public String paynotice(HttpServletRequest request){
        return payService.alipayNotify(request);
    }

DTO对象传入你所需要的参数,比如金额,账户id等等。

Service

@Slf4j
@Service
public class PayService{

    public String saveAliPayRechangeBill(AliPayRechargeDTO rechargeDTO){
        BigDecimal totalAmount = rechargeDTO.getRechargeTotalAmount();

        //实例化客户端(参数:网关地址、商户appid、商户私钥、格式、编码、支付宝公钥、加密类型),为了取得预付订单信息
        AlipayClient alipayClient = new DefaultAlipayClient(AliDevPayConfig.aliPayGateWay, AliDevPayConfig.aliPayAppId,
                AliDevPayConfig.aliPayPrivateKey, AliDevPayConfig.FORMAT, AliDevPayConfig.CHARSET,
                AliDevPayConfig.aliPayPublicKey, AliDevPayConfig.SIGN_TYPE);
        //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
        AlipayTradeAppPayRequest ali_request = new AlipayTradeAppPayRequest();


        //SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式
        AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();

        //对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。
        model.setBody("xx商品介绍");
        //商品名称
        model.setSubject("xx商品");
        //商户订单号(根据业务需求自己生成)
        model.setOutTradeNo("你自己业务账单的id");
        //交易超时时间 这里的30m就是30分钟
        model.setTimeoutExpress("30m");
        //支付金额 后面保留2位小数点..不能超过2位
        model.setTotalAmount(totalAmount.toString());
        //销售产品码(固定值)
        model.setProductCode("QUICK_MSECURITY_PAY");

        ali_request.setBizModel(model);



        //异步回调地址(后台)
        ali_request.setNotifyUrl(AliDevPayConfig.NOTIFY_URL);
        log.info("Alipay异步通知的地址为:" + ali_request.getNotifyUrl());

        try{
            // 这里和普通的接口调用不同,使用的是sdkExecute
            //返回支付宝订单信息(预处理)
            AlipayTradeAppPayResponse alipayTradeAppPayResponse = alipayClient.sdkExecute(ali_request);
            //就是orderString 可以直接给APP请求,无需再做处理。
            String alipayTransferId = alipayTradeAppPayResponse.getBody();
            log.info("需要返回给支付宝的数据 alipayTransferId:" + alipayTransferId);
            return alipayTransferId;
        }catch (AlipayApiException e){
            e.printStackTrace();
        }
        return null;
    }


    public String alipayNotify(HttpServletRequest request) {
        log.info("支付宝异步返回支付结果开始");

        //1.从支付宝回调的request域中取值
        //获取支付宝返回的参数集合
        Map<String, String[]> aliParams = request.getParameterMap();

        log.info("支付宝Post过来的反馈信息:" + aliParams.toString());

        //用以存放转化后的参数集合
        Map<String, String> conversionParams = new HashMap<String, String>();
        for (Iterator<String> iter = aliParams.keySet().iterator(); iter.hasNext();) {
            String key = iter.next();
            String[] values = aliParams.get(key);
            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"), "UTF-8");
            conversionParams.put(key, valueStr);
        }

        log.info("支付宝返回参数集合:"+conversionParams);
        String status=aliPayCheck(conversionParams);
        return status;
    }

    public String aliPayCheck(Map conversionParams){
        log.info("=支付宝异步请求逻辑处理=");
        //签名验证(对支付宝返回的数据验证,确定是支付宝返回的)
        boolean signVerified = false;
        try {
            //调用SDK验证签名
            String alipayPublicKey = AliDevPayConfig.aliPayPublicKey;
            String charset = AliDevPayConfig.CHARSET;
            String signType = AliDevPayConfig.SIGN_TYPE;

            signVerified = AlipaySignature.rsaCheckV1(conversionParams, alipayPublicKey, charset, signType);
            //对验签进行处理.
            if (signVerified) {
                log.info("+++++++++++支付宝回调签名认证成功+++++++++++");
                // 按照支付结果异步通知中的描述,对支付结果中的业务内容进行1\2\3\4二次校验,校验成功后在response中返回success,校验失败返回failure 支付宝官方建议校验的值(out_trade_no、total_amount、sellerId、app_id)
                //验签通过 获取交易状态
                String tradeStatus = (String)conversionParams.get("trade_status");

                //只处理支付成功的订单: 修改交易表状态,支付成功
                //只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功。
                if (tradeStatus.equals("TRADE_SUCCESS") ||tradeStatus.equals("TRADE_FINISHED")) {
                    //TODO 获取支付宝通知完成充值后续业务

                    //交易成功 获取商户账单id
                    String billId = (String) conversionParams.get("out_trade_no");
                    //支付宝交易流水号
                    String ali_pay_no = (String) conversionParams.get("trade_no");
                    

                    //TODO 修改业务订单信息
                    //TODO 余额到账,消息推送

                    return "success";
                } else {
                    return "fail";
                }
            }else{  //验签不通过
                log.info("++验签不通过 !++");
                return "fail";
            }
        } catch (AlipayApiException e) {
            log.info("+++验签失败 !+++");
            e.printStackTrace();
        }
        return "fail";
    }

}

以上saveAliPayRechangeBill方法返回的类型如下

app_id=2015052600090779&biz_content=%7B%22timeout_express%22%3A%2230m%22%2C%22seller_id%22%3A%22%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%2C%22total_amount%22%3A%220.01%22%2C%22subject%22%3A%221%22%2C%22body%22%3A%22%E6%88%91%E6%98%AF%E6%B5%8B%E8%AF%95%E6%95%B0%E6%8D%AE%22%2C%22out_trade_no%22%3A%22IQJZSRC1YMQB5HU%22%7D&charset=utf-8&format=json&method=alipay.trade.app.pay&notify_url=http%3A%2F%2Fdomain.merchant.com%2Fpayment_notify&sign_type=RSA2&timestamp=2016-08-25%2020%3A26%3A31&version=1.0&sign=cYmuUnKi5QdBsoZEAbMXVMmRWjsuUj%2By48A2DvWAVVBuYkiBj13CFDHu2vZQvmOfkjE0YqCUQE04kqm9Xg3tIX8tPeIGIFtsIyp%2FM45w1ZsDOiduBbduGfRo1XRsvAyVAv2hCrBLLrDI5Vi7uZZ77Lo5J0PpUUWwyQGt0M4cj8g%3D

以上结果等价于如下,但上面才是正常的返回结果。

body="test"&_input_charset="UTF-8"&it_b_pay="1d"&total_fee="1"&subject="test"&notify_url="http://www.bejson.com/api/alipay/testpayotify.php"&service="mobile.securitypay.pay"&seller_id="cw@bejson.com"&partner="2088301"&out_trade_no="2088301971894011"&payment_type="1"&show_url="http://www.dcloud.io/helloh5/"&sign="RtUKAGMfelb5sl2az4YKhxst051l94FSkpk9xoD91Hbpr2PKnWjHIafTWqNLyxGibde%2BKwcq9Y8cDN0qU%2FsO6hXjch0B4GaMJHBxZQM%2FnJK2YGxPPOWFKKL5rBKVJ%2BrX4OImfSQIyKKUpAEFG6uFfek2hh%2FPFJSXk2Phvmrb8U%3D"&sign_type="RSA"

调用时,请核对所有支付宝所必要的参数,参考支付宝参数

至此就已经差不多完成支付宝的接入了,如果有其他问题可以百度或者留言,如果有什么错误,欢迎多多指正批评。:)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容