В конце прошлого года я был очень близок к тому, чтобы подключить на сайте оплату через CloudPayments, уже настроил API, всё закодил красиво, и сейчас хотел бы поделиться опытом с вами, как я это сделал.
Хочу обратить внимание, что в этом уроке нет никаких партнёрских ссылок и это не проплаченный пост. Я бы добавил партнёрские ссылки, но что-то было лень заморачиваться ради этого.
Кстати, если вы не планируете кодить всё сами, пишите нам, мы вам поможем.
Как весь процесс оплаты будет работать в общем?
Погнали!
Ах да, ловите ссылку на официальную документацию.
Преимущество 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>
Самое главное, на что тут важно обратить внимание:
type="passowrd"
.#errors
будем записывать ошибочки.Возможно в предыдущем шаге вы могли заметить скрытое поле 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, если он пока вызывает у вас трудности, то вэлкам на мой видеокурс.
По сути содержимое файла 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' ] ) { // Ура! оплата прошла, делаем то, что нужно }
Несколько моментов:
Это уже содержимое файла 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'; }
И ещё, чтобы вам не пришлось искать тестовые номера карт, вот они.
Чтобы оставить комментарий, пожалуйста, зарегистрируйтесь или войдите.