最近在工做中须要使用支付宝app支付,在初次使用过程当中也不可避免的出现了一些问题,那么本次随笔主要是概述支付宝app支付服务端的整个实现过程以及就服务端出现的一些问题作一些总结。java
https://open.alipay.com/platform/home.htmweb
首先须要建立一个应用。json
而后须要设置应用公钥。安全
下载支付宝密钥生成器。生成成功以后会有商户应用公钥和私钥,将公钥复制到这里, 私钥请妥善保存。下载地址:https://docs.open.alipay.com/291/106097/。保存设置以后会显示支付宝公钥,请妥善保存。app
最后提交审核,等待。异步
注意:若是应用审核经过上线以后,支付宝公钥忘记后可经过进入应用详情页,按以下图所示查看支付宝公钥。maven
首先须要下载SDK,https://docs.open.alipay.com/54/104509。编码
完成以后,须要切换命令行,进入SDK所在目录,执行以下命令。若是命令没法执行,请百度如何配置maven环境变量,配置好以后再执行。加密
mvn install:install-file -DgroupId=com.alipay.sdk -DartifactId=alipay-sdk-java -Dversion=3.1.0 -Dpackaging=jar -Dfile=SDK文件名.jar
groupId:能够本身定义,pom文件依赖依据与此
artifactId:能够本身定义,pom文件依赖依据与此
version:能够本身定义,pom文件依赖依据与此
packaging:打包方式(jar)
file:文件的路径的路径
在pom.xml中引入依赖,以下。url
<!-- 支付宝支付相关start --> <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>3.1.0</version> </dependency> <!-- 支付宝支付相关end -->
#支付宝支付相关配置
#支付宝分配给开发者的应用Id aliPayAppId=XXX
#卖家支付宝用户号(对应异步通知返回参数seller_id)(能够不配置,只是异步通知时为了进一步校验而配置) aliPaySellerId=XXX
#卖家支付宝帐号(对应异步通知返回参数seller_email)(能够不配置,只是异步通知时为了进一步校验而配置) alipayAccount=XXX
#商户应用公钥 rsaPublicKey=XXX
#商户应用私钥(注意,若是是Java语言,须要使用pkcs8格式的私钥,避免出现不可预知的错误) rsaPrivatKey=XXX
#支付宝公钥 rsaAlipayPublicKey=XXX
#加密方式 signType=XXX
#仅支持JSON alipayFormat=json
#请求使用的编码格式,如utf-8,gbk,gb2312等 alipayCharset=utf-8
/** *app支付 * *@author lp *@date 2019/1/4 16:32 */ @ApiOperation("app支付") @RequestMapping(value = "alipay", method = RequestMethod.POST) public String alipay(@RequestBody CombinedPaymentDto dto, HttpServletResponse response, HttpServletRequest request) { response.setHeader("Access-Control-Allow-Origin", "*"); // 获取项目中实际的订单的信息 // 此处是相关业务代码 // 获取配置文件中支付宝相关信息(可使用本身的方式获取) String aliPayGateway = PropertiesUtils.getInstace("config/webService.properties").getProperty("aliPayGateway"); String aliPayAppId = PropertiesUtils.getInstace("config/webService.properties").getProperty("aliPayAppId"); String rsaPublicKey = PropertiesUtils.getInstace("config/webService.properties").getProperty("rsaPublicKey"); String rsaPrivatKey = PropertiesUtils.getInstace("config/webService.properties").getProperty("rsaPrivatKey"); String rsaAlipayPublicKey = PropertiesUtils.getInstace("config/webService.properties").getProperty("rsaAlipayPublicKey"); String signType = PropertiesUtils.getInstace("config/webService.properties").getProperty("signType"); String alipayFormat = PropertiesUtils.getInstace("config/webService.properties").getProperty("alipayFormat"); String alipayCharset = PropertiesUtils.getInstace("config/webService.properties").getProperty("alipayCharset"); // 开始使用支付宝SDK中提供的API AlipayClient alipayClient = new DefaultAlipayClient(aliPayGateway, aliPayAppId, rsaPrivatKey, alipayFormat, alipayCharset, rsaAlipayPublicKey, signType); // 注意:不一样接口这里的请求对象是不一样的,这个能够查看蚂蚁金服开放平台的API文档查看 AlipayTradeAppPayRequest alipayRequest = new AlipayTradeAppPayRequest(); AlipayTradeAppPayModel model = new AlipayTradeAppPayModel(); model.setBody("XXX"); model.setSubject("XXX"); // 惟一订单号 根据项目中实际须要获取相应的 model.setOutTradeNo(""); // 支付超时时间(根据项目须要填写) model.setTimeoutExpress("30m"); // 支付金额(项目中实际订单的须要支付的金额,金额的获取与操做请放在服务端完成,相对安全) model.setTotalAmount(""); model.setProductCode("QUICK_MSECURITY_PAY"); alipayRequest.setBizModel(model); // 支付成功后支付宝异步通知的接收地址url alipayRequest.setNotifyUrl("XXX/getAlipayNotifyInfo"); // 注意:每一个请求的相应对象不一样,与请求对象是对应。 AlipayTradeAppPayResponse alipayResponse = null; try { alipayResponse = alipayClient.sdkExecute(alipayRequest); } catch (AlipayApiException e) { e.printStackTrace(); } // 返回支付相关信息(此处能够直接将getBody中的内容直接返回,无需再作一些其余操做) return alipayResponse.getBody(); }
/** *接收支付宝异步通知消息 * *@author lp *@date 2019/1/4 17:19 */ @ApiOperation("接收支付宝异步通知消息") @RequestMapping(value = "getAlipayNotifyInfo", method = RequestMethod.POST) public String getAlipayNotifyInfoOfCombinedPayment(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException { response.setHeader("Access-Control-Allow-Origin", "*"); // 解决POST请求中文乱码问题(推荐使用此种方式解决中文乱码,由于是支付宝发送异步通知使用的是POST请求) request.setCharacterEncoding("UTF-8"); //获取支付宝POST过来反馈信息 Map<String,String> params = new HashMap<>(); Map<String,String[]> requestParams = request.getParameterMap(); for (Iterator<String> 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] + ","; } // 官方demo中使用以下方式解决中文乱码,在此本人不推荐使用,可能会出现中文乱码解决无效的问题。 // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8"); params.put(name, valueStr); } // 支付宝公钥(请注意,不是商户公钥) String rsaAlipayPublicKey = PropertiesUtils.getInstace("config/webService.properties").getProperty("rsaAlipayPublicKey"); String signType = PropertiesUtils.getInstace("config/webService.properties").getProperty("signType"); String alipayCharset = PropertiesUtils.getInstace("config/webService.properties").getProperty("alipayCharset"); boolean signVerified = false; try { //调用SDK验证签名 signVerified = AlipaySignature.rsaCheckV1(params, rsaAlipayPublicKey, alipayCharset, signType); if(signVerified) { // 验证通知后执行本身项目须要的业务操做 // 通常须要判断支付状态是否为TRADE_SUCCESS // 更严谨一些还能够判断 1.appid 2.sellerId 3.out_trade_no 4.total_amount 等是否正确,正确以后再进行相关业务操做。 // 成功要返回success,否则支付宝会不断发送通知。 return "success"; } // 验签失败 笔者在这里是输出log,能够根据须要作一些其余操做 // 失败要返回success,否则支付宝会不断发送通知。 return "fail"; } catch (AlipayApiException e) { e.printStackTrace(); // 验签异常 笔者在这里是输出log,能够根据须要作一些其余操做 return "fail"; } }