انتقل إلى المحتوى الرئيسي

مثال على التكامل مع PayPal

يوضح هذا الدرس كيفية التكامل مع PayPal، ويتعرّف خلاله على عُقد جديدة.

1. تتبّع حدث إنشاء الطلب​

1.1. الحدث "order created" في وحدة "Events"​

لتتبّع الأحداث في وحدة "Integrations"، أنشئ حدثًا في وحدة "Events".

وحدة Events موصوفة بالتفصيل هنا.

(يفتح في علامة تبويب جديدة)

1.2. تتبّع حدث إنشاء الطلب​

  • اسحب العقدة "events" إلى مساحة العمل.
  • غيّر القيمة في الحقل "Set" إلى "orderEvent".
  • سيُحفظ الحدث في الكائن "msg.orderEvent"، ويمكن استخدامه في عُقد أخرى.
  • اختر من القائمة الحدث الذي أنشأته "order created"، ثم انقر "submit".

في هذا المثال نشترك في حدث إنشاء الطلب ونحفظه في "msg.orderEvent" لنستخدمه لاحقًا.

المزيد عن العقدة Events هنا.

(يفتح في علامة تبويب جديدة)

2. إنشاء جلسة الدفع​

2.1. أنشئ حساب دفع

قبل البدء بالتكامل، أنشئ حسابًا مخصصًا لـ PayPal.

طريقة إنشائه موصوفة هنا.

(يفتح في علامة تبويب جديدة)

2.2. أنشئ جلسة دفع

  • اسحب العقدة "admin-api" إلى مساحة العمل وصِلها بالعقدة من الخطوة السابقة.
  • اختر الطريقة "Creating a payment session"، والصق الكود التالي في الحقل "Request body".
{
"orderId": {{orderEvent.order.id}},
"type": "session"
}

هنا نستخرج معرّف الطلب من الكائن "msg.orderEvent" ونكوّن طلبًا لإنشاء جلسة دفع. يقبل طلب إنشاء الجلسة المعاملين: "orderId" (المعرّف) و"type" (نوع جلسة الدفع: session أو intent).

المزيد عن العقدة admin-api هنا.

(يفتح في علامة تبويب جديدة)

2.3. احفظ المعرّف الناتج في msg.paymentSessionId

  • اسحب العقدة "function" إلى مساحة العمل وصِلها بالعقدة من الخطوة السابقة.
  • الصق الكود من المثال في الحقل "Function".

هنا نضع في "msg.paymentSessionId" معرّف جلسة الدفع الذي أعادته العقدة السابقة.

msg.paymentSessionId = msg.payload.id

return msg

المزيد عن العقدة Function هنا.

(يفتح في علامة تبويب جديدة)

3. المصادقة في PayPal​

3.1. عيّن معاملات المصادقة في PayPal

  • اسحب العقدة "function" إلى مساحة العمل وصِلها بالعقدة من الخطوة السابقة.
  • الصق الكود من المثال في الحقل "Function".

هنا نعيّن قيم الحقلين "payload" و"headers" في الكائن "msg". تحتاج العقدة التالية إلى هذه القيم لتعمل.

// تعيين جسم الطلب
msg.payload = {
grant_type: 'client_credentials',
}
// تعيين الترويسات
msg.headers = {
'Content-Type': 'application/x-www-form-urlencoded',
Accept: 'application/json',
}

return msg

المزيد عن معاملات الدفع في وثائق PayPal

المزيد عن العقدة Function هنا.

(يفتح في علامة تبويب جديدة)

3.2. طلب الحصول على access token

  • اسحب العقدة "http request" إلى مساحة العمل وصِلها بالعقدة من الخطوة السابقة.
  • في الحقل Method اختر "POST".
  • في الحقل Data اختر "Send as request body".
  • في الحقل Link الصق الرابط https://api-m.sandbox.paypal.com/v1/oauth2/token.
  • في الحقل Return اختر "Object JSON".
  • فعّل "Use Authentication".
  • أدخل client ID الخاص بك في PayPal في الحقل "Username"، وclient secret في الحقل "Password".

يُستخدم هذا الطلب للحصول على "access_token".

المزيد عن المصادقة في وثائق PayPal

المزيد عن العقدة http request هنا.

(يفتح في علامة تبويب جديدة)

3.3. عيّن معاملات إنشاء رابط الدفع

  • اسحب العقدة "function" إلى مساحة العمل وصِلها بالعقدة من الخطوة السابقة.
  • الصق الكود من المثال في الحقل "Function".

في هذا المثال نكوّن طلب إنشاء رابط الدفع من بيانات العُقد السابقة.

// access_token الخاص بـ PayPal، الذي حصلنا عليه في العقدة "paypal auth"
const accessToken = msg.payload.access_token
// بيانات الطلب التي حصلنا عليها في العقدة "order created"
// يطابق الكائن order الطلبَ في orders api https://oneentry.cloud/instructions/api
const order = msg.orderEvent.order
// معرّف جلسة الدفع الذي حصلنا عليه في العقدة "create payment session"
const paymentSessionId = msg.paymentSessionId

// تكوين بيانات PayPal من بيانات الطلب
const items = order.products.map((product) => {
return {
name: product.title,
description: 'your description',
quantity: String(product.quantity),
unit_amount: {
currency_code: order.currency,
value: product.price,
},
}
})

const totalSum = parseFloat(order.totalSum)

const data = {
intent: 'CAPTURE',
purchase_units: [
{
items,
custom_id: String(paymentSessionId),
amount: {
currency_code: order.currency,
value: totalSum,
breakdown: {
item_total: {
currency_code: order.currency,
value: totalSum,
},
},
},
payment_instruction: {
billingId: String(order.id),
},
},
],
payment_source: {
paypal: {
experience_context: {
payment_method_preference: 'UNRESTRICTED',
payment_method_selected: 'PAYPAL',
brand_name: 'EXAMPLE INC',
locale: 'en-US',
landing_page: 'LOGIN',
shipping_preference: 'NO_SHIPPING',
user_action: 'PAY_NOW',
return_url: 'https://example.com/return',
cancel_url: 'https://example.com/cancel',
},
},
},
}

// جسم الطلب
msg.payload = data
// ترويسات الطلب
msg.headers = {
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
Prefer: 'return=representation',
}

return msg

المزيد في وثائق PayPal

المزيد عن العقدة Function هنا.

(يفتح في علامة تبويب جديدة)

4. إنشاء رابط الدفع​

يستخدم هذا المثال العقدة "http request"، وهي تتيح إرسال طلبات http.

  • اسحب العقدة "http request" إلى مساحة العمل وصِلها بالعقدة من الخطوة السابقة.
  • في الحقل Method اختر "POST".
  • في الحقل Data اختر "Send as request body".
  • في الحقل Link الصق الرابط https://api-m.sandbox.paypal.com/v2/checkout/orders.
  • في الحقل Return اختر "Object JSON".

بهذا نرسل إلى PayPal طلبًا لإنشاء رابط دفع ببيانات العقدة السابقة.

المزيد في وثائق PayPal

المزيد عن العقدة http request هنا.

(يفتح في علامة تبويب جديدة)

5. تحديث جلسة الدفع​

  • اسحب العقدة "admin-api" إلى مساحة العمل وصِلها بالعقدة من الخطوة السابقة.
  • اختر الطريقة "Payment session update".
  • الصق الكود التالي في الحقل "Query parameters".
{
"id": {{paymentSessionId}}
}
  • الصق الكود التالي في الحقل "Request body".
{
"paymentUrl": "{{{payload.links.1.href}}}"
}

هنا نستخرج من الطلبات السابقة معرّف رابط الدفع "msg.paymentSessionId" ورابط الدفع "msg.payload.links[0].href".

المزيد عن القيم المُعادة في وثائق PayPal

المزيد عن العقدة admin-api هنا.

(يفتح في علامة تبويب جديدة)

6. إضافة endpoint للحصول على رابط الدفع​

6.1. عيّن الموضوع "createPaymentLink"

  • اسحب العقدة "function" إلى مساحة العمل وصِلها بالعقدة من الخطوة السابقة.
  • الصق الكود من المثال في الحقل "Function".

يُستخدم هذا لتمييز التدفق الحالي.

msg.topic = 'createPaymentLink'

return msg

المزيد عن العقدة Function هنا.

(يفتح في علامة تبويب جديدة)

6.2. أنشئ نقطة نهاية للحصول على رابط الدفع

  • اسحب العقدة "http in" إلى مساحة العمل.
  • اختر الطريقة "POST".
  • أدخل الرابط /get-payment-link.

ستُستخدم نقطة النهاية هذه للحصول على رابط الدفع الحالي.

المزيد عن العقدة http in هنا.

(يفتح في علامة تبويب جديدة)

6.3. عيّن الموضوع "getPaymentLink"

  • اسحب العقدة "function" إلى مساحة العمل وصِلها بالعقدة من الخطوة السابقة.
  • الصق الكود من المثال في الحقل "Function".

يُستخدم هذا لتمييز التدفق الحالي.

msg.topic = 'getPaymentLink'

return msg

المزيد عن العقدة Function هنا.

(يفتح في علامة تبويب جديدة)

6.4. احفظ البيانات في السياق

  • اسحب العقدة "function" إلى مساحة العمل وصِلها بالعقدة من الخطوة السابقة.
  • الصق الكود من المثال في الحقل "Function".

يُستخدم هذا لتكوين الاستجابة.

// الحصول على معرّف الطلب الحالي
const orderId = msg.payload.orderId
// مفتاح السياق الحالي
const contextKey = `payment_link_${orderId}`
// الحصول على OneEntry api
const api = global.get('api')
// بيانات السياق الحالية
const contextData = flow.get(contextKey) || {}
// حفظ البيانات في السياق حسب الموضوع
if (msg.topic === 'createPaymentLink') {
contextData.paymentSessionId = msg.paymentSessionId
contextData.createPaymentLinkCompleted = true
}
if (msg.topic === 'getPaymentLink') {
contextData.getPaymentLinkCompleted = true
contextData.res = msg.res
}
// كتابة بيانات السياق في السياق
flow.set(contextKey, contextData)
// إذا اكتمل createPaymentLink وgetPaymentLink، أرسل الاستجابة مع الجلسة الحالية
if (
contextData.createPaymentLinkCompleted &&
contextData.getPaymentLinkCompleted
) {
// الحصول على جلسة الدفع حسب المعرّف من api
const paymentSession = await api.getPaymentSessionById({
id: contextData.paymentSessionId,
})
msg.payload = paymentSession
msg.res = contextData.res

// مسح api
flow.set(contextKey, null)

return msg
}

return null

المزيد عن العقدة Function هنا.

(يفتح في علامة تبويب جديدة)

6.5. نقطة الخروج لرابط الدفع

  • اسحب العقدة "http response" إلى مساحة العمل وصِلها بالعقدة من الخطوة السابقة.

تُعيد هذه العقدة الاستجابة على الطلب.

المزيد عن العقدة http response هنا.

(يفتح في علامة تبويب جديدة)

7. إعداد webhooks لـ PayPal​

7.1. نقطة الدخول لـ PayPal

  • اسحب العقدة "http in" إلى مساحة العمل.
  • اختر الطريقة "POST".
  • أدخل الرابط /paypal.

ستُستخدم نقطة النهاية هذه لتحديث حالة الدفع عبر PayPal.

المزيد عن العقدة http in هنا.

(يفتح في علامة تبويب جديدة)

7.2. الاستجابة على الطلب

  • اسحب العقدة "function" إلى مساحة العمل وصِلها بالعقدة من الخطوة السابقة.
  • الصق الكود من المثال في الحقل "Function".

يُستخدم هذا لتكوين الاستجابة.

msg.payload = {
ok: true,
}

return msg

المزيد عن العقدة function هنا.

(يفتح في علامة تبويب جديدة)

7.3. نقطة الخروج لـ PayPal

  • اسحب العقدة "http response" إلى مساحة العمل وصِلها بالعقدة من الخطوة السابقة.

تُعيد هذه العقدة الاستجابة على الطلب.

المزيد عن العقدة http response هنا.

(يفتح في علامة تبويب جديدة)

7.4. الحصول على حالة الدفع

  • اسحب العقدة "function" إلى مساحة العمل وصِلها بالعقدة من الخطوة السابقة.
  • الصق الكود من المثال في الحقل "Function".

في هذه العقدة نأخذ القيمة الواردة من العقدة "paypal webhook" ونكتبها في "msg.status" لنستخدمها في العقدة التالية.

msg.status = msg.payload.resource.status

return msg

المزيد عن العقدة Function هنا.

(يفتح في علامة تبويب جديدة)

7.5. التحقق من حالة الدفع

  • اسحب العقدة "switch" إلى مساحة العمل وصِلها بالعقدة من الخطوة السابقة.
  • في "Property" اكتب القيمة "status".
  • أضف قاعدة التحقق الأولى: اختر الشرط "==" وأدخل القيمة "APPROVED".
  • أضف قاعدة التحقق الثانية: اختر الشرط "else".

تتحقق هذه العقدة من مطابقة القيمة في "msg.status" للقواعد المحددة. إذا كانت القيمة "APPROVED" تُنفَّذ عُقد الفرع الأول، وإلا فعُقد الفرع الثاني.

المزيد عن العقدة switch هنا.

(يفتح في علامة تبويب جديدة)

7.6. الحصول على معرّف جلسة الدفع

  • اسحب العقدة "function" إلى مساحة العمل وصِلها بالعقدة من الخطوة السابقة.
  • الصق الكود من المثال في الحقل "Function".

في هذه العقدة نأخذ معرّف جلسة الدفع الذي حفظناه في العقدة "set payment data".

msg.paymentSessionId = parseInt(
msg.payload.resource.purchase_units[0].custom_id,
10
)

return msg

المزيد عن القيم المُعادة في وثائق PayPal

المزيد عن العقدة Function هنا.

(يفتح في علامة تبويب جديدة)

7.7. تحديث حالة الدفع

  • اسحب العقدة "admin-api" إلى مساحة العمل وصِلها بالعقدة من الخطوة السابقة.
  • اختر الطريقة "Payment session update".
  • الصق الكود التالي في الحقل "Query parameters".
{
"id": {{paymentSessionId}}
}
  • الصق الكود التالي في الحقل "Request body".
{
"status": "completed"
}

هنا نحدّث حالة الدفع باستخدام معرّفه من "msg.paymentSessionId".

المزيد عن العقدة admin-api هنا.

(يفتح في علامة تبويب جديدة)

7.8. أضف webhook في حسابك على PayPal

رابط مشروعك + /api/admin/workflows/endpoints/paypal

مثال:

https://<مشروعك>.oneentry.cloud/api/admin/workflows/endpoints/paypal

المزيد في وثائق PayPal

8. التحقق من التكامل​

8.1. أنشئ طلبًا

Postman: طلب POST إلى orders-storage/marker/order_storage/orders مع الترويستين Authorization وx-app-token، والاستجابة &quot;201 Created&quot; مع الطلب id 15

قسم &quot;Orders&quot;، مخزن &quot;order storage&quot;: الطلب رقم 15 بقيمة 2.00 usd عبر Paypal بالحالة &quot;order created&quot;

طريقة إنشاء الطلب موصوفة في وثائق API

8.2. احصل على رابط الدفع

Postman: طلب POST إلى workflows/endpoints/get-payment-link بجسم orderId 15، والاستجابة &quot;200 OK&quot; بالحالة waiting ورابط paymentUrl إلى PayPal

  • أرسل طلب POST إلى https://<مشروعك>.oneentry.cloud/api/admin/workflows/endpoints/get-payment-link، مع استبدال https://<مشروعك>.oneentry.cloud برابط مشروعك.

  • في جسم الطلب، حدّد معرّف الطلب الذي أنشأته سابقًا:

{
"orderId": 15
}

8.3. ادفع قيمة الطلب

صفحة الدفع في PayPal بمبلغ 2.00 $: طريقة الدفع المحددة &quot;PayPal balance&quot;، وفي الأسفل زر &quot;Complete Purchase&quot;

8.4. تحقّق من حالة الطلب

قسم &quot;Orders&quot;، مخزن &quot;order storage&quot;: الطلب رقم 15 أصبح بالحالة &quot;order completed&quot;، مع أيقونة قفل في عمود &quot;Actions&quot;