java微信支付v3系列——9.微信支付之商家转账API

目录

java微信支付v3系列——1.微信支付准备工作
java微信支付v3系列——2.微信支付基本配置
java微信支付v3系列——3.订单创建准备操作
java微信支付v3系列——4.创建订单的封装及使用
java微信支付v3系列——5.微信支付成功回调
java微信支付v3系列——6.微信支付查询订单API
java微信支付v3系列——7.微信支付之申请退款
java微信支付v3系列——8.微信支付之退款成功回调
java微信支付v3系列——9.微信支付之商家转账API

正文

这个功能就比较复杂了,首先是得有90天的资金流水才能开通,其次开通后还需要在官网进行配置,不能直接调用,并且限制了IP地址。

如下图所示,首先需要进行产品设置,将里面都设置好后才能进行开发,只开通功能是远远不够的。

image-20220805130622451

image-20220805130533437

商家转账设置说明及避坑指南

  • 页面发起:即登录微信支付后,手动输入用户信息,进行转账
  • 验密批量API:开启这个才能调用API,否则会提示没有调用API的权限

单笔付款区间默认1-200元,最低改为0.3,所以你去提现0.01去做测试是没有效果的。

image-20220805164244551

这个钱不是从“基本账户”扣除的,而是从运营账户扣除的,如果提示“提现失败,商家运营账户资金不足”,那你可就要看看运营账户里面是不是没钱了。

请求参数及讲解

商家转账支持一次性多次转账,一次最多可以发起3000笔转账,估计是为了防止营销手段,所以该接口设置了QPS为50,注意自己的业务,别踩雷!

那么数据可以理解为,转账说明,和详细说明。也就是由转账信息+转账对象列表组成,请求的json官方实例如下。

{
  "appid": "wxf636efh567hg4356",
  "out_batch_no": "plfk2020042013",
  "batch_name": "2019年1月深圳分部报销单",
  "batch_remark": "2019年1月深圳分部报销单",
  "total_amount": 4000000,
  "total_num": 200,
  "transfer_detail_list": [
    {
      "out_detail_no": "x23zy545Bd5436",
      "transfer_amount": 200000,
      "transfer_remark": "2020年4月报销",
      "openid": "o-MYE42l80oelYMDE34nYD456Xoy",
      "user_name": "757b340b45ebef5467rter35gf464344v3542sdf4t6re4tb4f54ty45t4yyry45"
    }
  ]
}

那么我们可以封装为:

/**
 * @author cv大魔王
 * @version 1.0
 * @description 微信支付商家转账到零钱请求参数
 * @date 2022/8/4
 */
@Data
public class WechatTransferBatchesParam {

    /**
     * 商户系统内部的商家批次单号,对应 out_batch_no,
     */
    private String batchId;

    /**
     * 该笔批量转账的名称,对应 batch_name,示例值:2019年1月深圳分部报销单
     */
    private String title;

    /**
     * 批次备注
     */
    private String remark;

    /**
     * 转账总金额
     */
    private BigDecimal totalMoney;

    /**
     * 转账明细列表
     */
    private List<transferDetail> transferDetailList;

    @Data
    public static class transferDetail {

        /**
         * 商户系统内部的商家批次单号,对应 out_detail_no,
         */
        private String batchId;

        /**
         * 转账金额
         */
        private BigDecimal totalDetailMoney;

        /**
         * 转账备注
         */
        private String detailRemark;

        /**
         * openid是微信用户在公众号(小程序)appid下的唯一用户标识
         */
        private String openid;
    }
}

商家转账请求工具类

这里和发起创建支付订单的请求相似,因此不单独列出,首先是封装转账请求参数,然后是获取请求对象发起请求,完成签名验证发送请求,最后解析数据,如果转账失败则返回提示信息给用户。

@Slf4j
public class WxPayTransferBatchesUtils {

    /**
     * 发起商家转账,支持批量转账
     *
     * @param wxPayConfig 微信配置信息
     * @param param 转账请求参数
     * @param wxPayClient 微信请求客户端()
     * @return 微信支付二维码地址
     */
    public static String transferBatches(WxPayConfig wxPayConfig, WechatTransferBatchesParam param, CloseableHttpClient wxPayClient) {
        // 1.获取请求参数的Map格式
        Map<String, Object> paramsMap = getParams(wxPayConfig, param);

        // 2.获取请求对象,WxApiType.TRANSFER_BATCHES="/v3/transfer/batches"
        HttpPost httpPost = getHttpPost(wxPayConfig,WxApiType.TRANSFER_BATCHES , paramsMap);

        // 3.完成签名并执行请求
        CloseableHttpResponse response = null;
        try {
            response = wxPayClient.execute(httpPost);
        } catch (IOException e) {
            e.printStackTrace();
            throw new DefaultException("商家转账请求失败");
        }

        // 4.解析response对象
        HashMap<String, String> resultMap = resolverResponse(response);
        if (resultMap != null) {
            // batch_id微信批次单号,微信商家转账系统返回的唯一标识
            return resultMap.get("batch_id");
        }
        return null;
    }


    /**
     * 解析响应数据
     * @param response 发送请求成功后,返回的数据
     * @return 微信返回的参数
     */
    private static HashMap<String, String> resolverResponse(CloseableHttpResponse response) {
        try {
            // 1.获取请求码
            int statusCode = response.getStatusLine().getStatusCode();
            // 2.获取返回值 String 格式
            final String bodyAsString = EntityUtils.toString(response.getEntity());

            Gson gson = new Gson();
            if (statusCode == 200) {
                // 3.如果请求成功则解析成Map对象返回
                HashMap<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class);
                return resultMap;
            } else {
                if (StringUtils.isNoneBlank(bodyAsString)) {
                    log.error("商户转账请求失败,提示信息:{}", bodyAsString);
                    // 4.请求码显示失败,则尝试获取提示信息
                    HashMap<String, String> resultMap = gson.fromJson(bodyAsString, HashMap.class);
                    throw new DefaultException(resultMap.get("message"));
                }
                log.error("商户转账请求失败,未查询到原因,提示信息:{}", response);
                // 其他异常,微信也没有返回数据,这就需要具体排查了
                throw new IOException("request failed");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new DefaultException(e.getMessage());
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 获取请求对象(Post请求)
     *
     * @param wxPayConfig 微信配置类
     * @param apiType     接口请求地址
     * @param paramsMap   请求参数
     * @return Post请求对象
     */
    private static HttpPost getHttpPost(WxPayConfig wxPayConfig, WxApiType apiType, Map<String, Object> paramsMap) {
        // 1.设置请求地址
        HttpPost httpPost = new HttpPost(wxPayConfig.getDomain().concat(apiType.getType()));

        // 2.设置请求数据
        Gson gson = new Gson();
        String jsonParams = gson.toJson(paramsMap);

        // 3.设置请求信息
        StringEntity entity = new StringEntity(jsonParams, "utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");
        return httpPost;
    }

    /**
     * 封装转账请求参数
     *
     * @param wxPayConfig 微信的配置文件
     * @param param 批量转账请求数据
     * @return 封装后的map对象
     */
    private static Map<String, Object> getParams(WxPayConfig wxPayConfig, WechatTransferBatchesParam param) {
        Map<String, Object> paramsMap = new HashMap<>();
        paramsMap.put("appid", wxPayConfig.getAppid());
        paramsMap.put("out_batch_no", param.getBatchId());
        paramsMap.put("batch_name", param.getTitle());
        paramsMap.put("batch_remark", param.getRemark());
        paramsMap.put("total_amount", param.getTotalMoney().multiply(new BigDecimal("100")).intValue());
        paramsMap.put("total_num", param.getTransferDetailList().size());

        // 存储转账明细,一次最多三千笔
        if (param.getTransferDetailList().size() > 3000) {
            throw new DefaultException("发起批量转账一次最多三千笔");
        }
        List<Map<String, Object>> detailList = new ArrayList<>();
        for (WechatTransferBatchesParam.transferDetail detail : param.getTransferDetailList()) {
            Map<String, Object> detailMap = new HashMap<>();
            detailMap.put("out_detail_no",detail.getBatchId());
            detailMap.put("transfer_amount",detail.getTotalDetailMoney().multiply(new BigDecimal("100")).intValue());
            detailMap.put("transfer_remark",detail.getDetailRemark());
            detailMap.put("openid",detail.getOpenid());
            detailList.add(detailMap);
        }
        paramsMap.put("transfer_detail_list", detailList);
        return paramsMap;
    }
}

使用方法

@Autowired
private WxPayConfig wxPayConfig;

@Autowired
private CloseableHttpClient wxPayClient;
@ApiOperation("转账测试")
@GetMapping("/transfer/batches")
public String transferBatches() {
    WechatTransferBatchesParam param = new WechatTransferBatchesParam();
    String batchId = IdWorker.getIdStr();
    log.info("转账Id:{}", batchId);
    param.setBatchId(batchId);
    param.setTitle("转账测试");
    param.setRemark("转账测试");
    param.setTotalMoney(new BigDecimal("0.02"));


    // 批量转账,可以同时转账给多人,但是不能超过3000,我这里只转账给一个人,只用来测试
    List<WechatTransferBatchesParam.transferDetail> detailList = new ArrayList<>();
    WechatTransferBatchesParam.transferDetail detail = new WechatTransferBatchesParam.transferDetail();
    detail.setBatchId(batchId);
    detail.setTotalDetailMoney(new BigDecimal("0.02"));
    detail.setDetailRemark("转账测试详情");
    detail.setOpenid("DF7E6901802E9F75A6FB45137C6D3685");
    detailList.add(detail);


    param.setTransferDetailList(detailList);
    return WxPayTransferBatchesUtils.transferBatches(wxPayConfig,param,wxPayClient);
}

麻烦点个赞再走吧~~

  • 16
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
作为一款全球流行的社交软件,微信的架构设计非常复杂和庞大。微信的架构涉及到包括移动客户端、服务器、数据库、网络通信等多个方面。下面将对微信的架构进行详细的介绍。 一、微信移动客户端架构 微信移动客户端是微信的主要入口,也是用户使用最为频繁的部分。微信移动客户端主要包括以下几个模块: 1.登录模块:用户需要先进行注册和登录才能使用微信,登录模块主要实现用户身份验证和授权。 2.聊天模块:微信最核心的模块,主要实现文字、语音、视频、图片等多种形式的聊天功能。 3.通讯录模块:主要实现好友管理、添加好友、查找好友等功能。 4.发现模块:主要提供了微信朋友圈、公众号、小程序等功能,让用户可以更方便地浏览和使用。 5.我模块:主要提供了账户管理、设置、支付等功能。 微信移动客户端采用MVC(Model-View-Controller)架构,将客户端的业务逻辑、界面显示和用户交互分离开来,使得代码更加模块化和清晰。其中,Model层主要负责业务逻辑的处理和数据的操作,View层主要负责用户界面的显示和交互,Controller层主要负责协调Model和View的交互。 二、微信服务器架构 微信服务器是微信移动客户端和其他系统之间的中间件,主要负责数据的传输和处理。微信服务器主要包括以下几个模块: 1.登录验证模块:用户登录后,微信服务器需要对用户进行身份验证和授权,并生成相应的token。 2.消息传输模块:微信服务器需要将用户发送的消息进行传输和处理,包括文字、语音、视频、图片等多种形式的消息。 3.好友管理模块:微信服务器需要对好友关系进行管理,包括添加好友、删除好友、查找好友等。 4.朋友圈管理模块:微信服务器需要对朋友圈进行管理,包括发表动态、评论和点赞等。 5.支付模块:微信服务器需要对用户的支付进行管理,包括支付请求、支付处理和支付结果通知等。 微信服务器采用分布式架构,将不同的功能模块分别部署在不同的服务器上,以提高系统的稳定性和可扩展性。同时,微信服务器采用负载均衡技术,将访问请求分配到不同的服务器上,以降低单一服务器的压力。 三、微信数据库架构 微信数据库主要用于存储用户信息、聊天记录、朋友圈动态、支付记录等数据。微信数据库采用分布式数据库架构,将不同类型的数据分别存储在不同的数据库中。具体来说,微信采用以下几种数据库: 1.关系型数据库:主要用于存储用户信息、聊天记录和支付记录等数据,采用MySQL和Oracle等关系型数据库。 2.非关系型数据库:主要用于存储朋友圈动态和其他非结构化数据,采用MongoDB和Redis等非关系型数据库。 3.图数据库:主要用于存储社交网络数据,采用Neo4j等图数据库。 微信数据库采用分库分表技术,将数据按照用户ID进行分片存储,以提高数据库的性能和扩展性。同时,微信数据库采用主从复制和备份技术,以保证数据的安全性和可靠性。 四、微信网络通信架构 微信的网络通信架构主要包括移动网络、运营商网络、互联网和微信服务器之间的通信。微信采用HTTPS加密协议进行通信,以保证数据的安全性和可靠性。具体来说,微信的通信架构包括以下几个部分: 1.移动网络:主要是用户的移动设备和运营商之间的通信,包括2G、3G、4G和5G等移动网络。 2.运营商网络:主要是用户的移动设备和微信服务器之间的通信,包括电信、联通和移动等运营商网络。 3.互联网:主要是微信服务器之间的通信,采用互联网协议TCP/IP进行通信。 4.微信服务器:主要是微信移动客户端和其他系统之间的中间件,采用HTTPS协议进行通信。 微信的网络通信架构采用CDN(Content Delivery Network)技术,将用户请求分配到离用户最近的服务器上,以提高访问速度和减少网络延迟。同时,微信采用反向代理和负载均衡技术,将访问请求分配到不同的服务器上,以降低单一服务器的压力。 五、微信技术架构 微信的技术架构主要由以下几个方面组成: 1.移动开发技术:微信移动客户端采用原生开发技术,包括iOS和Android两个平台,同时还采用了React Native和Flutter等跨平台开发技术。 2.服务器开发技术:微信服务器采用Java、Python、C++等编程语言进行开发,同时还采用了Spring、Hibernate、MyBatis等框架和技术。 3.数据库技术:微信数据库采用MySQL、Oracle、MongoDB、Redis等数据库技术。 4.网络通信技术:微信采用HTTPS、TCP/IP、CDN、反向代理、负载均衡等网络通信技术。 5.大数据技术:微信采用Hadoop、Spark、HBase等大数据技术进行数据分析和处理。 微信技术架构是一个复杂而庞大的系统,涉及到多种技术和工具的应用和整合。微信技术架构的设计和优化,对于提高微信的性能和稳定性具有重要意义。 六、微信安全架构 微信的安全架构主要包括以下几个方面: 1.身份验证和授权:微信使用OAuth 2.0协议进行身份验证和授权,以保证用户的身份安全。 2.数据加密和解密:微信采用AES加密算法进行数据加密和解密,以保证数据的安全性。 3.防范攻击:微信采用防火墙、入侵检测、反病毒等安全技术,防范各种攻击和恶意软件。 4.数据备份和恢复:微信采用数据备份和恢复技术,以保证数据的安全性和可靠性。 微信的安全架构采用多层次和多重保护措施,以保证用户的账户和数据的安全性和可靠性。 七、微信数据分析架构 微信数据分析架构主要用于对用户数据进行收集、分析和处理,以提供更好的用户体验和服务。微信数据分析架构主要包括以下几个方面: 1.数据收集:微信采用数据收集工具,收集用户的行为数据、社交网络数据、搜索数据等。 2.数据存储:微信采用分布式数据库和云存储技术,存储用户的数据,包括用户信息、聊天记录、朋友圈动态等。 3.数据处理:微信采用Hadoop、Spark、HBase等大数据技术,对用户数据进行处理和分析,提供更好的用户体验和服务。 4.数据可视化:微信采用数据可视化技术,将数据以图表、报表等形式展现出来,方便用户进行数据分析和决策。 微信数据分析架构的设计和优化,对于提高微信的用户体验和服务质量具有重要意义。 综上所述,微信的架构设计非常复杂和庞大,涉及到移动客户端、服务器、数据库、网络通信、技术、安全和数据分析等多个方面。微信的架构设计和优化,对于提高微信的性能、可靠性和安全性,以及提供更好的用户体验和服务质量具有重要意义。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CV大魔王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值