Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

企业微信支付的发送红包及相关接口使用

伍华聪 2019-02-25 16:27:00 阅读数:216 评论数:0 点赞数:0 收藏数:0

企业微信的支付自从企业号变化为企业微信后,增加了一些支付接口以及对很多接口进行了调整,企业微信的支付处理也是变化了不少,往往有时候碰到不少坑,一步一个脚印趟过来的;企业微信支付是需要结合微信商户后台进行处理,有时候也需要设置好商户平台的相关处理,才能进行发送红包、支付到个人等等支付处理。本篇随笔介绍在企业微信的支付处理中的发送红包的操作相关内容。

1、企业微信的支付接口

我们查看企业微信API的目录,可以看到企业微信支付的相关介绍,如下所示。

 

1)常见错误处理

企业微信支付,经常见到的错误信息,就是签名错误这个操作,这个很多人出招,解决方法各种各样,其实很多可能是不符合的,这样排查问题起来就很吃力。

这里需要遵循官方的解析进行排查,特别对参数的顺序和数量进行核对,注意不要增加多一个参数,否则都容易出现签名错误。

我就是在官方需要参数都有了,打印输出的格式也没问题,就是不小心多了一个参数(还是升级前有的一个),导致错误很难排查,弄得很头大。

一般来说发送企业红包,很容易发生签名错误的情况,请检查以下内容 1、企业微信的CorpID/CorpSecret 2、企业微信的支付Secret和商户的API支付秘钥 3、参数不能多也不能少(重要),如很多时候由于版本原因这里不小心多了一个total_num导致签名错误 4、商户平台的证书和密码是否正确

另外,除了这些问题外,重要的问题就是签名的处理了,微信支付除了有一个常规的签名sign参数外,还增加了一个workwx_sign的参数,两者的规则是不同的。

workwxsign参数在前,使用系统给出的计算方式计算后,然后在计算sign参数,sign参数的计算是包含本身之外的所有参数进行计算,包括了workwxsign参数。

2)签名参数处理

对于企业微信的签名workwx_sign参数,不要将参数全部参与计算签名,否则会返回微信签名错误!

发红包api固定如下几个字段参与签名:act_namemch_billnomch_idnonce_strre_openidtotal_amountwxappid

付款api固定如下几个字段参与签名:amountappiddescmch_idnonce_stropenidpartnertradenowwmsgtype

计算企业微信签名的字符串最后拼的secret是企业微信管理端支付应用页面的secret,如下图所示。

示例:请求内容:act_name XXXmch_billno 11111234567890mch_id 10000098nonce_str qFKEgfig76DF9912fewmkpre_openid oxTWIuGaIt6gTKsQRLau2M0yL16Etotal_amount 100wxappid wx123456789

第一步: 对参数按照key=value的格式,并按照参数名ASCII字典序排序如下stringA=”actname=XXX&mchbillno=11111234567890&mchid=10000098&noncestr=qFKEgfig76DF9912fewmkp&reopenid=oxTWIuGaIt6gTKsQRLau2M0yL16E&totalamount=100&wxappid=wx123456789第二步:拼接企业微信支付应用secret(参见企业微信管理端支付应用页面):stringSignTemp=”stringA&secret=192006250b4c09247ec02edce69f6a2d”sign=MD5(stringSignTemp).toUpperCase()

 

2、企业微信发送红包

测试企业微信发送红包和直接支付的接口,响应效果如下所示

在企业微信中,常用到的企业微信的userid,不过发送红包则需要把userid转换为微信的openid进行使用,转换函数根据UserID 换取用户的OpenId 如下。

一般封装一个函数来使用即可。private string GetOpenId(stringuserid) {//根据UserID 换取用户的OpenId ICorpBasicApi basicAPi = newCorpBasicApi();return basicAPi.ConvertToOpenId(this.token, userid); }

发送企业红包调用如下代码所示

//构建发送红包的参数信息 SendRedPackJson packJson = newSendRedPackJson() { actname= "恭喜发财", clientip=NetworkUtil.GetIPAddress(), remark= "企业红包", wishing= "企业红包", totalamount= 100, totalnum= 1, re_openid= openid //发送给用户的OpenID };//调用发送企业红包接口发送 var result = hbApi.SendWorkRedPack(packJson);

函数SendWorkRedPack的实现内容如下所示。

///

///发放企业红包。需要商户证书/// /// /// publicSendRedPackResult SendWorkRedPack(SendRedPackJson json) { CheckAccount();//检查AccountInfo的对象属性值//加入常规的参数 WxPayData data = newWxPayData(); data.SetValue("noncestr", data.GenerateNonceStr());//随机字符串//商户订单号(每个订单号必须唯一) 组成:mchid+yyyymmdd+10位一天内不能重复的数字。//接口根据商户订单号支持重入,如出现超时可再调用。 data.SetValue("mchbillno", data.GenerateOutTradeNo(AccountInfo.MchID)); data.SetValue("mchid", AccountInfo.MchID);//商户号 data.SetValue("wxappid", AccountInfo.AppID);//公众账号appid data.SetValue("sendername", AccountInfo.Name);//红包发送者名称//发送者头像,此id为微信默认的头像(如果想自定义头像,请参见第三部分) data.SetValue("senderheadermediaid", "1G6nrLmr5EC3MMb-zK1dDdzmd0p7cNliYu9V5w7o8K0");//以企业应用的名义发红包,企业应用id,整型,//可在企业微信管理端应用的设置页面查看。与sendername互斥,二者只能填一个。//data.SetValue("agentid", "3010046");//企业应用id//发放红包使用场景,红包金额大于200时必传 if (!string.IsNullOrEmpty(json.sceneid)) { data.SetValue("sceneid", json.sceneid); } data.SetValue("reopenid", json.reopenid);//接受红包的用户.用户在wxappid下的openid。 data.SetValue("totalamount", json.totalamount);//金额 data.SetValue("wishing", json.wishing);//红包祝福语 data.SetValue("actname", json.actname);//项目名称 data.SetValue("remark", json.remark);//备注 data.SetValue("workwxsign", data.MakeWorkWxSign(AccountInfo.CorpPaySecret));//企业微信签名 data.SetValue("sign", data.MakeSign(AccountInfo.PayAPIKey));//发送企业红包,很容易发生签名错误的情况,请检查以下内容//1、企业微信的CorpID/CorpSecret//2、企业微信的支付Secret和商户的API支付秘钥//3、参数不能多也不能少(重要),很多时候由于版本原因这里不小心多了一个total_num导致签名错误//4、商户平台的证书和密码是否正确 var url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendworkwxredpack";return Helper.GetPayResultWithCert(data, url, AccountInfo.CertPath, AccountInfo.CertPassword); }

其实以上很多参数大家应该都很了解,相对于来说MakeWorkWxSign 和 MakeSign 就是这里的关键处理,而前者正是很多人没有处理好的问题所在。

下面把相关函数贴出来,方便对照了解下吧,其实下面这些函数是放在WxPayData类里面,统一管理处理对应的签名的。///

///拼接用来签名的几个参数,发送红包和付款的签名字段不同/// /// 是否为发送红包操作,或者是付款操作,两者需要签名的字段不同 /// private string ToWorkWxUrl(boolisRedPack) { List paramRedPack = new List() { "actname", "mchbillno", "mchid", "noncestr", "reopenid", "totalamount", "wxappid"}; List paramPay = new List() { "amount", "appid", "desc", "mchid", "noncestr", "openid", "partnertradeno", "wwmsgtype"};string buff = "";foreach (KeyValuePair pair inValues) {if (pair.Value != null && pair.Value.ToString() != "") {if(isRedPack) {//发送红包的签名字段 if(paramRedPack.Contains(pair.Key)) { buff+= pair.Key + "=" + pair.Value + "&"; } }else{//付款的签名字段 if(paramPay.Contains(pair.Key)) { buff+= pair.Key + "=" + pair.Value + "&"; } } } } buff= buff.Trim('&');returnbuff; }/// ///生成企业微信签名/// /// 企业支付的Secret /// 是否为发送红包操作,或者是付款操作,两者需要签名的字段不同 /// public string MakeWorkWxSign(string corpPaySecret, bool isRedPack = true) {//转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 = newStringBuilder();foreach (byte b inbs) { sb.Append(b.ToString("x2")); }//所有字符转为大写 returnsb.ToString().ToUpper(); }

///

///生成签名,详见签名生成算法/// /// 签名, sign字段不参加签名 public string MakeSign(stringpayAPIKey) {//转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 = newStringBuilder();foreach (byte b inbs) { sb.Append(b.ToString("x2")); }//所有字符转为大写 var result =sb.ToString().ToUpper();returnresult; }

 

3、企业微信直接支付的接口

对照这些官方资料,我们可以编写对应的接口API来处理。///

///企业付款(请求需要双向证书)///企业付款业务是基于微信支付商户平台的资金管理能力,为了协助商户方便地实现企业向个人付款,///针对部分有开发能力的商户,提供通过API完成企业付款的功能。 比如目前的保险行业向客户退保、给付、理赔。///企业付款将使用商户的可用余额,需确保可用余额充足。查看可用余额、充值、提现请登录商户平台“资金管理”进行操作。https://pay.weixin.qq.com/ ///注意:与商户微信支付收款资金并非同一账户,需要单独充值。/// /// 企业支付数据 /// publicCorpPayResult CorpPay(CorpPayJson json) { CheckAccount();//检查AccountInfo的对象属性值 WxPayData data= newWxPayData(); data.SetValue("mchappid", AccountInfo.AppID);//公众账号appid, 注意是mchappid,而非wxappid data.SetValue("mchid", AccountInfo.MchID);//商户号, 注意是mchid而非mchid data.SetValue("noncestr", data.GenerateNonceStr());//随机字符串 data.SetValue("spbillcreateip", NetworkUtil.GetIPAddress());//终端ip data.SetValue("partnertradeno", data.GenerateOutTradeNo(AccountInfo.MchID));//随机字符串 data.SetValue("deviceinfo", json.deviceinfo);//终端ip data.SetValue("openid", json.openid); data.SetValue("checkname", json.checkname); data.SetValue("reusername", json.reusername); 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(data, url, AccountInfo.CertPath, AccountInfo.CertPassword); }

其中里面的很多参数的处理是和前面支付差不多的,因此不再赘述

调用的处理代码如下所示//构建处理信息 CorpPayJson json = newCorpPayJson() { amount= 100, checkname=PayCheckName.FORCECHECK.ToString(), desc= "测试退款", openid=openid, deviceinfo= "", reusername= "伍华聪", spbillcreate_ip=NetworkUtil.GetIPAddress() };//直接付款到员工账号 var result = api.CorpPay(json);

 

最新的第一条就是直接付款的信息提示。

版权声明
本文为[伍华聪]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/wuhuacong/p/10431609.html

编程之旅,人生之路,不止于编程,还有诗和远方。
阅代码原理,看框架知识,学企业实践;
赏诗词,读日记,踏人生之路,观世界之行;