企业微信支付的发送红包及相关接口使用
企業(yè)微信的支付自從企業(yè)號(hào)變化為企業(yè)微信后,增加了一些支付接口以及對(duì)很多接口進(jìn)行了調(diào)整,企業(yè)微信的支付處理也是變化了不少,往往有時(shí)候碰到不少坑,一步一個(gè)腳印趟過(guò)來(lái)的;企業(yè)微信支付是需要結(jié)合微信商戶(hù)后臺(tái)進(jìn)行處理,有時(shí)候也需要設(shè)置好商戶(hù)平臺(tái)的相關(guān)處理,才能進(jìn)行發(fā)送紅包、支付到個(gè)人等等支付處理。本篇隨筆介紹在企業(yè)微信的支付處理中的發(fā)送紅包的操作相關(guān)內(nèi)容。
1、企業(yè)微信的支付接口
我們查看企業(yè)微信API的目錄,可以看到企業(yè)微信支付的相關(guān)介紹,如下所示。
1)常見(jiàn)錯(cuò)誤處理
企業(yè)微信支付,經(jīng)常見(jiàn)到的錯(cuò)誤信息,就是簽名錯(cuò)誤這個(gè)操作,這個(gè)很多人出招,解決方法各種各樣,其實(shí)很多可能是不符合的,這樣排查問(wèn)題起來(lái)就很吃力。
這里需要遵循官方的解析進(jìn)行排查,特別對(duì)參數(shù)的順序和數(shù)量進(jìn)行核對(duì),注意不要增加多一個(gè)參數(shù),否則都容易出現(xiàn)簽名錯(cuò)誤。
我就是在官方需要參數(shù)都有了,打印輸出的格式也沒(méi)問(wèn)題,就是不小心多了一個(gè)參數(shù)(還是升級(jí)前有的一個(gè)),導(dǎo)致錯(cuò)誤很難排查,弄得很頭大。
一般來(lái)說(shuō)發(fā)送企業(yè)紅包,很容易發(fā)生簽名錯(cuò)誤的情況,請(qǐng)檢查以下內(nèi)容
1、企業(yè)微信的CorpID/CorpSecret
2、企業(yè)微信的支付Secret和商戶(hù)的API支付秘鑰
3、參數(shù)不能多也不能少(重要),如很多時(shí)候由于版本原因這里不小心多了一個(gè)total_num導(dǎo)致簽名錯(cuò)誤
4、商戶(hù)平臺(tái)的證書(shū)和密碼是否正確
另外,除了這些問(wèn)題外,重要的問(wèn)題就是簽名的處理了,微信支付除了有一個(gè)常規(guī)的簽名sign參數(shù)外,還增加了一個(gè)workwx_sign的參數(shù),兩者的規(guī)則是不同的。
workwx_sign參數(shù)在前,使用系統(tǒng)給出的計(jì)算方式計(jì)算后,然后在計(jì)算sign參數(shù),sign參數(shù)的計(jì)算是包含本身之外的所有參數(shù)進(jìn)行計(jì)算,包括了workwx_sign參數(shù)。
2)簽名參數(shù)處理
對(duì)于企業(yè)微信的簽名workwx_sign參數(shù),不要將參數(shù)全部參與計(jì)算簽名,否則會(huì)返回微信簽名錯(cuò)誤!
發(fā)紅包api固定如下幾個(gè)字段參與簽名:
act_name
mch_billno
mch_id
nonce_str
re_openid
total_amount
wxappid
付款api固定如下幾個(gè)字段參與簽名:
amount
appid
desc
mch_id
nonce_str
openid
partner_trade_no
ww_msg_type
計(jì)算企業(yè)微信簽名的字符串最后拼的secret是企業(yè)微信管理端支付應(yīng)用頁(yè)面的secret,如下圖所示。
示例:請(qǐng)求內(nèi)容:
act_name XXX
mch_billno 11111234567890
mch_id 10000098
nonce_str qFKEgfig76DF9912fewmkp
re_openid oxTWIuGaIt6gTKsQRLau2M0yL16E
total_amount 100
wxappid wx123456789
第一步: 對(duì)參數(shù)按照key=value的格式,并按照參數(shù)名ASCII字典序排序如下
stringA=”act_name=XXX&mch_billno=11111234567890&mch_id=10000098&nonce_str=qFKEgfig76DF9912fewmkp&re_openid=oxTWIuGaIt6gTKsQRLau2M0yL16E&total_amount=100&wxappid=wx123456789
第二步:拼接企業(yè)微信支付應(yīng)用secret(參見(jiàn)企業(yè)微信管理端支付應(yīng)用頁(yè)面):
stringSignTemp=”stringA&secret=192006250b4c09247ec02edce69f6a2d”
sign=MD5(stringSignTemp).toUpperCase()
2、企業(yè)微信發(fā)送紅包
測(cè)試企業(yè)微信發(fā)送紅包和直接支付的接口,響應(yīng)效果如下所示
在企業(yè)微信中,常用到的企業(yè)微信的userid,不過(guò)發(fā)送紅包則需要把userid轉(zhuǎn)換為微信的openid進(jìn)行使用,轉(zhuǎn)換函數(shù)根據(jù)UserID 換取用戶(hù)的OpenId如下。
一般封裝一個(gè)函數(shù)來(lái)使用即可。
private string GetOpenId(string userid)
{
//根據(jù)UserID 換取用戶(hù)的OpenId
ICorpBasicApi basicAPi = new CorpBasicApi();
return basicAPi.ConvertToOpenId(this.token, userid);
}
發(fā)送企業(yè)紅包調(diào)用如下代碼所示
//構(gòu)建發(fā)送紅包的參數(shù)信息
SendRedPackJson packJson = new SendRedPackJson()
{
act_name = "恭喜發(fā)財(cái)",
client_ip = NetworkUtil.GetIPAddress(),
remark = "企業(yè)紅包",
wishing = "企業(yè)紅包",
total_amount = 100,
total_num = 1,
re_openid = openid //發(fā)送給用戶(hù)的OpenID
};
//調(diào)用發(fā)送企業(yè)紅包接口發(fā)送
var result = hbApi.SendWorkRedPack(packJson);
函數(shù)SendWorkRedPack的實(shí)現(xiàn)內(nèi)容如下所示。
/// <summary>
/// 發(fā)放企業(yè)紅包。需要商戶(hù)證書(shū)
/// </summary>
/// <param name="json"></param>
/// <returns></returns>
public SendRedPackResult SendWorkRedPack(SendRedPackJson json)
{
CheckAccount();//檢查AccountInfo的對(duì)象屬性值
//加入常規(guī)的參數(shù)
WxPayData data = new WxPayData();
data.SetValue("nonce_str", data.GenerateNonceStr());//隨機(jī)字符串
//商戶(hù)訂單號(hào)(每個(gè)訂單號(hào)必須唯一) 組成:mch_id+yyyymmdd+10位一天內(nèi)不能重復(fù)的數(shù)字。
//接口根據(jù)商戶(hù)訂單號(hào)支持重入,如出現(xiàn)超時(shí)可再調(diào)用。
data.SetValue("mch_billno", data.GenerateOutTradeNo(AccountInfo.MchID));
data.SetValue("mch_id", AccountInfo.MchID);//商戶(hù)號(hào)
data.SetValue("wxappid", AccountInfo.AppID);//公眾賬號(hào)appid
data.SetValue("sender_name", AccountInfo.Name);//紅包發(fā)送者名稱(chēng)
//發(fā)送者頭像,此id為微信默認(rèn)的頭像(如果想自定義頭像,請(qǐng)參見(jiàn)第三部分)
data.SetValue("sender_header_media_id", "1G6nrLmr5EC3MMb_-zK1dDdzmd0p7cNliYu9V5w7o8K0");
//以企業(yè)應(yīng)用的名義發(fā)紅包,企業(yè)應(yīng)用id,整型,
//可在企業(yè)微信管理端應(yīng)用的設(shè)置頁(yè)面查看。與sender_name互斥,二者只能填一個(gè)。
//data.SetValue("agentid", "3010046");// 企業(yè)應(yīng)用id
//發(fā)放紅包使用場(chǎng)景,紅包金額大于200時(shí)必傳
if (!string.IsNullOrEmpty(json.scene_id))
{
data.SetValue("scene_id", json.scene_id);
}
data.SetValue("re_openid", json.re_openid);//接受紅包的用戶(hù).用戶(hù)在wxappid下的openid。
data.SetValue("total_amount", json.total_amount);//金額
data.SetValue("wishing", json.wishing);//紅包祝福語(yǔ)
data.SetValue("act_name", json.act_name);//項(xiàng)目名稱(chēng)
data.SetValue("remark", json.remark);//備注
data.SetValue("workwx_sign", data.MakeWorkWxSign(AccountInfo.CorpPaySecret));//企業(yè)微信簽名
data.SetValue("sign", data.MakeSign(AccountInfo.PayAPIKey));
//發(fā)送企業(yè)紅包,很容易發(fā)生簽名錯(cuò)誤的情況,請(qǐng)檢查以下內(nèi)容
//1、企業(yè)微信的CorpID/CorpSecret
//2、企業(yè)微信的支付Secret和商戶(hù)的API支付秘鑰
//3、參數(shù)不能多也不能少(重要),很多時(shí)候由于版本原因這里不小心多了一個(gè)total_num導(dǎo)致簽名錯(cuò)誤
//4、商戶(hù)平臺(tái)的證書(shū)和密碼是否正確
var url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendworkwxredpack";
return Helper.GetPayResultWithCert<SendRedPackResult>(data, url, AccountInfo.CertPath, AccountInfo.CertPassword);
}
其實(shí)以上很多參數(shù)大家應(yīng)該都很了解,相對(duì)于來(lái)說(shuō)MakeWorkWxSign 和MakeSign 就是這里的關(guān)鍵處理,而前者正是很多人沒(méi)有處理好的問(wèn)題所在。
下面把相關(guān)函數(shù)貼出來(lái),方便對(duì)照了解下吧,其實(shí)下面這些函數(shù)是放在WxPayData類(lèi)里面,統(tǒng)一管理處理對(duì)應(yīng)的簽名的。
/// <summary>
/// 拼接用來(lái)簽名的幾個(gè)參數(shù),發(fā)送紅包和付款的簽名字段不同
/// </summary>
/// <param name="isRedPack">是否為發(fā)送紅包操作,或者是付款操作,兩者需要簽名的字段不同</param>
/// <returns></returns>
private string ToWorkWxUrl(bool isRedPack)
{
List<string> paramRedPack = new List<string>() { "act_name", "mch_billno", "mch_id", "nonce_str", "re_openid", "total_amount", "wxappid" };
List<string> paramPay = new List<string>() { "amount", "appid", "desc", "mch_id", "nonce_str", "openid", "partner_trade_no", "ww_msg_type" };
string buff = "";
foreach (KeyValuePair<string, object> pair in Values)
{
if (pair.Value != null && pair.Value.ToString() != "")
{
if (isRedPack)
{
//發(fā)送紅包的簽名字段
if (paramRedPack.Contains(pair.Key))
{
buff += pair.Key + "=" + pair.Value + "&";
}
}
else
{
//付款的簽名字段
if (paramPay.Contains(pair.Key))
{
buff += pair.Key + "=" + pair.Value + "&";
}
}
}
}
buff = buff.Trim('&');
return buff;
}
/// <summary>
/// 生成企業(yè)微信簽名
/// </summary>
/// <param name="corpPaySecret">企業(yè)支付的Secret</param>
/// <param name="isRedPack">是否為發(fā)送紅包操作,或者是付款操作,兩者需要簽名的字段不同</param>
/// <returns></returns>
public string MakeWorkWxSign(string corpPaySecret, bool isRedPack = true)
{
//轉(zhuǎn)url格式
string str = ToWorkWxUrl(isRedPack);
//在string后加入secret
str += "&secret=" + corpPaySecret;
//MD5加密
var md5 = MD5.Create();
var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
var sb = new StringBuilder();
foreach (byte b in bs)
{
sb.Append(b.ToString("x2"));
}
//所有字符轉(zhuǎn)為大寫(xiě)
return sb.ToString().ToUpper();
}
/// <summary>
/// 生成簽名,詳見(jiàn)簽名生成算法
/// </summary>
/// <returns>簽名, sign字段不參加簽名</returns>
public string MakeSign(string payAPIKey)
{
//轉(zhuǎn)url格式
string str = ToUrl();
//在string后加入API KEY
str += "&key=" + payAPIKey;
//MD5加密
var md5 = MD5.Create();
var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(str));
var sb = new StringBuilder();
foreach (byte b in bs)
{
sb.Append(b.ToString("x2"));
}
//所有字符轉(zhuǎn)為大寫(xiě)
var result = sb.ToString().ToUpper();
return result;
}
3、企業(yè)微信直接支付的接口
對(duì)照這些官方資料,我們可以編寫(xiě)對(duì)應(yīng)的接口API來(lái)處理。
/// <summary>
/// 企業(yè)付款(請(qǐng)求需要雙向證書(shū))
/// 企業(yè)付款業(yè)務(wù)是基于微信支付商戶(hù)平臺(tái)的資金管理能力,為了協(xié)助商戶(hù)方便地實(shí)現(xiàn)企業(yè)向個(gè)人付款,
/// 針對(duì)部分有開(kāi)發(fā)能力的商戶(hù),提供通過(guò)API完成企業(yè)付款的功能。 比如目前的保險(xiǎn)行業(yè)向客戶(hù)退保、給付、理賠。
/// 企業(yè)付款將使用商戶(hù)的可用余額,需確保可用余額充足。查看可用余額、充值、提現(xiàn)請(qǐng)登錄商戶(hù)平臺(tái)“資金管理”進(jìn)行操作。https://pay.weixin.qq.com/
/// 注意:與商戶(hù)微信支付收款資金并非同一賬戶(hù),需要單獨(dú)充值。
/// </summary>
/// <param name="json">企業(yè)支付數(shù)據(jù)</param>
/// <returns></returns>
public CorpPayResult CorpPay(CorpPayJson json)
{
CheckAccount();//檢查AccountInfo的對(duì)象屬性值
WxPayData data = new WxPayData();
data.SetValue("mch_appid", AccountInfo.AppID);//公眾賬號(hào)appid, 注意是mch_appid,而非wxappid
data.SetValue("mchid", AccountInfo.MchID);//商戶(hù)號(hào), 注意是mchid而非mch_id
data.SetValue("nonce_str", data.GenerateNonceStr());//隨機(jī)字符串
data.SetValue("spbill_create_ip", NetworkUtil.GetIPAddress());//終端ip
data.SetValue("partner_trade_no", data.GenerateOutTradeNo(AccountInfo.MchID));//隨機(jī)字符串
data.SetValue("device_info", json.device_info);//終端ip
data.SetValue("openid", json.openid);
data.SetValue("check_name", json.check_name);
data.SetValue("re_user_name", json.re_user_name);
data.SetValue("amount", json.amount);
data.SetValue("desc", json.desc);
data.SetValue("sign", data.MakeSign(AccountInfo.PayAPIKey));//最后生成簽名
var url = string.Format("https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers");
return Helper.GetPayResultWithCert<CorpPayResult>(data, url, AccountInfo.CertPath, AccountInfo.CertPassword);
}
其中里面的很多參數(shù)的處理是和前面支付差不多的,因此不再贅述
調(diào)用的處理代碼如下所示
//構(gòu)建處理信息
CorpPayJson json = new CorpPayJson()
{
amount = 100,
check_name = PayCheckName.FORCE_CHECK.ToString(),
desc = "測(cè)試退款",
openid = openid,
device_info = "",
re_user_name = "伍華聰",
spbill_create_ip = NetworkUtil.GetIPAddress()
};
//直接付款到員工賬號(hào)
var result = api.CorpPay(json);
最新的第一條就是直接付款的信息提示。
總結(jié)
以上是生活随笔為你收集整理的企业微信支付的发送红包及相关接口使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 三星90s53g怎样安装路由器如何安装三
- 下一篇: [Chrome0S]VM虚拟机安装