>백엔드 개발 >PHP 튜토리얼 >ThinkPHP로 WeChat 결제(jsapi 결제)를 구현하는 단계에 대한 자세한 설명

ThinkPHP로 WeChat 결제(jsapi 결제)를 구현하는 단계에 대한 자세한 설명

php中世界最好的语言
php中世界最好的语言원래의
2018-05-18 10:33:032301검색

이번에는 ThinkPHP로 WeChat 결제(jsapi 결제)를 구현하는 단계에 대해 자세히 설명하겠습니다. ThinkPHP로 WeChat 결제(jsapi 결제)를 구현하는 경우 주의 사항은 무엇인가요?

당시 환경은 프레임워크를 사용하지 않았는데, 도메인 이름이 가리키는 디렉터리 아래에 직접 새 디렉터리를 생성한 후 해당 디렉터리에 접근하는 방식으로 구현되었습니다. 그러나 프레임워크에 적용할 때 여전히 몇 가지 문제가 있었습니다. ThinkPHP에서는 라우팅 규칙과 결제 승인 디렉토리로 인해 불일치가 있어 오류가 보고됩니다. 이 기사에서는 TP에 WeChat 결제를 통합하는 과정에 대해 설명합니다.

구스팩토리에서 제작한 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,'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'; 
// 亲^_^ 后面不需要任何代码了 就是如此简单

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

(2) 결제 시작

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

/** 
* 支付测试 
* 微信访问: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>

하지만 결제 페이지의 URL에는 많은 매개변수가 있어야 하기 때문에 결제 페이지의 URL에 주의해야 합니다. 방금 에서 사용된 REWRITE 모드를 언급했습니다. TP, 귀하의 링크는 [ 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/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中文网其它相关文章!

推荐阅读:

PHP实现单向散列加密操作步骤详解

PHP实现单点登录步骤详解

위 내용은 ThinkPHP로 WeChat 결제(jsapi 결제)를 구현하는 단계에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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