iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 29
2
Modern Web

寫給朋友的 PHP 從 0 到 100 實戰教程系列 第 29

Day 29. PHP教學: 刷完信用卡導回網站的處理

先來看看我在 config 定義的常數,商家 ID 跟 API_URL 都是綠界文件上測試用的參數,套上去就可以用特定的卡號完成刷卡結帳測試。

config/Config.php

... 上略 ...
const ECPAY_CALLBACK_URL = "http://localhost/game/ecpay-callback";
const ECPAY_API_URL = "https://payment-stage.ecpay.com.tw/Cashier/AioCheckOut/V2";
const ECPAY_HASH_KEY = "5294y06JbISpM5x9";
const ECPAY_HASH_IV = "v77hoKGq4kWxNNIS";
const ECPAY_MERCHANT_ID = "2000132";
/**
 * ECPAY 測試環境僅接受以下的測試卡號
 * 4311-9522-2222-2222
 * 測試卡號有效月年需是未來,卡片背面末三碼:222
 */

由此可知 我設計讓綠界完成結帳後導回的網址是 ecpay-callback 我習慣先 print_r($_POST) 徹底確認到底會打什麼 POST 參數回來,確認後 認定 RtnCode 是 1 的情況下就代表成功!那就驗證它吧。
這邊用 Session 記住 Order 內容,因為會離開網站再回來。設定訂單完成後,儲存它,就可以送感謝頁囉。

controller/ecpay-callback.php

<?php
/**
 * 
 * print_r($_POST); 可得到 ECPAY 的回傳參數
 * Array
(
    [AlipayID] = 
    [AlipayTradeNo] = 
    [amount] = 100
    [ATMAccBank] = 
    [ATMAccNo] = 
    [auth_code] = 777777
    [card4no] = 2222
    [card6no] = 431195
    [eci] = 0
    [ExecTimes] = 
    [Frequency] = 
    [gwsr] = 10625000
    [MerchantID] = 2000132
    [MerchantTradeNo] = TWMO15161330399485
    [PayFrom] = 
    [PaymentDate] = 2018/01/17 04:05:23
    [PaymentNo] = 
    [PaymentType] = Credit_CreditCard
    [PaymentTypeChargeFee] = 1
    [PeriodAmount] = 
    [PeriodType] = 
    [process_date] = 2018/01/17 04:05:23
    [red_dan] = 0
    [red_de_amt] = 0
    [red_ok_amt] = 0
    [red_yet] = 0
    [RtnCode] = 1
    [RtnMsg] = Succeeded
    [SimulatePaid] = 0
    [staed] = 0
    [stage] = 0
    [stast] = 0
    [TenpayTradeNo] = 
    [TotalSuccessAmount] = 
    [TotalSuccessTimes] = 
    [TradeAmt] = 100
    [TradeDate] = 2018/01/17 04:04:00
    [TradeNo] = 1801170404001853
    [WebATMAccBank] = 
    [WebATMAccNo] = 
    [WebATMBankName] = 
    [CheckMacValue] = 5EB7AF8FEEFB1290072864A4A6615272A7BADE186E0E327314A0DC9C03A8B9A1
)
 */

 if(isset($_POST['RtnCode']) AND $_POST['RtnCode'] == 1)
 {
    $order = unserialize(base64_decode($_SESSION['order']));
    $order->setOrderComplete();
    $order->save();
    $_SESSION['order'] = base64_encode(serialize($order));
    header('Location: '.Config::BASE_URL."thankyou");
    exit;
 }else{
    header('Location: '.Config::BASE_URL."fail");
    exit;
 }

在感謝頁的邏輯層中,要檢查是否登入狀態,訂單是否完成,未完成要清掉購物車踹回首頁。
如果都沒問題,就開放下載囉!

controller/thankyou.php

<?php

  if(!UserVeridator::isLogin(isset($_SESSION['memberID'])?$_SESSION['memberID']:'')){
    header('Location: '.Config::BASE_URL);
    exit;
  }

  $order = unserialize(base64_decode($_SESSION['order']));

  if($order->status == 1){
    $cart = new Cart($_SESSION['cartQty'], $_SESSION['cartPrice'], $_SESSION['cartName']);
    $productKeys = $cart->getAllProductID();

    include('view/header/default.php'); // 載入共用的頁首
    include('view/body/thankyou.php');    
    include('view/footer/default.php'); // 載入共用的頁尾
  }else{
    
    unset($_SESSION['cartQty']);
    unset($_SESSION['cartPrice']);
    unset($_SESSION['cartName']);
    unset($_SESSION['order']);
    header('Location: '.Config::BASE_URL);
    exit;
  }

在感謝頁下方有個按鈕是回首頁,其實這個按鈕導向是 do_unset 用來幫使用者清除所有購物車跟訂單。
以免公用電腦被其他人免費下載資料

controller/do_unset.php

<?php
  
  unset($_SESSION['cartQty']);
  unset($_SESSION['cartPrice']);
  unset($_SESSION['cartName']);
  unset($_SESSION['order']);

  header('Location: '.Config::BASE_URL);
  exit;

這樣就可以測試出這樣的付費流程囉:

https://ithelp.ithome.com.tw/upload/images/20180117/20107394mYDsPQZKcG.pnghttps://ithelp.ithome.com.tw/upload/images/20180117/20107394AjQG7ED0Wm.pnghttps://ithelp.ithome.com.tw/upload/images/20180117/20107394ngrVfVPANJ.pnghttps://ithelp.ithome.com.tw/upload/images/20180117/20107394VuBHKZt2Aw.png


上一篇
Day 28. PHP教學: 實作商務邏輯層
下一篇
Day 30. 竟然要結束了那就大放送附專案原始碼
系列文
寫給朋友的 PHP 從 0 到 100 實戰教程30

1 則留言

0
billingchan
iT邦新手 5 級 ‧ 2020-09-19 12:10:42

您好:雖然這篇已經過兩年了,接綠界的版本說不定也不同了~不過原理應該還是可以討論一下?從綠界付完款之後回來接的頁面(ecpay-callback.php),應該抓不到原本登入的$SESSION 才對?因為連線是綠界與伺服器,而不是client與伺服器?謝謝!

falconwei iT邦新手 5 級 ‧ 2020-09-19 14:26:57 檢舉

轉送去綠界之前可以用 session 記住當前訂單編號,付款完畢後從綠界回來就能抓同一組session 比對回傳的訂單編號。

或是直接把必要資訊寫到綠界的自訂欄位中也可以

我要留言

立即登入留言