Skip to content

Instantly share code, notes, and snippets.

@jagdeepsingh
Last active October 16, 2024 18:49
Show Gist options
  • Save jagdeepsingh/c538e21f3839f65732a5932e35809d60 to your computer and use it in GitHub Desktop.
Save jagdeepsingh/c538e21f3839f65732a5932e35809d60 to your computer and use it in GitHub Desktop.
Apple Pay on Web (iPhone)

Guidelines for using Apple Pay

Apple provides a set of guidelines for businesses that wish to incorporate Apple Pay into their websites. As a merchant, you must follow all of them to be eligible for using Apple Pay.

Back to Top

Setup merchant account on Apple

Contents:

You, as a merchant, will need an Apple Developer Account which you can setup on their Developer Console.

Register a Merchant ID

Log into your developer account and follow steps below to register a Merchant Identifier for your business:

  1. Go to Certificates, Identifiers & Profiles.

  1. Select Identifiers > Merchant IDs.
  2. Register a Merchant ID.

Generate Payment Processing Certificate

  1. Go to Certificates, Identifiers & Profiles.
  2. Select Identifiers > Merchant IDs.
  3. Select the Merchant ID you created and click Edit.
  4. In the Payment Processing Certificate section, click Create Certificate.
  5. Select if your payments will be processed exclusively in China and click "Continue".

  1. Either Obtain a CSR file from your Payment Provider OR follow below steps to create a CSR file:

    • In the Applications folder on your Mac, open Utilities and launch Keychain Access.
    • In Keychain Access drop down menu, select Keychain Access > Certificate Assistant > Request a Certificate from a Certificate Authority.
    • In the Certificate information window, enter the following:
      • Email address
      • Common Name for your key e.g. JD_TD_APPLE_PAY_PAYMENT_DEV_KEY
      • Leave CA Email Address blank
      • In the Request is group, select Saved to disk option.
      • Select Let me specify key pair information.
    • Click Continue and save the file at desired location.
    • Set the Key Pair Information to the following:
      • Algorithm: ECC
      • Key Size: 256 bits
    • Click Continue. Your certificate is generated.
  2. Under Generate your certificate, click Choose File, select your CSR file, and click Continue.

  1. Download the certificate by clicking Download, and click Done. Certificate will be downloaded as apple_pay.cer.
  2. Follow guide to convert this ".cer" file to ".pem" file.

Register and verify website domain

You will also need to register the domain where your application runs. It can be done as follows:

  1. Go to Certificates, Identifiers & Profiles.
  2. Select Identifiers > Merchant IDs.
  3. Select the Merchant ID from the list and click Edit.
  4. In Apple Pay on Web > Merchant Domains section, click on Add Domain button.
  5. Enter your fully qualified domain name. You can use ngrok to get a domain for localhost.

  1. On clicking Continue, you will be given a file to download.

On clicking Download, a file named apple-developer-merchantid-domain-association will be downloaded on your system.

Now, you need to host the file at location specified by Apple e.g. https://abcd1234.ngrok.io/.well-known/apple-developer-merchantid-domain-association. If you are using Ruby on Rails, you can do it as follows:

Put the downloaded file at path public/apple-developer-merchantid-domain-association.

# config/routes.rb
match '/.well-known/apple-developer-merchantid-domain-association',
to: 'apple_pay_merchants#domain_association'
# app/controllers/apple_pay_merchants_controller.rb
class ApplePayMerchantsController < ApplicationController
  layout false

  def domain_association
    render file: 'public/apple-developer-merchantid-domain-association'
  end
end
  1. Click on Verify button. Apple will ping the verification URL and if verification succeeds, the site returns to the iOS Merchant ID Settings page and Status will be set to Verified.

Generate Merchant Identity Certificate

A Merchant Identity Certificate is needed to create a session with Apple.

  1. Go to Certificates, Identifiers & Profiles.
  2. Select Identifiers > Merchant IDs.
  3. Select the Merchant ID from the list and click Edit.
  4. In Apple Pay on Web > Merchant Identity Certificate section, click on Create Certificate button.
  5. Follow below steps to create a CSR file:
    • In the Applications folder on your Mac, open Utilities and launch Keychain Access.
    • In Keychain Access drop down menu, select Keychain Access > Certificate Assistant > Request a Certificate from a Certificate Authority.
    • In the Certificate information window, enter the following:
      • Email address
      • Common Name for your key e.g. JD_TD_APPLE_PAY_MERCHANT_DEV_KEY
      • Leave CA Email Address blank
      • In the Request is group, select Saved to disk option.
      • Do NOT select Let me specify key pair information.
    • Click Continue and save the file at desired location.
  6. In Upload CSR file, click on Choose File and upload the CSR file generated in previous step. Click Continue.
  7. Download the generated Merchant Identity Certificate. Certificate will be named merchant_id.cer.
  8. Follow guide to convert this ".cer" file to ".pem" file.

Back to Top

Create merchant session

Put merchant_id.cer file and its corresponding ".pem" file in /certificates inside your Ruby on Rails application. DO NOT push the certificates to whatever Version Control System you are using. For git, add the files to .gitignore.

Add a JS file to handle display of Apple Pay modal and callbacks for authorizing payments.

// app/assets/javascripts/apple_pay.js
/**
* This method is called when the page is loaded.
*/
document.addEventListener('DOMContentLoaded', () => {
  if (isApplePayAvailable()) {
    $('#applepay-btn').on('click', applePayButtonClicked);
  } else {
    // Browser and/or user's cards do not support Apple Pay
  }
});

/**
* Returns a boolean value indicating if Apple Pay is supported in your device
*/
function isApplePayAvailable() {
  var unavailable = false;
  unavailable = unavailable || !window.ApplePaySession;
  if (!unavailable) {
    var promise = ApplePaySession.canMakePaymentsWithActiveCard(MERCHANT_ID);
    promise.then(function(canMakePayments) {
      return unavailable = unavailable || !!canMakePayments;
    });
  }
  return !unavailable;
};

/**
* Apple Pay Logic
* Our entry point for Apple Pay interactions.
* Triggered when the Apple Pay button is pressed
*/
function applePayButtonClicked() {
  /**
  * Sample payment data
  */
  function paymentRequestData() {
    return {
      countryCode: 'JP',
      currencyCode: 'JPY',
      total: {
        label: 'Purchase at MyStore',
        amount: 2000
      },
      supportedNetworks: ['masterCard', 'visa', 'discover', 'amex'],
      merchantCapabilities: ['supports3DS']
    };
  };

  var paymentRequest = paymentRequestData();
  var session = new ApplePaySession(2, paymentRequest);

  /**
  * Makes an AJAX request to your application server with URL provided by Apple
  */
  function getSession(url) {
    return new Promise(function(resolve, reject) {
      var xhr = new XMLHttpRequest;
      var requestUrl = '/path/to/applepay/merchant/session';

      xhr.open('POST', requestUrl);

      xhr.onload = function() {
        if (this.status >= 200 && this.status < 300) {
          return resolve(JSON.parse(xhr.response));
        } else {
          return reject({
            status: this.status,
            statusText: xhr.statusText
          });
        }
      };

      xhr.onerror = function() {
        return reject({
          status: this.status,
          statusText: xhr.statusText
        });
      };

      xhr.setRequestHeader('Content-Type', 'application/json');

      return xhr.send(JSON.stringify({
        url: url
      }));
    });
  };

  /**
  * Merchant Validation
  * We call our merchant session endpoint, passing the URL to use
  */
  session.onvalidatemerchant = (event) => {
    const validationURL = event.validationURL;
    var promise = getSession(event.validationURL);
    promise.then(function(response) {
      session.completeMerchantValidation(response);
    });
  };

  /**
  * This is called when user dismisses the payment modal
  */
  session.oncancel = (event) => {
    // Re-enable Apple Pay button
  };
 
  /**
  * Payment Authorization
  * Here you receive the encrypted payment data. You would then send it
  * on to your payment provider for processing, and return an appropriate
  * status in session.completePayment()
  */
  session.onpaymentauthorized = (event) => {
    const payment = event.payment;
    // You can see a sample `payment` object in an image below.
    // Use the token returned in `payment` object to create the charge on your payment gateway.

    if (chargeCreationSucceeds) {
      // Capture payment from Apple Pay
      session.completePayment(ApplePaySession.STATUS_SUCCESS);
    } else {
      // Release payment from Apple Pay
      session.completePayment(ApplePaySession.STATUS_FAILURE);
    }
  };

  /**
  * This will show up the modal for payments through Apple Pay
  */
  session.begin();
}

Sample payment JSON:

See text version of above JSON here.

You also need to setup an end point on your server side to create merchant session:

# app/controllers/apple_pay_merchants_controller.rb
require 'net/http'
require 'uri'

class ApplePayMerchantsController < ApplicationController
  CERTIFICATES_DIR = 'certificates'.freeze
  MERCHANT_ID_CERT_FILE = 'merchant_id.cer'.freeze
  MERCHANT_ID_PEM_FILE = 'MerchantIdCertificate.key.pem'.freeze

  def get_session
    uri = URI.parse(params[:url])
    http = build_http(uri)

    # Read Merchant Identity Certificate
    cert = Rails.root.join(CERTIFICATES_DIR, MERCHANT_ID_CERT_FILE).read
    http.cert = OpenSSL::X509::Certificate.new(cert)

    # Read Merchant Identity pem file
    pem = Rails.root.join(CERTIFICATES_DIR, MERCHANT_ID_PEM_FILE).read
    http.key = OpenSSL::PKey::RSA.new(pem, nil)

    request = build_request(uri)
    response = http.request(request)

    respond_to do |format|
      format.json { render json: response.body, status: :ok }
    end
  end
  
  private

  def build_http(uri)
    http = ::Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    http.ssl_version = :TLSv1_2
    http.ciphers = ['ECDHE-RSA-AES128-GCM-SHA256']
    http.verify_mode = OpenSSL::SSL::VERIFY_PEER
    http
  end

  def build_request(uri)
    request = ::Net::HTTP::Post.new(uri.request_uri, 'Content-Type' => 'application/json')
    body = { merchantIdentifier: MERCHANT_ID,
             domainName: DOMAIN,
             displayName: 'ToDo Application' }
    request.body = body.to_json
    request
  end
end

Now, Add an "Apple Pay" button on your payment page. All the different designs of Apple Pay button can be found here.

Back to Top

Setup Apple Pay on customer iPhone

You will need an iPhone that supports payments through Apple Pay. Complete list can be found here.

Test

  1. Setup your finger print on your iPhone to make easy payments by just touching the home button. (Optional)
  2. Set up a Sandbox tester account on iTunes Connect.
  3. Sign in to iCloud on iPhone using tester account credentials.
  4. In iPhone > Settings > General > Language & Region, set region to one of the supported countries. Sandbox testing is supported only in these countries.
  5. In Wallet app on iPhone:
    • Click on "Add Credit or Debit Card".

    • Click on "Enter Card Details Manually".

    • Enter Name and Card Number and click "Next".

    • Enter Expiration Date and Security Code and click "Next".

    • Click "Agree".

Your card will be added to Wallet now.

All test credit cards are available here.

  1. Select the card just added, click on "i" icon at the bottom, and enter Info > Billing Address for the card.

  1. In iPhone > Settings > Wallet & Apple Pay, set Default Card, Shipping Address, Email, and Phone.

Live

  1. Setup your finger print on your iPhone to make easy payments by just touching the home button. (Optional)
  2. Sign in to iCloud on iPhone with your actual account.
  3. In iPhone > Settings > General > Language & Region, select your region.
  4. Add a credit card by scanning it or entering the card details manually.
  5. Select the card just added, click on "i" icon at the bottom, and enter Info > Billing Address for the card.
  6. In iPhone > Settings > Wallet & Apple Pay, set Default Card, Shipping Address, Email, and Phone.

In your iPhone, open Safari and run your application on HTTPS. You should see a working "Apple Pay" button there. Click the button and complete payment through touch ID or passcode.

Back to Top

Extract payment token from Apple Pay response

Apple Pay JSON response

Below is the sample Apple Pay JSON response:

payment = {"token"=>{"paymentData"=>{"version"=>"EC_v1", "data"=>"VsVvw2VCOaMa11WYJthb/MpAifih9wk2fqPU6FxJRrrCainBOPKjtW4mIBpnK0U/3BH+B3CA/j8yyoCuBUj900JyhyhGnyHP0vkz5iEO1rxEnjviJUkDktox8V8S9tOspjKssQ7yr6RlcjJA5P4Bj6GMgE+l+okFaKD1NRquMpRvi1MoplxYeX7KHDKsGQyRSgtY5zc/yvE3WHltcBnNpZlgJ995ACyuXAkcll75TGF+Qn+TY/9E//4QizZ+cRVjRYMRq19rWhtp2gW6stRuXy75SWefMwyLxl6tZaum2CGvQrijRfzzA5JYQr+vTEuMmr5mhm7AIIwnwapV272QRIYSOOI1L7c09xdTwKrDm8HbD+S3jo3TFgPktA64e9RtuEm1ream6BQM+5mP", "signature"=>"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", "header"=>{"ephemeralPublicKey"=>"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6jY12R9PoL7bzaC3/ibs6q6+g/cqjSkiO3GVFld2NVUA6kRlq0iJRT+XzfmGFvRs/G2qwgmWY8fKu7p6Ktgxug==", "publicKeyHash"=>"AJiEM3d+czut7s1t4QdtRBPjSOxw0D6iWSp1MUdXueM=", "transactionId"=>"f8f0c804922303decba1a8a4f7c503df1a6314e44e8db5ae7eb6b7fe0323513b"}}, "paymentMethod"=>{"displayName"=>"MasterCard 1471", "network"=>"MasterCard", "type"=>"debit"}, "transactionIdentifier"=>"F8F0C804922303DECBA1A8A4F7C503DF1A6314E44E8DB5AE7EB6B7FE0323513B"}}

Install gems

We are using gala and aead for decrypting the JSON response returned by Apple Pay.

# Gemfile
gem 'gala', '~> 0.3.1'
gem 'aead', git: 'https://github.com/Shopify/aead.git', ref: '340e7718d8bd9c1fcf3c443e32f439436ea2b70d'

Run bundle install.

Please see this if you face any errors installing above gems.

Decrypt response

require 'gala'

payment_token = ::Gala::PaymentToken.new(payment['token']['paymentData'])
=> #<Gala::PaymentToken:0x007feb6c73f2d0 @version="EC_v1", @data="VsVvw2VCOaMa11WYJthb/MpAifih9wk2fqPU6FxJRrrCainBOPKjtW4mIBpnK0U/3BH+B3CA/j8yyoCuBUj900JyhyhGnyHP0vkz5iEO1rxEnjviJUkDktox8V8S9tOspjKssQ7yr6RlcjJA5P4Bj6GMgE+l+okFaKD1NRquMpRvi1MoplxYeX7KHDKsGQyRSgtY5zc/yvE3WHltcBnNpZlgJ995ACyuXAkcll75TGF+Qn+TY/9E//4QizZ+cRVjRYMRq19rWhtp2gW6stRuXy75SWefMwyLxl6tZaum2CGvQrijRfzzA5JYQr+vTEuMmr5mhm7AIIwnwapV272QRIYSOOI1L7c09xdTwKrDm8HbD+S3jo3TFgPktA64e9RtuEm1ream6BQM+5mP", @signature="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", @transaction_id="f8f0c804922303decba1a8a4f7c503df1a6314e44e8db5ae7eb6b7fe0323513b", @ephemeral_public_key="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6jY12R9PoL7bzaC3/ibs6q6+g/cqjSkiO3GVFld2NVUA6kRlq0iJRT+XzfmGFvRs/G2qwgmWY8fKu7p6Ktgxug==", @public_key_hash="AJiEM3d+czut7s1t4QdtRBPjSOxw0D6iWSp1MUdXueM=", @application_data=nil>

cert = Rails.root.join('path', 'to', 'apple_pay.cer').read
=> "0\x82\u0004t0\x82\u0004\u0019\xA0\u0003\u0002...\xB3\u000F\xF0\b\xAE;\xF1j\u000Fʴ\xC8@\xC7"

pem = Rails.root.join('path', 'to', 'payment_processing_certificate.key.pem').read
=> "Bag Attributes\n    friendlyName: TODO_PAYMENT_CSR_0728\n    localKeyID: 51 61 60 E5 2F 38 ... FB 6E A8 17 DC 4E \nKey Attributes: <No Attributes>\n-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEILXPhijAztJ0l4zleKgTy1fSh2undI60AEUKc...+ZwK4YlMSmRkQ9swCKyRdjAs3vU6AXC+F8bA==\n-----END EC PRIVATE KEY-----\n"

data = payment_token.decrypt(cert, pem)
=> "{\"applicationPrimaryAccountNumber\":\"5204242750270010\",\"applicationExpirationDate\":\"190731\",\"currencyCode\":\"392\",\"transactionAmount\":346,\"deviceManufacturerIdentifier\":\"050110030273\",\"paymentDataType\":\"3DSecure\",\"paymentData\":{\"onlinePaymentCryptogram\":\"AK5g1Zu5CPm7AAV8DSTlAoABFA==\"}}"

JSON.parse(data)
=> {"applicationPrimaryAccountNumber"=>"5204242750270010", "applicationExpirationDate"=>"190731", "currencyCode"=>"392", "transactionAmount"=>346, "deviceManufacturerIdentifier"=>"050110030273", "paymentDataType"=>"3DSecure", "paymentData"=>{"onlinePaymentCryptogram"=>"AK5g1Zu5CPm7AAV8DSTlAoABFA=="}}

Back to Top

Make payment on GMO

Install gem

# Gemfile
gem 'gmo', github: 'JagdeepSingh/gmo-payment-ruby', branch: 'add-brandtoken-methods'

Run bundle install.

EntryTranBrandtoken.idPass

Build ShopAPI instance.

gmo_shop = GMO::Payment::ShopAPI.new(host: 'p01.mul-pay.jp', shop_id: SHOP_ID, shop_pass: SHOP_PASSWORD)

For test environment, use host 'kt01.mul-pay.jp'.

entry_tran_response = gmo_shop.entry_tran_brandtoken(order_id: 'ord10001',
                                                     job_cd: 'CAPTURE',
                                                     amount: 1000)
=> {"AccessID"=>"139f8ec33a07c55f406937c52ce4473d", "AccessPass"=>"2689b204d2c17192fa35f9269fa7e744"}

ExecTranBrandtoken.idPass

Sample Apple Pay JSON response.

payment = {"token"=>{"paymentData"=>{"version"=>"EC_v1", "data"=>"VsVvw2VCOaMa11WYJthb/MpAifih9wk2fqPU6FxJRrrCainBOPKjtW4mIBpnK0U/3BH+B3CA/j8yyoCuBUj900JyhyhGnyHP0vkz5iEO1rxEnjviJUkDktox8V8S9tOspjKssQ7yr6RlcjJA5P4Bj6GMgE+l+okFaKD1NRquMpRvi1MoplxYeX7KHDKsGQyRSgtY5zc/yvE3WHltcBnNpZlgJ995ACyuXAkcll75TGF+Qn+TY/9E//4QizZ+cRVjRYMRq19rWhtp2gW6stRuXy75SWefMwyLxl6tZaum2CGvQrijRfzzA5JYQr+vTEuMmr5mhm7AIIwnwapV272QRIYSOOI1L7c09xdTwKrDm8HbD+S3jo3TFgPktA64e9RtuEm1ream6BQM+5mP", "signature"=>"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", "header"=>{"ephemeralPublicKey"=>"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6jY12R9PoL7bzaC3/ibs6q6+g/cqjSkiO3GVFld2NVUA6kRlq0iJRT+XzfmGFvRs/G2qwgmWY8fKu7p6Ktgxug==", "publicKeyHash"=>"AJiEM3d+czut7s1t4QdtRBPjSOxw0D6iWSp1MUdXueM=", "transactionId"=>"f8f0c804922303decba1a8a4f7c503df1a6314e44e8db5ae7eb6b7fe0323513b"}}, "paymentMethod"=>{"displayName"=>"MasterCard 1471", "network"=>"MasterCard", "type"=>"debit"}, "transactionIdentifier"=>"F8F0C804922303DECBA1A8A4F7C503DF1A6314E44E8DB5AE7EB6B7FE0323513B"}}
require 'base64'

payment_token = Base64.encode64(payment['token']['paymentData'].to_json)

gmo_shop.exec_tran_brandtoken(order_id: 'ord10001',
                              access_id: entry_tran_response['AccessID'],
                              access_pass: entry_tran_response['AccessPass'],
                              token_type: :apple_pay,
                              token: payment_token)
=> {"Status"=>"CAPTURE", "OrderID"=>"597ae8c36120b23a3c00014e", "Forward"=>"2a99663", "Approve"=>"5487394", "TranID"=>"1707281634111111111111771216", "TranDate"=>"20170728163453", "ClientField1"=>"", "ClientField2"=>"", "ClientField3"=>""}

In test environment, use Base64 ecnoded version of below tokens instead of actual token returned by Apple:

# Settlement OK / MASTER brand
{"header"=>{"ephemeralPublicKey"=>"testPublicKey", "publicKeyHash"=>"testKeyHash", "transactionId"=>"testTransaction"}, "data"=>"eyJhcHBsaWNhdGlvblByaW1hcnlBY2NvdW50TnVtYmVyIjogIjUxMTExMTExMTExMTExMTEiLCAiYXBwbGljYXRpb25FeHBpcmF0aW9uRGF0ZSI6ICIyMjEyMzEiLCAiY3VycmVuY3lDb2RlIjoiMzkyIiwgInRyYW5zYWN0aW9uQW1vdW50IjoiMTAwMCIsICJjYXJkaG9sZGVyTmFtZSI6ICIiLCAiZGV2aWNlTWFudWZhY3R1cmVySWRlbnRpZmllciI6ICIiLCAicGF5bWVudERhdGFUeXBlIjoiM0RTZWN1cmUiLCAicGF5bWVudERhdGEiOiB7ICAgICJvbmxpbmVQYXltZW50Q3J5cHRvZ3JhbSI6ICJEdW1teUNBVlZBQUFBQUFBQUFBQUFBQUFBQUFBIiwgICAgImVjaUluZGljYXRvciIgOiAiMDUiICB9fQo=", "signature"=>"testSignature", "version"=>"Mock"}

# Settlement OK / JCB brand
{"header"=>{"ephemeralPublicKey"=>"testPublicKey", "publicKeyHash"=>"testKeyHash", "transactionId"=>"testTransaction"}, "data"=>"ewogImFwcGxpY2F0aW9uUHJpbWFyeUFjY291bnROdW1iZXIiOiAiMzExMTExMTExMTExMTExMSIsCiAiYXBwbGljYXRpb25FeHBpcmF0aW9uRGF0ZSI6ICIyMjEyMzEiLAogImN1cnJlbmN5Q29kZSI6IjM5MiIsCiAidHJhbnNhY3Rpb25BbW91bnQiOiIxMDAwIiwKICJjYXJkaG9sZGVyTmFtZSI6ICIiLAogImRldmljZU1hbnVmYWN0dXJlcklkZW50aWZpZXIiOiAiIiwKICJwYXltZW50RGF0YVR5cGUiOiIzRFNlY3VyZSIsIAogInBheW1lbnREYXRhIjogewogICJvbmxpbmVQYXltZW50Q3J5cHRvZ3JhbSI6ICJEdW1teUNBVlZBQUFBQUFBQUFBQUFBQUFBQUFBIiwKICAiZWNpSW5kaWNhdG9yIiA6ICIwNSIKICB9Cn0K", "signature"=>"testSignature", "version"=>"Mock"}

# Settlement OK / AMEX brand
{"header"=>{"ephemeralPublicKey"=>"testPublicKey", "publicKeyHash"=>"testKeyHash", "transactionId"=>"testTransaction"}, "data"=>"ewogImFwcGxpY2F0aW9uUHJpbWFyeUFjY291bnROdW1iZXIiOiAiMzc1OTg3MDAwMDAwMDYyIiwKICJhcHBsaWNhdGlvbkV4cGlyYXRpb25EYXRlIjogIjIyMTIzMSIsCiAiY3VycmVuY3lDb2RlIjoiMzkyIiwKICJ0cmFuc2FjdGlvbkFtb3VudCI6IjEwMDAiLAogImNhcmRob2xkZXJOYW1lIjogIiIsCiAiZGV2aWNlTWFudWZhY3R1cmVySWRlbnRpZmllciI6ICIiLAogInBheW1lbnREYXRhVHlwZSI6IjNEU2VjdXJlIiwgCiAicGF5bWVudERhdGEiOiB7CiAgIm9ubGluZVBheW1lbnRDcnlwdG9ncmFtIjogIkR1bW15Q0FWVkFBQUFBQUFBQUFBQUFBQUFBQUEiLAogICJlY2lJbmRpY2F0b3IiIDogIjA1IgogIH0KfQo=", "signature"=>"testSignature", "version"=>"Mock"}

# Settlement OK / VISA brand
{"header"=>{"ephemeralPublicKey"=>"testPublicKey", "publicKeyHash"=>"testKeyHash", "transactionId"=>"testTransaction"}, "data"=>"ewogImFwcGxpY2F0aW9uUHJpbWFyeUFjY291bnROdW1iZXIiOiAiNDExMTExMTExMTExMTExMSIsCiAiYXBwbGljYXRpb25FeHBpcmF0aW9uRGF0ZSI6ICIyMjEyMzEiLAogImN1cnJlbmN5Q29kZSI6IjM5MiIsCiAidHJhbnNhY3Rpb25BbW91bnQiOiIxMDAwIiwKICJjYXJkaG9sZGVyTmFtZSI6ICIiLAogImRldmljZU1hbnVmYWN0dXJlcklkZW50aWZpZXIiOiAiIiwKICJwYXltZW50RGF0YVR5cGUiOiIzRFNlY3VyZSIsIAogInBheW1lbnREYXRhIjogewogICJvbmxpbmVQYXltZW50Q3J5cHRvZ3JhbSI6ICJEdW1teUNBVlZBQUFBQUFBQUFBQUFBQUFBQUFBIiwKICAiZWNpSW5kaWNhdG9yIiA6ICIwNSIKICB9Cn0K", "signature"=>"testSignature", "version"=>"Mock"}

# Settlement NG / MASTER brand
{"header"=>{"ephemeralPublicKey"=>"testPublicKey", "publicKeyHash"=>"testKeyHash", "transactionId"=>"testTransaction"}, "data"=>"ewogImFwcGxpY2F0aW9uUHJpbWFyeUFjY291bnROdW1iZXIiOiAiNTk5OTAwMDAwMDAwMDAwMSIsCiAiYXBwbGljYXRpb25FeHBpcmF0aW9uRGF0ZSI6ICIyMjEyMzEiLAogImN1cnJlbmN5Q29kZSI6IjM5MiIsCiAidHJhbnNhY3Rpb25BbW91bnQiOiIxMDAwIiwKICJjYXJkaG9sZGVyTmFtZSI6ICIiLAogImRldmljZU1hbnVmYWN0dXJlcklkZW50aWZpZXIiOiAiIiwKICJwYXltZW50RGF0YVR5cGUiOiIzRFNlY3VyZSIsIAogInBheW1lbnREYXRhIjogewogICJvbmxpbmVQYXltZW50Q3J5cHRvZ3JhbSI6ICJEdW1teUNBVlZBQUFBQUFBQUFBQUFBQUFBQUFBIiwKICAiZWNpSW5kaWNhdG9yIiA6ICIwNSIKICB9Cn0K", "signature"=>"testSignature", "version"=>"Mock"}

Convert above tokens to JSON using to_json and then call Base64.encode64 on them before passing in "ExecTranBrandtoken.idPass" request. All these tokens are available in a yml file here.

Back to Make payment on GMO

Back to Top

Convert certificate to pem

  1. Double-click on the ".cer" file to install in Keychain Access.
  2. Locate the certificate in Keychain Access. Right-click on it and select Export ....
  3. Select the location to save ".p12" file and click Continue.
  4. When prompted to set password, do NOT set any, and click Continue.
  5. Grant access and click Continue. You will have a ".p12" file now with the certificate and its secret key.
  6. Now, open the terminal and run openssl pkcs12 -in path/to/p12/file -out Certificate.key.pem -nocerts -nodes. When prompted to enter Import password, leave it blank. This will generate a Certificate.key.pem file. Check the name of output file carefully so that it does not over-write any existing certificate.

Back to Top

Extra

Error installing gala and aead

If you see below error while installing gala and aead:

Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    /Users/vinsol/.rvm/rubies/ruby-2.1.3/bin/ruby extconf.rb
checking for openssl/ssl.h... no
checking for SSLv23_method() in -lssl... yes
creating Makefile

make "DESTDIR=" clean

make "DESTDIR="
compiling aead.c
aead.c:2:10: fatal error: 'openssl/ssl.h' file not found
#include <openssl/ssl.h>
         ^
1 error generated.
make: *** [aead.o] Error 1

make failed, exit code 2

Gem files will remain installed in /Users/vinsol/.rvm/gems/ruby-2.1.3/gems/aead-1.8.1 for inspection.
Results logged to /Users/vinsol/.rvm/gems/ruby-2.1.3/extensions/x86_64-darwin-14/2.1.0-static/aead-1.8.1/gem_make.out

An error occurred while installing aead (1.8.1), and Bundler cannot continue.
Make sure that `gem install aead -v '1.8.1'` succeeds before bundling.

Follow below steps:

$ brew update
$ brew install openssl
$ bundle config build.aead --with-cppflags=-I$(brew --prefix openssl)/include
$ bundle install

Back to Extra

Back to Top

Test tokens for making payments on GMO

---
  :applepay:
    :token:
      :mastercard:
        header: &HEADER
          ephemeralPublicKey: &TEST_PUBLIC_KEY testPublicKey
          publicKeyHash: &TEST_KEY_HASH testKeyHash
          transactionId: &TEST_TRANSACTION testTransaction
        data: 'eyJhcHBsaWNhdGlvblByaW1hcnlBY2NvdW50TnVtYmVyIjogIjUxMTExMTExMTExMTExMTEiLCAiYXBwbGljYXRpb25FeHBpcmF0aW9uRGF0ZSI6ICIyMjEyMzEiLCAiY3VycmVuY3lDb2RlIjoiMzkyIiwgInRyYW5zYWN0aW9uQW1vdW50IjoiMTAwMCIsICJjYXJkaG9sZGVyTmFtZSI6ICIiLCAiZGV2aWNlTWFudWZhY3R1cmVySWRlbnRpZmllciI6ICIiLCAicGF5bWVudERhdGFUeXBlIjoiM0RTZWN1cmUiLCAicGF5bWVudERhdGEiOiB7ICAgICJvbmxpbmVQYXltZW50Q3J5cHRvZ3JhbSI6ICJEdW1teUNBVlZBQUFBQUFBQUFBQUFBQUFBQUFBIiwgICAgImVjaUluZGljYXRvciIgOiAiMDUiICB9fQo='
        signature: &TEST_SIGNATURE testSignature
        version: &MOCK Mock

      :jcb:
        header: *HEADER
        data: 'ewogImFwcGxpY2F0aW9uUHJpbWFyeUFjY291bnROdW1iZXIiOiAiMzExMTExMTExMTExMTExMSIsCiAiYXBwbGljYXRpb25FeHBpcmF0aW9uRGF0ZSI6ICIyMjEyMzEiLAogImN1cnJlbmN5Q29kZSI6IjM5MiIsCiAidHJhbnNhY3Rpb25BbW91bnQiOiIxMDAwIiwKICJjYXJkaG9sZGVyTmFtZSI6ICIiLAogImRldmljZU1hbnVmYWN0dXJlcklkZW50aWZpZXIiOiAiIiwKICJwYXltZW50RGF0YVR5cGUiOiIzRFNlY3VyZSIsIAogInBheW1lbnREYXRhIjogewogICJvbmxpbmVQYXltZW50Q3J5cHRvZ3JhbSI6ICJEdW1teUNBVlZBQUFBQUFBQUFBQUFBQUFBQUFBIiwKICAiZWNpSW5kaWNhdG9yIiA6ICIwNSIKICB9Cn0K'
        signature: *TEST_SIGNATURE
        version: *MOCK

      :amex:
        header: *HEADER
        data: 'ewogImFwcGxpY2F0aW9uUHJpbWFyeUFjY291bnROdW1iZXIiOiAiMzc1OTg3MDAwMDAwMDYyIiwKICJhcHBsaWNhdGlvbkV4cGlyYXRpb25EYXRlIjogIjIyMTIzMSIsCiAiY3VycmVuY3lDb2RlIjoiMzkyIiwKICJ0cmFuc2FjdGlvbkFtb3VudCI6IjEwMDAiLAogImNhcmRob2xkZXJOYW1lIjogIiIsCiAiZGV2aWNlTWFudWZhY3R1cmVySWRlbnRpZmllciI6ICIiLAogInBheW1lbnREYXRhVHlwZSI6IjNEU2VjdXJlIiwgCiAicGF5bWVudERhdGEiOiB7CiAgIm9ubGluZVBheW1lbnRDcnlwdG9ncmFtIjogIkR1bW15Q0FWVkFBQUFBQUFBQUFBQUFBQUFBQUEiLAogICJlY2lJbmRpY2F0b3IiIDogIjA1IgogIH0KfQo='
        signature: *TEST_SIGNATURE
        version: *MOCK

      :visa:
        header: *HEADER
        data: 'ewogImFwcGxpY2F0aW9uUHJpbWFyeUFjY291bnROdW1iZXIiOiAiNDExMTExMTExMTExMTExMSIsCiAiYXBwbGljYXRpb25FeHBpcmF0aW9uRGF0ZSI6ICIyMjEyMzEiLAogImN1cnJlbmN5Q29kZSI6IjM5MiIsCiAidHJhbnNhY3Rpb25BbW91bnQiOiIxMDAwIiwKICJjYXJkaG9sZGVyTmFtZSI6ICIiLAogImRldmljZU1hbnVmYWN0dXJlcklkZW50aWZpZXIiOiAiIiwKICJwYXltZW50RGF0YVR5cGUiOiIzRFNlY3VyZSIsIAogInBheW1lbnREYXRhIjogewogICJvbmxpbmVQYXltZW50Q3J5cHRvZ3JhbSI6ICJEdW1teUNBVlZBQUFBQUFBQUFBQUFBQUFBQUFBIiwKICAiZWNpSW5kaWNhdG9yIiA6ICIwNSIKICB9Cn0K'
        signature: *TEST_SIGNATURE
        version: *MOCK

      :error:
        :master:
          header: *HEADER
          data: 'ewogImFwcGxpY2F0aW9uUHJpbWFyeUFjY291bnROdW1iZXIiOiAiNTk5OTAwMDAwMDAwMDAwMSIsCiAiYXBwbGljYXRpb25FeHBpcmF0aW9uRGF0ZSI6ICIyMjEyMzEiLAogImN1cnJlbmN5Q29kZSI6IjM5MiIsCiAidHJhbnNhY3Rpb25BbW91bnQiOiIxMDAwIiwKICJjYXJkaG9sZGVyTmFtZSI6ICIiLAogImRldmljZU1hbnVmYWN0dXJlcklkZW50aWZpZXIiOiAiIiwKICJwYXltZW50RGF0YVR5cGUiOiIzRFNlY3VyZSIsIAogInBheW1lbnREYXRhIjogewogICJvbmxpbmVQYXltZW50Q3J5cHRvZ3JhbSI6ICJEdW1teUNBVlZBQUFBQUFBQUFBQUFBQUFBQUFBIiwKICAiZWNpSW5kaWNhdG9yIiA6ICIwNSIKICB9Cn0K'
          signature: *TEST_SIGNATURE
          version: *MOCK

Back to Extra

Back to Top

@rhiannanb
Copy link

Hi, I'm trying to do a proof of concept for Apple Pay using ngrok, and am having trouble with validating my site--the url they're looking for is 100% reachable, and using ngrok's validated certificate, yet Apple is claiming the domain certificate is untrusted. What settings did you use when setting up your tunnel? Thanks!

@jagdeepsingh
Copy link
Author

jagdeepsingh commented Jun 3, 2019

Hi @rhiannanb. Sorry I am sooooo late in replying. Missed this thread somehow. I set up ngrok the most basic way. No configurations. Just installed it and ran ngrok http localhost:3000.

@pushpendra2011
Copy link

Hi Jagdeep,

Your instructions for creating apple dev account ready for apple pay was really helpful. I am able to verify my domain and both certificates have been created for payment processing and merchant ID.

However, I am having a hard time implementing the coding part. I wish to only use JavaScript, HTML, and CSS for the transaction. Is it possible to do so? If yes, can u guide us on how we can acheive the results? Thanks for ur time for writing elaborated guide on the implementing of apple pay on web.

@jagdeepsingh
Copy link
Author

Hi @Pushpendra92, glad that i was helpful. Unfortunately, this is all that i worked on Apple Pay. I switched to different projects after implementing this.

Good luck with your code. :)

@hassanuos
Copy link

hassanuos commented Feb 17, 2021

@Pushpendra92 I hope it could help you. I integrate that with PayFort And I am hoping it will help you. @jagdeepsingh Sardar Ji already provides this below coding. You just follow the extended code that ajax requests will go to your payment gateway with token: event.payment.token, and take you can see I give the URL in the ajax request. This ajax all data will go to your payment gateway CURL request of your payment gateway and return response either false or true. So based on that you need to show the message on your device.

`session.onpaymentauthorized = (event) => {

    $("#paymentMethodVal").val("apple-pay");

    // You can see a sample `payment` object in the image below.
    // Use the token returned in the `payment` object to create the charge on your payment gateway.
    $form = $("#reservation-form");
    console.log($form.serialize());
    callRequest({
        url: '/reserve/init-apple-pay',
        method: 'POST',
        data: {
            token: event.payment.token,
            reservationData: $form.serialize()
        },
        beforeRequest: function(e) {},
        afterRequest: function(response) {
            response = JSON.parse(response);
            if(response.status){
               toastr.success(response.message);
               session.completePayment(ApplePaySession.STATUS_SUCCESS);
            }else{
                toastr.error(response.message.split(/\r\n|\r|\n/g).join('<br/>'));
                session.completePayment(ApplePaySession.STATUS_FAILURE);
            }
        }
    });
};`

@jagdeepsingh thank you sir it was the great code poetry :).

If you still not understand. Here the steps are explained in deep detail.

https://github.com/norfolkmustard/ApplePayJS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment