Подключение оплаты через CloudPayments API

Владислав Белецкий
Владислав Белецкий .
Категория:
Комментариев: 0

В конце прошлого года я был очень близок к тому, чтобы подключить на сайте оплату через CloudPayments, уже настроил API, всё закодил красиво, и сейчас хотел бы поделиться опытом с вами, как я это сделал.

Хочу обратить внимание, что в этом уроке нет никаких партнёрских ссылок и это не проплаченный пост. Я бы добавил партнёрские ссылки, но что-то было лень заморачиваться ради этого.

Как весь процесс оплаты будет работать в общем?

Погнали!

Ах да, ловите ссылку на официальную документацию.

1. Форма оплаты на сайте

Преимущество CloudPayments перед например Робокассой в том, что форма ввода данных карты находится непосредственно на вашем сайте и вы можете закастомить её, как пожелаете.

<div id="errors"></div>
<form id="cp-form" action="checkout.php" method="POST">
	<input type="text" id="first_name" name="first_name" placeholder="Имя" />
	<input type="email" id="email" name="email" placeholder="Email" />
	<input type="text" id="ccNo" placeholder="Номер карты" />
	<input type="number" id="expMonth" placeholder="Месяц" />
	<input type="number" id="expYear" placeholder="Год" />
	<input type="password" id="cvv" placeholder="CVV" />
	<input name="token" type="hidden" value="" />
</form>

Самое главное, на что тут важно обратить внимание:

2. Создание токена при отправке формы

Возможно в предыдущем шаге вы могли заметить скрытое поле token с пустым значением. В него мы преобразуем данные карты при помощи скрипта от CloudPayments. Для начала нужно этот скрипт подключить на сайт.

Так как мы говорим на этом блоге в основном о WordPress, то и скрипт будем подключать через хук wp_enqueue_scripts.

add_action( 'wp_enqueue_scripts', function() {
	wp_enqueue_script( 'cp', 'https://checkout.cloudpayments.ru/checkout.js' );
} );

После этого напишем скрипт обработки формы:

// инициализируем Cloud Payments
const checkout = new cp.Checkout({
	publicId: 'ПУБЛИЧНЫЙ API КЛЮЧ',
});
 
// обрабатываем отправку формы
const paymentForm = document.getElementById( 'cp-form' );
paymentForm.addEventListener( 'submit', ( event ) => {
 
	// предотвращаем стандартную отправку
	event.preventDefault();
 
	const form = event.target;
	const errContainer = document.getElementById( 'errors' );
 
	// очищаем старые ошибки, если они есть
	errContainer.style.display = 'none';
	errContainer.innerHTML = '';
 
	// получаем данные карты
	const fieldValues = {
	  cvv: form.querySelector( '#cvv' ).value,
	  cardNumber: form.querySelector( '#ccNo' ).value,
	  expDateMonth: form.querySelector( '#expMonth' ).value,
	  expDateYear: form.querySelector( '#expYear' ).value,
	}
 
	// создаём токен (или по-научному платёжную криптограмму!)
	checkout.createPaymentCryptogram(fieldValues)
		.then((cryptogram) => {
 
			//console.log(cryptogram); // чисто почекать, что всё ок
 
			form.token.value = cryptogram; // записываем в скрытое поле
			form.submit(); // сабмитим форму ручками
 
		}).catch((errors) => {
 
			// стандартное сообщение об ошибке
			let errMessage = 'Что-то пошло не так...';
 
			// каждая ошибка является свойством объекта
			// так что вы можете все их обработать по разному
			// errors.cardNumber, errors.cvv, errors.expDateMonth
			// например
			if(  'CardNumber_Empty' == errors.cardNumber ) {
				errMessage = 'Не могли бы вы указать номер карты?';
			}
 
			errContainer.innerHTML = errMessage;
			errContainer.style.display = 'block';
 
		});
 
} );

Как видите, в примере я решил не использовать jQuery и написал обработку на чистом JavaScript, если он пока вызывает у вас трудности, то вэлкам на мой видеокурс.

3. Обработка формы

По сути содержимое файла checkout.php (или смотря куда вы ссылкаетесь с формы в шаге 1).

// не забываем подключить среду WordPress
require_once( __DIR__ . '/wp-load.php' );
 
$publicID = 'ПУБЛИЧНЫЙ API КЛЮЧ';
$apiKey = 'СЕКРЕТНЫЙ API КЛЮЧ';
 
// вообще бы рекомендовал создать что-то типо заказа на сайте в этом моменте
// $order_id = wp_insert_post( ....
// update_post_meta( $order_id, 'ord_payer_email', ... 
 
// обрабатываем оплату
$response = wp_remote_post(
	//'https://api.cloudpayments.ru/test',
	'https://api.cloudpayments.ru/payments/cards/charge',
	array(
		'method' => 'POST',
		'timeout' => 45,
		'headers' => array(
			'Accept' => 'application/json',
			'Content-Type' => 'application/json',
		 	'Authorization' => 'Basic ' . base64_encode( "$publicID:$apiKey" ),
		),
		'body' => json_encode(
			array(
				'Amount' => $amount,
				'Currency' => 'USD',
				'InvoiceId' => $order_id,
				'IpAddress' =>  $ip,
				'CardCryptogramPacket' => $_POST[ 'token' ],
				'CultureName' => 'en-US',
				'Payer' => array(
					'FirstName' => $_POST[ 'first_name' ]
				)
			)
		)
	)
);
 
// добавляем проверки, что запрос не улетел в ошибку
if( is_wp_error( $response ) || 'OK' !== wp_remote_retrieve_response_message( $response ) ) {
	// обрабатываем ошибку
}
 
// не ошибка? продолжаем
$body = json_decode( wp_remote_retrieve_body( $response ), true );
 
// это обработка 3-D Secure
if( false == $body[ 'Success' ] ) {
 
	$MD = isset( $body[ 'Model' ][ 'TransactionId' ] ) && $body[ 'Model' ][ 'TransactionId' ] ? $body[ 'Model' ][ 'TransactionId' ] : false;
	$PaReq = isset( $body[ 'Model' ][ 'PaReq' ] ) && $body[ 'Model' ][ 'PaReq' ] ? $body[ 'Model' ][ 'PaReq' ] : false;
	$AcsUrl = isset( $body[ 'Model' ][ 'AcsUrl' ] ) && $body[ 'Model' ][ 'AcsUrl' ] ? $body[ 'Model' ][ 'AcsUrl' ] : false;
 
	if( $AcsUrl && $PaReq ) {
 
		// формируем HTML форму прямо тут! и редиректим!
		echo '<p>Редиректим...</p><form id="process3d" action="' . esc_url( $AcsUrl ) . '" method="POST">
			<input type="hidden" name="MD" value="' . absint( $MD ) . '">
			<input type="hidden" name="PaReq" value="' . esc_attr( $PaReq ) . '">
			<input type="hidden" name="TermUrl" value="http://урл-на-вашем-сайте/3ds.php">
			</form>
			<script type="text/javascript">
			    document.getElementById( 'process3d' ).submit();
			</script>';
		exit;
	}
 
	// всё ещё тут? значит какая-то ошибка и тут вам надо её обработать
 
}
 
// всё ещё тут? продолжаем!
if( true == $body[ 'Success' ] ) { 
	// Ура! оплата прошла, делаем то, что нужно
}

Несколько моментов:

Обработка 3-D Secure

Это уже содержимое файла 3ds.php.

$publicID = 'ПУБЛИЧНЫЙ API КЛЮЧ';
$apiKey = 'СЕКРЕТНЫЙ API КЛЮЧ';
 
// обрабатываем платёж после ввода кода потрвеждения
$response = wp_remote_post(
	'https://api.cloudpayments.ru/payments/cards/post3ds',
	array(
		'method' => 'POST',
		'timeout' => 45,
		'headers' => array(
			'Accept' => 'application/json',
			'Content-Type' => 'application/json',
		 	'Authorization' => 'Basic ' . base64_encode( "$publicID:$apiKey" ),
		),
		'body' => json_encode(
			array(
				'TransactionId' => $_POST[ 'MD' ],
				'PaRes' => $_POST[ 'PaRes' ]
			)
		)
	)
);
 
// добавляем проверки, что запрос не улетел в ошибку
if( is_wp_error( $response ) || 'OK' !== wp_remote_retrieve_response_message( $response ) ) {
	// обрабатываем ошибку
}
 
$body = json_decode( wp_remote_retrieve_body( $response ), true );
 
if( true == $body[ 'Success' ] ) {
	// Ура! всё круто
} else {
	// Не круто...
 
	// Код ошибки можно кстати вытащить так:
	$ReasonCode = isset( $body[ 'Model' ][ 'ReasonCode' ] ) && $body[ 'Model' ][ 'ReasonCode' ] ? absint( $body[ 'Model' ][ 'ReasonCode' ] ) : 'declined';
}

И ещё, чтобы вам не пришлось искать тестовые номера карт, вот они.

Подписаться
Уведомить о
guest
0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии