微信商家转账常见的一些问题汇总(附Java调用示例)

 更新时间:2025年12月21日 13:56:30   作者:xxxzsh  
这篇文章主要介绍了微信商家转账常见的一些问题汇总,文中附Java调用示例,包括IP地址不允许调用接口、APPID不存在、未获取转账场景、暂不支持展示用户收款感知、未传入完整且对应的转账场景报备信息以及商户运营账户资金不足等问题的解决步骤,需要的朋友可以参考下

前言

官方也汇总了一个QA,常见问题_商家转账|微信支付商户文档中心

大家可以直接看官方的。

我这边是我自己遇到的就蛮记录下来,相比官网的更口语化一点。

1,此IP地址不允许调用接口,请按开发指引设置

{
    "code": "INVALID_REQUEST",
    "message": "此IP地址不允许调用接口,请按开发指引设置"
}

这个就是要设置一下白名单,扫码登陆商户平台

产品中心 -> 运营工具 -> 商家转账 -> 前往功能 ->安全能力-> 点击「接口IP」

按需选择场景就好,关键是IP要添加一下开发者和服务器的IP就行了。

有ipv6的话记得也得填。

2,APPID不存在

{
    "code": "INVALID_REQUEST",
    "message": "APPID不存在"
}

这个是你得把你要调用的这个小程序或者公众号啥的关联到这个商户号上。

打开产品中心 -> AppID账号管理 -> 账号关联

进入授权申请页面;

可以看看官方文档:APPID授权管理功能介绍 - 微信支付商户平台

授权完之后要到微信公众平台那边点击接受,就可以了。 

3,你尚未获取该转账场景

{
    "code": "INVALID_REQUEST",
    "message": "你尚未获取该转账场景"
}

转账场景说白了就是你转账的用途。后面的接口调用全都需要跟你的场景挂钩,不同场景的参数都是不同的。

打开:产品中心 > 运营工具 > 商家转账到零钱 > 前往功能 > 转账场景。

然后就是选择、申请、等审核。

4,暂不支持展示当前传入的用户收款感知

{
    "code": "INVALID_REQUEST",
    "message": "暂不支持展示当前传入的用户收款感知"
}

用户收款感知 说白了就是当微信把钱打给用户时,在用户微信里展示一些“这是什么钱”的提示。对应字段:user_recv_perception

比如:

  • “现金奖励”

  • “拉新红包”

  • “活动奖励”

每个转账场景要填的内容都不一样。各场景展示的默认内容和支持传入的内容详见官方文档:
现金营销_商家转账|微信支付商户文档中心:https://pay.weixin.qq.com/doc/v3/merchant/4013774588在左侧可以选场景:

举个例子,比如上图的 佣金报酬(transfer_scene_id = 1005) 场景下,你只能支持这几个:【劳务报酬】、【报销款】、【企业补贴】、【开工利是】,不传则默认展示【劳务报酬】。

你如果填了别的,就会报这个 “暂不支持...” 这个错。

所以按文档和你的转账场景填就行了。

5,未传入完整且对应的转账场景报备信息,请根据接口文档检查

{
    "code": "PARAM_ERROR",
    "message": "未传入完整且对应的转账场景报备信息,请根据接口文档检查"
}

转账场景报备信息 说白了就是给微信审核用的,告诉微信 “我这个转账是什么用途”,符合政策才允许转账。对应字段:transfer_scene_report_infos

比如:

  • 转账原因

  • 场景说明

  • 奖励类型

每个场景要传的参数都不同。具体每个场景要传的参数可以在这里看:现金营销_商家转账|微信支付商户文档中心:https://pay.weixin.qq.com/doc/v3/merchant/4013774588
在左侧可以选场景:

以佣金报酬为例,如上图,他这里写着了 必须要岗位类型和报酬说明,那调用时就这样:

就可以了。

6,商户运营账户资金不足,充值后可以原单号发起重试,请勿更换商户单号

{
    "code": "NOT_ENOUGH",
    "message": "商户运营账户资金不足,充值后可以原单号发起重试,请勿更换商户单号"
}

很明显,要充钱。不过记得是要充到运营账户里面,不是这个基本账户:

Java的调用示例:

package co.yixiang.modules.transferToUser.utils;

import com.google.gson.annotations.SerializedName;
import lombok.Data;
import okhttp3.*;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.security.PrivateKey;
import java.util.ArrayList;
import java.util.List;

/**
 * 发起转账
 */
public class TransferToUser {
    private static String HOST = "https://api.mch.weixin.qq.com";
    private static String METHOD = "POST";
    private static String PATH = "/v3/fund-app/mch-transfer/transfer-bills";

    public static void main(String[] args) {
        // TODO: 请准备商户开发必要参数,参考:https://pay.weixin.qq.com/doc/v3/merchant/4013070756
        TransferToUser client = new TransferToUser(
                "12321321",                    // 商户号,是由微信支付系统生成并分配给每个商户的唯一标识符,商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/merchant/4013070756
                "12321321321321312",         // 商户API证书序列号,如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013053053
                "E:\\Java_project_self\privateKey.pem"     // 商户API证书私钥文件路径,本地文件路径
        );

        TransferToUserRequest request = new TransferToUserRequest();
        request.appid = "wx213123213";
        request.outBillNo = "plfk212DS" + System.currentTimeMillis();
        request.transferSceneId = "1005";
        request.openid = "21321321321213";
        request.transferAmount = 10L;
        request.transferRemark = "佣金提现到账";
        request.notifyUrl = "https://www.weixin.qq.com/wxpay/pay.php";

        List<TransferSceneReportInfo> list = new ArrayList<>();

        TransferSceneReportInfo info1 = new TransferSceneReportInfo();
        info1.infoType = "岗位类型";
        info1.infoContent = "分享有礼";
        list.add(info1);

        TransferSceneReportInfo info2 = new TransferSceneReportInfo();
        info2.infoType = "报酬说明";
        info2.infoContent = "用户推广获得佣金";
        list.add(info2);

        request.userRecvPerception = "劳务报酬";
        request.transferSceneReportInfos = list;

        try {
            TransferToUserResponse response = client.run(request);
            // TODO: 请求成功,继续业务逻辑
            System.out.println(response);
        } catch (Exception e) {
            // TODO: 请求失败,根据状态码执行不同的逻辑
            e.printStackTrace();
        }
    }

    public TransferToUserResponse run(TransferToUserRequest request) {
        String uri = PATH;
        String reqBody = WXPayUtility.toJson(request);

        Request.Builder reqBuilder = new Request.Builder().url(HOST + uri);
        reqBuilder.addHeader("Accept", "application/json");

        reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchid, certificateSerialNo, privateKey, METHOD, uri, reqBody));
        reqBuilder.addHeader("Content-Type", "application/json");
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody);
        reqBuilder.method(METHOD, requestBody);
        Request httpRequest = reqBuilder.build();

        // 发送HTTP请求
        OkHttpClient client = new OkHttpClient.Builder().build();
        try (Response httpResponse = client.newCall(httpRequest).execute()) {
            String respBody = WXPayUtility.extractBody(httpResponse);
            if (httpResponse.code() >= 200 && httpResponse.code() < 300) {
                // 2XX 成功,验证应答签名
//                WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey,
//                        httpResponse.headers(), respBody);

                // 从HTTP应答报文构建返回数据
                return WXPayUtility.fromJson(respBody, TransferToUserResponse.class);
            } else {
                throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers());
            }
        } catch (IOException e) {
            throw new UncheckedIOException("Sending request to " + uri + " failed.", e);
        }
    }

    private final String mchid;
    private final String certificateSerialNo;
    private final PrivateKey privateKey;

    public TransferToUser(String mchid, String certificateSerialNo, String privateKeyFilePath) {
        this.mchid = mchid;
        this.certificateSerialNo = certificateSerialNo;
        this.privateKey = WXPayUtility.loadPrivateKeyFromPath(privateKeyFilePath);
    }

    @Data
    public static class TransferToUserRequest {
        @SerializedName("appid")
        public String appid;

        @SerializedName("out_bill_no")
        public String outBillNo;

        @SerializedName("transfer_scene_id")
        public String transferSceneId;

        @SerializedName("openid")
        public String openid;

        @SerializedName("user_name")
        public String userName;

        @SerializedName("transfer_amount")
        public Long transferAmount;

        @SerializedName("transfer_remark")
        public String transferRemark;

        @SerializedName("notify_url")
        public String notifyUrl;

        @SerializedName("user_recv_perception")
        public String userRecvPerception;

        @SerializedName("transfer_scene_report_infos")
        public List<TransferSceneReportInfo> transferSceneReportInfos = new ArrayList<TransferSceneReportInfo>();
    }

    @Data
    public static class TransferToUserResponse {
        @SerializedName("out_bill_no")
        public String outBillNo;

        @SerializedName("transfer_bill_no")
        public String transferBillNo;

        @SerializedName("create_time")
        public String createTime;

        @SerializedName("state")
        public TransferBillStatus state;

        @SerializedName("package_info")
        public String packageInfo;
    }

    @Data
    public static class TransferSceneReportInfo {
        @SerializedName("info_type")
        public String infoType;

        @SerializedName("info_content")
        public String infoContent;
    }

    public enum TransferBillStatus {
        @SerializedName("ACCEPTED")
        ACCEPTED,
        @SerializedName("PROCESSING")
        PROCESSING,
        @SerializedName("WAIT_USER_CONFIRM")
        WAIT_USER_CONFIRM,
        @SerializedName("TRANSFERING")
        TRANSFERING,
        @SerializedName("SUCCESS")
        SUCCESS,
        @SerializedName("FAIL")
        FAIL,
        @SerializedName("CANCELING")
        CANCELING,
        @SerializedName("CANCELLED")
        CANCELLED
    }

}

总结 

到此这篇关于微信商家转账常见的一些问题汇总的文章就介绍到这了,更多相关微信商家转账常见问题Java内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 快速入门HarmonyOS的Java UI框架的教程

    快速入门HarmonyOS的Java UI框架的教程

    这篇文章主要介绍了快速入门HarmonyOS的Java UI框架,本文给大家介绍的非常详细对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • Java IO流对文件File操作

    Java IO流对文件File操作

    这篇文章主要介绍了Java IO流对文件File操作,java封装的一个操作文件及文件夹(目录)的对象。可以操作磁盘上的任何一个文件和文件夹
    2022-12-12
  • java中如何对arrayList按数字大小逆序排序

    java中如何对arrayList按数字大小逆序排序

    这篇文章主要介绍了java中如何对arrayList按数字大小逆序排序问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • Spring security 自定义过滤器实现Json参数传递并兼容表单参数(实例代码)

    Spring security 自定义过滤器实现Json参数传递并兼容表单参数(实例代码)

    这篇文章主要介绍了Spring security 自定义过滤器实现Json参数传递并兼容表单参数,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • SpringBoot中@Transiactional注解没有效果的解决

    SpringBoot中@Transiactional注解没有效果的解决

    这篇文章主要介绍了SpringBoot中@Transiactional注解没有效果的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • 解决Nacos在执行startup.cmd的时候出现闪退的问题

    解决Nacos在执行startup.cmd的时候出现闪退的问题

    因为在工作中的项目中需要使用到nacos作为注册中心,但是在使用nacos的过程中运行startup.cmd的时候出现了闪退的情况,运行startup.cmd闪一下就没有了,我把解决这个问题的全过程理了一下,希望能帮到您,需要的朋友可以参考下
    2023-12-12
  • Java Stream 的 flatMap 与 map 的核心区别从原理到实战应用全解析

    Java Stream 的 flatMap 与 map 的核

    map进行元素到元素的单层转换,flatMap则将元素映射为流后再扁平化处理,适用于嵌套结构展开,二者核心差异在于是否展开多层数据,选择时需根据数据结构层级和性能需求决定,本文给大家介绍Java Stream 的flatMap与map的核心区别,感兴趣的朋友一起看看吧
    2025-08-08
  • idea中提示Class 'xxx' is never used的解决

    idea中提示Class 'xxx' is never us

    这篇文章主要介绍了idea中提示Class 'xxx' is never used的解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • 使用fileupload组件实现文件上传功能

    使用fileupload组件实现文件上传功能

    这篇文章主要为大家详细介绍了使用fileupload实现文件上传功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-10-10
  • IDEA突然无法使用Git功能的问题解决

    IDEA突然无法使用Git功能的问题解决

    本文主要介绍了IDEA突然无法使用Git功能的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-08-08

最新评论