Java对接支付宝的支付、退款、提现

您所在的位置:网站首页 支付宝退款教程 Java对接支付宝的支付、退款、提现

Java对接支付宝的支付、退款、提现

2024-07-10 19:37| 来源: 网络整理| 查看: 265

本篇主要是正对Java对接支付宝的常用功能,需要开通个人的沙箱环境和内网穿透(我用了阿里云服务器)。

集成前提:开发者在集成和开发前需要了解一下常用的接入方式和架构建议,如下图所示:

图片

1、登录网页版的个人支付宝

https://auth.alipay.com/login/ant_sso_index.htm

2、进入研发服务进入沙箱环境

3、通过开发平台去配置秘钥配置

https://opendocs.alipay.com/open/200/105311

4、配置yml文件和pom alipay: appId: 2016110300790369 #在支付宝创建的应用的id notifyUrl: http://127.0.0.1/api/pay/notify #支付宝会悄悄的给我们发送一个请求,告诉我们支付成功的信息 returnUrl: http://127.0.0.1/api/page/success #同步通知,支付成功,一般跳转到成功页 http://127.0.0.1/api/page/success?charset=utf-8&out_trade_no=6837ec3c-11b5-4290-b423-54515caf2fa5&method=alipay.trade.page.pay.return&total_amount=93.80&sign=c7jnEO8n6O%2BZXpk7dF3zYtIJb9lTMIM0%2B%2FmLm2JjPgdH5vEib7wp49%2F2%2FMB05YyKOxk6PYI5B2W0k%2FdHi%2Biyk083ZKcwL3a4ToXusG%2BZji66PaYe3tIe72N%2FgzpKcxF9lwF2%2FR0%2FbPhTDJpqem2v9Ej0d1yszLVeBQzU8IuQRglM4U6ev5gt%2Bslv8BViBkXWuy2OM6pA7k6CFptHWwXBYsdg9Ik%2BAIh0LD3rZobpzyn1w7y71Bu2Nj8XHev2gzmkxjyRSuERZJVVBSNNqtGY6xxlNqzh9L5k%2B4FcwEqNv5UPgWlCnvT9BI%2FB3cCUcAUTOxcdLwi1W8gTaqeI3rStyw%3D%3D&trade_no=2020122122001400320501115075&auth_app_id=2016110300790369&version=1.0&app_id=2016110300790369&sign_type=RSA2&seller_id=2088102181741856×tamp=2020-12-21+11%3A53%3A05 signType: RSA2 #签名方式 charset: utf-8 #字符编码格式 gatewayUrl: https://openapi.alipaydev.com/gateway.do #沙箱环境 timeoutExpress: 30m format: json merchantPrivateKey: # 商户私钥 alipayPublicKey: #支付宝公钥 com.alipay.sdk alipay-sdk-java 4.9.28.ALL org.jdom jdom2 2.0.6 5、包含网页支付(已测试)、APP支付、提现、退款、回调接口

5.1、请求入口代码

package com.example.mybaties.controller; import com.example.mybaties.result.BaseResponse; import com.example.mybaties.result.ResultGenerator; import com.example.mybaties.service.AliPayService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * @description: 支付宝下单支付 * @author: lst * @date: 2020-12-01 16:58 */ @RestController @RequestMapping("/pay") @Api(value = "AliPayController", tags = "支付宝下单支付") public class AliPayController { @Autowired private AliPayService aliPayService; /** * @Description 支付宝下单支付 * @author lst * @date 2020-12-1 17:27 * @return com.example.mybaties.result.BaseResponse */ @PostMapping(value = "/place-order", produces = "application/json; charset=utf-8") @ApiOperation(value = "支付宝下单支付", notes = "支付宝下单支付", produces = "application/json") public BaseResponse placeOrder() { return ResultGenerator.genSuccessResult(aliPayService.placeOrder()); } /** * @Description 网页版支付宝下单支付 * @author lst * @date 2020-12-2 14:16 * @return com.example.mybaties.result.BaseResponse */ @PostMapping(value = "/alipay-page", produces = "application/json; charset=utf-8") @ApiOperation(value = "网页版支付宝下单支付", notes = "网页版支付宝下单支付", produces = "application/json") public void alipayPage(HttpServletResponse response) { aliPayService.alipayPage(response); } /** * @Description 支付宝提现 * @author lst * @date 2020-12-2 17:03 * @param response */ @PostMapping(value = "/alipay-withdraw", produces = "application/json; charset=utf-8") @ApiOperation(value = "支付宝提现", notes = "支付宝提现", produces = "application/json") public void withdraw(HttpServletResponse response) { aliPayService.withdraw(response); } /** * @Description 支付宝退款 * @author lst * @date 2020-12-21 14:19 * @param response */ @PostMapping(value = "/alipay-refund", produces = "application/json; charset=utf-8") @ApiOperation(value = "支付宝退款", notes = "支付宝退款", produces = "application/json") public void refund(HttpServletResponse response) { aliPayService.refund(response); } /** * @Description 支付宝支付成功后,回调该接口 * @author lst * @date 2020-12-1 17:27 * @param request * @param response * @return java.lang.String */ @RequestMapping(value="/notify",method={RequestMethod.POST,RequestMethod.GET}) @ApiOperation(value = "支付宝支付成功后,回调该接口", notes = "支付宝支付成功后,回调该接口", produces = "application/json") public String notify(HttpServletRequest request, HttpServletResponse response) { return aliPayService.notifyData(request,response); } }

5.2、实现层代码

package com.example.mybaties.service.impl; import com.example.mybaties.form.AlipayBean; import com.example.mybaties.form.AlipayRefundForm; import com.example.mybaties.form.WithdrawBean; import com.example.mybaties.service.AliPayService; import com.example.mybaties.utils.AlipayUtil; import com.example.mybaties.utils.StringUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.UUID; /** * @description: 支付宝下单支付 * @author: lst * @date: 2020-12-01 17:01 */ @Service @Slf4j public class AliPayServiceImpl implements AliPayService { @Autowired private AlipayUtil alipayUtil; /** * @Description 支付宝下单支付 * @author lst * @date 2020-12-1 17:27 * @return java.lang.String */ @Override public String placeOrder() { String body = alipayUtil.alipay(); return body; } /** * @Description 支付宝支付成功后,回调该接口 * @author lst * @date 2020-12-1 17:27 * @param request * @param response * @return java.lang.String */ @Override public String notifyData(HttpServletRequest request, HttpServletResponse response) { return alipayUtil.notifyData(request,response); } /** * @Description 网页版支付宝下单支付 * @author lst * @date 2020-12-1 17:27 * @param response * @return java.lang.String */ @Override public void alipayPage(HttpServletResponse response) { AlipayBean alipayBean = new AlipayBean(); //商户订单号,商户网站订单系统中唯一订单号,必填 alipayBean.setOut_trade_no(UUID.randomUUID().toString()); //付款金额,必填 alipayBean.setTotal_amount("93.8"); //订单名称,必填 alipayBean.setSubject("商品名称:网页版支付测试Java"); //商品描述,可空 alipayBean.setBody("商品信息"); String payResult = alipayUtil.alipayPage(alipayBean); response.setContentType("text/html;charset=utf-8"); try { response.getWriter().write(""); response.getWriter().write(""); response.getWriter().write(""); response.getWriter().write(""); response.getWriter().write(""); response.getWriter().write(payResult); response.getWriter().write(""); response.getWriter().write(""); response.getWriter().flush(); response.getWriter().close(); } catch (IOException e) { e.printStackTrace(); } } /** * @Description 支付宝提现 * @author lst * @date 2020-12-2 17:03 * @param response * @return void */ @Override public void withdraw(HttpServletResponse response) { WithdrawBean withdrawBean = new WithdrawBean(); String payResult = alipayUtil.withdraw(withdrawBean); response.setContentType("text/html;charset=utf-8"); try { response.getWriter().write(""); response.getWriter().write(""); response.getWriter().write(""); response.getWriter().write("提现"); response.getWriter().write(""); response.getWriter().write(""); if("success".equals(payResult)){ response.getWriter().write(" 恭喜提现成功"); }else{ response.getWriter().write(" 提现失败"); } response.getWriter().write(""); response.getWriter().write(""); response.getWriter().flush(); response.getWriter().close(); } catch (IOException e) { e.printStackTrace(); } } @Override public void refund(HttpServletResponse response) { AlipayRefundForm alipayRefundForm = new AlipayRefundForm(); String payResult = alipayUtil.alipayRefund(alipayRefundForm); response.setContentType("text/html;charset=utf-8"); try { response.getWriter().write(""); response.getWriter().write(""); response.getWriter().write(""); response.getWriter().write("退款"); response.getWriter().write(""); response.getWriter().write(""); if(StringUtil.isNotEmpty(payResult)){ response.getWriter().write(" 恭喜退款成功"); }else{ response.getWriter().write(" 退款失败"); } response.getWriter().write(""); response.getWriter().write(""); response.getWriter().flush(); response.getWriter().close(); } catch (IOException e) { e.printStackTrace(); } } }

5.3、支付工具类

package com.example.mybaties.utils; import com.alibaba.fastjson.JSONObject; 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.domain.AlipayTradeRefundModel; import com.alipay.api.internal.util.AlipaySignature; import com.alipay.api.request.AlipayFundTransToaccountTransferRequest; import com.alipay.api.request.AlipayTradeAppPayRequest; import com.alipay.api.request.AlipayTradePagePayRequest; import com.alipay.api.request.AlipayTradeRefundRequest; import com.alipay.api.response.AlipayFundTransToaccountTransferResponse; import com.alipay.api.response.AlipayTradeAppPayResponse; import com.alipay.api.response.AlipayTradeRefundResponse; import com.example.mybaties.constants.AlipayProperties; import com.example.mybaties.exceptionhandler.BaseException; import com.example.mybaties.exceptionhandler.BaseExceptionEnum; import com.example.mybaties.form.AlipayBean; import com.example.mybaties.form.AlipayRefundForm; import com.example.mybaties.form.WithdrawBean; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.UUID; /** * @description: 支付宝支付工具 * @author: lst * @date: 2020-12-01 15:57 * 支付宝管理:https://open.alipay.com/platform/developerIndex.htm * 支付宝对接文档:https://opendocs.alipay.com/open/54/106370 */ @Slf4j @Component public class AlipayUtil { @Autowired private AlipayProperties alipayProperties; /** * @Description APP支付宝下单支付 * @author lst * @date 2020-12-1 17:28 * @param * @return java.lang.String */ public String alipay(){ //TODO 1、实例化客户端 AlipayClient alipayClient = new DefaultAlipayClient(alipayProperties.getGatewayUrl(), alipayProperties.getAppId(), alipayProperties.getMerchantPrivateKey(), alipayProperties.getFormat(), alipayProperties.getCharset(), alipayProperties.getAlipayPublicKey(), alipayProperties.getSignType()); //TODO 2、实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest(); //TODO 3、SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。 AlipayTradeAppPayModel model = new AlipayTradeAppPayModel(); //商品信息 model.setBody("商品信息"); //商品名称 model.setSubject("商品名称:App支付测试Java"); //商品订单号(自动生成) model.setOutTradeNo(UUID.randomUUID().toString()); //交易超时时间 model.setTimeoutExpress(alipayProperties.getTimeoutExpress()); //支付金额 model.setTotalAmount("0.01"); //销售产品码 model.setProductCode("QUICK_MSECURITY_PAY"); model.setTimeExpire("2020-12-21 17:52:00"); request.setBizModel(model); //回调地址 request.setNotifyUrl(alipayProperties.getNotifyUrl()); log.info("请求数据:{},回调地址:{}",request.getBizModel(),request.getNotifyUrl()); //这里和普通的接口调用不同,使用的是sdkExecute AlipayTradeAppPayResponse response = null; try { response = alipayClient.sdkExecute(request); //就是orderString 可以直接给客户端请求,无需再做处理。 log.info("支付宝返回数据:{}",response.getBody()); } catch (AlipayApiException e) { e.printStackTrace(); throw new BaseException(BaseExceptionEnum.ALIPAY_MSG_ERROR); } return response.getBody(); } /** * @Description APP支付宝支付成功后,回调该接口 * @author lst * @date 2020-12-1 17:29 * @param request * @param response * @return java.lang.String */ public String notifyData(HttpServletRequest request, HttpServletResponse response){ Map params = new HashMap(); //TODO 1、从支付宝回调的request域中取值 Map requestParams = request.getParameterMap(); for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) { String name = iter.next(); String[] values = 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); } for (Map.Entry entry : params.entrySet()) { log.info("key:{}, value:{}",entry.getKey(),entry.getValue()); } //TODO 2.封装必须参数 商户订单号 订单内容 交易状态(TRADE_SUCCESS) String outTradeNo = request.getParameter("out_trade_no"); String orderType = request.getParameter("body"); String tradeStatus = request.getParameter("trade_status"); log.info("商户订单号:{},订单内容:{},交易状态:{}",outTradeNo,orderType,tradeStatus); //TODO 3.签名验证(对支付宝返回的数据验证,确定是支付宝返回的) try { boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayProperties.getAlipayPublicKey(), alipayProperties.getCharset(), alipayProperties.getSignType()); if (signVerified) { //验签成功 log.info("*******验签成功******"); //TODO 业务处理逻辑 return "success"; } else { // 验签失败 log.info("*******验签失败******"); return "fail"; } } catch (AlipayApiException e) { e.printStackTrace(); return "fail"; } } /** * @Description 网页版支付宝下单支付 * @author lst * @date 2020-12-2 14:11 * @param alipayBean * @return java.lang.String */ public String alipayPage(AlipayBean alipayBean){ //TODO 1、实例化客户端 AlipayClient alipayClient = new DefaultAlipayClient(alipayProperties.getGatewayUrl(), alipayProperties.getAppId(), alipayProperties.getMerchantPrivateKey(), alipayProperties.getFormat(), alipayProperties.getCharset(), alipayProperties.getAlipayPublicKey(), alipayProperties.getSignType()); //TODO 2、实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay //2、创建一个支付请求 //设置请求参数 AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest(); alipayRequest.setReturnUrl(alipayProperties.getReturnUrl()); alipayRequest.setNotifyUrl(alipayProperties.getNotifyUrl()); alipayBean.setTimeout_express(alipayProperties.getTimeoutExpress()); //绝对超时时间,格式为yyyy-MM-dd HH:mm:ss 2016-12-31 10:05:01 //alipayBean.setTime_expire("2020-12-21 17:52:00"); alipayRequest.setBizContent(JSONObject.toJSONString(alipayBean)); String result = ""; try { result = alipayClient.pageExecute(alipayRequest).getBody(); //会收到支付宝的响应,响应的是一个页面,只要浏览器显示这个页面,就会自动来到支付宝的收银台页面 log.info("支付宝的响应:{}",result); } catch (AlipayApiException e) { e.printStackTrace(); throw new BaseException(BaseExceptionEnum.ALIPAY_MSG_ERROR); } return result; } /** * @Description 支付宝提现 * @author lst * @date 2020-12-2 17:04 * @param withdrawBean * @return java.lang.String */ public String withdraw(WithdrawBean withdrawBean){ //提现 //TODO 1、实例化客户端 AlipayClient alipayClient = new DefaultAlipayClient(alipayProperties.getGatewayUrl(), alipayProperties.getAppId(), alipayProperties.getMerchantPrivateKey(), alipayProperties.getFormat(), alipayProperties.getCharset(), alipayProperties.getAlipayPublicKey(), alipayProperties.getSignType()); //TODO 2、实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay AlipayFundTransToaccountTransferRequest alipayRequest = new AlipayFundTransToaccountTransferRequest(); /* "\"out_biz_no\":\"3142321423432\"," + "\"payee_type\":\"ALIPAY_LOGONID\"," + "\"payee_account\":\"[email protected]\"," + "\"amount\":\"12.23\"," + "\"payer_show_name\":\"上海交通卡退款\"," + "\"payee_real_name\":\"张三\"," + "\"remark\":\"转账备注\"" + " }"*/ //商户转账唯一订单号 withdrawBean.setOut_biz_no(DateUtil.getDateTime14()); withdrawBean.setPayee_type("ALIPAY_LOGONID"); withdrawBean.setPayee_account("[email protected]"); withdrawBean.setPayee_real_name("ycknrb8604"); withdrawBean.setAmount("22.4"); withdrawBean.setPayer_show_name(""); withdrawBean.setRemark("推推提现"); String jsonData = JSONObject.toJSONString(withdrawBean); log.info("支付宝提现请求数据:{}",jsonData); alipayRequest.setBizContent(jsonData); //TODO 3、转账/提现 try { AlipayFundTransToaccountTransferResponse response = alipayClient.execute(alipayRequest); log.info("支付宝的响应:{}",JSONObject.toJSON(response)); if(response.isSuccess()){ //提现成功 return "success"; }else { throw new BaseException(BaseExceptionEnum.ALIPAY_WITHDRAW_ERROR); } } catch (AlipayApiException e) { e.printStackTrace(); throw new BaseException(BaseExceptionEnum.ALIPAY_WITHDRAW_ERROR); } } /** * @Description 支付宝退款 * @author lst * @date 2020-12-21 14:12 * @param alipayRefundForm * @return java.lang.String */ public String alipayRefund(AlipayRefundForm alipayRefundForm){ //TODO 1、实例化客户端 AlipayClient alipayClient = new DefaultAlipayClient(alipayProperties.getGatewayUrl(), alipayProperties.getAppId(), alipayProperties.getMerchantPrivateKey(), alipayProperties.getFormat(), alipayProperties.getCharset(), alipayProperties.getAlipayPublicKey(), alipayProperties.getSignType()); AlipayTradeRefundRequest aliPayRequest = new AlipayTradeRefundRequest(); AlipayTradeRefundModel model = new AlipayTradeRefundModel(); //订单支付时传入的商户订单号,不能和 trade_no同时为空 model.setOutTradeNo("b87267c8-435b-449b-9ebb-e12efe06a1dd"); //支付宝交易号,和商户订单号不能同时为空 model.setTradeNo("2020122122001400320501115255"); //需要退款的金额,该金额不能大于订单金额,单位为元,支持两位小数 model.setRefundAmount("93.80"); //退款的原因说明 model.setRefundReason("正常退款"); //标识一次退款请求,同一笔交易多次退款需要保证唯一,如需部分退款,则此参数必传。 model.setOutRequestNo(DateUtil.getDateTime14()); aliPayRequest.setBizModel(model); try { AlipayTradeRefundResponse aliPayResponse = alipayClient.execute(aliPayRequest); log.debug("aliPayResponse:{}", aliPayResponse); if (!"10000".equals(aliPayResponse.getCode())) { log.info("支付宝退款失败,支付宝交易号:{},状态码:{}", "2020122122001400320501115254", aliPayResponse.getCode()); throw new BaseException(aliPayResponse.getSubMsg()); } return aliPayResponse.getMsg(); } catch (AlipayApiException e) { e.printStackTrace(); throw new BaseException("退款失败"); } } }

5.4、支付宝支付配置信息类

package com.example.mybaties.constants; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; /** * @description: 支付宝支付配置信息 * @author: lst * @date: 2020-12-01 15:50 */ @Component @ConfigurationProperties(prefix = "alipay") @Data public class AlipayProperties { /** * 在支付宝创建的应用的id */ private String appId; /** * 商户私钥,您的PKCS8格式RSA2私钥 */ private String merchantPrivateKey; /** * 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。 */ private String alipayPublicKey; /** * 服务器[异步通知]页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 * 支付宝会悄悄的给我们发送一个请求,告诉我们支付成功的信息 */ private String notifyUrl; /** * 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 * 同步通知,支付成功,一般跳转到成功页 */ private String returnUrl; /** * 签名方式 */ private String signType; /** * 字符编码格式 */ private String charset; /** * 支付宝网关; https://openapi.alipaydev.com/gateway.do 正式环境 https://openapi.alipay.com/gateway.do */ private String gatewayUrl; /** * 该笔订单允许的最晚付款时间,逾期将关闭交易 */ private String timeoutExpress; /** * 请求的格式:json */ private String format; }

5.5、网页支付代码orderPage.html、下单成功代码success.html

网页下单 function placeOrder() { var url = "/pay/alipay-page"; $.ajax({ url: url, type: 'POST', dataType: 'JSON', success: function (data) { console.log(data); $('#orderPage').html(data) }, error: function (msg) { } }); } 成功页面 恭喜下单成功 6、打入服务器进行测试

输入网址点击‘提交’ 按钮,后端已经默认支付数据,我用沙箱APP支付成功后可以跳转到成功页面。

手机端也可以测试

HwVideoEditor

想要源码的小伙伴可以下方留言。

 

 

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3