微信扫码支付(模式一)详解

最近在写微信扫码支付(模式一),特此记录一下开发过程中的问题。
模式一时序图
一、二维码生成:

1.1、二维码所需参数列表:
在这里插入图片描述
1.2、生成二维码内容链接,如下:

weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX

1.3、生成二维码:

使用qrcode类库,将1.2中生成的二维码链接转换为二维码(qrcode的使用请自行百度)。

二、设置回调地址:

进入商户平台–>产品中心–>开发配置,进行配置和修改,如下图:
在这里插入图片描述
注:回调地址要保证外网可以访问

三、API秘钥设置:

进入商户平台–>账户中心–>API安全,进行配置和修改,如下图:
在这里插入图片描述
说明:
3.1、秘钥必须为加密后的32位字符串,可以使用md5,随便写的32位字符,一般设置不会成功;
3.2、秘钥设置后,一定要显示秘钥生成时间才表示秘钥已经生效(如图中所示)。此处比较坑,我第一次设置秘钥提示成功,但不显示秘钥生成时间,结果扫码后一直提示URL原生参数错误

四、请求过程:

说明:请求过程需要做两次签名认证,分别为:
调用统一下单接口时,重新生成签名;
返回prepay_id给微信支付系统时,重新生成签名。

4.1、获取支付系统返回的参数

使用  
file_get_contents("php://input");
或者 $GLOBALS['HTTP_RAW_POST_DATA'];      //此时要在php.ini中开启always_populate_raw_post_data = On 

得到返回的XML数据,如下图:
在这里插入图片描述
4.2、调用统一下单接口:

说明:在统一下单接口中,需要根据请求参数,重新生成sign签名,不要使用生成二维码时的签名

/**设置随机字符串**/
public function getNonceStr($length = 32)
{
     $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ123456789";
     $str ="";
     for ( $i = 0; $i < $length; $i++ )  {
         $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
     }
     return $str;
 }

/**设置订单号**/
public function outTradeNo(){
  return date('YmdHis'). rand(100000,999999);
}

/**设置curl请求**/
public  function postXmlCurl($xml, $url, $second = 30){

   $ch = curl_init();

    //设置超时

    curl_setopt($ch, CURLOPT_TIMEOUT, $second);

    curl_setopt($ch, CURLOPT_URL, $url);

    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);

    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); //严格校验

    //设置header

    curl_setopt($ch, CURLOPT_HEADER, FALSE);

    //要求结果为字符串且输出到屏幕上

    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

    //post提交方式
    curl_setopt($ch, CURLOPT_POST, TRUE);

    curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);

    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 20);

    curl_setopt($ch, CURLOPT_TIMEOUT, 40);

    set_time_limit(0);

    //运行curl

    $data = curl_exec($ch);

    //返回结果

    if ($data) {

      curl_close($ch);

      return $data;

    } else {

      $error = curl_errno($ch);

      curl_close($ch);

      return 'error';

    }

}

/**设置sign签名**/
public function SetSign($values)
{
   //按字典排序参数,并判断排序是否成功
   if(ksort($values)){
       //排序后拼接字符串
       $string = '';
       foreach($values as $k=>$v){
           if(isset($v) && !empty($v)){
               $string .= $k . "=" . $v . "&";
           }
       }
       $stringA = trim($string,"&");
       //拼接key,得到stringSignTemp
       $stringSignTemp = $stringA."&key=".$this->key;
       $signValue = strtoupper(md5($stringSignTemp));
       $this->values['sign'] = $signValue;
       return $signValue;
   }
}

/*数组转XML*/
public function arrToXml($arr){
    //判断数组是否为空
    if(empty($arr) || !is_array($arr)){
        return '';    //暂时返回空
    }
    $xml  =  '<xml>';
    //数组转XML
    foreach($arr as $k=>$v){
        if (is_numeric($v)){
            $xml.="<".$k.">".$v."</".$k.">";
        }else{
            $xml.="<".$k."><![CDATA[".$v."]]></".$k.">";
        }
    }
    $xml .= '<xml/>';
    return $xml;
}

/*XML转数组*/
private function xmlToArr($xml){
  $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
  return $array_data;
}

得到统一下单XML参数,如下图所示:
在这里插入图片描述
4.3、获取prepay_id 参数:

获取统一下单接口返回参数如下:
在这里插入图片描述
4.4、将prepay_id 返回给微信支付系统:

说明:
1、在返回prepay_id时,需要根据请求参数,重新生成sign签名,不要使用统一下单中生成的签名;
2、此处生成签名使用的随机字符串,要使用统一下单接口返回的随机字符串,不要使用自己生成的随机字符串

返回参数如下图所示:
在这里插入图片描述
在这里插入图片描述
至此,扫码支付模式一完成。
如有不足欢迎指正!!!

五、常见错误:
5.1、
错误一:扫描二维码,提示原生URL参数错误:
解决方法:
a、首先验证sign签名是否正确,使用官方校验工具;
b、查看API秘钥是否设置成功。
5.2、
错误二:扫描二维码,提示系统繁忙:
解决方法:此错误多数是sign签名错误,检查签名。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值