Skip to main content

Flutter SDK - Merchant's Checkout

  1. Open your app’s pubspec.yaml file and add the dependencies as following.

    chaipay_flutter_package:
    path: "Path of the Flutter Package"
    url_launcher: ^6.0.18
    receive_sharing_intent: ^1.4.5
  2. Create an instance of PortOneImpl() to access the methods of PortOne Package with the appropriate environment.

    /*
    PortOne is providing two types of environment
    1. For Production:- "live"
    2. For testing:- "sandbox"
    */
    final environment = "sandbox";
    late PortOneImpl portone = PortOneImpl(context, $environment);
  3. Add the following Intent Filter to the Launcher Activity of your app which will be in your manifest file. In the data tag there are two parameters host and scheme whose values will be set according the redirection url.

    redirectionUrl= **portone://checkout**
    then the host will be **checkout** and the scheme will be **portone**
    <data
    android:host="checkout"
    android:scheme="portone" />
    <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data
    android:host="$host"
    android:scheme="$scheme" />
    </intent-filter>
  4. In the root stateful widgets implement two override method name initState() and dispose() then add the following code to receive Intent from other apps.

    // Create the following variables
    late StreamSubscription _intentData;
    String? paymentStatus;
    @override
    void initState() {
    super.initState();
    _intentData = ReceiveSharingIntent.getTextStream().listen((String value) {
    setState(() {
    paymentStatus = value;
    });
    });
    }
    @override
    void dispose() {
    _intentData.cancel();
    super.dispose();
    }
    • Add Listener to listen the payment status by callback to initState()
    portone.setPaymentStatusListener(
    callback: (Map<String, dynamic> paymentStatus) {
    print('PortOne_PaymentStatus-> $paymentStatus');
    });
  1. Generate SignatureHash and JWT token.

    • Add the following packages to the pubspec.yaml. crypto: ^3.0.1 jaguar_jwt: ^3.0.0

    Signature Hash Generation:

    String getSignatureHash(String amount, String currency, String failureUrl,
    String orderId, String clientKey, String successUrl) {
    Map<String, String> params = {
    "amount": amount,
    "client_key": clientKey,
    "currency": currency,
    "failure_url": failureUrl,
    "merchant_order_id": orderId,
    "success_url": successUrl
    };
    params.forEach((key, value) {
    var encodedValue = Uri.encodeComponent(value);
    if (message.isNotEmpty) {
    message = message + "&$key=$encodedValue";
    } else {
    message = message + "$key=$encodedValue";
    }
    });
    final keyBytes = const Utf8Encoder().convert(SECRET_KEY_Dev3);
    final dataBytes = const Utf8Encoder().convert(message);
    final hmacBytes = Hmac(sha256, keyBytes).convert(dataBytes).bytes;
    final hmacBase64 = base64Encode(hmacBytes);
    return hmacBase64;
    }

    Payment Request | PortOne

    JWT Token Generation:

    String getJWTToken() {
    final claimSet = JwtClaim(
    issuedAt: DateTime.now(),
    expiry: DateTime.now().add(const Duration(seconds: 100)),
    issuer: "CHAIPAY",
    subject: CLIENT_KEY,
    otherClaims: <String, dynamic>{
    "typ": "JWT",
    "alg": "HS256",
    });
    String token = issueJwtHS256(claimSet, SECRET_KEY);
    return token;
    }

    Authentication | PortOne

  1. Create an instance of WebCheckoutRequest() , add the required order details in the instance and call a method named checkoutUsingWeb and pass the params.

    //To get Available Payment Methods
    portone.getPaymentMethods("$clientKey");
    portone.setPaymentMethodsListener(callback: (PaymentMethodResponse response) {
    print('PortOne_Response-> $response');
    });
    //To get the Otp
    portone.getOTP(requests.mobileNo);
    portone.setOtpListener(callback: (GetOtpResponse response) {
    print('PortOne_Response-> $response');
    });
    //To get the saved crads
    portone.getSavedCards("$token", "$clientKey", "$phoneNo", "$otp");
    portone.setSavedCardsListener(callback: (CreditCardDetailsResponse response) {
    print('PortOne_Response-> $response');
    });
    //To Initiate Checkout Using Wallet
    WithoutTokenizationRequest request = WithoutTokenizationRequest();
    portone.checkoutWithoutTokenization("$request");
    portone.setCheckoutWithoutTokenizationListener(
    callback: (WithoutTokenizationResponse response) {
    print('PortOne_Response-> $response');
    });
    //To Initiate Checkout Using Credit Card
    WithTokenizationRequest request = WithTokenizationRequest();
    portone.checkoutWithTokenization("$request");
    portone.setCheckoutWithTokenizationListener(callback: (WithTokenizationResponse response) {
    print('PortOne_Response-> $response');
    });
    //To Initiate Checkout Using New Credit Card
    WithTokenizationRequest request = WithTokenizationRequest();
    ChanexTokenRequest cardDetails = ChanexTokenRequest();
    portone.checkoutUsingNewCard("$request","$cardDetails");
    portone.setCheckoutWithoutTokenizationListener(
    callback: (WithoutTokenizationResponse response) {
    print('PortOne_Response-> $response');
    }); /* This is the same listener as above to receive the response. */
  2. Things to be taken care while generating payload:

    1. Mandatory params in payload:

      price
      promo_discount (0 is also acceptable)
      shipping_charges (0 is also acceptable)
    2. If items are provided then please verify the values provided should match the total amount: sum(items price * items quantity) + shipping charge - discount = amount