サブスクリプション決済を無料でやりたい③



決済が成功すると会員が「有効」に変わる!

決済が成功すると会員の有効期限が表示(更新)され「無効」の場合は「有効」に変わる。


リンク決済「リンク」用のカスタムフィールドを追加

Squareリンク決済「リンク」が作成出来たら次に「リンク」で実際に決済出来るようにメンバーシップを拡張する。


①ACFでリンク決済用の下記のフィールドを追加する


プランの説明(テキストエリア)やリンク先(URL)、リンク名(リッチエディター)のフィールドを追加
※各リンク決済「リンク」毎にリンク先とリンク名は追加する。




②カスタムフィールドにリンクなどを入力


メンバーシップの編集ページで追加したカスタムフィールドにリンク決済でコピーした「リンク」とそのリンク名を入力する



リンク決済用に固定ページを追加する

リンク決済には「会員プラン・課金」「決済完了」の2つの固定ページが必要である。
①「会員プラン・課金」にはメンバーシップの情報を表示及びリンク決済「リンク」を実装
②「決済完了」はリンク決済が終了した時に飛ぶ「Square リンク決済」で指定するリダイレクト先になる

外部サイト経由で会員システムと連携させるには

リンク決済は非常にお手軽で素晴らしいなのだが、今回のように会員システムと連携させるには工夫が必要だ。
リンク決済は外部サイトに飛ぶので、通常のページ遷移だと会員システムの連携に必要な情報が渡せない受け取れない。

そこで今回は「iframe」に外部サイトが表示されるようにする。
親ページと「iframe」間で会員情報を橋渡しさせる。
またUI/UXを考慮しモーダルウィンドウを使う。
※リダイレクト先は必ず同一サイトを指定する。


下記は全て「会員プラン・課金」ページ

モーダル内Square外部サイト

モーダル内リダイレクトの同一サイト


3Dセキュア(VISA)

3Dセキュア(Mastercard)

「会員プラン・課金」ページ


PHPコード

メンバーシップの情報を表示及びリンク決済「リンク」を実装するコードを固定ページに追加する。

//page-plans.php
$current_user = wp_get_current_user();
$user_id = $current_user->ID;
$modify = "+30 day";
$membership = "gold";
$admin_url = admin_url() . 'admin-ajax.php';

if ( $user_id ) {
	//memberships
	$html = "";
	$membershipsArr = array();
	foreach ( wpmem_get_memberships() as $key => $value ) {
		$has_access = wpmem_user_has_access( $key, $user_id );
		$desc = isset($value["desc"]) ? $value["desc"] : '';
		$square_link1 = isset($value["square_link1"]) ? $value["square_link1"] : '';
		$square_text1 = isset($value["square_text1"]) ? $value["square_text1"] : '';
		$square_class1 = isset($value["square_class1"]) ? ' '.$value["square_class1"] : '';
		$square_link2 = isset($value["square_link2"]) ? $value["square_link2"] : '';
		$square_text2 = isset($value["square_text2"]) ? $value["square_text2"] : '';
		$square_class2 = isset($value["square_class2"]) ? ' '.$value["square_class2"] : '';
		$square_link3 = isset($value["square_link3"]) ? $value["square_link3"] : '';
		$square_text3 = isset($value["square_text3"]) ? $value["square_text3"] : '';
		$square_class3 = isset($value["square_class3"]) ? ' '.$value["square_class3"] : '';
		$membershipsArr[$key] = array($value["title"], $has_access, $desc, $value["name"], $square_link1, $square_text1, $square_class1, $square_link2, $square_text2, $square_class2, $square_link3, $square_text3, $square_class3);
	}

	if ( !empty($membershipsArr) ){
		$html .= '<ul class="memberships_plan">';
		$cou = 1;
		foreach ( $membershipsArr as $k => $v ) {
			$prod_timestamp_meta = get_user_meta( $user_id, "_wpmem_products_".$v[3], true);
			$prod_timestamp = '';
			if ( !empty( $prod_timestamp_meta && $prod_timestamp_meta != 1 ) ) {
				$dt = new DateTime();
				$dt->setTimestamp($prod_timestamp_meta);
				$prod_date =  $dt->format('Y-m-d H:i:s');
				$prod_timestamp = '有効期限:' .$prod_date;
			}
			$has_access = $v[1] ? '有効' : '無効';
			$class = $v[1] ? ' class="has"' : ' class="invalid"';
			$html .= '<li' . $class . '><div><h3 class="pageH3">' . $v[0] . '</h3><p class="has_access">' . $has_access . '</p></div>';
			$html .= '<p class="desc">' . $v[2] . '</p>';
			$html .= '<p class="timestamp">' . $prod_timestamp . '</p>';

			if ( !empty($v[4]) ){//$square_link1
				$html .= '<a href="#modal" class="modal-btn js-modal' . $v[6] . '" data-src="' . $v[4] .'">' . $v[5] .'</a>';
			}
			if ( !empty($v[7]) ){//$square_link2
				$html .= '<a href="#modal" class="modal-btn js-modal' . $v[9] . '" data-src="' . $v[7] .'">' . $v[8] .'</a>';
			}
			if ( !empty($v[10]) ){//$square_link3
				$html .= '<a href="#modal" class="modal-btn js-modal' . $v[12] . '" data-src="' . $v[10] .'">' . $v[11] .'</a>';
			}
			$html .= '</li>';
		}
		$html .= '</ul>';
	}
	echo $html;
	//modal_html
	$modal_html = '<div id="modal" class="modal-content">
<iframe id="squareframe" src="" width="100%" height="1400px" scrolling="no" frameborder="0" data-uid="' . $user_id .'" data-modify="' . $modify .'" data-membership="' . $membership .'" data-admin_url="' . $admin_url .'"></iframe>
</div>';
	echo $modal_html;

JSコード


	// 親ウィンドウの名前
	window.parentWindowName = 'window_parent_plans';

	//plans
	if ($('.js-modal')[0]) {
		$(".js-modal").modaal({
			//start_open: true, // ページロード時に表示する
		});
	}

	if ($('.modal-btn.js-modal')[0]) {
		$('.modal-btn.js-modal').on('click', function () {
			var src = $(this).data('src');
			$("iframe#squareframe").attr('src', src);
		});
	}

「決済完了」ページ


必要なコード

JSのやり取りで下記のHTMLコードが必要なので追加する

//page-square_thanks.php
<p id="result"></p>

<p class="modal-close_center"><button class="modal-btn js-modal-close">モーダルを閉じる</button></p>

JSコード


	function ajax_update_membership_exp(uid, modify, membership, admin_url) {
		var fd = new FormData();
		fd.append('action', 'update_membership_expiration');
		fd.append('uid', uid);
		fd.append('modify', modify);
		fd.append('membership', membership);
		$.ajax({
			url: admin_url,
			type: 'POST',
			data: fd,
			processData: false,
			contentType: false,
			success: function(response) {
				var result = JSON.parse(response);
				if(result.show_button){
					$('#ajax-result').text('Form submitted successfully!').addClass("show");
					$('h3.pageH3').text('Square決済が終了しました!');
				}
			}, error: function(xhr, status, error) {
				console.error(xhr);
				$('#ajax-result').text('Error submitting form. Please try again.').addClass("show");
			}
		});
	}

	var isset = function(data){
		if(data === "" || data === null || data === undefined){
			return false;
		}else{
			return true;
		}
	};

	$(window).on('load', function() {
		if(window.parent && window != window.parent){
			const parentName = window.parent.parentWindowName;
			console.log(parentName);
			if(parentName == 'window_parent_plans'){
				const uid = $("iframe#squareframe", window.parent.document).data('uid');
				const admin_url = $("iframe#squareframe", window.parent.document).data('admin_url');
				const modify = $("iframe#squareframe", window.parent.document).data('modify');
				const membership = $("iframe#squareframe", window.parent.document).data('membership');
				if( isset(uid) && isset(admin_url) && isset(modify) && isset(membership) ){
					ajax_update_membership_exp(uid, modify, membership, admin_url);
				}else{
					$("#result").text('Error3!');
				}
			}else{
				$("#result").text('Error2!');
			}
		} else {
			$("#result").text('Error1!');
		}
	});
	$('.js-modal-close').on('click', function () {
		if(window != window.parent){
			window.parent.location.reload();
		}
	});

【リンク決済のデメリット(というか願望)】

名前やメールアドレス、クレジットカード情報などを自動入力したい!!

Squareに限らずだが、リンク決済は外部サイトを経由すると会員情報を渡したり受け取ったりが難しい。
外部サイトなので無理もないが必要な会員情報を決済フォームに渡したい。

あらかじめ会員情報として入力された名前やメールアドレス、クレジットカード情報のことである。
外部サイトへ会員情報のData渡しは「iframe」で一部実装しているが
本来はフォームの見える項目に名前やメールアドレス、クレジットカード情報を自動入力し
見せない項目(input[hidden])に会員IDなどを自動入力したい。
自動入力の実装はAPIを使うしかないか。。


決済情報をリダイレクト先ページで受けとりたい!

上記と同様であるが、必要な会員や決済情報をリダイレクト先ページで受けとりたい。
リダイレクト先で会員情報などのData受けが出来ると良いのだが。。
但しこの機能は必須ではない。