>  기사  >  백엔드 개발  >  ThinkPHP가 WeChat 결제를 구현하는 방법의 예

ThinkPHP가 WeChat 결제를 구현하는 방법의 예

小云云
小云云원래의
2018-03-16 09:44:422267검색

이 글은 ThinkPHP에서 WeChat 결제(jsapi 결제) 구현에 대한 자세한 튜토리얼을 주로 소개합니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

구스팩토리에서 제작한 SDK와 문서는 이해하기 어렵고 직접 사용해보시면 얼마나 신선한지 아실 겁니다. 문서와 SDK는 최대한 간단하고 이해하기 쉬워야 하지 않나요? 활발한 리팩토링만이 구스팩토리 프로그래머들의 뛰어난 기술력을 보여줄 수 있는 것일까요? 음... 루키 속성을 노출한건가... 사실 SDK는 사용하기는 꽤 쉬운데, 이전 글에서 본 것처럼 결제 완료 콜백 기능이 정말 헷갈립니다.

공식에서 우회하고 싶지 않고 TP에서 WeChat 결제를 사용하려는 분들을 위해 공식 문서를 기반으로 마스터가 재구성하고 간소화한 TP에 적합한 결제 SDK를 살펴볼 수 있습니다. 소스코드를 다운받아서 살펴보니 코드가 작성되어 있습니다. 소개가 매우 우아하고 과정도 간단하고 이해하기 쉽습니다. 자세한 내용은 블로그 게시물을 참조하세요: http://baijunyao.com/article/78

아직도 눈살을 찌푸리고 공식 SDK를 사용하여 성공적으로 결제를 구현했습니다.

1.SDK 다운로드 그리고 수정

이에 대해 너무 자세히 설명하지는 않겠습니다. 모르신다면 제 마지막 기사를 읽어보세요. PHP는 다운로드한 파일을 수정해야 하는 세부 사항을 설명하는 WeChat 결제(jsapi 결제) 프로세스를 구현합니다. .

2. 공식 계정 설정

A. 여전히 웹페이지 인증 도메인 이름을 설정해야 합니다. 이것은 특별한 것이 아닙니다.

B 여기에서 결제 인증 디렉토리를 주의하세요. REWRITE 모드를 사용하거나 REWRITE 모드를 사용하는 동안 의사 정적 모드를 사용하세요. 이때 생성되는 링크는 다음과 같습니다. http://serverName/Home/Blog/read/id/1

PATHINFO 모드를 사용하는 경우 생성합니다. 링크는 http://serverName/index.php/Home/Blog/read/id/1입니다. 예를 들어 홈 모듈 아래 블로그 컨트롤러의 메소드를 통해 결제하는 경우 결제에 대한 인증 디렉터리는 http여야 합니다. : //serverName/Home/Blog/ 또는 http://serverName/index.php/Home/Blog/, 이는 귀하의 TP에서 설정한 URL 패턴에 따라 다릅니다.

3. 결제 프로세스

(1) 통합 주문

주문의 결제 매개변수 구성은 기본적으로 이전과 동일합니다. 중요한 점은 결제 콜백 확인 링크가 필요하기 때문입니다. 여러 번 호출하여 매개변수 구성을 Application/Common/Common/function.php에 직접 캡슐화했습니다. 제 SDK는 프로젝트 루트 디렉터리 아래 Api 디렉터리에 있으므로 SDK 도입 시 Vendor 기능을 사용하지 않습니다.


/** 
 * 微信支付 
 * @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; 
}

주의, 주의, 핵심은 다음과 같습니다.

결제 콜백 확인 링크는 허가 없이 확인되어야 하며, 확인을 위해 로그인하고 등록해야 하는 경우에는 시도하지 마세요. . 링크는 액세스 가능해야 하며 매개변수 문자열이 전달되어서는 안 됩니다.

가장 좋은 점은 간단하고 조잡한 http://serverName/xxx.php입니다. index.php와 유사하게 다음 디렉토리에 결제 콜백을 위한 특수 항목 파일인 Payment.php를 다시 작성했습니다. Application/ 디렉토리의 WexinApi), 컨트롤러(WeixinPay) 및 메소드(notify):


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

이제 http://serverName/pay.php를 방문하면 http://serverName /pay.php로 바로 이동됩니다. /WexinApi/WeixinPay/notify이므로 콜백 확인 링크는 http://serverName/pay.php 또는 http://serverName/pay.php/WexinApi/WeixinPay/notify로 작성할 수 있습니다.

(2) 결제 시작

은 여전히 ​​매우 간단합니다.


/** 
* 支付测试 
* 微信访问:http://daoshi.sdxiaochengxu.com/payment.php/WexinApi/WeixinPay/pay 
*/ 
public function pay(){ 
 $order_sn = getrand_num(true); 
 $openId = &#39;&#39;; 
 $jsApiParameters = wxpay($openId,&#39;江南极客&#39;,$order_sn,1); 
 $this->assign(array( 
  &#39;data&#39; => $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( 
   &#39;getBrandWCPayRequest&#39;, data, 
   function(res){ 
    WeixinJSBridge.log(res.err_msg); 
    //alert(&#39;err_code:&#39;+res.err_code+&#39;err_desc:&#39;+res.err_desc+&#39;err_msg:&#39;+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(&#39;WeixinJSBridgeReady&#39;, jsApiCall, false); 
   }else if (document.attachEvent){ 
    document.attachEvent(&#39;WeixinJSBridgeReady&#39;, jsApiCall); 
    document.attachEvent(&#39;onWeixinJSBridgeReady&#39;, 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>

하지만 결제 페이지의 URL에는 많은 매개변수가 있어야 하기 때문에 결제 페이지의 URL에 주의해야 합니다. 방금 REWRITE에 대해 언급했습니다. 귀하의 링크는 더 많은 매개변수를 포함할 수 있는 [ http://serverName/Home/Blog/read/id/1 ]와 유사합니다. 현재 WeChat Pay는 귀하의 결제 승인 디렉토리를 [ http ://serverName /Home/Blog/read/id/ ]이지만 실제 승인된 디렉터리는 [ http://serverName/Home/Blog/]이므로 오류가 보고됩니다. 해결 방법은 결제 페이지 진입 시 URL을 재구성하여 일반 모드인 [http://serverName/Home/Blog/read?id=1]로 작성하면 끝입니다.

(3) 성공 콜백 지원

이제 결제가 완료되었으니 앞서 작성한 링크에 해당하는 메소드인 [ http://serverName/paid.php/WexinApi/WeixinPay/notify ]를 입력하시면 됩니다. ]:


//微信支付回调验证 
public function notify(){ 
 $xml = $GLOBALS[&#39;HTTP_RAW_POST_DATA&#39;]; 
 // 这句file_put_contents是用来查看服务器返回的XML数据 测试完可以删除了 
 file_put_contents(&#39;./Api/wxpay/logs/log.txt&#39;,$xml,FILE_APPEND); 
 //将服务器返回的XML数据转化为数组 
 //$data = json_decode(json_encode(simplexml_load_string($xml,&#39;SimpleXMLElement&#39;,LIBXML_NOCDATA)),true); 
 $data = xmlToArray($xml); 
 // 保存微信服务器返回的签名sign 
 $data_sign = $data[&#39;sign&#39;]; 
 // sign不参与签名算法 
 unset($data[&#39;sign&#39;]); 
 $sign = $this->makeSign($data); 
 // 判断签名是否正确 判断支付状态 
 if ( ($sign===$data_sign) && ($data[&#39;return_code&#39;]==&#39;SUCCESS&#39;) && ($data[&#39;result_code&#39;]==&#39;SUCCESS&#39;) ) { 
  $result = $data; 
  // 这句file_put_contents是用来查看服务器返回的XML数据 测试完可以删除了 
  file_put_contents(&#39;./Api/wxpay/logs/log1.txt&#39;,$xml,FILE_APPEND); 
  //获取服务器返回的数据 
  $order_sn = $data[&#39;out_trade_no&#39;]; //订单单号 
  $order_id = $data[&#39;attach&#39;];  //附加参数,选择传递订单ID 
  $openid = $data[&#39;openid&#39;];   //付款人openID 
  $total_fee = $data[&#39;total_fee&#39;]; //付款金额 
  //更新数据库 
  $this->updateDB($order_id,$order_sn,$openid,$total_fee); 
 }else{ 
  $result = false; 
 } 
 // 返回状态给微信服务器 
 if ($result) { 
  $str=&#39;<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>&#39;; 
 }else{ 
  $str=&#39;<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[签名失败]]></return_msg></xml>&#39;; 
 } 
 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에서의 WeChat 결제가 완료됩니다. 이는 공식 SDK를 통합하여 구현됩니다. SDK를 사용하지 않는 경우 더 간단한 방법을 사용할 수 있습니다. PHP를 사용하여 WeChat 결제(jsapi 결제) 및 환불 구현(결제 SDK 통합 필요 없음)

관련 추천:

PHP는 WeChat 결제 및 Alipay 결제 예시 코드를 개발

PHP는 WeChat 결제 기능 개발 코드 공유를 구현합니다

php는 WeChat 결제 기업 결제 예시 코드

위 내용은 ThinkPHP가 WeChat 결제를 구현하는 방법의 예의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.