<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ライセンスキー &#8211; WordPress Memo</title>
	<atom:link href="https://blog.riverforest-wp.info/tag/%E3%83%A9%E3%82%A4%E3%82%BB%E3%83%B3%E3%82%B9%E3%82%AD%E3%83%BC/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.riverforest-wp.info</link>
	<description>WordPress に関する覚え書き</description>
	<lastBuildDate>Fri, 09 May 2025 12:48:52 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://blog.riverforest-wp.info/wp-content/uploads/2018/05/cropped-icon-256x256-1-32x32.png</url>
	<title>ライセンスキー &#8211; WordPress Memo</title>
	<link>https://blog.riverforest-wp.info</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>WooCommerce でライセンスキーを発行するプラグイン及びそれを Web サービスで利用するためのコード</title>
		<link>https://blog.riverforest-wp.info/simple-license-key-for-woocommerce/</link>
		
		<dc:creator><![CDATA[Katsushi Kawamori]]></dc:creator>
		<pubDate>Thu, 23 Sep 2021 01:48:46 +0000</pubDate>
				<category><![CDATA[Plugin]]></category>
		<category><![CDATA[Webサービス]]></category>
		<category><![CDATA[ライセンスキー]]></category>
		<guid isPermaLink="false">https://blog.riverforest-wp.info/?p=2872</guid>

					<description><![CDATA[題名が長くなりましたが、以下のプラグインを自分のサービスで利用するために開発しました。 プラグイン自体は可能な限りシンプルにしていて、以下の機能に絞っています。 購入されたライセンスキーを暗号化して Rest API で [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>題名が長くなりましたが、以下のプラグインを自分のサービスで利用するために開発しました。</p>



<div class="pluginstatsview-card-wrap">
	<div>
		<img decoding="async" src="https://ps.w.org/simple-license-key-for-woocommerce/assets/icon-256x256.png?rev=2603932" alt="Simple License Key for WooCommerce のアイコン" class="pluginstatsview-card-icon" />
		<div class="pluginstatsview-after-icon">
			<div class="pluginstatsview-bold"><a href="https://wordpress.org/plugins/simple-license-key-for-woocommerce/" class="pluginstatsview-astyle">Simple License Key for WooCommerce</a></div>
			<div class="pluginstatsview-small">ウェブサービス用の WooCommerce 商品のライセンスキーを生成します。</div>
			<div class="pluginstatsview-small">作者: <a href="https://profiles.wordpress.org/katsushi-kawamori/">Katsushi Kawamori</a></div>
			<div style="clear: both;"></div>
		</div>
	</div>
	<div style="clear: both;"></div>

	<div class="pluginstatsview-small">
		<span class="pluginstatsview-card-left"><a href="https://wordpress.org/plugins/simple-license-key-for-woocommerce/#reviews" title="0.0(5点満点中)" class="pluginstatsview-astyle">	<span class="pluginstatsview-stars">
					<span class="dashicons dashicons-star-empty"></span><span class="dashicons dashicons-star-empty"></span><span class="dashicons dashicons-star-empty"></span><span class="dashicons dashicons-star-empty"></span><span class="dashicons dashicons-star-empty"></span>
			</span>
	</a>(0)</span>
		<span class="pluginstatsview-card-right">最終更新: 2日 前</span>
	</div>
	<div class="pluginstatsview-small">
		<span class="pluginstatsview-card-left">3,292ダウンロード</span>
		<span class="pluginstatsview-card-right">検証済み: 7.0</span>
	</div>
	<div class="pluginstatsview-small">
		<span class="pluginstatsview-card-left">ダウンロード: <a href="https://downloads.wordpress.org/plugin/simple-license-key-for-woocommerce.1.18.zip" class="dashicons dashicons-download pluginstatsview-download"></a></span>
		<span class="pluginstatsview-card-right">リリース: 2021-09-23</span>
	</div>
	<div class="pluginstatsview-small pluginstatsview-card-center">
		2026-03-31 09:30 時点の統計	</div>
</div>



<p>プラグイン自体は可能な限りシンプルにしていて、以下の機能に絞っています。</p>



<ul class="wp-block-list"><li>購入されたライセンスキーを暗号化して Rest API で出力</li><li>商品にライセンスキーを付与するかのチェック</li><li>ライセンスキーの有効期日の指定</li></ul>



<p>後は、購入したユーザーが、Web サービス上でメールで届いたライセンスキーを入力すると、それを復号化して検証するという仕組みです。それについては、Web サービス上でコードを書く必要があります。暗号化は、OpenSSL の共通パスフレーズを用いています。コードに関しては、WordPress の管理画面上での PHP と、React で以下に記していきますが、Rest API と、OpenSSL を利用しているので、他の言語やシステムでも別のコードを書けば使えると思います。その辺りに詳しい方は、チャレンジしてみてください。</p>



<h3 class="wp-block-heading">動作</h3>



<figure class="wp-block-video"><video height="720" style="aspect-ratio: 1280 / 720;" width="1280" controls src="https://blog.riverforest-wp.info/wp-content/uploads/20210923/slmwoo.mp4"></video></figure>



<h3 class="wp-block-heading">ライセンスキー販売サイトの商品の設定</h3>



<p>ライセンスキーを発行にチェックし、有効期限を決めます。有効期限を過ぎると、REST API への暗号化されたライセンスキーの出力は無くなります。商品は、バーチャルにチェックを入れます。</p>



<h3 class="wp-block-heading">ライセンスキー販売サイトのプラグイン側の設定</h3>



<p>共通パスフレーズを決めます。これは流出しないように大切に保管してください。また、プラグインの設定画面上で、REST API の URL を知る事ができます。この２点は、後で PHP と React 上に書き込みます。</p>



<h3 class="wp-block-heading">Web サービス側の PHP コード</h3>



<p>子テーマの、functions.php に書く前提で記していきます。</p>



<p>ライセンスキーを入力するためのメニューページを作成するコード</p>



<ul class="wp-block-list"><li>管理画面に、Test License というページを作成</li><li>ページには、React を利用するので、id 属性を指定して、echo するのみ</li></ul>



<pre class="prism line-numbers"><code class="language-php language-html">/** ==================================================
 * Add Menu for Test license
 *
 * @since 1.00
 */
function add_pages() {
	add_menu_page(
		'Test License',
		'Test License',
		'edit_posts',
		'TestLicense',
		'credit_page'
	);
}
add_action( 'admin_menu', 'add_pages' );

/** ==================================================
 * Credit
 *
 * @since 1.00
 */
function credit_page() {

	echo '&lt;div id="test-license-page"&gt;&lt;/div&gt;';

}</code></pre>



<p>メニューページに読み込むスクリプト用のコード</p>



<ul class="wp-block-list"><li>子テーマ内に、test-license というフォルダを作成し、その下の dist フォルダ内に、React の build ファイルを置くためのコード</li></ul>



<pre class="prism line-numbers"><code class="language-php language-html">/** ==================================================
 * License Page Scripts
 *
 * @param string $hook_suffix  hook_suffix.
 * @since 1.00
 */
function license_page_scripts( $hook_suffix ) {

	if ( 'toplevel_page_TestLicense' !== $hook_suffix ) {
		return;
	}

	$asset_file = include( get_stylesheet_directory() . '/test-license/dist/test-license.asset.php' );

	wp_enqueue_style(
		'test-license-style',
		get_stylesheet_directory_uri() . '/test-license/dist/test-license.css',
		array( 'wp-components' ),
		'1.0.0'
	);

	wp_enqueue_script(
		'test-license',
		get_stylesheet_directory_uri() . '/test-license/dist/test-license.js',
		$asset_file&#91;'dependencies'],
		$asset_file&#91;'version'],
		true
	);

}
add_action( 'admin_enqueue_scripts', 'license_page_scripts', 10, 1 );</code></pre>



<p>REST API を出力し、入力されたライセンスキーを検証するコード</p>



<ul class="wp-block-list"><li>権限は以下の場合は編集者権限</li><li>license_api_verify 内の検証コード内に、復号化のための共通パスフレーズを記す</li><li>検証して、入力されたライセンスキーと、プラグインの入っているライセンスキー販売サイトの REST API を復号化したものが一致していれば、ユーザーオプションテーブルの test_licensed を true にする</li></ul>



<pre class="prism line-numbers"><code class="language-php language-html">/** ==================================================
 * Register Rest API
 *
 * @since 1.00
 */
function register_rest() {

	register_rest_route(
		'test/license_api',
		'/token',
		array(
			'methods' =&gt; 'POST',
			'callback' =&gt; 'license_api_verify',
			'permission_callback' =&gt; 'editor_rest_permission',
		)
	);

}
add_action( 'rest_api_init', 'register_rest' );

/** ==================================================
 * Rest Permission for editor
 *
 * @since 1.00
 */
function editor_rest_permission() {

	return current_user_can( 'edit_posts' );

}

/** ==================================================
 * License Rest API verify
 *
 * @param object $request  changed data.
 * @since 1.00
 */
function license_api_verify( $request ) {

	$args = json_decode( $request-&gt;get_body(), true );

	$input_license_key = $args&#91;'license_key'];
	$get_license_api_arr = $args&#91;'license_api'];
	foreach ( $get_license_api_arr as $key =&gt; $value ) {
		/* 共通パスフレーズは、プラグイン側で指定したもの。以下の場合は、'm#xs@%5NhZlR' */
		$get_license_key = openssl_decrypt( $value&#91;'open_key'], 'aes-256-cfb', 'm#xs@%5NhZlR', 0, openssl_cipher_iv_length( 'aes-256-cfb' ) );
		if ( $get_license_key === $input_license_key ) {
			/* ライセンスが一致した時の処理 */
			update_user_option( get_current_user_id(), 'test_licensed', true );
		}
	}
	$args&#91;'licensed'] = get_user_option( 'test_licensed', get_current_user_id() );

	return new WP_REST_Response( $args, 200 );

}</code></pre>



<h3 class="wp-block-heading"> Web サービス側の React コード </h3>



<p>LicenseCheck コンポーネント</p>



<ul class="wp-block-list"><li>Fetch で販売サイトの REST API を取得</li><li>apiFetch で Web サービス側で、ライセンスキーを入力したものと、Fetch で取得した暗号化されたライセンスキーを php 側と通信</li></ul>



<pre class="prism line-numbers"><code class="language-php language-html">import './license-check.css';

import apiFetch from '@wordpress/api-fetch';

import { Button, TextControl } from '@wordpress/components';

import {
	useState,
	useEffect
} from '@wordpress/element';

const LicenseCheck = ( props ) =&gt; {

	const &#91; paidFlag, updatePaidFlag ] = useState( false );
	const &#91; paidText, updatePaidText ] = useState( '' );

	const &#91; currentLicense, updateCurrentLicense ] = useState( '' );
	const &#91; licenseApi, updateLicenseApi ] = useState( {} );

	const items_licensed = &#91;];
	if ( ! paidFlag ) {
		items_licensed.push(
			&lt;div&gt;
				&lt;hr /&gt;
				&lt;h3&gt;{ props.license_text }&lt;/h3&gt;
				&lt;p className="description"&gt;{ props.purchase_description }&lt;/p&gt;
				&lt;div&gt;
					&lt;Button
						className="button button-large"
						href={ props.purchase_site }
						target="_blank"
					&gt;
					{ props.purchase_text }
					&lt;/Button&gt;
				&lt;/div&gt;
				&lt;div className="license_key_input_line"&gt;
					{ props.license_text_input }
					&lt;TextControl
						className = "license_key_input"
						value = { currentLicense }
						onChange = { ( value ) =&gt; updateCurrentLicense( value ) }
					/&gt;
				&lt;/div&gt;
			&lt;/div&gt;
		);
	}

	useEffect( () =&gt; {

		fetch( props.url )
		.then( response =&gt; response.json() )
		.then( data =&gt; {
			//console.log( data );
			updateLicenseApi( data );
		} );

		apiFetch( {
			path: props.path,
			method: 'POST',
			data: {
				license_key: currentLicense,
				license_api: licenseApi,
			}
		} ).then( ( response ) =&gt; {
			//console.log( response );
			if ( response&#91;'licensed'] ) {
				updatePaidFlag( true );
				updatePaidText( props.paid_text );
			} else {
				updatePaidFlag( false );
				updatePaidText( props.no_paid_text );
			}
		} );

	}, &#91; currentLicense ] );

	return (
		&lt;div className="wrap"&gt;
			&lt;h2&gt;{ props.title }&lt;/h2&gt;
			&lt;h3&gt;{ paidText }&lt;/h3&gt;
			{ items_licensed }
		&lt;/div&gt;
	);

};

export default LicenseCheck;</code></pre>



<p>コンポーネント用の CSS</p>



<pre class="prism line-numbers"><code class="language-php language-html">.license_key_input {
	width: 200px;
}
.license_key_input_line {
	display: inline-flex;
}</code></pre>



<p>メインのコード</p>



<ul class="wp-block-list"><li>コンポーネントを読み込む。コンポーネントの属性に各種値を入力。</li><li>属性<ul><li>title : タイトル</li><li>license_text : タイトル２</li><li>purchase_description : 購入の説明</li><li>purchase_text : 購入ボタンの文字</li><li>purchase_site : ライセンスキー商品販売ページの URL</li><li>license_text_input : ライセンスキー入力フォームの左側のテキスト</li><li>paid_text : ライセンスされている事を示すテキスト</li><li>no_paid_text : ライセンスされていない事を示すテキスト</li><li>url : ライセンス販売サイトの REST API の URL（プラグインの設定画面に記してあるもの）</li><li>path : Web サービス側の REST API のパス（PHP に記したパス）</li></ul></li></ul>



<pre class="prism line-numbers"><code class="language-php language-html">import './test-license.scss';

import { render } from '@wordpress/element';

import LicenseCheck from './components/license-check';

const TestLicenseView = () =&gt; {

	return (
		&lt;div className="wrap"&gt;
			&lt;LicenseCheck
				title = { 'ライセンスチェックテスト' }
				license_text = { 'ライセンスキー' }
				purchase_description = { '以下のショップで購入したライセンスキーを入力すると制限が解除されます。' }
				purchase_site = 'https://shop-jp.riverforest.test/product/license'
				purchase_text = { '購入' }
				license_text_input = { 'ライセンスキー入力' }
				paid_text = { 'ライセンス済み' }
				no_paid_text = { '未ライセンス' }
				/* REST API by Simple License Key for WooCommerce */
				url = 'https://shop-jp.riverforest.test/wp-json/rf/slk-woo-open-key_api/token'
				/* Web service REST API */
				path = 'test/license_api/token'
			/&gt;
		&lt;/div&gt;
	);

};

render(
	&lt;TestLicenseView /&gt;,
	document.getElementById( 'test-license-page' )
);</code></pre>



<p>メインの CSS</p>



<pre class="prism line-numbers"><code class="language-php language-html">#test-license-page {
}</code></pre>



<h3 class="wp-block-heading">ダウンロード</h3>



<p>コードを子テーマ毎一式以下に置きました。</p>



<div class="wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex">
<div class="wp-block-button"><a class="wp-block-button__link" href="https://blog.riverforest-wp.info/wp-content/uploads/20210923/twentytwentyone_child.zip">ダウンロード</a></div>
</div>
]]></content:encoded>
					
		
		<enclosure url="https://blog.riverforest-wp.info/wp-content/uploads/20210923/slmwoo.mp4" length="24326105" type="video/mp4" />

			</item>
	</channel>
</rss>
