為WooCommerce創建一個支付網關插件

在本文中,我將指導您完成為WooCommerce創建自定義支付網關插件時所需的所有步驟。

第1步:我們首先創建一個插件

當我第一次聽說WordPress插件時,我認為創建插件非常困難。但是實際上,要創建一個插件,您只需要創建一個文件并在其中添加幾行代碼即可。

因此,在plugins文件夾中,我創建了misha-gateway.php文件,并在其中添加了以下代碼。如果您的插件有多個文件,請將其放在具有相同名稱的文件夾中,例如:misha-gateway/misha-gateway.php

<?php
/*
 * Plugin Name: WooCommerce Misha Payment Gateway
 * Plugin URI: https://rudrastyh.com/woocommerce/payment-gateway-plugin.html
 * Description: Take credit card payments on your store.
 * Author: Misha Rudastyh
 * Author URI: http://rudrastyh.com
 * Version: 1.0.1
 *

完成后,該插件將顯示在您的管理區域中!您甚至可以激活它。

在WooCommerce中添加自定義支付網關

第2步:創建支付網關PHP類框架

我們必須創建一個自定義PHP類來擴展WooCommerce 的 WC_Payment_Gateway類。每個類方法如下所述。您可以首先將以下代碼復制并粘貼到主插件文件中。

/*
 * 這個動作掛鉤將我們的PHP類注冊為WooCommerce支付網關
 */
add_filter( 'woocommerce_payment_gateways', 'misha_add_gateway_class' );
function misha_add_gateway_class( $gateways ) {
	$gateways[] = 'WC_Misha_Gateway'; // 在這里添加類名稱
	return $gateways;
}
 
/*
 * 類本身,請注意,它掛載到plugins_loaded動作鉤子內
 */
add_action( 'plugins_loaded', 'misha_init_gateway_class' );
function misha_init_gateway_class() {
 
	class WC_Misha_Gateway extends WC_Payment_Gateway {
 
 		/**
 		 * 類構造函數,在第3步中有更多關于它的信息
 		 */
 		public function __construct() {
 
		...
 
 		}
 
		/**
 		 * 插件選項,我們也在第3步中處理它
 		 */
 		public function init_form_fields(){
 
		...
 
	 	}
 
		/**
		 * 如果您需要自定義信用卡表格,則將需要它,步驟4就是關于它的
		 */
		public function payment_fields() {
 
		...
 
		}
 
		/*
		 * 自定義CSS和JS,在大多數情況下,僅在您決定使用自定義信用卡表格時才需要
		 */
	 	public function payment_scripts() {
 
		...
 
	 	}
 
		/*
 		 * 字段驗證,更多信息請參見第5步
		 */
		public function validate_fields() {
 
		...
 
		}
 
		/*
		 * 我們正在此處處理付款,有關付款的所有步驟均在第5步中
		 */
		public function process_payment( $order_id ) {
 
		...
 
	 	}
 
		/*
		 * 如果您需要Webhook,例如PayPal IPN等
		 */
		public function webhook() {
 
		...
 
	 	}
 	}
}

如果您在插件文件中按“原樣”插入代碼,則會出現500錯誤,因為該代碼僅顯示插件類的結構,每個方法應在其中完善。

第3步:支付網關插件選項

在類構造函數中,我們:

  • 定義類屬性,例如網關ID和名稱,第3-13行,
  • 初始化設置,第15-19行,
  • 將選項附加到類屬性,第20-25行,
  • 保存選項,第28行,
  • 如果需要,將自定義JavaScript和CSS排入隊列,第31行。

我們還可以在類構造函數中注冊支付網關的webhooks(例如第34行的示例)。

public function __construct() {
 
	$this->id = 'misha'; // 支付網關插件ID 
	$this->icon = ''; // 將顯示在結帳頁面上您的網關名稱附近的圖標的URL 
	$this->has_fields = true; // 如果您需要自定義信用卡形式
	$this->method_title = 'Misha Gateway';
	$this->method_description = 'Description of Misha payment gateway'; // 將顯示在選項頁面上
 
	// 網關可以支持訂閱,退款,保存付款方式,
	// 但在本教程中,我們先從簡單的支付開始
	$this->supports = array(
		'products'
	);
 
	// 具有所有選項字段的方法
	$this->init_form_fields();
 
	// 加載設置。
	$this->init_settings();
	$this->title = $this->get_option( 'title' );
	$this->description = $this->get_option( 'description' );
	$this->enabled = $this->get_option( 'enabled' );
	$this->testmode = 'yes' === $this->get_option( 'testmode' );
	$this->private_key = $this->testmode ? $this->get_option( 'test_private_key' ) : $this->get_option( 'private_key' );
	$this->publishable_key = $this->testmode ? $this->get_option( 'test_publishable_key' ) : $this->get_option( 'publishable_key' );
 
	// 這個動作掛鉤保存設置
	add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
 
	// 我們需要自定義JavaScript以獲得令牌
	add_action( 'wp_enqueue_scripts', array( $this, 'payment_scripts' ) );
 
	// 您也可以在此處注冊一個
	// add_action( 'woocommerce_api_{webhook name}', array( $this, 'webhook' ) );
 }

根據您使用的付款處理器的不同,選項字段可能會有所不同,但是在大多數情況下,您將具有“已啟用/已禁用”,“標題”,“描述”和“測試模式”選項。

public function init_form_fields(){
 
	$this->form_fields = array(
		'enabled' => array(
			'title'       => 'Enable/Disable',
			'label'       => 'Enable Misha Gateway',
			'type'        => 'checkbox',
			'description' => '',
			'default'     => 'no'
		),
		'title' => array(
			'title'       => 'Title',
			'type'        => 'text',
			'description' => 'This controls the title which the user sees during checkout.',
			'default'     => 'Credit Card',
			'desc_tip'    => true,
		),
		'description' => array(
			'title'       => 'Description',
			'type'        => 'textarea',
			'description' => 'This controls the description which the user sees during checkout.',
			'default'     => 'Pay with your credit card via our super-cool payment gateway.',
		),
		'testmode' => array(
			'title'       => 'Test mode',
			'label'       => 'Enable Test Mode',
			'type'        => 'checkbox',
			'description' => 'Place the payment gateway in test mode using test API keys.',
			'default'     => 'yes',
			'desc_tip'    => true,
		),
		'test_publishable_key' => array(
			'title'       => 'Test Publishable Key',
			'type'        => 'text'
		),
		'test_private_key' => array(
			'title'       => 'Test Private Key',
			'type'        => 'password',
		),
		'publishable_key' => array(
			'title'       => 'Live Publishable Key',
			'type'        => 'text'
		),
		'private_key' => array(
			'title'       => 'Live Private Key',
			'type'        => 'password'
		)
	);
}

如果您正確完成了所有操作,則您的選項頁面應如下所示:

我們的自定義網關的付款方式

第4步:直接結帳表單

在實施以下代碼之前,請閱讀以下要點:

  • 如果要創建類似PayPal的支付網關,所有用戶操作都在支付網關網站上進行,則可以跳過此步驟,不用添加payment_fields()validate_fields()方法,然后繼續執行第5步。
  • 在本教程中,我假設您使用付款處理器,該處理器使用其自己的AJAX請求發送信用卡數據并為您提供可在PHP中使用的令牌,因此請不要向信用卡表單字段添加 name 屬性。步驟如下:
    1. 客戶填寫他的信用卡數據,然后單擊“下訂單”按鈕。
    2. 我們checkout_place_order在WooCommerce中使用事件延遲了表單提交的時間,并將帶有信用卡數據的AJAX請求直接發送到我們的付款處理方,
    3. 如果客戶詳細信息確定,則處理者將返回令牌,我們將其添加到下面的表單中,
    4. 現在,我們可以提交表單(當然是用JS),
    5. 我們使用PHP中的令牌來通過付款處理器的API捕獲付款。

4.1 引入腳本

在第2步中,我們已經向其中添加了wp_enqueue_scripts動作掛鉤和連接 payment_scripts方法。

public function payment_scripts() {
 
	// 我們需要JavaScript僅在購物車/結帳頁面上處理令牌,對嗎?
	if ( ! is_cart() && ! is_checkout() && ! isset( $_GET['pay_for_order'] ) ) {
		return;
	}
 
	// 如果我們的付款網關被禁用,無需引入JavaScript
	if ( 'no' === $this->enabled ) {
		return;
	}
 
	// 如果沒有設置API密鑰,無需引入JavaScript
	if ( empty( $this->private_key ) || empty( $this->publishable_key ) ) {
		return;
	}
 
	// 如果是測試模式或非HTTPS下,無需執行
	if ( ! $this->testmode && ! is_ssl() ) {
		return;
	}
 
	// 假設我們的付款處理器JavaScript允許獲取令牌
	wp_enqueue_script( 'misha_js', 'https://www.mishapayments.com/api/token.js' );
 
	// 這是我們在您的插件目錄中使用的自定義js,它和token.js 一起工作
	wp_register_script( 'woocommerce_misha', plugins_url( 'misha.js', __FILE__ ), array( 'jquery', 'misha_js' ) );
 
	// 在大多數支付處理器中,您必須使用PUBLIC KEY來獲得令牌 
	wp_localize_script( 'woocommerce_misha', 'misha_params', array(
		'publishableKey' => $this->publishable_key
	) );
 
	wp_enqueue_script( 'woocommerce_misha' );
 
}

4.2 在JavaScript中獲取令牌

首先,我想說的是,對于每個支付處理器而言,此代碼可以有所不同,但是主要思想是相同的。這是misha.js文件的內容:

var successCallback = function(data) {
 
	var checkout_form = $( 'form.woocommerce-checkout' );
 
	// 將令牌添加到我們的隱藏輸入字段中
	// console.log(data)查找令牌 
	checkout_form.find('#misha_token').val(data.token);
 
	// 停用tokenRequest函數事件 
	checkout_form.off( 'checkout_place_order', tokenRequest );
 
	// 現在提交表單 
	checkout_form.submit();
 
};
 
var errorCallback = function(data) {
    console.log(data);
};
 
var tokenRequest = function() {
 
	// 這將是一個支付網關功能,處理來自表單的所有信用卡數據,
	// 也許它將需要您的Publishable API密鑰,即misha_params.publishableKey 
	// 并在成功時觸發successCallback(),而在失敗時觸發errorCallback 
	return false;
 
};
 
jQuery(function($){
 
	var checkout_form = $( 'form.woocommerce-checkout' );
	checkout_form.on( 'checkout_place_order', tokenRequest );
 
});

4.3 帶有信用卡數據的表單

使用payment_fields()類方法,您可以使用以下信用卡字段創建付款表單:

下面是代碼:

public function payment_fields() {
 
	// OK,讓我們顯示付款形式之前的一些說明
	if ( $this->description ) {
		// 你可以為測試模式的說明,我的意思是測試卡號碼等。
		if ( $this->testmode ) {
			$this->description .= ' TEST MODE ENABLED. In test mode, you can use the card numbers listed in <a href="#" target="_blank" rel="noopener noreferrer">documentation</a>.';
			$this->description  = trim( $this->description );
		}
		// 顯示<p>標記包含的描述等
		echo wpautop( wp_kses_post( $this->description ) );
	}
 
	// 輸出表單,但你可以關閉PHP標簽和直接在HTML打印
	echo '<fieldset id="wc-' . esc_attr( $this->id ) . '-cc-form" class="wc-credit-card-form wc-payment-form" style="background:transparent;">';
 
	// 如果希望您的自定義支付網關支持它,請添加此操作掛鉤 
	do_action( 'woocommerce_credit_card_form_start', $this->id );
 
	// 我建議使用Inique ID,因為其他網關可能已經使用#ccNo, #expdate, #cvc
	echo '<div class="form-row form-row-wide"><label>Card Number <span class="required">*</span></label>
		<input id="misha_ccNo" type="text" autocomplete="off">
		</div>
		<div class="form-row form-row-first">
			<label>Expiry Date <span class="required">*</span></label>
			<input id="misha_expdate" type="text" autocomplete="off" placeholder="MM / YY">
		</div>
		<div class="form-row form-row-last">
			<label>Card Code (CVC) <span class="required">*</span></label>
			<input id="misha_cvv" type="password" autocomplete="off" placeholder="CVC">
		</div>
		<div class="clear"></div>';
 
	do_action( 'woocommerce_credit_card_form_end', $this->id );
 
	echo '<div class="clear"></div></fieldset>';
 
}

第5步:處理付款

5.1 驗證字段

我知道諸如名字、姓氏之類的結帳字段應該進行驗證,但這僅是示例:

public function validate_fields(){
 
	if( empty( $_POST[ 'billing_first_name' ]) ) {
		wc_add_notice(  'First name is required!', 'error' );
		return false;
	}
	return true;
 
}

5.2 使用API??捕獲付款并設置訂單狀態

說明文字有點多哦:

  • 一旦您使用 wc_get_order() 函數獲得了訂單對象,您可以使用它的方法,如get_billing_first_name()get_billing_country()get_billing_address_1()等,以獲得客戶的付款和發貨的細節(順便說一下,你可以 在WooCommerce插件文件夾的includes/class-wc-order.php 找到所有的方法)。您也可以從$_POST數組中獲取賬單詳細信息,在撰寫本教程時,我不確定哪個更好。
  • 您可以使用$order->add_order_note()方法向訂單添加備注,在編輯訂單頁面上可以是給客戶的備注(將顯示在會員區域)私人備注(僅在編輯訂單頁面上)。
  • 在本教程中,我們考慮使用直接付款而不訪問網關網站。但是,如果出于您的目的,客戶必須訪問支付網關網站來完成付款,則您必須跳過第4步,而在此步驟中,您可以使用 wp_remote_post()獲取付款,用add_query_arg()為您的付款網關結帳頁面建立正確的重定向URL。
  • 使用$order->get_total()獲取訂單金額。
  • get_woocommerce_currency() 應該可以幫助您獲取當前的商店貨幣。
  • 如果您的付款網關要求列出訂單中的所有產品,請使用$order->get_items(),您可以在此處找到一些示例。
public function process_payment( $order_id ) {
 
	global $woocommerce;
 
	// 我們需要它來獲取任何訂單詳細信息
	$order = wc_get_order( $order_id );
 
 
	/*
 	 * 具有用于API交互的參數的數組
	 */
	$args = array(
 
		...
 
	);
 
	/*
	 * 可以使用wp_remote_post()構建您的API交互
 	 */
	 $response = wp_remote_post( '{payment processor endpoint}', $args );
 
 
	 if( !is_wp_error( $response ) ) {
 
		 $body = json_decode( $response['body'], true );
 
		 // 根據您的付款處理器的不同,這里是不同的
		 if ( $body['response']['responseCode'] == 'APPROVED' ) {
 
			// 我們收到了付款
			$order->payment_complete();
			$order->reduce_order_stock();
 
			// 給客戶的一些備注(用false代替true使其變為私有)
			$order->add_order_note( 'Hey, your order is paid! Thank you!', true );
 
			// 空購物車
			$woocommerce->cart->empty_cart();
 
			// 重定向到“感謝頁面” 
			return array(
				'result' => 'success',
				'redirect' => $this->get_return_url( $order )
			);
 
		 } else {
			wc_add_notice(  'Please try again.', 'error' );
			return;
		}
 
	} else {
		wc_add_notice(  'Connection error.', 'error' );
		return;
	}
 
}

5.3 支付網關回調

我們可能需要操作付款網關回調(即時付款通知,Webhooks等)。

假設我們的自定義支付網關沒有自己的信用卡數據表單,并且客戶填寫了帳單詳細信息(如姓名,地址等)后,他將被重定向到支付網關網站。

我們如何檢查付款是否完成并顯示在我們的商店中?

手動嗎?是嗎 ??

許多付款網關都有付款通知,這就是它的工作方式—一旦客戶在付款網關網站上完成了訂單,網關就會向我們在網關的設置頁面上設置的網站的特定網址發送帶有$_GET參數的請求。WooCommerce允許處理這些請求。

WooCommerce 中的webshook URL(回調URL)如下所示: http://rudrastyh.com/wc-api/{webhook name}/ ,鉤子名稱可以任意,例如 paypal-payment-complete或 misha。這絕對不意味著您將在此處使用什么,主要要求是網址中的{webhook name}和過濾器中的{webhook name}步驟3,第34行)必須匹配。

add_action( 'woocommerce_api_{webhook name}', array( $this, 'webhook' ) );

并且webhook()是可以使用接收到的$_GET參數執行任何操作的函數(類方法)。

public function webhook() {
 
	$order = wc_get_order( $_GET['id'] );
	$order->payment_complete();
	$order->reduce_order_stock();
 
	update_option('webhook_debug', $_GET);
}

您不必在末尾添加 exit; 內容,因為一旦其中的代碼被觸發,它就會退出WordPress。

這就是本教程的全部內容。

如果您對 WooCommerce 的使用還不太了解,或者想系統學習 WooCommerce 開發,可以學習教程《WooCommerce 開發指南視頻課程(使用詳解/主題開發/支付寶網關開發)》。

聲明:原文出自 https://rudrastyh.com/woocommerce/payment-gateway-plugin.html ,由WordPress大學翻譯整理,轉載請保留本聲明。

倡萌

一個文科IT宅男,喜歡折騰WordPress和被它折騰 ^_^

暫無評論

發表評論