mkharibalaji / react-native-adyen-payment

React Native Adyen Payment
https://mkharibalaji.github.io/react-native-adyen-payment/
MIT License
35 stars 35 forks source link

Question for AdyenPayment.initialize? #76

Open KerryDss opened 2 years ago

KerryDss commented 2 years ago
var appServiceConfigData = {
      environment: 'test',
      base_url: paymentDetails?.baseUrl,
      // additional_http_headers: {
      //   'x-demo-server-api-key': DEMO_SERVER_API_KEY,
      // },
    };
    AdyenPayment.initialize(appServiceConfigData);

In the above code to initialize the app I can't seem to remove or comment out additional_http_headers. Is that a necessary to initialize ? because I am getting this error

Screenshot_1647150413

{
    "merchantName": "Someone",
    "apiKey": "awofjaowiejfaoijewfawejfoawjefaojwefoaijwefoiajwoefiajweoifjaoeiwjfoaijewfoijwefawofejaowefj/awefoijawef",
    "originKey": "apofekwfe",
    "liveUrlPrefix": "",
    "allowSaveCards": true,
    "testMode": true,
    "amountValue": 6910,
    "currency": "SGD",
    "cssUrl": "https://checkoutshopper-test.adyen.com/checkoutshopper/sdk/3.6.3/adyen.css",
    "javascriptUrl": "https://checkoutshopper-test.adyen.com/checkoutshopper/sdk/3.6.3/adyen.js",
    "paymentMethodsResponse": null,
    "checkOutEndPointUrl": "https://checkout-test.adyen.com/v52/paymentMethods",
    "environment": "Test",
    "baseUrl": "https://abc.com/Default.aspx?ID=33&CheckoutHandlerOrderID=CART1593&redirect=false",
    "submitUrl": "https://abc.com/Default.aspx?ID=33&CheckoutHandlerOrderID=CART1593&redirect=false&Action=SelectMethod",
    "additionalUrl": "https://abc.com/Default.aspx?ID=33&CheckoutHandlerOrderID=CART1593&redirect=false&Action=SelectMethod",
    "shopperReference": 0,
    "referenceId": "CART1593",
    "paymentMethodId": "PAY1",
    "name": "Adyen"
}

These are the parameter given to me to test the api. Any help would be really appreciated.Because I am stuck here for 3 days

ChielBruin commented 2 years ago

In my implementation I just send en empty object for the additional_http_headers. I probably did that to prevent this error

KerryDss commented 2 years ago

@ChielBruin Hi I got another question

in my code I write something like this

useEffect(() => {
    var appServiceConfigData = {
      environment: paymentDetails?.environment,
      base_url: 'https://checkout-test.adyen.com/v52/paymentMethods/',
      additional_http_headers: {},
    };
    AdyenPayment.initialize(appServiceConfigData);

    AdyenPayment.onSuccess(payload => {
      console.log('success', payload);
            setStatus(STATUS.success);
    });
    AdyenPayment.onError(payload => {
      console.log('failure', payload);
      setStatus(STATUS.failure);
    });

  }, []);

  useEffect(() => {
    MOCK_PAYMENT_DETAILS = {
      amount: {
        value: paymentDetails?.amountValue,
        currency: paymentDetails?.currency,
      },
      reference: paymentDetails?.referenceId,
      shopperReference: paymentDetails?.shopperReference,
      shopperEmail: 'abc@gmail.com',
      shopperLocale: 'en_SG',
      channel: Platform.OS === 'ios' ? 'iOS' : 'Android',
      countryCode: 'SG',
      // Remember to replace returnUrl with your app scheme
      returnUrl:
        Platform.OS === 'ios' ? 'your-ios-scheme://' : 'com.abc.com',
       merchantAccount: paymentDetails?.merchantName,

      additionalData: {
        allow3DS2: true,
        executeThreeD: true,
      },
    };

    MOCK_COMPONENT_DATA = {
      scheme: {
        card_public_key: paymentDetails?.originKey,
      },
    };
  }, [paymentDetails]);

  function handleDropInButtonPress() {
        setStatus(STATUS.initiated);
    try {
      AdyenPayment.startPayment(
        AdyenPayment.DROPIN,
        MOCK_COMPONENT_DATA,
        MOCK_PAYMENT_DETAILS,
      );
    } catch (err) {
      console.error(err);
    }
  }

What happen is that when I call handleDropInButtonPress func I got an error like this, after dismiss the status does not change into failure is this the correct behaviours?

Here is the error Screenshot_1647234131

ChielBruin commented 2 years ago

The main difference I see with my usage is that I use the async variants of startPayment. Are you sure the value you provide for the merchantAccount is a non-empty string?

KerryDss commented 2 years ago

@ChielBruin Actually I hard coded the merchant account in merchantAccount: "SomeoneAccountNum".

ChielBruin commented 2 years ago

Also not that you define the MOCK_PAYMENT_DETAILS inside a useEffect by re-assigning it to a variable. As far as I know, this will not trigger a React state update. This will mean that when pressing the button, you might still get the original value (which you probably have initialized as null or undefined). This will then result in passing a lot of null/undefined values to the drop-in (due to all the a?.b constructs you used). Instead set the values directly or use a setState() to update it. I would also highly recommend checking for null before calling startPayment instead of defaulting everything to null using the ? operators

KerryDss commented 2 years ago

HI @ChielBruin

I will update my question here.

import AdyenPayment from 'react-native-adyen-payment';

const DEMO_SERVER_API_KEY =
  'DEMO_SERVER API KEY FROM ADYEN DEVELOPERS > API CREDITENTIALS';
const CARD_PUBLIC_KEY = 'CLIENT KEY GENERATED FROM THE ADYEN';
const MERCHANT_ACCOUNT = 'MERCHANT ACC NAME';

import React, {Component} from 'react';
import {Button, View, Text} from 'react-native';
import EStyleSheet from 'react-native-extended-stylesheet';

export default class CartPaymentTwo extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isLoading: false,
      adyen_payment_status: 'initiated',
    };
    /*
    The base URL should be your API server running with the following POST endpoints
     - /paymentMethods
     - /payments
     - /payments/details
     Ex :
     Base URL : https://XXXXXX.com/payments/adyen
     https://XXXXXX.com/payments/adyen/paymentMethods
     https://XXXXXX.com/payments/adyen/payments
     https://XXXXXX.com/payments/adyen/payments/details
     Any Extra Header Parameters to be passed can be given in the "additional_http_headers"
     As an example we are using Adyens Demo Server Base URL
    */
    var appServiceConfigData = {
      environment: 'test',
      // base_url: 'https://checkout-test.adyen.com/checkout/v51/',
      base_url: 'https://checkout-test.adyen.com/v51/',

      additional_http_headers: {
        'x-demo-server-api-key': DEMO_SERVER_API_KEY,
      },
    };
    AdyenPayment.initialize(appServiceConfigData);

    AdyenPayment.onSuccess(payload => {
      this.setState({adyen_payment_status: 'success'});
      console.log(payload);
    });

    AdyenPayment.onError((code, error) => {
      console.log('Adyen Error : ', error);
      this.setState({adyen_payment_status: 'failure'});
    });
  }

  onClickPayment = () => {
    var paymentDetails = {
      amount: {
        value: 200, //In Multiples of hundred
        currency: 'EUR',
      },
      reference: 'XXXXXXXX',
      shopperReference: 'XXXXXX',
      shopperEmail: 'XXXXXXX@XXXX.com',
      channel: Platform.OS === 'ios' ? 'iOS' : 'Android',
      countryCode: 'SG',
      shopperLocale: 'sg_SG',
      returnUrl:
        Platform.OS === 'ios'
          ? '<YourAppDisplayName>-app://'
          : 'adyencheckout://com.dynamicwebapac.bhg',
      merchantAccount: MERCHANT_ACCOUNT,
      additionalData: {
        allow3DS2: true,
        executeThreeD: true,
      },
    };
    // Data for various Components
    var componentData = {
      scheme: {
        card_public_key: CARD_PUBLIC_KEY,
      },
    };

    try {
      // The Following Payment Methods are supported
      //DROPIN,IDEAL,MOLPAY_MALAYSIA,MOLPAY_THAILAND,MOLPAY_VIETNAM,DOTPAY,EPS,ENTERCASH,OPEN_BANKING,
      //SCHEME,GOOGLE_PAY,SEPA,BCMC,WECHAT_PAY_SDK,APPLE_PAY,

      AdyenPayment.startPayment(
        AdyenPayment.DROPIN,
        componentData,
        paymentDetails,
      );
    } catch (err) {
      console.log(err.message);
    }
  };

  render() {
    return (
      <View style={styles.container}>
        <Text>{this.state.adyen_payment_status}</Text>
        <Button
          label={'Pay'}
          title="Drop In"
          onPress={() => {
            this.onClickPayment();
          }}
        />
      </View>
    );
  }
}

My questions here is that what CARD_PUBLIC_KEY referring to ? am I using the right one? Another one is the base url is the one I am using usable? If not, where can I find one so that I can test.

Here my situation What happening now is that if I click the button there will be a quick loading and will not console anything. even if it fail or success. If I deep dive enough in AdyenPaymentModule.kt it will reach the syntax if (response.isSuccessful()) {

but the response is Response{protocol=http/1.1, code=401, message=, url=https://checkout-test.adyen.com/v51/paymentMethods} and it exit there I think

ChielBruin commented 2 years ago

You should never communicate directly with the Adyen API here, always route the traffic through your own server. If you communicate directly there are some keys missing that should be set in the backend.

KerryDss commented 2 years ago

@ChielBruin Thanks for responding. 🥺

I am really confuse when reading the documentation. Yeah I notice from Adyen documentation. Mobile app should not directly connected with Adyen.

In our team I got another developer who is handling the merchant server side which will communicate with Adyen server

From my understanding I should request that person to return only the base_url which in turn should handle the three post request. So all transaction make with Adyen server will handle my merchant server.

 /adyen/paymentMethods
 /adyen/payments
 /adyen/payments/details

So what react-native need to do is especially what frontend app developer need to do is when user press the Pay button. I just need to call this function AdyenPayment.startPayment( AdyenPayment.DROPIN, componentData, paymentDetails, ) and the merchants server need to handle all the logic. Am I understanding correctly?

ChielBruin commented 2 years ago

Yes that is correct. The dropin sends requests on those three endpoints to your own server. There you use the other packages provided by Adyen (for example this one for node.js: https://github.com/Adyen/adyen-node-api-library) to communicate to the Adyen servers.

KerryDss commented 2 years ago

@ChielBruin I have some new questions. I get to the step of showing the bottom sheet card.

In android studio . I got an error like this in log-cat when DropIn modal popup when I press the button that initiate payment.

E/CO.DropInViewModel: PaymentMethod not yet supported - cup

Screen Shot 2022-03-24 at 16 33 17

and after when I press the Pay $$ The screen keep on loading for a very long time without transaction going through.

Screenshot_1648116132

ChielBruin commented 2 years ago

As the error states, the payment method cup is not supported by this library, so it cannot render it in the list of available payment options. Have you checked the list of available payment methods received from your server? To troubleshoot the loading spinner, you can check if any request reaches your server, as it might be that the event is not properly handled there. I can recommend using a tool like charles to debug the communication between the app and the backend

KerryDss commented 2 years ago

@ChielBruin Thanks , the error goes away when I remove the node modules, clean gradle files and reinstall again