当前位置: 首页 > news >正文

支付宝支付详细流程

1、二维码的生成

  • 二维码生成坐标

<!-- zxing生成二维码 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.3.3</version></dependency><dependency><groupId>com.google.zxing</groupId><artifactId>javase</artifactId><version>3.3.3</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.4</version>
  • 二维码生成工具类①

package com.xuechengpluscommon.utils;import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.apache.commons.lang3.StringUtils;import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;/*** @author Mr.M* @version 1.0* @description 二维码生成工具* @date 2022/10/3 0:03*/
public class QRCodeUtil {/*** 生成二维码** @param content 二维码对应的URL* @param width   二维码图片宽度* @param height  二维码图片高度* @return*/public String createQRCode(String content, int width, int height) throws IOException {String resultImage = "";//除了尺寸,传入内容不能为空if (!StringUtils.isEmpty(content)) {ServletOutputStream stream = null;ByteArrayOutputStream os = new ByteArrayOutputStream();//二维码参数@SuppressWarnings("rawtypes")HashMap<EncodeHintType, Comparable> hints = new HashMap<>();//指定字符编码为“utf-8”hints.put(EncodeHintType.CHARACTER_SET, "utf-8");//L M Q H四个纠错等级从低到高,指定二维码的纠错等级为M//纠错级别越高,可以修正的错误就越多,需要的纠错码的数量也变多,相应的二维吗可储存的数据就会减少hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);//设置图片的边距hints.put(EncodeHintType.MARGIN, 1);try {//zxing生成二维码核心类QRCodeWriter writer = new QRCodeWriter();//把输入文本按照指定规则转成二维吗BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, width, height, hints);//生成二维码图片流BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix);//输出流ImageIO.write(bufferedImage, "png", os);/*** 原生转码前面没有 data:image/png;base64 这些字段,返回给前端是无法被解析,所以加上前缀*/resultImage = new String("data:image/png;base64," + EncryptUtil.encodeBase64(os.toByteArray()));return resultImage;} catch (Exception e) {e.printStackTrace();throw new RuntimeException("生成二维码出错");} finally {if (stream != null) {stream.flush();stream.close();}}}return null;}public static void main(String[] args) throws IOException {QRCodeUtil qrCodeUtil = new QRCodeUtil();System.out.println(qrCodeUtil.createQRCode("http://192.168.101.1:63030/orders/alipaytest", 200, 200));}
}
  • 二维码生成工具类②

package com.xuechengpluscommon.utils;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Base64;public class EncryptUtil {private static final Logger logger = LoggerFactory.getLogger(EncryptUtil.class);public static String encodeBase64(byte[] bytes){String encoded = Base64.getEncoder().encodeToString(bytes);return encoded;}public static byte[]  decodeBase64(String str){byte[] bytes = null;bytes = Base64.getDecoder().decode(str);return bytes;}public static String encodeUTF8StringBase64(String str){String encoded = null;try {encoded = Base64.getEncoder().encodeToString(str.getBytes("utf-8"));} catch (UnsupportedEncodingException e) {logger.warn("不支持的编码格式",e);}return encoded;}public static String  decodeUTF8StringBase64(String str){String decoded = null;byte[] bytes = Base64.getDecoder().decode(str);try {decoded = new String(bytes,"utf-8");}catch(UnsupportedEncodingException e){logger.warn("不支持的编码格式",e);}return decoded;}public static String encodeURL(String url) {String encoded = null;try {encoded =  URLEncoder.encode(url, "utf-8");} catch (UnsupportedEncodingException e) {logger.warn("URLEncode失败", e);}return encoded;}public static String decodeURL(String url) {String decoded = null;try {decoded = URLDecoder.decode(url, "utf-8");} catch (UnsupportedEncodingException e) {logger.warn("URLDecode失败", e);}return decoded;}public static void main(String [] args){String str = "abcd{'a':'b'}";String encoded = EncryptUtil.encodeUTF8StringBase64(str);String decoded = EncryptUtil.decodeUTF8StringBase64(encoded);System.out.println(str);System.out.println(encoded);System.out.println(decoded);String url = "== wo";String urlEncoded = EncryptUtil.encodeURL(url);String urlDecoded = EncryptUtil.decodeURL(urlEncoded);System.out.println(url);System.out.println(urlEncoded);System.out.println(urlDecoded);}}
  • 测试生成二维码

@Testvoid contextLoads() {try {String helloWorld = new QRCodeUtil().createQRCode("http://d6nt2p.natappfree.cc/pay/test", 200, 200);System.out.println(helloWorld);} catch (IOException e) {e.printStackTrace();}}
  • 结果(二维码内容如果是网址则会跳转,如果是接口,则返回接口数据)

2、订单号生成工具类

package com.xuechengpluscommon.utils;import java.util.Random;/*** snow flow .**/
public final class IdWorkerUtils {private static final Random RANDOM = new Random();private static final long WORKER_ID_BITS = 5L;private static final long DATACENTERIDBITS = 5L;private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);private static final long MAX_DATACENTER_ID = ~(-1L << DATACENTERIDBITS);private static final long SEQUENCE_BITS = 12L;private static final long WORKER_ID_SHIFT = SEQUENCE_BITS;private static final long DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;private static final long TIMESTAMP_LEFT_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTERIDBITS;private static final long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS);private static final IdWorkerUtils ID_WORKER_UTILS = new IdWorkerUtils();private long workerId;private long datacenterId;private long idepoch;private long sequence = '0';private long lastTimestamp = -1L;private IdWorkerUtils() {this(RANDOM.nextInt((int) MAX_WORKER_ID), RANDOM.nextInt((int) MAX_DATACENTER_ID), 1288834974657L);}private IdWorkerUtils(final long workerId, final long datacenterId, final long idepoch) {if (workerId > MAX_WORKER_ID || workerId < 0) {throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", MAX_WORKER_ID));}if (datacenterId > MAX_DATACENTER_ID || datacenterId < 0) {throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", MAX_DATACENTER_ID));}this.workerId = workerId;this.datacenterId = datacenterId;this.idepoch = idepoch;}/*** Gets instance.** @return the instance*/public static IdWorkerUtils getInstance() {return ID_WORKER_UTILS;}public synchronized long nextId() {long timestamp = timeGen();if (timestamp < lastTimestamp) {throw new RuntimeException(String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));}if (lastTimestamp == timestamp) {sequence = (sequence + 1) & SEQUENCE_MASK;if (sequence == 0) {timestamp = tilNextMillis(lastTimestamp);}} else {sequence = 0L;}lastTimestamp = timestamp;return ((timestamp - idepoch) << TIMESTAMP_LEFT_SHIFT)| (datacenterId << DATACENTER_ID_SHIFT)| (workerId << WORKER_ID_SHIFT) | sequence;}private long tilNextMillis(final long lastTimestamp) {long timestamp = timeGen();while (timestamp <= lastTimestamp) {timestamp = timeGen();}return timestamp;}private long timeGen() {return System.currentTimeMillis();}/*** Build part number string.** @return the string*/public String buildPartNumber() {return String.valueOf(ID_WORKER_UTILS.nextId());}/*** Create uuid string.** @return the string*/public String createUUID() {return String.valueOf(ID_WORKER_UTILS.nextId());}public static void main(String[] args) {System.out.println(IdWorkerUtils.getInstance().nextId());}
}

3、导入阿里支付坐标

<dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-sdk-java</artifactId><version>4.34.0.ALL</version>
</dependency>

这里需要三个重要的数据:(沙箱模式或者已是商户才可以拥有)

  1. APPID(appid)

  1. RSA_PRIVATE_KEY(应用密匙)

  1. ALIPAY_PUBLIC_KEY(应用公匙)

4、进行订单支付(被动获取订单支付状态)

详细地址:电脑网站支付快速接入 - 支付宝文档中心 (alipay.com)

 @RequestMapping("/aliyuntest/pc")public void aliyuntest (HttpServletRequest httpRequest,HttpServletResponse httpResponse)   throws  ServletException, IOException  {AlipayClient alipayClient =  new  DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);  //获得初始化的AlipayClientAlipayTradePagePayRequest alipayRequest =  new  AlipayTradePagePayRequest(); //创建API对应的request
//        alipayRequest.setReturnUrl( "http://192.168.31.196:63100/pay/payNotify" );alipayRequest.setNotifyUrl( "http://d6nt2p.natappfree.cc/pay/payNotify" ); //在公共参数中设置回跳和通知地址alipayRequest.setBizContent( "{"  +"    \"out_trade_no\":\"2012523432526230\","  +"    \"product_code\":\"FAST_INSTANT_TRADE_PAY\","  +"    \"total_amount\":5688.88,"  +"    \"subject\":\"Iphone14pro 8+256G\","  +"    \"body\":\"Iphone14pro 8+256G\","  +"    \"passback_params\":\"merchantBizType%3d3C%26merchantBizNo%2012523432526230\","  +"    \"extend_params\":{"  +"    \"sys_service_provider_id\":\"201413352010\""  +"    }" +"  }" ); //填充业务参数String form= "" ;try  {form = alipayClient.pageExecute(alipayRequest).getBody();  //调用SDK生成表单}  catch  (AlipayApiException e) {e.printStackTrace();}httpResponse.setContentType( "text/html;charset="  + AlipayConfig.CHARSET);httpResponse.getWriter().write(form); //直接将完整的表单html输出到页面httpResponse.getWriter().flush();httpResponse.getWriter().close();}
  • alipayRequest.setBizContent()的内容可以自己进行替换

  • alipayRequest.setNotifyUrl()里面的地址必须公网也可以访问,即意味着无法使用本地服务器路径,这里使用内网穿透

  • 详细地址:(4条消息) 使用natapp实现内网穿透详细教程_小龙Hibernation的博客-CSDN博客

  • 接口测试:

5、主动获取订单支付状态

@GetMapping("/queryPayResult")@ResponseBodypublic String queryPayResult() throws AlipayApiException {AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.URL,AlipayConfig.APPID,AlipayConfig.RSA_PRIVATE_KEY,AlipayConfig.FORMAT,AlipayConfig.CHARSET,AlipayConfig.ALIPAY_PUBLIC_KEY,AlipayConfig.SIGNTYPE);AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();JSONObject bizContent = new JSONObject();bizContent.put("out_trade_no", "2012523432526225");
//bizContent.put("trade_no", "2023021722001443820502204183");request.setBizContent(bizContent.toString());AlipayTradeQueryResponse response = alipayClient.execute(request);System.out.println("____________________________________");String body = response.getBody();System.out.println("____________________________________");if(response.isSuccess()){System.out.println("调用成功");} else {System.out.println("调用失败");}return body;}

将商品Id输入之后便可查询结果

6、被动获取订单支付结果

@RequestMapping("/payNotify")public void payNotify(HttpServletRequest request,HttpServletResponse response) throws IOException, AlipayApiException {Map<String,String> params = new HashMap<String,String>();Map requestParams = request.getParameterMap();for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {String name = (String) iter.next();String[] values = (String[]) requestParams.get(name);String valueStr = "";for (int i = 0; i < values.length; i++) {valueStr = (i == values.length - 1) ? valueStr + values[i]: valueStr + values[i] + ",";}//乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");params.put(name, valueStr);}//获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)////商户订单号String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");//支付宝交易号String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");//交易状态String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");//获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)////计算得出通知验证结果//boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)boolean verify_result = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, "RSA2");if(verify_result){//验证成功////请在这里加上商户的业务逻辑程序代码//——请根据您的业务逻辑来编写程序(以下代码仅作参考)——if(trade_status.equals("TRADE_FINISHED")){//判断该笔订单是否在商户网站中已经做过处理//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序//请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的//如果有做过处理,不执行商户的业务程序//注意://如果签约的是可退款协议,退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知//如果没有签约可退款协议,那么付款完成后,支付宝系统发送该交易状态通知。} else if (trade_status.equals("TRADE_SUCCESS")){//判断该笔订单是否在商户网站中已经做过处理//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序//请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的//如果有做过处理,不执行商户的业务程序log.info("=========================支付成功=========================");//注意://如果签约的是可退款协议,那么付款完成后,支付宝系统发送该交易状态通知。}//——请根据您的业务逻辑来编写程序(以上代码仅作参考)——response.getWriter().println("success");//请不要修改或删除//}else{//验证失败response.getWriter().println("fail");}
http://www.lryc.cn/news/11430.html

相关文章:

  • TCP 的演化史-fast retransmit/recovery
  • CSS基础选择器,你认识多少?
  • ChatGPT入门案例|商务智能对话客服(三)
  • Matlab 最小二乘法拟合平面(SVD)
  • AtCoder Regular Contest 126 D题题解
  • Android R WiFi热点流程浅析
  • 【C++进阶】二、多态详解(总)
  • node-sass@4.14.1 包含风险, 如何升级依赖至 dart-sass
  • DataWhale 大数据处理技术组队学习task2
  • 一文读懂select、poll、epoll的用法
  • 《C陷阱与缺陷》----词法“陷阱”
  • 千锋教育+计算机四级网络-计算机网络学习-04
  • 蓝桥杯算法训练合集十四 1.P08052.P07053.同余方程4.P08015.ascii应用
  • 判断字符串中的字符的类型isdecimal();isalpha();isdigit();isalnum()
  • VSCode远程调试Linux代码,python解释器配置
  • 03:入门篇 - CTK Plugin Framework 基本原理
  • 面试攻略,Java 基础面试 100 问(九)
  • JavaScript 代码不嵌套主义
  • 使用默认参数的4大要点
  • Linux文件系统中的硬链接及常见面试题
  • opencv-StereoBM算法
  • 图像分类竞赛进阶技能:OpenAI-CLIP使用范例
  • Metasploit框架基础(一)
  • pytorch零基础实现语义分割项目(二)——标签转换与数据加载
  • python(8.5)--列表习题
  • rt-thread pwm 多通道
  • C语言练习 | 初学者经典练习汇总
  • 华为OD机试 - 自动曝光(Python) | 机试题算法思路 【2023】
  • 「6」线性代数(期末复习)
  • 1.1 硬件与micropython固件烧录及自编译固件