php 微信支付企業付款


 

1.所需參數

 

字段名 變量名 必填 示例值 類型 描述
公眾賬號appid mch_appid wx8888888888888888 String 公眾號的appId
商戶號 mchid 1900000109 String(32) 微信支付平台商戶號
就是平台賬號
隨機字符串 nonce_str 5K8264ILTKCH16CQ2502SI8ZNMTM67VS String(32) 隨機字符串,隨便隨機個什么<32位
商戶訂單號 partner_trade_no 10000098201411111234567890 String 訂單號,保持唯一性,自定義一個隨機訂單號
用戶
openid
openid oxTWIuGaIt6gTKsQRLau2M0yL16E String 商戶appid下,某用戶的openid
校驗用戶姓名選項 check_name NO_CHECK
不檢驗 (小額推薦)
FORCE_CHEC
強制檢驗
OPTION_CHECK
自動檢驗
String NO_CHECK:不校驗真實姓名 
FORCE_CHECK:強校驗真實姓名(未實名認證的用戶會校驗失敗,無法轉賬) 
OPTION_CHECK:針對已實名認證的用戶才校驗真實姓名(未實名認證用戶不校驗,可以轉賬成功)
收款用戶姓名 re_user_name 可選 馬花花
(如果上一個參數為強制檢驗此為必填項)
String 收款用戶真實姓名。 
如果check_name設置為FORCE_CHECK或OPTION_CHECK,則必填用戶真實姓名
金額 amount 100
單位為分
100就是100分.
int 企業付款金額,單位為分
企業付款描述信息 desc 獎金啊,提現成功啊
退款成功啊什么的
String 企業付款操作說明信息。必填。
Ip地址 spbill_create_ip 192.168.0.1 String(32) 調用接口的機器Ip地址服務器ip
支付密鑰
key
F5YguNW77Ao4N5yu5wZ8Lb00NKO987ks
String(32)
設置在商戶平台上的支付密鑰
簽名
sign
C380BEC2BFD727A4B6845133519F3AD6
String(32)
上面的內容的一個綜合的加密結果

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=10000098201411111234567890&spbill_create_ip=192.168.0.1";

  1. 簽名是不是一直變動的呢?是的 每一個簽名都是不一樣的,別想着存起來一直用!怎么算呢?官方有一個文檔,對於會的人來說就是廢話,對於不會的來說就是天書。總的來說分為3部,官方有一個簽名生成工具https://pay.weixin.qq.com/wiki/tools/signverify/

    1. 將你本次請求的所有參數(當然除了簽名),按照一定的順序排序成一個字符串,順序一會再說,先說格式,比如本次的這次請求有9個參數:

      $str = "amount=100&check_name=NO_CHECK&desc=獎金啊,提現成功啊 退款成功啊什么的&mch_appid=wx8888888888888888&mchid=1900000109&nonce_str=5K8264ILTKCH16CQ2502SI8ZNMTM67VS&openid=oxTWIuGaIt6gTKsQRLau2M0yL16E&partner_trade_no=10000098201411111234567890&spbill_create_ip=192.168.0.1";

      仔細觀察不難發現,字符串排列是有順序的 為鍵值首字母的排列順序。而官方為了聽起來霸氣,講的是根據 參數按照參數名ASCII碼從小到大排序(字典序),使用URL鍵值對的格式排序嚇的我一哆嗦啊! 不就字母順序表么!不過仔細一看發現不對了,比如 mchid和 mch_appid這尼瑪前三個字母一樣啊,一位一位排序下來出現一個 i 和 _怎么辦呢? 這時候就用到ASCII碼表了,不過看官也不用去查了 上面的可以直接粘去用了 而ASCII碼表的順序呢就是按照0123456789:;< = > ? @ ABCDEFGHIJKLMNOPQRSTUVWXYZ [ \ ] ^ _ ` abcdefghijklmnopqrstuvwxyz { | }~的順序排列 那么我門就知道mch_appid應該在 mchid 前面了。
    2. 排序完這9個參數 之后再用&加上特殊參數 微信支付平台上設置的支付密鑰就是

      $str = "amount=100&check_name=NO_CHECK&desc=獎金啊,提現成功啊 退款成功啊什么的&mch_appid=wx8888888888888888&mchid=1900000109&nonce_str=5K8264ILTKCH16CQ2502SI8ZNMTM67VS&openid=oxTWIuGaIt6gTKsQRLau2M0yL16E&partner_trade_no=10000098201411111234567890&spbill_create_ip=192.168.0.1&key=F5YguNW77Ao4N5yu5wZ8Lb00NKO987ks"
    3. 之后就簡單了先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.weixin.qq.com/mmpaymkttransfers/promotion/transfers';
                $this->qyzf_post($url,$xml,$config);
            }            
        }else{
            return false;
        }
    }

上面的代碼我是在thinkphp3.2框架里面寫的,所以方法之間的調用用的是$this->XXX();

其他的框架或原生的php可以進行修改方法調用方式即可


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM