会议网站定制广州网站建设定制方案
news/
2025/10/2 16:14:19/
文章来源:
会议网站定制,广州网站建设定制方案,西安网站开发定制制作,网站建设与维护论文文章目录 一、介绍1. 支付2. 支付结果 二、前提准备1. 支付宝开放平台2. 内网穿透3. 局域网 三、order微服务1. 依赖、配置2. 工具类1. 二维码生成2. AlipayConfig 3. 端点代码1. /generatepaycode2. /requestpay3. /payresult4. /receivenotify 环境如下
Version手机安卓支付… 文章目录 一、介绍1. 支付2. 支付结果 二、前提准备1. 支付宝开放平台2. 内网穿透3. 局域网 三、order微服务1. 依赖、配置2. 工具类1. 二维码生成2. AlipayConfig 3. 端点代码1. /generatepaycode2. /requestpay3. /payresult4. /receivenotify 环境如下
Version手机安卓支付平台支付宝SpringBoot3.2.1alipay-sdk-java4.38.200.ALL
一、介绍
系统处于开发阶段时无需营业执照无需任何费用沙箱模拟网站在线完整支付流程。
参考资料如下
手机网站支付快速接入alipay.trade.query(统一收单交易查询)异步通知说明
1. 支付
有一个在线网站可以为商品生成支付二维码手机支付宝扫码支付。
支付流程大体如下
2. 支付结果
获取支付结果有两种方法
一种为主动查询。在顾客支付后再查询方可得到正确的结果然而这个时机是无法确定的。一种为被动接收。顾客支付后支付宝服务器向微服务发送消息通知。 二、前提准备
1. 支付宝开放平台 注册支付宝开放平台 https://openhome.alipay.com/ 来到控制台下滑找到沙箱 https://openhome.alipay.com/develop/manage 或者点这里进入沙箱环境 https://openhome.alipay.com/develop/sandbox/app 下载支付宝沙箱版到手机
2. 内网穿透 下载软件 https://hsk.oray.com/download 本文选择的是贝锐花生壳会赠送一个域名。 添加映射 映射类型HTTPS外网端口貌似改不了内网ip:portorder微服务的地址端口。 这样之后谁往https://5m34y83626.vicp.fun/orders/receivenotify发送请求就相当于往order微服务的/orders/receivenotify这个端点发送请求。
3. 局域网
参考这篇文章 同一Wifi下允许手机访问电脑win10
主要目的就是要知道手机通过什么ip可以访问到电脑。本文是192.168.0.102所以访问192.168.0.102:63030就相当于访问到了order微服务。
三、order微服务
1. 依赖、配置 !-- 支付宝SDK --dependencygroupIdcom.alipay.sdk/groupIdartifactIdalipay-sdk-java/artifactIdversion4.38.200.ALL/version/dependency!--生成二维码--dependencygroupIdcom.google.zxing/groupIdartifactIdcore/artifactIdversion3.3.3/version/dependencydependencygroupIdcom.google.zxing/groupIdartifactIdjavase/artifactIdversion3.3.3/version/dependencyserver:servlet:context-path: /ordersport: 63030pay:#扫描二维码得到urlqrcodeurl: http://???:63030/orders/requestpay?payNo%salipay:APP_ID: ???APP_PRIVATE_KEY: ???ALIPAY_PUBLIC_KEY: ??????填充分别为 在同一局域网中手机访问电脑的ip 沙箱环境-沙箱应用-应用信息-基本信息 沙箱环境-沙箱应用-应用信息-开发信息-应用私钥 沙箱环境-沙箱应用-应用信息-开发信息-支付宝公钥
2. 工具类
1. 二维码生成
package com.xuecheng.orders.config;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 com.xuecheng.base.utils.EncryptUtil;
import jakarta.servlet.ServletOutputStream;
import org.apache.commons.lang3.StringUtils;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;/*** author mumu* version 1.0* description 二维码生成工具* date 2024/02/16 14:56*/
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)HashMapEncodeHintType, 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 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();//String qrCode qrCodeUtil.createQRCode(http://10.0.2.2:63030/orders/alipaytest, 200, 200);String qrCode qrCodeUtil.createQRCode(http://192.168.0.102:63030/orders/alipaytest, 200, 200);System.out.println(qrCode);}
}这里的content参数就是指二维码扫出来指向的url在本文中这个url指的是order微服务orders/requestpay端点请求支付。
2. AlipayConfig
package com.xuecheng.orders.config;/*** author mumu* version 1.0* description 支付宝配置参数* date 2024/02/16 14:56*/
public class AlipayConfig {// 服务器异步通知页面路径 需http://或者https://格式的完整路径不能加?id123这类自定义参数必须外网可以正常访问public static String notify_url https://5m34y83626.vicp.fun/orders/receivenotify;// 页面跳转同步通知页面路径 需http://或者https://格式的完整路径不能加?id123这类自定义参数必须外网可以正常访问 商户可以自定义同步跳转地址//public static String return_url http://商户网关地址/alipay.trade.wap.pay-JAVA-UTF-8/return_url.jsp;// 请求网关地址//public static String URL https://openapi.alipaydev.com/gateway.do;public static String URL https://openapi-sandbox.dl.alipaydev.com/gateway.do;// 编码public static String CHARSET UTF-8;// 返回格式public static String FORMAT json;// 日志记录目录public static String log_path /log;// RSA2public static String SIGNTYPE RSA2;
}这里的notify_url 指的是贝锐花生壳给的域名/orders/receivenotify用于支付宝服务器通知我们支付结果。 这里的URL 指的是支付宝网关地址目前沙箱环境用的是固定的https://openapi-sandbox.dl.alipaydev.com/gateway.do如有变更可以去 沙箱环境-沙箱应用-开发信息 校验。
3. 端点代码
1. /generatepaycode
前端点击“前往支付”按钮后携带商品信息向后端发送一个生成支付二维码的请求。后端收到商品信息结合用户信息为他们创建一张订单到数据库包含金额等信息订单号为payNo。
于是我们把这个payNo拼接到二维码所表示的url中当用户扫码后携带订单号前往支付端点。
参考代码如下 Value(${pay.qrcodeurl})private String qrcodeurl;//生成二维码QRCodeUtil qrCodeUtil new QRCodeUtil();String url String.format(qrcodeurl, payNo);String qrCode null;try {qrCode qrCodeUtil.createQRCode(url, 200, 200);} catch (IOException e) {XueChengPlusException.cast(生成二维码失败);}2. /requestpay
后端返回二维码到前端拿起手机打开支付宝沙箱版登录。 账号密码在 沙箱环境-沙箱账号-买家信息 登录后拿起扫一扫二维码会请求形如http://192.168.0.102:63030/orders/requestpay?payNo1758388376771436544也就是请求到/requestpay端点。后端从数据库取出订单信息比如金额等填入bizContent 作为支付宝api必要数据。
参考代码如下 Value(${pay.alipay.APP_ID})String APP_ID;Value(${pay.alipay.APP_PRIVATE_KEY})String APP_PRIVATE_KEY;Value(${pay.alipay.ALIPAY_PUBLIC_KEY})String ALIPAY_PUBLIC_KEY;RequestMapping(/requestpay)public void requestpay(String payNo, HttpServletResponse httpResponse) throws AlipayApiException, IOException {//约束XcPayRecord payRecord orderService.getPayRecordByPayNo(payNo);if (payRecord null){XueChengPlusException.cast(支付记录不存在异常);}if (601002.equals(payRecord.getStatus())){XueChengPlusException.cast(已支付无需重复支付);}//获得初始化的AlipayClientAlipayClient alipayClient new DefaultAlipayClient(AlipayConfig.URL, APP_ID, APP_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, ALIPAY_PUBLIC_KEY,AlipayConfig.SIGNTYPE);//创建API对应的requestAlipayTradeWapPayRequest alipayRequest new AlipayTradeWapPayRequest();//在公共参数中设置回跳和通知地址alipayRequest.setNotifyUrl(AlipayConfig.notify_url);//alipayRequest.setReturnUrl(AlipayConfig.return_url);JSONObject bizContent new JSONObject();//商户订单号商家自定义保持唯一性bizContent.put(out_trade_no, payNo);//支付金额最小值0.01元bizContent.put(total_amount, payRecord.getTotalPrice());//订单标题不可使用特殊符号bizContent.put(subject, payRecord.getOrderName());bizContent.put(product_code, QUICK_WAP_WAY);alipayRequest.setBizContent(bizContent.toString());//填充业务参数String form alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单httpResponse.setContentType(text/html;charset AlipayConfig.CHARSET);httpResponse.getWriter().write(form);//直接将完整的表单html输出到页面httpResponse.getWriter().flush();}后端把form 返回到手机这个form会唤起支付功能手机上完成支付支付宝服务端就会收到请求。
3. /payresult
现在订单支付完了怎么知道支付结果呢一种是主动查询需要当时向支付宝服务器发送支付请求时填入的out_trade_no也就是payNo。可以设计一个前端按钮“查询支付结果”发送请求到后端/payresult端点后端主动携带payNo去支付宝服务器请求结果。
参考代码如下 Value(${pay.alipay.APP_ID})String APP_ID;Value(${pay.alipay.APP_PRIVATE_KEY})String APP_PRIVATE_KEY;Value(${pay.alipay.ALIPAY_PUBLIC_KEY})String ALIPAY_PUBLIC_KEY;//查询支付状态//获得初始化的AlipayClientAlipayClient alipayClient new DefaultAlipayClient(AlipayConfig.URL, APP_ID, APP_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET, ALIPAY_PUBLIC_KEY,AlipayConfig.SIGNTYPE);//创建API对应的requestAlipayTradeQueryRequest alipayRequest new AlipayTradeQueryRequest();JSONObject bizContent new JSONObject();//商户订单号商家自定义保持唯一性bizContent.put(out_trade_no, payNo);alipayRequest.setBizContent(bizContent.toString());//填充业务参数AlipayTradeQueryResponse response null;try {response alipayClient.execute(alipayRequest);} catch (AlipayApiException e) {XueChengPlusException.cast(查询支付宝支付状态失败);}//解析支付结果PayStatusDto payStatusDto new PayStatusDto();payStatusDto.setOut_trade_no(payNo);payStatusDto.setTrade_no(response.getTradeNo());payStatusDto.setTrade_status(response.getTradeStatus());payStatusDto.setApp_id(APP_ID);payStatusDto.setTotal_amount(response.getTotalAmount());return payStatusDto;然后可以根据response.getTradeStatus()的值校验是否支付成功然后编写后续业务代码。
4. /receivenotify
除了主动查询支付结果之外还可以定义端点让支付宝服务端异步通知我们。支付宝服务器在公网所以我们也需要一个公网来接收它的请求利用内网穿透技术把我们的/receivenotify端点暴露到公网并指定notify_url来告知支付宝服务端该向哪里发起异步通知指定notify_url在/requestpay那一步完成。
参考代码 Value(${pay.alipay.APP_ID})String APP_ID;Value(${pay.alipay.APP_PRIVATE_KEY})String APP_PRIVATE_KEY;Value(${pay.alipay.ALIPAY_PUBLIC_KEY})String ALIPAY_PUBLIC_KEY;PostMapping(/receivenotify)public void receivenotify(HttpServletRequest request,HttpServletResponse response) throws AlipayApiException, IOException {MapString,String params new HashMapString,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);}//获取支付宝的通知返回参数可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)////计算得出通知验证结果//boolean AlipaySignature.rsaCheckV1(MapString, String params, String publicKey, String charset, String sign_type)boolean verify_result AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, AlipayConfig.SIGNTYPE);if(verify_result) {//验证成功////请在这里加上商户的业务逻辑程序代码//商户订单号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);//交易金额String total_amount new String(request.getParameter(total_amount).getBytes(ISO-8859-1), UTF-8);//——请根据您的业务逻辑来编写程序以下代码仅作参考——if (trade_status.equals(TRADE_SUCCESS)) {PayStatusDto payStatusDto new PayStatusDto();payStatusDto.setOut_trade_no(out_trade_no);payStatusDto.setTrade_no(trade_no);payStatusDto.setTrade_status(trade_status);//app_id和total_amount可以不填payStatusDto.setApp_id(APP_ID);payStatusDto.setTotal_amount(total_amount);System.out.println(payStatusDto);orderService.saveAliPayStatus(payStatusDto);}System.out.println(success);response.getWriter().write(success);}else{response.getWriter().write(支付情况校验失败);}}完。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/925070.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!