本篇主要是正对Java对接支付宝的常用功能,需要开通个人的沙箱环境和内网穿透(我用了阿里云服务器)。
集成前提:开发者在集成和开发前需要了解一下常用的接入方式和架构建议,如下图所示:
1、登录网页版的个人支付宝
https://auth.alipay.com/login/ant_sso_index.htm
https://opendocs.alipay.com/open/200/105311
alipay:appId: 2016110300790369 #在支付宝创建的应用的idnotifyUrl: 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%3A05signType: RSA2 #签名方式charset: utf-8 #字符编码格式gatewayUrl: https://openapi.alipaydev.com/gateway.do #沙箱环境timeoutExpress: 30mformat: jsonmerchantPrivateKey: # 商户私钥alipayPublicKey: #支付宝公钥
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 {@Autowiredprivate 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 {@Autowiredprivate AlipayUtil alipayUtil;/*** @Description 支付宝下单支付* @author lst* @date 2020-12-1 17:27* @return java.lang.String*/@Overridepublic 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*/@Overridepublic 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*/@Overridepublic 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*/@Overridepublic 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("
}
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 {@Autowiredprivate 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.payAlipayTradeAppPayRequest 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());//这里和普通的接口调用不同,使用的是sdkExecuteAlipayTradeAppPayResponse 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
}
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
输入网址点击‘提交’ 按钮,后端已经默认支付数据,我用沙箱APP支付成功后可以跳转到成功页面。
手机端也可以测试
HwVideoEditor
想要源码的小伙伴可以下方留言。