php微信支付v3版签名生成(php 微信支付流程)

发布时间:2022-11-12

本文目录一览:

  1. [如何利用PHP实现 APP端微信支付功能](#如何利用PHP实现 APP端微信支付功能)
  2. 用PHP做微信支付签名错误,请教一下这个是什么原因
  3. 如何用PHP实现微信支付,求教。新手!说明详细点
  4. 微信网页支付V3版js_api_call.php从订单跳转到微信支付提示缺少统一支付接口必填参数out_trade_no!
  5. 如何用PHP实现微信支付?
  6. 微信支付遇到签名验证失败的解决方法

如何利用PHP实现 APP端微信支付功能

一丶 PHP后台生成预支付交易单,返回正确的预支付交易回话标识后再在APP里面调起支付!官方文档: 根据文档拼接微信需要的参数,这里需要几个方法,直接上代码! 传输给微信的参数要组装成xml格式发送,传如参数数组!

public function ToXml($data=array())
{
    if(!is_array($data) || count($data) == 0)
    {
        return '数组异常';
    }
    $xml = "";
    foreach ($data as $key=>$val)
    {
        if (is_numeric($val)){
            $xml.="<".$key.">".$val."</".$key.">";
        }else{
            $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
        }
    }
    $xml.="</xml>";
    return $xml;
}

2.生成随机字符串,微信所需参数! 这里方法很多,看自己爱好都行!

function rand_code(){
    $str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';//62个字符
    $str = str_shuffle($str);
    $str = substr($str,0,32);
    return  $str;
}

3.这里是微信比较重要的一步了,这个方法会多次用到!生成签名

private function getSign($params) {
    ksort($params);    //将参数数组按照参数名ASCII码从小到大排序
    foreach ($params as $key => $item) {
        if (!empty($item)) {    //剔除参数值为空的参数
            $newArr[] = $key.'='.$item;   // 整合新的参数数组
        }
    }
    $stringA = implode("&", $newArr);    //使用 & 符号连接参数
    $stringSignTemp = $stringA."&key="."************************";    //拼接key
    // key是在商户平台API安全里自己设置的
    $stringSignTemp = MD5($stringSignTemp);    //将字符串进行MD5加密
    $sign = strtoupper($stringSignTemp);   //将所有字符转换为大写
    return $sign;
}

4.传递参数给微信,生成预支付订单! 接收微信返回的数据,在反给APP端,APP端调用支付接口,完成支付 ! APP端所需参数见微信文档:;index=2

public function wx_pay() {
    $nonce_str = $this->rand_code();    //调用随机字符串生成方法获取随机字符串
    $data['appid'] ='wxdbc5dc*******';   //appid
    $data['mch_id'] = '1493*****' ;     //商户号
    $data['body'] = "APP支付测试";
    $data['spbill_create_ip'] = $_SERVER['HTTP_HOST'];  //ip地址
    $data['total_fee'] = 1;             //金额
    $data['out_trade_no'] = time().mt_rand(10000,99999); //商户订单号,不能重复
    $data['nonce_str'] = $nonce_str;           //随机字符串
    $data['notify_url'] = ''; //接收支付后的通知,必须为能直接访问的网址,不能跟参数
    $data['trade_type'] = 'APP';   //支付方式
    //将参与签名的数据保存到数组 注意:以上几个参数是追加到$data中的,$data中应该同时包含开发文档中要求必填的剔除sign以外的所有数据
    $data['sign'] = $this->getSign($data);    //获取签名
    $xml = $this->ToXml($data);      //数组转xml
    //curl 传递给微信方
    $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    //header("Content-type:text/xml");
    $ch = curl_init();
    curl_setopt($ch,CURLOPT_URL, $url);
    if(stripos($url,"https://")!==FALSE){
        curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
    } else {
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
    }
    //设置header
    curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
    curl_setopt($ch, CURLOPT_HEADER, FALSE);
    //要求结果为字符串且输出到屏幕上
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    //设置超时
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_POST, TRUE);
    //传输文件
    curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
    //运行curl
    $data = curl_exec($ch);
    //返回结果
    if($data){
        curl_close($ch);
        //返回成功,将xml数据转换为数组.
        $re = $this->FromXml($data);
        if($re['return_code'] != 'SUCCESS'){
            json("201",'签名失败');
        }
        else{
            //接收微信返回的数据,传给APP!
            $arr =array(
                'prepayid'=>$re['prepay_id'],
                'appid' => 'wxdbc5dc*****',
                'partnerid' => '14937****',
                'package' => 'Sign=WXPay',
                'noncestr' => $nonce_str,
                'timestamp' =>time(),
            );
            //第二次生成签名
            $sign = $this->getSign($arr);
            $arr['sign'] = $sign;
            json('200','签名成功',$arr);
        }
    } else {
        $error = curl_errno($ch);
        curl_close($ch);
        json('201',"curl出错,错误码:$error");
    }
}

5.将xml数据转换为数组,接收微信返回数据时用到.

public function FromXml($xml)
{
    if(!$xml){
        echo "xml数据异常!";
    }
    //将XML转为array
    //禁止引用外部xml实体
    libxml_disable_entity_loader(true);
    $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    return $data;
}

二 .APP支付成功后,会调用你填写的回调地址 . 返回参数详见微信文档:;index=3

// 微信支付回调
function wx_notify(){
    //接收微信返回的数据数据,返回的xml格式
    $xmlData = file_get_contents('php://input');
    //将xml格式转换为数组
    $data = $this->FromXml($xmlData);
    //用日志记录检查数据是否接受成功,验证成功一次之后,可删除。
    $file = fopen('./log.txt', 'a+');
    fwrite($file,var_export($data,true));
    //为了防止假数据,验证签名是否和返回的一样。
    //记录一下,返回回来的签名,生成签名的时候,必须剔除sign字段。
    $sign = $data['sign'];
    unset($data['sign']);
    if($sign == $this->getSign($data)){
        //签名验证成功后,判断返回微信返回的
        if ($data['result_code'] == 'SUCCESS') {
            //根据返回的订单号做业务逻辑
            $arr = array(
                'pay_status' => 1,
            );
            $re = M('order')->where(['order_sn'=>$data['out_trade_no']])->save($arr);
            //处理完成之后,告诉微信成功结果!
            if($re){
                echo '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';exit();
            }
        }
        //支付失败,输出错误信息
        else{
            $file = fopen('./log.txt', 'a+');
            fwrite($file,"错误信息:".$data['return_msg'].date("Y-m-d H:i:s"),time()."\r\n");   
        }
    }
    else{
        $file = fopen('./log.txt', 'a+');
        fwrite($file,"错误信息:签名验证失败".date("Y-m-d H:i:s"),time()."\r\n");   
    }
}

在这里,微信APP支付流程就成功走完了!谢谢支持!

用PHP做微信支付签名错误,请教一下这个是什么原因

出现这种情况可能是您的网络不好,或者是没有遵循开发规范,导致数字签名失败 建议您更换更好的网络,同时根据开发规范调整后台代码。

如何用PHP实现微信支付,求教。新手!说明详细点

微信公众号JSAPI支付 一:配置参数 申请成功后,获取接口文件, 将所有文件放入项目根目录weixin下,在WxPay.ub.config.php中填入配置账户信息; 二:设置授权 开发者中心-网页服务-网页授权获取用户基本信息-修改; “授权回调页面域名修改成你的域名地址即可,须保证网页授权已获得,不然会报redirect_uri 参数错误; 三:网页授权获取用户openid js_api_call.php 请求文件中改动(所有传给微信的参数都在入口文件中接收)

$out_trade_no = $_GET['out_trade_no']; //商户系统内部订单号 32个字符内
$total_fee = $_GET['total_fee']*100; //订单总金额 单位为分,不能带小数点,所以须把价格乘以100,
//不然获取prepay_id时会报错误(设置金额字段时最好设为小数点后2位)
$pay_status = get_pay_status($out_trade_no);//查看订单支付状态
$return_url = get_return_url($out_trade_no); //设置支付成功后跳转页面
//使用jsapi接口
$jsApi = new JsApi_pub();
//通过code获得openid
if (!isset($_GET['code'])) { //触发微信返回code码
    //设置redirect_uri参数,返回code码地址,其实就是重定向到当前页面,获取用户code码参数
    $url = WxPayConf_pub::JS_API_CALL_URL."?showwxpaytitle=1&out_trade_no=$out_trade_not&total_fee=$total_fee";
    $url = $jsApi->createOauthUrlForCode($url);
    Header("Location: $url");
}else{ //获取code码,以获取openid
    $code = $_GET['code'];
    $jsApi->setCode($code);
    $openid = $jsApi->getOpenId(); //用户标识
}

再就是WxPayHubHelper.php文件 JsApi_pub()类下createOauthUrlForCode($redirectUrl)方法, 第二个参数 改为 $urlObj["redirect_uri"] = urlencode($redirectUrl); //对$url变量进行url编码 不然header重定向时无法获取订单号和金额 四:设置统一支付接口参数,获取prepay_id (预支付ID 微信生成的预支付 ID,用于后续接口调用中使用) 微信支付-开发配置-支付测试-测试授权目录和测试白名单添加 (支付授权目录需要精确到最细一级的目录,且在使用时,目录名称后直接加文件名,如ccc.com/weixin/) 确保你 WxPayPubHelper.php文件里 UnifiedOrder_pub 这个类的getPrepayId这个方法能正常使用 这一步的调试在 getPrepayId()内 var_dump($this->result); 就能看到错误代码;

function postXml() {
    $xml = $this->createXml();
    //**在此处查看xml文件是否正常生成
    include_once("log_.php");
    $log = new Log_();
    $log->log_result("log.txt",$xml);
    //** 由于打印一些xml格式的文件只显示字符长度,不显示内容。于是用log的形式写在服务器上调试
    $this->response = $this->postXmlCurl($xml,$this->url,$this->curl_timeout);
    return $this->response;
}

保证xml这个变量格式如下; 参数正确,postXmlCurl才能正确提交,提交后就能得到正确的prepay_id,就能弹出支付框了 五:使用jsapi调起支付 根据prepay_id生成jsapi支付参数

$jsApi->setPrepayId($prepay_id);
$jsApiParameters = $jsApi->getParameters();
//调用微信JS api 支付
function jsApiCall() {
    WeixinJSBridge.invoke(
        'getBrandWCPayRequest',
        <?php echo $jsApiParameters; ?>,
        function(res){
            WeixinJSBridge.log(res.err_msg);
            if(res.err_msg == "get_brand_wcpay_request:ok") { //支付成功后
                window.location.href="" //跳转地址及订单操作,在异步页面也须处理订单,防止同步时失败
            }else{
                alert("支付失败"+res.err_code+res.err_desc+res.err_msg);
            }
        }
    );
}

(每次请求callpay方法时须判断订单状态,防止重复提交) 六:通用通知接口 异步处理微信返回结果 支付完成后,notify.php中获取微信的回调

$xml = $GLOBALS['HTTP_RAW_POST_DATA'];
//须验证签名,并回应微信。
if($notify->checkSign() == TRUE) //签名验证通过并更新订单状态后
    $notify->setReturnParameter("return_code","SUCCESS"); //设置返回码,保证支付状态改变后才返回成功
//对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败,
//微信会通过一定的策略(如30分钟共8次)定期重新发起通知,
$returnXml = $notify->returnXml();
echo $returnXml;(将xml数据返回微信 当return_code为SUCCESS时,不会再通知)
//当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过,
//如果没有处理过再进行处理,如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前,
//要采用数据锁进行并发控制,以避免函数重入造成的数据混乱.
//判断是否在微信浏览器打开
function isWeiXin(){
    var ua = window.navigator.userAgent.toLowerCase();
    if(ua.match(/MicroMessenger/i) == 'micromessenger'){
        return true;
    }else{
        return false;
    }
}

步骤够详细了吧,我自己实现过,所以写了日志,结合php版本的demo 大致弄得出来了,如果对整个流程不太清楚,仔细的看完微信公众号支付接口文档,你申请微信公众号支付成功了就会有的,

微信网页支付V3版js_api_call.php从订单跳转到微信支付提示缺少统一支付接口必填参数out_trade_no!

这个out_trade_no你请求过去没, 这个out_trade_no是你自己网站上的订单号,流程是这样的 用户在你的网站支付,你自己的网站首先生成一个订单号,比如1234,然后把相关的信息请求给微信,这个out_trade_no也就是你的订单号(1234),然后微信那边支付成功之后会回调,他会把这个out_trade_no依然给你,你可以通过这个来识别是谁支付成功了 你的图片 看到没,那是个例子,你依然把他注释了,所以那个$out_trade_no是空的, 商户支付的订单号由商户自定义生成,微信支付要求商户订单号保持唯一性(建议根据当前系统时间加随机序列来生成订单号)。重新发起一笔支付要使用原订单号,避免重复支付;已支付过或已调用关单、撤销(请见后文的API列表)的订单号不能重新发起支付。

如何用PHP实现微信支付?

以PHP语言为例,对微信支付的开发流程进行一下说明:

  1. 获取订单信息。
  2. 根据订单信息和支付相关的账号生成sign,并且生成支付参数。
  3. 将支付参数信息POST到微信服务器,获取返回信息。
  4. 根据返回信息生成相应的支付代码(微信内部)或是支付二维码(非微信内),完成支付。

微信支付遇到签名验证失败的解决方法

  1. 下单的签名方式使用MD5方式
  2. 利用下单获取到的prepay_id,来进行调起支付阶段的paySign的签名
  3. 如果提示签名验证失败: ① 首先检查你的5个参数是否完整:timeStamp,nonceStr,package,signType,paySign ② signType 必须是MD5,官方demo不是MD5,改为MD5,这也是大坑,当然我自己用python 写的时候直接用的MD5 ③ 在做paySign签名的时候,需要6个参数,上述5个参数去掉paySign(不参与签名),加上appId(注意是大写I,这是个大坑,这个错了那签名必然失败)和key ④ 如果上述步骤没问题还是失败,那么去验证以下你的签名是否通过 ⑤ 还有一点签名的时候必须把所有英文全部转为大写
  4. 欢迎评论,多多交流