Bahij.Mik
Bahij.Mik

Reputation: 1484

Flutter - stripe payment with laravel api

So basically what i am trying to do is to let customers add credit cards for later use, what i did on flutter is:

StripePayment.setOptions(StripeOptions(
        publishableKey: "MY_KEY_HERE"));

and added a button:

onPressed: () async {
                    dynamic value =
                        await StripePayment.paymentRequestWithCardForm(
                      CardFormPaymentRequest(),
                    ).catchError(setError).then(
                      (PaymentMethod paymentMethod) async {
                        try {
                          addCreditCard(paymentMethod);    // post request to laravel cashier api with the payment method
                          print("Payment Method ID: ${paymentMethod.id}");
                        } catch (e) {
                          print(e);
                        }
                      },
                    );
                  },

So what i did here is, the user is able to press a button, an input form pops up that includes all required card details with the stripe verification algorithm, and once everything is entered i will get a PaymentMethod object returned(which contains a token and last 4digits etc..) after that i sent this PaymentMethod object to laravel cashier api which contains this function:


public function create_card(Request $request)
    {
        $user = $request->user();
        $user->addPaymentMethod($request->method); //Laravel billable cashier function
        return response()->json([
            'message' => 'Successfully updated credit card'
        ], 201);
    }

I get a response of No such payment method, i am not sure how to continue from here since i can't find any documentation for this.. Any help would be great.

Laravel's cashier billable addPaymentMethod function:

public function addPaymentMethod($paymentMethod)
    {
        $this->assertCustomerExists();

        $stripePaymentMethod = $this->resolveStripePaymentMethod($paymentMethod);

        if ($stripePaymentMethod->customer !== $this->stripe_id) {
            $stripePaymentMethod = $stripePaymentMethod->attach(
                ['customer' => $this->stripe_id], $this->stripeOptions()
            );
        }

        return new PaymentMethod($this, $stripePaymentMethod);
    }

Upvotes: 0

Views: 2162

Answers (2)

Last Templar
Last Templar

Reputation: 336

For anyone still struggling with this issue, I finally found a working solution for adding a payment method.

My setup is this:

Laravel Framework 8.37.0
    "laravel/cashier": "^12.12",
    "laravel/sanctum": "^2.9",

Flutter (Channel stable, 2.0.5)
    Dart 2.12.3
    stripe_payment: ^1.0.11

Flutter side:

sample_view.dart is the screen that holds a button that calls the Stripe method:

import 'package:my_sample_package/services/payment_services.dart';
import 'package:flutter/material.dart';
import 'package:stripe_payment/stripe_payment.dart';


class Subscribe extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: ElevatedButton(
            child: Text("Add new Payment Method"),
            onPressed: () {
              StripeService.addNewPayment();
            },
          )
        )
      ),
    );
  }
}

payment_services.dart is the file that handles the Stripe and Api calls:

import 'dart:convert';
import 'dart:developer';
import 'package:dio/dio.dart';
import 'package:flutter/services.dart';
import 'package:stripe_payment/stripe_payment.dart';

class StripeService {
  Dio dio = new Dio();
  static Future<dynamic> addNewPayment() async {
    StripePayment.setOptions(
      StripeOptions(
        publishableKey: "your_stripe_publishable_key",
        merchantId: "Test",
        androidPayMode: 'test'
      )
    );

    Dio dio = new Dio(); // I'm using Dio instead of the http package
    String baseUrl = 'http://192.168.1.122:8000/api/'; // Your host, I started mine using ## php artisan serve --host 192.168.1.122 --port 8000 ##
    String token = 'my_laravel_access_token'; // This is the token I get from Laravel Sanctum

    await StripePayment.paymentRequestWithCardForm(
      CardFormPaymentRequest(), // This will show the Native Payment Card form 
    )
    .then(
      (PaymentMethod paymentMethod) async {
        try {
          inspect(paymentMethod);
          final response = await dio.post(
            baseUrl + "user/subscription/payment-method/update", // My Laravel endpoint for updating the payment method
            options: Options(
              headers: { 'Authorization': 'Bearer $token' },
            ),
            data: {
              "payment_method": paymentMethod
            }
          );
          inspect(response);
        } catch (e) {
          inspect(e);
        }
      },
    ).onError((error, stackTrace) {
      inspect(error);
    });
  }
}

Laravel Side:

routes/api.php file to register the route we need:

...
Route::group(['prefix' => 'user', 'middleware' => ['auth:sanctum']], function () {
    Route::post('subscription/payment-method/update', [UserController::class, 'updatePaymentMethod']);
});
...

Controllers/UserController.php file to register our method:

public function updatePaymentMethod(Request $request): \Illuminate\Http\JsonResponse
    {
        $user = auth()->user();
        $user->updateDefaultPaymentMethod($request->payment_method['id']); // You need to pass just the payment method ID, not the whole object

        return response()->json([
            'message' => 'Payment method saved'
        ], 200);
    }

Upvotes: 0

oussama fahd
oussama fahd

Reputation: 85

Try removing "async" and print the paymentMethod to check if you're getting a payment method id or not:

StripePayment
.paymentRequestWithCardForm(CardFormPaymentRequest())
.then((paymentMethod) {
print(paymentMethod);
}).catchError((error)=>{print(error)});

Upvotes: 0

Related Questions