支付宝当面付扫码支付下单以及回调(证书模式)

支付宝当面付扫码支付下单以及回调(证书模式)支付宝当面付扫码支付 证书模式 支付下单生成二维码以及支付回调 支付宝当面付开发

大家好,欢迎来到IT知识分享网。

支付宝当面付扫码支付(证书模式)

前言:自己对接时的成功代码,其中验签为支付宝技术支持提供

一、官网:

1、支付宝开放平台:https://open.alipay.com

2、当面付开发者文档:https://opendoc.alipay.com/open-v3/05pf4i?pathHash=d7773c48

3、沙箱控制台环境:https://open.alipay.com/develop/sandbox/app

二、引入依赖:

<!--支付宝支付SDK--> <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>4.39.190.ALL</version> </dependency> <!--生成二维码--> <dependency> <groupId>com.google.zxing</groupId> <artifactId>javase</artifactId> <version>3.0.0</version> </dependency> 

三、配置文件:

请将以下参数替换为你自己的实际参数

alibaba: pay: #网关:沙箱网关(正式网关:https://openapi.alipay.com/gateway.do) gatewayHost: https://openapi-sandbox.dl.alipaydev.com/gateway.do appId: #APPID sellerId: #商家PID appPrivateKey: #应用私钥 appCertPublicKey: #应用公钥证书的存放路径 alipayCertPublicKey: #支付宝公钥证书存放路径 alipayRootCert: #支付宝根证书存放路径 notifyUrl: #回调地址(必须为https且公网可以访问的接口地址) 

四、支付方法:

注意:请求支付下单成功后记得编写自己的订单逻辑

import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.AlipayConfig; import com.alipay.api.DefaultAlipayClient; import com.alipay.api.domain.AlipayTradePrecreateModel; import com.alipay.api.request.AlipayTradePrecreateRequest; import com.alipay.api.response.AlipayTradePrecreateResponse; import com.yunjianlaike.common.utils.file.QRImageUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.io.File; / * @Author: Zacc * @Desc: 简单支付宝支付 * @DateTime: 2024/9/3 15:32 */ @Component public class AliPay { 
    @Value("${alibaba.pay.gatewayHost}") private String gatewayHost; @Value("${alibaba.pay.appId}") private String appId; @Value("${alibaba.pay.appPrivateKey}") private String appPrivateKey; @Value("${alibaba.pay.appCertPublicKey}") private String appCertPublicKey; @Value("${alibaba.pay.alipayCertPublicKey}") private String alipayCertPublicKey; @Value("${alibaba.pay.alipayRootCert}") private String alipayRootCert; @Value("${alibaba.pay.notifyUrl}") private String notifyUrl; public String pay(ShrOrder order) throws AlipayApiException { 
    //构造支付配置 AlipayConfig alipayConfig = new AlipayConfig(); alipayConfig.setAppId(appId); alipayConfig.setAlipayPublicCertPath(alipayCertPublicKey); alipayConfig.setRootCertPath(alipayRootCert); alipayConfig.setAppCertPath(appCertPublicKey); alipayConfig.setPrivateKey(appPrivateKey); alipayConfig.setServerUrl(gatewayHost); alipayConfig.setFormat("json"); alipayConfig.setCharset("UTF8"); alipayConfig.setSignType("RSA2"); AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig); AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest(); AlipayTradePrecreateModel model = new AlipayTradePrecreateModel(); //设置支付参数 //自己生成的订单号(必须保证同一个商家号中唯一,这里使用统一前缀+当前时间的毫秒值) model.setOutTradeNo("out_trade_no_"+ System.currentTimeMillis()); model.setSubject("测试订单"); //订单金额(精确到小数后两位,并且需要转换成字符串) model.setTotalAmount("10.00"); //设置超时时间 model.setTimeoutExpress("3m"); request.setBizModel(model); //设置回调地址 request.setNotifyUrl(notifyUrl); AlipayTradePrecreateResponse response = alipayClient.certificateExecute(request); if (response.isSuccess()) { 
    //根据成功响应中的QrCode生成验证码图片Url返回给前端 String qrCode = response.getQrCode(); String image = QRImageUtils.getQRImage(qrCode); return image; } return null; } } 
import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatWriter; import com.google.zxing.common.BitMatrix; import java.util.Base64; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.util.HashMap; import java.util.Map; / * @Author: Zacc * @Desc: 二维码工具类 * @DateTime: 2024/9/3 15:32 */ public class QRImageUtils { 
    // 二维码需要使用到的颜色 private static final int BLACK = 0xFF000000; private static final int WHITE = 0xFFFFFFFF; //你的二维码存放路径 private static final String imgPath = "/usr/local/qrcode/"; public static String getQRImage(String QrCodeStr) { 
    try{ 
    // 生成的二维码名称 String imgName = "QrCodeStr"+ System.currentTimeMillis() +".jpg"; // 创建二维码try { 
    Map<EncodeHintType, String> charcter = new HashMap<>(); // 设置字符集 charcter.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 设置二维码的四个参数 需要生成的字符串,类型设置为二维码,二维码宽度,二维码高度,字符串字符集 BitMatrix bitMatrix = new MultiFormatWriter() .encode(QrCodeStr, BarcodeFormat.QR_CODE, 500, 500, charcter); // 创建文件对象 File file = new File(imgPath, imgName); if (!file.getParentFile().exists()) { 
    file.getParentFile().mkdirs(); } // 二维码像素,也就是上面设置的 500 int width = bitMatrix.getWidth(); int height = bitMatrix.getHeight(); // 创建二维码对象 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); for (int x = 0; x < width; x++) { 
    for (int y = 0; y < height; y++) { 
    // 按照上面定义好的二维码颜色编码生成二维码 image.setRGB(x, y, bitMatrix.get(x, y) ? BLACK : WHITE); } } // 1、第一种方式// 生成的二维码图片对象转 base64 ByteArrayOutputStream stream = new ByteArrayOutputStream(); // 设置图片的格式 ImageIO.write(image, "png", stream); String base64 = Base64.getEncoder().encodeToString(stream.toByteArray()); // 输出转换成功后的base64编码 System.out.println(base64); // 2、第二种方式 // 直接输出二维码文件 ImageIO.write(image, "jpg", file); return imgPath + imgName; } catch (Exception e) { 
    e.printStackTrace(); } return "验证码生成异常"; } } 

五、支付异步回调:

使用官方文档上的验签方法一直验签失败,无奈只能求助支付宝技术支持,其中的验签方法为支付宝技术支持提供

package com.yunjianlaike.web.controller.share; import com.alibaba.fastjson2.JSONObject; import com.alibaba.fastjson2.TypeReference; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayConstants; import com.alipay.api.internal.util.AlipaySignature; import com.wechat.pay.contrib.apache.httpclient.util.AesUtil; import com.yunjianlaike.share.pay.HttpUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; import java.util.*; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; import java.util.stream.Stream; / * @Author: Zacc * @Desc: 支付回调 * @DateTime: 2024/8/26 9:23 */ @Slf4j @RestController public class NotifyController { 
    @Value("${alibaba.pay.certPath}") private String certPath; private final ReentrantLock lock = new ReentrantLock(); / * Desc: 支付宝支付回调 * * @param request * @param response * @return: void */ @PostMapping("/aliNotify") public String aliNotify(HttpServletRequest request, HttpServletResponse response) { 
    System.out.println(response); if (lock.tryLock()) { 
    try { 
    //参数拼接(此方法为支付宝技术支持提供) Map<String, String[]> requestParams = request.getParameterMap(); StringBuffer buffer = new StringBuffer(); requestParams.forEach((key, val) -> buffer.append(key).append("=").append(val[0]).append("&")); String resultInfo = buffer.toString(); resultInfo = resultInfo.substring(0, resultInfo.length() - 1); //对待签名字符串数据通过&进行拆分 String[] temp = resultInfo.split("&"); LinkedHashMap<String, String> params = new LinkedHashMap<>(); //把拆分数据放在map集合内 for (int i = 0; i < temp.length; i++) { 
    String[] arr = temp[i].split("=", 2); //通过"="号分割成2个数据 String[] tempAagin = new String[arr.length]; //再开辟一个数组用来接收分割后的数据 for (int j = 0; j < arr.length; j++) { 
    tempAagin[j] = arr[j]; } params.put(tempAagin[0], tempAagin[1]); } //验签方法(证书验签) boolean signVerified = AlipaySignature.rsaCertCheckV1(params, certPath, AlipayConstants.CHARSET_UTF8, AlipayConstants.SIGN_TYPE_RSA2); if (signVerified) { 
    //商户订单号,之前生成的带用户ID的订单号 String outTradeNo = new String(params.get("out_trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); //支付宝交易号 String tradeNo = new String(params.get("trade_no").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); //交易状态 String tradeStatus = new String(params.get("trade_status").getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); //TODO根据交易状态进行幂等操作,避免数据重入(支付回调会每隔几秒调用) } else { 
    return "fail"; } } catch (AlipayApiException e) { 
    throw new RuntimeException(e); } finally { 
    //要主动释放锁 lock.unlock(); } } return "success"; } } 

根据公钥证书文件获取公钥:

String alipaypublicKey = AlipaySignature.getAlipayPublicKey("/opt/module/office/alipayCertPublicKey_RSA2.crt"); 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/153058.html

(0)
上一篇 2025-03-06 14:05
下一篇 2025-03-06 14:10

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信