手把手带你服务端实现支付功能的通用解决方案!(全网最新)

news2024/11/26 1:27:32

友情提示: 跳转到本人juejin观看体验更佳(当然CSDN也很好😋)
link —> https://juejin.cn/user/679936123997707/posts
Thanks!🌹

前言

前段时间,和朋友们一起搭建的一个网站需要实现支付功能,使得用户支付后可以成为会员并且能使用更多一些强大的功能。让网站也具备一定的盈利能力。
在这里插入图片描述


平时大家用的支付基本上也就是微信支付、支付宝支付、银行卡支付了。我们也是成功接入了微信支付,并且上线。目前网站仍处于一个内测阶段,大家如果有什么问题或者有更好的建议我们可以在下方评论区一起交流一下🌹

下面以最新版本的微信支付为例,展示一个接入支付功能较为通用的解决方案:

实现网站的微信支付功能

理清支付流程

一个完整的微信支付(此处以最简单的Native支付为例子)升级为会员流程包括有:

  1. 用户获取各种支付类型信息
  2. 选择某种类型拉取订单并生成二维码
  3. 用户扫码支付成功后,回调通知服务器已支付
  4. 对用户进行升级会员业务操作


    在此我们主要讲如何开发并调试2、3步骤,1、4步骤就根据不同场景进行不同开发哩

第一步:准备商户基本信息

要实现微信支付的功能,首先需要有微信支付商户收款方的资质也就是你的收款方信息。


包含信息有

  • 商户号 mch-id
  • AppID
  • 商户API证书序列号 mch-serial-no
  • API v3密钥 (目前最新版v3)
  • 商户私钥文件 private-key (可以是文件形式也可以把文件内容拷出来)

微信支付商户平台 —> https://pay.weixin.qq.com/index.php/core/home

我们在微信商户平台准备上述需要的基础信息


第二步:编写配置信息注入配置类

配置信息放入yml中

wechat:
  pay-config:
    #认证类型
    auth-type: WECHATPAY2-SHA256-RSA2048
    # 商户号
    mch-id: 1···7
    # APPID
    appid: wx·····a2
    # 商户API证书序列号
    mch-serial-no: 5··················6
    # APIv3密钥
    api-v3-key: J··············123
    # 支付结果微信回调
    notify-url: https://······/notify  //可以先不管,后续会讲到
    # 商户私钥文件
    private-key: MIME····

配置类 WeChatPayConfig

@Data
// @RefreshScope 可以搭配Nacos配置中心进行热更新处理 若没有忽略
@Configuration
@ConfigurationProperties(prefix = "wechat.pay-config")
public class WeChatPayConfig {
    private String authType;
    private String mchId;
    private String mchSerialNo;
    private String privateKey;
    private String apiV3Key;
    private String appId;
    private String notifyUrl;
}

初始化单例RSA签名配置

@Configuration
public class BeanConfig {
    @Autowired
    private WeChatPayConfig weChatPayConfig;

    /**
     * 单例一个RSAAutoCertConfig微信API认证config
     * @return wechatAPICertConfig
     */
    @Bean
    public RSAAutoCertificateConfig rsaAutoCertificateConfig() {
        return new RSAAutoCertificateConfig.Builder()
                .merchantId(weChatPayConfig.getMchId())
                .privateKey(weChatPayConfig.getPrivateKey())
                .merchantSerialNumber(weChatPayConfig.getMchSerialNo())
                .apiV3Key(weChatPayConfig.getApiV3Key())
                .build();
    }
}

这样配置好之后,在需要使用到的类注入配置类校验是否注入成功

@Autowired

private WeChatPayConfig weChatPayConfig;

log或者sout打印出来校验,校验注入成功后我们进行下一步。


第三步:开发 点击支付拉起二维码

微信支付官方API文档: https://pay.weixin.qq.com/docs/merchant/sdk-tools/sdk-tool.html

微信支付官方JavaSDK仓库: https://github.com/wechatpay-apiv3/wechatpay-java

首先将SDK依赖导入你的支付模块中,然后开始code

package com.wechat.pay.java.service;

import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.payments.nativepay.NativePayService;
import com.wechat.pay.java.service.payments.nativepay.model.Amount;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse;

/** Native 支付下单为例 */
public class QuickStart {
    @Autowired
    private WeChatPayConfig weChatPayConfig;
    @Autowired
    private RSAAutoCertificateConfig certificateConfig;
    

    public static void main(String[] args) {
        // 构建service
        NativePayService service = new NativePayService.Builder().config(certificateConfig).build();
        // request.setXxx(val)设置所需参数,具体参数可见Request定义
        PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();
        amount.setTotal(100);
        request.setAmount(amount);
        request.setAppid("wxa9d9651ae******");
        request.setMchid("190000****");
        request.setDescription("测试商品标题");
        request.setNotifyUrl("https://notify_url");
        request.setOutTradeNo("out_trade_no_001");
        // 调用下单方法,得到应答
        PrepayResponse response = service.prepay(request);
        // 使用微信扫描 code_url 对应的二维码,即可体验Native支付
        System.out.println(response.getCodeUrl());
    }
}

通过上述代码就可以将用户扫码支付的二维码调用出来。

那么我的服务端如何知道用户是否支付成功了呢?


这个就是配置文件中的回调地址的作用了,微信支付中台会使用POST请求你的这个url,发送支付结果。

在这里插入图片描述

所以我们需要编写一个接口进行接收处理微信支付中台发送给我们的、用户的支付结果。

例如:


/**
 * 处理wechatNative支付回调通知端点
 */
@PostMapping("/notify")
public Map<String,String> getNativeNotify(HttpServletRequest request){
    String resultCode = payService.solveNotify(request);
    Map<String,String> resultMap = new HashMap<>();
    resultMap.put("code", resultCode);
    //通知wechat平台是否成功,成功后不再回调
    return resultMap;
}

❗注意这个回调地址只能是https的形式



此处解释为什么:

  1. 微信支付中台在公网,所以你的端点需要能被它所访问到,也要在公网能被访问到。
  2. https表示是可靠可信任的端点。

总结一下就是微信支付中台需要能在公网一个可信任的端点告诉你的服务器这个二维码订单的支付结果。

在开发中,每次都将这个接收微信发送的支付结果的接口上线到我们的服务器,才能通过https进行调试,未免太过烦琐了.

所以我们需要一个更好的办法,能够满足我们的本地开发调试。

此处我们使用ngrok内网穿透的方式,将本地服务暴露成公网可访问的形式进行开发调试。

具体实操请看此篇文章,讲的很好 --> https://juejin.cn/post/6844903617279819784?searchId=2024100714145171494C06D97630D7A20B

记得将这个回调端点url写在配置文件中噢。

😋 然后我们就可以进行支付后的调试了!!


第四步: 前端轮询支付结果

在微信中台告诉服务器的支付结果并处理之后,正常来说前后端分离的项目,前端是还不知道支付是否成功的。

这里我们大致有两种解决方案 让前端能得知支付结果渲染不同页面。

  1. 轮询接口
  2. 服务端主动推送

在支付结果的这件小通知来说,我认为前端进行轮询的方式是更好的。

服务端主动推送有两种网络协议能够做到,WebSocket和SSE协议都能让服务端推送信息到客户端。但是如果用户频繁调用订单,成交率很低的话,需要维护多条连接,一时间可能消耗服务器非常多的内存和cpu占有率

所以我们采取的解决方案是:

  • 我们可以通过redis缓存订单支付结果,将轮询的请求打在缓存中
  • 采取布隆过滤器防止订单不存在的缓存穿透问题。

伪代码如下:


    /**
     * 提供前端轮询获取支付结果
     * @param tradeNo 外部订单号
     * @return 支付成功与否
     */
    @GetMapping("/{tradeNo}/result")
    public R<String> getPayResult(@PathVariable String tradeNo){
        //布隆过滤器防止缓存穿透
//        if(!bloomService.contains(RedisConstants.ORDER_IS_DEAL+tradeNo, tradeNo))
//            return R.error(ResultCode.VALIDATE_FAILED, "订单不存在");

        if("1".equals(redisService.getValue(RedisConstants.ORDER_IS_DEAL+tradeNo))){
            Order order = orderDao.getOrderByTradeNo(tradeNo);
            String vipExpiration = redisService.getValue( RedisConstants.USER_VIP+ order.getUid());
            redisService.deleteValue(RedisConstants.ORDER_IS_DEAL+tradeNo);
            return R.success(vipExpiration, "支付已成功, 本用户vip截至");
        }
        return R.error(ResultCode.FAILED, "订单未完成或不存在");
    }

以上就是实现微信支付功能的具体步骤啦,还有很多细节方面的事情可以根据自己的需求来自由处理。

祝大家写的代码永无bug,都能一次过过过~

国庆美美的长假也是结束了😭😭 如果能回到七天前就好了😋

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2195088.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

速卖通、Shopee、Lazada自养号测评的五大关键步骤:从环境构建到风控应对

在跨境电商领域&#xff0c;速卖通、Shopee和Lazada等平台上的自养号测评已成为提升销量、优化产品排名的重要手段。自养号测评不仅能够帮助卖家快速积累好评&#xff0c;还能有效提升产品的曝光率和转化率。然而&#xff0c;自养号测评并非易事&#xff0c;需要掌握一系列专业…

软考UML图 -- ( 类图,对象图,用例图,序列图,通信图,状态图,活动图,构件图,部署图)

文章目录 一、UML统一建模语言二、关系三、UML图1. 类图2. 对象图3. 用例图4. 序列图&#xff08;顺序图&#xff09;—— 交互图5. 通信图 —— 交互图6. 状态图7. 活动图8. 构件图&#xff08;组件图&#xff09;9. 部署图10. 总结 一、UML统一建模语言 UML由3个要素构成:UM…

Linux 外设驱动 应用 1 IO口输出

从这里开始外设驱动介绍&#xff0c;这里使用的IMX8的芯片作为驱动介绍 开发流程&#xff1a; 修改设备树&#xff0c;配置 GPIO1_IO07 为 GPIO 输出。使用 sysfs 接口或编写驱动程序控制 GPIO 引脚。编译并测试。 这里假设设备树&#xff0c;已经配置好了。不在论述这个问题…

PDF转JPG神器!这四款软件让你轻松搞定文档转换

尊敬的朋友们&#xff0c;您是否曾在数字办公和娱乐的海洋中&#xff0c;遭遇过因格式问题而一筹莫展的时刻&#xff1f;比如&#xff0c;手头有一份绝美的PDF文件&#xff0c;却想将其转换为JPG图片格式&#xff0c;好让它能在你的社交圈中大放异彩&#xff1b;别急&#xff0…

自然语言处理-语言转换

文章目录 一、语言模型二、统计语言模型1.含义与方法2.存在的问题 三、神经语言模型1.含义与方法2.one-hot编码3.词嵌入-word2vec4.模型的训练过程 四、总结 自然语言处理&#xff08;NLP&#xff09;中的语言转换方法主要涉及将一种形式的语言数据转换为另一种形式&#xff0c…

IDEA创建、导入、删除maven项目

全局配置&#xff1a; 1.File->Close Project 2.Customize->All settings 3. Apply 4.选择JRE版本->Apply 5.选择字节码版本->Apply->OK 全局配置结束 创建maven项目&#xff1a; 1.File->New->Module 2.Build system选择Maven GroupId&#xff1a…

Django学习笔记十三:优秀案例学习

Django CMS 是一个基于 Django 框架的开源内容管理系统&#xff0c;它允许开发者轻松地创建和管理网站内容。Django CMS 提供了一个易于使用的界面来实现动态网站的快速开发&#xff0c;并且具有丰富的内容管理功能和多种插件扩展。以下是 Django CMS 的一些核心特性和如何开始…

智能医疗:Spring Boot医院管理系统开发

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常适…

手术器械检测系统源码分享

手术器械检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision …

【Nacos入门到实战十三】Nacos配置管理:配置优先级与加载顺序解读

个人名片 &#x1f393;作者简介&#xff1a;java领域优质创作者 &#x1f310;个人主页&#xff1a;码农阿豪 &#x1f4de;工作室&#xff1a;新空间代码工作室&#xff08;提供各种软件服务&#xff09; &#x1f48c;个人邮箱&#xff1a;[2435024119qq.com] &#x1f4f1…

Thinkphp/Laravel基于vue的金融理财产品销售系统设计与实现Vscode毕业设计成品源码.

目录 技术栈和环境说明具体实现截图设计思路关键技术课题的重点和难点&#xff1a;框架介绍数据访问方式PHP核心代码部分展示代码目录结构解析系统测试详细视频演示源码获取 技术栈和环境说明 采用PHP语言开发&#xff0c;开发环境为phpstudy 开发工具notepad并使用MYSQL数据库…

allegro 替换过孔

操作步骤如下 1.选择操作对象&#xff08;需要替换的过孔&#xff09;&#xff0c;右键–>Repace……–>Selected…… 2.在弹出的窗口中选择最终需要的过孔既可以

2024系统分析师考试---数据仓库相关概念

前言&#xff1a; 传统的操作型数据库主要面向业务的&#xff0c;所执行的操作基本上也是联机事务处理&#xff0c;随着企业规模的增长&#xff0c;历史积累的数据越来越多&#xff0c;如何利用历史数据来为未来决策服务&#xff0c;就显得越来越重要了&#xff0c;而数据仓库就…

微信小程序开发问题记录

文章目录 一&#xff0c;全局文件配置windows title不起作用 一&#xff0c;全局文件配置windows title不起作用 全局配置中配置窗口导航栏标题不生效。 但是页面使用的导航栏插件配置的title能生效。

source insight 的开源替代

source insight 的开源替代——sourcetrail&#xff0c;开源地址&#xff1a;https://github.com/CoatiSoftware/Sourcetrail Sourcetrail 是一个交互式源代码浏览器&#xff0c;它通过为代码编制索引并收集有关其结构的数据来简化现有源代码中的导航。然后&#xff0c;Sourcet…

图吧工具箱

图吧工具箱202309绿色版自动解压程序R2.exe&#xff0c;永久有效 链接&#xff1a;https://pan.baidu.com/s/1M6TI7Git8bXOzZX_qZ3LJw?pwdzked 提取码&#xff1a;zked

Java中常用的线程工具(JUC)

多线程 多线程 基本概念 CAS (Compare-And-Swap&#xff0c;比较并交换)&#xff0c;是一种用于实现多线程同步的原子操作。主要原理&#xff1a;1.比较内存中的某个位置的当前值和预期值 2.交换如果当前值与预期值相等&#xff0c;则将该位置的值更新为新值&#xff0c;否则…

ZYNQ:Petalinunx构建工程

资料准备 1、xsa 文件&#xff1a;top_020.xsa&#xff08;使用vivado 2024.1制作&#xff09; 2、设置 Petalinux &#xff08;2024.1&#xff09;环境变量&#xff1a;sptl 创建 petalinux 工程 构建工程 petalinux-create -t project --template zynq -n project配置…

Linux--IO模型与高级IO重要概念

什么是IO&#xff1f; IO是指计算机系统与外部世界进行数据交换的过程。在计算机中&#xff0c;IO通常用于与外部设备通信&#xff0c;这些设备包括键盘、鼠标、打印机、显示器、网络等。通过IO操作&#xff0c;计算机系统可以接收来自外部设备的输入数据&#xff0c;也可以将…

黑马JavaWeb开发跟学(九)MyBatis基础操作

黑马JavaWeb开发跟学九.MyBatis基础操作 1. Mybatis基础操作1.1 需求1.2 准备1.3 删除1.3.1 功能实现1.3.2 日志输入1.3.3 预编译SQL1.3.3.1 介绍1.3.3.2 SQL注入1.3.3.3 参数占位符 1.4 新增1.4.1 基本新增1.4.2 主键返回 1.5 更新1.6 查询1.6.1 根据ID查询1.6.2 数据封装1.6.…