教學中的內容未實現識別哪個貼文或文章收到的打款,當然我的網站已經實現,你可以試試哈。有一段時間沒有寫實戰類的文章了,今天分享一篇,使用yii2 houjs yii2-wx實現微信送禮物功能。
先來個效果圖
簡單點說就是點擊「送禮物」按鈕後出現一個彈出框,裡面有很多禮物,點擊某個禮物後彈出框刷新並出現一個二維碼,微信掃碼支付。
當然這個錢會進入到會員的個人帳號內,然後提現。
為何要做這樣一個功能那? 說心裡話我真心沒想過透過這個得到多少,更多算一種激勵吧,如果你在我們學習社群分享了有價值的文章,你非常有可能受到我的禮物。
好了,還是說功能吧,功能有幾個
建立資料表結構(禮物以及送禮物日誌)
使用houjs完成前台彈出框
使用yii2-wx實作支付二維碼
為使用者增加帳戶功能
使用yii2-wx的企業付款到零錢和yii2的控制台模式現實為用戶打款功能(大於等於2元就打款)。
我勒個去,乾貨滿滿呀。開始。
既然是送禮品,那自然包含禮品表,還有送禮物的日誌表,我規劃如下。
禮物表gift
#禮物日誌表gift_log
##對於
gift_log 表可以不用lang_id,這裡為了統計方便添加了這個欄位。
整體思路用戶送禮物的整體邏輯如下<button class="ui green button" id="giftBtn" data-url="<?= Url::to(['/gift/list','id'=>$lang->id]);?>"> <i class="share icon"></i>送礼物 </button>
requirejs(['mods/modal','jSmart'],function(modal,jSmart){ $('#giftBtn').click(function(){ var url = $(this).attr('data-url'); $.getJSON(url,{},function(d){ if(d.result === 'ok'){ // d.data }else{ modal.msg(d.message); } }); }); })
public function actionList($id){ Yii::$app->response->format = 'json'; try { $data = Gift::find()->where(['lang_id'=>$id])->asArray()->all(); return ['result'=>'ok','data'=>$data]; }catch(Exception $e){ return ['result'=>'fail','message'=>$e->getMessage()]; } }
<script id="giftTpl" type="text/x-jsmart-tmpl"> <p class="gifts-box"> <p class="gifts"> {foreach $data as $key=>$gift} <a href=""> <p class="gift-icon"><img src='{$gift.icon}'/ alt="三招教你怎樣實現微信禮物打賞功能 (程式碼全)" ></p> <p class="gift-name">{$gift.name}</p> </a> {/foreach} </p> </p> </script>
requirejs(['mods/modal','jSmart'],function(modal,jSmart){ $('#giftBtn').click(function(){ var url = $(this).attr('data-url'); $.getJSON(url,{},function(d){ if(d.result === 'ok'){ var tplText = $('#giftTpl').html(); var compiledTemplate = new jSmart(tplText); var output = compiledTemplate.fetch(d); modal.alert(output,{ inPage:false, title:'送礼物', size:'tiny' }); }else{ modal.msg(d.message); } }); }); })
和後台互動並且得到支付二維碼。
得到支付二維碼在本章我們使用yii2-wx擴充實作微信支付功能,其想法點擊禮物後取得支付二維碼。 在進行之前我們對上一步的js方法進行最佳化,將程式碼放到一個單獨的js模組中,在houjs中對於業務上的js程式碼推薦放到houjs/js/modules中,如下define(function(require,exports,modules){ var modal = require('mods/modal'); var jSmart = require('jSmart'); exports.list = function(){ $('#giftBtn').click(function(){ var url = $(this).attr('data-url'); $.getJSON(url,{},function(d){ if(d.result === 'ok'){ var tplText = $('#giftTpl').html(); var compiledTemplate = new jSmart(tplText); var output = compiledTemplate.fetch(d); modal.alert(output,{ inPage:false, title:'送礼物给作者', size:'tiny' }); }else{ modal.msg(d.message); } }); }); }; });
requirejs(['modules/gift'],function(gift){ gift.list(); })
如何取得支付二維碼?
我的想法如下:使用者點擊每個禮品後發起一次get請求到伺服器,本次請求包含了禮物的ID,後台收到後產生送禮物日誌並且和微信伺服器通訊得到支付二維碼,返回給瀏覽器,前台渲染此二維碼。
說乾就乾。 首先補充禮物列表,每個禮物的a鏈接,如下<script id="giftTpl" type="text/x-jsmart-tmpl"> <p class="gifts-box"> <p class="gifts"> {foreach $data as $key=>$gift} <a class="_get_qrcode" href="javascript:;" data-url="<?= Url::to(['/gift/qrcode']);?>?id={$gift.id}"> <p class="gift-icon"><img src='{$gift.icon}'/ alt="三招教你怎樣實現微信禮物打賞功能 (程式碼全)" ></p> <p class="gift-name">{$gift.name}</p> </a> {/foreach} </p> </p> </script>
class="_get_qrcode" 一个类,这个类并不起到样式作用,主要是为js监听此标签使用。
href="javascript:;" 防止点击跳转
data-url 点击连接后,js函数将根据data-url提供的地址发起请求
接下来我们做一个js方法实现a链接点击的监听,如下
// houjs/js/modules/gift.js define(function(require,exports,modules){ var modal = require('mods/modal'); var jSmart = require('jSmart'); ..... /** * 获取某一个礼物的支付二维码 */ exports.qrcode = function(){ $('._get_qrcode').click(function(){ var url = $(this).attr('data-url'); $.getJSON(url,{},function(d){ if(d.result === 'ok'){ $('#payQrcode') .html("<img style="max-width:90%"+d.qrcode+"'/ alt="三招教你怎樣實現微信禮物打賞功能 (程式碼全)" >"); }else{ modal.msg(d.message); } }); }); }; });
有一点要说明,因此礼物列表是在页面dom渲染后加入的html代码,因此如果想让礼物列表的a链接被监听,在获取礼物列表成功后需要调用exports.qrcode()函数进行监听,如下
// houjs/js/modules/gift.js define(function(require,exports,modules){ var modal = require('mods/modal'); var jSmart = require('jSmart'); exports.list = function(){ $('#giftBtn').click(function(){ var url = $(this).attr('data-url'); $.getJSON(url,{},function(d){ if(d.result === 'ok'){ .... exports.qrcode(); }else{ modal.msg(d.message); } }); }); }; /** * 获取某一个礼物的支付二维码 */ exports.qrcode = function(){ .... }; });
此刻用户点击了礼物的a链接,gift.qrcode()方法开始运作,请求达到了yii2的gift/qrcode动作,我写了如下代码。
// yii2 GiftController/actionQrcode <?php namespace app\controllers; use app\models\Gift; use app\models\GiftLog; use yii\helpers\Url; use abei2017\wx\Application; use Da\QrCode\QrCode; use Yii; use yii\base\Exception; class GiftController extends NBase { .... public function actionQrcode($id){ Yii::$app->response->format = 'json'; try { $model = Gift::findOne($id); // order $order = new GiftLog(); $order->gift_id = $id; $order->user_id = Yii::$app->user->id; $order->created_at = time(); $order->number = 1; $order->money = $order->number*$model->price; $order->status = 'unpay'; $order->lang_id = $model->lang_id; if($order->save() == false){ throw new Exception(implode(',',$order->getFirstErrors())); } $out_trade_no = "gift-{$order->id}-".rand(1000,9999); $totalFee = $order->money*100; $conf = Yii::$app->params['wx']; $app = new Application(['conf'=>$conf['mp']]); $pay = $app->driver("mp.pay"); $attributes = [ 'body'=>"送礼物", 'detail'=>"{$model->name}", 'out_trade_no'=>$out_trade_no, 'total_fee'=>$totalFee, 'notify_url'=>Yii::$app->urlManager->createAbsoluteUrl(['/gift/notify']), 'product_id'=>'gift-'.$id ]; $native = $pay->native($attributes); $qrCode = (new QrCode($native['code_url']))->setSize(250)->setMargin(20); return ['result'=>'ok','qrcode'=>$qrCode->writeDataUri()]; }catch(Exception $e){ return ['result'=>'fail','message'=>$e->getMessage()]; } } }
首先要说明的是上述代码没有问题,但如果上线还是要处理细节的。
在actionQrcode方法中我们做了3件事情
生成送礼物日志
调用yii2-wx生成支付二维码
使用QrCode生成二维码并传给浏览器
这里使用的是yii2-wx提供的生成二维码方法native,剩下的事情就是如何显示这个二维码。
为了让用户可以在支付前重新选择礼物,本次并没有选择弹出二维码,而是使用了礼物页面替换的方法,如下图
在礼物的右侧我增加了一个p来存放二维码,没有选择的时候用一些帮助来填充。这个二维码的存放工作由gift.qrcode()方法实现
$('#payQrcode').html("<img style="max-width:90%"+d.qrcode+"'/ alt="三招教你怎樣實現微信禮物打賞功能 (程式碼全)" >");
对应的礼物列表模板也增加了支付区域
<script id="giftTpl" type="text/x-jsmart-tmpl"> <p class="gifts-box"> <p class="gifts"> {foreach $data as $key=>$gift} <a class="_get_qrcode" href="javascript:;" data-url="<?= Url::to(['/gift/qrcode']);?>?id={$gift.id}"> <p class="gift-icon"><img src='{$gift.icon}'/ alt="三招教你怎樣實現微信禮物打賞功能 (程式碼全)" ></p> <p class="gift-name">{$gift.name}</p> </a> {/foreach} </p> <p id="payQrcode"> <h1>使用小提示</h1> <p> 点击左侧的小礼物后会出现支付二维码,扫码即送。 </p> </p> <p class="clear"></p> </p> </script>
好,看下效果。
当用户得到支付二维码后必然是扫码支付,接下来有两个事情要做
yii2要处理微信支付结果通知,将此礼物日志设置为已经支付。
浏览器上次礼物列表二维码消失,提示支付成功。
先来处理结果通知,这个使用yii2-wx非常好实现。在GiftController中增加一个notify动作。
// GiftController.php <?php namespace app\controllers; use app\models\Gift; use app\models\GiftLog; use yii\data\ActiveDataProvider; use yii\helpers\Url; use abei2017\wx\Application; use Da\QrCode\QrCode; use Yii; use yii\base\Exception; class GiftController extends NBase { public $enableCsrfValidation = false; ...... public function actionNotify(){ $conf = Yii::$app->params['wx']; $app = new Application(['conf'=>$conf['mp']]); $pay = $app->driver("mp.pay"); $response = $pay->handleNotify(function($notify,$isSuccess){ if($isSuccess){ @list($_,$id,$_) = explode('-',$notify['out_trade_no']); $model = GiftLog::findOne($id); if($model->status == 'pay'){ return true; } $model->status = 'pay'; $model->paid_at = time(); $model->transaction_id = $notify['transaction_id']; $model->update(); return true; } }); return $response; } }
对上面的逻辑有几点要注意,这也是我们用yii2-wx的时候要注意的。
关闭csrf验证 主要是防止yii2将微信给我们的结果通知请求屏蔽掉。
在设置礼物日志已付款前要判断下,如果已经付款则返回true,这样微信就不会再发请求。
现在我们搞定了回调,看下效果。
不错不错
离成功越来越近了!接下来我们要解决一个问题,就是当用户支付后在浏览器上礼物列表的变化,我希望二维码消失同时出现一个支付成功的页面。
我需要一个轮询,那么开始吧,为此我在gift.js中增加一个轮询功能,这个功能在渲染出二维码后被触发。
//gift.js exports.askIsPay = function(id){ var url = '/gift/is-pay.html'; $.getJSON(url,{id:id},function(d){ if(d.result === 'ok'){ $('#payQrcode').empty() .html("<h1>支付成功</h1><p>感谢您对作者的支持,他会知道您的名字以及打款。</p>"); }else{ setTimeout(function(){ exports.askIsPay(id) },3000); } }); }
每3秒询问一次服务器上gift/is-pay动作是否此送礼物日志已经付款,当然要告诉是哪个订单,如果已经付款则改变p#payQrcode的内容,否则继续调用exports.askIsPay(id)再一次询问。一点注意的是我们在生成二维码的时候需要服务器将此日志的id返回(这需要服务器的gift/qrcode动作返回此送礼物日志的ID),当exports.askIsPay触发时export.qrcode将其传入。
... if(d.result === 'ok'){ $('#payQrcode').empty() .html("<img style="max-width:90%"+d.qrcode+"'/ alt="三招教你怎樣實現微信禮物打賞功能 (程式碼全)" >"); exports.askIsPay(d.oId); }else{ modal.msg(d.message); } ...
当然我们还要在服务器上新建一个控制器的动作。
// GiftController.php public function actionIsPay($id){ Yii::$app->response->format = 'json'; try { $model = GiftLog::findOne($id); if($model->status == 'unpay'){ throw new Exception('还没有支付'); } return ['result'=>'ok']; }catch(Exception $e){ return ['result'=>'fail','message'=>$e->getMessage()]; } }
大功告成,看看效果。
到此我们就完成了永不打赏礼物的全过程,算上部吧,下部我们将实现具体的打款到用户账号以及使用yii2-wx调用微信企业付款到零钱包接口实现钱到微信功能。
相关推荐:
以上是三招教你怎樣實現微信禮物打賞功能 (程式碼全)的詳細內容。更多資訊請關注PHP中文網其他相關文章!