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

网友投稿 1235 2022-05-29

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

接口参数参考地址:https://doc.open.alipay.com/docs ... Id=105465&docType=1

直接上代码:

/**          * 调用支付宝的SDK,封装发送给支付宝服务器的数据参数。 
         * 返回数据供APICloud支付方式一调用。 
         * 调用签名方法进行数据签名,步骤如下:          * 

             * 
  1. 参考接口参数文档,对于sign之外的数据,进行封装,存入到map中
  2.          * 
  3. 调用AlipaySignature.rsaSign方法,进行数据签名。方法内部会自动完成排序。
  4.          * 
  5. 将得到的sign内容,赋值给sign。加入到map中。          * 
  6.          * 
  7. 将所有的参数数据,进行URLEncoder编码。
  8.          * 
  9. 最后调用SDK方法,将map转换成排序后的字符串,返回给客户端
  10.          * 
         * 

         * 注意:坑比较多,文档中也有错误,不需要Base64的编码。          * 

         *           * @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 infoMap = new HashMap();                 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 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中的方法调用了。

另外,如果电商订单,关于订单的后处理,要在回调接口方法中完成,如下示例:

/**          * 支付宝支付完成之后,返回数据到客户服务端。          * 

         * 程序执行完后必须打印输出“success”(不包含引号)。如果商户反馈给支付宝的字符不是success这7个字符,支付宝服务器会不断重发通知,直到超过24小时22分钟。一般情况下,25          * 小时以内完成8次通知(通知的间隔频率一般是:4m,10m,10m,1h,2h,6h,15h);          * 

         *           * @param request          * @param response          * @author JiangZhongyan          * @throws IOException          */         @RequestMapping(value = "/alipay-finish-notify")         @SystemControllerLog         public void alipayNotify(HttpServletRequest request, HttpServletResponse response)                         throws IOException         {        Map 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一侧执行。

以上是服务器端的代码,因为代码不全,仅供讲解过程,具体逻辑代码,根据实际情况调整。拼装的数据,示例如下:

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

【支付宝支付请求参数】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=, 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次

Java 订单

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:手把手教你opencv做人脸识别(附源码+文档)
下一篇:《敏捷软件开发:用户故事实战》—为什么要改变?
相关文章