天天看點

Yansongda、EasyWeChat對接支付寶、微信支付

最近在開發一個項目包含web端、H5端和App端,在開發支付功能時每個端的情況略有不同在這裡做一下記錄,支付寶支付使用Yangsongda,微信支付使用EasyWeChat,如有不對之處歡迎指正。

安裝Yansongda

composer require yansongda/pay -vvv
           

安裝EasyWeChat

composer require w7corp/easywechat
           

下面上代碼,可以直接使用

use EasyWeChat\Factory;
use Yansongda\LaravelPay\Facades\Pay;

class PayController extends BaseController
{
    public function buyVip(Request $request)
    {
        $user_id = $this->getUserId();
        $type = $request->input('type', '');
        $id = (int)$request->input('id', 0);
        $device_type = $this->deviceType;
        if (!$type) {
            return $this->error('支付類型不能為空');
        }
        if (!$id) {
            return $this->error('商品ID不能為空');
        }

        $vip = Vip::where('id', $id)->first();
        if (!$vip) {
            return $this->error('充值金額不存在');
        }

        if ($type == 'wxpay') {

            $order = OrderService::createOrder($user_id, $vip, 'alipay');
            $config = config('wechat.payment.default');

            $app = Factory::payment($config);

            if ($device_type == 'app') {
                // APP支付
                $result = $app->order->unify([
                    'body' => $order['subject'],
                    'out_trade_no' => $order['order_sn'],
                    'total_fee' => $order['amount'] * 100,
                    //'notify_url' => 'https://pay.weixin.qq.com/wxpay/pay.action', // 支付結果通知網址,如果不設定則會使用配置裡的預設位址
                    'trade_type' => 'APP', // 請對應換成你的支付方式對應的值類型
                ]);

            } else {

                if (isWechat()) {
                    $openid = DB::table('user')->where('id', $user_id)->value('wechat_openid');
                    if (!$openid) {
                        return $this->error('openid不存在');
                    }
                    //h5 微信jssdk
                    $result = $app->order->unify([
                        'body' => $order['subject'],
                        'out_trade_no' => $order['order_sn'],
                        'total_fee' => $order['amount'] * 100,
                        //'notify_url' => 'https://pay.weixin.qq.com/wxpay/pay.action', // 支付結果通知網址,如果不設定則會使用配置裡的預設位址
                        'trade_type' => 'JSAPI', // 請對應換成你的支付方式對應的值類型
                        'openid' => $openid,
                    ]);

                } else {
                    // web/h5 掃碼支付
                    $result = $app->order->unify([
                        'body' => $order['subject'],
                        'out_trade_no' => $order['order_sn'],
                        'total_fee' => $order['amount'] * 100,
                        //'notify_url' => 'https://pay.weixin.qq.com/wxpay/pay.action', // 支付結果通知網址,如果不設定則會使用配置裡的預設位址
                        'trade_type' => 'NATIVE', // 請對應換成你的支付方式對應的值類型
                    ]);

                }
            }

            if ($result['return_code'] != 'SUCCESS') {

                return $this->error('通信失敗:' . $result['return_msg'], $result);
            }

            if ($result['result_code'] != 'SUCCESS') {
                return $this->error('支付失敗:' . $result['err_code'] . ':' . $result['err_code_des'], $result);
            }

            return $this->success('支付成功', $result);


        } elseif ($type == 'alipay') {
            $order = OrderService::createOrder($user_id, $vip, 'alipay');
            $config = config('pay.alipay');
            $alipay = Pay::alipay($config);
            $body = [
                'subject' => $order['subject'],
                'out_trade_no' => $order['order_sn'],
                'total_amount' => $order['amount'],
            ];
            if ($device_type == 'app') {
                return $alipay->web($body);
            } else {
                if (isMobile()) {
                    return $alipay->wap($body);
                } else {

                    return $alipay->app($body);
                }
            }


        } elseif ($type == 'applepay') {
            $order = OrderService::createOrder($user_id, $vip, 'applepay');
            $data = [
                'order_id' => $order['id'],
                'order_sn' => $order['order_sn'],
                'price' => $order['amount'],
                'payment' => $order['payment']
            ];

            return $this->success('操作成功', $data);
        }

        return $this->error('error');

    }

    //微信支付異步回調
    public function wxpayNotify()
    {
        $config = config('wechat.payment.default');

        $app = Factory::payment($config);

        $response = $app->handlePaidNotify(function ($message, $fail) {
            // 使用通知裡的 "微信支付訂單号" 或者 "商戶訂單号" 去自己的資料庫找到訂單
            $order = Order::where('order_sn', $message['out_trade_no'])->first();

            if (!$order || $order->status == 1) { // 如果訂單不存在 或者 訂單已經支付過了
                return true; // 告訴微信,我已經處理完了,訂單沒找到,别再通知我了
            }

            / <- 建議在這裡調用微信的【訂單查詢】接口查一下該筆訂單的情況,确認是已經支付 /

            if ($message['return_code'] != 'SUCCESS') { // return_code 表示通信狀态,不代表支付狀态

                return $fail('通信失敗,請稍後再通知我');

            }

            // 使用者是否支付成功
            if (array_get($message, 'result_code') === 'SUCCESS') {
                $order->pay_time = time(); // 更新支付時間為目前時間
                $order->status = 1;

                // 使用者支付失敗
            } elseif (array_get($message, 'result_code') === 'FAIL') {
                $order->status = 2;
            }

            $order->save(); // 儲存訂單

            return true; // 傳回處理完成
        });

        return $response;
    }

    //支付寶支付異步回調
    public function alipayNotify(Request $request)
    {
        $config = config('pay.alipay');
        $alipay = Pay::alipay($config);
        try {
            $data = $alipay->verify(); // 是的,驗簽就這麼簡單!
            //以下根據自己業務進行支付校驗
            $order = Order::where('order_sn', $data->out_trade_no)->first();
            if (!$order || $order->status == 1) {
                //如果訂單狀态異常直接退出
                return $alipay->success();
            }

            \Log::debug('Alipay notify', $data->all());
            //進行訂單狀态變更等支付成功操作
            PayService::handleOrderPaid($order);
            return $alipay->success();

        } catch (\Exception $e) {

        }
        return $alipay->success();// laravel 架構中請直接 `return $alipay->success()`
    }


    //支付寶支付同步接口
    public function alipayReturn(Request $request)
    {
        $config = config('pay.alipay');
        $alipay = Pay::alipay($config);

        return $alipay->gateway()->verify($request->all());

    }

    
    //蘋果支付訂單結果查詢
    public function appleNotify(Request $request)
    {
        $receipt_data = $request->input('receipt-data', '');
        $order_sn = $request->input('order_sn', '');
        $is_sandbox = (int)$request->input('is_sandbox', 0);
        if (!$receipt_data || !$order_sn) {
            return $this->error('缺少必要參數');
        }

        //是否沙箱環境
        $sandbox = false;
        if ($is_sandbox) {
            $sandbox = true;
        }
        $result = PayService::validateApplePay($receipt_data, $sandbox);

        if ($result['status'] == true) {
            //通過驗證
            $order = Order::where('order_sn', $order_sn)->first();
            if (!$order) {
                return $this->error('訂單不存在');
            }

            if ($order['status'] != 1) {
                PayService::handleOrderPaid($order);

            }
            return $this->success('支付成功');
        } else {

            return $this->error($result['message']);
        }
    }

}
           

代碼中有幾個類庫沒有引入,要根據自己實際情況添加。

也可以參考該文章:

可能是我用過的最優雅的 Alipay 和 WeChat 的支付 SDK 擴充包了 — 闫嵩達 | yansongda

Web端調起支付效果 

Yansongda、EasyWeChat對接支付寶、微信支付
Yansongda、EasyWeChat對接支付寶、微信支付

 移動端調起支付效果

Yansongda、EasyWeChat對接支付寶、微信支付
Yansongda、EasyWeChat對接支付寶、微信支付