Add PayPal Payment integration in Open Event Attendee Application

The open event attendee is an android app which allows users to discover events happening around the world using the Open Event Platform. It consumes the APIs of the open event server to get a list of available events and can get detailed information about them. PayPal is a very common method to pay for anything throughout the world. It is a highly popular platform and it’s only right that there should be an option to pay through PayPal on Eventyay attendee for tickets. This blog will explain how and why I added PayPal payment feature in the application with a sandbox account. Why PayPal?Get API key for a sandbox accountIntegration with Android StudioConclusionResources Let’s analyze every step in detail. Advantages of using PayPal Payment integration Provide UI to gather payment information from the userGet your credentials, which identify your PayPal account as the payment receiver. Specifically, obtain a client ID and secret.Returns a proof of payment to your app.Provides the user their goods or services. Setup Sandbox account and get the API key Go to https://developer.paypal.com/ and sign up for a developer account: After Sign up, go to the dashboard and create an app:  Now in app credentials go to sandbox accounts. Here you can find your API key. Now, Create a new sandbox account with entering some amount of money for testing purposes: PayPal SDK integration in the application Add PayPal SDK in build.gradle dependencies: //PayPal compile 'com.paypal.sdk:paypal-android-sdk:2.16.0' Store the API key in the android manifest file: <meta-data android:name="com.paypal.android.API_KEY" android:value="${PAYPAL_CLIENT_ID}"/> Get the API key in the fragment where PayPal payment is required: private lateinit var PAYPAL_API_KEY: String PAYPAL_API_KEY = activity?.packageManager?.getApplicati<meta-data android:name="com.paypal.android.API_KEY" android:value="${PAYPAL_CLIENT_ID}"/>onInfo(activity?.packageName, PackageManager.GET_META_DATA) ?.metaData?.getString(PAYPAL_KEY).toString() Start PayPal services on create view: val payPalConfiguration = PayPalConfiguration() .environment(PayPalConfiguration.ENVIRONMENT_SANDBOX) .clientId(PAYPAL_API_KEY)val intent = Intent(context, PaymentActivity::class.java)intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, payPalConfiguration)activity?.startService(intent) Now start the Payment conditionally with same intent:  val payment = PayPalPayment(BigDecimal(amount.toString()), "USD", "Pay for tickets", PayPalPayment.PAYMENT_INTENT_SALE) intent.putExtra(PaymentActivity.EXTRA_PAYMENT, payment) startActivityForResult(intent, PAYPAL_REQUEST_CODE) Handle the result after payment is done: override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { if (requestCode == PAYPAL_REQUEST_CODE) { if (resultCode == Activity.RESULT_OK) { val paymentConfirmation = data?.getParcelableExtra<PaymentConfirmation>(PaymentActivity.EXTRA_RESULT_CONFIRMATION) if (paymentConfirmation != null) { val paymentInfo = paymentConfirmation.toJSONObject() val tokenId = paymentInfo.getJSONObject("response").getString("id") Timber.d(paymentInfo.toString(4)) // Send the token to server val charge = Charge(attendeeViewModel.getId().toInt(), tokenId, null) attendeeViewModel.completeOrder(charge) } } else if (resultCode == Activity.RESULT_CANCELED) Toast.makeText(context, "Payment canceled!", Toast.LENGTH_SHORT).show() else if (resultCode == PaymentActivity.RESULT_EXTRAS_INVALID) Toast.makeText(context, "Invalid Payment Configuration", Toast.LENGTH_SHORT).show() } } GIF In a nutshell With almost 250 million users worldwide, PayPal is an extremely popular platform for monetary transactions and it’s quite essential that every application an option to use it. Given the nature of Eventyay attendee and its pan-world appeal, I have added PayPal as a payment system for tickets to any event. Resources PayPal Android SDK guide: PayPal Android SDKPayPal SDK repo: PayPal-Android-SDK Tags PayPal, Android, Payments, FOSSASIA, GSoC, AndroidPayments, Kotlin

Continue ReadingAdd PayPal Payment integration in Open Event Attendee Application

Integrating Stripe OAuth in Open Event Frontend

Why is Stripe Oauth needed in frontend? Open event allows organizers to add tickets and accepts payments for tickets through various modes for example, Credit card, Debit card, Netbanking and offline payments. Stripe allows users to accept payments into their linked accounts on various online platforms after they provide client secret and publishable key. So to enable online payments in open event, organizers were required to authenticate their stripe account. This is done through Stripe OAuth. Flow of OAuth To allow organizers to link their stripe account admin has to enable stripe under payment gateway in admin settings. Admin provides his client ID and secret key. Admin also sets the redirect URL for his app on the stripe dashboard. After enabling these settings organizer will see an option to link their stripe account to open event when they are creating an event with paid tickets. Here is what open event frontend does when we click connect to stripe button: Opens a popup to allow organizer to fill his stripe credentials and authorize open event app to access their secret and publishable key. Once the organizer fills his credentials and authorizes open event app, open event frontend fetches organizers auth code and saves it to server. Server on receiving auth code from frontend makes a request to stripe using the auth code to retrieve the publishable key and secret key. Once these are fetched server saves this information against the event so that all payments for that event can go to the linked stripe account. Implementing the Frontend portion: Choosing the library: After looking at various libraries that support OAuth for Ember applications we decided to use Torii. Torii is the library that allows the addition of OAuth for various social apps such as Facebook, Google and Stripe too. It allows writing a custom provider for OAuth in case we do not want to use clients for which torii provides supports by default. Implementing Stripe Provider: Default provider for stripe given by torii fetched the client ID and redirect URL from environment.js file. But since in open event we have already saved client id of admin in our database so we will extend default stripe provider and modify its client Id so that it fetches client id from server. Code for extending default provider is given here: import stripeConnect from 'torii/providers/stripe-connect'; import { alias } from '@ember/object/computed'; import { inject } from '@ember/service'; import { configurable } from 'torii/configuration'; function currentUrl() { let url = [window.location.protocol, '//', window.location.host].join(''); if (url.substr(-1) !== '/') { url += '/'; } return url; } export default stripeConnect.extend({ settings: inject(), clientId: alias('settings.stripeClientId'), redirectUri: configurable('redirectUri', function() { return `${currentUrl()}torii/redirect.html`; }) });   We have fetched clientId from our settings service as alias('settings.stripeClientId'). We have already defined settings in our services so we just need to inject the service here to be able to use it. By default torii provides redirect url as {currentUrl}/torii/redirect.html. But in open event frontend we allow organizers to edit information on two routes…

Continue ReadingIntegrating Stripe OAuth in Open Event Frontend

Implementing Permissions for Orders API in Open Event API Server

Open Event API Server Orders API is one of the core APIs. The permissions in Orders API are robust and secure enough to ensure no leak on payment and ticketing.The permission manager provides the permissions framework to implement the permissions and proper access controls based on the dev handbook. The following table is the permissions in the developer handbook.   List View Create Update Delete Superadmin/admin ✓ ✓ ✓ ✓ ✓ Event organizer ✓ [1] ✓ [1] ✓ [1] ✓ [1][2] ✓ [1][3] Registered user ✓ [4] Everyone else Only self-owned events Can only change order status A refund will also be initiated if paid ticket Only if order placed by self Super Admins and admins are allowed to create any order with any amount but any coupon they apply is not consumed on creating order. They can update almost every field of the order and can provide any custom status to the order. Permissions are applied with the help of Permission Manager which takes care the authorization roles. For example, if a permission is set based on admin access then it is automatically set for super admin as well i.e., to the people with higher rank. Self-owned events This allows the event admins, Organizer and Co-Organizer to manage the orders of the event they own. This allows then to view all orders and create orders with or without discount coupon with any custom price and update status of orders. Event admins can provide specific status while others cannot if not has_access('is_coorganizer', event_id=data['event']): data['status'] = 'pending' And Listing requires Co-Organizer access elif not has_access('is_coorganizer', event_id=kwargs['event_id']): raise ForbiddenException({'source': ''}, "Co-Organizer Access Required") Can only change order status The organizer cannot change the order fields except the status of the order. Only Server Admin and Super Admins are allowed to update any field of the order. if not has_access('is_admin'): for element in data: if element != 'status': setattr(data, element, getattr(order, element)) And Delete access is prohibited to event admins thus only Server admins can delete orders by providing a cancelling note which will be provided to the Attendee/Buyer. def before_delete_object(self, order, view_kwargs): if not has_access('is_coorganizer', event_id=order.event.id): raise ForbiddenException({'source': ''}, 'Access Forbidden') Registered User A registered user can create order with basic details like the attendees' records and payment method with fields like country and city. They are not allowed to provide any custom status to the order they are creating. All orders will be set by default to “pending” Also, they are not allowed to update any field in their order. Any status update will be done internally thus maintaining the security of Order System. Although they are allowed to view their place orders. This is done by comparing their logged in user id with the user id of the purchaser. if not has_access('is_coorganizer_or_user_itself', event_id=order.event_id, user_id=order.user_id): return ForbiddenException({'source': ''}, 'Access Forbidden') Event Admins The event admins have one more restriction, as an event admin, you cannot provide discount coupon and even if you do it will be ignored. # Apply discount only…

Continue ReadingImplementing Permissions for Orders API in Open Event API Server