Judopay Documentation

Deprecated Integration Methods

iOS Swift

Caution

iOS Swift SDK has been deprecated and will not longer be updated.

You will get the following warning when you submit your app to the Apple app store:

"ITMS-90809: Deprecated API Usage - App updates that use UIWebView will no longer be accepted as of December 2020.

Instead, use WKWebView for improved security and reliability."

To integrate, see our new iOS JudoKit SDK.

Getting started

If you haven’t chosen your integration method yet, begin by selecting your method and following the What to do next steps first.

Integrate simple and secure in-app card payments into your iOS Swift app with our Judopay SDK.

Judopay’s Out-of-the-box UI comes with built-in checks and security features, including real-time error detection, 3D Secure, data and address validation for frictionless card data capture.

This minimises PCI compliance and allows you focus on developing other areas of your app.

See our UI customization guide to learn more.

deprecated

Integration Requirements

Versions of the SDK greater or equal to 6.2.5 require Xcode 8 and Swift 3.

Version 6.2.4 is the last version to be support Xcode 7.3.1 and Swift 2.2.

Add the Swift SDK to the top of the file where you want to use it:

 

Install Cocoapods with the following command:

$ gem install cocoapods 

If you are not integrating using Cocoapods, please visit our guides for Carthage integration.

Add Judopay to your Podfile to integrate it into your Xcode project.

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!
pod 'JudoKit', '~> 6.2'

Install the new pod in your project

$ pod install 

Please ensure that you always use the newly generated .xcworkspace file instead of the .xcodeproj file.

In Xcode, go to the Project Navigator called ‘Pods’, select the JudoKit target and open the tab called Build Phases.

Add a new Run Script Phase and drag it above the Compile Sources build phase.

Include the following line in the shell script:

sh "${PODS_ROOT}/DeviceDNA/Framework/strip-frameworks-cocoapods.sh"

Setup

To start setting up your app, please complete all the relevant integration steps in the getting started section.

By following these steps, you are ensuring that your app will be secure and frictionless for you and your customers.

If you have completed the setup section, start using Judopay’s iOS Swift SDK by adding your app’s token and secret when initializing the SDK:

var judoKitSession = JudoKit(token: token, secret: secret)

Command the SDK to communicate with sandbox environment by including the following line where the payment is initiated in the ViewController:

self.judoKitSession.sandboxed(true)

Point to the live environment

In your app’s ViewController, find and delete the following line that specifies the targeted environment:

self.judoKitSession.sandboxed(true)

Replace your sandbox API token and secret for the live API token and secret in the correspondent line.

Both credentials are located in the dashboard, under the Your apps section.

Follow our Access token and secret guide if you need help to find them.

var judoKitSession = JudoKit(token: token, secret: secret)

Ruby Server SDK

Caution

Ruby Server SDK has been deprecated and will not longer be updated.

 

Easily handle simple and secure payments on your back-end with the Judopay Ruby server side SDK. 

If you haven’t chosen your integration method yet, begin by selecting your method and following the What to do next steps first.

 

Integration Requirements

Ruby 1.9.3 and above (including 2.0.x and 2.1.x).

Add the following line to your application’s Gemfile:

gem 'judopay'

Once the Gemfile is set, then there are two options to finish the installation:

Execute the following line:

$ bundle-

Or install it yourself as:

$ gem install judopay

Setup

To start setting up your app, please complete all the relevant integration steps in the setup section.

By following these steps, you are ensuring that your app will be secure and frictionless for you and your customers.

When you have completed the setup, start using Judopay’s PHP SDK by adding your app’s token and secret when initializing the SDK:

Judopay.configure do |config| config.judo_id = 12345 config.api_token = 'your-token' config.api_secret = 'your-secret' # Set to true on production, defaults to false which is the sandbox config.use_production = false
end

Remember, if you perform payments only from your backend, you should only enable the Register Card Transactions permission for your app and create a separate app for your backend with only the Make Payments permission enabled. 

Processing transactions with AmEx cards requires that your account supports it as well.

Please contact us first if you are planning to accept AmEx.

The SDK allows further configuration:

  • Logging – You will be able to attach a logger library to help you debug your Judopay integration.

Point to the live environment

In the Judopay gem, find and change the production environment setting from ‘false’ to ‘true’.

Replace your sandbox API token and secret for the live API token and secret in the corresponding lines.

Both credentials are located in the dashboard, under the Your apps section.

Follow our Access token and secret guide if you need help to find them.

Judopay.configure do |config| config.judo_id = 12345 config.api_token = 'your-token' config.api_secret = 'your-secret' # Set to true on production, defaults to false which is the sandbox config.use_production = true end

React Native V2.1

Caution

Version 2.1 is now deprecated.

Warning

For Mobile apps, it is recommended not to make a transaction from the app, as the Token and Secret could become compromised.

Use the server to make the transaction.

Create a Register Card app and enable the Register Card Transactions permission.

For examples on how to integrate the SDK, see our sample app for more information.

Requirements

  • Version 0.62+

Installing React-Native

  1. In your package.json file add under scripts section:

"postinstall": "node node_modules/judo-react-native/scripts/sample-app_postinstall.js node_modules/judo-react-native"

  1. Under the dependencies section add:

"judo-react-native": "file:../",In your root project folder run:sh rm yarn.lock && rm -rf node_modules yarn install

  1. Navigate to ios/folder

    and run: 

sh rm -rf Pods/ && rm Podfile.lock pod install

To run the Judopay React Native SDK:

  1. Import:

import {
  RNJudo,
  type JudoOptions,
  type JudoApplePayOptions,
  type JudoGooglePayOptions,
  type PaymentOptions
} from "judo-react-native";
  1. Configure the JudoOptions object:

const judoOptions: JudoOptions = {
  token: "<TOKEN>",
  secret: "<SECRET>",
  judoId: "<JUDO_ID>",
  isSandbox: true,
  amount: "0.01",
  currency: "GBP",
  consumerReference: "myCustomerReference",
  paymentReference: "myPaymentReference",
  metaData: {metadatakey: "metadataValue", metadatakey2: "metadataValue2"}
};

Note

token | secret | judoId | amount | currency = mandatory fields.

You will need to pass the judoOptions object each time you want to make a call to the JudoPay React Native SDK.

Setting Up React Native

To create a Payment:

try {
  let response = await RNJudo.makePayment(judoOptions);
  if (response.result === "Success") {
    //Handle successful result
  } else {
    //Handle unsuccessful result
  }
} catch (e) {
    //handle error
}

To create a PreAuth:

try {
  let response = await RNJudo.makePreAuth(judoOptions);
  if (response.result === "Success") {
    //Handle successful result
  } else {
    //Handle unsuccessful result
  }
} catch (e) {
  //handle error
}

 

response object will contain all data contained in JPTransactionData.h the same field is exposed in Android. e - error.

All error codes found in NSError+Judo.h are the same for Android.

 

Payment Methods UI

For the payment methods UI to appear, pass the following 3 objects:

  • paymentOptions

  • applePayOptions

  • googlePayOptions

Payment Options

Select one of the following constants:

const paymentOptions: PaymentOptions = {
  paymentMethods: RNJudo.PAYMENT_METHOD_NONE
};
Payment method types: {
  RNJudo.PAYMENT_METHOD_NONE
  RNJudo.PAYMENT_METHOD_CARD
  RNJudo.PAYMENT_METHOD_GOOGLE_PAY
  RNJudo.PAYMENT_METHOD_APPLE_PAY
  RNJudo.PAYMENT_METHOD_ALL
}

Call showPaymentMethods:

try {
  let response = await RNJudo.showPaymentMethods(
    Object.assign({}, judoOptions, applePayOptions, googlePayOptions, paymentOptions)
  );
  if (response.result === "Success") {
    //Handle successful result
  } else {
    //Handle non-success flow
  }
} catch (e) {
    //handle error
}

Apple Pay Options

Apple Pay configuration:

try {
  let response = await RNJudo.showPaymentMethods(
    Object.assign({}, judoOptions, applePayOptions, googlePayOptions, paymentOptions)
  );
  if (response.result === "Success") {
    //Handle successful result
  } else {
    //Handle non-success flow
  }
} catch (e) {
    //handle error
}

Select one of the following constants:

Transaction types: {
  RNJudo.APPLE_PAY_TRANSACTION_PAYMENT
  RNJudo.APPLE_PAY_TRANSACTION_PAYMENT
}

Shipping types: {
  RNJudo.APPLE_PAYMENT_SHIPPING
  RNJudo.APPLE_PAYMENT_DELIVERY
  RNJudo.APPLE_PAYMENT_STORE_PICKUP
  RNJudo.APPLE_PAYMENT_SERVICE_PICKUP
}

Apple Pay payment summary item types: {
  RNJudo.APPLE_PAYMENT_SUMMARY_FINAL
  RNJudo.APPLE_PAYMENT_SUMMARY_PENDING
}

Apple pay button light/dark styles: {
  RNJudo.APPLE_PAY_BUTTON_THEME_LIGHT
  RNJudo.APPLE_PAY_BUTTON_THEME_DARK
}

 

To make an Apple Pay transaction:

try {
  let response = await RNJudo.makeApplePayPayment(
    Object.assign({}, judoOptions, applePayOptions)
  );
  if (response.result === "Success") {
    //Handle successful result
  } else {
    //Handle non-success flow
  }
} catch (e) {
    //handle error
}

Tip

You can call judoOptions and applePayOptions, the same as showPaymentMethods.

Google Pay Options

Google Pay configuration:

const googlePayOptions: JudoGooglePayOptions = {
  googlePayTestEnvironment: false,
  isPayment: false, // pre-auth
  isRequestBilling: false,
  isRequestContactDetails: false,
  isRequestShipping: false
};

To make a Google Pay transaction:

try {
  let response = await RNJudo.makeGooglePayPayment(
    Object.assign({}, judoOptions, googlePayOptions)
  );
  if (response.result === "Success") {
    //Handle successful result
  } else {
    //Handle unsuccess flow
  }
} catch (e) {
    //handle error
}

Tip

You can call judoOptions and googlePayOptions, the same as showPaymentMethods.

Google Pay™ as a Payment Method

Configuring the Wallet

Caution

Wallet Configuration is now deprecated.

There are two environments for Google Pay™:

  • Sandbox

  • Production 

Ensure you configure the Wallet to specify your payment environment.

This is reflected by the WalletConstants enum in the android wallet package:

public static final int PAYMENTS_ENVIRONMENT = WalletConstants.ENVIRONMENT_PRODUCTION;

public static final int PAYMENTS_ENVIRONMENT = WalletConstants.ENVIRONMENT_SANDBOX;

Google Pay™ supports both tokenized and non-tokenized cards. 

Tokenised:  Google Pay™ generates a token which represents the card. Only this token is sent when making a payment. Your customer's card number does not leave Google Pay™.

For security reasons, Judopay only currently supports tokenized cards. Therefore you must configure your application to only support the tokenized card method. 

Note

This means any invalid cards will not appear as a payment option when your consumer tries to pay with your application.

public static final List<Integer> SUPPORTED_METHODS = Arrays.asList(
        // PAYMENT_METHOD_TOKENIZED_CARD refers to EMV tokenized credentials stored in the
        // Google Pay app, assuming it's installed.
        WalletConstants.PAYMENT_METHOD_TOKENIZED_CARD
);

1. Set the Gateway name to judopay:

public static final String GATEWAY_TOKENIZATION_NAME = "judopay";

2. When creating a new PaymentsClient (another Android class), initialise it with the PAYMENTS_ENVIRONMENT, and the activity launching your payment:

public static PaymentsClient createPaymentsClient(Activity activity) {
    Wallet.WalletOptions walletOptions = new Wallet.WalletOptions.Builder()
            .setEnvironment(Constants.PAYMENTS_ENVIRONMENT)
            .build();
    return Wallet.getPaymentsClient(activity, walletOptions);
}

3. Set the tokenization parameters with your merchant ID (Judo ID):

public static final List<Pair<String, String>> GATEWAY_TOKENIZATION_PARAMETERS = Arrays.asList(
    Pair.create("gatewayMerchantId", "{YOUR_JUDO_ID}")
);

4. Specify the card networks to support, and the allowed shipping countries. This might vary depending on your application and product.

// The allowed networks to be requested from the API. If the user has cards from networks not
// specified here in their account, these will not be offered for them to choose in the popup.
public static final List<Integer> SUPPORTED_NETWORKS = Arrays.asList(
        WalletConstants.CARD_NETWORK_AMEX,
        WalletConstants.CARD_NETWORK_DISCOVER,
        WalletConstants.CARD_NETWORK_VISA,
        WalletConstants.CARD_NETWORK_MASTERCARD
);

// Supported countries for shipping (use ISO 3166-1 alpha-2 country codes).
// Relevant only when requesting a shipping address.
public static final List<String> SHIPPING_SUPPORTED_COUNTRIES = Arrays.asList(
        "US",
        "GB"
);

Generating a Google Pay™ Payment

In your checkout activity:

  • Find the view/button to trigger the payment

  • Add the request payment listener

The Google Pay sample application project has a sample view layout for a Google Pay button you can use (googlepay_button.xml) which follows the Google Pay style conventions.

// Arbitrarily-picked result code.
private static final int LOAD_PAYMENT_DATA_REQUEST_CODE = 991;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_checkout);


    mGooglePayButton = findViewById(R.id.googlepay_button);
    mGooglePayStatusText = findViewById(R.id.googlepay_status);

    mGooglePayButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            requestPayment(view);
        }
    });

    // It's recommended to create the PaymentsClient object inside the onCreate method.
    mPaymentsClient = PaymentsUtil.createPaymentsClient(this);
    checkIsReadyToPay();
}

// This method is called when the Pay with Google button is clicked.
public void requestPayment(View view) {
    // Disables the button to prevent multiple clicks.
    mGooglePayButton.setClickable(false);

    // The price provided to the API should include taxes and shipping.
    // This price is not displayed to the user.
    String price = PaymentsUtil.microsToString(YOUR_ITEM_PRICE);

    TransactionInfo transaction = PaymentsUtil.createTransaction(price);
    PaymentDataRequest request = PaymentsUtil.createPaymentDataRequest(transaction);
    Task<PaymentData> futurePaymentData = mPaymentsClient.loadPaymentData(request);

    // Since loadPaymentData may show in the UI asking the user to select a payment method, we use
    // AutoResolveHelper to wait for the user interacting with it. Once completed,
    // onActivityResult will be called with the result.
    AutoResolveHelper.resolveTask(futurePaymentData, this, LOAD_PAYMENT_DATA_REQUEST_CODE);
}

private void checkIsReadyToPay() {
    // The call to isReadyToPay is asynchronous and returns a Task. We need to provide an
    // OnCompleteListener to be triggered when the result of the call is known.
    PaymentsUtil.isReadyToPay(mPaymentsClient).addOnCompleteListener(
            new OnCompleteListener<Boolean>() {
                public void onComplete(Task<Boolean> task) {
                    try {
                        boolean result = task.getResult(ApiException.class);
                        setGooglePayAvailable(result);
                    } catch (ApiException exception) {
                        // Process error
                        Log.w("isReadyToPay failed", exception);
                    }
                }
            });
}

private void setGooglePayAvailable(boolean available) {
    // If isReadyToPay returns true, show the button and hide the "checking" text. Otherwise,
    // notify the user that Pay with Google is not available.
    // Please adjust to fit in with your current user flow. You are not required to explicitly
    // let the user know if isReadyToPay returns false.
    if (available) {
        mGooglePayStatusText.setVisibility(View.GONE);
        mGooglePayButton.setVisibility(View.VISIBLE);
    } else {
        mGooglePayStatusText.setText(R.string.googlepay_status_unavailable);
    }
}

Create the PaymentDataRequest, passing in the gateway name and parameters set earlier.

Ensure to set the tokenization type as: WalletConstants.PAYMENT_METHOD_TOKENIZATION_TYPE_PAYMENT_GATEWAY:

public static PaymentDataRequest createPaymentDataRequest(TransactionInfo transactionInfo) {
    PaymentMethodTokenizationParameters.Builder paramsBuilder =
            PaymentMethodTokenizationParameters.newBuilder()
                    .setPaymentMethodTokenizationType(
                            WalletConstants.PAYMENT_METHOD_TOKENIZATION_TYPE_PAYMENT_GATEWAY)
                    .addParameter("gateway", Constants.GATEWAY_TOKENIZATION_NAME);
    for (Pair<String, String> param : Constants.GATEWAY_TOKENIZATION_PARAMETERS) {
        paramsBuilder.addParameter(param.first, param.second);
    }

    return createPaymentDataRequest(transactionInfo, paramsBuilder.build());
}

private static PaymentDataRequest createPaymentDataRequest(TransactionInfo transactionInfo, PaymentMethodTokenizationParameters params) {
    PaymentDataRequest request =
            PaymentDataRequest.newBuilder()
                    .setPhoneNumberRequired(false)
                    .setEmailRequired(true)
                    .setShippingAddressRequired(true)

                    // Omitting ShippingAddressRequirements altogether means all countries are
                    // supported.
                    .setShippingAddressRequirements(
                            ShippingAddressRequirements.newBuilder()
                                    .addAllowedCountryCodes(Constants.SHIPPING_SUPPORTED_COUNTRIES)
                                    .build())

                    .setTransactionInfo(transactionInfo)
                    .addAllowedPaymentMethods(Constants.SUPPORTED_METHODS)
                    .setCardRequirements(
                            CardRequirements.newBuilder()
                                    .addAllowedCardNetworks(Constants.SUPPORTED_NETWORKS)
                                    .setAllowPrepaidCards(true)
                                    .setBillingAddressRequired(true)

                                    // Omitting this parameter will result in the API returning
                                    // only a "minimal" billing address (post code only).
                                    .setBillingAddressFormat(WalletConstants.BILLING_ADDRESS_FORMAT_FULL)
                                    .build())
                    .setPaymentMethodTokenizationParameters(params)

                    // If the UI is not required, a returning user will not be asked to select
                    // a card. Instead, the card they previously used will be returned
                    // automatically (if still available).
                    // Prior whitelisting is required to use this feature.
                    .setUiRequired(true)
                    .build();

    return request;
}

Handle a Successful Payment

Catch the payment result in your checkout activity:

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case LOAD_PAYMENT_DATA_REQUEST_CODE:
            switch (resultCode) {
                case Activity.RESULT_OK:
                    PaymentData paymentData = PaymentData.getFromIntent(data);
                    handlePaymentSuccess(paymentData);
                    break;
                case Activity.RESULT_CANCELED:
                    // Nothing to here normally - the user simply cancelled without selecting a
                    // payment method.
                    break;
                case AutoResolveHelper.RESULT_ERROR:
                    Status status = AutoResolveHelper.getStatusFromIntent(data);
                    handleError(status.getStatusCode());
                    break;
            }

            // Re-enables the Pay with Google button.
            mGooglePayButton.setClickable(true);
            break;
    }
}

 

The function below demonstrates how to handle the payment request returned from the intent, and send on the necessary tokenized card details to the Judopay API to be processed:

private void handlePaymentSuccess(PaymentData paymentData) {
    // PaymentMethodToken contains the payment information, as well as any additional
    // requested information, such as billing and shipping address.
    PaymentMethodToken token = paymentData.getPaymentMethodToken();

    // getPaymentMethodToken will only return null if PaymentMethodTokenizationParameters was
    // not set in the PaymentRequest.
    if (token != null) {
        String encryptedToken = token.getToken();
        String cardNetwork = paymentData.getCardInfo().getCardNetwork();
        String cardDetails = paymentData.getCardInfo().getCardDetails();

        JudoApiService apiService = getJudo().getApiService(getApplicationContext());
        GooglePayRequest request = getGooglePayRequest(encryptedToken, cardNetwork, cardDetails);
        apiService.googlePayPreAuth(request);
    }
}

private GooglePayRequest getGooglePayRequest(String encryptedToken, String cardNetwork, string cardDetails) {
    return new GooglePayRequest.Builder()
            .setJudoId("YOUR_JUDO_ID")
            .setGooglePayWallet(new GooglePayWallet.Builder()
                    .setCardNetwork(cardNetwork)
                    .setCardDetails(cardDetails)
                    .setToken(encryptedToken)
                    .build())
            .setAmount(YOUR_PRICE)
            .setCurrency(Currency.GBP)
            .setConsumerReference(UNIQUE_GUID)
            .build();
}