文章目录
- 一 技术准备
- 1.1 二维码技术(java)
- 1.2 支付宝沙箱环境准备
- 1.3 内网穿透
- 二 支付宝支付相关知识
- 2.1 各种支付方式
- 2.2 扫码付接入流程
- 2.3 系统交互流程(时序图)
- 2.4 加密逻辑
- 三 扫码支付实现
- 3.1 添加maven依赖(Easy版)
- 3.2 完善配置文件和配属属性类
- 3.3 扫码支付controller实现
- 3.4 运行结果
一 技术准备
1.1 二维码技术(java)
-
二维码 (dimensional barcode) ,又称二维条码,是在一维条码的基础上扩展出的一种具有可读性的条码。
-
设备扫描二维条码,通过识别条码的长度和宽度中所记载的二进制数据,可获取其中所包含的信息
-
总之:二维码是信息的载体
-
纠错级别: L、M、Q、H 由低到高。
- 低级别的像素块更大,可以远距离识别,但是遮挡就会造成无法识别。
- 高级别则相反,像素块小,允许遮挡一定范围,但是像素块更密集。
QrConfig config = new QrConfig(); config.setErrorCorrection(ErrorCorrectionLevel.H);
- Hutool是一个Java工具包类库,对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装,组成各种Util工具类。
- 实现步骤:
- 导入maven依赖
<dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.3.3</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.5</version></dependency>
- 生成二维码
public static void main(String[] args) {QrConfig config = new QrConfig();config.setErrorCorrection(ErrorCorrectionLevel.H);config.setBackColor(Color.WHITE); // 设置背景颜色config.setForeColor(Color.blue); // 设置前景色config.setWidth(500);config.setHeight(500);QrCodeUtil.generate("yuanyou.blog.csdn.net",config,new File("path\\res.jpg"));}
1.2 支付宝沙箱环境准备
- 沙箱环境:沙箱环境是协助开发者进行接口开发及主要功能联调的模拟环境
- 通过支付宝账号登录 支付宝开放平台
- 在控制台找到沙箱管理,手机、平板下载沙箱APP(沙箱环境目前只支持Android环境安装)
- 使用沙箱账号进行的登录(有时候会出现错误,请多次尝试),账号和密码在沙箱账号页面有提供
1.3 内网穿透
- 参看window使用cpolar实现内网穿透
- 在支付包的通知回调地址会使用该公网IP(支付宝无法访问私网IP)
二 支付宝支付相关知识
- 支付宝开放平台
2.1 各种支付方式
-
扫一扫支付:用户可以通过支付宝app的“扫一扫”功能,扫描商家的二维码进行支付,或者向商家展示自己的付款码供商家扫描。
-
付款码支付:用户打开支付宝app,展示付款码,由商家扫描用户的付款码完成交易。
-
条形码支付:用户展示支付宝app内的条形码,由商家扫描进行支付。
-
蓝牙支付:借助蓝牙技术,用户可以在支持蓝牙支付的设备附近完成支付。
-
在线支付(网页或APP内):在线购物时,选择支付宝作为支付方式,在跳转到支付宝支付页面后登录账户并确认支付。
-
面部识别支付:在具备面部识别功能的设备上,用户可以通过扫描面部信息来完成支付,称为“刷脸支付”。
-
NFC支付:利用近场通讯(NFC)技术,用户只需将手机靠近支持NFC功能的POS机即可完成支付。
2.2 扫码付接入流程
2.3 系统交互流程(时序图)
2.4 加密逻辑
非对称加密:
- 公钥:加密、验签
- 私钥:解密、签名
- 支付宝公钥加密、应用私钥签名
- 支付宝私钥解密、应用公钥验签
- 支付宝请求加密解密过程
- 支付宝响应加密解密过程
- 应用公钥加密,支付宝私钥签名
- 支付宝公钥验签,应用私钥解密
三 扫码支付实现
3.1 添加maven依赖(Easy版)
- 两个版本SDK:easy版和通用版
- Easy版maven地址
<!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-easysdk --> <dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-easysdk</artifactId><version>2.2.3</version> </dependency>
- 通用版maven地址
<dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-sdk-java</artifactId><version>4.38.183.ALL</version> </dependency>
3.2 完善配置文件和配属属性类
需要的信息和获取方式:
- 沙箱应用APPID
- 应用私钥,应用公钥
- 通知回调地址,
使用coplar生成的https地址+/notify接口
- 在application.yml中添加配置
alipay:easy:protocol: httpsgatewayHost: openapi-sandbox.dl.alipaydev.comsignType: RSA2appId: #沙箱应用的APPIDmerchantPrivateKey: #应用私钥alipayPublicKey: # 支付宝公钥notifyUrl: https://xxx.r6.cpolar.top/notify
- 创建文件
AliPayProperties.java
import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration;@Configuration @Data @ConfigurationProperties(prefix = "alipay.easy") public class AliPayProperties {//请求协议private String protocol;// 请求网关private String gatewayHost;// 签名类型 RSA2private String signType;// 应用IDprivate String appId;// 应用私钥private String merchantPrivateKey;// 支付宝公钥private String alipayPublicKey;// 异步通知接收服务地址private String notifyUrl;// 设置AES密钥private String encryptKey; }
AlipayConfig.java
import com.alipay.easysdk.kernel.Config; import com.itheima.alipay.prop.AliPayProperties; import lombok.Data; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;@Configuration @Data public class AlipayConfig {@Beanpublic Config config(AliPayProperties payProperties) {Config config = new Config();config.protocol = payProperties.getProtocol();config.gatewayHost = payProperties.getGatewayHost();config.signType = payProperties.getSignType();config.appId = payProperties.getAppId();config.merchantPrivateKey = payProperties.getMerchantPrivateKey();config.alipayPublicKey = payProperties.getAlipayPublicKey();//可设置异步通知接收服务地址(可选)config.notifyUrl = payProperties.getNotifyUrl();config.encryptKey = "";return config;} }
3.3 扫码支付controller实现
import cn.hutool.extra.qrcode.QrCodeUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.easysdk.factory.Factory;
import com.alipay.easysdk.kernel.Config;
import com.alipay.easysdk.payment.common.models.AlipayTradeQueryResponse;
import com.alipay.easysdk.payment.facetoface.models.AlipayTradePrecreateResponse;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.io.File;@RestController
@Slf4j
@AllArgsConstructor
public class EasyPayController {private final Config alipayConfig;@GetMapping("/pay")public String pay() throws Exception {Factory.setOptions(alipayConfig);//调用支付宝接口AlipayTradePrecreateResponse response = Factory.Payment.FaceToFace().preCreate("rtx 4090 24G", "1656235762657645", "20000");//解析结果String httpBody = response.getHttpBody();//转JSON对象JSONObject jsonObject = JSONObject.parseObject(httpBody);String qrUrl = jsonObject.getJSONObject("alipay_trade_precreate_response").get("qr_code").toString();//生成二维码QrCodeUtil.generate(qrUrl,300,300,new File("C:\\res.jpg"));return httpBody;}@PostMapping("/notify")public String notify(HttpServletRequest request){log.info("收到支付成功通知");String out_trade_no = request.getParameter("out_trade_no");log.info("流水号:{}",out_trade_no);//TODO 后续业务流程return "success";}@GetMapping("/query")public String query() throws Exception {Factory.setOptions(alipayConfig);AlipayTradeQueryResponse response = Factory.Payment.Common().query("1656235762657645");return response.getHttpBody();}
}
3.4 运行结果
2024-01-07 21:30:49.127 INFO 6628 --- [nio-8080-exec-3] c.i.alipay.controller.EasyPayController : 收到支付成功通知
2024-01-07 21:30:49.128 INFO 6628 --- [nio-8080-exec-3] c.i.alipay.controller.EasyPayController : 流水号:1656235762657645
- 访问
localhost:8080/query
即可查询到付款成功的结果
{"alipay_trade_query_response": {"code": "10000","msg": "Success","buyer_logon_id": "hro***@sandbox.com","buyer_pay_amount": "20000.00","buyer_user_id": "2088722025453088","buyer_user_type": "PRIVATE","fund_bill_list": [{"amount": "20000.00","fund_channel": "ALIPAYACCOUNT"}],//...
}
- 沙箱环境的支付宝中可以查询到支付记录