UniApp前端联动Java后端:微信支付功能的架构设计与实操剖析

文章标题:UniApp前端与Java后端结合:微信支付功能的架构设计与实战剖析

一、概述

在移动互联网的大环境下,支付功能已然成为应用开发里不可或缺的核心能力之一。本篇文章以UniApp前端搭配Java后端的技术组合为例,全方位剖析微信支付功能的设计思路与实际落地方式,为开发者展现从技术架构搭建到安全防护的完整图景。

微信支付功能是跨平台应用(由UniApp前端和Java后端构成)与微信支付系统进行对接的核心模块,能够达成用户从下单直至支付完成的闭环流程。它支持多种支付场景,诸如APP支付、小程序支付、H5支付等,保障交易的安全性、实时性以及数据的一致性。通常,公司会将支付系统独立出来,以此确保其服务的安全、可靠与稳定,所以支付系统是现代互联网的关键核心系统。

1.1:微信支付流程图

大致如下:流程图中第2、3步虽有调换,但不影响整体,建议先创建订单。

1.2:流程步骤

1、用户提交订单请求
  • 行为主体:用户(通过UniApp前端操作)
  • 动作描述:用户在UniApp中选定商品或服务,点击支付按钮,前端把订单信息(例如商品ID、数量、金额等)发送到Java后端。
2、生成业务订单
  • 行为主体:Java后端
  • 动作描述
  • 后端接收到订单请求后,对数据的合法性进行验证,比如检查金额是否合理、商品库存是否充足等。
  • 在数据库中生成唯一的业务订单号(out_trade_no),并将订单状态记录为“待支付”。
3、调用微信统一下单API
  • 行为主体:Java后端→微信支付平台
  • 动作描述
  • 后端构造统一下单的请求参数,包含商户号、订单号、金额、回调地址等信息。
  • 使用商户API密钥生成签名,以保障请求的安全性。
  • 向微信支付平台发送HTTP请求,调用统一下单接口(URL: https://api.mch.weixin.qq.com/pay/unifiedorder)。
4、接收预支付交易单响应
  • 行为主体:微信支付平台→Java后端
  • 动作描述
  • 微信对请求参数和签名进行验证,确认无误后生成预支付交易单。
  • 返回XML格式的响应数据,包含关键字段:
    • prepay_id(预支付交易标识,用于后续支付)
    • return_code(通信状态码,如SUCCESS/FAIL)
    • result_code(业务结果码,如SUCCESS/FAIL)
5、返回支付参数至前端
  • 行为主体:Java后端→UniApp前端
  • 动作描述
  • 后端解析微信返回的prepay_id,重新构造前端支付所需的参数(需进行二次签名)。
  • 返回JSON数据给UniApp,包含:
    • appId(微信应用ID)
    • timeStamp(时间戳)
    • nonceStr(随机字符串)
    • package(固定值Sign=WXPay
    • signType(签名类型,通常为MD5或HMAC-SHA256)
    • paySign(最终支付签名)
6、调起微信支付界面
  • 行为主体:用户(UniApp前端)→微信客户端
  • 动作描述
  • UniApp通过uni.requestPayment API,传入后端返回的支付参数。
  • 微信客户端(APP/小程序)依据参数拉起支付界面,用户确认金额并输入密码。
7、用户完成支付
  • 行为主体:微信支付平台→用户
  • 动作描述
  • 微信验证支付密码和账户余额,扣款成功后,向用户展示支付结果页面(成功/失败)。
8、异步通知支付结果
  • 行为主体:微信支付平台→Java后端
  • 动作描述
  • 微信通过POST请求调用后端预先设置的notify_url(需公网可访问)。
  • 推送XML格式的回调数据,包含:
    • out_trade_no(商户订单号)
    • transaction_id(微信支付单号)
    • total_fee(实际支付金额)
    • result_code(支付结果,如SUCCESS/FAIL)
9、处理回调并响应微信
  • 行为主体:Java后端→微信支付平台
  • 动作描述
  • 后端接收回调数据后:
    • 验证签名以防止伪造请求
    • 检查订单金额与业务系统是否一致
    • 更新订单状态为“已支付”(需进行幂等处理,避免重复更新)
  • 返回XML响应(必须包含<return_code><![CDATA[SUCCESS]]></return_code>),告知微信已正确处理。
10、通知前端最终结果
  • 行为主体:Java后端→UniApp前端
  • 动作描述
  • 若前端未实时感知支付结果(例如用户关闭页面),可通过两种方式同步:
    • 轮询查询:前端定期请求后端订单状态接口
    • WebSocket推送:后端主动推送支付结果
  • 更新前端界面显示支付成功/失败状态。

二、账号准备工作

2.1:申请微信小程序账号

开发小程序的第一步是拥有小程序账号,所以首先要进行小程序账号的申请。小程序注册地址:小程序注册链接。填写相关信息完成注册后,会生成AppID和AppSecret。小程序的AppID相当于小程序平台的一个标识,后续在很多场景中都会用到,需注意区分于服务号或订阅号的AppID。

2.2:微信支付官网开通商户支付能力

访问微信支付官网:微信支付官网。找到接入微信支付的入口进行绑定注册,注册时需要提供营业执照、法人信息等,按照要求填写即可。注册完成后获取微信支付商户号,申请证书和AIPv3秘钥(v2已逐步淘汰,直接使用v3),妥善下载并保存好秘钥及证书。

三、接入实现

3.1:服务端代码

1、导入maven依赖
            <!-- 微信支付API -->
            <dependency>
                <groupId>com.github.wxpay</groupId>
                <artifactId>wxpay-sdk</artifactId>
                <version>0.0.3</version>
            </dependency>
            <dependency>
                <groupId>com.thoughtworks.xstream</groupId>
                <artifactId>xstream</artifactId>
                <version>1.4.20</version>
                <scope>compile</scope>
            </dependency>
    <!-- 微信支付SDK(官方或第三方封装) -->
    <dependency>
        <groupId>com.github.wechatpay-apiv3</groupId>
        <artifactId>wechatpay-apache-httpclient</artifactId>
        <version>0.4.7</version>
    </dependency>
2、配置商户信息
# 微信支付配置
pay:
  appId: xxx #应用id
  mchId: xxx #商户id
  notifyUrl: https://服务器ip或对应域名/wxpay/weixin/callback #支付回调地址
3、实体类代码

WeChatPay:微信支付预下单实体类

@Data
@Accessors(chain = true)
public class WeChatPay {

    /**
     * 返回状态码  此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断
     */
    public String return_code;

    /**
     * 返回信息 当return_code为FAIL时返回信息为错误原因 ,例如 签名失败 参数格式校验错误
     */
    private String return_msg;

    /**
     * 公众账号ID 调用接口提交的公众账号ID
     */
    private String appid;

    /**
     * 商户号 调用接口提交的商户号
     */
    private String mch_id;

    /**
     * api密钥 详见:https://pay.weixin.qq.com/index.php/extend/employee
     */
    private String api_key;

    /**
     * 设备号  自定义参数,可以为请求支付的终端设备号等
     */
    private String device_info;

    /**
     * 随机字符串    5K8264ILTKCH16CQ2502SI8ZNMTM67VS   微信返回的随机字符串
     */
    private String nonce_str;

    /**
     * 签名 微信返回的签名值,详见签名算法:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=4_3
     */
    private String sign;

    /**
     * 签名类型
     */
    private String sign_type;


    /**
     * 业务结果 SUCCESS SUCCESS/FAIL
     */
    private String result_code;

    /**
     * 错误代码 当result_code为FAIL时返回错误代码,详细参见下文错误列表
     */
    private String err_code;

    /**
     * 错误代码描述 当result_code为FAIL时返回错误描述,详细参见下文错误列表
     */
    private String err_code_des;

    /**
     * 交易类型 JSAPI JSAPI -JSAPI支付 NATIVE -Native支付 APP -APP支付 说明详见;https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=4_2
     */
    private String trade_type;

    /**
     * 预支付交易会话标识 微信生成的预支付会话标识,用于后续接口调用中使用,该值有效期为2小时
     */
    private String prepay_id;

    /**
     * 二维码链接     weixin://wxpay/bizpayurl/up?pr=NwY5Mz9&groupid=00 trade_type=NATIVE时有返回,此url用于生成支付二维码,然后提供给用户进行扫码支付。注意:code_url的值并非固定,使用时按照URL格式转成二维码即可
     */
    private String code_url;

    /**
     * 商品描述  商品简单描述,该字段请按照规范传递,具体请见 https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=4_2
     */
    private String body;

    /**
     * 商家订单号 商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|* 且在同一个商户号下唯一。详见商户订单号 https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=4_2
     */
    private String out_trade_no;

    /**
     * 标价金额 订单总金额,单位为分,详见支付金额 https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=4_2
     */
    private String total_fee;

    /**
     * 终端IP 支持IPV4和IPV6两种格式的IP地址。用户的客户端IP
     */
    private String spbill_create_ip;

    /**
     * 通知地址 异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。公网域名必须为https,如果是走专线接入,使用专线NAT IP或者私有回调域名可使用http
     */
    private String notify_url;

    /**
     * 子商户号 sub_mch_id 非必填(商户不需要传入,服务商模式才需要传入) 微信支付分配的子商户号
     */
    private String sub_mch_id;

    /**
     * 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
     */
    private String attach;

    /**
     * 商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔。
     */
    private String out_refund_no;

    /**
     * 退款总金额,单位为分,只能为整数,可部分退款。详见支付金额 https://pay.weixin.qq.com/wiki/doc/api/native_sl.php?chapter=4_2
     */
    private String refund_fee;

    /**
     * 退款原因 若商户传入,会在下发给用户的退款消息中体现退款原因 注意:若订单退款金额≤1元,且属于部分退款,则不会在退款消息中体现退款原因
     */
    private String refund_desc;

    /**
     * 交易结束时间 订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。其他详见时间规则 注意:最短失效时间间隔必须大于5分钟
     */
    private String time_expire;

    /**
     * 用户标识 trade_type=JSAPI,此参数必传,用户在主商户appid下的唯一标识。openid和sub_openid可以选传其中之一,如果选择传sub_openid,则必须传sub_appid。下单前需要调用【网页授权获取用户信息: https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html 】接口获取到用户的Openid。
     */
    private String openid;

    /**
     * 时间戳
     */
    private String time_stamp;

    /**
     * 会员类型
     */
    private String memberShipType;

}

PayParameterVO:微信支付,商品信息对象

@Data
public class PayParameterVO {

    /** 商品价格(单位:分) */
    private String price;

    /** 微信openId */
    private String wxOpenId;

    /** 商品描述 */
    private String goodsTitle;

}

OrderReturnInfo:预下单成功之后返回结果对象

@Data
public class OrderReturnInfo {


        /** 返回状态码 */
        private String return_code;

        /** 返回信息 */
        private String return_msg;

        /** 业务结果 */
        private String result_code;

        /** 小程序appID */
        private String appid;

        /** 商户号 */
        private String mch_id;

        /** 随机字符串 */
        private String nonce_str;

        /** 签名 */
        private String sign;

        /**  预支付交易会话标识。用于后续接口调用中使用,该值有效期为2小时 */
        private String prepay_id;

        /** 交易类型 */
        private String trade_type;
}

QueryReturnInfo:查询订单返回实体类

@Data
public class QueryReturnInfo {

    /** 返回状态码 */
    private String return_code;

    /** 返回信息 */
    private String return_msg;


    /** 业务结果 */
    private String result_code;

    /** 错误代码 */
    private String err_code;

    /** 错误代码描述 */
    private String err_code_des;

    /** 小程序appID */
    private String appid;

    /** 商户号 */
    private String mch_id;

    /** 随机字符串 */
    private String nonce_str;

    /** 签名 */
    private String sign;

    /** 签名类型 */
    private String sign_type;

    private String prepay_id;

    /** 交易类型 */
    private String trade_type;

    /** 设备号 */
    private String device_info;

    /** 用户标识 */
    private String openid;

    /** 是否关注公众账号 */
    private String is_subscribe;

    private String trade_state;

    /** 付款银行 */
    private String bank_type;

    /** 订单金额 */
    private int total_fee;

    /** 应结订单金额 */
    private int settlement_total_fee;

    /** 货币种类 */
    private String fee_type;

    /** 现金支付金额 */
    private int cash_fee;

    /** 现金支付货币类型 */
    private String cash_fee_type;

    /** 总代金券金额 */
    private int coupon_fee;

    /** 代金券使用数量 */
    private int coupon_count;

    /** 代金券类型 */
    private String coupon_type_$n;

    /** 代金券ID */
    private String coupon_id_$n;

    /** 单个代金券支付金额 */
    private String coupon_fee_$n;

    /** 微信支付订单号 */
    private String transaction_id;

    /** 商户订单号 */
    private String out_trade_no;

    /** 支付完成时间 */
    private String time_end;

    private String trade_state_desc;

    /** 商家数据包 */
    private String attach;
}

SignInfo:签名实体类

@Data
public class SignInfo {

    private String appId;//小程序ID

    private String timeStamp;//时间戳

    private String nonceStr;//随机串

    @XStreamAlias("package")
    private String repay_id;

    private String signType;//签名方式
    public void setSignType(String signType) {
        this.signType = signType;
    }
}
4、工具类代码

SignUtils:签名工具类
```java
@Slf4j
public class SignUtils {

    /**
     * 签名

文章整理自互联网,只做测试使用。发布者:Lomu,转转请注明出处:https://www.it1024doc.com/12612.html

(0)
LomuLomu
上一篇 9小时前
下一篇 1分钟前

相关推荐

  • 2025年最新DataGrip激活码永久破解教程(亲测有效)

    本教程适用于JetBrains全家桶,包括IDEA、PyCharm、DataGrip、Golang等开发工具! 先给大家看看最新版本的破解效果,可以看到已经成功激活到2099年,完全不用担心过期问题! 下面我将通过详细的图文教程,手把手教你如何永久激活DataGrip。这个方法同样适用于旧版本,无论你使用什么操作系统,都能轻松搞定! 下载DataGrip安装…

    2025 年 5 月 10 日
    26300
  • PyCharm 2024永久激活教程 – 破解与安装方法

    本教程适用于PyCharm 2025、IDEA、DataGrip、Goland等Jetbrains产品,支持全家桶激活!无论您使用的是Windows、Mac还是Linux,均可按照本教程成功激活PyCharm 2025至2097年。 激活截图展示 首先,我们来展示一下最新版本的PyCharm 2025破解成功的截图,如下所示,您可以看到已经成功激活至2097…

    PyCharm破解教程 2025 年 4 月 22 日
    28300
  • 2025年最新DataGrip永久破解教程(亲测有效,激活至2099年)🔥

    🚀 本教程适用于Jetbrains全家桶(IDEA、PyCharm、DataGrip、Golang等所有产品)! 先给大家看看最新版本的破解成果,直接激活到2099年,简直不要太爽!😎 下面我将手把手教你如何永久激活DataGrip,这个方法同样适用于旧版本哦!✨ 无论你用的是Windows、Mac还是Linux系统,都能完美破解! 第一步:下载DataGr…

    6天前
    20700
  • 彻底解决Java中的`IllegalStateException`异常:实用指南与最佳实践

    在Java编程实践中,java.lang.IllegalStateException是一种典型的运行时异常,它往往暗示着程序当前所处的状态与预期操作不匹配。当某个方法被调用时,如果其前置条件未能满足,或者对象处于不适合执行该操作的状态时,系统就会抛出这个异常。本指南将深入剖析该异常的产生根源,并给出切实可行的应对策略,助力开发者有效规避和解决相关问题。 1.…

    未分类 2025 年 5 月 13 日
    7200
  • 全面剖析NoSQL数据库:文档存储到图数据库的全场景应用

    全方位解读NoSQL数据库:从文档存储到图数据库的全场景运用 title: 透彻剖析NoSQL数据库:自文档存储至图数据库的全场景实践date: 2025/2/19updated: 2025/2/19author: cmdragon excerpt:借助电商、社交网络、物联网等十二个行业场景,融合MongoDB聚合管道、Redis Stream实时处理、Ca…

    4天前
    2400

发表回复

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

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信