Have not written the actual combat class article for some time, today share an article, using Yii2 + HouJS + Yii2-wX to achieve wechat gift function.

Let’s start with a rendering

To put it simply, a pop-up box will appear after clicking the “Send a gift” button. There are many gifts in it. After clicking a gift, the pop-up box will refresh and a TWO-DIMENSIONAL code will appear.

Of course the money goes into the member’s personal account and is withdrawn.

Why make such a feature? To tell you the truth, I really don’t expect to get much from this. It’s more of an incentive. If you share valuable articles in our learning community, you are very likely to receive gifts from me.

Well, let’s talk about functions. There are several functions

  • Set up data table structure (gift and gift log)
  • Use HouJS to complete the foreground popup
  • Use Yii2-WX to realize payment QR code
  • Add account function for users
  • Using yii2-WX’s corporate pay-to-change and Yii2’s console mode reality allows users to make payments ($2 or more).

Library Url list

  1. houjs https://github.com/abei2017/yii2-wx
  2. yii2-wx https://github.com/abei2017/houjs

Oh, my god. It’s full of dry stuff. Start.

Data table structure

Since it is a gift, it naturally includes the gift table, as well as the log table for sending gifts. I plan as follows.

Gift gift table

Gift log table GIFt_log

Lang_id can be omitted for the GIFt_log table, which is added here for statistical purposes.

The overall train of thought

The overall logic of user gift giving is as follows

  1. Click “Send gifts” and background interactive access to this community gift list.
  2. After obtaining the data, jSmart engine is used to render the HTML code of the specific gift.
  3. Use Modal to put the gift list in the popup box to pop up.
  4. Click the gift and background interaction, the background generates a QR code to return.
  5. The user scans the code to pay.
  6. Payment successful.

Get the gift list

Next we use HouJS to build the foreground function. Houjs can be used to view the portal in the community. We mainly use its Modal popup helper and jSmart template engine.

Start by specifying a button

<button class="ui green button" id="giftBtn" data-url="<? = Url::to(['/gift/list','id'=>$lang->id]); ? < I class="share icon"></ I >Copy the code

Data-url represents the route used to get the gift list, doing a click event handling for the 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); }}); }); })Copy the code

A request is made to retrieve the gift list, and an error message is displayed if it fails.

Next we create a new giftController.php and define the list action.

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()]; }}Copy the code

From this we know that d. ata is now the community’s gift list in the data you get when you click the button.

After the console gets the gift list, use JSmart to convert the data into HTML code. To do this, we need to make a JSmart template and add this template in the gift button page.

<script id="giftTpl" type="text/x-jsmart-tmpl">
    <div class="gifts-box">
        <div class="gifts">
        {foreach $data as $key=>$gift}
            <a href="">
                <div class="gift-icon"><img src='{$gift.icon}'/></div>
                <div class="gift-name">{$gift.name}</div>
            </a>
        {/foreach}
        </div>
    </div>
</script>
Copy the code

The general meaning of this template is to loop the data in d. ata, put each gift in tag A, and then we supplement the JS code of the background to get the gift list, as follows.

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:'Give a gift'.size:'tiny'
                });
            }else{ modal.msg(d.message); }}); }); })Copy the code

To render the template, it’s time to see the effect.

I like it very much, using yii2 and houjs modal&jsmart to complete the gift list function. Next we need to do an important thing, interact with the background and get the payment QR code.

Get payment QR code

In this chapter, we use yii2-WX extension to realize wechat payment function. The idea is to click the gift to obtain the qr code of payment.

Before proceeding, we optimize the JS method of the previous step and put the code into a separate JS module. In HouJS, it is recommended to put the BUSINESS JS code into HouJS /js/modules, as follows

define(function(require,exports,modules){
    var modal = require('mods/modal');
    var jSmart = require('jSmart');

    exports.list = function(a){$('#giftBtn').click(function(a){
            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:'Send a gift to the author',
                        size:'tiny'
                    });
                }else{ modal.msg(d.message); }}); }); }; });Copy the code

So the js code call to get the gift list becomes simpler, as follows

requirejs(['modules/gift'].function(gift){
    gift.list(a); })Copy the code

Future GIFT JS code can be put into houjs/js/modules/gift.js.

Ok, back to this part of the topic. How to obtain the PAYMENT QR code?

** My thinking is as follows: ** The user clicks on each gift and initiates a GET request to the server. This request contains the ID of the gift. After receiving it, the background generates a gift sending log and communicates with the wechat server to get the PAYMENT QR code, which is returned to the browser and rendered by the foreground.

No sooner said than done.

First add the gift list, a link for each gift, as follows

<script id="giftTpl" type="text/x-jsmart-tmpl"> <div class="gifts-box"> <div class="gifts"> {foreach $data as $key=>$gift} <a class="_get_qrcode" href="javascript:;" data-url="<? = Url::to(['/gift/qrcode']); ? >? id={$gift.id}"> <div class="gift-icon"><img src='{$gift.icon}'/></div> <div class="gift-name">{$gift.name}</div> </a> {/foreach} </div> </div> </script>Copy the code

We set three properties for each gift’s A link

  • Class =”_get_qrcode” class, this class does not play the role of the style, mainly for JS to listen for the tag used.
  • href=”javascript:;” Prevent clicking to jump
  • Data-url After the link is clicked, the JS function will initiate a request based on the address provided by data-URL

Next, we will make a JS method to implement the listening of a link click, as follows

// houjs/js/modules/gift.js
define(function(require,exports,modules){
    var modal = require('mods/modal');
    var jSmart = require('jSmart'); ./** * get the payment QR code for a gift */
    exports.qrcode = function(){$('._get_qrcode').click(function(){
            var url = $(this).attr('data-url');
            $.getJSON(url,{},function(d){
                if(d.result === 'ok'){
                    $('#payQrcode')
                        .html("<img width='120' src='"+d.qrcode+"' / >");
                }else{ modal.msg(d.message); }}); }); }; });Copy the code

One thing to note is that the gift list is HTML code added after dom rendering of the page, so if you want the a link of the gift list to be listened, you need to call the exports.qrcode() function to listen after successfully retrieving the gift list, as shown below

// 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); }}); }); };/** * get the payment QR code for a gift */
    exports.qrcode = function(){... }; });Copy the code

Now the user clicked on the a link of the gift and the gift.qrcode() method started to work. The request reached the gift/qrcode action of Yii2. I wrote the following code.

// yii2 GiftController/actionQrcode

      
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'= >"Gift giving".'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()]; }}}Copy the code

The first thing to note is that there is no problem with the above code, but you still need to deal with the details if it goes live.

We do three things in the actionQrcode method

  1. Generate a gift sending log
  2. Call Yii2-WX to generate payment QR code
  3. Use QrCode to generate the QrCode and send it to the browser

The method of generating QR code native provided by Yii2-WX is used here. All that remains is how to display the QR code.

In order to allow users to re-select gifts before payment, the qr code is not selected this time, but the gift page replacement method is used, as shown below

I added a div to store the QR code on the right side of the gift, and filled it with some help when there is no choice. The qrcode is stored by the gift.qrcode() method

$('#payQrcode').html("<img width='120' src='"+d.qrcode+"' / >");
Copy the code

The corresponding gift list template also adds a payment area

<script id="giftTpl" type="text/x-jsmart-tmpl">
    <div class="gifts-box">
        <div class="gifts">
        {foreach $data as $key=>$gift}
            <a class="_get_qrcode" href="javascript:;" data-url="
        ? id={$gift.id}">
                <div class="gift-icon"><img src='{$gift.icon}'/></div>
                <div class="gift-name">{$gift.name}</div>
            </a>
        {/foreach}
        </div>
        <div id="payQrcode">
            <h1>Use tips</h1>
            <p>Click on the left side of the small gift will appear the payment qr code, scan the code to send.</p>
        </div>
        <div class="clear"></div>
    </div>
</script>
Copy the code

All right, let’s see what happens.

Users pay with their phones

When the user gets the payment qr code is bound to scan the code payment, there are two things to do next

  • Yii2 will process wechat payment result notification and set this gift log as paid.
  • The qr code of the gift list disappears in the browser last time, indicating successful payment.

Let’s start with the result notification, which is very easy to do with yii2-Wx. Add a notify action to the GiftController.

// GiftController.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(a){
        $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(The '-',$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; }}Copy the code

There are a few things to note about the logic above, and this is what we should note when using yii2-Wx.

  • Closing CSRF verification is mainly to prevent Yii2 from shielding the result notification request sent to us by wechat.
  • Check before setting the gift log that the payment has been made, return true if the payment has been made, so wechat will not send the request again.

Now that we’ve done the callback, let’s see what happens.

Good good

Closer and closer to success! Next, we need to solve a problem, which is the change of the gift list on the browser after the user pays. I hope the QR code will disappear and a page of successful payment will appear.

I need a poll, so let’s get started. To do this, I added a poll feature to gift.js, which is triggered when the QR code is rendered.

//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 > Payment successful 

Thank you for your support to the author, he will know your name and the payment.

"
); }else{ setTimeout(function(a){ exports.askIsPay(id) },3000); }}); }Copy the code

Every 3 seconds ask if the gift/ IS-pay action on the server has been paid, of course tell which order, if it has been paid change the content of div#payQrcode, otherwise continue to call exports. AskIsPay (id) ask again. One thing to note is that when we generate the qrcode, we need the server to return the id of the log (this requires the server’s gift/qrcode action to return the id of the gift log). When exports.askispay is triggered, export.qrcode passes it in.

. if(d.result ==='ok'){
    $('#payQrcode').empty()
        .html("<img width='120' src='"+d.qrcode+"' / >");
    exports.askIsPay(d.oId);
}else{ modal.msg(d.message); }...Copy the code

Of course we also need to create a new controller action on the server.

// GiftController.php
public function actionIsPay($id){
    Yii::$app->response->format = 'json';
    try {
        $model = GiftLog::findOne($id);
        if($model->status == 'unpay') {throw new Exception('Not paid yet');
        }

        return ['result'= >'ok'];
    }catch(Exception $e){
        return ['result'= >'fail'.'message'=>$e->getMessage()]; }}Copy the code

There we go. Look at the results.

summary

At this point, we have completed the whole process of never tipping gifts, including the first part. In the second part, we will realize the specific payment to user account and use yii2-WX to call wechat enterprise payment to zero wallet interface to realize the money to wechat function.

The content in the tutorial is not implemented to identify which post or article received payment, of course my site has implemented, you can try ha.

More original Yii2 articles