ThinkPHP で WeChat 支払い (jsapi 支払い) プロセスを実装する

藏色散人
リリース: 2019-12-19 17:54:42
転載
3994 人が閲覧しました

WeChat 決済 (jsapi 決済) を PHP で実装する手順については以前に記事を書きましたので、詳しくは PHP で WeChat 決済 (jsapi 決済) を実装する手順をご覧ください。

当時の環境はフレームワークを使用せず、ドメイン名が指すディレクトリ配下に直接新規ディレクトリを作成し、そのディレクトリにアクセスするという実装でした。 ThinkPHP では、ルーティング ルールが支払い承認ディレクトリと一致しないため、エラーが報告されます。この記事では、WeChat 支払いを TP に統合するプロセスについて説明します。

Goose Factory が作成した SDK やドキュメントはわかりにくいですが、使ってみるとわかります。ドキュメントと SDK はできるだけシンプルで理解しやすいものであるべきではないでしょうか?精力的なリファクタリングだけが Goose Factory プログラマーの優れた技術を示すことができるのでしょうか?うーん…新人属性をさらけてしまったのか…実際、SDKは非常に使いやすいのですが、前回の記事で見たように、支払い完了のコールバック関数が非常にわかりにくいのです。

公式による回避を望まず、TP で WeChat 決済を使用したい場合は、マスターによって再構築され、合理化された TP に適した決済 SDK を参照してください。公式ドキュメントからソースコードをダウンロードして読んでみましたが、洗練された簡潔な方法で書かれており、プロセスもシンプルで理解しやすいです。

私はそれでも眉をひそめましたが、公式 SDK を使用して、支払いを正常に実装できました。プロセスを共有しましょう:

1.SDK のダウンロードと変更

これについてはあまり詳しく説明しません。知らない場合は、私の前回のブログ投稿を読んでください: PHP は WeChat 支払い (jsapi 支払い) プロセスを実装し、変更が必要なダウンロード ファイルの詳細を示しています。 . .

2. パブリック アカウントの設定

A. Web ページの承認済みドメイン名を設定する必要がありますが、これは特別なことではありません;

B.この支払い認証ディレクトリに注意してください。TP を使用すると、多くの人が書き換えモード (REWRITE モード) を使用するか、REWRITE モードを使用しながら擬似静的モードを使用します。このときに生成されるリンクは次のとおりです: [http://serverName/Home/Blog/] read/id/1]; PATHINFO モードが使用されている場合、生成されるリンクは [http://serverName/index.php/Home/Blog/read/id/1] (Home モジュールの Blog コントロールなど) です。サーバー内の特定の方法を使用して支払うには、支払いの認証ディレクトリは [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.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/payment.php] にアクセスすると、直接 [ http://serverName/payment.php/WexinApi/WeixinPay/notify] なので、コールバック検証リンクは [http://serverName/payment.php] または [http://serverName/payment .php/] として記述できます。 WexinApi/WeixinPay/通知]。

(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";
    }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/>
<div 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" οnclick="callpay()" >果断买买买^_^</button>
</div>
</body>
</html>
ログイン後にコピー

ただし、支払いページの URL に注意する必要があります。 TP で使用される 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]) で記述することです。それだけです。

ThinkPHP で WeChat 支払い (jsapi 支払い) プロセスを実装する

(3) サポート成功コールバック

支払いが完了したので、前に書いたリンクに対応するメソッド、つまり [ http://serverName/payment.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;
}
ログイン後にコピー

この時点で、WeChat 支払いはでTP完了です。これは、公式 SDK を統合することで実現されます。SDK を使用しない場合は、より簡単な方法を使用できます。「PHP で WeChat 支払い (jsapi 支払い) と返金を実装する (支払い SDK を統合する必要はありません)」

## を参照してください。

ThinkPHP で WeChat 支払い (jsapi 支払い) プロセスを実装する#

以上がThinkPHP で WeChat 支払い (jsapi 支払い) プロセスを実装するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:csdn.net
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!