sanmai/gmopg

View on GitHub
src/GMO/ImmediatePayment.php

Summary

Maintainability
A
2 hrs
Test Coverage
<?php
/**
 * This code is licensed under the MIT License.
 *
 * Copyright (c) 2015-2017 Alexey Kopytko
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

namespace GMO;

use GMO\API\Call\AlterTran;
use GMO\API\Call\EntryTran;
use GMO\API\Call\ExecTran;
use GMO\API\Call\Magic;
use GMO\API\Errors;
use GMO\API\MethodsSandbox;
use GMO\API\Response\AlterTranResponse;
use GMO\API\Response\EntryTranResponse;
use GMO\API\Response\ErrorResponse;
use GMO\API\Response\ExecTranResponse;

class ImmediatePayment
{
    /**
     * Unique ID for the payment.
     *
     * @var int
     */
    public $paymentId;

    /**
     * Payment amount (Japanese yen only).
     *
     * @var int
     */
    public $amount;

    /**
     * Card number to be credited from.
     *
     * For testing use 4111111111111111
     *
     * @var string
     */
    public $cardNumber;

    /**
     * Card's expiration year (four digits, e.g. 2038).
     *
     * @var string
     */
    public $cardYear;

    /**
     * Card's expiration month (from 1 to 12, not zero-padded).
     *
     * @var string
     */
    public $cardMonth;

    /**
     * CVV code.
     *
     * @var string
     */
    public $cardCode;

    /**
     * Payment token.
     *
     * @var string
     */
    public $token;

    private $errorShortCode;
    private $errorCode;

    /** @var EntryTran */
    private $entryTran;

    /** @var EntryTranResponse */
    private $entryTranResponse;

    /** @var ExecTran */
    private $execTran;

    /** @var ExecTranResponse */
    private $execTranResponse;

    /** @var AlterTran */
    private $alterTran;

    /** @var AlterTranResponse */
    private $alterTranResponse;

    // Test details
    public $testShopId;
    public $testShopPassword;
    public $testShopName;

    /**
     * Proceeds with a payment. Can be done just once for a single payment ID.
     *
     * @return bool if a valid response received
     */
    public function execute()
    {
        $this->checkRequiredVars([
            'paymentId',
            'amount',
        ]);

        if (isset($this->token)) {
            $this->checkRequiredVars(['token']);
        } else {
            $this->checkRequiredVars([
                'cardNumber',
                'cardYear',
                'cardMonth',
                'cardCode',
            ]);
        }

        // Setup transaction details (password etc)
        $this->entryTran = new EntryTran();

        if ($this->testShopId) {
            // Use sandbox methods if requested
            $this->entryTran->setMethods(new MethodsSandbox());
            $this->entryTran->setShop($this->testShopId, $this->testShopPassword, $this->testShopName);
        }

        $this->entryTran->OrderID = $this->paymentId;
        $this->entryTran->Amount = $this->amount;
        $this->entryTranResponse = $this->entryTran->dispatch();

        if (!$this->verifyResponse($this->entryTranResponse)) {
            return false;
        }

        $this->execTran = new ExecTran();
        // configure this request using earlier request's data
        $this->entryTran->setupOther($this->execTran);
        // payment ID must be the same as before
        $this->execTran->OrderID = $this->paymentId;
        // copy the access keys for the transaction
        $this->execTran->setAccessID($this->entryTranResponse);

        if (!isset($this->token)) {
            // setup card number and such
            $this->execTran->setCardNumber($this->cardNumber);
            $this->execTran->setCardExpiryYearMonth($this->cardYear, $this->cardMonth);
            $this->execTran->setCardSecurityCode($this->cardCode);
        } else {
            $this->execTran->setToken($this->token);
        }

        $this->execTranResponse = $this->execTran->dispatch();

        if (!$this->verifyResponse($this->execTranResponse)) {
            // @codeCoverageIgnoreStart
            return false; // this should never happen under normal circumstances
            // @codeCoverageIgnoreEnd
        }

        // verify the checksum
        if (!$this->execTran->verifyResponse($this->execTranResponse)) {
            // @codeCoverageIgnoreStart
            return false; // this should never happen under normal circumstances
            // @codeCoverageIgnoreEnd
        }

        $this->alterTran = new AlterTran();
        // configure this request using earlier request's data
        $this->entryTran->setupOther($this->alterTran);
        // copy the access keys
        $this->alterTran->setAccessID($this->entryTranResponse);
        // confirm the payment amount
        $this->alterTran->setActualSaleAmount($this->amount);

        $this->alterTranResponse = $this->alterTran->dispatch();

        // this should never return false under normal circumstances
        return $this->verifyResponse($this->alterTranResponse);
    }

    /**
     * Returns payment details. These should be stored in the database for the future use.
     *
     * @return \GMO\API\Response\ExecTranResponse
     */
    public function getResponse()
    {
        return $this->execTranResponse;
    }

    /**
     * Array of error codes.
     *
     * @return array
     */
    public function getErrorCode()
    {
        return $this->errorCode;
    }

    /**
     * Returns an array of maching error codes and descriptions.
     */
    public function getErrors()
    {
        $result = [];
        foreach ($this->errorCode as $code) {
            $result[$code] = Errors::getDescription($code);
        }

        return $result;
    }

    public function setupOther(Magic $method)
    {
        return $this->entryTran->setupOther($method);
    }

    private function verifyResponse($response)
    {
        if ($response instanceof ErrorResponse) {
            $this->errorShortCode = $response->ErrCode;
            $this->errorCode = $response->ErrInfo;

            return false;
        }

        return true;
    }

    private function checkRequiredVars($vars)
    {
        foreach ($vars as $requiredVar) {
            if (empty($this->{$requiredVar})) {
                throw new Exception("Missing $requiredVar");
            }
        }
    }
}