Home >Backend Development >PHP Tutorial >ThinkPHP implements WeChat payment (jsapi payment) process tutorial detailed explanation_php example

ThinkPHP implements WeChat payment (jsapi payment) process tutorial detailed explanation_php example

php中世界最好的语言
php中世界最好的语言Original
2018-03-24 10:22:483883browse

This time I will bring you a detailed explanation of ThinkPHP's implementation of jsapi payment. What are the precautions for ThinkPHP's implementation of jsapi payment? The following is a practical case, let's take a look.

The environment at that time did not use a framework. It was implemented by directly creating a new directory under the directory pointed to by a domain name and then accessing the directory. However, there were still some problems when applied to the framework. In ThinkPHP, due to routing rules There is a discrepancy with the payment authorization directory, so an error will be reported. This article talks about the process of integrating WeChat payment in TP.

The SDK and documentation produced by Goose Factory are difficult to understand, and you will know it after using it. Shouldn’t the documentation and SDK be as simple and understandable as possible? Is it possible that only vigorous reconstruction can show the superb technology of Goose Factory programmers? Well...did I expose my rookie attributes...In fact, the SDK is quite easy to use, but as I saw in the previous article, the payment completion callback function is really confusing.

For those who don’t want to be bypassed by the official and want to use WeChat payment in TP, you can take a look at the payment SDK suitable for TP which was restructured and streamlined by a master based on the official documents. I downloaded the source code and read it. Well, the code is very elegant and concise, and the process is very simple and easy to understand. See the blog post for details: http://baijunyao.com/article/78

I still frowned, used the official SDK, and successfully implemented the payment. Let me share the process with you:

1.SDK download and modification

I won’t go into too much detail about this. If you don’t know, you can read my previous article: PHP implements WeChat payment (jsapi payment) process , which details which downloaded files need to be modified.

2. Public account settings

A. You still need to set the web page authorized domain name, this is nothing special;

B. Pay attention to this Payment authorization directory, using TP, many people use the rewrite mode (REWRITE mode) or use the pseudo-static mode while using the REWRITE mode. The generated link at this time is: http://serverName/Home/Blog/read /id/1 ;

If you are using PATHINFO mode, the generated link is: http://serverName/index.php/Home/Blog/read/id/1, such as under the Home module Use a method in the Blog controller to pay. The authorized directory for our payment should be http://serverName/Home/Blog/ or http://serverName/index.php/Home/Blog/, which is based on our own TP. Depends on the URL pattern set.

3. Payment process

(1) Unified order placement

The payment parameter configuration for order placement is basically different from the previous one. Change, the important thing to pay attention to is the payment callback verification link. Because it needs to be called multiple times, I encapsulated the parameter configuration directly in Application/Common/Common/function.php. My SDK is placed in the Api directory under the project root directory. , so the Vendor function is not used when introducing the SDK.

/** 
 * 微信支付 
 * @param string $openId  openid 
 * @param string $goods  商品名称 
 * @param string $attach  附加参数,我们可以选择传递一个参数,比如订单ID 
 * @param string $order_sn 订单号 
 * @param string $total_fee 金额 
 */ 
function wxpay($openId,$goods,$order_sn,$total_fee,$attach){ 
 require_once APP_ROOT."/Api/wxpay/lib/WxPay.Api.php"; 
 require_once APP_ROOT."/Api/wxpay/payment/WxPay.JsApiPay.php"; 
 require_once APP_ROOT.'/Api/wxpay/payment/log.php'; 
 //初始化日志 
 $logHandler= new CLogFileHandler(APP_ROOT."/Api/wxpay/logs/".date('Y-m-d').'.log'); 
 $log = Log::Init($logHandler, 15); 
 $tools = new JsApiPay(); 
 if(empty($openId)) $openId = $tools->GetOpenid(); 
 $input = new WxPayUnifiedOrder(); 
 $input->SetBody($goods);     //商品名称 
 $input->SetAttach($attach);     //附加参数,可填可不填,填写的话,里边字符串不能出现空格 
 $input->SetOut_trade_no($order_sn);   //订单号 
 $input->SetTotal_fee($total_fee);   //支付金额,单位:分 
 $input->SetTime_start(date("YmdHis"));  //支付发起时间 
 $input->SetTime_expire(date("YmdHis", time() + 600));//支付超时 
 $input->SetGoods_tag("test3"); 
 //$input->SetNotify_url("http://".$_SERVER['HTTP_HOST']."/payment.php"); //支付回调验证地址 
 $input->SetNotify_url("http://".$_SERVER['HTTP_HOST']."/payment.php/WexinApi/WeixinPay/notify"); 
 $input->SetTrade_type("JSAPI");    //支付类型 
 $input->SetOpenid($openId);     //用户openID 
 $order = WxPayApi::unifiedOrder($input); //统一下单 
 $jsApiParameters = $tools->GetJsApiParameters($order); 
 return $jsApiParameters; 
}

Attention, attention, here’s the key point:

The payment callback verification link must be verified without permission. If you access that link yourself, you still need to log in and register for verification. , don't try it, the link must be accessible, and there must be no series of parameters passed.

The best is simple and crude http://serverName/xxx.php. I re-wrote a special one for payment callback in the following directory, similar to index.php Entry file payment.php, and its corresponding module (WexinApi), controller (WeixinPay) and method (notify) in the Application/ directory:

// 检测PHP环境 
if(version_compare(PHP_VERSION,'5.3.0','<&#39;)) die(&#39;require PHP > 5.3.0 !'); 
// $_GET['m']='Admin'; 
// 开启调试模式 建议开发阶段开启 部署阶段注释或者设为false 
define('APP_DEBUG',True); 
//指定模块控制器和方法 
$_GET['m']='WexinApi'; 
$_GET['c']='WeixinPay'; 
$_GET['a']='notify'; 
// 定义应用目录 
define('APP_PATH','./Application/'); 
define("APP_ROOT",dirname(FILE)); 
// 引入ThinkPHP入口文件 
require './ThinkCore/ThinkCore.php'; 
// 亲^_^ 后面不需要任何代码了 就是如此简单

Now visit http://serverName/payment .php, it will go directly to http://serverName/payment.php/WexinApi/WeixinPay/notify, so the callback verification link can be written as http://serverName/payment.php or http://serverName/payment .php/WexinApi/WeixinPay/notify.

(2) Initiating payment

is still very simple:

/** 
* 支付测试 
* 微信访问:http://daoshi.sdxiaochengxu.com/payment.php/WexinApi/WeixinPay/pay 
*/ 
public function pay(){ 
 $order_sn = getrand_num(true); 
 $openId = ''; 
 $jsApiParameters = wxpay($openId,'江南极客',$order_sn,1); 
 $this->assign(array( 
  'data' => $jsApiParameters 
 )); 
 $this->display(); 
} 
<html> 
<head> 
 <meta http-equiv="content-type" content="text/html;charset=utf-8"/> 
 <meta name="viewport" content="width=device-width, initial-scale=1"/> 
 <title>小尤支付测试</title> 
 <script type="text/javascript"> 
 //调用微信JS api 支付 
 function jsApiCall() 
 { 
  var data={$data}; 
  WeixinJSBridge.invoke( 
   'getBrandWCPayRequest', data, 
   function(res){ 
    WeixinJSBridge.log(res.err_msg); 
    //alert('err_code:'+res.err_code+'err_desc:'+res.err_desc+'err_msg:'+res.err_msg); 
    //alert(res.err_code+res.err_desc+res.err_msg); 
    //alert(res); 
    if(res.err_msg == "get_brand_wcpay_request:ok"){ 
     alert("支付成功!"); 
     window.location.href="http://m.blog.csdn.net/article/details?id=72765676" rel="external nofollow" ; 
    }else if(res.err_msg == "get_brand_wcpay_request:cancel"){ 
     alert("用户取消支付!"); 
    }else{ 
     alert("支付失败!"); 
    } 
   } 
  ); 
 } 
 function callpay() 
 { 
  if (typeof WeixinJSBridge == "undefined"){ 
   if( document.addEventListener ){ 
    document.addEventListener('WeixinJSBridgeReady', jsApiCall, false); 
   }else if (document.attachEvent){ 
    document.attachEvent('WeixinJSBridgeReady', jsApiCall); 
    document.attachEvent('onWeixinJSBridgeReady', jsApiCall); 
   } 
  }else{ 
   jsApiCall(); 
  } 
 } 
 </script> 
</head> 
<body> 
 <br/> 
 <font color="#9ACD32"><b>该笔订单支付金额为<span style="color:#f00;font-size:50px">1分</span>钱</b></font><br/><br/> 
 <font color="#9ACD32"><b><span style="color:#f00;font-size:50px;margin-left:40%;">1分</span>钱也是爱</b></font><br/><br/> 
 <p align="center"> 
  <button style="width:210px; height:50px; border-radius: 15px;background-color:#FE6714; border:0px #FE6714 solid; cursor: pointer; color:white; font-size:16px;" type="button" onclick="callpay()" >果断买买买^_^</button> 
 </p> 
</body> 
</html>

However, you should pay attention to the URL of the payment page, because the URL of the payment page must have many parameters. Just now Speaking of the REWRITE mode used in TP, your link is similar to [ http://serverName/Home/Blog/read/id/1 ], which may have more parameters. At this time, WeChat Pay will consider your payment The authorization directory is [http://serverName/Home/Blog/read/id/], but your real authorization directory is [http://serverName/Home/Blog/], so an error will be reported. The solution is to reconstruct the URL when entering the payment page and write it in normal mode, which is [http://serverName/Home/Blog/read?id=1], and that's it.

(3)支持成功回调

现在支付完成,就会进入到之前写好的链接对应的方法,即[  http://serverName/payment.php/WexinApi/WeixinPay/notify]:

//微信支付回调验证 
public function notify(){ 
 $xml = $GLOBALS['HTTP_RAW_POST_DATA']; 
 // 这句file_put_contents是用来查看服务器返回的XML数据 测试完可以删除了 
 file_put_contents('./Api/wxpay/logs/log.txt',$xml,FILE_APPEND); 
 //将服务器返回的XML数据转化为数组 
 //$data = json_decode(json_encode(simplexml_load_string($xml,'SimpleXMLElement',LIBXML_NOCDATA)),true); 
 $data = xmlToArray($xml); 
 // 保存微信服务器返回的签名sign 
 $data_sign = $data['sign']; 
 // sign不参与签名算法 
 unset($data['sign']); 
 $sign = $this->makeSign($data); 
 // 判断签名是否正确 判断支付状态 
 if ( ($sign===$data_sign) && ($data['return_code']=='SUCCESS') && ($data['result_code']=='SUCCESS') ) { 
  $result = $data; 
  // 这句file_put_contents是用来查看服务器返回的XML数据 测试完可以删除了 
  file_put_contents('./Api/wxpay/logs/log1.txt',$xml,FILE_APPEND); 
  //获取服务器返回的数据 
  $order_sn = $data['out_trade_no']; //订单单号 
  $order_id = $data['attach'];  //附加参数,选择传递订单ID 
  $openid = $data['openid'];   //付款人openID 
  $total_fee = $data['total_fee']; //付款金额 
  //更新数据库 
  $this->updateDB($order_id,$order_sn,$openid,$total_fee); 
 }else{ 
  $result = false; 
 } 
 // 返回状态给微信服务器 
 if ($result) { 
  $str='<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>'; 
 }else{ 
  $str='<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>'; 
 } 
 echo $str; 
 return $result; 
}

为了安全起见,对返回过来的签名,要重新验证:

/** 
* 生成签名 
* @return 签名,本函数不覆盖sign成员变量 
*/ 
protected function makeSign($data){ 
 //获取微信支付秘钥 
 require_once APP_ROOT."/Api/wxpay/lib/WxPay.Api.php"; 
 $key = \WxPayConfig::KEY; 
 // 去空 
 $data=array_filter($data); 
 //签名步骤一:按字典序排序参数 
 ksort($data); 
 $string_a=http_build_query($data); 
 $string_a=urldecode($string_a); 
 //签名步骤二:在string后加入KEY 
 //$config=$this->config; 
 $string_sign_temp=$string_a."&key=".$key; 
 //签名步骤三:MD5加密 
 $sign = md5($string_sign_temp); 
 // 签名步骤四:所有字符转为大写 
 $result=strtoupper($sign); 
 return $result; 
}

至此,TP中微信支付也就搞定了。这是集成了官方的SDK实现的,如果不使用SDK,可以使用更简单的方法,见:PHP实现微信支付(jsapi支付)和退款(无需集成支付SDK)

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

总结一些MySQL陷阱

PHP直接实现生成海报广告

The above is the detailed content of ThinkPHP implements WeChat payment (jsapi payment) process tutorial detailed explanation_php example. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn