场景需求:
通过支付宝扫描二维码进入手机H5网站,获取用户唯一标识appid来标识用户以及处理逻辑。一系列操作后,调起支付窗口完成支付宝支付
1、支付宝开放平台配置
1、登陆支付宝开放平台中心,选择“ 网页&移动应用 ”,然后创建一个应用。此时该应用的状态为开发中,需要我们添加一些功能和信息后去审核,审核通过就成了已上线。就可以开始使用了。
这里我们只需要两项功能:1、手机网站支付;2、用户信息授权
除此之外还需要配置一下开发设置,如下图:
具体配置可以参照上面官方的文档来。
我这里只配了一个接口加签方式(支付使用),加签方式有两种,一种是普通加签——需要设置支付宝公钥。另一种是证书加签方式。这个有点复杂,看个人需求,具体参照官方文档。
我这里选择普通加签方式,按照官方文档的指示,下载了一个“ 支付宝开放平台开发助手 ” 的软件用来生成相应的应用公钥和应用私钥
首先,用上面这个工具生成一对密钥,这里叫做应用私钥和应用公钥。我们要做的就是 保存 好这对密钥!!!。普通加签方式就是把这里的应用公钥上传(复制粘贴)到配置里面,然后旁边会有个生成支付宝公钥的按钮,点击生成支付宝公钥。然后把这段支付宝公钥保存下来。跟之前应用私钥和应用公钥一起。后面支付会用到。
接下来就是配置授权回调地址。:这个回调地址就是我们做用户信息授权登陆的时候用到的。这里要配置一个正规的可访问域名。支付宝会检测的。
这里简单介绍一下这个回调地址有什么用。首先我们得知道用户信息授权的流程:用户通过特定规则拼接传输数据到支付宝指定授权地址(url),支付宝校验你传输的数据,通过的话就会给你返回一个auth_code。我们再通过返回过来的auth_code去换取支付宝用户唯一标识appid。拿到这个appid。我们就完成了授权。
上面返回的auth_code就是在支付宝校验我们传输的数据后,会请求我们后台配置的授权回调地址。然后会在url后面带上auth_code
简单来说就是:我们请求支付宝,支付宝通过后会访问我们配置的授权回调地址来将auth_code返回给我们。
配置这一块就结束了。总共配置两个地方:一个加签方式(支付使用),一个授权回调地址(授权使用)。完成后我们就可以提交,等待审核了。(所有功能都必须审核通过才能使用)
用户信息授权
上面我们基本配置了授权所需要的配置,其实就只配置一个授权回调地址来获取返回的auth_code。
先上代码后讲解:
redirectForAliCode() {goodsApi.getAliSign().then(res => {//授权需要用到开放平台里我们创建应用的appid。不是用户appid。const rr = res.data;const redirectUrl = window.location.href;var result = redirectUrl.match(/=(\S*)#/)[1];var results = result.match(/(\d*)/)[1];let param = 'app_id=' + rrparam += '&scope=auth_base'//可参考文档,因为我们只要授权,所以,这里只写auth_base//下面的redirect_uri值必须经过URLENCODE转义,不能明文传输param += '&redirect_uri=' + encodeURIComponent('http://****.com')//这里写我们后台配置的授权回调地址param += '&state='+results //一定要一模一样,否则授权会失败console.log('url:', 'https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?'+ param);window.location.href = 'https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?' + param;//支付宝授权指定url}).catch(err => {})}
通过该代码调用获取auth_code后,我们再通过这个auth_code去换取appid
public Map<String, Object> getPrivateAccessToken(String code) {//之前拿到的auth_codeAlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.URL,//支付宝apialipayConfig.APPID,alipayConfig.RSA_PRIVATE_KEY,alipayConfig.FORMAT,alipayConfig.CHARSET,alipayConfig.ALIPAY_PUBLIC_KEY,alipayConfig.SIGNTYPE);AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();request.setCode(code);request.setGrantType("authorization_code");Map map = Maps.newHashMap();try {AlipaySystemOauthTokenResponse oauthTokenResponse = alipayClient.execute(request);logger.info("AccessToken:"+oauthTokenResponse.getAccessToken());logger.info("UserId:"+oauthTokenResponse.getUserId());map.put("AccessToken",oauthTokenResponse.getAccessToken());map.put("UserId",oauthTokenResponse.getUserId());} catch (AlipayApiException e) {//处理异常e.printStackTrace();logger.info("获取userID异常,信息如下:"+e.getErrMsg());}return map;}
通过上面这个代码,可以换取到auth_code。上面创建支付宝api实例的时候有几个参数。
URL:固定请求地址。
APPID:应用appid。
RSA_PRIVATE_KEY:还记得之前保存的应用私钥吗。这里用到了。
FORMAT:格式,只支持json。
CHARSET:编码,只支持UTF-8。
ALIPAY_PUBLIC_KEY:之前配置加签方式保存下来的支付宝公钥
SIGNTYPE:签名类型,固定:RSA2
至此,我们的appid就拿到了,用户授权信息功能也完成了。接下来就是业务逻辑的一些处理了。(上面授权的这些参数待会支付接口也会用到。)
手机网站支付
下面就到了支付环节了,首先我简单说下支付的大概流程:
我们整理一下订单数据,通过调用支付宝api,然后返回一个form表单,我们再把得到的form表单放到页面上自动提交,就会调起支付密码框,输入密码后就支付完成。
整个支付接口,我分为两个阶段
1、支付准备阶段:
这里最少需要准备两个订单数据字段,一个是我们的业务系统订单号(不可重复哟)。再一个就是支付的金额了(单位是元,最小到分)。
public String aliPay(String orderSn,Double monery){AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig.URL,alipayConfig.APPID,alipayConfig.RSA_PRIVATE_KEY,alipayConfig.FORMAT,alipayConfig.CHARSET,alipayConfig.ALIPAY_PUBLIC_KEY,alipayConfig.SIGNTYPE);AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();//支付成功与否回调通知地址request.setNotifyUrl(alipayConfig.notify_url);//支付完成后自动返回的地址(一般为作我们的业务系统自定义的查询是否支付页面)request.setReturnUrl(alipayConfig.return_url+orderSn);request.setBizContent("{" +"\"subject\":\"随便写个名称,用作支付宝后台报表查询标识的\"," +"\"out_trade_no\":\""+orderSn+"\"," +"\"total_amount\":"+monery+"," +"\"product_code\":\"QUICK_WAP_WAY\"" +" }");AlipayTradeWapPayResponse response = null;try {response = alipayClient.pageExecute(request);//这里会返回一个form表单(调起支付框--这个框就是我们平时用支付宝支付,输密码的框)String result = response.getBody();logger.info(result);return result;} catch (AlipayApiException e) {e.printStackTrace();}if(response.isSuccess()){System.out.println("调用成功");} else {System.out.println("调用失败");}return null;}
这上面构造支付宝api实例的参数跟上面获取授权一样。不同的是支付这里,必须得传一个支付是否成功的回调通知地址,以及一个支付完成后的返回地址。(支付宝这里跟微信jsapi支付不同,是要我们自己将地址传到支付宝后台,由他们来请求我们的地址。)
我们拿到form表单后,把这个表单返回给前台自动提交。
<form name="punchout_form" method="post" action="">
<input type="hidden" name="biz_content" value="{"subject":"深圳校服","out_trade_no":"20200513085536016569","total_amount":0.01,"product_code":"QUICK_WAP_WAY" }">
<input type="submit" value="立即支付" style="display:none" >
</form>
<script>document.forms[0].submit();</script>
生成的form表单大概是这个样子。
aliPrepare(){
//前台传订单号去后台,后台查出订单金额传给支付宝api,返回一个form表单payApi.aliPrepare(this.order.orderNo).then(res => {// 存储微信支付数据datalet data = res.data//返回的form表单console.log("即将跳转支付宝支付,返回的数据为:"+data)const div = document.createElement('div');div.innerHTML = datadocument.body.appendChild(div)document.forms[0].submit();//这些document操作应该不用过多解释了=-=}).catch(err =>{Toast('系统异常,青稍后再试')Toast(err)})},
执行完这个js后就会自动弹出一个支付框啦。支付准备阶段就完成了。
2、支付完成阶段
在我们输入密码完成支付后,(页面):支付宝会请求我们支付的时候传的return_url地址。
(后台):支付宝会调用我们传过去的通知回调NotifyUrl地址
如何处理回调通知。官方文档里有demo。这里就不做展示了。
支付宝手机网站demo
我这里由于用的是springboot。所以直接返回即可
/*** 支付宝支付回调* @return*/@RequestMapping(value = "ali/notify",method = RequestMethod.POST)public String aliNotify(){logger.info("开始进入支付宝支付的回调,地址:ali/notify");String msg = aliPayService.resultNotify();logger.info("支付宝回调返回:"+msg);String jsonmes = JSON.toJSONString(msg);logger.info("支付宝回调返回(fast处理):"+jsonmes);return msg;//直接返回success,不要带任何东西,否则会一直回调}
问题一:
由于maven中央仓库里没有支付宝的api。所以我们需要手动下载jar。提取码为:gt05
springboot的话,只需要这一个jar包就可以。
然后自己导入进maven仓库里。具体步骤可以自行百度,将jar打进你本地的maven仓库后就可以正常导入pom文件使用。
pom文件展示:
<!-- alipay --><dependency><groupId>com.alipay</groupId><artifactId>sdk-java</artifactId><version>4.9.3</version></dependency>
至此,支付宝授权登陆,支付接口就完成了。
实战操作建议配合官方文档一起,便于自己深刻理解。
如对上面有疑问的可以评论留言,看到会解答。