上一章已经讲述了支付宝如何生成支付订单,这一章讲述一下支付宝生成订单之后,异步通知接口的开发。

这里先讲一下啥叫支付宝异步通知:对于App支付产生的交易,支付宝会根据原始支付API中传入的异步通知地址notify_url,通过POST请求的形式将支付结果作为参数通知到商户系统。

通知参数详细见官方API:https://docs.open.alipay.com/204/105301/

1、异步通知参数说明

异步通知参数

参数

参数名称

类型

必填

描述

范例

notify_time

通知时间

Date

通知的发送时间。格式为yyyy-MM-dd HH:mm:ss

2015-14-27 15:45:58

notify_type

通知类型

String(64)

通知的类型

trade_status_sync

notify_id

通知校验ID

String(128)

通知校验ID

ac05099524730693a8b330c5ecf72da9786

app_id

支付宝分配给开发者的应用Id

String(32)

支付宝分配给开发者的应用Id

2014072300007148

charset

编码格式

String(10)

编码格式,如utf-8、gbk、gb2312等

utf-8

version

接口版本

String(3)

调用的接口版本,固定为:1.0

1.0

sign_type

签名类型

String(10)

商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2

RSA2

sign

签名

String(256)

请参考异步返回结果的验签

601510b7970e52cc63db0f44997cf70e

trade_no

支付宝交易号

String(64)

支付宝交易凭证号

2013112011001004330000121536

out_trade_no

商户订单号

String(64)

原支付请求的商户订单号

6823789339978248

out_biz_no

商户业务号

String(64)

商户业务ID,主要是退款通知中返回退款申请的流水号

HZRF001

buyer_id

买家支付宝用户号

String(16)

买家支付宝账号对应的支付宝唯一用户号。以2088开头的纯16位数字

2088102122524333

buyer_logon_id

买家支付宝账号

String(100)

买家支付宝账号

15901825620

seller_id

卖家支付宝用户号

String(30)

卖家支付宝用户号

2088101106499364

seller_email

卖家支付宝账号

String(100)

卖家支付宝账号

zhuzhanghu@alitest.com

trade_status

交易状态

String(32)

交易目前所处的状态,见交易状态说明

TRADE_CLOSED

total_amount

订单金额

Number(9,2)

本次交易支付的订单金额,单位为人民币(元)

20

receipt_amount

实收金额

Number(9,2)

商家在交易中实际收到的款项,单位为元

15

invoice_amount

开票金额

Number(9,2)

用户在交易中支付的可开发票的金额

10.00

buyer_pay_amount

付款金额

Number(9,2)

用户在交易中支付的金额

13.88

point_amount

集分宝金额

Number(9,2)

使用集分宝支付的金额

12.00

refund_fee

总退款金额

Number(9,2)

退款通知中,返回总退款金额,单位为元,支持两位小数

2.58

subject

订单标题

String(256)

商品的标题/交易标题/订单标题/订单关键字等,是请求时对应的参数,原样通知回来

当面付交易

body

商品描述

String(400)

该订单的备注、描述、明细等。对应请求时的body参数,原样通知回来

当面付交易内容

gmt_create

交易创建时间

Date

该笔交易创建的时间。格式为yyyy-MM-dd HH:mm:ss

2015-04-27 15:45:57

gmt_payment

交易付款时间

Date

该笔交易的买家付款时间。格式为yyyy-MM-dd HH:mm:ss

2015-04-27 15:45:57

gmt_refund

交易退款时间

Date

该笔交易的退款时间。格式为yyyy-MM-dd HH:mm:ss.S

2015-04-28 15:45:57.320

gmt_close

交易结束时间

Date

该笔交易结束时间。格式为yyyy-MM-dd HH:mm:ss

2015-04-29 15:45:57

fund_bill_list

支付金额信息

String(512)

支付成功的各个渠道金额信息,详见资金明细信息说明

[{“amount”:“15.00”,“fundChannel”:“ALIPAYACCOUNT”}]

passback_params

回传参数

String(512)

公共回传参数,如果请求时传递了该参数,则返回给商户时会在异步通知时将该参数原样返回。本参数必须进行UrlEncode之后才可以发送给支付宝

merchantBizType%3d3C%26merchantBizNo%3d2016010101111

voucher_detail_list

优惠券信息

String

本交易支付时所使用的所有优惠券信息,详见优惠券信息说明

[{“amount”:“0.20”,“merchantContribute”:“0.00”,“name”:“一键创建券模板的券名称”,“otherContribute”:“0.20”,“type”:“ALIPAY_DISCOUNT_VOUCHER”,“memo”:“学生卡8折优惠”]

交易状态说明 

枚举名称 枚举说明
WAIT_BUYER_PAY 交易创建,等待买家付款
TRADE_CLOSED 未付款交易超时关闭,或支付完成后全额退款
TRADE_SUCCESS 交易支付成功
TRADE_FINISHED 交易结束,不可退款

通知触发条件

触发条件名 触发条件描述 触发条件默认值
TRADE_FINISHED 交易完成 true(触发通知)
TRADE_SUCCESS 支付成功 true(触发通知)
WAIT_BUYER_PAY 交易创建 false(不触发通知)
TRADE_CLOSED 交易关闭 true(触发通知)

其它参数我就不一一列出了,详细见官方API。

2、服务器异步通知页面特性

必须保证服务器异步通知页面(notify_url)上无任何字符,如空格、HTML标签、开发系统自带抛出的异常提示信息等;
支付宝是用POST方式发送通知信息,因此该页面中获取参数的方式,如:request.Form(“out_trade_no”)、$_POST[‘out_trade_no’];
支付宝主动发起通知,该方式才会被启用;
只有在支付宝的交易管理中存在该笔交易,且发生了交易状态的改变,支付宝才会通过该方式发起服务器通知(即时到账交易状态为“等待买家付款”的状态默认是不会发送通知的);
服务器间的交互,不像页面跳转同步通知可以在页面上显示出来,这种交互方式是不可见的;
第一次交易状态改变(即时到账中此时交易状态是交易完成)时,不仅会返回同步处理结果,而且服务器异步通知页面也会收到支付宝发来的处理结果通知;
程序执行完后必须打印输出“success”(不包含引号)。如果商户反馈给支付宝的字符不是success这7个字符,支付宝服务器会不断重发通知,直到超过24小时22分钟。一般情况下,25小时以内完成8次通知(通知的间隔频率一般是:4m,10m,10m,1h,2h,6h,15h);
程序执行完成后,该页面不能执行页面跳转。如果执行页面跳转,支付宝会收不到success字符,会被支付宝服务器判定为该页面程序运行出现异常,而重发处理结果通知;
cookies、session等在此页面会失效,即无法获取这些数据;
该方式的调试与运行必须在服务器上,即互联网上能访问;
该方式的作用主要防止订单丢失,即页面跳转同步通知没有处理订单更新,它则去处理;
当商户收到服务器异步通知并打印出success时,服务器异步通知参数notify_id才会失效。也就是说在支付宝发送同一条异步通知时(包含商户并未成功打印出success导致支付宝重发数次通知),服务器异步通知参数notify_id是不变的。

3、异步返回结果的验签

为了帮助开发者调用开放接口,我们提供了开放平台服务端DEMO&SDK,包含JAVA、PHP和.NET三语言版本,封装了签名&验签、HTTP接口请求等基础功能。强烈建议先下载对应语言版本的SDK并引入您的开发工程进行快速接入。

某商户设置的通知地址为https://api.xx.com/receive_notify.htm,对应接收到通知的示例如下:
注:以下示例报文仅供参考,实际返回的详细报文请以实际返回为准。

https://api.xx.com/receive_notify.htm?total_amount=2.00&buyer_id=2088102116773037&body=大乐透2.1&trade_no=2016071921001003030200089909&refund_fee=0.00&notify_time=2016-07-19 14:10:49&subject=大乐透2.1&sign_type=RSA2&charset=utf-8&notify_type=trade_status_sync&out_trade_no=0719141034-6418&gmt_close=2016-07-19 14:10:46&gmt_payment=2016-07-19 14:10:47&trade_status=TRADE_SUCCESS&version=1.0&sign=kPbQIjX+xQc8F0/A6/AocELIjhhZnGbcBN6G4MM/HmfWL4ZiHM6fWl5NQhzXJusaklZ1LFuMo+lHQUELAYeugH8LYFvxnNajOvZhuxNFbN2LhF0l/KL8ANtj8oyPM4NN7Qft2kWJTDJUpQOzCzNnV9hDxh5AaT9FPqRS6ZKxnzM=&gmt_create=2016-07-19 14:10:44&app_id=2015102700040153&seller_id=2088102119685838&notify_id=4a91b7a78a503640467525113fb7d8bg8e

第一步: 在通知返回参数列表中,除去sign、sign_type两个参数外,凡是通知返回回来的参数皆是待验签的参数。

第二步: 将剩下参数进行url_decode, 然后进行字典排序,组成字符串,得到待签名字符串:

app_id=2015102700040153&body=大乐透2.1&buyer_id=2088102116773037&charset=utf-8&gmt_close=2016-07-19 14:10:46&gmt_payment=2016-07-19 14:10:47&notify_id=4a91b7a78a503640467525113fb7d8bg8e&notify_time=2016-07-19 14:10:49&notify_type=trade_status_sync&out_trade_no=0719141034-6418&refund_fee=0.00&seller_id=2088102119685838&subject=大乐透2.1&total_amount=2.00&trade_no=2016071921001003030200089909&trade_status=TRADE_SUCCESS&version=1.0

第三步: 将签名参数(sign)使用base64解码为字节码串。

第四步: 使用RSA的验签方法,通过签名字符串、签名参数(经过base64解码)及支付宝公钥验证签名。

第五步:在步骤四验证签名正确后,必须再严格按照如下描述校验通知数据的正确性。

1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email),4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。在上述验证通过后商户必须根据支付宝不同类型的业务通知,正确的进行不同的业务处理,并且过滤重复的通知结果数据。在支付宝的业务通知中,只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功。

验签过程代码描述【这里列举java示例,按照服务端SDK中提供的工具类】:

Map<String, String> paramsMap = ... //将异步通知中收到的待验证所有参数都存放到map中
boolean signVerified = AlipaySignature.rsaCheckV1(paramsMap, ALIPAY_PUBLIC_KEY, CHARSET) //调用SDK验证签名
if(signVerfied){// TODO 验签成功后//按照支付结果异步通知中的描述,对支付结果中的业务内容进行1\2\3\4二次校验,校验成功后在response中返回success,校验失败返回failure
}else{// TODO 验签失败则记录异常日志,并在response中返回failure.
}

注意:

  • 状态TRADE_SUCCESS的通知触发条件是商户签约的产品支持退款功能的前提下,买家付款成功;
  • 交易状态TRADE_FINISHED的通知触发条件是商户签约的产品不支持退款功能的前提下,买家付款成功;或者,商户签约的产品支持退款功能的前提下,交易已经成功并且已经超过可退款期限。

4、代码实现

4.1基础类

AlipayConfig配置类,主要包含支付宝的配置信息

package com.hisap.xql.api.common.ali;/*** @Author: QijieLiu* @Description: 支付宝配置信息* @Date: Created in 10:39 2018/8/20*/
public class AlipayConfig {public static String APP_ID = "xxxxxx";public static String APP_PRIVATE_KEY = "xxxxxx";//APP私钥public static String APP_PUBLIC_KEY = "xxxxxx";//APP公钥public static String ALIPAY_PUBLIC_KEY = "xxxxxx";//支付宝公钥public static String UNIFIEDORDER_URL = "https://openapi.alipay.com/gateway.do";public static String NOTIFY_URL = "http://xxx.xxx.xxx.xxx/XqlApi/xxx/paynotify";public static String CHARSET = "UTF-8";public static String FORMAT = "json";public static String SIGNTYPE = "RSA2";public static String TIMEOUT_EXPRESS = "30m";
}

4.2业务类

AliPayController类

package com.hisap.xql.api.controller;import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alipay.api.internal.util.AlipaySignature;
import com.hisap.xql.api.common.ali.AlipayConfig;
import com.hisap.xql.api.common.bean.ResponseJson;
import com.hisap.xql.api.common.constant.CodeMsg;
import com.hisap.xql.api.common.utils.CommonUtil;
import com.hisap.xql.api.service.AliPayService;/*** @Author: QijieLiu* @Description: 支付宝支付信息* @Date: Created in 10:39 2018/8/20*/
@Controller
@RequestMapping("/xxx")
public class AliPayController {private static final Logger logger = LoggerFactory.getLogger(AliPayController.class);@Autowiredprivate AliPayService aliPayService;@RequestMapping("/xxx")@ResponseBodypublic String paynotify(HttpServletRequest request,HttpServletResponse response) throws Exception {
//      String requestJson = IOUtils.toString(request.getInputStream(), "utf-8");
//      logger.info("支付宝支付结果通知接口请求数据json:" + requestJson);try {java.util.Enumeration enu=request.getParameterNames();  while(enu.hasMoreElements()){  String paraName=(String)enu.nextElement();  System.out.println(paraName+": "+request.getParameter(paraName));  }} catch (Exception e4) {e4.printStackTrace();return "fail";}//获取支付宝POST过来反馈信息Map<String,String> receiveMap = getReceiveMap(request);logger.info("支付宝支付回调参数:" + receiveMap);boolean signVerified = false;try{signVerified = aliPayService.paynotify(receiveMap);logger.info("支付宝支付结果通知接口响应数据json:" + signVerified);}catch(Exception e){e.printStackTrace();logger.error("支付宝支付结果通知接口服务端异常,异常信息---" + e.getMessage(), e);return "fail";}if(signVerified){return "success";}else{return "fail";}}/***<p>方法说明: TODO 获取请求参数*<p>返回说明: Map<String,String> receiveMap*<p>创建时间: 2018年8月20日 下午3:05:02*<p>创  建  人: QijieLiu**/private static Map<String,String> getReceiveMap(HttpServletRequest request){Map<String,String> params = new HashMap<String,String>();Map requestParams = request.getParameterMap();for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {String name = (String) iter.next();String[] values = (String[]) requestParams.get(name);String valueStr = "";for (int i = 0; i < values.length; i++) {valueStr = (i == values.length - 1) ? valueStr + values[i]: valueStr + values[i] + ",";}//乱码解决,这段代码在出现乱码时使用。//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");params.put(name, valueStr);}return params;}
}

AliPayService接口类

package com.hisap.xql.api.service;import java.math.BigDecimal;
import java.util.Map;import com.hisap.xql.api.common.bean.ResponseJson;/*** @Author: QijieLiu* @Description: 支付宝支付* @Date: Created in 11:29 2018/8/20*/
public interface AliPayService {boolean paynotify(Map<String,String> receiveMap) throws Exception;
}

AliPayServiceImpl接口实现类

package com.hisap.xql.api.service.impl;import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.hisap.xql.api.common.ali.AlipayConfig;
import com.hisap.xql.api.common.ali.AlipayRefund;
import com.hisap.xql.api.common.bean.ResponseJson;
import com.hisap.xql.api.common.constant.CodeMsg;
import com.hisap.xql.api.common.utils.Collections3;
import com.hisap.xql.api.common.utils.CommonUtil;
import com.hisap.xql.api.common.utils.StringUtil;
import com.hisap.xql.api.common.utils.VersionUtil;
import com.hisap.xql.api.dao.XqlOrderGoodsMapper;
import com.hisap.xql.api.model.XqlOrder;
import com.hisap.xql.api.model.XqlOrderGoods;
import com.hisap.xql.api.model.XqlOrderGoodsExample;
import com.hisap.xql.api.model.XqlVersion;
import com.hisap.xql.api.service.AliPayService;
import com.hisap.xql.api.service.CommonService;
import com.hisap.xql.api.service.ErpInterfaceService;
import com.hisap.xql.api.service.WeChatPayService;
import com.hisap.xql.api.service.XqlOrderService;@Service
public class AliPayServiceImpl implements AliPayService {private static final Logger logger = LoggerFactory.getLogger(AliPayServiceImpl.class);@AutowiredCommonService commonService;@AutowiredXqlOrderService xqlOrderServiceImpl;@AutowiredXqlOrderGoodsMapper xqlOrderGoodsMapper;@AutowiredWeChatPayService weChatPayServiceImpl;@AutowiredErpInterfaceService erpInterfaceServiceImpl;@Overridepublic boolean paynotify(Map<String, String> receiveMap) throws Exception {boolean signVerified = false;signVerified = AlipaySignature.rsaCheckV1(receiveMap,AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET,AlipayConfig.SIGNTYPE);if (signVerified) {String tradeStatus = receiveMap.get("trade_status");if ("TRADE_FINISHED".equals(tradeStatus)|| "TRADE_SUCCESS".equals(tradeStatus)) {String orderNoStr = receiveMap.get("out_trade_no").toString();BigDecimal orderNo = new BigDecimal(orderNoStr);XqlOrder xqlOrder = xqlOrderServiceImpl.selectXqlOrderByOrderNo(orderNo);// 订单不存在if (xqlOrder == null) {logger.info("订单号" + orderNoStr + "不存在");return false;}// 订单已经支付if (xqlOrder.getOrderStatus() != 101&& xqlOrder.getPayStatus() == 1) {logger.info("订单号" + orderNoStr + "已经支付");return true;}// 判断电商订单还是门店订单Short deliveryType = xqlOrder.getDeliveryType();String trade_no = xqlOrder.getPayNo();Long orderAmountL = xqlOrder.getOrderAmount();BigDecimal orderAmountB = new BigDecimal(orderAmountL);BigDecimal d100 = new BigDecimal(100); BigDecimal orderAmount = orderAmountB.divide(d100, 2, 2);// 根据单据类型进行补单,成功则更新单据支付信息,失败则进行退款ResponseJson responseJson = weChatPayServiceImpl.fullorder(deliveryType, orderNo);if (responseJson.getCode().equalsIgnoreCase(CodeMsg.SUCCESS_CODE)) {XqlOrder xqlOrder1 = new XqlOrder();xqlOrder1.setOrderNo(orderNo);if(xqlOrder.getDeliveryType() == 0){xqlOrder1.setOrderStatus(302);xqlOrder1.setSelfDeliveryStatus((short) 0);}else{xqlOrder1.setOrderStatus(201);}xqlOrder1.setPayStatus((short) 1);xqlOrder1.setPayType((short) 1);xqlOrder1.setPayAccount(receiveMap.get("trade_no"));xqlOrder1.setPayNo(receiveMap.get("trade_no"));xqlOrder1.setPaidAmount(Math.round(Double.parseDouble(receiveMap.get("total_amount").toString()) * 100));xqlOrder1.setPayTime(new Date());int returnResult = xqlOrderServiceImpl.updateXqlOrderByOrderNo(xqlOrder1);if (returnResult > 0) {return true;} else {logger.info("订单号" + orderNoStr + "更新支付信息失败");return false;}} else {// 退单refund(trade_no, orderAmount);}}}return signVerified;}
}

在异步返回结果的验签过程中,一开始死活验签不通过,查阅了大量资料,发现AlipaySignature.rsaCheckV1(paramsMap, ALIPAY_PUBLIC_KEY, CHARSET)方法中,ALIPAY_PUBLIC_KEY参数为支付宝公钥,并不是APP的公钥。

切记alipaypublickey是支付宝的公钥,请去open.alipay.com对应应用下查看。

这里我截取了我的支付宝沙箱环境图片,供大家参考:

好了,这一章支付宝验证异步通知消息就已经完成了,下一章讲述支付宝申请退款接口开发。

Java支付宝APP支付-验证异步通知消息相关推荐

  1. PHP支付宝支付事务,php实现支付宝app支付和异步通知的代码实例

    本篇文章给大家分享的内容是关于php实现支付宝app支付和异步通知的代码实例,内容很详细,有需要的朋友可以参考一下,希望可以帮助到你们. 之前写过支付宝app支付的支付的后台代码,现在来说一下异步通知 ...

  2. android 支付宝 40247,支付宝 app支付异常摘记 -- ALI40247

    一. 支付 1. 系统繁忙,请稍后重试.(ALI40247): 签名错误. 我的问题来源(两个问题): ① 签名串sign=签名串,这个签名串是不带双引号的,我不小心两头有双引号: ② 签名流程是: ...

  3. java 支付宝服务端,支付宝app支付服务端的实现-Java版

    前言 最近在工作中需要使用支付宝app支付,在初次使用过程中也不可避免的出现了一些问题,那么本次随笔主要是概述支付宝app支付服务端的整个实现过程以及就服务端出现的一些问题做一些总结. 1.准备工作 ...

  4. 支付宝app支付java后台流程、原理分析(含nei wang chuan tou)

    java版支付宝app支付流程及原理分析 本实例是基于springmvc框架编写      一.流程步骤          1.执行流程            当手机端app(就是你公司开发的app) ...

  5. java后端实现集成支付宝APP支付(沙箱环境)

    沙箱环境集成支付宝APP支付后端实现 前言 获取支付宝相关信息 整体开发流程 1.获取核心参数 2.将支付宝SDK集成到项目中 3.后台使用支付宝SDK与支付宝进行交互逻辑 1.将支付宝公共信息参数写 ...

  6. 支付宝APP支付Java服务端

    支付宝APP支付Java服务端: 公司项目要求对接支付宝进行支付功能,这边做出整理方便以后使用(支付宝的支付对接还是很简单的). 1):去支付宝开放平台,-1.注册账号,2.创建应用 3.配置应用 4 ...

  7. 支付宝APP支付(java后台版)

    本实例是基于springBoot框架编写 一.流程步骤          1.执行流程            当手机端app在支付页面时,调起服务端创建订单(自己公司业务接口)接口,后台把需要调起支付 ...

  8. java SpringBoot 对接支付宝 APP支付 证书模式及非证书模式

    一. 添加maven依赖 sdk <dependency><groupId>com.alipay.sdk</groupId><artifactId>al ...

  9. Java实现支付宝APP支付实现记录

    支付宝支付成功返回结果封装 import com.alibaba.fastjson.annotation.JSONField;import java.math.BigDecimal; import j ...

最新文章

  1. mysql图标_MySQL 支持 emoji 图标存储
  2. html表单提交后怎么发送邮箱,Dreamweaver中用表单制作了留言板,如何将内容提交后发到指定邮箱?...
  3. [html] 写一个布局,当页面滚动一定高时,导航始终固定在顶部,反之恢复原位
  4. java面向对象多态特性
  5. html 只能输入正数,vue 限制input只能输入正数
  6. 攻城掠地sdk服务器没有响应,攻城掠地没落的原因及对策
  7. 杭电oj首字母变大写
  8. 安卓操作系统版本(Version)与应用程序编程接口等级(Application Programming Interface Level)对照表...
  9. Hadoop学习---Zookeeper+Hbase配置学习
  10. 合沟微服务怎么添加_微服务架构:动态配置中心搭建
  11. json字符串转json对象
  12. js通过pako压缩数据后java解压数据
  13. 我的听歌神器--网易云
  14. Python min()函数
  15. asp万年历简易版本
  16. window10怎么设置共享计算机,Win10系统网络共享功能怎么用?Windows10网络共享功能使用方法...
  17. 处理器后面的字母含义_CPU后面的数字和字母都是什么意思?全面解答。
  18. Professional Microsoft Office SharePoint Designer 2007
  19. 案例十、检测域名是否到期
  20. 华为OD机试 - 自动曝光(C 语言解题)【独家】

热门文章

  1. 云计算在未来一年的发展预测
  2. MPX200 ROM DIY指南[转]
  3. 一文了解公有云、私有云、混合云、边缘云、专有云、分布式云
  4. 润乾报表CookBook与使用
  5. 微信小程序java装修家装系统
  6. 只谈处理器 且看Apple A4到A5的进化
  7. 腾讯云 mysql远程访问_远程连接腾讯云的mysql
  8. 令程序员泪流满面的瞬间
  9. 关于笔记本电脑插上网线没反应的解决方案
  10. 事后诸葛亮-团队总结