微信转账php开发心得

最近做了一个项目涉及到微信转账,总结一些坑点,以为后事之师

坑点如下:

1.证书报错 (错误编码58)
这是最苦恼的问题,到处找问题就报了个58和失败,也没有其他的错误警告,一时间就成了丈二的和尚摸不着头脑了,最后查看curl官方(官方链接http://curl.haxx.se/libcurl/c/libcurl-errors.html)错误编码提示才发现是证书路径不对。
在这里插入图片描述
解决方法:路径拼接需要使用绝对路径:

 $isdir = $_SERVER['DOCUMENT_ROOT']."/cert/";//证书位置;绝对路径
 curl_setopt($ch, CURLOPT_SSLCERT, $isdir . 'apiclient_cert.pem');//证书位置

2. 产品权限验证失败,请查看您当前是否具有该产品的权限

需同时满足两个条件,才有开通该功能入口:
1、T+0 (T日结算至基本账户),结算商户需满足两个条件:
1、入驻满90天,
2、截止今日往回推30天连续不间断保持有交易。
2、其余结算周期的商户无限制,可立即前往【商户平台】->【产品中心】申请开通。
注:连续30天交易无金额限制,请保持正常交易

解决方法:自己做一个微信支付一分钱的订单每天支付,除此之外还没发现其他的方法

完整代码如下:

<?php
/**
 * Class WeixinPayToUser微信转账
 */
class WeixinPayToUser
{
    /**
     * API 参数
     * @var array
     * 'mch_appid'         # 公众号APPID
     * 'mchid'             # 商户号
     * 'device_info'       # 设备号
     * 'nonce_str'         # 随机字符串
     * 'partner_trade_no'  # 商户订单号
     * 'openid'            # 收款用户openid
     * 'check_name'        # 校验用户姓名选项 针对实名认证的用户
     * 're_user_name'      # 收款用户姓名
     * 'amount'            # 付款金额
     * 'desc'              # 企业付款描述信息
     * 'spbill_create_ip'  # Ip地址
     * 'sign'              # 签名
     */
    public $parameters = [];
    public $SSLROOTCA_PATH='';
    public $SSLCERT_PATH='';
    public $SSLKEY_PATH='';
    public $appid='';
    public $secret='';
    public $mchid='';
    public $key='';//商户密钥

    public function __construct()
    {
        $this->appid='#####';
        $this->secret='#####';
        $this->key='#####';
        $this->mchid='#####';
        $this->url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';
    }

    /**
     * [xmltoarray xml格式转换为数组]
     * @param [type] $xml [xml]
     * @return [type]  [xml 转化为array]
     */
    function xmltoarray($xml) {
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
        $val = json_decode(json_encode($xmlstring),true);
        return $val;
    }

    /**
     * [arraytoxml 将数组转换成xml格式(简单方法):]
     * @param [type] $data [数组]
     * @return [type]  [array 转 xml]
     */
    function arraytoxml($data){
        $str='<xml>';
        foreach($data as $k=>$v) {
            $str.='<'.$k.'>'.$v.'</'.$k.'>';
        }
        $str.='</xml>';
        return $str;
    }

    /**
     * [createNoncestr 生成随机字符串]
     * @param integer $length [长度]
     * @return [type]   [字母大小写加数字]
     */
    function createNoncestr($length =32){
        $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxyz0123456789";
        $str ="";

        for($i=0;$i<$length;$i++){
            $str.= substr($chars, mt_rand(0, strlen($chars)-1), 1);
        }
        return $str;
    }

    /**
     * [curl_post_ssl 发送curl_post数据]
     * @param [type] $url  [发送地址]
     * @param [type] $xmldata [发送文件格式]
     * @param [type] $second [设置执行最长秒数]
     * @param [type] $aHeader [设置头部]
     * @return [type]   [description]
     */
    function curl_post_ssl($url, $xmldata, $second = 30, $aHeader = array()){
        $isdir = $_SERVER['DOCUMENT_ROOT']."/system/Wxpay/cert/";//证书位置;绝对路径

        $ch = curl_init();//初始化curl

        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_SSLCERTTYPE, 'PEM');//证书类型
        curl_setopt($ch, CURLOPT_SSLCERT, $isdir . 'apiclient_cert.pem');//证书位置
     
        curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');//CURLOPT_SSLKEY中规定的私钥的加密类型
        curl_setopt($ch, CURLOPT_SSLKEY, $isdir . 'apiclient_key.pem');//证书位置
        curl_setopt($ch, CURLOPT_CAINFO, 'PEM');
        curl_setopt($ch, CURLOPT_CAINFO, $isdir . 'rootca.pem');
        if (count($aHeader) >= 1) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);//设置头部
        }
        curl_setopt($ch, CURLOPT_POST, 1);//post提交方式
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xmldata);//全部数据使用HTTP协议中的"POST"操作来发送

        $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;
        }
    }


    /**
     * [sendMoney 企业付款到零钱]
     * @param [type] $amount  [发送的金额(分)目前发送金额不能少于1元]
     * @param [type] $re_openid [发送人的 openid]
     * @param string $desc  [企业付款描述信息 (必填)]
     * @param string $check_name [收款用户姓名 (选填)]
     * @return [type]    [description]
     */
   public function sendMoney($amount,$re_openid,$desc='测试',$check_name=''){

        $total_amount = (100) * $amount;

        $data=array(
            'mch_appid'=>$this->appid,//商户账号appid
            'mchid'=> $this->mchid,//商户号
            'nonce_str'=>$this->createNoncestr(32),//随机字符串
            'partner_trade_no'=> date('YmdHis').rand(1000, 9999),//商户订单号
            'openid'=> $re_openid,//用户openid
            'check_name'=>'NO_CHECK',//校验用户姓名选项,
            're_user_name'=> $check_name,//收款用户姓名
            'amount'=>$total_amount,//金额
            'desc'=> $desc,//企业付款描述信息
            'spbill_create_ip'=> $_SERVER["SERVER_ADDR"],//Ip地址
        );

        //生成签名算法
        $secrect_key=$this->key;///这个就是个API密码。MD5 32位。
        $data=array_filter($data);
        ksort($data);
        $str='';
        foreach($data as $k=>$v) {
            $str.=$k.'='.$v.'&';
        }
        $str.='key='.$secrect_key;
        $data['sign']=md5($str);
        //生成签名算法


        $xml=$this->arraytoxml($data);


        $res=$this->curl_post_ssl($this->url,$xml);
        $return=$this->xmltoarray($res);


        print_r($return);

        $responseObj = simplexml_load_string($res, 'SimpleXMLElement', LIBXML_NOCDATA);
        $res= $responseObj->return_code; //SUCCESS 如果返回来SUCCESS,则发生成功,处理自己的逻辑

        return $res;
    }

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值