Don't forget that you have had a dream

    

微信支付——企业付款到银行卡,零钱,查询订单

最近,业务上有个需求,用到了微信的企业付款到银行卡这个接口。网上找了些资料,总之是坑比较多吧,但是这也算是微信文档的通病了。为此,我整理了一下企业付款到银行卡的使用类。商户可以将商户号余额付款至指定的收款银行账户。通过指定收款银行账户户名、卡号,以及收款银行信息即可实现付款。

文档地址:

https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_1&index=1

使用条件

  1. 商户号(或同主体其他非服务商商户号)已入驻90日
  2. 商户号(或同主体其他非服务商商户号)有30天连续正常交易
  3. 登录微信支付商户平台-产品中心,开通企业付款。
  4. 企业付款至银行卡只支持新资金流类型账户
  5. 目前企业付款到银行卡支持17家银行,更多银行逐步开放中
  6. 付款到账实效为1-3日,最快次日到账
  7. 每笔按付款金额收取手续费,按金额0.1%收取,最低1元,最高25元,如果商户开通了运营账户,手续费和付款的金额都从运营账户出。如果没有开通,则都从基本户出。
  8. 每个商户号每天可以出款100万,单商户给同一银行卡付款每天限额5万
  9. 发票:在账户中心-发票信息页面申请开票的商户会按月收到发票(已申请的无需重复申请)。企业付款到银行卡发票与交易手续费发票为拆分单独开具。

代码

<?php
namespace Jykj\\Balance\\Weixin;
/***************************************************************
 *   企业付款到零钱、企业付款到银行卡、查询企业付款;证书的加密,解密。有问题邮件联系我
 *  Copyright notice
 *
 *  (c) Wang Hongbin <wanghongbin@ngoos.org>, 极益科技
 *
 * @Author: Wang Hongbin
 * @Email: wanghongbin@ngoos.org
 * @Date:   2018-06-13 11:29:39
 * @Last Modified by:   Wang Hongbin
 * @Last Modified time: 2018-06-13 16:50:46
 ***************************************************************/
class WxPubApi
{
   private $params;
    private $paths  = ""; // 证书存放路径
    private $cpath   = ""; // 公钥路径
    private $kpath = ""; // 私钥路径
    const KEY       = ''1111111111111111111111111111qq''; // 32位
    const MCHID     = ''1111111111''; // 商户号
    const APPID     = ''wxdwdq1312312qweqw'';
    const SECRET    = ''asdddddddddddddddddddddddddddd'';

    const PAYURL     = ''https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers'';
    const SEPAYURL    = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo";
    const BANKPAY   = "https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank";
    const PKURL     = "https://fraud.mch.weixin.qq.com/risk/getpublickey";

    public function __construct(){
        $this->paths = dirname(__FILE__).''/cert/'';
        $this->cpath = dirname(__FILE__).''/cert/apiclient_cert.pem'';
      $this->kpath = dirname(__FILE__).''/cert/apiclient_key.pem'';
    }

    /**
     * 付款到零钱
     * @param  [type] $data [description]
     * @return [type]       [description]
     */
    public function createComPay($data){
        //构建原始数据
        $this->params = [
            ''mch_appid''         => self::APPID,//APPid,
            ''mchid''             => self::MCHID,//商户号,
            ''nonce_str''         => strtoupper(md5(time())), //随机字符串
            ''partner_trade_no''  => $data[''trade_no''], //商户订单号
            ''openid''            => $data[''openid''], //用户openid
            ''check_name''        => ''NO_CHECK'',//校验用户姓名选项 NO_CHECK:不校验真实姓名 FORCE_CHECK:强校验真实姓名
            //''re_user_name''    => '''',//收款用户姓名  如果check_name设置为FORCE_CHECK,则必填用户真实姓名
            ''amount''            => $data[''price''],//金额 单位分
            ''desc''              => $data[''desc''],//付款描述
            ''spbill_create_ip''  => $_SERVER[''SERVER_ADDR''],//调用接口机器的ip地址
        ];
        //将数据发送到接口地址
        return $this->SendData(self::PAYURL);
    }

    /**
     * 转账到银行卡
     * @param  [type] $data [description]
     * @return [type]       [description]
     */
    public function createBankPay($data){
        $this->params = [
            ''mch_id''          => self::MCHID,//商户号
            ''partner_trade_no''    => date(''YmdHis''),//商户付款单号
            ''nonce_str''           => strtoupper(md5(time())), //随机串
            ''enc_bank_no''        => $data[''enc_bank_no''],//收款方银行卡号RSA加密
            ''enc_true_name''       => $data[''enc_true_name''],//收款方姓名RSA加密
            ''bank_code''           => $data[''bank_code''],//收款方开户行
            ''amount''          => $data[''amount''],//付款金额
        ];
         //将数据发送到接口地址
        return $this->SendData(self::BANKPAY);
    }

    /**
     * 查询订单
     * @param  [type] $oid [description]
     * @return [type]      [description]
     */
    public function searchPayByOrder($oid){
        $this->params = [
            ''nonce_str''         => md5(time()),//随机串
            ''partner_trade_no''  => $oid, //商户订单号
            ''mch_id''            => self::MCHID,//商户号
            ''appid''               => self::APPID //APPID
        ];
        //将数据发送到接口地址
        return $this->SendData(self::SEPAYURL);
    }

    /**
     * 获取公钥
     * @return [type] [description]
     */
    public function getRsaPuyKey(){
        $this->params = [
            ''mch_id''    => self::MCHID,//商户ID
            ''nonce_str'' => strtoupper(MD5(time())),
            ''sign_type'' => ''MD5''
        ];
        //将数据发送到接口地址
        $pubkey = $this->SendData(self::PKURL);
        file_put_contents($this->paths.''pubkey.pem'', $pubkey[''pub_key'']);
        return $pubkey;
    }

    public function getSign($params=array()){
        //去除空值
        $params = array_filter($params);
        if(isset($params[''sign''])) unset($params[''sign'']);
        //按照键名字典排序
        ksort($params);
        //生成url格式的字符串
        $str = $this->arrToUrl($params).''&key=''.self::KEY;
        $params[''sign''] = strtoupper(md5($str));
        return $params;
    }

    public function arrToUrl($arr){
        return urldecode(http_build_query($arr));
    }

    /**
     * 获取随机数
     * @param  integer $length [description]
     * @return [type]          [description]
     */
    public function getRandomKeys($length=30)
    {
        $str = ''ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz'';
        $key = null;
        for ($i = 0; $i < $length; $i++) {
            $key .= $pattern{mt_rand(0, 30)};    //生成php随机数
        }
        return $key;
    }

    //数组转xml
    public function ArrToXml($arr){
        if(!is_array($arr) || count($arr) == 0) return '''';
        $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; 
    }
    
    //Xml转数组
    public function XmlToArr($xml){   
        if($xml == '''') return '''';
        libxml_disable_entity_loader(true);
        $arr = json_decode(json_encode(simplexml_load_string($xml, ''SimpleXMLElement'', LIBXML_NOCDATA)), true);     
        return $arr;
    }

    /**
     * 下面是写死的东西不需要改变 //通用发送CURL接口
     * @param [type] $data [description]
     * @param [type] $url  [description]
     */
    public function SendCurl($data,$url){
        $ch = curl_init();
        //接口地址
        $MENU_URL = $url;
        curl_setopt($ch,CURLOPT_URL, $MENU_URL);
        curl_setopt($ch,CURLOPT_CUSTOMREQUEST,"POST");
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST, FALSE);
        //证书地址,微信支付下面
        curl_setopt($ch,CURLOPT_SSLCERT,$this->cpath);
        curl_setopt($ch,CURLOPT_SSLKEY,$this->kpath);
        // curl_setopt($ch, CURLOPT_USERAGENT, ''Mozilla/5.0 (compatible; MSIE 5.01;
        // Windows NT 5.0)'');
        //curl_setopt ( $ch, CURLOPT_FOLLOWLOCATION, 1 );
        curl_setopt($ch,CURLOPT_AUTOREFERER,1);
        curl_setopt($ch,CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
        $info = curl_exec($ch);
        if (curl_errno($ch)) {
            //echo ''Errno'' . curl_error ( $ch );
            exit(''CURL执行失败'');
        }
        curl_close($ch);
        return $info;
    }

    /**
     * 发送数据包
     * @param  [type] $url [description]
     * @return [type]      [description]
     */
    public function SendData($url){
        $params    = $this->getSign($this->params);
        $xmldata    = $this->ArrToXml($params);
        $returnData = $this->SendCurl($xmldata,$url);
        return $this->XmlToArr($returnData);
    }
}


/**
 *     公钥,秘钥的加密,解密
 */
class WxRSA
{
  private $public_key_resource = ''''; //公钥资源
    private $private_key_resource = ''''; //私钥资源
    /**
     * 构造函数
     * @param [string] $public_key  [公钥数据字符串]
     * @param [string] $private_key [私钥数据字符串]
     */
    public function __construct($public_key,$private_key) {
        $this->public_key_resource = !empty($public_key) ? openssl_pkey_get_public($this->get_public_key($public_key)) : false;
        $this->private_key_resource = !empty($private_key) ? openssl_pkey_get_private($this->get_private_key($private_key)) : false;
    }

   /**
  * 获取私有key字符串 重新格式化  为保证任何key都可以识别
   */
 public function get_private_key($private_key){
      $search = [
         "-----BEGIN RSA PRIVATE KEY-----",
          "-----END RSA PRIVATE KEY-----",
            "\\n",
          "\\r",
          "\\r\\n"
        ];

      $private_key=str_replace($search,"",$private_key);
      return $search[0] . PHP_EOL . wordwrap($private_key, 64, "\\n", true) . PHP_EOL . $search[1];
   }


   /**
  * 获取公共key字符串  重新格式化 为保证任何key都可以识别
   */
 public function get_public_key($public_key){
        $search = [
         "-----BEGIN PUBLIC KEY-----",
           "-----END PUBLIC KEY-----",
         "\\n",
          "\\r",
          "\\r\\n"
        ];
      $public_key=str_replace($search,"",$public_key);
        return $search[0] . PHP_EOL . wordwrap($public_key, 64, "\\n", true) . PHP_EOL . $search[1];
    }

    /**
     * 生成一对公私钥 成功返回 公私钥数组 失败 返回 false
     */
    public function create_key() {
        $res = openssl_pkey_new();
        if($res == false) return false;
        openssl_pkey_export($res, $private_key);
        $public_key = openssl_pkey_get_details($res);
        return array(''public_key''=>$public_key["key"],''private_key''=>$private_key);
    }
    /**
     * 用私钥加密
     */
    public function private_encrypt($input) {
        openssl_private_encrypt($input,$output,$this->private_key_resource);
        return base64_encode($output);
    }
    /**
     * 解密 私钥加密后的密文
     */
    public function public_decrypt($input) {
        openssl_public_decrypt(base64_decode($input),$output,$this->public_key_resource);
        return $output;
    }
    /**
     * 用公钥加密
     */
    public function public_encrypt($input) {
        openssl_public_encrypt($input,$output,$this->public_key_resource,OPENSSL_PKCS1_OAEP_PADDING);
        return base64_encode($output);
    }
    /**
     * 解密 公钥加密后的密文
     */
    public function private_decrypt($input) {
        openssl_private_decrypt(base64_decode($input),$output,$this->private_key_resource,OPENSSL_PKCS1_OAEP_PADDING);
        return $output;
    }
}

您可以自由的转载和修改,但请务必注明文章来源并且不可用于商业目的。
本站部分内容收集于互联网,如果有侵权内容、不妥之处,请联系我们删除。敬请谅解!
所有原创文章采用 知识共享署名-非商业性使用 4.0 国际许可协议 知识共享许可协议 进行许可。

评论已关闭

  更新日志

博客banner下方滚动文字替换为使用 一言API 随机获取 --- updated on 2019-05-22 09:04:31 星期三

  关于博主

三里林,一个致力于分享,分享心得,分享技术,分享知识点的个人博客

  近期评论

  分类目录

我爱你,与你有何相干?毁灭你,又与你有何相干?

以前高中时,羡慕大学考试只要及格就行;现在大学了,怀念高中考试及不及格都行…

别师犹染凡心 剑端新雪霁 独恨无留迹

一懒众衫小

成王败寇,失败才是丑恶的。

孙大圣,快收了神通吧!

明月清风晓星尘,凌霜傲雪宋子琛。

你还有好多未完成的梦,你有什么理由停下脚步