web 端对接 applepay

2022-11-27  本文已影响0人  别闹__

这方面国内的文档很少,也踩了不少的坑,今天有空记录一下

  1. 准备工作,商户配置,沙盒测试账号配置,需要在applepay 开发者 官网中配置,测试卡号也需要使用官方的沙盒 测试账号;
  2. 需要将官网的证书下载下来,一同放到服务器,证书有过期时间
  3. 前端需要在https 的环境下,才能进行调试,本地调试需要搭建环境,nginx 之类的进行转发

直接上前端代码

import PropTypes from 'prop-types';
import { useEffect, useState } from 'react';
import scriptLoader from 'react-async-script-loader';
import { useSelector } from 'react-redux';

// 这是后端提供的一个接口,获取applepay的token,需要拿到这个token 做鉴权;
import getApplePaySession from 'services/controller/checkout/getApplePaySession';

import { ButtonWrapper } from './ApplePayButton.style';

let applePayPayment = {};

function ApplyPayButton({
  isScriptLoaded,
  isScriptLoadSucceed,
  onSave,
  initiateResponse = {},
}) {
  const [showButton, setShowButton] = useState(false);
  const ckeckoutUpdate = {
    newTotal: {
      label: 'demo',
      amount:totalToPay,
    },
    newLineItems: [
      {
        label: 'Product Amount',
        amount:productAmount,
      },
      {
        label: 'Shipping Fee',
        amount: shippingFee,
      },
      {
        label: 'Tax',
        amount: totalTax,
      },
    ],
  };

  function onApplePayButtonClicked() {
    try {
      const request = {
        countryCode:  '',
        currencyCode: '',
        merchantCapabilities: [],
        supportedNetworks:  [],
        total: {
          label: label,
          type: 'final',
          amount: totalToPay,
        },
      };
      console.log('apple payment request', request);
      console.log('storeInfo', storeInfo);
      // Create ApplePaySession
      // eslint-disable-next-line no-undef
      const session = new ApplePaySession(3, request);

      session.onvalidatemerchant = async (event) => {
        console.log('event', event);
        // Call your own server to request a new merchant session.
        const hostName = window.location.host;
        const merchantSession = await getApplePaySession(
          applePayConfig,
          event.validationURL,
          hostName
        );
        console.log('merchantSession', merchantSession);
        session.completeMerchantValidation(merchantSession);
      };

      session.onpaymentmethodselected = (event) => {
        console.log('paymentChange', event);
        // Define ApplePayPaymentMethodUpdate based on the selected payment method.
        // No updates or errors are needed, pass an empty object.
        session.completePaymentMethodSelection(ckeckoutUpdate);
      };

      session.onshippingmethodselected = (event) => {
        console.log('shippingMethodChange', event);
        // Define ApplePayShippingMethodUpdate based on the selected shipping method.
        session.completeShippingMethodSelection(ckeckoutUpdate);
      };

      session.onshippingcontactselected = (event) => {
        console.log('onshippingcontactselected', event);
        // Define ApplePayShippingContactUpdate based on the selected shipping contact.
        session.completeShippingContactSelection(ckeckoutUpdate);
      };

      session.onpaymentauthorized = (event) => {
        const billingAddressInfo = {
          countryId:  'US',
          zipCode: '',
          city:  '',
          lastName:  '',
          state:  '',
          firstName:  '',
          addressLine2:  '',
          addressLine1: '',
        };

        console.log('Success1', event.payment);
        // eslint-disable-next-line no-undef
        console.log('SuccessStatus', ApplePaySession.STATUS_SUCCESS);
        const result = {
          // eslint-disable-next-line no-undef
          status: ApplePaySession.STATUS_SUCCESS,
        };
        applePayPayment = {
          applePayEncryptedPaymentBundle: {
            data: event.payment?.token.paymentData?.data,
            signature: event.payment?.token.paymentData.signature,
            header: event.payment?.token.paymentData.header,
            protocolVersion: event.payment?.token.paymentData.version,
          },
          digitalWalletType: 'ApplePay',
          digitalWalletLatitudeLongitude: '1,1',
          cardType:
            event.payment?.token?.paymentMethod?.network === 'AmEx'
              ? 'Amex'
              : event.payment?.token?.paymentMethod?.network,
          billingAddressInfo,
        };
        console.log('applyPayPayment', applePayPayment);
        onSave(applePayPayment);
        session.completePayment(result);
      };

      session.oncancel = (event) => {
        // Payment cancelled by WebKit
        console.log('cancel', event);
      };

      session.begin();
    } catch (e) {
      console.log('error', e);
    }
  }

  useEffect(() => {
    if (isScriptLoaded && isScriptLoadSucceed) {
      // eslint-disable-next-line no-undef
      if (window.ApplePaySession && ApplePaySession.canMakePayments) {
        setShowButton(true);
      }
      //   onApplePayButtonClicked();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [isScriptLoadSucceed, isScriptLoaded]);

  return (
    <ButtonWrapper>
      {showButton && (
        <>
          <button
            onClick={onApplePayButtonClicked}
            type='button'
            label
            className='apple-pay-button'
            style={{ width: '293px', height: '50px' }}
          />
        </>
      )}
    </ButtonWrapper>
  );
}

ApplyPayButton.defaultProps = {
  isScriptLoaded: false,
  isScriptLoadSucceed: false,
};

ApplyPayButton.propTypes = {
  onSave: PropTypes.func.isRequired,
  isScriptLoaded: PropTypes.bool,
  isScriptLoadSucceed: PropTypes.bool,
  initiateResponse: PropTypes.func,
};

export default scriptLoader(['https://applepay.cdn-apple.com/jsapi/v1/apple-pay-sdk.js'])(
  ApplyPayButton
);

代码基本都是官网的代码,这个比官网看的更直接一点;

  1. window.ApplePaySession && ApplePaySession.canMakePayments 判断浏览器是否支持
  2. getApplePaySession 这个是自己封装的方法,核心代码就是调用后端接口,取回数据,数据结构applepay 官网有,返回一样的结构体就行
上一篇下一篇

猜你喜欢

热点阅读