GithubHelp home page GithubHelp logo

martina6hall / appr-wrapper Goto Github PK

View Code? Open in Web Editor NEW

This project forked from opportunitylivetv/appr-wrapper

1.0 3.0 0.0 87 KB

Payment Request wrapper for Apple Pay JS

Home Page: https://web-payment-apis.appspot.com

License: Apache License 2.0

JavaScript 20.94% TypeScript 79.06%

appr-wrapper's Introduction

appr-wrapper: Payment Request wrapper for Apple Pay JS

"appr-wrapper" wraps Apple Pay JS and allows you to write Payment Request API code to use the API.

Try a demo from Safari on iOS and Chrome for Android. See that it works on both platforms in a single code base.

Build the code

The repo comes with a build script (./dist/appr.js) but in case you want to build one yourself, follow this instruction:

Clone the repo

git clone [email protected]:GoogleChrome/appr-wrapper.git

Pull dependencies

npm install

Build the code

npm run build

Try the demo on your own server

To try the demo on your own server, you need to go through Apple Pay JS merchant registration process. Follow Apple's instructions and setup yours. There are 3 things required:

  • Verify your domain by putting a file you can obtain from Apple named apple-developer-merchantid-domain-association in ./demo/well-known folder.
  • Put your merchant identity certificate to ./certs directory with a name apple-pay-cert.pem at project's root.
  • Modify ./demo.js and replace params with your own configuration: APPLE_PAY_CERTIFICATE_PATH, MERCHANT_IDENTIFIER, MERCHANT_DOMAIN, MERCHANT_DISPLAY_NAME

One the set up is done, run the server:

npm run serve

How to use

./dist/appr.js will be the code to import. You can either load it from script tag or import it via module loader.

<script src="./scripts/appr.js"></script>

 

import PaymentRequest from './appr.js';

Then, simply implement Payment Request API following the standard. You can handle Apple Pay JS by adding a payment method specifying "https://apple.com/apple-pay" as following example:

let method = [{
  supportedMethods: ['https://apple.com/apple-pay'],
  data: {
    supportedNetworks: [
      'amex', 'discover', 'masterCard', 'visa'
    ],
    countryCode: 'US',
    validationEndpoint: '/applepay/validate/',
    merchantIdentifier: 'merchant.com.agektmr.payment'
  }
}];

let details = {
  displayItems: [{
    label: 'Original donation amount',
    amount: { currency: 'USD', value: '0.01' }
  }],
  shippingOptions: [{
    id: 'standard',
    label: 'Standard shipping',
    amount: { currency: 'USD', value: '0.01' }
  }, {
    id: 'express',
    label: 'Express shipping',
    amount: { currency: 'USD', value: '0.99' }
  }],
  total: {
    label: 'Total due',
    amount: { currency: 'USD', value : '0.01' }
  }
};

let options = {
  requestShipping: true,
  requestPayerEmail: true,
  requestPayerPhone: true,
  requestPayerName: true,
  shippingType: 'shipping'
};

let request = new PaymentRequest(methods, details, options);
let response;

request.addEventListener('shippingaddresschange', e => {
  e.updateWith(new Promise(resolve => {
    let result;
    let addr = request.shippingAddress;
    let price = new priceCalc(details);
    if (addr.country.toUpperCase() === 'US') {
      result = price.selectShippingOption('standard');
    } else if (addr.country.toUpperCase() === 'JP') {
      result = price.selectShippingOption('express');
    } else {
      details.shippingOptions = [];
      resolve(details);
      return;
    }
    resolve(result);
  }));
});

request.addEventListener('shippingoptionchange', e => {
  e.updateWith(new Promise(resolve => {
    let calc = new priceCalc(details);
    let result = calc.selectShippingOption(request.shippingOption);
    resolve(result);
  }));
});

request.show().then(result => {
  if (response.methodName === 'https://apple.com/apple-pay') {
    // Apple Pay JS case
    // Do whatever you need to do with the token:
    // `response.applePayRaw`
  } else {
    // Everything else will be pure Payment Request API response
  }
}).then(response => {
  response.complete('success');
}).catch(e => {
  if (e) {
    alert(`Could not make payment: ${e}`);
  }
  if (response) {
    response.complete('fail');
  }
});

Payment method properties

The first argument to the PaymentRequest constructor.

  • supportedNetworks is required.
  • data:
    • countryCode is required.
    • billingContact is optional.
    • shippingContact is optional. It allows you to provide default shipping contact information in Apple Pay JS.
    • merchantCapabilities defaults to ['supports3DS'] unless you provide any.
    • validationEndpoint is optional. Specify the merchant validation endpoint on your server. If you omit this, handle validatemerchant event yourself.
    • merchantIdentifier is required. Specify your merchant id.

With validationEndpoint, appr-wrapper automatically handles validatemerchant event for you. On your server's specified endpoint, you'll receive a POST request with validationURL, so you can validate yourself and respond with a merchant session object returned following these instructions. You can optionally handle the validatemerchant event by yourself by adding an event handler.

let method = [{
  supportedMethods: ['https://apple.com/apple-pay'],
  data: {
    supportedNetworks: [
      'amex', 'discover', 'masterCard', 'visa'
    ],
    countryCode: 'US',
    validationEndpoint: '/applepay/validate/',
    merchantIdentifier: 'merchant.com.agektmr.payment'
  }
}];

Payment details properties

The second argument to the PaymentRequest constructor.

  • The total.amount.currency is converted to currencyCode in Apple Pay JS.
let details = {
  displayItems: [{
    label: 'Original donation amount',
    amount: { currency: 'USD', value: '0.01' }
  }],
  shippingOptions: [{
    id: 'standard',
    label: 'Standard shipping',
    amount: { currency: 'USD', value: '0.01' }
  }, {
    id: 'express',
    label: 'Express shipping',
    amount: { currency: 'USD', value: '0.99' }
  }],
  total: {
    label: 'Total due',
    amount: { currency: 'USD', value : '0.01' }
  }
};

Let's look into what each parameters convert to, one by one.

Payment options properties

The third argument to the PaymentRequest constructor.

  • requestPayerEmail, requestPayerPhone, requestPayerName are respectively converted to requireBillingContactFields and requireShippingContactFields values in Apple Pay JS.
  • pickup in shippingType will be converted to servicePickup in Apple Pay JS. Others are handled as they are.
let options = {
  requestShipping: true,
  requestPayerEmail: true,
  requestPayerPhone: true,
  requestPayerName: true,
  shippingType: 'shipping'
};

canMakePayment()

canMakePayment() will invoke canMakePaymentsWithActiveCard() in Apple Pay JS.

request.canMakePayment().then(result => {
  if (result) {
    return request.show();
  } else {
    // fallback to checkout form or start setting up ApplePayJS
  }
});

Shipping contact selected event / shipping method selected event

You can handle

request.addEventListener('shippingaddresschange', e => {
  e.updateWith(new Promise(resolve => {
    let result;
    let addr = request.shippingAddress;
    let price = new priceCalc(details);
    if (addr.country.toUpperCase() === 'US') {
      result = price.selectShippingOption('standard');
    } else if (addr.country.toUpperCase() === 'JP') {
      result = price.selectShippingOption('express');
    } else {
      details.shippingOptions = [];
      resolve(details);
      return;
    }
    resolve(result);
  }));
});

request.addEventListener('shippingoptionchange', e => {
  e.updateWith(new Promise(resolve => {
    let calc = new priceCalc(details);
    let result = calc.selectShippingOption(request.shippingOption);
    resolve(result);
  }));
});

Handling payment response

Once show() resolves, you will recive an object which is slightly different from actual PaymentResponse object. Equivalent to this resolution is paymentauthorized event where you will receive an event object that contains an ApplePayPayment object in Apple Pay JS.

To determine if the response is for Apple Pay JS, you can examine methodName property of the payment response. If it is "https://apple.com/apple-pay", this is Apple Pay JS. The payment response object is constructed to replicate PaymentResponse as much as possible, but it's not perfect due to technical restrictions. If you prefer using actual payment response from Apple Pay JS API, try applePayRaw property which holds actual ApplePayPayment object.

request.show().then(result => {
  // process payment
  response = result;
  if (response.methodName === 'https://apple.com/apple-pay') {
    // Apple Pay JS case
    // Do whatever you need to do with the token:
    // `response.applePayRaw`
  } else {
    // Everything else will be pure Payment Request API response
  }
}).then(response => {
  response.complete('success');
}).catch(e => {
  if (e) {
    alert(`Could not make payment: ${e}`);
  }
  if (response) {
    response.complete('fail');
  }
});

appr-wrapper's People

Contributors

agektmr avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.