Yii2 對接 ping++支付接口

ping++是一個第三方接口,官網:https://www.pingxx.com

github:    https://github.com/PingPlusPlus/pingpp-php

  

我用到的wechat的公衆號支付 和 alipay  ,主要的邏輯:

先在後臺控制器接收到前端發送過來的channel,然後,調用 pay() 函數。


public
static function pay($money,$orderNo,$channel) { $api_key = Yii::$app->params['API_KEY']; $app_id = Yii::$app->params['PAPP_ID']; //引入你的签名私钥 $path = dirname(dirname(__FILE__)).'/components/pingpp/rsa_private_key.pem'; PingppPingpp::setPrivateKeyPath($path); //$extra用于设置支付渠道所需的额外参数,额外参数多数是可选,请根据需求来决定。详情看参考文档 $extra = []; switch ($channel) { case 'alipay_wap': $extra = array( // success_url 和 cancel_url 在本地测试不要写 localhost ,请写 127.0.0.1。URL 后面不要加自定义参数 'success_url' =>Yii::$app->request->getHostInfo().'/'. Yii::$app->params['pay_success_url'], 'cancel_url' => Yii::$app->request->getHostInfo().'/'.Yii::$app->params['pay_cancel_url'], ); break; case 'wx_pub': $cookies = Yii::$app->request->cookies; $wx_code = $cookies->getValue('wx_code');  //下面有將怎麼獲取 $wx_app_id = Yii::$app->params['wechat']['wx_app_id']; $wx_app_secret = Yii::$app->params['wechat']['wx_app_secret']; $open_id = WxpubOAuth::getOpenid($wx_app_id, $wx_app_secret, $wx_code); $extra = array( 'open_id' => $open_id// 用户在商户微信公众号下的唯一标识,获取方式可参考 pingpp-php/lib/WxpubOAuth.php ); break; } PingppPingpp::setApiKey($api_key); //设置API-KEY try { //create方法表示发送支付请求到ping++平台,$ch表示请求成功时返回的charge对象(json格式),服务器端如果发起请求成功,此时只需要把charge对象传递给APP客户端,交给客户端处理 $ch = PingppCharge::create([ 'subject' => '標題', //关于这些参数的意义,请参考文档https://www.pingxx.com/api#api-c-new 'body' => '內容', 'amount' => $money, 'order_no' => $orderNo, 'currency' => 'cny', //货币代码 'extra' => $extra, 'channel' => $channel, 'client_ip' => $_SERVER['REMOTE_ADDR'], 'app' => ['id' => $app_id] ]); return $ch; } catch (PingppErrorBase $e) { //如果发起支付请求失败,则抛出异常 // 捕获报错信息 if ($e->getHttpStatus() != NULL) { header('Status: ' . $e->getHttpStatus()); echo $e->getHttpBody(); } else { echo $e->getMessage(); } } }

wx_code的獲取:

 /**
     * 判断是否在微信客户端打开链接
     * 如果是就跳转到微信code的重定向url地址
     * 如果不是就跳到支付宝支付界面
     */

    public function actionGetcode()
    {
        $isWechat = Helper::isWechatBrowser();if($isWechat){
            $url = Helper::GetWxCodeUrl();
            header("Location: $url");
            exit();
        } else {
            $this->redirect(['order/payment']);
        }
    }



    /**
     * 通过微信重定向url获取code,
     * 并且把code设置为cookie
     */

    public function actionGetwxcode()
    {
        $code = Yii::$app->request->get('code');if(!empty($code)){
            $cookies = Yii::$app->response->cookies;
            $cookies->add(new yiiwebCookie([
                'name' => 'wx_code',
                'value' => $code,
                'expire'=>time()+3600,
            ]));
        }

        $this->redirect(['/order/payment']);
    }

Helper.php

        /**
         * 判断是否微信打开
         * @return boolean
         */
        public static function isWechatBrowser()
        {
            if (strpos($_SERVER['HTTP_USER_AGENT'],'MicroMessenger') !== false ) {
                return true;
            }
            
            return false;
        }


        /**
         * 获取微信code的重定向前的url
         * @return string
         */
        public static function GetWxCodeUrl()
        {
            $wx_app_id = Yii::$app->params['wechat']['wx_app_id'];
            $redirect_url = Yii::$app->params['wechat']['redirect_url'];
            $code_url = WxpubOAth::createOauthUrlForCode($wx_app_id, $redirect_url);  //WxpubOAth這個類在pingpplibWxpubOAth.php裏面
            
            return $code_url;
        }

然後,再看前端

$("#pay").click(function(){
        var pay_way = $("input[type='radio']:checked").val();
        if(pay_way == 1){
            wap_pay(1) //支付寶支付
        }else if(pay_way == 2){
            wap_pay(2) //微信支付
        }else if(pay_way == 3){
            paypal_pay() //PayPal支付
        }
    });

wap_way :

function wap_pay(channel) {
        if(url.length == 0 || !url.startsWith('http')){
            alert("请填写正确的URL");
            return;
        }

        var xhr = new XMLHttpRequest();
        xhr.open("POST", url, true);
        xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded;charset=UTF-8");
        xhr.send("channel="+channel+"&ssid="+ssid+"&_csrf="+_csrf);
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4 && xhr.status == 200) {
                console.log(xhr.responseText);
                pingpp.createPayment(xhr.responseText, function(result, err) {
                    console.log(result);
                    console.log(err.msg);
                    console.log(err.extra);
                    if (result == "success") {
                        // 只有微信公众账号 wx_pub 支付成功的结果会在这里返回,其他的支付结果都会跳转到 extra 中对应的 URL。
                        window.location.href = "<?php echo Url::to('/order/success')?>";
                    } else if (result == "fail") {
                        // charge 不正确或者微信公众账号支付失败时会在此处返回
                        window.location.href = "<?php echo Url::to('/order/cancel')?>";
                    } else if (result == "cancel") {
                        // 微信公众账号支付取消支付
                        window.location.href = "<?php echo Url::to('/order/cancel')?>";
                    }
                });
            }
        }
    }

最後,需要添加一個 回調url

在ping++設置中有一個webhooks,添加你的url地址

<?php
namespace frontendcontrollers;
use frontendcomponentsWechatPay;
use Yii;
use frontendcontrollersBaseController;
use frontendmodelsMovieOnlineOrder;
use frontendmodelsMovieSeat;


class CallbackController extends BaseController
{
    public $enableCsrfValidation = false;
/**
     * ping++的 異步回調 函數 
     */
    public function actionWebhooks()
    {
        $event = json_decode(file_get_contents("php://input"));
        
        // 对异步通知做处理
        if (!isset($event->type)) {
            header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request');
            exit("fail");
        }
        switch ($event->type) {
            case "charge.succeeded":
                // 开发者在此处加入对支付异步通知的处理代码
                
                header($_SERVER['SERVER_PROTOCOL'] . ' 200 OK');
                break;
            case "refund.succeeded":
                // 开发者在此处加入对退款异步通知的处理代码
                header($_SERVER['SERVER_PROTOCOL'] . ' 200 OK');
                break;
            default:
                header($_SERVER['SERVER_PROTOCOL'] . ' 400 Bad Request');
                break;
        }
    }



        
}
原文地址:https://www.cnblogs.com/weishuan/p/7464086.html