iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 15
1
Software Development

PHP新手30天實戰金流系列 第 15

[Day15]平台串金流--付款(下) / 超商付款 ECPay

tags: PHP新手30天實戰金流, Laravel6

前言

我們今天的目標是要將原本 ECPay的付款成功畫面改為我們自己的前端頁面。

PS ECpay 沒有退款的測試環境 因此沒有繼續做下去

  • 修改前:
  • 修改後:
    (付款完之後直接轉到訂單狀態頁面)

Step 1 Ngrok

我們會傳 ReturnURL 當作付款完成通知回傳的網址,為了讓 ECPay server 可以找到我們在本機建立的 server,我們使用 Ngrok 來連接外網

  1. 安裝 brew cask install ngrok
  2. 執行 ngrok http 8000
ngrok by @inconshreveable                                                            (Ctrl+C to quit)
                                                                                                     
Session Status                online                                                                 
Session Expires               7 hours, 59 minutes                                                    
Version                       2.3.34                                                                 
Region                        United States (us)                                                     
Web Interface                 http://127.0.0.1:4040                                                  
Forwarding                    http://4c1b0ff5.ngrok.io -> http://localhost:8000                      
Forwarding                    https://4c1b0ff5.ngrok.io -> http://localhost:8000                     
                                                                                                     
Connections                   ttl     opn     rt1     rt5     p50     p90                            
                              0       0       0.00    0.00    0.00    0.00 

現在我們開啟 http://4c1b0ff5.ngrok.io 就等於連到 http://localhost:8000

Step 2 PaymentController

我們在 Day 13 的時候 有在 payByWebsite 函式中設定 API 參數-- "ReturnURL" , 現在加一個 "OrderResultURL",這主要是可以將付款後的畫面轉到我們自己的頁面,差異如下表。

  • 此外,我們在這個函式裡將訂單的付款編號設為 "特店交易編號",好讓我們在收到 server 回傳通知的時候能夠去對應找到該訂單。
    $order->update([
                        'payment_no'        => $MerchantTradeNo,
                    ]);
    
  • payByWebsite 函式的完整程式碼如下:

p.s ['ReturnURL'], ['OrderResultURL'], ['ClientBackURL']中的 ngrok 臨時 url 須自行更換唷!

    public function payByWebsite(Order $order)
    {
        $this->authorize('own', $order);

        // 訂單已支付或關閉
        if ($order->paid_at || $order->closed) {
            throw new InvalidRequestException('無法付款');
        }


        include('ECPay.Payment.Integration.php');
            try {
                
                $obj = new ECPay_AllInOne();
           
                //服務參數
                $obj->ServiceURL  = "https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V5";  //服務位置
                $obj->HashKey     = '5294y06JbISpM5x9' ;                                          //測試用Hashkey,請自行帶入ECPay提供的HashKey
                $obj->HashIV      = 'v77hoKGq4kWxNNIS' ;                                          //測試用HashIV,請自行帶入ECPay提供的HashIV
                $obj->MerchantID  = '2000214';                                                    //測試用MerchantID,請自行帶入ECPay提供的MerchantID
                $obj->EncryptType = '1';                                                          //CheckMacValue加密類型,請固定填入1,使用SHA256加密
        

                $MerchantTradeNo = substr($order['no'],10,10).time() ; 
                //基本參數(請依系統規劃自行調整)
                $obj->Send['ReturnURL']         = "http://4af10922.ngrok.io/payment/website/listenPayResult" ;     //付款完成通知回傳的網址
                $obj->Send['OrderResultURL']    = "http://4af10922.ngrok.io/payment/website/notify";
                $obj->Send['ClientBackURL']    ="http://4af10922.ngrok.io/orders";
                $obj->Send['MerchantTradeNo']   = $MerchantTradeNo;              //訂單編號
                $obj->Send['MerchantTradeDate'] = date('Y/m/d H:i:s');                        //交易時間
                $obj->Send['TotalAmount']       = $order->total_amount;                                       //交易金額
                $obj->Send['TradeDesc']         = "ecpay test" ;                           //交易描述
                $obj->Send['ChoosePayment']     = ECPay_PaymentMethod::ALL ;
                                  //付款方式:全功能

                $order->update([
                    'payment_no'        => $MerchantTradeNo,
                ]);
                
            }catch (Exception $e) {
                echo $e->getMessage();
            }  
            //訂單的商品資料
            foreach ($order['items'] as $a_item)
            {
                array_push($obj->Send['Items'], array('Name'     => $a_item['product']->title,
                                                        'Price'    => (int) $a_item->price,
                                                        'Currency' => "元",
                                                        'Quantity' => (int) $a_item['amount'],
                                                        'URL'      => "dedwed"));
            }
            
            $obj->CheckOut();
            return redirect()->route('orders.show', [$order]);
    }

Step 3 listenPayResult, websiteNotify 函式

我們將 ReturnURL 設為 listenPayResult,這裡回傳 '1|OK' 給 ECPay;
將 OrderResultURL 設為 websiteNotify,回傳一個前端畫面。

public function listenPayResult(Request $request)
{


    if ($request->all()['RtnCode']){
        $data = $request->all();
        $order = Order::where('payment_no', $data['MerchantTradeNo'])->first();

        $order->update([
            'paid_at'        => now(),
            'payment_method' => 'website',
        ]);
    }
    return '1|OK';
}
public function websiteNotify(Request $request)
{
    return redirect()->route('orders.show', compact('order'));
}

超商付款

  • 產生一筆繳費單:
    • 廠商訂單編號 38296644421569897542
    • 超商繳費代碼 LLL19274850920
  • 在ECPay的廠商測試帳號中模擬付款

上一篇
[Day14]平台串金流--付款(中)
下一篇
[Day16]平台串金流--退款 失敗 (ECpay 沒有退款的測試環境)
系列文
PHP新手30天實戰金流34

尚未有邦友留言

立即登入留言