Java项目中微信与支付宝支付的实战攻略(超详细)

个人主页:java之路-CSDN博客(期待您的关注)

目录

项目支付功能的重要性

前期准备工作

微信支付准备

支付宝支付准备

微信支付集成步骤

引入微信支付 SDK

配置微信支付参数

发起微信支付请求

处理微信支付结果通知

支付宝支付集成步骤

引入支付宝 SDK

配置支付宝支付参数

发起支付宝支付请求

处理支付宝支付结果通知

常见问题及解决方法

签名验证失败

支付回调异常


项目支付功能的重要性

在当今数字化时代,无论是电商平台、在线教育、生活服务类应用,还是其他各类软件项目,支付功能都已成为其核心功能之一。支付功能就像是连接商家与用户之间的桥梁,直接关系到交易的顺畅进行和用户体验的好坏。

从用户角度来看,便捷、安全的支付方式是他们选择使用某个应用或服务的重要因素。想象一下,当用户在电商平台上精心挑选完心仪的商品,准备结账付款时,如果支付过程繁琐复杂,或者不支持他们常用的支付方式,用户很可能会放弃购买,甚至对该平台产生负面印象,转而选择其他竞争对手的产品。因此,提供丰富多样且操作简便的支付方式,能够大大提高用户的满意度和忠诚度,促进用户的消费行为。

对于商家而言,支付功能的顺畅与否直接影响到业务的收入和运营效率。高效的支付系统能够确保交易快速完成,资金及时到账,加速企业的资金流转,有利于企业的资金管理和业务拓展。同时,准确的支付记录和数据分析,还能帮助商家了解用户的消费习惯和偏好,为精准营销和产品优化提供有力支持。

微信支付和支付宝支付作为国内占据主导地位的两大第三方支付平台,拥有庞大的用户基础和完善的支付生态体系。在 Java 项目中集成微信和支付宝支付,能够让项目快速接入这两大支付渠道,满足绝大多数用户的支付需求,为项目的成功实施和业务发展提供坚实的保障。

前期准备工作

微信支付准备

  1. 注册微信支付商户账号
  • 准备材料:营业执照彩色扫描件或数码照片,若已三证合一,无需提供组织机构代码证;对公银行账户信息,包含开户行省市信息、开户账号;法人身份证彩色扫描件或数码照片;用于接收微信支付开户邮件及日常业务通知的邮箱;法人手机号。
  • 注册方式:
  •     手机端:打开微信,进入 “微信收款商业版” 小程序或 “微信支付商家助手” 小程序,选择 “成为商家”,按页面提示填写相关信息,上传所需材料,提交后等待审核结果。
  •     电脑端:访问微信支付商户平台官网(https://pay.weixin.qq.com/ ),点击 “注册” 按钮进行账号注册。注册成功后,登录微信商户平台,按页面提示填写商户信息,上传相关材料并提交审核,审核周期一般为 1 - 5 个工作日。
  • 2. 获取关键信息
  • APPID:微信支付使用的 appid 是微信服务号或小程序的 appid。登录微信服务号后台,在 “开发 - 基本配置 / 开发者 ID (AppID)” 中查看;若为小程序,网页搜索 “微信公众平台”,扫码选择小程序登录,在左侧 “开发 - 开发管理 - 小程序 AppID” 处复制。
  • MCHID:登录微信商户平台,在最顶部的 “你好,[数字]” 中的那串数字即为商户号(MCHID),也是使用账号登录微信商户平台的那串数字。
  • API 密钥:登录微信商户平台,选择 “账户中心 / API 安全 / 设置密钥”,设置 32 位商户 API 密钥,设置时需在电脑上安装操作证书才能进行相关操作 。

支付宝支付准备

  1. 注册支付宝开发者账号
  • 打开官网:直接打开链接https://open.alipay.com/platform/home.htm进入,或百度搜索蚂蚁金服开放平台点击第一个进入官网。
  • 申请账号:点击 “免费入驻”,移到 “自主开发者”,点击 “立即入驻”,登录支付宝账号,填写信息后立即申请,无需人工审核。
  • 选择开发类型:点击 “开发者中心”,可选择 “网页 & 移动应用” 等进行开发。
  1. 创建应用并获取信息
  • 应用 ID:在开发者中心首页创建应用,提供应用名称、应用类型、业务注册国家 / 地区以及应用描述等基本信息。创建应用程序后,在 “基本信息” 页面查看应用 ID(client ID )。
  • 应用公钥、应用私钥
  •       准备支付宝密匙生成器,可根据系统类型从支付宝文档中心下载。
  •       安装并打开密钥生成器,选择密钥长度(一般为 RSA2)和格式(若为 Java 开发选择 PKCS1 格式),点击 “生成密钥”,生成应用私匙和应用公匙。
  •       登录支付宝开放平台,进入创建的应用详情页面,点击 “开发设置”,在 “接口加签方式” 处点击 “设置”,选择加签模式为 “公钥”,将生成的 “应用公匙” 复制到 “填写公匙字符” 选项中,点击 “设置保存” 后生成支付宝公匙,生成的 “应用私匙” 即为支付宝私匙。

微信支付集成步骤

引入微信支付 SDK

我们可以通过 Maven 或 Gradle 来引入微信支付 SDK。以 Maven 为例,在项目的pom.xml文件中添加如下依赖:

<dependency>

<groupId>com.github.wxpay</groupId>

<artifactId>wxpay-sdk</artifactId>

<version>4.0.1</version>

</dependency>

添加完成后,Maven 会自动下载并管理该依赖。如果使用 Gradle,在build.gradle文件中添加:

implementation 'com.github.wxpay:wxpay-sdk:4.0.1'

配置微信支付参数

在配置文件(如application.properties或application.yml)中设置微信支付所需的参数:

application.properties 配置示例

wxpay.appId=你的APPID

wxpay.mchId=你的MCHID

wxpay.apiKey=你的API密钥

wxpay.notifyUrl=http://yourdomain.com/wechat/pay/notify # 支付结果通知地址

application.yml 配置示例

wxpay:
  appId: 你的APPID
  mchId: 你的MCHID
  apiKey: 你的API密钥
  notifyUrl: http://yourdomain.com/wechat/pay/notify

在代码中获取这些配置参数,例如在 Spring Boot 项目中,可以通过@Value注解来注入:

import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Component;

@Component

public class WxPayConfig {

@Value("${wxpay.appId}")

private String appId;

@Value("${wxpay.mchId}")

private String mchId;

@Value("${wxpay.apiKey}")

private String apiKey;

@Value("${wxpay.notifyUrl}")

private String notifyUrl;

// 省略getter和setter方法

}

发起微信支付请求

以 Native 支付为例,发起微信支付请求的流程如下:

  1. 创建内部订单:在业务系统中创建订单,记录订单相关信息,如订单号、商品信息、价格等。
  1. 调用微信 API 获取二维码数据:根据订单信息,调用微信支付的统一下单接口,获取预支付交易会话标识(prepay_id),并生成二维码链接。
  1. 返回二维码给前端:将生成的二维码链接返回给前端,前端展示二维码供用户扫码支付。

代码实现如下:

import com.github.wxpay.sdk.WXPay;

import com.github.wxpay.sdk.WXPayUtil;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.*;

import java.util.HashMap;

import java.util.Map;

@RestController

@RequestMapping("/wechat/pay")

public class WeChatPayController {

@Autowired

private WxPayConfig wxPayConfig;

@PostMapping("/native")

public String nativePay(@RequestBody Map<String, Object> orderInfo) throws Exception {

// 创建WXPay对象

WXPay wxPay = new WXPay(wxPayConfig);

// 构建请求参数

Map<String, String> params = new HashMap<>();

params.put("body", (String) orderInfo.get("body")); // 商品描述

params.put("out_trade_no", (String) orderInfo.get("out_trade_no")); // 商户订单号

params.put("total_fee", ((Number) orderInfo.get("total_fee")).intValue() + ""); // 订单金额,单位为分

params.put("spbill_create_ip", (String) orderInfo.get("spbill_create_ip")); // 终端IP

params.put("notify_url", wxPayConfig.getNotifyUrl()); // 支付结果通知地址

params.put("trade_type", "NATIVE"); // 交易类型,NATIVE为原生扫码支付

// 调用统一下单接口

Map<String, String> result = wxPay.unifiedOrder(params);

if ("SUCCESS".equals(result.get("result_code"))) {

// 获取二维码链接

String codeUrl = result.get("code_url");

return codeUrl;

} else {

// 处理支付失败情况

return "支付失败: " + result.get("err_code_des");

}

}

}

处理微信支付结果通知

微信支付完成后,会向我们设置的notifyUrl发送支付结果通知。我们需要创建一个接口来接收并处理这些通知。

  1. 设置微信支付结果通知接口:在控制器中创建一个接口来接收微信支付的回调通知。
  2. 验证通知合法性:使用微信提供的签名验证机制,验证通知的来源是否合法,防止恶意篡改。
  3. 进行业务处理:根据通知中的支付结果,更新订单状态、记录支付日志等。

代码实现如下:

import com.github.wxpay.sdk.WXPay;

import com.github.wxpay.sdk.WXPayUtil;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;

import java.util.Map;

@RestController

@RequestMapping("/wechat/pay")

public class WeChatPayNotifyController {

@Autowired

private WxPayConfig wxPayConfig;

@PostMapping("/notify")

public String notify(HttpServletRequest request) throws Exception {

// 读取请求数据

String xmlData = WXPayUtil.inputStreamToString(request.getInputStream(), "UTF-8");

// 转换为Map

Map<String, String> resultMap = WXPayUtil.xmlToMap(xmlData);

// 创建WXPay对象

WXPay wxPay = new WXPay(wxPayConfig);

// 验证签名

if (wxPay.isPayResultNotifySignatureValid(resultMap)) {

// 验证通过,处理业务逻辑

String returnCode = resultMap.get("return_code");

String resultCode = resultMap.get("result_code");

if ("SUCCESS".equals(returnCode) && "SUCCESS".equals(resultCode)) {

// 支付成功,更新订单状态等

String outTradeNo = resultMap.get("out_trade_no");

// 业务处理代码,如更新订单为已支付状态

System.out.println("订单 " + outTradeNo + " 支付成功");

} else {

// 支付失败,记录错误信息

String errCode = resultMap.get("err_code");

String errCodeDes = resultMap.get("err_code_des");

System.out.println("支付失败: " + errCode + " - " + errCodeDes);

}

return WXPayUtil.mapToXml(WXPayUtil.successMap());

} else {

// 签名验证失败,返回错误信息

return WXPayUtil.mapToXml(WXPayUtil.failMap("签名验证失败"));

}

}

}

支付宝支付集成步骤

引入支付宝 SDK

  1. Maven 配置:在项目的pom.xml文件中添加支付宝 SDK 依赖,如下:
    <dependency>
    
    <groupId>com.alipay.sdk</groupId>
    
    <artifactId>alipay-sdk-java</artifactId>
    
    <version>4.9.116.ALL</version>
    
    </dependency>

添加完成后,Maven 会自动下载并管理该依赖。如果使用 Gradle,在build.gradle文件中添加:

implementation 'com.alipay.sdk:alipay-sdk-java:4.9.116.ALL'

  1. 手动导入:如果不想使用 Maven 或 Gradle,也可以从支付宝开放平台官网下载 SDK 的 JAR 包,然后将其手动添加到项目的lib目录下,并在项目的构建路径中添加该 JAR 包的引用。

配置支付宝支付参数

在配置文件(如application.properties或application.yml)中设置支付宝支付所需的参数:

application.properties 配置示例

alipay.appId=你的APPID

alipay.privateKey=你的应用私钥

alipay.alipayPublicKey=支付宝公钥

alipay.notifyUrl=http://yourdomain.com/alipay/pay/notify # 支付结果通知地址

alipay.returnUrl=http://yourdomain.com/alipay/pay/return # 支付成功后返回的页面地址

application.yml 配置示例

alipay:
  appId: 你的APPID
  privateKey: 你的应用私钥
  alipayPublicKey: 支付宝公钥
  notifyUrl: http://yourdomain.com/alipay/pay/notify
  returnUrl: http://yourdomain.com/alipay/pay/return

在代码中获取这些配置参数,例如在 Spring Boot 项目中,可以通过@Value注解来注入:

import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Component;

@Component

public class AlipayConfig {

@Value("${alipay.appId}")

private String appId;

@Value("${alipay.privateKey}")

private String privateKey;

@Value("${alipay.alipayPublicKey}")

private String alipayPublicKey;

@Value("${alipay.notifyUrl}")

private String notifyUrl;

@Value("${alipay.returnUrl}")

private String returnUrl;

// 省略getter和setter方法

}

发起支付宝支付请求

以网页支付为例,发起支付宝支付请求的流程如下:

  1. 创建内部订单:在业务系统中创建订单,记录订单相关信息,如订单号、商品信息、价格等。
  2. 调用支付宝 API 生成支付请求:根据订单信息,调用支付宝的支付接口,生成支付请求参数。
  3. 发送支付请求到支付宝:将生成的支付请求参数发送给支付宝,支付宝会返回一个包含支付信息的 HTML 表单,将该表单展示给用户,用户点击表单中的支付按钮即可跳转到支付宝支付页面进行支付。

代码实现如下:

import com.alipay.api.AlipayApiException;

import com.alipay.api.AlipayClient;

import com.alipay.api.DefaultAlipayClient;

import com.alipay.api.request.AlipayTradePagePayRequest;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.*;

@RestController

@RequestMapping("/alipay/pay")

public class AlipayPayController {

@Autowired

private AlipayConfig alipayConfig;

@PostMapping("/page")

public String pagePay(@RequestBody Map<String, Object> orderInfo) throws AlipayApiException {

// 创建AlipayClient对象

AlipayClient alipayClient = new DefaultAlipayClient(

"https://openapi.alipay.com/gateway.do",

alipayConfig.getAppId(),

alipayConfig.getPrivateKey(),

"json",

"UTF-8",

alipayConfig.getAlipayPublicKey(),

"RSA2");

// 创建支付请求对象

AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();

alipayRequest.setReturnUrl(alipayConfig.getReturnUrl());

alipayRequest.setNotifyUrl(alipayConfig.getNotifyUrl());

// 构建业务参数

String bizContent = "{" +

"\"out_trade_no\":\"" + orderInfo.get("out_trade_no") + "\"," +

"\"product_code\":\"FAST_INSTANT_TRADE_PAY\"," +

"\"total_amount\":\"" + orderInfo.get("total_amount") + "\"," +

"\"subject\":\"" + orderInfo.get("subject") + "\"" +

"}";

alipayRequest.setBizContent(bizContent);

// 发起支付请求

return alipayClient.pageExecute(alipayRequest).getBody();

}

}

处理支付宝支付结果通知

支付宝支付完成后,会向我们设置的notifyUrl发送支付结果通知。我们需要创建一个接口来接收并处理这些通知。

  1. 设置支付宝支付结果通知接口:在控制器中创建一个接口来接收支付宝支付的回调通知。
  2. 验证通知合法性:使用支付宝提供的签名验证机制,验证通知的来源是否合法,防止恶意篡改。
  3. 进行业务处理:根据通知中的支付结果,更新订单状态、记录支付日志等。

代码实现如下:

import com.alipay.api.AlipayApiException;

import com.alipay.api.internal.util.AlipaySignature;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;

import java.util.HashMap;

import java.util.Map;

@RestController

@RequestMapping("/alipay/pay")

public class AlipayNotifyController {

@Autowired

private AlipayConfig alipayConfig;

@PostMapping("/notify")

public String notify(HttpServletRequest request) throws AlipayApiException {

// 获取支付宝POST过来反馈信息

Map<String, String> params = new HashMap<>();

Map<String, String[]> requestParams = request.getParameterMap();

for (String name : requestParams.keySet()) {

String[] values = requestParams.get(name);

String valueStr = "";

for (int i = 0; i < values.length; i++) {

valueStr = (i == values.length - 1)? valueStr + values[i]

: valueStr + values[i] + ",";

}

params.put(name, valueStr);

}

// 验证签名

boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPublicKey(), "UTF-8", "RSA2");

if (signVerified) {

// 验证通过,处理业务逻辑

String tradeStatus = params.get("trade_status");

if ("TRADE_SUCCESS".equals(tradeStatus)) {

// 支付成功,更新订单状态等

String outTradeNo = params.get("out_trade_no");

// 业务处理代码,如更新订单为已支付状态

System.out.println("订单 " + outTradeNo + " 支付成功");

} else {

// 支付失败,记录错误信息

System.out.println("支付失败,交易状态: " + tradeStatus);

}

return "success";

} else {

// 签名验证失败,返回错误信息

return "fail";

}

}

}

常见问题及解决方法

签名验证失败

在微信支付和支付宝支付中,签名验证是确保支付请求和回调数据完整性与安全性的重要环节。然而,在实际集成过程中,签名验证失败是较为常见的问题。

微信支付签名验证失败

  • 原因分析
  • 密钥错误:微信支付使用 API 密钥来生成和验证签名。如果在配置文件中设置的 API 密钥与微信商户平台上设置的不一致,就会导致签名验证失败。例如,在微信商户平台上修改了 API 密钥,但在项目的配置文件中未及时更新。
  • 参数传递错误:签名的生成依赖于请求或回调中的参数。如果参数缺失、参数值错误或者参数顺序不正确,都会导致生成的签名与微信支付服务器端的签名不一致。比如,在发起支付请求时,忘记传递nonce_str(随机字符串)参数,或者传递的total_fee(订单金额)格式不正确。
  • 签名算法不一致:微信支付支持多种签名算法,如 MD5 和 HMAC - SHA256。如果在代码中使用的签名算法与微信支付服务器端期望的算法不一致,签名验证也会失败。例如,微信支付服务器端要求使用 HMAC - SHA256 算法进行签名验证,但代码中使用的是 MD5 算法。
  • 解决方法
  • 仔细核对密钥:登录微信商户平台,确认 API 密钥的正确性,并与项目配置文件中的密钥进行比对。如果不一致,及时在项目中更新密钥。
  • 检查参数传递:仔细检查支付请求和回调处理代码中涉及的参数,确保参数的完整性、正确性和顺序与微信支付文档要求一致。可以使用日志记录每次请求和回调的参数,方便排查问题。
  • 统一签名算法:参考微信支付官方文档,确定当前业务场景下微信支付服务器端期望的签名算法,并在代码中使用相应的算法进行签名生成和验证。

支付宝支付签名验证失败

  • 原因分析
  • 应用私钥和支付宝公钥错误:支付宝支付使用应用私钥进行签名生成,使用支付宝公钥进行签名验证。如果应用私钥生成错误、丢失,或者支付宝公钥配置错误,就会导致签名验证失败。例如,在生成应用私钥时,使用的密钥长度或格式不符合要求,或者在配置文件中错误地填写了支付宝公钥。
  • 参数编码问题:支付宝支付要求参数在签名前进行特定的编码处理。如果在代码中对参数的编码方式与支付宝支付服务器端的要求不一致,可能会导致签名验证失败。比如,在构建支付请求参数时,没有对参数进行 UTF - 8 编码,或者在签名验证时,对回调参数的解码方式不正确。
  • 签名参数遗漏或错误:与微信支付类似,支付宝支付的签名生成也依赖于一系列参数。如果在签名过程中遗漏了必要的参数,或者参数值错误,都会导致签名验证失败。例如,在生成签名时,忘记包含sign_type(签名类型)参数,或者out_trade_no(商户订单号)参数值与实际订单号不一致。
  • 解决方法
  • 重新生成和核对密钥:使用支付宝提供的密钥生成工具,重新生成应用私钥和支付宝公钥,并确保在项目配置文件中正确配置。同时,可以通过支付宝开放平台提供的工具或接口,验证公钥和私钥的正确性。
  • 统一参数编码方式:在代码中,确保对支付请求和回调参数的编码和解码方式与支付宝支付文档要求一致,统一使用 UTF - 8 编码。
  • 全面检查签名参数:仔细检查签名生成和验证过程中涉及的参数,确保参数的完整性和正确性。可以使用调试工具或日志记录,跟踪签名参数的传递和处理过程。

支付回调异常

支付回调是支付流程中的关键环节,它用于通知商户支付结果,以便商户进行相应的业务处理,如更新订单状态、发货等。然而,在实际应用中,可能会出现各种支付回调异常情况。

微信支付回调异常

  • 回调接口无法访问
  • 原因分析:网络问题是导致回调接口无法访问的常见原因之一,如服务器网络故障、防火墙设置限制了微信支付服务器的访问。另外,如果回调接口的 URL 配置错误,微信支付服务器无法正确找到回调地址,也会导致回调失败。例如,在配置文件中填写的回调 URL 中包含了错误的域名或端口号,或者回调接口所在的服务器 IP 地址发生了变化,但未及时更新配置。
  • 解决方法:检查服务器网络连接是否正常,确保服务器能够正常接收外部请求。同时,检查防火墙设置,添加允许微信支付服务器访问回调接口的规则。仔细核对回调接口的 URL 配置,确保其正确性,并在服务器 IP 地址或域名发生变化时,及时更新微信支付商户平台和项目配置文件中的回调 URL。
  • 回调数据解析错误
  • 原因分析:微信支付回调数据通常以 XML 格式返回,如果在解析回调数据时,使用的解析方法不正确或者解析库版本不兼容,可能会导致解析错误。例如,使用了不支持 XML 解析的 JSON 解析库,或者在解析 XML 数据时,没有正确处理特殊字符和节点嵌套。
  • 解决方法:使用合适的 XML 解析库,如 JAXB、Dom4j 等,并确保解析库的版本与项目环境兼容。在解析回调数据时,按照微信支付回调数据的 XML 结构进行正确的解析,处理好特殊字符和节点嵌套问题。可以通过编写单元测试来验证解析方法的正确性。

支付宝支付回调异常

  • 回调接口无法访问
  • 原因分析:与微信支付类似,网络问题和回调 URL 配置错误是导致支付宝支付回调接口无法访问的主要原因。此外,支付宝支付回调服务器可能会对回调接口的响应时间有一定要求,如果回调接口响应过慢,可能会被支付宝支付服务器判定为无效接口。例如,回调接口所在的服务器负载过高,导致处理回调请求的时间过长。
  • 解决方法:检查网络连接和防火墙设置,确保支付宝支付服务器能够正常访问回调接口。优化回调接口的性能,减少响应时间,例如通过缓存技术、优化数据库查询等方式提高接口处理速度。同时,定期检查回调 URL 的配置,确保其有效性。
  • 回调数据解析错误
  • 原因分析:支付宝支付回调数据可以是 JSON 格式或 XML 格式,具体取决于接口设置。如果在解析回调数据时,没有正确判断数据格式,或者使用的解析方法与数据格式不匹配,就会导致解析错误。例如,接口设置为返回 JSON 格式的回调数据,但代码中使用了 XML 解析方法。
  • 解决方法:在回调接口中,首先判断回调数据的格式,然后使用相应的解析方法进行解析。如果是 JSON 格式的数据,可以使用 Jackson、Gson 等 JSON 解析库;如果是 XML 格式的数据,可以使用前面提到的 JAXB、Dom4j 等 XML 解析库。同时,对解析过程进行异常处理,确保在解析失败时能够及时记录错误信息并进行相应的处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值