**Integrate with Flutter SDK**
The PortOne Flutter SDK offers merchants a seamless way to integrate the PortOne Payment Gateway into their Flutter applications, enabling them to accept payments securely and efficiently. This SDK serves as a bridge between a merchant's app and the PortOne Payment Gateway, providing a comprehensive set of tools and features tailored specifically for handling payment transactions.
The PortOne Flutter SDK empowers merchants to unlock the full potential of their Flutter applications by seamlessly integrating a reliable and secure payment gateway, enhancing user experience, and driving business growth through efficient payment processing capabilities
Sample App#
Check the sample app to integrate on GitHub
Prerequisites#
- **Create an account on PortOne:** Before proceeding with the integration, ensure you have created an account on PortOne to access their services and functionalities.
- Enable Payment Channels and Methods: Customize and enable the specific payment channels and methods that align with your business requirements and preferences.
- **Access API Keys** Login to the portone portal where you can access the API Keys (portone key and secret key) for integrations under Settings -> API tab.
Integration#
Steps to integrate your Flutter application with PortOne Flutter SDK.
- Configure the Flutter SDK with the Flutter App
- Initialise the PortOneInstance
- Set the Intent Filters in the manifests
- Add a listener to listen the payment status
- Setup to Obtain JWT Token from the Server:
1. Configure the Flutter SDK with the Flutter App#
- Retrieve the Flutter package distributed by the PortOne team and ensure it is placed at the same directory level as your Flutter application within the folder structure.
- To integrate the necessary dependencies in your Flutter project, you can update the - pubspec.yamlfile with the following configuration:- Parameters - Description - portone_flutter_package - This is the package where the portone flutter sdk lies and it also has one param name path which requires the path of the sdk. - In above code the given path is dummy please put the path where your portone sdk lies. - | app_links: ^6.1.1 | The app_links package plays a crucial role in your application by enabling the reception of intents from deep links or other applications. Its functionality is essential for capturing payment status updates seamlessly within your Flutter app. | 
2. Initialise the PortOne Instance#
- To facilitate checkout processing within your widget, initialize the PortOneImpl()instance. This instance grants access to the checkout methods necessary for transaction processing.
- Additionally, ensure to provide the environment parameter (SANDBOX or LIVE) for seamless integration and transaction testing.
3. Enable deep links#
- For Android: - Change the project structure to Android from Project OR 
- To add an Intent Filter to the activity in your AndroidManifest.xml file so that users are navigated to a specific activity (default being Checkout Activity) after payment completion - In this setup: - The <intent-filter>block defines the conditions under which the activity should be launched.
- The <data>tag specifies the scheme and host required in the incoming Intent for it to be directed to this activity after payment completion.
- The <activity>tag specifies the activity to which the Intent Filter applies.
 
- The 
 - Update the activity name (e.g., - .CheckoutActivity) as per your actual activity name and place this Intent Filter configuration within the corresponding- <activity>tag in the AndroidManifest.xml file to handle post-payment navigation effectively.- By configuring the scheme as " - portone" and host as "- checkout" within the- <data>tag of the Intent Filter, your Android application will be able to intercept the redirection URL with the format "portone://checkout" and navigate the user to the specified activity (e.g., CheckoutActivity) after payment completion. Adjust the activity name in the configuration according to your actual activity name for proper redirection handling.
- For iOS: - To open your application, add the url schemes to the app, Go to ProjectSettings -> info 
- Add url schemes and identifier inside the URL types. - You can see the scheme and identifier details in info.plist as below: 
- To open the other applications, should include the url schemes in info.plist - LSApplicationQueriesSchemes - Specifies the URL schemes you want the app to be able to use with the canOpenURL: method of the UIApplication class. 
 
4.  Add a listener to listen the payment status by the callback to initState()#
- Receiving Payment Status: - a. Set up app-to-app communication to receive a deep link via intent post-checkout. - b. In the root stateful widget, implement - initState()and- dispose()methods.- c. Declare variables: 
- Initialization in - initState():- a. Initialize - initState()method to handle payment status reception:
- Dispose Method Handling: - a. To cancel the subscription and avoid memory leaks, implement - dispose():
- Adding Payment Status Listener: - a. Implement the following method in the checkout activity to capture checkout status post-completion: 
- Listening to Payment Status on Checkout Activity: - Implement the following method in the checkout activity to receive and handle the checkout status post-completion: - By integrating this method, you can effectively capture and process the payment status updates within the checkout activity using the PortOne SDK in your Flutter application. 
5. Have a setup to get JWT token from the server#
To set up the process of obtaining a JWT token from the server, you need to construct a JWT token that accepts the portoneKey as input. Here's an outline of the steps involved in setting up this process:
- JWT Token Construction: - Implement the server-side logic to generate a JWT token using the - portoneKeyas a key component of the token payload.
- Token Retrieval in Android App: - Implement logic in your Android application to make a server request to retrieve the JWT token using the portoneKey.
- Receive and store the returned token securely within the app for subsequent API authentication.
 
- Implement logic in your Android application to make a server request to retrieve the JWT token using the 
Flutter Connect#
Flutter SDK Variant V2 empowers merchants with advanced business logic functionalities, focusing solely on core processing capabilities without the inclusion of pre-built user interface components. This design choice offers flexibility to merchants, allowing them the freedom to craft and customize their own unique checkout interface tailored to their brand aesthetics and user experience preferences.
The Flutter SDK V2 provides a detailed breakdown of key functionalities essential for merchants to enhance their payment processing capabilities efficiently. Each point represents a specific feature or action that can be easily referenced for seamless integration and utilization within merchant applications.
Overview:#
- Fetch Enabled Payment Methods and Channels
- Checkout Using a New Credit/Debit Card
- Checkout Using Saved Credit/Debit Cards- Retrieve Saved Cards Using Phone Number- Fetch OTP for Authentication
- Fetch Saved Cards Using Phone Number and OTP
 
- Retrieve Saved Cards Using Auth Token
 
- Retrieve Saved Cards Using Phone Number
- Checkout Using Non-Tokenized Methods- Instalments
- Direct Bank Transfer
 
- Merchant Centric Card Vault- Create a Customer
- Save a Card for Customer
- Fetch a List of Cards for a Customer
- Delete Card for a Customer
 
- PreAuth and Capture
- Failover Routing
The subsequent methods are elaborated upon extensively, including their practical applications:
- This method is utilized to retrieve the available payment channels and methods that can be used for the checkout process. - Parameters - Data Type - portoneKey - String - mandatory - subMerchantKey - String - Optional - currency - String - mandatory - For receiving the response, the following listener needs to be added. 
- This method is employed to initiate the checkout process with a new card, allowing for payment from a card that has not been saved previously. - jwtToken#- The - jwtTokenserves as the authentication mechanism in the API, generated following the guidelines outlined in the integration documentation.- ChanexTokenRequest()#- Parameters - Data Type - cardNumber - String - mandatory - cardType - String - mandatory - cardholderName - String - mandatory - serviceCode - String - mandatory - expiryYear - String - mandatory - expiryMonth - String - mandatory - environment - String - mandatory - portoneKey - String - mandatory - WithTokenizationRequest#- Parameters - Data Type - portoneKey - String - mandatory - paymentChannel - String - mandatory - paymentMethod - String - mandatory - merchantOrderId - String - mandatory - amount - Double - mandatory - currency - String - mandatory - billingDetails - CheckoutPaymentDto.BillingDetails - Optional - shippingDetails - CheckoutPaymentDto.ShippingDetails - Optional - orderDetails - List< CheckoutPaymentDto.OrderDetail> - Optional - successUrl - String - mandatory - failureUrl - String - mandatory - environment - String - mandatory - redirectUrl - String - mandatory - description - String - Optional - source - String - mandatory - transactionType - String - mandatory - For receiving the response, the following listener needs to be added. 
- To make a payment using saved cards for the first time, the following method facilitates fetching the cards linked to the phone number. However, to access the cards, OTP authentication is necessary, requiring a two-step process. - Retrieving the saved cards for the initial occurrence.- This method is employed to send an OTP to the registered phone number. - Parameters - Data Type - phoneNo - String - mandatory 
- Upon completing the previous step, an OTP will be sent to the phone number, serving as the input for subsequent authentication. - Parameters - Data Type - token - String - Optional - portoneKey - String - mandatory - phoneNo - String - mandatory - otp - String - mandatory - For receiving the response, the following listener needs to be added. 
 
- Retrieving the saved cards repeatedly.
Following the initial retrieval of saved cards, a token is obtained in the response, offering an alternative method for authentication. This token can be utilised in place of the OTP, providing convenience for subsequent card retrievals.
 
- Retrieving the saved cards for the initial occurrence.
- The following method is utilized for processing non-tokenized payment methods, where tokenization is not required for transaction completion. This method facilitates streamlined checkout experiences for payment methods that do not necessitate the tokenization process. - For the non-tokenized flow, it is necessary to pass an object containing the checkout request details to facilitate the payment process without requiring tokenization. - WithoutTokenizationRequest()#- Parameters - Data Type - portoneKey - String - mandatory - paymentChannel - String - mandatory - paymentMethod - String - mandatory - merchantOrderId - String - mandatory - amount - Double - mandatory - currency - String - mandatory - billingDetails - CheckoutPaymentDto.BillingDetails - Optional - shippingDetails - CheckoutPaymentDto.ShippingDetails - Optional - orderDetails - List< CheckoutPaymentDto.OrderDetail> - Optional - successUrl - String - mandatory - failureUrl - String - mandatory - environment - String - mandatory - redirectUrl - String - mandatory - description - String - Optional - source - String - mandatory - transactionType - String - mandatory - The parameters mentioned above are standard for non-tokenized checkout methods. However, additional parameters and steps are required for specific methods such as Direct Bank Transfer and Instalments. - These methods also fall under the non-tokenized flow but necessitate extra parameters and steps in the request process. - Direct Bank Transfer
- Instalments
 - These methods, while classified under non-tokenized flows, entail supplementary parameters and steps in the request, as outlined in detail below. - Direct Bank Transfer#- To process a Direct Bank Transfer checkout, the following steps should be followed: - Fetch Direct Bank Transfer Details:
Utilise the following method that only requires the portoneKeyas input to retrieve the details pertaining to Direct Bank Transfer.
- Process Checkout with Bank Details:
Once the bank details are obtained, incorporate them into the payload for checkout processing.
 - Instalments#- To initiate an Instalments checkout, the following steps need to be taken: - Retrieve Bank List for Instalments: Initially, fetching the bank list that offers instalment options is necessary to process instalment payments. 
- Request Parameters for Instalments: - The subsequent request parameters are consistent with the generic checkout request object without tokenization, apart from the addition of a supplementary object for Instalments. - PaymentDto.CheckoutWithInstallationRequest()#- Parameters - Data Type - portoneKey - String - mandatory - paymentChannel - String - mandatory - paymentMethod - String - mandatory - merchantOrderId - String - mandatory - amount - Double - mandatory - currency - String - mandatory - billingDetails - CheckoutPaymentDto.BillingDetails - Optional - shippingDetails - CheckoutPaymentDto.ShippingDetails - Optional - orderDetails - List< CheckoutPaymentDto.OrderDetail> - Optional - successUrl - String - mandatory - failureUrl - String - mandatory - environment - String - mandatory - redirectUrl - String - mandatory - description - String - Optional - source - String - mandatory - transactionType - String - mandatory - bankDetails - PaymentDto.BankDetails - mandatory - BankDetails#- Parameters - Data Type - bankCode - String - mandatory - bankName - String - mandatory - isMerchantSponsored - Boolean - mandatory - overrideDefault - Boolean - mandatory - installmentPeriod - PaymentDto.TermObject - mandatory - PaymentDto.TermObject#- Parameters - Data Type - month - Int - mandatory 
 
For non-tokenized methods such as Direct Bank Transfer and Installments, the method for receiving the response is already included during integration, which is the payment status listener.
Merchant Centric Card Vault#
The Merchant Centric Card Vault operates by enrolling merchants initially, followed by adding customers specific to each merchant. Cards are then saved based on individual customers, ensuring a personalized and secure card storage system. Several methods are available to facilitate various operations within this card vault setup.
- The subsequent method is utilised for customer addition. - Parameters - Data Type - token - String - mandatory - portoneKey - String - mandatory - subMerchantKey - String - Optional - name - String - mandatory - phoneNo - String - mandatory - email - String - mandatory - customerRef - String - mandatory - For receiving the response, the following listener needs to be added. 
- The following method is used to save a particular card for a specific customer. - Parameters - Data Type - customerUUID - String - mandatory - token - String - mandatory - portoneKey - String - mandatory - subMerchantKey - String - Optional - ChanexTokenRequest()#- Parameters - Data Type - cardNumber - String - mandatory - cardType - String - mandatory - cardholderName - String - mandatory - serviceCode - String - mandatory - expiryYear - String - mandatory - expiryMonth - String - mandatory - environment - String - mandatory - portoneKey - String - mandatory - For receiving the response, the following listener needs to be added. 
- This method is utilized to retrieve the stored cards based on the customer. - Parameters - Data Type - customerUUID - String - mandatory - token - String - mandatory - portoneKey - String - mandatory - subMerchantKey - String - Optional - For receiving the response, the following listener needs to be added. 
- This method is employed to remove a specific card for an individual customer. - Parameters - Data Type - customerUUID - String - mandatory - token - String - mandatory - portoneKey - String - mandatory - subMerchantKey - String - Optional - Parameters - Data Type - Remarks - cardToken - String - mandatory - The Card Token can be retrieved in the above fetching the list of cards method - For receiving the response, the following listener needs to be added. 
Pre Auth and Capture Payment#
During Pre-authorization, the transaction is initially approved, and at a later time or within specified days, the payment can be processed using the Capture API.
To designate a transaction for pre-authorization, a specific parameter must be configured in the payload:
transactionType = *PREAUTH*
Following the pre-authorization of a transaction, the subsequent method is utilized for capturing the transaction.
| Parameters | Data Type | |
|---|---|---|
| orderReference | String | mandatory | 
| portoneKey | String | mandatory | 
| token | String | mandatory | 
For receiving the response, the following listener needs to be added.
Failover Routing#
Failover routing is a feature developed for the seamless credit card payment methods. In this feature we set up primary and secondary payment channel from the admin portal so that while paying using one payment channel is not successful due to any reason, it will take user directly to the secondary payment channel.
Following method is used to fetch routes created in admin portal.
This method provides the routeRef that should be included in the payload as outlined below:
- Enable routing by setting isRoutingEnabledto true.
- Specify the Routing Param type as failover.
- Include the Routing Ref, which is configured in the merchant portal.
Possible Error Scenarios:#
INVALID_UNAUTHORIZED_JWT_TOKEN_ERROR#
- Ensure that the PortOne Key and Secret Key belong to the same account.
- Confirm that the Secret Key has not been altered.
- Verify that the Bearerkeyword precedes the generated token with a space. Example:Bearer $jwtToken.
- Check if the token expiration time is after the current time.
INVALID_UNAUTHORIZED_TRANSACTION_SIGNATURE_ERROR#
- Validate if all parameters align with the payload/request.
- Ensure that the PortOne key matches with the payload and the account.
INVALID_UNAUTHORIZED_TRANSACTION_IAMPORTKEY_ERROR#
- Confirm that the PortOne key matches with the payload and the account.
INVALID_PAYMENT_CHANNEL#
- Validate that the payment channels and methods included in the payload are enabled in the PortOne portal.
INVALID_ENVIRONMENT#
- Verify that an environment (sandboxorlive) has been specified.
Summation of order value, tax, duties, shipping, and discount should equal the total amount#
- If items are provided, ensure that the values match the total amount calculation formula: sum(items price * items quantity) + shipping charge - discount = amount.
- Mandatory parameters in the payload:- price
- promo_discount (0 accepted)
- shipping_charges (0 accepted)