@a-tech.jo/atech_payment 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,10 +17,16 @@ This Package is the frontend interface to integrate with A-Tech payment project,
17
17
  3. **Publishing**
18
18
  When ready to share the package, publish it by running `npm publish`.
19
19
  After publishing, it can be installed in any app using:
20
- `npm run publish`
20
+ `npm run publish:npm`
21
21
 
22
22
  4. **Add to your project**
23
23
  1. Open next.config.js
24
24
  2. Add the package to transpilePackages key as below:
25
25
  transpilePackages: [ "@a-tech.jo/atech_payment"]
26
- 3. use the package
26
+ 3. use the package
27
+
28
+
29
+ 5. **To specify environment it can be detected using.env variable NODE_ENV as below: **
30
+ 1. production
31
+ 2. staging
32
+ 3. development
@@ -0,0 +1,37 @@
1
+ {
2
+ "entityId":"8a8294174d0595bb014d05d82e5b01d2",
3
+ "amount":"0.00",
4
+ "paymentType":"PA",
5
+ "createRegistration":"true",
6
+ "currency":"EUR",
7
+ "testMode":"EXTERNAL",
8
+ "paymentBrand":"VISA",
9
+ "card.number":"4242426505984705",
10
+ "card.holder":"John Smith",
11
+ "card.expiryMonth":"12",
12
+ "card.expiryYear":"2026",
13
+ "card.cvv":"123",
14
+ "customer.email":"john.smith@gmail.com",
15
+ "customer.givenName":"Smith",
16
+ "customer.ip":"192.168.0.0",
17
+ "customer.surname":"John",
18
+ "customer.language":"DE",
19
+ "billing.city":"MyCity",
20
+ "billing.country":"DE",
21
+ "billing.postcode":"712121",
22
+ "billing.state":"DE",
23
+ "billing.street1":"MyStreet",
24
+ "standingInstruction.type":"RECURRING",
25
+ "standingInstruction.mode":"INITIAL",
26
+ "standingInstruction.source":"CIT",
27
+ "standingInstruction.recurringType":"SUBSCRIPTION",
28
+ "threeDSecure.eci":"05",
29
+ "threeDSecure.authenticationStatus":"Y",
30
+ "threeDSecure.version":"2.2.0",
31
+ "threeDSecure.dsTransactionId":"c75f23af-9454-43f6-ba17-130ed529507e",
32
+ "threeDSecure.acsTransactionId":"2c42c553-176f-4f08-af6c-f9364ecbd0e8",
33
+ "threeDSecure.verificationId":"MTIzNDU2Nzg5MDEyMzQ1Njc4OTA=",
34
+ "threeDSecure.amount":"19.99",
35
+ "threeDSecure.currency":"EUR",
36
+ "threeDSecure.flow":"challenge"
37
+ }
File without changes
package/index.js CHANGED
@@ -7,27 +7,21 @@ const PymentOrder = ({
7
7
  clientId = "test",
8
8
  onChange = () => {},
9
9
  onStatusChange = () => {},
10
- env = "development",
11
10
  redirectUrl = "",
12
11
  }) => {
13
12
  if (provider === "paypal") {
14
- console.log(process.env.API_URL);
15
13
  return (
16
14
  <PaypalOrder
17
15
  order={order}
18
16
  clientId={clientId}
19
17
  onChange={onChange}
20
18
  onStatusChange={onStatusChange}
21
- env={env}
22
19
  />
23
20
  );
24
21
  }
25
22
 
26
23
  if (provider === "hyperpay") {
27
- console.log(process.env.API_URL);
28
- return (
29
- <HyperpayOrder order={order} redirectUrl={redirectUrl} env={env} />
30
- );
24
+ return <HyperpayOrder order={order} redirectUrl={redirectUrl} />;
31
25
  }
32
26
 
33
27
  return <div />;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a-tech.jo/atech_payment",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "type": "module",
5
5
  "description": "A-Tech Payment React Package",
6
6
  "source": "index.js",
@@ -19,7 +19,7 @@
19
19
  "build:prod": "webpack --mode=production --node-env=production",
20
20
  "watch": "webpack --watch",
21
21
  "serve": "webpack serve",
22
- "publish": "npm publish --access public"
22
+ "publish:npm": "npm publish --access public"
23
23
  },
24
24
  "author": "A-Tech",
25
25
  "license": "GNU",
@@ -0,0 +1,98 @@
1
+ import { useEffect, useState } from "react";
2
+ import hyperpayConnector from "../shared/requests/hyperpayConnector.js";
3
+
4
+ const HyperpayOrder = ({ redirectUrl, order }) => {
5
+ const [error, setError] = useState(null);
6
+ const [checkoutId, setCheckoutId] = useState(null);
7
+ const [isLoading, setIsLoading] = useState(false);
8
+
9
+ useEffect(() => {
10
+ if (order) {
11
+ initiateOrder();
12
+ }
13
+ }, [order]);
14
+
15
+ const initiateOrder = async () => {
16
+ try {
17
+ if (!order) {
18
+ setError("Order data must be provided");
19
+ return;
20
+ }
21
+ setIsLoading(true);
22
+ const result = await hyperpayConnector.createHyperpayOrder(order);
23
+ setIsLoading(false);
24
+
25
+ if (result?.error) {
26
+ setError(result.error);
27
+ return;
28
+ }
29
+
30
+ setCheckoutId(result?.id);
31
+ } catch (err) {
32
+ console.error("err", err);
33
+ setError("An unexpected error occurred.");
34
+ }
35
+ };
36
+
37
+ const checkout = async () => {
38
+ try {
39
+ if (!checkoutId) {
40
+ setError("Checkout ID must be provided");
41
+ return;
42
+ }
43
+ setIsLoading(true);
44
+ const result = await hyperpayConnector.getOrderStatus(checkoutId);
45
+ setIsLoading(false);
46
+
47
+ if (result?.error) {
48
+ setError(result.error);
49
+ return;
50
+ }
51
+
52
+ return result;
53
+ } catch (err) {
54
+ console.error("err", err);
55
+ setError("An unexpected error occurred.");
56
+ }
57
+ };
58
+
59
+ useEffect(() => {
60
+ if (checkoutId) {
61
+ const script = document.createElement("script");
62
+ script.src = `https://eu-test.oppwa.com/v1/paymentWidgets.js?checkoutId=${checkoutId}`;
63
+ script.async = true;
64
+ script.crossOrigin = "anonymous";
65
+ document.body.appendChild(script);
66
+
67
+ return () => {
68
+ document.body.removeChild(script);
69
+ };
70
+ }
71
+ }, [checkoutId]);
72
+
73
+ if (error) {
74
+ return <p>Error: {error}</p>;
75
+ }
76
+
77
+ if (isLoading) {
78
+ return <p>Loading...</p>;
79
+ }
80
+
81
+ if (checkoutId) {
82
+ return (
83
+ <form
84
+ action={redirectUrl}
85
+ className="paymentWidgets"
86
+ data-brands="VISA MASTER AMEX"
87
+ ></form>
88
+ );
89
+ }
90
+
91
+ return (
92
+ <div>
93
+ <p>No order</p>
94
+ </div>
95
+ );
96
+ };
97
+
98
+ export default HyperpayOrder;
@@ -0,0 +1,76 @@
1
+ import React from "react";
2
+ import { PayPalButtons, usePayPalScriptReducer } from "@paypal/react-paypal-js";
3
+ import backendConnector from "../shared/requests/backendConnector.js";
4
+
5
+ const Spinner = () => <div className="spinner">Processing payment...</div>;
6
+
7
+ const ButtonWrapper = ({
8
+ order,
9
+ onChange = () => {},
10
+ onStatusChange = () => {},
11
+ env,
12
+ }) => {
13
+ if (env !== "production" && env !== "development") {
14
+ return <div>Invalid Env</div>;
15
+ }
16
+ const [{ isPending }] = usePayPalScriptReducer();
17
+
18
+ const createOrderOrSubscription = async () => {
19
+ try {
20
+ const response = await backendConnector.createPaypalOrder(order, env);
21
+ onChange({ event: "createOrder", data: response });
22
+ return response.id;
23
+ } catch (error) {
24
+ console.error("Error creating PayPal transaction:", error);
25
+ throw new Error("Transaction creation failed");
26
+ }
27
+ };
28
+
29
+ const handleApproval = async (data, actions) => {
30
+ try {
31
+ console.log(data);
32
+ const captureData = {
33
+ orderId: data?.orderID || undefined,
34
+ subscriptionId: data?.subscriptionID || data?.id,
35
+ type: order.type,
36
+ };
37
+
38
+ await backendConnector.approveOrder(captureData, env);
39
+ if (order.type == "order") {
40
+ return actions.order.capture().then(function (details) {
41
+ onStatusChange(true);
42
+ onChange({ event: "approveOrder", data: data });
43
+
44
+ console.log(
45
+ "Transaction completed by " + details.payer.name.given_name
46
+ );
47
+ });
48
+ }
49
+ onStatusChange(true);
50
+ onChange({ event: "approveOrder", data: data });
51
+ } catch (error) {
52
+ console.error("Error capturing PayPal transaction:", error);
53
+ }
54
+ };
55
+
56
+ return (
57
+ <>
58
+ {isPending ? <Spinner /> : null}
59
+ <PayPalButtons
60
+ style={{ layout: "vertical" }}
61
+ disabled={false}
62
+ fundingSource={undefined}
63
+ createOrder={
64
+ order.type === "order" ? createOrderOrSubscription : undefined
65
+ }
66
+ createSubscription={
67
+ order.type === "subscription" ? createOrderOrSubscription : undefined
68
+ }
69
+ onError={(err) => console.log(err)}
70
+ onApprove={handleApproval}
71
+ />
72
+ </>
73
+ );
74
+ };
75
+
76
+ export default ButtonWrapper;
@@ -0,0 +1,33 @@
1
+ import React from "react";
2
+ import { PayPalScriptProvider } from "@paypal/react-paypal-js";
3
+ import ButtonWrapper from "./buttonWrapper.js";
4
+ import config from "../shared/config.js";
5
+
6
+ const PaypalOrder = ({
7
+ currency = "USD",
8
+ clientId = "test",
9
+ order = {},
10
+ onChange = () => {},
11
+ onStatusChange = () => {},
12
+ }) => {
13
+ const env = config.NODE_ENV;
14
+ const initialOptions = {
15
+ clientId: clientId,
16
+ currency: currency,
17
+ vault: order.type === "subscription",
18
+ };
19
+ return (
20
+ <div style={{ maxWidth: "750px", minHeight: "200px" }}>
21
+ <PayPalScriptProvider options={initialOptions}>
22
+ <ButtonWrapper
23
+ order={order}
24
+ onChange={onChange}
25
+ onStatusChange={onStatusChange}
26
+ env={env}
27
+ />
28
+ </PayPalScriptProvider>
29
+ </div>
30
+ );
31
+ };
32
+
33
+ export default PaypalOrder;
@@ -0,0 +1,20 @@
1
+ let config = {
2
+ NODE_ENV: process.env.NODE_ENV,
3
+ BACKEND_BASE_URL: "http://localhost:5000/api",
4
+ HYPERPAY_BASE_URL: "https://eu-test.oppwa.com/",
5
+ };
6
+
7
+ const production = {
8
+ BACKEND_BASE_URL: "http://prod:5000/api",
9
+ HYPERPAY_BASE_URL: "https://eu-prod.oppwa.com/",
10
+ };
11
+
12
+ const staging = {
13
+ BACKEND_BASE_URL: "https://payment.staging.a-tech.dev/api",
14
+ };
15
+
16
+ if (process.env.NODE_ENV === "production")
17
+ config = { ...config, ...production };
18
+ if (process.env.NODE_ENV === "staging") config = { ...config, ...staging };
19
+
20
+ export default config;
@@ -0,0 +1,16 @@
1
+ // Services
2
+ import backendConnector from "./requests/backendConnector";
3
+
4
+ class PaypalService {
5
+ async createOrder(data) {
6
+ const result = await backendConnector.createPaypalOrder(data);
7
+ if (result?.id) return result?.id;
8
+ }
9
+
10
+ async onApprove(data) {
11
+ const result = await backendConnector.approveOrder(data);
12
+ return result;
13
+ }
14
+ }
15
+
16
+ export default new PaypalService();
@@ -0,0 +1,24 @@
1
+ // Services
2
+ import request from "./request.js";
3
+
4
+ class BackendConnector {
5
+ async createPaypalOrder(data) {
6
+ const requestConfig = {
7
+ url: "/paypal/orders/create-order",
8
+ data,
9
+ };
10
+ const result = await request.post(requestConfig);
11
+ return result;
12
+ }
13
+
14
+ async approveOrder(data) {
15
+ const requestConfig = {
16
+ url: "/paypal/orders/capture-order",
17
+ data,
18
+ };
19
+ const result = await request.post(requestConfig);
20
+ return result;
21
+ }
22
+ }
23
+
24
+ export default new BackendConnector();
@@ -0,0 +1,54 @@
1
+ // Services
2
+ import config from "../config.js";
3
+ import request from "./request.js";
4
+
5
+ class HyperpayConnector {
6
+ constructor() {
7
+ this.BASEURL = config.HYPERPAY_BASE_URL;
8
+ this.DEV_BASEURL = config.HYPERPAY_BASE_URL;
9
+ }
10
+
11
+ defaultHeaders = (data) => {
12
+ const headers = {
13
+ "Content-Type": "application/x-www-form-urlencoded",
14
+ "Content-Length": data?.length,
15
+ };
16
+
17
+ return headers;
18
+ };
19
+ async createHyperpayOrder(data) {
20
+ const headers = this.defaultHeaders();
21
+ const url = "/hyperpay/orders/create-order";
22
+ const requestConfig = {
23
+ url: url,
24
+ data,
25
+ headers: headers,
26
+ };
27
+ console.log("requestConfig", requestConfig);
28
+ const result = await request.post(requestConfig);
29
+ console.log("result", result);
30
+ return result;
31
+ }
32
+
33
+ async getOrderStatus(checkoutId) {
34
+ const headers = this.defaultHeaders();
35
+ const requestConfig = {
36
+ url: `/hyperpay/orders/get-order/${checkoutId}`,
37
+ headers,
38
+ };
39
+ const result = await request.get(requestConfig);
40
+ return result;
41
+ }
42
+
43
+ async captureOrder(orderId) {
44
+ const headers = this.defaultHeaders();
45
+ const requestConfig = {
46
+ url: `/hyperpay/orders/capture-order/${orderId}`,
47
+ headers,
48
+ };
49
+ const result = await request.post(requestConfig);
50
+ return result;
51
+ }
52
+ }
53
+
54
+ export default new HyperpayConnector();
@@ -0,0 +1,92 @@
1
+ import axios from "axios";
2
+ // CONFIG
3
+ import config from "../config.js";
4
+
5
+ class Request {
6
+ constructor() {}
7
+
8
+ async handleRequests(finalConfig) {
9
+ try {
10
+ axios.defaults.baseURL = config.BACKEND_BASE_URL;
11
+ const response = await axios.request(finalConfig);
12
+
13
+ return response.data;
14
+ } catch (err) {
15
+ console.log("err", err);
16
+ if (err.response) {
17
+ if (err.response.status === 401) {
18
+ return (window.location.href = "/login");
19
+ }
20
+ return err.response.data;
21
+ } else if (err.request) {
22
+ return {
23
+ success: false,
24
+ message: "No response received, please try again later.",
25
+ };
26
+ } else {
27
+ return {
28
+ success: false,
29
+ message: "An unexpected error occurred.",
30
+ };
31
+ }
32
+ }
33
+ }
34
+
35
+ async post(config) {
36
+ const defaultConfig = {
37
+ method: "post",
38
+ };
39
+
40
+ const finalConfig = {
41
+ ...defaultConfig,
42
+ ...config,
43
+ };
44
+ return await this.handleRequests(finalConfig);
45
+ }
46
+
47
+ async get(config = {}) {
48
+ const defaultConfig = {
49
+ method: "get",
50
+ };
51
+ const finalConfig = {
52
+ ...defaultConfig,
53
+ ...config,
54
+ };
55
+ return await this.handleRequests(finalConfig);
56
+ }
57
+
58
+ async put(config) {
59
+ const defaultConfig = {
60
+ method: "put",
61
+ };
62
+ const finalConfig = {
63
+ ...defaultConfig,
64
+ ...config,
65
+ };
66
+ return await this.handleRequests(finalConfig);
67
+ }
68
+
69
+ async patch(config) {
70
+ const defaultConfig = {
71
+ method: "patch",
72
+ };
73
+ const finalConfig = {
74
+ ...defaultConfig,
75
+ ...config,
76
+ };
77
+ return await this.handleRequests(finalConfig);
78
+ }
79
+
80
+ async delete(config) {
81
+ const defaultConfig = {
82
+ method: "delete",
83
+ };
84
+ const finalConfig = {
85
+ ...defaultConfig,
86
+ ...config,
87
+ };
88
+ return await this.handleRequests(finalConfig);
89
+ }
90
+ }
91
+
92
+ export default new Request();