zoukankan      html  css  js  c++  java
  • 微信支付之h5方式(非微信内置浏览器中支付)

    这两天完成了公司网站手机和PC端的支付对接,就是支付宝和微信.

    对接完后有所感触,我们来聊一聊,微信支付的坑,为什么这么说呢,因为我在对接完支付宝后是很愉快的,基本上在demo上稍加修改就ok了,

    对于支付宝我觉得基本上都没什么可以说的,而微信支付...

    网上搜了一下,基本上没有看到有针对h5支付的成功教程,全都是复制粘贴官方文档,有意思吗.

    恰好今天空了,来聊一聊微信支付的坑,当然本文也不是光吐槽了事,我会把完整的代码放到文末尾处,并加以适当的注释.

    ------------------------------

    首先第一步去微信商户平台开通h5支付的.

    因为公司的app中的微信支付是我对接的,所以在开始做手机网站的微信支付前,我首先想到去微信开放平台,新建了一个网站应用,

    最后审核下来居然没有支付接口,只有获取用户信息的接口,我有点蒙笔,然后我打了一下客服电话,那边客服说h5支付在公众号平台中完成(注意:这里客服mm向我扔了一个巨坑,接着往下看

    既然这样,我就去了微信公众号平台,我们有服务号,拿着appid和mch_id就开始搞,一切都很好,但是提示[商户号该产品权限预开通中,请等待产品开通后重试],

    我赶紧登录商户平台看一下,确定h5是开通的没问题,这个时候我注意到一个问题,就是我的公众号平台中的商户号和商户平台中的商户号不一致,我检查了公司信息,邮箱,手机号,两者都是完全一样的.

    这个时候我把代码中的商户号(微信公众号平台的)改成了商户平台的商户号,请求接口返回[商户号和appid不匹配],我再次坚定,应该用微信公众号平台的商户号,因为appid是用的微信公众号平台的.

    这个时候我陷入了焦灼,网上找了很久,没有搜到任何跟[商户号该产品权限预开通中,请等待产品开通后重试] 有关的结果,我给微信支付技术发了一封邮件,阐述了我遇到的问题,

    第二天技术回复了我,说 "你开通h5支付的商户号是这个(商户平台的),而不是你现在用这个(微信公众号平台的)",这就是前面那个客服mm给我扔的大坑!!

    邮件中还告诉我,我开通h5支付的商户号对应的appid是这个[appid**],而这个appid是我在开放平台中以前建的移动应用,也就是我们之前的app中用的...此时一万只草泥马在开始奔腾.

    前后跨度太大,让我一时无法接受这个事实,

    你先告诉我,h5支付为什么跟移动应用扯上关系了,其次你文档中提到了一星半点吗,没有!,客服mm也是调皮,动不动就h5支付跟开放平台没关系,只需要公众号平台.

    还有 你微信产品真多 微信公众号平台(配置),微信开放平台(文档),微信商户平台(配置),我对接个微信支付要在三大平台之间来回切换,你真的666!!!

    ---------------------------------

    平复一下心情,来看一下h5支付的流程,整个逻辑是这样的,首先用户打开手机网站某个服务页面

    点击开通某个产品时,此时通过ajax请求带上产品价格,名称等参数来请求一个php脚本(wxpay_wap.php),

    这个脚本根据官方文档要求的参数,组合,生成签名,请求统一下单接口,

    返回一个支付url,然后用js生成一个a标签并模拟点击或者直接location.href应该都是可以的,

    就会调起微信支付,支付完成后微信会发送一个请求到你设定的回调脚本(wxpay_wap_notify.php),在回调脚本里写业务逻辑

    大体就是这样的,以下代码稍加修改就可以直接用了

    ---------------------------------

    wxpay_wap.php

     1 // 文档中说的,价格 单位是分
     2 $money = $_POST['money']*100; //商品价格
     3 // 前台请求的参数
     4 $title = $_POST['title']; //商品名称
     5 $userid = $_POST['userid']; //用户id
     6 
     7 $time = time();
     8 
     9 $nonce_str = "hcuasduvihasdiovjerjgvujsaru"; //随机字符串
    10 $appid = "wx**************33"; //在微信开放平台中的 appid(先要创建一个移动应用)
    11 $mch_id = "147****642";  //商户号,在商户平台中查看
    12 $key = "51b*************************f15e"; //在微信开放平台中的 
    13 $notify_url = "http://www.xxx.com/xxx/wxnotify.php"; //用户支付完后微信会来触发这个脚本,是处理业务逻辑的地方
    14 //订单号可以灵活使用,比如我这个地方把userid加进去,在异步回调的时候方便直接操作用户
    15 $out_trade_no = $time."__".$userid; 
    16 
    17 // 下面的参数含义直接看文档
    18 $tmpArr = array(
    19     'appid'=>$appid,   //不要填成了 公众号原始id
    20     'attach'=>$title, 
    21     'body'=>$title,
    22     'mch_id'=>$mch_id,
    23     'nonce_str'=>$nonce_str,  
    24     'notify_url'=>$notify_url,
    25     'out_trade_no'=>$out_trade_no, 
    26     'spbill_create_ip'=>$_SERVER['REMOTE_ADDR'],
    27     'total_fee'=>$money,
    28     'trade_type'=>'MWEB' 
    29     );
    30 // 签名逻辑官网有说明,签名步骤就不解释了
    31 ksort($tmpArr);  
    32 
    33 $buff = "";
    34 foreach ($tmpArr as $k => $v)
    35 {
    36    $buff .= $k . "=" . $v . "&";
    37 }
    38 $buff = trim($buff, "&");
    39 $stringSignTemp=$buff."&key=51b3363e91fe317fc346526f5933f15e";
    40 $sign= strtoupper(md5($stringSignTemp)); //签名
    41 
    42 $xml = "<xml>
    43            <appid>".$appid."</appid>
    44            <attach>".$title."</attach>
    45            <body>".$title."</body>
    46            <mch_id>".$mch_id."</mch_id>
    47            <nonce_str>".$nonce_str."</nonce_str>
    48            <notify_url>".$notify_url."</notify_url>
    49            <out_trade_no>".$out_trade_no."</out_trade_no>
    50            <spbill_create_ip>".$_SERVER['REMOTE_ADDR']."</spbill_create_ip>
    51            <total_fee>".$money."</total_fee>
    52            <trade_type>MWEB</trade_type>
    53            <sign>".$sign."</sign>
    54         </xml> ";
    55 
    56 $posturl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    57 
    58 $ch = curl_init($posturl);
    59 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
    60 curl_setopt($ch, CURLOPT_POST, 1);  
    61 curl_setopt($ch, CURLOPT_POSTFIELDS, $xml); 
    62 $response = curl_exec($ch);  
    63 curl_close($ch);
    64 
    65 $xmlobj = json_decode(json_encode(simplexml_load_string($response, 'SimpleXMLElement', LIBXML_NOCDATA ))); 
    66 exit($xmlobj->mweb_url);

     ------------------------------------------

    wxpay_wap_notify.php

     1 // 本脚本的业务逻辑只是个例子,仅供参考
     2 
     3 // 拿到原始数据并通过xml类解析为对象
     4 $postObj = simplexml_load_string(file_get_contents("php://input"), 'SimpleXMLElement', LIBXML_NOCDATA );
     5 // 你可以通过下面这种方式来看一下微信究竟返回了那些参数,请保证log.php存在并且有写权限
     6 // file_put_contents(dirname(__file__)."/log.php",file_get_contents("php://input"));
     7 $arr = array();
     8 foreach ($postObj as $key => $value) {
     9     $arr[$key] = $value;
    10 } 
    11 // 订单状态
    12 $status = $arr['result_code'];
    13 
    14 if(trim($status) == "SUCCESS") {
    15     // 微信订单
    16     $out_trade_no = $arr['transaction_id'];
    17 
    18         // 价格
    19         $money = $arr['total_fee']/100;
    20         // 在商户订单号中提取用户id,上一个脚本中我说了这个商户订单号可以灵活使用
    21         $uid = explode("__", $arr['out_trade_no'])[1];
    22 
    23         // 在数据库中检查这个订单号是否已经处理过了 以免重复处理,因为很多原因微信可能多次触发本脚本
    24         // checkrepeat(orderid);
    25 
    26         /////////////////////////////////////////////////////////////
    27         ////                                                    /////
    28         ////    这里处理业务逻辑....                            /////    
    29         ////                                                    /////            
    30         /////////////////////////////////////////////////////////////
    31 
    32         // 处理完逻辑 返回这个xml数据,告诉微信服务器,这个订单号已经处理完了 不要在来骚扰我了
    33         $xml = "
    34                 <xml>
    35                   <return_code><![CDATA[".$status."]]></return_code>
    36                   <return_msg><![CDATA[OK]]></return_msg>
    37                 </xml>";
    38         echo $xml;
    39         
    40 }

     如果需要微信扫码支付或者支付宝支付相关文章,请在我的php分类中查看

  • 相关阅读:
    Android学习笔记一:项目目录结构
    ReactNative踩坑日志——OnPress随着render()执行被自动调用?
    ReactNative踩坑日志——使用async/await语法解决网络请求的异步导致的指令执行顺序错乱问题
    ReactNative踩坑日志——代码执行方式(面向对象)
    ReactNative踩坑日志——fetch如何向服务器传递参数
    ReactNative踩坑日志——函数绑定this
    ReactNative踩坑日志——如何实现删除scrollview中的视图
    ReactNative踩坑日志——页面跳转之——Undefined is not an Object(evaluating this2.props.navigation.navigate)
    Git使用笔记
    CSS拾遗
  • 原文地址:https://www.cnblogs.com/codeAB/p/7617355.html
Copyright © 2011-2022 走看看