微信商家轉(zhuǎn)賬常見的一些問題匯總(附Java調(diào)用示例)
前言
官方也匯總了一個QA,常見問題_商家轉(zhuǎn)賬|微信支付商戶文檔中心
大家可以直接看官方的。
我這邊是我自己遇到的就蠻記錄下來,相比官網(wǎng)的更口語化一點(diǎn)。
1,此IP地址不允許調(diào)用接口,請按開發(fā)指引設(shè)置
{
"code": "INVALID_REQUEST",
"message": "此IP地址不允許調(diào)用接口,請按開發(fā)指引設(shè)置"
}
這個就是要設(shè)置一下白名單,掃碼登陸商戶平臺
產(chǎn)品中心 -> 運(yùn)營工具 -> 商家轉(zhuǎn)賬 -> 前往功能 ->安全能力-> 點(diǎn)擊「接口IP」


按需選擇場景就好,關(guān)鍵是IP要添加一下開發(fā)者和服務(wù)器的IP就行了。

有ipv6的話記得也得填。
2,APPID不存在
{
"code": "INVALID_REQUEST",
"message": "APPID不存在"
}
這個是你得把你要調(diào)用的這個小程序或者公眾號啥的關(guān)聯(lián)到這個商戶號上。
打開產(chǎn)品中心 -> AppID賬號管理 -> 賬號關(guān)聯(lián)
進(jìn)入授權(quán)申請頁面;

可以看看官方文檔:APPID授權(quán)管理功能介紹 - 微信支付商戶平臺
授權(quán)完之后要到微信公眾平臺那邊點(diǎn)擊接受,就可以了。
3,你尚未獲取該轉(zhuǎn)賬場景
{
"code": "INVALID_REQUEST",
"message": "你尚未獲取該轉(zhuǎn)賬場景"
}
轉(zhuǎn)賬場景說白了就是你轉(zhuǎn)賬的用途。后面的接口調(diào)用全都需要跟你的場景掛鉤,不同場景的參數(shù)都是不同的。
打開:產(chǎn)品中心 > 運(yùn)營工具 > 商家轉(zhuǎn)賬到零錢 > 前往功能 > 轉(zhuǎn)賬場景。


然后就是選擇、申請、等審核。
4,暫不支持展示當(dāng)前傳入的用戶收款感知
{
"code": "INVALID_REQUEST",
"message": "暫不支持展示當(dāng)前傳入的用戶收款感知"
}
用戶收款感知 說白了就是當(dāng)微信把錢打給用戶時,在用戶微信里展示一些“這是什么錢”的提示。對應(yīng)字段:user_recv_perception
比如:
“現(xiàn)金獎勵”
“拉新紅包”
“活動獎勵”
每個轉(zhuǎn)賬場景要填的內(nèi)容都不一樣。各場景展示的默認(rèn)內(nèi)容和支持傳入的內(nèi)容詳見官方文檔:
現(xiàn)金營銷_商家轉(zhuǎn)賬|微信支付商戶文檔中心:https://pay.weixin.qq.com/doc/v3/merchant/4013774588在左側(cè)可以選場景:

舉個例子,比如上圖的 傭金報酬(transfer_scene_id = 1005) 場景下,你只能支持這幾個:【勞務(wù)報酬】、【報銷款】、【企業(yè)補(bǔ)貼】、【開工利是】,不傳則默認(rèn)展示【勞務(wù)報酬】。
你如果填了別的,就會報這個 “暫不支持...” 這個錯。
所以按文檔和你的轉(zhuǎn)賬場景填就行了。
5,未傳入完整且對應(yīng)的轉(zhuǎn)賬場景報備信息,請根據(jù)接口文檔檢查
{
"code": "PARAM_ERROR",
"message": "未傳入完整且對應(yīng)的轉(zhuǎn)賬場景報備信息,請根據(jù)接口文檔檢查"
}
轉(zhuǎn)賬場景報備信息 說白了就是給微信審核用的,告訴微信 “我這個轉(zhuǎn)賬是什么用途”,符合政策才允許轉(zhuǎn)賬。對應(yīng)字段:transfer_scene_report_infos
比如:
轉(zhuǎn)賬原因
場景說明
獎勵類型
每個場景要傳的參數(shù)都不同。具體每個場景要傳的參數(shù)可以在這里看:現(xiàn)金營銷_商家轉(zhuǎn)賬|微信支付商戶文檔中心:https://pay.weixin.qq.com/doc/v3/merchant/4013774588
在左側(cè)可以選場景:

以傭金報酬為例,如上圖,他這里寫著了 必須要崗位類型和報酬說明,那調(diào)用時就這樣:

就可以了。
6,商戶運(yùn)營賬戶資金不足,充值后可以原單號發(fā)起重試,請勿更換商戶單號
{
"code": "NOT_ENOUGH",
"message": "商戶運(yùn)營賬戶資金不足,充值后可以原單號發(fā)起重試,請勿更換商戶單號"
}
很明顯,要充錢。不過記得是要充到運(yùn)營賬戶里面,不是這個基本賬戶:

Java的調(diào)用示例:
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;
/**
* 發(fā)起轉(zhuǎn)賬
*/
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: 請準(zhǔn)備商戶開發(fā)必要參數(shù),參考:https://pay.weixin.qq.com/doc/v3/merchant/4013070756
TransferToUser client = new TransferToUser(
"12321321", // 商戶號,是由微信支付系統(tǒng)生成并分配給每個商戶的唯一標(biāo)識符,商戶號獲取方式參考 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 = "傭金提現(xiàn)到賬";
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 = "勞務(wù)報酬";
request.transferSceneReportInfos = list;
try {
TransferToUserResponse response = client.run(request);
// TODO: 請求成功,繼續(xù)業(yè)務(wù)邏輯
System.out.println(response);
} catch (Exception e) {
// TODO: 請求失敗,根據(jù)狀態(tài)碼執(zhí)行不同的邏輯
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();
// 發(fā)送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 成功,驗(yàn)證應(yīng)答簽名
// WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey,
// httpResponse.headers(), respBody);
// 從HTTP應(yīng)答報文構(gòu)建返回數(shù)據(jù)
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
}
}
總結(jié)
到此這篇關(guān)于微信商家轉(zhuǎn)賬常見的一些問題匯總的文章就介紹到這了,更多相關(guān)微信商家轉(zhuǎn)賬常見問題Java內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mybatis?collection和association的區(qū)別解析
這篇文章主要介紹了mybatis?collection解析以及和association的區(qū)別,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-07-07
Java如何導(dǎo)出數(shù)據(jù)庫中的所有數(shù)據(jù)表到指定文件夾
這篇文章主要介紹了Java導(dǎo)出數(shù)據(jù)庫中的所有數(shù)據(jù)表到指定文件夾,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-06-06
java web開發(fā)之購物車功能實(shí)現(xiàn)示例代碼
這篇文章主要介紹了java web開發(fā)之購物車功能實(shí)現(xiàn)示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10
SpringMVC結(jié)構(gòu)簡介及常用注解匯總
這篇文章主要介紹了SpringMVC結(jié)構(gòu)簡介及常用注解匯總,幫助大家更好的理解和學(xué)習(xí)使用SpringMVC,感興趣的朋友可以了解下2021-03-03

