Trevor Prime
Trevor Prime

Reputation: 21

Can't save credit card using Square's Cards API - Error: Invalid Source-id

I am trying to allow users to create monthly subscriptions via my website.

To achieve the above, I've followed Square's suggested flow:

  1. Use Payments SDK to collect users card information client side and generate a token and source_id for the credit card in question. This worked successfully.

1.5 Create a customer and obtain a customer_id. success!

  1. Use source_id from step 1 to create a payment and obtain a payment_id. This was successfully.

  2. Use payment_id returned from step 2 to save the card on file. This calls results in in an error:

This is the request sent in step 2:

public function createPayment($request) {

    $response = Http::withHeaders(
        [
            'Authorization' => "Bearer " . $this->config['square']['access_token'],
            'Content-Type' => 'application/json',
            'Square-Version' => "2022-01-20",
        ]
    )->post($this->config['square']['paymentsEndpoint'], [

        "idempotency_key" => $request['source_id'],
        "amount_money" => [
            "amount" => $request['amount'],
            "currency" => "USD",
        ],
        "source_id" => $request['source_id'],
        "autocomplete" => true,
        "location_id" => $this->config['square']['locationId'],
        "reference_id" => "creator-id-" . $request['id'],

    ]);
    $created = json_decode($response);

    if (isset($created->payment->id)) {

        return $created->payment->id;
    }
}

The above returns:

{#1522
  +"payment": {#1485
    +"id": "xmhTZnkyo9oZ9PH0eKdVfWwfvSJZY"
    +"created_at": "2022-02-11T14:20:08.746Z"
    +"updated_at": "2022-02-11T14:20:08.982Z"
    +"amount_money": {#1513
      +"amount": 100
      +"currency": "USD"
    }
    +"status": "COMPLETED"
    +"delay_duration": "PT168H"
    +"source_type": "CARD"
    +"card_details": {#1483
      +"status": "CAPTURED"
      +"card": {#1529
        +"card_brand": "VISA"
        +"last_4": "1111"
        +"exp_month": 11
        +"exp_year": 2023
        +"fingerprint": "sq-1-up5lr5N9rhqnx9-2Ho9ZGmb-6_ldGkuEsjOhgzaJ5Xhuv7Qqv0wCBhms-hMLTh-y0Q"
        +"card_type": "CREDIT"
        +"prepaid_type": "NOT_PREPAID"
        +"bin": "411111"
      }
      +"entry_method": "KEYED"
      +"cvv_status": "CVV_ACCEPTED"
      +"avs_status": "AVS_ACCEPTED"
      +"statement_description": "SQ *DEFAULT TEST ACCOUNT"
      +"card_payment_timeline": {#1528
        +"authorized_at": "2022-02-11T14:20:08.856Z"
        +"captured_at": "2022-02-11T14:20:08.982Z"
      }
    }
    +"location_id": "LABQBPRYSFTE8"
    +"order_id": "StJEDwNo1Q7eXeF0l8vD9Iaeac4F"
    +"reference_id": "creator-id-1"
    +"risk_evaluation": {#1527
      +"created_at": "2022-02-11T14:20:08.856Z"
      +"risk_level": "NORMAL"
    }
    +"total_money": {#1526
      +"amount": 100
      +"currency": "USD"
    }
    +"approved_money": {#1525
      +"amount": 100
      +"currency": "USD"
    }
    +"receipt_number": "xmhT"
    +"receipt_url": "https://squareupsandbox.com/receipt/preview/xmhTZnkyo9oZ9PH0eKdVfWwfvSJZY"
    +"delay_action": "CANCEL"
    +"delayed_until": "2022-02-18T14:20:08.746Z"
    +"application_details": {#1524
      +"square_product": "ECOMMERCE_API"
      +"application_id": "sandbox-sq0idb-FrLggaZMvpJBc2UDN3zKlg"
    }
    +"version_token": "mzLRfLZlX4n0M6DyXqkDeWqDx4nKy9zZM4Mz2UBlr9v6o"
  }
}

Then this code calls the Cards endpoint to create a card:

public function createCard($request) {

    $id = auth()->user()->id;
    $user = User::find($id);
    $subscription = Subscription::where('user_id', '=', $id)->get();

    $response = Http::withHeaders(
        [
            'Authorization' => "Bearer " . $this->config['square']['access_token'],
            'Content-Type' => 'application/json',
            'Square-Version' => "2022-01-20",
        ]
    )->post($this->config['square']['cardsEndpoint'], [

        "idempotency_key" => $request['source_id'],
        "source_id" => $request['source_id'],
        "card" => [
            "billing_address" => [
                "address_line_1" => $subscription[0]['address_line_1'],
                "address_line_2" => $subscription[0]['address_line_2'] ?? "",
                "locality" => $subscription[0]['admin_area_2'],
                "administrative_district_level_1" => $subscription[0]['admin_area_1'],
                "postal_code" => $subscription[0]['postal_code'],
                "country" => $subscription[0]['country_code'],
            ],
            "cardholder_name" => $request['fullname'],
            "customer_id" => $request['customer_id'],
            "reference_id" => "creator-id-" . $request['id'],
        ],
    ]);

    return json_decode($response);

}

This call returns:

{"errors":[{"category":"INVALID_REQUEST_ERROR","code":"INVALID_CARD_DATA","detail":"Invalid card data.","field":"source_id"}]}

I tried running this in both sandbox and production environment and receive the same results.

The card data used on the client side is as follows:

Alternatively, in regards to the card number, I have follow the following recommendation from the Subscription API and got the same result:

Call CreateCard to add a card on file using the payment token ("cnon:card-nonce-ok") that Square provides for Sandbox testing.

Can someone please help me figure this out?

Upvotes: 2

Views: 1469

Answers (1)

Nauman Ilyas
Nauman Ilyas

Reputation: 47

I was facing the same issue and seem like the billing_address causing issue while binding with card. It work If I remove the billing_address and keep it simple :)

Square PHP SDK

    $card = new \Square\Models\Card();
    $card->setCustomerId($customer_id);
    $body = new \Square\Models\CreateCardRequest(
        uniqid(), // perfer version 5
        $request->payment_token,
        $card
    );
    return  $this->client->getCardsApi()->createCard($body);

You can also try it via API.

Endpoint:https://connect.squareupsandbox.com/v2/cards

{
"idempotency_key": "62d683de53df21",
"source_id": "cnon:XYZ...", //one time payment use payment token
 "card": {
  "customer_id": "123213...",
}

Upvotes: 1

Related Questions