1.所需参数
2.还需要支付时使用的证书
3.签名的规则
意思就是将上述的除了支付秘钥和签名的9-10项(因为收款用户姓名是根据验证选项而决定是否需要的)
按照ASCII的从小到大排序之后的字符串
例如:$str = "amount=100&check_name=NO_CHECK&desc=奖金啊,提现成功啊 退款成功啊什么的&mch_appid=wx8888888888888888&mchid=1900000109&nonce_str=5K8264ILTKCH16CQ2502SI8ZNMTM67VS&openid=oxTWIuGaIt6gTKsQRLau2M0yL16E&partner_trade_no=1000009811111234567890&spbill_create_ip=192.168.0.1";
签名是不是一直变动的呢?是的 每一个签名都是不一样的,别想着存起来一直用!怎么算呢?官方有一个文档,对于会的人来说就是废话,对于不会的来说就是天书。总的来说分为3部,官方有一个签名生成工具https://pay./wiki/tools/signverify/。
将你本次请求的所有参数(当然除了签名),按照一定的顺序排序成一个字符串,顺序一会再说,先说格式,比如本次的这次请求有9个参数:
$str = "amount=100&check_name=NO_CHECK&desc=奖金啊,提现成功啊 退款成功啊什么的&mch_appid=wx8888888888888888&mchid=1900000109&nonce_str=5K8264ILTKCH16CQ2502SI8ZNMTM67VS&openid=oxTWIuGaIt6gTKsQRLau2M0yL16E&partner_trade_no=1000009811111234567890&spbill_create_ip=192.168.0.1";
仔细观察不难发现,字符串排列是有顺序的 为键值首字母的排列顺序。而官方为了听起来霸气,讲的是根据参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式排序吓的我一哆嗦啊! 不就字母顺序表么!不过仔细一看发现不对了,比如mchid和mch_appid这尼玛前三个字母一样啊,一位一位排序下来出现一个i和_怎么办呢? 这时候就用到ASCII码表了,不过看官也不用去查了 上面的可以直接粘去用了 而ASCII码表的顺序呢就是按照0123456789:;< = > ? @ ABCDEFGHIJKLMNOPQRSTUVWXYZ [ \ ] ^ _ ` abcdefghijklmnopqrstuvwxyz { | }~的顺序排列 那么我门就知道mch_appid应该在mchid前面了。排序完这9个参数 之后再用&加上特殊参数 微信支付平台上设置的支付密钥就是
$str = "amount=100&check_name=NO_CHECK&desc=奖金啊,提现成功啊 退款成功啊什么的&mch_appid=wx8888888888888888&mchid=1900000109&nonce_str=5K8264ILTKCH16CQ2502SI8ZNMTM67VS&openid=oxTWIuGaIt6gTKsQRLau2M0yL16E&partner_trade_no=1000009811111234567890&spbill_create_ip=192.168.0.1&key=F5YguNW77Ao4N5yu5wZ8Lb00NKO987ks"之后就简单了先md5加密下然后转为大写 签名就OK了
$sign = strtoupper(md5($str));
然后我们就要将这些参数填充到xml格式的字符串中去了
4.开始撸码吧
/*** 格式化参数格式化成url参数*/public function ToUrl($arr){$buff = "";foreach ($arr as $k => $v){if($k != "sign" && $v != "" && !is_array($v)){$buff .= $k . "=" . $v . "&";}} $buff = trim($buff, "&");return $buff;}//将乱序的数组 public function ToSign($arr,$key){//签名步骤一:按字典序排序参数ksort($arr);$string = ToUrl($arr); //签名步骤二:在string后加入KEY$string = $string . "&key=".$key;//签名步骤三:MD5加密$string = md5($string); //签名步骤四:所有字符转为大写// $result1 = strtoupper($string);return $string;}/*** 输出xml字符* @throws WxPayException**/public static function ToXml($arr){if(!is_array($arr) || count($arr) <= 0){echo '数据异常';}$xml = "<xml>";foreach ($arr as $key=>$val){if (is_numeric($val)){$xml.="<".$key.">".$val."</".$key.">";}else{$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";}}$xml.="</xml>";return $xml; }/*** zll 生成唯一订单号*/public function order_sn(){$str = "qyfk".uniqid();return $str;}/*** zll 将信息提交到微信服务器,发起企业付款*/public function qyzf_post($url,$xml,$config,$second=30){$ch = curl_init();curl_setopt($ch,CURLOPT_TIMEOUT,$second);curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);curl_setopt($ch,CURLOPT_URL,$url);curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);// curl_setopt($ch,CURLOPT_SSLCERT,"/home/lizi/addons/grow/template/mobile/cash/apiclient_cert.pem");// curl_setopt($ch,CURLOPT_SSLKEY,"/home/lizi/addons/grow/template/mobile/cash/apiclient_key.pem");$str = 'D:/www/';//证书必须使用绝对路径,否则报错,错误貌似是52什么的curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');curl_setopt($ch,CURLOPT_SSLCERT,$str.trim($config['apiclient_cert'],'.'));curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');curl_setopt($ch,CURLOPT_SSLKEY,$str.trim($config['apiclient_key'],'.'));curl_setopt($ch,CURLOPT_POST, 1);curl_setopt($ch,CURLOPT_POSTFIELDS,$xml);$data = curl_exec($ch);if($data){curl_close($ch);return $data;}else{$error = curl_errno($ch);echo "call faild, errorCode:$error\n";curl_close($ch);return false;}}/*** zll 企业付款*/public function qiyezhifu($data){//解释amount为付款金额,单位分,貌似最低1元,desc为付款的描述(必填),ip就是服务器ip必填//$data = array('wxappid'=>14,'openid'=>'oRyzq0LrtuqKqQdH-FubBqcMuTi8-','amount'=>100,'desc'=>'提现奖励','ip'=>'123.207.19.254');//获取数据库的支付配置信息$config = get_pay_conf($data['wxappid']);if($config){//对必备参数进行有效性判断if(empty($config['appid']) || empty($config['shh']) || empty($config['partnerkey']) || empty($data['amount']) || empty($config['apiclient_cert']) || empty($config['apiclient_key'])){throw new Exception("支付配置中的appid或商户号或支付秘钥不能为空,或支付金额不能为空");}else{$da['mch_appid'] = $config['appid'];//appid$da['mchid'] = $config['shh']; //商户号$da['nonce_str'] = $this->getStr(32);//随机字符串$da['partner_trade_no'] = $this->order_sn(); //订单号,保持唯一性即可$da['openid'] = $data['openid'];//粉丝的openid$da['check_name'] = "NO_CHECK"; //NO_CHECK:不校验真实姓名 FORCE_CHECK:强校验真实姓名(未实名认证的用户会校验失败,无法转账) OPTION_CHECK:针对已实名认证的用户才校验真实姓名(未实名认证用户不校验,可以转账成功)//$da['re_user_name'] = ""; //收款用户真实姓名。 如果check_name设置为FORCE_CHECK或OPTION_CHECK,则必填用户真实姓名$da['amount'] = $data['amount']; //付款金额,单位分$da['desc'] = $data['desc'] ? $data['desc']:"提现奖励"; //企业付款描述信息$da['spbill_create_ip'] = $data['ip'] ? $data['ip'] : "123.207.19.254"; //服务器ip$da['sign'] = $this->ToSign($da, $config['partnerkey']);//生成签名//$da['key'] = $config['partnerkey'];//支付秘钥//将数组转为xml$xml = $this->ToXml($da);$url = 'https://api.mch./mmpaymkttransfers/promotion/transfers';$this->qyzf_post($url,$xml,$config);} }else{return false;}}
上面的代码我是在thinkphp3.2框架里面写的,所以方法之间的调用用的是$this->XXX();
其他的框架或原生的php可以进行修改方法调用方式即可
如果觉得《php 微信支付企业付款》对你有帮助,请点赞、收藏,并留下你的观点哦!