Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ThinkingMan's avatar

Pass form data to controller for JSON post to external API

I am building an integration to a payment gateway and have some pieces working independently and am now at the point where I need to handover some tokenized data to my controller so it can POST to to the payment gateway and get the response. So the flow is:

  • User goes to payment form, enters card info (Functional)
  • View calls tokenizer and returns tokenized value with JavaScript (Functional)
  • Form calls POST method to payment controller (Functional)
  • Need to package the form data to submit (Need help)

So I know I am handing over the request to the controller because I have tested with dump(request ()->all());

How do I hand the array to my JSON? Here is the controller with hard coded data that I have tested successfully with the Gateway using guzzle.

public function store()
    {

        $client = new Client();
        $url = "https://fts.cardconnect.com:6443/cardconnect/rest/auth";
        $response = $client->put($url,[
            'headers' => ['Content-type' => 'application/json'],
            'auth' => [
                'testing',
                'testing123'
            ],
            'json' => ['merchid' => '999990873888',
                'account' => '9424209629051443',
                'expiry' => '1020',
                'cvv2' => '123',
                'amount' => '25.97',
                'curreny' => 'USD',
                'orderid' => '1001',
                'name' => 'First Name',
                'address' => '123 Test Street',
                'region' => 'MD',
                'country' => 'US',
                'postal' => '21212',
                'capture' => 'y',
                'invoiceid' => 'TEST-API'],
        ]);

        echo $response->getBody();
    }

So it is the JSON array with the card detail that needs to have the form variables passed in. I was starting to try to use $request as New Request and build out the values but I am not calling local data, just the form Request.

(NOTE - This is just the basic, assumed to be successful code. Will add more response and error handling later. Hence the echo at the end.)

Thanks in advance!

0 likes
15 replies
jlrdw's avatar

Any credit card information is done on the payment Gateway, not your system, you really need to fix that first.

Then the payment Gateway will have API instructions to follow.

ThinkingMan's avatar

I understand. I am just trying to hand the data to the gateway from my form controller so I can get the approval/decline response. My specific question has to do with how to get my form data array and pass those variables to my JSON payload. So this question could apply to anything, not just a credit card post. I just wanted to male sure the flow was there for context.

Thanks

jlrdw's avatar

But the Gateway would not be asking for such data.

What Gateway are you using that would ask for such data I'm curious I'd like to look them up and do more research.

If you're just practicing API stuff maybe you could practice with the simpler fields. Just a thought.

PayPal has practice accounts

https://developer.paypal.com/docs/classic/payflow/test-hosted-pages/

Other gateways should be very similar.

ThinkingMan's avatar

How would a gateway not expect to get basic data like card number and amount?

ThinkingMan's avatar

And again, I am able to post to the API via guzzle with the values you see in my example. So posting and getting the reaponse isn't the problem. The specific issue I am facing has to do with how to hand the array of form data to a controller that I can then embed in my JSON payload. This really is more of a generic Laravel framework question. I guess I should have never mentioned credit cards...

fylzero's avatar

Yes, you can use Guzzle for this... are you sure you don't need an API key or Bearer token in your headers? I also typically set to accept json... Guzzle already knows to send the array as JSON data.

$client = new Client();
$headers = [
    'Accept' => 'application/json',
    'Content-Type' => 'application/json',
    'API-Key' => env('API_KEY')
];
$response = $client->request('POST', $url,
    [
        'headers' => $this->headers,
        'json' => $data
    ]
);
1 like
fylzero's avatar

@thinkingman Payment gateways would not be asking for this information because services like Stripe, etc. use client-side payfield APIs. The whole purpose is that backend systems, not only do not store, but do not touch credit card data.

They create a card token, which you store... then you exchange for payment tokens, which allow you to make charges. Yes, you should not be passing card data this way.

1 like
ThinkingMan's avatar

I really didn't mean for this to become a discussion about payment gateways. If anyone is interested in the API details for this gateway then they are available here. https://cardconnect.com/developers. Stripe is great and I have used it before. However, there is a business reason to use CardConnect CardPointe. Not sure how much folks know about downgrades but card not present transactions drive higher processing rates. So the more information that gets passed to the gateway that authenticates the card holder then the lower the rate. Stripe is 2.9% which is high when compared to card present situations.

Anyway, to recap... I am able to post the detail to the CardPointe API but prior to posting the detail it gets tokenized. So I never pass a card number in the clear. Now, where I am stuck is getting the form data over to the controller.

So here is the form:

extends('layouts.app')

@section('content')

    <script language="JavaScript">

        function showMe() {
            alert($("#tokenframe").contents().find("#ccnumfield"));
            var mytoken = document.getElementById('mytoken');
            alert("Token=" + mytoken.value);
        }

        window.addEventListener('message', function(event) {
            document.getElementById('mytoken').value = JSON.parse(event.data);

            var token = JSON.parse(event.data);

            alert('Received message ' + token.message);
            var mytoken = document.getElementById('mytoken');
            mytoken.value = token.message;
        }, false);

    </script>

    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <div class="card">
                    <div class="card-header">Make Payment</div>

                    <div class="card-body">

                        <form method="post" action="{{ route('payment') }}">
                            <div class="form-group">
                                @csrf
                                <label for="name">Cardholder:</label>
                                <input type="text" class="form-control" name="name"/>
                            </div>
                            <div class="form-group">
                                <label for="address">Address:</label>
                                <input type="text" class="form-control" name="address"/>
                            </div>
                            <div class="form-group">
                                <label for="account">Card Number:</label>
                                <iframe id="tokenframe" name="tokenframe" src="https://fts.cardconnect.com:6443/itoke/ajax-tokenizer.html?css=%2Eerror{color:%20red;}" frameborder="0" scrolling="no" width="200" height="30"></iframe>
                                <input type="hidden" name="mytoken" id="mytoken">
                            </div>
                            <button type="submit" class="btn btn-primary" onClick="javascript:showMe();">Make Payment</button>
                        </form>
                    </div>
                    </div>
                </div>
            </div>
        </div>
    </div>


    </body>
@endsection

And then the route

Route::post('/payment', 'PaymentController@store')->name('payment');

And then again the controller


use Illuminate\Http\Request;
use GuzzleHttp\Client;

class PaymentController extends Controller
{
    public function index()
    {
    }


    public function store()
    {
        //dump(request()->all());
        //$request_data = $this->mapData();

        $client = new Client();
        $url = "https://fts.cardconnect.com:6443/cardconnect/rest/auth";
        $response = $client->put($url,[
            'headers' => ['Content-type' => 'application/json'],
            'auth' => [
                'testing',
                'testing123'
            ],
            'json' => ['merchid' => '466660873888',
                'account' => '9999909629051443',
                'expiry' => '1020',
                'cvv2' => '123',
                'amount' => '25.97',
                'curreny' => 'USD',
                'orderid' => '1001',
                'name' => 'First Name',
                'address' => '123 Test Street',
                'region' => 'MD',
                'country' => 'US',
                'postal' => '21212',
                'capture' => 'y',
                'invoiceid' => 'TEST-API'],
        ]);

        echo $response->getBody();
    }

    private function mapData()
    {
        $data = array (
         //Can I get this from the form?
        return $data;
    }


}
fylzero's avatar

Your actual question is "How do I hand the array to my JSON?"

Either you mean on the put, which isn't necessary, as Guzzle converts your PHP array to JSON on the way out. This is already handled.

Or you mean, actually return the JSON response.

Try this...

Instead of...

echo $response->getBody();

Use this...

$data_array = json_decode($response->getBody(), true);
$data_json = json_encode($data_array);
return $data_json;

I know it's wonky and I think there is a more elegant answer, but that should do what you want. You're basically getting an object back, using decode with true makes it an associative array, which can be encoded to JSON. I always forget PHP objects are a thing, but that's what I think you're dealing with in the response.

Also, if you find this helpful... this is how I handle my catch blocks for Guzzle...

catch (ClientException $e) {
    $response = ($e->hasResponse()) ? $e->getResponse() : 'No response provided';
    $statuscode = $response->getStatusCode();
    $body = $response->getBody();

    Log::error($body);

    return [
        'success' => false,
        'status_code' => $statuscode,
        'body' => $body ?? null,
    ];
}

You may also want to check out this if you just want the data from the response.

$response->getBody()->getContents();
1 like
jlrdw's avatar

What also confuses me about the question is: if you are using a payment Gateway, their API would have specific instructions on exactly how to handle this.

For example if Guzzle was needed there would be an example of how they expect you to use Guzzle.

So really I am not sure what you are doing, but just saying it doesn't sound like an authorized payment Gateway, just an observation.

Edit: honest not trying to argue just saying I've never seen one of these apis not have instructions to follow.

fylzero's avatar
fylzero
Best Answer
Level 67

I had to re-read your question like 10 times... are you just trying to figure out how to pass the request data to Guzzle???

Bruh...

public function store(Request $request)
    {
        //dump(request()->all());
        //$request_data = $this->mapData();

        $client = new Client();
        $url = "https://fts.cardconnect.com:6443/cardconnect/rest/auth";
        $response = $client->put($url,[
            'headers' => ['Content-type' => 'application/json'],
            'auth' => [
                'testing',
                'testing123'
            ],
            'json' => [
                'merchid' => $request->merchid,
                'account' => $request->account,
                'expiry' => $request->expiry,
                'cvv2' => $request->cvv2,
                'amount' => $request->amount,
                'curreny' => $request->curreny,
                'orderid' => $request->orderid,
                'name' => $request->name,
                'address' => $request->address,
                'region' => $request->region,
                'country' => $request->country,
                'postal' => $request->postal,
                'capture' => $request->capture,
                'invoiceid' => $request->invoiceid
            ],
        ]);

        echo $response->getBody();
    }

Just swap the request-> with what ever your keys are.

Make sure to pass the Request $request into the store function.

...and pull in request at the top of your file...

use Illuminate\Http\Request;
1 like
ThinkingMan's avatar

Yes, and I was just testing some things out. Here is where I landed but will probably go your route. Sorry, wasn't trying to be obtuse! Thank you!!!

public function store(Request $request)
    {

        $data_array = $request->toArray();


        try{
        $client = new Client();
        $url = "https://fts.cardconnect.com:6443/cardconnect/rest/auth";
        $response = $client->put($url,[
            'headers' => ['Content-type' => 'application/json'],
            'auth' => [
                'testing',
                'testing123'
            ],
            'json' => $data_array,
        ]);}catch (RequestException $e) {
            $response = ($e->hasResponse()) ? $e->getResponse() : 'No response provided';
            $statuscode = $response->getStatusCode();
            $body = $response->getBody();

            Log::error($body);

            return [
                'success' => false,
                'status_code' => $statuscode,
                'body' => $body ?? null,
            ];
        }




        return view("paysuccess",compact('paysuccess'));

    }
fylzero's avatar

@thinkingman You're fine... I just think you had a very simple question buried under a veil of Guzzle and Payment API that threw me off. Definitely break your questions down more to the core issue if you can next time. Glad you got it situated.

2 likes
ThinkingMan's avatar

The CardConnect gateway was a request by the person I am working with. They resell payment services hence the need to use that gateway. It is owned by FirstData who is very big in the payment space so it is legit. Just not as pervasive as say Stripe.

1 like

Please or to participate in this conversation.