企业微信的支付自从企业号变化为企业微信后,增加了一些支付接口以及对很多接口进行了调整,企业微信的支付处理也是变化了不少,往往有时候碰到不少坑,一步一个脚印趟过来的;企业微信支付是需要结合微信商户后台进行处理,有时候也需要设置好商户平台的相关处理,才能进行发送红包、支付到个人等等支付处理。本篇随笔介绍在企业微信的支付处理中的发送红包的操作相关内容。
1、企业微信的支付接口
我们查看企业微信API的目录,可以看到企业微信支付的相关介绍,如下所示。
1)常见错误处理
企业微信支付,经常见到的错误信息,就是签名错误这个操作,这个很多人出招,解决方法各种各样,其实很多可能是不符合的,这样排查问题起来就很吃力。
这里需要遵循官方的解析进行排查,特别对参数的顺序和数量进行核对,注意不要增加多一个参数,否则都容易出现签名错误。
我就是在官方需要参数都有了,打印输出的格式也没问题,就是不小心多了一个参数(还是升级前有的一个),导致错误很难排查,弄得很头大。
一般来说发送企业红包,很容易发生签名错误的情况,请检查以下内容 1、企业微信的CorpID/CorpSecret 2、企业微信的支付Secret和商户的API支付秘钥 3、参数不能多也不能少(重要),如很多时候由于版本原因这里不小心多了一个total_num导致签名错误 4、商户平台的证书和密码是否正确
另外,除了这些问题外,重要的问题就是签名的处理了,微信支付除了有一个常规的签名sign参数外,还增加了一个workwx_sign的参数,两者的规则是不同的。
workwx_sign参数在前,使用系统给出的计算方式计算后,然后在计算sign参数,sign参数的计算是包含本身之外的所有参数进行计算,包括了workwx_sign参数。
2)签名参数处理
对于企业微信的签名workwx_sign参数,不要将参数全部参与计算签名,否则会返回微信签名错误!
发红包api固定如下几个字段参与签名:act_namemch_billnomch_idnonce_strre_openidtotal_amountwxappid
付款api固定如下几个字段参与签名:amountappiddescmch_idnonce_stropenidpartner_trade_noww_msg_type
计算企业微信签名的字符串最后拼的secret是企业微信管理端支付应用页面的secret,如下图所示。
示例:请求内容:act_name XXXmch_billno 11111234567890mch_id 10000098nonce_str qFKEgfig76DF9912fewmkpre_openid oxTWIuGaIt6gTKsQRLau2M0yL16Etotal_amount 100wxappid wx123456789
第一步: 对参数按照key=value的格式,并按照参数名ASCII字典序排序如下stringA=”act_name=XXX&mch_billno=11111234567890&mch_id=10000098&nonce_str=qFKEgfig76DF9912fewmkp&re_openid=oxTWIuGaIt6gTKsQRLau2M0yL16E&total_amount=100&wxappid=wx123456789第二步:拼接企业微信支付应用secret(参见企业微信管理端支付应用页面):stringSignTemp=”stringA&secret=192006250b4c09247ec02edce69f6a2d”sign=MD5(stringSignTemp).toUpperCase()
2、企业微信发送红包
测试企业微信发送红包和直接支付的接口,响应效果如下所示
在企业微信中,常用到的企业微信的userid,不过发送红包则需要把userid转换为微信的openid进行使用,转换函数根据UserID 换取用户的OpenId 如下。
一般封装一个函数来使用即可。
发送企业红包调用如下代码所示
<span style="color: #0000ff;">var result = hbApi.SendWorkRedPack(packJson);
函数SendWorkRedPack的实现内容如下所示。
</span><span style="color: #008000;">//</span><span style="color: #008000;">加入常规的参数</span>
WxPayData data = <span style="color: #0000ff;">new</span><span style="color: #000000;"> WxPayData();
data.SetValue(</span><span style="color: #800000;">"</span><span style="color: #800000;">nonce_str</span><span style="color: #800000;">"</span>,data.GenerateNonceStr());<span style="color: #008000;">//</span><span style="color: #008000;">随机字符串
</span><span style="color: #008000;">//</span><span style="color: #008000;">商户订单号(每个订单号必须唯一) 组成:mch_id+yyyymmdd+10位一天内不能重复的数字。
</span><span style="color: #008000;">//</span><span style="color: #008000;">接口根据商户订单号支持重入,如出现超时可再调用。</span>
data.SetValue(<span style="color: #800000;">"</span><span style="color: #800000;">mch_billno</span><span style="color: #800000;">"</span><span style="color: #000000;">,data.GenerateOutTradeNo(AccountInfo.MchID));
data.SetValue(</span><span style="color: #800000;">"</span><span style="color: #800000;">mch_id</span><span style="color: #800000;">"</span>,AccountInfo.MchID);<span style="color: #008000;">//</span><span style="color: #008000;">商户号</span>
data.SetValue(<span style="color: #800000;">"</span><span style="color: #800000;">wxappid</span><span style="color: #800000;">"</span>,AccountInfo.AppID);<span style="color: #008000;">//</span><span style="color: #008000;">公众账号appid</span>
<span style="color: #000000;">
data.SetValue(
<span style="color: #008000;">//<span style="color: #008000;">发送者头像,此id为微信默认的头像(如果想自定义头像,请参见第三部分)
data.SetValue(<span style="color: #800000;">"<span style="color: #800000;">sender_header_mediaid<span style="color: #800000;">",<span style="color: #800000;">"<span style="color: #800000;">1G6nrLmr5EC3MMb-zK1dDdzmd0p7cNliYu9V5w7o8K0<span style="color: #800000;">"<span style="color: #000000;">);
</span><span style="color: #008000;">//</span><span style="color: #008000;">以企业应用的名义发红包,企业应用id,整型,
</span><span style="color: #008000;">//</span><span style="color: #008000;">可在企业微信管理端应用的设置页面查看。与sender_name互斥,二者只能填一个。
</span><span style="color: #008000;">//</span><span style="color: #008000;">data.SetValue("agentid","3010046");</span><span style="color: #008000;">//</span><span style="color: #008000;"> 企业应用id
</span><span style="color: #008000;">//</span><span style="color: #008000;">发放红包使用场景,红包金额大于200时必传 </span>
<span style="color: #0000ff;">if</span> (!<span style="color: #0000ff;">string</span><span style="color: #000000;">.IsNullOrEmpty(json.scene_id))
{
data.SetValue(</span><span style="color: #800000;">"</span><span style="color: #800000;">scene_id</span><span style="color: #800000;">"</span><span style="color: #000000;">,json.scene_id);
}
data.SetValue(</span><span style="color: #800000;">"</span><span style="color: #800000;">re_openid</span><span style="color: #800000;">"</span>,json.re_openid);<span style="color: #008000;">//</span><span style="color: #008000;">接受红包的用户.用户在wxappid下的openid。</span>
data.SetValue(<span style="color: #800000;">"</span><span style="color: #800000;">total_amount</span><span style="color: #800000;">"</span>,json.total_amount);<span style="color: #008000;">//</span><span style="color: #008000;">金额</span>
data.SetValue(<span style="color: #800000;">"</span><span style="color: #800000;">wishing</span><span style="color: #800000;">"</span>,json.wishing);<span style="color: #008000;">//</span><span style="color: #008000;">红包祝福语</span>
data.SetValue(<span style="color: #800000;">"</span><span style="color: #800000;">act_name</span><span style="color: #800000;">"</span>,json.act_name);<span style="color: #008000;">//</span><span style="color: #008000;">项目名称</span>
data.SetValue(<span style="color: #800000;">"</span><span style="color: #800000;">remark</span><span style="color: #800000;">"</span>,json.remark);<span style="color: #008000;">//</span><span style="color: #008000;">备注</span>
<span style="color: #000000;">
data.SetValue(<span style="color: #800000;">"<span style="color: #800000;">workwx_sign<span style="color: #800000;">",data.MakeWorkWxSign(AccountInfo.CorpPaySecret));<span style="color: #008000;">//<span style="color: #008000;">企业微信签名
data.SetValue(<span style="color: #800000;">"<span style="color: #800000;">sign<span style="color: #800000;">"<span style="color: #000000;">,data.MakeSign(AccountInfo.PayAPIKey));
</span><span style="color: #008000;">//</span><span style="color: #008000;">发送企业红包,很容易发生签名错误的情况,请检查以下内容
</span><span style="color: #008000;">//</span><span style="color: #008000;">1、企业微信的CorpID/CorpSecret
</span><span style="color: #008000;">//</span><span style="color: #008000;">2、企业微信的支付Secret和商户的API支付秘钥
</span><span style="color: #008000;">//</span><span style="color: #008000;">3、参数不能多也不能少(重要),很多时候由于版本原因这里不小心多了一个total_num导致签名错误
</span><span style="color: #008000;">//</span><span style="color: #008000;">4、商户平台的证书和密码是否正确</span>
<span style="color: #0000ff;">var</span> url = <span style="color: #800000;">"</span><span style="color: #800000;">https://api.mch.weixin.qq.com/mmpaymkttransfers/sendworkwxredpack</span><span style="color: #800000;">"</span><span style="color: #000000;">;
</span><span style="color: #0000ff;">return</span> Helper.GetPayResultWithCert<SendRedPackResult><span style="color: #000000;">(data,url,AccountInfo.CertPath,AccountInfo.CertPassword);
}</span></pre>
其实以上很多参数大家应该都很了解,相对于来说MakeWorkWxSign 和 MakeSign 就是这里的关键处理,而前者正是很多人没有处理好的问题所在。
下面把相关函数贴出来,方便对照了解下吧,其实下面这些函数是放在WxPayData类里面,统一管理处理对应的签名的。
</span><span style="color: #0000ff;">string</span> buff = <span style="color: #800000;">""</span><span style="color: #000000;">;
</span><span style="color: #0000ff;">foreach</span> (KeyValuePair<<span style="color: #0000ff;">string</span>,<span style="color: #0000ff;">object</span>> pair <span style="color: #0000ff;">in</span><span style="color: #000000;"> Values)
{
</span><span style="color: #0000ff;">if</span> (pair.Value != <span style="color: #0000ff;">null</span> && pair.Value.ToString() != <span style="color: #800000;">""</span><span style="color: #000000;">)
{
</span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (isRedPack)
{
</span><span style="color: #008000;">//</span><span style="color: #008000;">发送红包的签名字段</span>
<span style="color: #0000ff;">if</span><span style="color: #000000;"> (paramRedPack.Contains(pair.Key))
{
buff </span>+= pair.Key + <span style="color: #800000;">"</span><span style="color: #800000;">=</span><span style="color: #800000;">"</span> + pair.Value + <span style="color: #800000;">"</span><span style="color: #800000;">&</span><span style="color: #800000;">"</span><span style="color: #000000;">;
}
}
</span><span style="color: #0000ff;">else</span><span style="color: #000000;">
{
</span><span style="color: #008000;">//</span><span style="color: #008000;">付款的签名字段</span>
<span style="color: #0000ff;">if</span><span style="color: #000000;"> (paramPay.Contains(pair.Key))
{
buff </span>+= pair.Key + <span style="color: #800000;">"</span><span style="color: #800000;">=</span><span style="color: #800000;">"</span> + pair.Value + <span style="color: #800000;">"</span><span style="color: #800000;">&</span><span style="color: #800000;">"</span><span style="color: #000000;">;
}
}
}
}
buff </span>= buff.Trim(<span style="color: #800000;">'</span><span style="color: #800000;">&</span><span style="color: #800000;">'</span><span style="color: #000000;">);
</span><span style="color: #0000ff;">return</span><span style="color: #000000;"> buff;
}
</span><span style="color: #808080;">///</span> <span style="color: #808080;"><summary></span>
<span style="color: #808080;">///</span><span style="color: #008000;"> 生成企业微信签名
</span><span style="color: #808080;">///</span> <span style="color: #808080;"></summary></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><param name="corpPaySecret"></span><span style="color: #008000;">企业支付的Secret</span><span style="color: #808080;"></param></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><param name="isRedPack"></span><span style="color: #008000;">是否为发送红包操作,或者是付款操作,两者需要签名的字段不同</span><span style="color: #808080;"></param></span>
<span style="color: #808080;">///</span> <span style="color: #808080;"><returns></returns></span>
<span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> MakeWorkWxSign(<span style="color: #0000ff;">string</span> corpPaySecret,<span style="color: #0000ff;">bool</span> isRedPack = <span style="color: #0000ff;">true</span><span style="color: #000000;">)
{
</span><span style="color: #008000;">//</span><span style="color: #008000;">转url格式</span>
<span style="color: #0000ff;">string</span> str =<span style="color: #000000;"> ToWorkWxUrl(isRedPack);
</span><span style="color: #008000;">//</span><span style="color: #008000;">在string后加入secret</span>
str += <span style="color: #800000;">"</span><span style="color: #800000;">&secret=</span><span style="color: #800000;">"</span> +<span style="color: #000000;"> corpPaySecret;
</span><span style="color: #008000;">//</span><span style="color: #008000;">MD5加密</span>
<span style="color: #0000ff;">var</span> md5 =<span style="color: #000000;"> MD5.Create();
</span><span style="color: #0000ff;">var</span> bs =<span style="color: #000000;"> md5.ComputeHash(Encoding.UTF8.GetBytes(str));
</span><span style="color: #0000ff;">var</span> sb = <span style="color: #0000ff;">new</span><span style="color: #000000;"> StringBuilder();
</span><span style="color: #0000ff;">foreach</span> (<span style="color: #0000ff;">byte</span> b <span style="color: #0000ff;">in</span><span style="color: #000000;"> bs)
{
sb.Append(b.ToString(</span><span style="color: #800000;">"</span><span style="color: #800000;">x2</span><span style="color: #800000;">"</span><span style="color: #000000;">));
}
</span><span style="color: #008000;">//</span><span style="color: #008000;">所有字符转为大写</span>
<span style="color: #0000ff;">return</span><span style="color: #000000;"> sb.ToString().ToUpper();
}</span></pre>
3、企业微信直接支付的接口
对照这些官方资料,我们可以编写对应的接口API来处理。
data.SetValue(</span><span style="color: #800000;">"</span><span style="color: #800000;">sign</span><span style="color: #800000;">"</span>,data.MakeSign(AccountInfo.PayAPIKey));<span style="color: #008000;">//</span><span style="color: #008000;">最后生成签名</span>
<span style="color: #0000ff;">var</span> url = <span style="color: #0000ff;">string</span>.Format(<span style="color: #800000;">"</span><span style="color: #800000;">https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers</span><span style="color: #800000;">"</span><span style="color: #000000;">);
</span><span style="color: #0000ff;">return</span> Helper.GetPayResultWithCert<CorpPayResult><span style="color: #000000;">(data,AccountInfo.CertPassword);
}</span></pre>
其中里面的很多参数的处理是和前面支付差不多的,因此不再赘述
调用的处理代码如下所示
最新的第一条就是直接付款的信息提示。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。