【JAVA版】支付宝支付方案一详解

举报
星汉网络 发表于 2019/04/18 14:37:07 2019/04/18
【摘要】 在使用“aliPayPlus”模块进行接入支付宝支付过程中,如果采用方案一(推荐)进行支付时,重要组装orderInfo字段数据。APICloud的文档中,没有提及太多,示例代码中的数据也有一定的问题。参考蚂蚁金服接口参数文档,终于接入成功。后台采用Java代码书写,特将信息整理出来,避免新接入的朋友,重新趟雷。接口参数参考地址:https://doc.open.alipay.com/doc...

在使用“aliPayPlus”模块进行接入支付宝支付过程中,如果采用方案一(推荐)进行支付时,重要组装orderInfo字段数据。APICloud的文档中,没有提及太多,示例代码中的数据也有一定的问题。参考蚂蚁金服接口参数文档,终于接入成功。后台采用Java代码书写,特将信息整理出来,避免新接入的朋友,重新趟雷。
接口参数参考地址:https://doc.open.alipay.com/docs ... Id=105465&docType=1

直接上代码:

/**
         * 调用支付宝的SDK,封装发送给支付宝服务器的数据参数。 <br>
         * 返回数据供APICloud支付方式一调用。 <br>
         * 调用签名方法进行数据签名,步骤如下:
         * <ol>
         * <li>参考接口参数文档,对于sign之外的数据,进行封装,存入到map中</li>
         * <li>调用AlipaySignature.rsaSign方法,进行数据签名。方法内部会自动完成排序。</li>
         * <li>将得到的sign内容,赋值给sign。加入到map中。
         * <li>
         * <li>将所有的参数数据,进行URLEncoder编码。</li>
         * <li>最后调用SDK方法,将map转换成排序后的字符串,返回给客户端</li>
         * </ol>
         * <p>
         * 注意:坑比较多,文档中也有错误,不需要Base64的编码。
         * </p>
         * 
         * @param request
         * @param response
         * @return
         * @author
         * @throws AlipayApiException
         * @throws FrameworkException
         * @throws UnsupportedEncodingException
         * @see 蚂蚁金服接口参数文档
         */
        @ResponseBody
        @RequestMapping(value = "alipay-order-info")
        public String getPayOrderInfo(HttpServletRequest request, HttpServletResponse response)
                        throws AlipayApiException, FrameworkException, UnsupportedEncodingException
        {
                // 从客户端传递得到订单数据
                String tradeId = request.getParameter("out_trade_no");
                String amount = request.getParameter("total_amount");
                String notifyUrl = request.getParameter("notify_url");

                // 组装发送给支付宝服务器的数据串
                AlipayBizContent bizContent = new AlipayBizContent();
                bizContent.setOut_trade_no(tradeId);
                bizContent.setProduct_code(AlipayHelper.PRODUCT_CODE);
                bizContent.setSeller_id(prop.getAliSellerId());
                bizContent.setSubject(AlipayHelper.SUBJECT);
                bizContent.setTotal_amount(amount);

                Map<String, String> infoMap = new HashMap<String, String>();
                infoMap.put("app_id", prop.getAliAppId());
                infoMap.put("biz_content", JsonUtils.fromObject(bizContent));
                infoMap.put("charset", AlipayHelper.CHARSET);
                infoMap.put("method", AlipayHelper.METHOD);
                infoMap.put("notify_url", notifyUrl);
                infoMap.put("sign_type", AlipayHelper.SIGN_TYPE);
                infoMap.put("timestamp", DateTimeUtils.getNowTimeStanderd());
                infoMap.put("version", AlipayHelper.VERSION);

                // 对于数据进行签名操作
                String sign = AlipaySignature
                                .rsaSign(infoMap, prop.getAliRsaPriKey(), AlipayHelper.CHARSET);
                infoMap.put("sign", sign);

                // 将参数内容进行URL格式编码
                for (Map.Entry<String, String> entry : infoMap.entrySet())
                {
                        entry.setValue(URLEncoder.encode(entry.getValue(), AlipayHelper.CHARSET));
                }

                // 将Map数据按照规则排列转换成字符串,发送给支付宝服务端
                String orderInfo = AlipaySignature.getSignContent(infoMap);
                logger.info("【支付宝支付请求参数】" + orderInfo);

                JSONObject json = new JSONObject();
                json.put("orderInfo", orderInfo);

                return JsonUtils.fromObject(json);
        }

其中, AlipayBizContent 的类代码如下,参考接口文档

public class AlipayBizContent
{
        /**
         * 对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。
         */
        private String body;

        /**
         * 商品的标题/交易标题/订单标题/订单关键字等。
         */
        private String subject;

        /**
         * 商户网站唯一订单号
         */
        private String out_trade_no;

        /**
         * 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]
         */
        private String total_amount;

        /**
         * 收款支付宝用户ID。 如果该值为空,则默认为商户签约账号对应的支付宝用户ID
         */
        private String seller_id;

        /**
         * 销售产品码,商家和支付宝签约的产品码,为固定值QUICK_MSECURITY_PAY
         */
        private String product_code;

注意代码中的签名、编码和排序。要使用支付宝提供的接口jar方法实现。
这样,通过getPayOrderInfo方法得到的字符串数据,就可以供API中的方法调用了。
另外,如果电商订单,关于订单的后处理,要在回调接口方法中完成,如下示例:

/**
         * 支付宝支付完成之后,返回数据到客户服务端。
         * <p>
         * 程序执行完后必须打印输出“success”(不包含引号)。如果商户反馈给支付宝的字符不是success这7个字符,支付宝服务器会不断重发通知,直到超过24小时22分钟。一般情况下,25
         * 小时以内完成8次通知(通知的间隔频率一般是:4m,10m,10m,1h,2h,6h,15h);
         * </p>
         * 
         * @param request
         * @param response
         * @author JiangZhongyan
         * @throws IOException
         */
        @RequestMapping(value = "/alipay-finish-notify")
        @SystemControllerLog
        public void alipayNotify(HttpServletRequest request, HttpServletResponse response)
                        throws IOException
        {
       Map<String, String> reqMap = getParamMap(request.getParameterMap());
       // 校验支付返回数据状态&&变更订单状态
       if (alipayService.isPaySuccess(reqMap)
           && payService.dealOrder(reqMap.get("out_trade_no"), ConstantHelper.ORDER_PAY_ALI))
      {
               logger.info("【支付宝回调成功】-返回success");
               response.getOutputStream().write("success".getBytes());
      }
      else
     {
               response.getOutputStream().write("fail".getBytes());
     }
        }

在notify_url中,去完成你想要在支付成功之后做的事情。尽量不要在JS一侧执行。
以上是服务器端的代码,因为代码不全,仅供讲解过程,具体逻辑代码,根据实际情况调整。拼装的数据,示例如下:

【支付宝支付请求参数】app_id=<自己的ID号>&biz_content=%7B%22body%22%3A%22%22%2C%22out_trade_no%22%3A%2220170829093417364%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%2C%22seller_id%22%3A%222088221616699040%22%2C%22subject%22%3A%22%E6%98%9F%E6%B1%89%E6%9E%9C%E5%9B%AD%22%2C%22total_amount%22%3A%220.01%22%7D&charset=utf-8&method=alipay.trade.app.pay¬ify_url=http%3A%2F%2Fxinghansoft.com%2Ffruitshop%2Fapp%2Falipay-finish-notify.action&sign=<用私钥加密的签名数据>&sign_type=RSA×tamp=2017-08-29+09%3A34%3A21&version=1.0

从支付宝一侧返回的数据,示例如下:

【支付宝支付回调参数】{subject=<应用名称>, sign_type=RSA, buyer_logon_id=144***@qq.com, auth_app_id=<ID号>, notify_type=trade_status_sync, out_trade_no=20170829093417364, point_amount=0.00, version=1.0, fund_bill_list=[{"amount":"0.01","fundChannel":"ALIPAYACCOUNT"}], buyer_id=2088212389597532, total_amount=0.01, trade_no=2017082921001004530224695960, notify_time=2017-08-29 09:34:33, charset=utf-8, invoice_amount=0.01, trade_status=TRADE_SUCCESS, gmt_payment=2017-08-29 09:34:33, sign=<签名字符串>, gmt_create=2017-08-29 09:34:32, buyer_pay_amount=0.01, receipt_amount=0.01, app_id=2016050401362525, seller_id=<商户ID号>, notify_id=47a0e3508c7296c4f079a04043d2163k3a, seller_email=<商户邮箱>}

在APP一侧的JS代码如下:

/**
                 * 阿里支付宝支付
                 * 支付宝支付的金额单位为元
                 * @param  tradeNo 商户系统内部的订单号
                 * @param price 订单总金额,只能为整数,单位:分(¥)
                 */
                function execAlipay(tradeNo, price) {
                        var data = {
                                out_trade_no : tradeNo,
                                total_amount : price,
                                notify_url : extApi.MainUrl + 'app/alipay-finish-notify.action'
                        };
                        ajax.post('app/alipay-order-info.action', data, function(ret) {
                                var aliPayPlus = api.require('aliPayPlus');
                                aliPayPlus.payOrder({
                                        orderInfo : ret.orderInfo
                                }, function(ret, err) {
                                        if (ret.code == '9000') {
                                                closePayWin();
                                        }else{
                                           extApi.alert(getAliRetCodeMsg(ret.code), '支付结果');
                                        }
                                });
                        });
                }

                /**
                 * 阿里支付返回的错误码,取值范围如下:
                 * 9000:支付成功
                 * 8000:正在处理中,支付结果未知(有可能已经支付成功),请查询商户订单列表中订单的支付状态
                 * 4000:订单支付失败
                 * 5000:重复请求
                 * 6001:用户中途取消支付操作
                 * 6002:网络连接出错
                 * 6004:支付结果未知(有可能已经支付成功),请查询商户订单列表中订单的支付状态
                 */
                function getAliRetCodeMsg(code) {
                        switch(code) {
                                case '9000':
                                        return '支付成功';
                                case '8000':
                                        return '正在处理中';
                                case '4000':
                                        return '订单支付失败';
                                case '5000':
                                        return '重复请求';
                                case '6001':
                                        return '用户中途取消支付操作';
                                case '6002':
                                        return '网络连接出错';
                                case '6004':
                                        return '未知错误';
                                default:
                                        return '未知错误';
                        }
                }

到此,如果您账号正确,基本上就可以测试联通了。希望能够对你有帮助。
附件中,携带了两个Java文件,供参考。

    附件下载

  • aliPay.zip 5.29KB 下载次数:0
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。