200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > 支付宝支付-当面付之扫码支付「扫码支付」

支付宝支付-当面付之扫码支付「扫码支付」

时间:2020-02-29 09:06:39

相关推荐

支付宝支付-当面付之扫码支付「扫码支付」

前言

支付宝支付—沙箱环境使用

支付宝支付-支付宝PC端扫码支付

支付宝支付-手机浏览器H5支付

支付宝支付-当面付之扫码支付「本文

当面付包含两种支付方式:商品条形码支付 + 扫码支付

经过前面两篇PC端扫码支付手机H5支付,我们可以看到一个共同的特点就是接口返回的都是一个Form表单,然后交给提交执行,然后调起支付。其中PC端提交Form表单后跳转至新的窗口进行支付,而手机端H5支付则是唤起支付宝APP支付。

但是现在有这么个场景,我不希望在PC端支付时跳转支付宝网页支付,而是直接将二维码嵌入到系统当中,用户直观看到的就是一个弹窗二维码,然后用户拿支付宝扫码支付…这就是本文的当面付之扫码支付了。

废话不多说,直接进入主题。

本文开发环境:IDEA + Tomcat8.5+支付宝沙箱环境+SpringBoot

补充:调用沙箱环境接口,需要安装沙箱环境下的支付宝APP,不了解的小伙伴可以参考上方 支付宝支付—沙箱环境使用。

一、pom引入依赖 + 参数准备

引入支付宝支付依赖文件,本文基于4.9.153.ALL版本,及供参考, 最新版本可去官方文档查阅。

<!--alipay-->

<dependency>

<groupId>com.alipay.sdk</groupId>

<artifactId>alipay-sdk-java</artifactId>

<version>4.9.153.ALL</version>

</dependency>

关于支付宝公钥、私钥、回调地址啥的就不再重复了,不清楚的去看支付宝支付—沙箱环境使用。

配置可以单独创建一个类,静态初始化参数::AlipayConfig.java

publicclassAlipayConfig{

/**商户appid**/

publicstaticStringAPPID="10170070";

/**私钥pkcs8格式的**/

publicstaticStringRSA_PRIVATE_KEY="";

/**服务器异步通知页面路径需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问**/

publicstaticStringnotify_url="http://ngrok.sscai.club/alipay_trade_wap_pay_java_utf_8_war_exploded/notify_url.jsp";

/**页面跳转同步通知页面路径需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问商户可以自定义同步跳转地址**/

publicstaticStringreturn_url="http://ngrok.sscai.club/alipay_trade_wap_pay_java_utf_8_war_exploded/return_url.jsp";

/**请求网关地址**/

publicstaticStringURL="/gateway.do";

/**编码**/

publicstaticStringCHARSET="UTF-8";

/**返回格式**/

publicstaticStringFORMAT="json";

/**支付宝公钥**/

publicstaticStringALIPAY_PUBLIC_KEY="";

/**日志记录目录**/

publicstaticStringlog_path="/log";

/**RSA2**/

publicstaticStringSIGNTYPE="RSA2";

/**商户门店编号「需要申请当面付」**/

publicstaticStringSTORE_ID="122211242";

}

几个主要的参数:

APPID:商户appidRSA_PRIVATE_KEY:应用私钥ALIPAY_PUBLIC_KEY:支付宝公钥「注意不是应用公钥」

这几个参数不清楚的,可以看一下 沙箱环境使用,或者看一下官方文档参数说明。

二、后端代码

还是之前的代码,一个controller接口方法,一个具体的实现方法「没有使用开源SDK」:

Controller

@ApiOperation(value="获取支付宝支付二维码")

publicResult<AlipayResponse>getAliPayQrCode(@CurrentUserUserModeluser,@RequestBodyAlipayOrderRequestalipayOrderRequest){

/**返回给前端的二维码内容**/

StringsHtmlText=null;

try{

/**判断是否已经存在订单,根据自己业务的不同自行判断**/

if(!StringUtils.isNotBlank(alipayOrderRequest.getWidOutTradeNo())){

Ordersorders=ordersService.createOrder(user,alipayOrderRequest.getWidTotalFee(),alipayOrderRequest.getAppType());

alipayOrderRequest.setWidOutTradeNo(orders.getOrderId());

}else{

OrderResponseorders=ordersService.searchOrderDetail(user,alipayOrderRequest.getWidOutTradeNo());

alipayOrderRequest.setWidTotalFee(orders.getAmount().toString());

}

/**这是主要的方法**/

sHtmlText=alipayService.alipayOrder(alipayOrderRequest);

}catch(AlipayApiExceptione){

e.printStackTrace();

}

AlipayResponsealipayResponse=newAlipayResponse();

alipayResponse.setSHtmlText(sHtmlText);

alipayResponse.setOrderId(alipayOrderRequest.getWidOutTradeNo());

returnResultUtil.success(alipayResponse);

}

ServerImpl

@Transactional

publicStringalipayOrder(AlipayOrderRequestalipayOrderRequest)throwsAlipayApiException{

/**获得初始化的AlipayClient**/

AlipayClientalipayClient=newDefaultAlipayClient(AlipayConfig.gatewayUrl,

AlipayConfig.app_id,

AlipayConfig.merchant_private_key,

"json",

AlipayConfig.charset,

AlipayConfig.alipay_public_key,

AlipayConfig.sign_type);

/**当面付之「扫码支付」**/

AlipayTradePrecreateRequestalipayTradePrecreateRequest=newAlipayTradePrecreateRequest();

/**回调地址+异步通知**/

alipayTradePrecreateRequest.setNotifyUrl(AlipayConfig.notify_url);

alipayTradePrecreateRequest.setReturnUrl(AlipayConfig.return_url);

/**商户订单号,商户网站订单系统中唯一订单号,必填**/

Stringout_trade_no=alipayOrderRequest.getWidOutTradeNo();

/**付款金额,必填**/

Stringtotal_amount=alipayOrderRequest.getWidTotalFee();

/**订单名称,必填**/

Stringsubject=alipayOrderRequest.getWidSubject();

/**商户门店编号,必填**/

Stringstore_id=AlipayConfig.STORE_ID;

/**交易超时时间,订单允许的最晚付款时间,必填**/

Stringtimeout_express="120m";

/**拼接参数**/

alipayTradePrecreateRequest.setBizContent(

"{\"out_trade_no\":\""+out_trade_no+"\","

+"\"total_amount\":\""+total_amount+"\","

+"\"subject\":\""+subject+"\","

+"\"store_id\":\""+store_id+"\","

+"\"timeout_express\":\""+timeout_express+"\"}");

returnalipayClient.execute(alipayTradePrecreateRequest).getBody();

}

三、返回结果+测试

如上代码调用execute之后的返回结果:

{

"alipay_trade_precreate_response":{

"code":"10000",

"msg":"Success",

"out_trade_no":"160037744742",

"qr_code":"/bax06173nktjyrrwupss00bf"

},

"sign":"sdk3Q6idlQC+SRuuxc6xXv3g4BAkxEgpA9WYJoiE8oYH5mA6K8+GMwAETNKOhOPh/SoYS4CECzswk/H7qw9A=="

}

我们可以看到qr_code参数了,剩下的就是交给前端生成二维码了,然后用户扫码支付,在这我就不展示了,直接拿链接去草料二维码直接生成个二维码试试。

四、扫码支付回调地址

支付成功后支付宝会回调前边设置的回调地址,由后端的的return_url参数控制。

再看看支付成功后的回调接口,由后端的notify_url参数控制「没有使用开源的SDK演示」:

publicStringalipaynotify(Modelmodel,HttpServletRequestrequest){

log.info("支付宝异步回调------------beg-----------");

Stringresult="fail";

/**获取支付宝POST过来反馈信息**/

/**

*功能:支付宝服务器异步通知页面

*说明:

*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。

*该代码仅供学习和研究支付宝接口使用,只是提供一个参考。

*/

Map<String,String>params=this.getAlipayRequest(request);

if(params==null||params.size()==0){

BufferedReaderbufferReader=null;

StringBuildersb=newStringBuilder();

try{

bufferReader=newBufferedReader(request.getReader());

Stringline=null;

while((line=bufferReader.readLine())!=null){

sb.append(newString(line.getBytes("ISO-8859-1"),"utf-8"));

}

}catch(IOExceptione){

e.printStackTrace();

}

Stringbody=null;

try{

body=URLDecoder.decode(sb.toString(),"UTF-8");

}catch(UnsupportedEncodingExceptione){

e.printStackTrace();

}

params=UriComponentsBuilder.newInstance().query(body).build().getQueryParams().toSingleValueMap();

}

booleansignVerified=false;

try{

signVerified=AlipaySignature.rsaCheckV1(params,AlipayConfig.alipay_public_key,AlipayConfig.charset,AlipayConfig.sign_type);

}catch(AlipayApiExceptione1){

log.error("由于"+e1.getErrMsg()+"返回给支付宝系统的结果result:fail");

model.addAttribute("result","fail");

returnresult;

}

/**——请在这里编写您的程序(以下代码仅作参考)——**/

/*实际验证过程建议商户务必添加以下校验:

1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,

2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),

3、校验通知中的seller_id(或者seller_email)是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email)

4、验证app_id是否为该商户本身。

*/

log.error("支付宝验证签名:---------------------------------"+signVerified);

if(signVerified){/**验证成功**/

/**商户订单号**/

/**交易状态**/

log.info("支付宝异步回调验签成功!");

Stringtrade_status=params.get("trade_status");

if("TRADE_FINISHED".equals(trade_status)){

/**判断该笔订单是否在商户网站中已经做过处理**/

/**如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序**/

/**如果有做过处理,不执行商户的业务程序**/

/**注意:**/

/**退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知**/

try{

/**在这里处理支付成功后的操作,比如修改订单状态等等**/

coding...

result="success";

}catch(Exceptione){

log.error(e.getMessage());

result="fail";

}

}elseif("TRADE_SUCCESS".equals(trade_status)){

/**判断该笔订单是否在商户网站中已经做过处理**/

/**如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序**/

/**如果有做过处理,不执行商户的业务程序**/

/**注意:**/

/**付款完成后,支付宝系统发送该交易状态通知**/

try{

/**在这里处理支付成功后的操作,比如修改订单状态等等**/

coding...

result="success";

}catch(Exceptione){

log.error(e.getMessage());

result="fail";

}

}else{

result="fail";

}

}else{/**验证失败**/

result="fail";

/**调试用,写文本函数记录程序运行情况是否正常**/

/**StringsWord=AlipaySignature.getSignCheckContentV1(params);**/

/**AlipayConfig.logResult(sWord);**/

log.debug("支付宝异步回调验签失败");

}

log.debug("异步回调返回给支付宝系统的结果result:"+result);

model.addAttribute("result",result);

log.info("支付宝异步回调-------------end------------");

returnresult;

}

该方法返回给支付宝的 result 就successfail两个结果。

从以上看来,其实不难发现支付宝支付是非常简单的,尽管我上边贴了大量的代码,其实采用开源SDK的话可以更加缩减、美化一些。

ok,这篇文章就到这结束了,上边并没有详细介绍接口调用、参数说明等,详细介绍请查看官方文档:

/open/194/106078/

/open/194/103296

文章最后

博客地址:/niceyoo

如果觉得这篇文章有丶东西,不妨关注一下我,关注是对我最大的鼓励~

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。