[PHP]Paypal APIで月額課金を止める方法と不正利用されない方法

スポンサーリンク

Paypal APIの日本語の情報、少なすぎませんか?
調べてもほとんど出て来ません。 

今開発しているシステムでどうしても使わないといけないので、悪戦苦闘しています。

今回紹介するのはPayPalの定期支払いを止めるロジックです。
定期的な課金のプログラムは調べたら日本語でもあるのですが、その逆はありませんでした。

課金のプログラムはこちらが非常にわかりやすいです。Crowyにはお世話になっています。

PayPal APIの使い方 その4 ~ 定期支払いの実装 – hrendohの日記
GetRecurringPaymentsProfileDetails …

paypal
paypal / iliveisl

定期支払いを止めるロジック

定期支払いを止める、会員登録の場合は退会する場合に必要になります。課金を止めないと会員情報は削除できてるのに、なぜか課金し続けている・・・という詐欺になりかねません。

なんとかしないといけない!ということで、いろいろ調べて解決できました。

参考になったのが、このサイト。このサイトのコードをそのまま利用すれば、動きます。

Cancelling Subscriptions Created with PayPal Standard via the Express Checkout API | i blog
‘Cancel’ …

/**
 * Performs an Express Checkout NVP API operation as passed in $action.
 *
 * Although the PayPal Standard API provides no facility for cancelling a subscription, the PayPal
 * Express Checkout  NVP API can be used.
 */
function change_subscription_status( $profile_id, $action ) {

	$api_request = 'USER=' . urlencode( 'api_username' )
				.  '&PWD=' . urlencode( 'api_password' )
				.  '&SIGNATURE=' . urlencode( 'api_signature' )
				.  '&VERSION=76.0'
				.  '&METHOD=ManageRecurringPaymentsProfileStatus'
				.  '&PROFILEID=' . urlencode( $profile_id )
				.  '&ACTION=' . urlencode( $action )
				.  '&NOTE=' . urlencode( 'Profile cancelled at store' );

	$ch = curl_init();
	curl_setopt( $ch, CURLOPT_URL, 'https://api-3t.sandbox.paypal.com/nvp' ); // For live transactions, change to 'https://api-3t.paypal.com/nvp'
	curl_setopt( $ch, CURLOPT_VERBOSE, 1 );

	// Uncomment these to turn off server and peer verification
	// curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, FALSE );
	// curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, FALSE );
	curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
	curl_setopt( $ch, CURLOPT_POST, 1 );

	// Set the API parameters for this transaction
	curl_setopt( $ch, CURLOPT_POSTFIELDS, $api_request );

	// Request response from PayPal
	$response = curl_exec( $ch );

	// If no response was received from PayPal there is no point parsing the response
	if( ! $response )
		die( 'Calling PayPal to change_subscription_status failed: ' . curl_error( $ch ) . '(' . curl_errno( $ch ) . ')' );

	curl_close( $ch );

	// An associative array is more usable than a parameter string
	parse_str( $response, $parsed_response );

	return $parsed_response;
}

source by http://thereforei.am/2012/07/03/cancelling-subscriptions-created-with-paypal-standard-via-the-express-checkout-api/

ManageRecurringPaymentsProfileStatusというメソッドを呼び出しています。

ただし、api_username・api_password・api_signatureは各々の値に変換しましょう。

引数に$profile_idが必要になります。これは一番最初に紹介した課金のロジックを動かした時に取得できるので、データベースなどに保存しておきましょう。そうすれば、いつでも呼び出せます。

もう一つの引数に$actionがあります。これは’Cancel’,’Suspend’,’Reactivate’のいずれかを設定します。それぞれの意味はこちら。

Cancel: 有効または一時停止状態の設定のみをキャンセル
Suspend: 有効状態の設定のみを一時停止
Reactivate: 一時停止状態の設定のみを利用再開

手動で課金を止められる可能性もある

まずはこちらをご覧ください。

Paypalの月額課金を解除する方法 | ihayato.news

そうです、Paypalの課金を自分で止めることができてしまいます。いくらプログラムで頑張ってもこれをされると何故かお金が増えてないぞ!?と運営側は困った自体になります。

困ったものだと思いましたが、これも解決できます。

ユーザーの課金ステータスを取得できる

Paypal APIではユーザーの課金ステータスをいつでも取得できます。

ということで、ログイン時とかにこの課金ステータスを取得しましょう。異常があれば何らかのメッセージを出すようにしてあげれば、あらゆるケースに対応可能になります。

このロジックはサンプルが見つからなかったので、上記のコードを少し編集して作りました。あらかじめ言っておきますが、全てのロジックを理解していません。

function check_status( $profile_id ) {

	$api_request = 'USER=' . urlencode( 'api_username' )
				.  '&PWD=' . urlencode( 'api_password' )
				.  '&SIGNATURE=' . urlencode( 'api_signature' )
				.  '&VERSION=76.0'
				.  '&METHOD=GetRecurringPaymentsProfileDetails'
				.  '&PROFILEID=' . urlencode( $profile_id );

	$ch = curl_init();
	curl_setopt( $ch, CURLOPT_URL, 'https://api-3t.sandbox.paypal.com/nvp' ); // For live transactions, change to 'https://api-3t.paypal.com/nvp'
	curl_setopt( $ch, CURLOPT_VERBOSE, 1 );

	// Uncomment these to turn off server and peer verification
	// curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, FALSE );
	// curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, FALSE );
	curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
	curl_setopt( $ch, CURLOPT_POST, 1 );

	// Set the API parameters for this transaction
	curl_setopt( $ch, CURLOPT_POSTFIELDS, $api_request );

	// Request response from PayPal
	$response = curl_exec( $ch );

	// If no response was received from PayPal there is no point parsing the response
	if( ! $response )
		die( 'Calling PayPal to change_subscription_status failed: ' . curl_error( $ch ) . '(' . curl_errno( $ch ) . ')' );

	curl_close( $ch );

	// An associative array is more usable than a parameter string
	parse_str( $response, $parsed_response );

	return $parsed_response;
}

GetRecurringPaymentsProfileDetailsというメソッドを呼び出しています。

引数は$profile_idだけなので、データベースなどから取得し、設定しましょう。

戻り値は配列になります。定期支払いのステータスは配列名’STATUS’で取得できますので、以下の様な感じで取得してください。

		//定期支払いステータス取得
		$array = check_status(プロフィールID);
		echo $array["STATUS"];

取得できたステータスとユーザー情報を照合して、チェックに使えば、不正利用も防げます。

私自身、今回の開発の上で最も懸念してたPaypalとの連携もこれでうまくいきそうです。