一、使用微信支付前言
之前公司微信支付使用的第三方支付商的支付通道,由于业务整改现决定直接对接微信官方的支付通道。在接入微信支付过程中,对接入过程进行了整理,希望对接入有需要的朋友有所帮助。
前言:
1.微信支付使用微信APIv3支付。
2.微信使用直连方式(商户模式非合作商模式)。
3.公司接入的公众号支付、小程序支付、APP支付三种支付方式。此文章以公众号支付来介绍接入微信支付,虽然是以公众号支付为事例讲解,但是博主认为集中接入并没有区别,只不过调用微信底层接口不同,入参公众号支付与小程序支付一致,APP稍有差别。
二、微信支付APIv3接入准备
接入准备看官方文档即可,讲解的很详细,博主也是按照官方文档接入准备一步一步配置完成的。
微信官方接入准备文档地址:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_1.shtml
根据官方接入准备文档,完成公众号AppID申请、商户号申请、AppID与商户号绑定、配置API key、下载配置商户证书、配置支付授权目录、配置授权域名等上述7步。
每步步骤结果如下,各位朋友可以参考:
1.申请公众号AppID
2.申请商户号mchid
3.绑定公众号AppID和商户号mchid
4.配置API key
5.配置商户证书
6.配置支付授权目录
7.设置授权域名
备注:完成配置后可与上述步骤图片进行对比确定配置结果。
三、微信支付APIv3开发指引
开发指引官方文档。
微信官方《开发指引文档》地址:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_3.shtml
1.下载微信支付 APIv3 Java SDK
官方推荐版(java): wechatpay-java
其他版本请进入到《开发指引文档》查看:
备注:博主认为是有下载需要的,可以去看事例和实现,方便学习和快速接入。
2.业务流程图
四、微信支付官方api介绍
1.接口列表
官方接口列表地址:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_4.shtml
根据自己的需求选择接入的接口。
2.官方SDK学习
–直接看README,说明指引也很详细,这里展示一下位置,不做过多展示,有兴趣的朋友可以仔细看一遍。
查看SDK中的具体实现方法
查看上下文可以看到测试方法
感兴趣的朋友可以进行试着调试一下。
五、微信支付实操接入演示
开发重点准备与说明:
商户号:
public static String merchantId = "";
商户API私钥路径 **/apiclient_key.pem
public static String privateKeyPath = "";
商户证书序列号 登录商户平台可以看到
public static String merchantSerialNumber = "";
商户APIV3密钥 登录商户平台设置
public static String apiV3key = "";
接入的整体流程:
第一步:封装支付申请对象数据以及初始化商户配置信息数据。
第二步:初始化商户配置信息。
第三步:初始化服务。
第四部:调用微信方法。
接下来看代码:
1.创建处理方法
添加依赖:
<!--wechatpay-->
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-java</artifactId>
<version>0.2.9</version>
</dependency>
/**
* <b>方法名: </b> applyPay <br>
* <b>说明: </b> 支付申请处理方法 <br>
*
* @param wechatPayApplyRequest {@link WechatPayApplyRequest}
* @return {@link PrepayResponse} <br>
* <b>修改履历: </b>
* @author 2023/6/27 zj
*/
public static PrepayResponse applyPay(WechatPayApplyRequest wechatPayApplyRequest) {
PrepayResponse response = new PrepayResponse();
try {
response = CreateRequestUtil.prepay(wechatPayApplyRequest);
logger.info("微信官方支付---支付请求完成,响应参数:{}"+ JSON.toJSONString(response));
return response;
} catch (Exception e) {
logger.error("微信官方支付---支付请求异常:", e);
}
return response;
}
CreateRequestUtil:为我们的自定义支付下单申请处理Util
WechatPayApplyRequest:封装的入参数,其中包括两部分1.初始化商户部分信息、支付申请部分信息
PrepayResponse:为我们的返回对象,微信支付提供的。
2.创建CreateRequestUtil 支付申请处理类
/**
* 创建请求工具类
*/
public class CreateRequestUtil {
/**
* 微信公众号支付下单方法
* @param wechatPayApplyRequest 支付下单入参对象
* @return prepayResponse PrepayResponse
*/
public static PrepayResponse prepay(WechatPayApplyRequest wechatPayApplyRequest) {
PrepayRequest prepayRequest = new PrepayRequest();
prepayRequest.setAppid(wechatPayApplyRequest.getAppid());
prepayRequest.setMchid(wechatPayApplyRequest.getMchid());
prepayRequest.setDescription(wechatPayApplyRequest.getDescription());
prepayRequest.setOutTradeNo(wechatPayApplyRequest.getOutTradeNo());
if(null !=wechatPayApplyRequest.getTimeExpire() ){
prepayRequest.setTimeExpire(wechatPayApplyRequest.getTimeExpire());
}
if(null !=wechatPayApplyRequest.getAttach() ){
prepayRequest.setAttach(wechatPayApplyRequest.getAttach());
}
prepayRequest.setNotifyUrl(wechatPayApplyRequest.getNotifyUrl());
if(null !=wechatPayApplyRequest.getGoodsTag() ){
prepayRequest.setGoodsTag(wechatPayApplyRequest.getGoodsTag());
}
if(null !=wechatPayApplyRequest.getSupportFapiao() ){
prepayRequest.setSupportFapiao(wechatPayApplyRequest.getSupportFapiao());
}
prepayRequest.setAmount(wechatPayApplyRequest.getAmount());
prepayRequest.setPayer(wechatPayApplyRequest.getPayer());
if(null !=wechatPayApplyRequest.getDetail() ){
prepayRequest.setDetail(wechatPayApplyRequest.getDetail());
}
if(null !=wechatPayApplyRequest.getSceneInfo() ){
prepayRequest.setSceneInfo(wechatPayApplyRequest.getSceneInfo());
}
if(null !=wechatPayApplyRequest.getSettleInfo() ){
prepayRequest.setSettleInfo(wechatPayApplyRequest.getSettleInfo());
}
// 获取、初始化商户配置
Config config = MerchantUtil.getInstance().handleMer(wechatPayApplyRequest.getMchid(),
wechatPayApplyRequest.getPrivateFilePath(),wechatPayApplyRequest.getPrivateFileSn(),
wechatPayApplyRequest.getApiPrivate());
// 初始化服务
JsapiService service = new JsapiService.Builder().config(config).build();
// 调用处理接口,返回微信下单服务处理结果
return service.prepay(prepayRequest);
}
}
重要步骤:
(1)方法上部分为复制对象。
(2)初始化商户配置,博主也是创建了一个自定义Util来进行处理,这里需要注意的一点,项目启动后只需要初始化一次即可,所以要用单利来进行处理。
(3)初始化服务
(4)调用微信jar包中的方法,传入参数。
3.创建初始化商户配置类MerchantUtil
/**
* 商户初始化工具类
* 懒加载单利处理
*/
public class MerchantUtil {
private static MerchantUtil merchantUtil =null;
private static RSAAutoCertificateConfig config =null;
public MerchantUtil() {
}
public static synchronized MerchantUtil getInstance(){
if(merchantUtil ==null){
synchronized (MerchantUtil.class){
if(merchantUtil == null){
merchantUtil = new MerchantUtil();
}
}
}
return merchantUtil;
}
/**
* 微信公众号支付商户数据处理方法
* @param merchantId 直连商户的商户号,由微信支付生成并下发。
* @param privateKeyPath 商户API私钥路径
* @param merchantSerialNumber 商户证书序列号
* @param apiV3key 商户APIV3密钥
* @return config Config
*/
public static RSAAutoCertificateConfig handleMer(String merchantId, String privateKeyPath, String merchantSerialNumber, String apiV3key){
if(config ==null){
config = new RSAAutoCertificateConfig.Builder()
.merchantId(merchantId)
.privateKeyFromPath(privateKeyPath)
.merchantSerialNumber(merchantSerialNumber)
.apiV3Key(apiV3key)
.build();
}
return config;
}
}
这里肯定好多朋友会有疑问,为什么不在项目启动的时候初始化商户配置,我在这里说一下。我们的项目做了支付中心-》支付api-〉三方支付通道,做了接入隔离放到了支付api中,以jar的形式在支付中心引入,所以采用这种方式。各位朋友可以按照自己的需求和架构来设计。
商户配置初始化的两种方式:
(1)上面我们MerchantUtil中的这种,使用的是apiV3Key
(2)在上面讲微信官方sdk时提到的,用微信平台证书的方式
各位朋友根据自己的实际来
4.支付申请入参对象WechatPayApplyRequest
public class WechatPayApplyRequest {
/**
* 由微信生成的应用ID,全局唯一。请求基础下单接口时请注意APPID的应用属性,例如公众号场景下,需使用应用属性为公众号的服务号APPID
* 示例值:wxd678efh567hg6787
*/
private String appid;
/**
* 直连商户的商户号,由微信支付生成并下发。
* 示例值:1230000109
*/
private String mchid;
/**
* 商户API私钥路径
*/
private String privateFilePath;
/**
* 商户证书序列号
*/
public String privateFileSn;
/**
* 商户APIV3密钥
*/
private String apiPrivate;
/**
* 商品描述
* 示例值:Image形象店-深圳腾大-QQ公仔
*/
private String description;
/**
* 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一
*/
private String outTradeNo;
/**
* 否
* 订单失效时间,遵循rfc3339标准格式,格式为yyyy-MM-DDTHH:mm:ss+TIMEZONE,yyyy-MM-DD表示年月日,T出现在字符串中,表示time元素的开头,
* HH:mm:ss表示时分秒,TIMEZONE表示时区(+08:00表示东八区时间,领先UTC8小时,即北京时间)。例如:2015-05-20T13:29:35+08:00表示,
* 北京时间2015年5月20日 13点29分35秒。
* 示例值:2018-06-08T10:34:56+08:00
*/
private String timeExpire;
/**
* 否
* 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用,实际情况下只有支付完成状态才会返回该字段。
* 示例值:自定义数据
*/
private String attach;
/**
* 异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。 公网域名必须为https,如果是走专线接入,
* 使用专线NAT IP或者私有回调域名可使用http
* 示例值:https://www.weixin.qq.com/wxpay/pay.php
*/
private String notifyUrl;
/**
* 否
* 订单优惠标记
* 示例值:WXG
*/
private String goodsTag;
/**
* 否
* 传入true时,支付成功消息和支付详情页将出现开票入口。需要在微信支付商户平台或微信公众平台开通电子发票功能,传此字段才可生效。
* true:是
* false:否
* 示例值:true
*/
private Boolean supportFapiao;
/**
* 订单金额信息(分)人民币
*/
private Amount amount;
/**
* 支付者信息
* 用户在直连商户appid下的唯一标识。 下单前需获取到用户的Openid,Openid获取详见
* 示例值:oUpF8uMuAJO_M2pxb1Q9zNjWeS6o
*/
private Payer payer;
/**
* 否
* 优惠功能
*/
private Detail detail;
/**
* 支付场景描述
*/
private SceneInfo sceneInfo;
/**
* 结算信息
*/
private SettleInfo settleInfo;
}
具体参数各位朋友可以去看官方api接口文档
或者查看官方微信sdk中支付申请的入参对象
各位朋友可以自己尝试自己接入一下,其实在看过官方sdk后在接入还是比较简单的。
其他支付回调、退款申请、退款回调等接口也可以按照此方式进行,现查看官方sdk事例。
预祝各位朋友顺利接入成功!!!
六、代码实例DEMO
github地址:https://github.com/zjfg/pay-api.git
Demo中接入的支付申请,支付回调,退款申请,退款回调等微信支付的接口,可以为各位朋友提供参考:
1.添加配置信息即可使用:
配置相关参数,启动即可使用测试