Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
本外掛仍處於測試階段,同時還有若干已知問題,目前停止更新中。
因為公司的專案 applemint lab 需要,所以調查了一些限制內容的外掛。
當初針對「約期授權 (Subscription)」、「限制內容 (Content Restriction)」等關鍵字搜尋後,發現了兩款名稱相近的外掛 Paid Membership Pro (PMPro) 與 Paid Member Subscriptions (PMS)。試用一下之後,發現 PMS 蠻符合 applemint lab 的需求,因此就決定使用該款外掛來建立限制內容。
目前這類外掛都是由外國開發,因此串接的金流主要都是 PayPal 或是 Stripe 這類海外金流服務。為了能夠在台灣使用,因此嘗試串接了綠界的金流,作為主要的支付方式。
這篇文章主要是記錄當初是如何摸索串接的方法,跟 PMS 有關的相關設定,以及留下目前仍須解決的待辦事項。
首先,先來分享一下為了公司開發的專案 Paid Member Subscriptions Taiwan Gateways。有興趣的話,歡迎大家建立分支版本 (fork),協助讓這個套件更好用。
內容目錄
如果是一般使用者,可以前往這個 GitHub 專案,點擊 [Code] > [Download ZIP]。
在你的網站中,安裝 Paid Member Subscriptions。
最後再按照一般安裝外掛的流程,將剛才從 GitHub 下載的 .zip 檔上傳並安裝就好。
到 Paid Member Subscriptions 的 Settings 中,選擇 Payments 的分頁,便可以勾選綠界的支付管道「ECPay」了。
接著填入特店的編號、Hash Key 與 Hash IV。(目前 Return URL 功能尚未啟用)
如果你有些功能想要自己加入,或是想要將原本的 GitHub 專案分支出去,一起參與這款擴充套件的開發,接下來的內容會提供你一些 Paid Member Subscriptions 的細節,幫助你進一步了解串接的流程。
為了要在後台可以選擇支付方式,需要先註冊一個支付選項。
這裡除了需要包含註冊的支付管道名稱外,需要注意 class_name
這個值,這裡需要定義的是實際執行支付的物件類別 (Class)。
if ( !function_exists( 'pms_custom_gateway' ) ) { function pms_custom_gateway( $arr ){ $arr['ECPay'] = array( 'display_name_user' => __( 'ECPay', 'pms-taiwan-gateways' ), 'display_name_admin' => __( 'ECPay', 'pms-taiwan-gateways' ), 'class_name' => 'PMS_Payment_Gateway_TW_ECPay' ); return $arr; } } add_filter( 'pms_payment_gateways', 'pms_custom_gateway', 101, 1 );
從 0 開始串接實在是風險太大了,因此我先從外掛中,將 PayPal 的串接方式複製出來,並針對寫法進行分析,將相關的設定改為綠界支付所需要的資訊。
在延伸物件類別時,需要特別注意,為了避免找不到上層類別 (Parent Class) 造成繼承的錯誤,我是透過 plugins_loaded
這個勾點作為防護機制,但是並非其他外掛都可以用這種方法,所以遇到其他外掛時,建議先嘗試看看。
add_action( 'plugins_loaded', 'pms_ecpay_extend' ); //把 Class 的順序降低,等到其他外掛載入完之後再繼承 Class,不然會炸裂 function pms_ecpay_extend() { if ( class_exists( 'PMS_Payment_Gateway' ) ) { Class PMS_Payment_Gateway_TW_ECPay extends PMS_Payment_Gateway { //... // 定義綠界的參數 $ecpay_args = array(); // 開始執行 try { //把綠界 SDK 執行交易的流程套用到這裡 } } }
在這個步驟中,需要設定 $notify_url
變數,主要目的是用來接收 Webhook 回傳的資料 (綠界串接文件中的 Notify URL)。
參考了其他的支付管道後,發現都會建立一個 PMS_xx_Verifier
的物件,來檢查資料是否正確。
驗證完畢後,為了要變更交易狀態,因此需要透過 pms_ecpay_payment_data
這個勾點,帶入綠界回傳的資料。在這我把 subscription_id
這個選項,傳到綠界的自訂欄位 (CustomField2) 中,這樣回頭才能夠確認是不是與購入的方案相符。
$payment_data = apply_filters( 'pms_ecpay_payment_data', array( 'payment_id' => $payment_id, 'user_id' => $user_id, 'type' => $post_data['PaymentType'], 'status' => $post_data['RtnCode'] == 1 ? 'completed' : 'failed', 'transaction_id' => $post_data['MerchantTradeNo'], 'amount' => $post_data['TradeAmt'], 'date' => $post_data['PaymentDate'], 'subscription_id'=> $post_data['CustomField2'] ), $post_data );
PMS 後台提供了定期定額的選項 recurring
,可以用來判斷是否要串接綠界的定期定額功能。
$settings = get_option( 'pms_payments_settings' ); if( !empty( $settings['recurring'] ) ) { $ecpay_args['PeriodAmount'] = $this->amount; $ecpay_args['PeriodType'] = 'M'; $ecpay_args['Frequency'] = 1; $ecpay_args['ExecTimes'] = 99; $ecpay_args['PeriodReturnURL'] = $ecpay_args['return_url'] ?: ''; }
方法/函式名稱 | 功能 |
---|---|
pms_is_payment_test_mode() | 當後台設定勾選 [Test Mode] 時,會回傳 true ,用來判斷是否是測試狀態。 |
$payment = pms_get_payment() | 用來取得當前支付的交易細節。 |
$payment -> log_data( '名稱', $data ) | 可以將目前支付的狀態紀錄到資料庫中進行偵錯。 |
這裡與 WordPress 外掛學習者分享一個我自己分析外掛的方式,很陽春,但我自己覺得很實用。
首先,到後台找到設定支付管道的設定頁面,並複製關鍵字,用這個關鍵字搜尋到相關檔案。
搜尋後發現是在 view-page-settings-payments.php
這個檔案中。進一步查到下面這段程式碼:
// PMS 版本: 2.5.6 $payment_gateways = pms_get_payment_gateways(); if( count( $payment_gateways ) > 1 ) : // Checkboxes to select active Payment Gateways echo '<div class="pms-form-field-wrapper pms-form-field-active-payment-gateways">'; echo '<label class="pms-form-field-label">' . esc_html__( 'Active Payment Gateways', 'paid-member-subscriptions' ) . '</label>'; foreach( $payment_gateways as $payment_gateway_slug => $payment_gateways_details ) { echo '<label>'; echo '<input type="checkbox" name="pms_payments_settings[active_pay_gates][]" value="' . esc_attr( $payment_gateway_slug ) . '" ' . ( !empty( $this->options['active_pay_gates'] ) && in_array( $payment_gateway_slug, $this->options['active_pay_gates'] ) ? 'checked="checked"' : '' ) . '/>'; echo esc_html( $payment_gateways_details['display_name_admin'] ); echo '</label><br>'; } echo '</div>';
得知是透過 pms_get_payment_gateways
這個函式去取得所有的支付管道,接著再度搜尋所有檔案,發現了這個函式的原始定義。
/** * Function that returns an array with all payment gateways * * @param $only_slugs - returns an array with the payment gateways slugs * * @return array * */ function pms_get_payment_gateways( $only_slugs = false ) { $payment_gateways = apply_filters( 'pms_payment_gateways', array( 'manual' => array( 'display_name_user' => __( 'Manual/Offline', 'paid-member-subscriptions' ), 'display_name_admin' => __( 'Manual/Offline', 'paid-member-subscriptions' ), 'class_name' => 'PMS_Payment_Gateway_Manual' ), 'paypal_standard' => array( 'display_name_user' => __( 'PayPal', 'paid-member-subscriptions' ), 'display_name_admin' => __( 'PayPal Standard', 'paid-member-subscriptions' ), 'class_name' => 'PMS_Payment_Gateway_PayPal_Standard' ) )); if( $only_slugs ) $payment_gateways = array_keys( $payment_gateways ); return $payment_gateways; }
這篇文章的其他函式也都是透過這個方法逐個分析出來的。
如果是使用整合編輯器 (IDE),通常會提供套件,可以讓你更快的尋找到函式與方法的定義。
版主您好,感謝您開發了這個外掛!
想詢問 ECPay Execution Time(s) 設定為 12 的話,是用戶在 12 個月後就會自動停止訂閱的意思嗎?
以及 return URL 的用途是什麼呢?
謝謝版主