التوثيق

@xpayeg/sdk

الـ JavaScript SDK بتاع المتصفّح. مرجع لكل تصدير عام، وتوقيع دالة، ونوع خيار.

الـ JavaScript SDK بتاع XPay مكتبة صغيّرة بتتحمّل من الـ CDN، وبتديك XPayInstance مكتوب بالأنواع من مفتاحك القابل للنشر. ومنها تقدر تركّب واجهة دفع كـ Elements، أو تفتح drop-in checkout، أو تشغّل initCheckout باستدعاء واحد وتأكّد دفعة.

pnpm add @xpayeg/sdk
# or: npm install @xpayeg/sdk / yarn add @xpayeg/sdk

الـ package بيوفّر بناءات ESM وCJS، زائد أنواع TypeScript كاملة. وقت التشغيل نفسه بيتحمّل عند الطلب من https://checkout.xpay.app/v1/sdk.js.

فيه طريقتين لتحميل الـ SDK، وكل واحدة بتعرض الـ factory باسم مختلف. ده أكتر غلط شائع في التكامل، فخلّيك مظبّطه من البداية:

// استورد loadXPay واعمله await. ده المسار اللي باقي الصفحة بتوثّقه.
import { loadXPay } from "@xpayeg/sdk";

const xpay = await loadXPay("pk_test_...");
<!-- حطّ الـ CDN script tag، وبعدين استدعي الـ factory العام XPay() اللي الـ runtime
     بيحطّه على window. من غير import، ولا await، ولا build step. -->
<script src="https://checkout.xpay.app/v1/sdk.js"></script>
<script>
  const xpay = XPay("pk_test_...");
</script>

loadXPay موجود بس في الـ package بتاع npm؛ والـ CDN runtime بيعرض بس الـ global XPay. مش قابلين للتبديل: استدعاء loadXPay(...) بعد الـ script tag بيرمي ReferenceError: loadXPay is not defined، والـ global XPay مش قابل للاستيراد. اختار الصف اللي يناسب الإعداد بتاعك؛ أي حاجة بعد ما تحصل على نسخة xpay هي نفسها بالظبط. الصفحة دي بتوثّق مدخل npm (loadXPay). على مسار الـ HTML العادي، بدّل await loadXPay(k) بـ XPay(k) في أي مثال تحت.

شوفه شغّال: مثال HTML عادي

كل نمط في الصفحة دي كملفات HTML عادية جاهزة للتشغيل: CDN script tag + الـ factory العام XPay()، وسيرفر Express صغيّر، من غير build step. اعمل clone، وحطّ مفاتيح الاختبار، وافتح في المتصفّح.

الصفحة دي مرجع لكل تصدير عام. للشروحات، شوف Drop-in وElements تحت Integrate.

استخدم الـ package ده لما

@xpayeg/sdk هو الـ SDK الـ vanilla وهو الاختيار الصح كل ما تكون مش على React. ده بيغطي:

  • HTML العادي والمواقع الثابتة (الـ CDN script tag + الـ factory العام XPay()؛ شوف مساري التحميل فوق).
  • Vue، وSvelte، وSolid، وAngular، وLit، وQwik، وAstro، وأي إطار تاني. استدعي الـ SDK من جوّه دورة حياة مكوّن الإطار ده (mount، وonMount، وما يعادل useEffect، إلخ).
  • React Native عن طريق WebView لحد ما ينزل package أصلي.
  • سكربتات من ناحية السيرفر محتاجة تكتب حمولات الـ clientSecret بالأنواع (أنواع TypeScript بتاعة الـ package مستقلة عن الإطار).

لـ React، @xpayeg/react غلاف راحة رفيع فوق الـ package ده. مبني على loadXPay، وxpay.initCheckout، وxpay.elements، فأي حاجة بتقراها هنا بتنطبق تحت الكواليس هناك كمان.

البداية السريعة

المسار المنصوح بيه هو loadXPay على مستوى الموديول، وبعدين xpay.initCheckout() بمجرد ما يبقى عندك clientSecret من السيرفر بتاعك.

import { loadXPay } from "@xpayeg/sdk";

// Module-level: call once, share across the app.
const xpayPromise = loadXPay("pk_test_...");

async function startCheckout() {
  const xpay = await xpayPromise;
  if (!xpay) return; // SSR returns null on the server

  // initCheckout accepts a Promise<string> too, so you can pass the fetch directly.
  const checkout = await xpay.initCheckout({
    clientSecret: fetch("/api/create-checkout", { method: "POST" })
      .then((r) => r.json())
      .then((d) => d.clientSecret as string),
  });

  // Mount the payment element.
  const elements = checkout.getElements();
  const paymentElement = elements.create("payment");
  paymentElement.mount("#payment-element");

  // Listen for state changes (promo codes, quantity updates, fee recalcs).
  checkout.on("change", (session) => {
    document.getElementById("total")!.textContent =
      `${session.currency} ${(session.amountTotal / 100).toFixed(2)}`;
  });

  // Confirm when the customer submits.
  document.getElementById("pay")!.addEventListener("click", async () => {
    const result = await checkout.confirm({
      customerDetails: { email: "customer@example.com", name: "Aya Hassan" },
    });
    if (result.type === "error") {
      console.error(result.error.message);
      return;
    }
    window.location.href = "/thank-you";
  });
}

التصديرات بنظرة سريعة

التصديرالنوعيعني إيه
loadXPay(publishableKey)functionبيحمّل الـ SDK من الـ CDN ويرجّع XPayInstance (أو null على السيرفر أثناء الـ SSR).
XPayInstanceinterfaceالـ factory بتاع Elements، وdrop-in Checkout، وconfirmPayment، وinitCheckout.
Elementsinterfaceبيدير الـ payment elements (PaymentElement) ودورة حياة الجلسة.
PaymentElementinterfaceمختار وسيلة دفع قابل للتركيب مع فورم البطاقة، وBNPL، وكشك، ووسائل المحفظة.
ConfirmPaymentOptionsinterfaceالشكل المُمرَّر لـ xpay.confirmPayment() وcheckout.confirm().
CheckoutOptionsinterfaceإعداد xpay.checkout(). drop-in modal أو inline embed.
CheckoutInstanceinterfaceمقبض الـ drop-in checkout: open()، وclose()، وdestroy()، زائد الأحداث.
CheckoutCompleteResultinterfaceالحمولة لـ onComplete callback بتاع الـ drop-in.
InitCheckoutOptionsinterfaceخيارات xpay.initCheckout(). الـ API العصري باستدعاء واحد.
InitCheckoutResulttypeبيانات الجلسة مدموجة مع دوال الإجراءات (confirm، وأكواد الخصم، إلخ).
CheckoutActionsinterfaceدوال الإجراءات اللي بتركب على كائن الـ checkout.
CheckoutSessiontypeشكل بيانات الجلسة: المبلغ، والعملة، والحالة، ووسائل الدفع، والبنود.
ActionResulttypetagged union: { type: "success", session } أو { type: "error", error }.
XPayErrorinterfaceنوع الخطأ الموحَّد عبر كل إجراء في الـ SDK.
Appearancetypeتجاوزات العلامة التجارية للواجهة المضمّنة (وضع اللون، ونمط الحدّ، والألوان، والخط).
PaymentElementChangeEventinterfaceالحمولة لأحداث الـ change بتاعة PaymentElement.
ElementsReadyEventinterfaceالحمولة لحدث "ready" بتاع Elements.
ElementsLoadErrorEventinterfaceالحمولة لحدث "loaderror" بتاع Elements.
CustomerDetails, Addressinterfaceالأشكال لحقول العميل اللي فورمك بيجمّعها وبتتمرّر وقت التأكيد.
PaymentMethodInfotypeمعلومات عن وسيلة دفع متاحة على الجلسة.
SessionStatustypetagged union: open، أو expired، أو complete.

loadXPay(publishableKey)

بيحمّل وقت تشغيل الـ SDK من الـ CDN ويرجّع XPayInstance. استدعيه مرة واحدة على مستوى الموديول، مش جوّه مكوّن.

import { loadXPay } from "@xpayeg/sdk";

const xpayPromise = loadXPay("pk_test_...");
// later, when you have a clientSecret:
const xpay = await xpayPromise;
const elements = xpay.elements({ clientSecret: "cs_test_..." });
البارامترالنوعالوصف
publishableKeystringمفتاح الـ API القابل للنشر بتاعك (pk_test_... أو pk_live_...).

بيرجّع Promise<XPayInstance | null>. الـ null بيرجع أثناء العرض من ناحية السيرفر (مفيش window). الـ XPayProvider من @xpayeg/react بيتعامل مع الـ null بسلاسة بإعادة المحاولة على العميل.

وقت التشغيل بيتجاب مرة واحدة؛ واستدعاءات loadXPay اللي بعدها بتعيد استخدام نفس الـ script tag. لو فيه سكربت بـ sdk.js موجود أصلًا على الصفحة، ما بيتحقنش تاني.

XPayInstance

الـ factory اللي بيرجعلك من loadXPay. أربع دوال.

interface XPayInstance {
  elements(options: ElementsOptions): Elements;
  checkout(options: CheckoutOptions): CheckoutInstance;
  confirmPayment(options: ConfirmPaymentOptions): Promise<ActionResult>;
  initCheckout(options: InitCheckoutOptions): Promise<InitCheckoutResult>;
}

elements(options)

بينشئ نسخة Elements لواجهة دفع مخصّصة. مرّر له الـ clientSecret من جلسة دفع.

const elements = xpay.elements({
  clientSecret: "cs_test_...",
  appearance: { colorMode: "dark", borderStyle: "rounded" },
  locale: "en",
});

ElementsOptions:

الحقلالنوعالوصف
clientSecretstring | Promise<string>مطلوب. الـ client secret بتاع جلسة الدفع. ممكن يكون Promise.
appearanceAppearanceاختياري. تجاوزات الواجهة المدموجة مع العلامة التجارية من ناحية السيرفر للجلسة.
locale"en" | "ar"اختياري. الافتراضي "en".

checkout(options)

بينشئ نسخة drop-in checkout. شوف CheckoutOptions تحت.

confirmPayment(options)

بيقدّم دفعة باستخدام البيانات اللي Elements جمّعها. شوف ConfirmPaymentOptions تحت.

initCheckout(options)

الـ API العصري باستدعاء واحد: بيرجّع بيانات الجلسة ودوال الإجراءات مع بعض. شوف InitCheckoutOptions تحت.

Elements

بيرجعه xpay.elements(). بيدير iframe دفع مشترك واحد وبيكشف دوال تعديل الجلسة.

interface Elements {
  create(type: "payment"): PaymentElement;
  getElement(type: "payment"): PaymentElement | null;
  fetchPaymentMethods(): Promise<PaymentMethodInfo[]>;

  on(event: "ready" | "change" | "loaderror" | "error", handler): void;
  off(event: string, handler): void;

  applyPromotionCode(code: string): Promise<ActionResult>;
  removePromotionCode(): Promise<ActionResult>;
  updateLineItemQuantity(args: { lineItem: string; quantity: number }): Promise<ActionResult>;
  submit(): Promise<{ error?: XPayError; selectedPaymentMethod?: string }>;
  fetchUpdates(): Promise<ActionResult>;
  changeAppearance(appearance: Appearance): void;
  destroy(): void;
}

الأحداث

الحدثتوقيع الـ handlerبيطلق لما
"ready"(data: ElementsReadyEvent) => voidالجلسة اتحمّلت والـ elements قابلة للتركيب. بيطلق فورًا لو متحمّلة أصلًا.
"change"(session: CheckoutSession) => voidبيانات الجلسة بتتغيّر (اختيار وسيلة دفع، وأكواد خصم، وإعادة حساب رسوم).
"loaderror"(data: ElementsLoadErrorEvent) => voidالجلسة بتفشل في التحميل (خطأ شبكة، أو client secret غلط، أو خطأ API).
"error"(error: XPayError) => voidخطأ غير مطلوب مش جاي من إجراء التاجر (مثلًا جلسة انتهت أثناء إعادة حساب رسوم).

الدوال

  • create("payment", options?): بيرجّع PaymentElement تقدر تركّبه.
  • getElement("payment"): بيرجّع الـ element الموجود أو null لو ما اتعملش واحد.
  • fetchPaymentMethods(): بيرجّع قائمة الـ PaymentMethodInfo اللي الجلسة بتدعمها.
  • applyPromotionCode(code): بيطبّق كود خصم، ويرجّع ActionResult.
  • removePromotionCode(): بيشيل الكود المطبَّق، ويرجّع ActionResult.
  • updateLineItemQuantity({ lineItem, quantity }): بيحدّث بند، ويرجّع ActionResult.
  • submit(): بيتحقّق من حقول الـ element. بيرجّع يا إما error أو نص نوع الـ selectedPaymentMethod.
  • fetchUpdates(): بيعيد جلب الجلسة من السيرفر.
  • changeAppearance(appearance): بيحدّث العلامة التجارية في وقت التشغيل من غير ما يعيد إنشاء الـ elements.
  • destroy(): بيفكّك النسخة ويحرّر الموارد.

PaymentElement

مختار وسيلة الدفع الكامل مع فورم البطاقة، وBNPL، وكشك، ووسائل المحفظة. خُد واحد من elements.create("payment").

interface PaymentElement {
  mount(container: string | HTMLElement): void;
  unmount(): void;
  destroy(): void;
  focus(): void;
  blur(): void;
  collapse(): void;

  on(event: "ready" | "loaderstart" | "loaderror", handler): void;
  off(event: string, handler): void;
}

PaymentElementChangeEvent هو الحمولة لحدث "change" بتاع الـ Elements الأب لما يتطلق من تغيير وسيلة دفع:

الحقلالنوعالوصف
elementType"payment"دايمًا "payment" للـ element ده.
emptybooleanإذا كانت كل حقول البطاقة فاضية.
completebooleanإذا كان الفورم مكتمل وجاهز للتقديم.
collapsedbooleanإذا كان مختار الوسيلة مطوي (مفيش وسيلة مختارة).
value{ type: string }نوع وسيلة الدفع المختارة حاليًا.
sessionCheckoutSessionآخر لقطة للجلسة.

ConfirmPaymentOptions

الشكل المُمرَّر لـ xpay.confirmPayment() وcheckout.confirm().

الحقلالنوعالوصف
elementsElementsمطلوب (لـ xpay.confirmPayment). نسخة الـ Elements اللي بتدير الفورم. checkout.confirm بيحقنها لك.
customerDetailsCustomerDetailsاختياري. حقول العميل اللي فورمك جمّعها.
customFieldsRecord<string, string | number | boolean>اختياري. قيم الحقول المخصّصة للجلسة.
deviceFingerprint{ visitorId: string; confidence?: number }اختياري. بصمة الجهاز لكشف الاحتيال.
paymentMethodstringاختياري. تجاوز نوع وسيلة الدفع المختارة.
redirect"if_required" | "always"الافتراضي "if_required". بيتحكم في التنقّل بعد الدفع.
returnUrlstringاختياري. تجاوز afterCompletion.redirect.url بتاع الجلسة.

دلالات redirect:

  • "if_required" بيرجّع النتيجة لكودك؛ وبيحوّل بس لما وسيلة الدفع تتطلّب كده (مثلًا 3-D Secure، وBNPL).
  • "always" بيحوّل دايمًا لـ returnUrl بعد الدفع. الصفحة بتتنقّل بعيد والدالة عمرها ما بترجع عند النجاح.

CheckoutOptions

إعداد الـ drop-in xpay.checkout().

الحقلالنوعالوصف
clientSecretstringمطلوب. الـ client secret بتاع جلسة الدفع.
mode"modal" | "inline""modal" (افتراضي) بيعرض تغطية؛ و"inline" بيضمّن في container.
containerstring | HTMLElementمطلوب لوضع inline. CSS selector أو DOM node علشان يتضمّن فيه.
appearanceAppearanceتجاوزات الواجهة المدموجة مع العلامة التجارية للجلسة.
locale"en" | "ar"لغة الواجهة. الافتراضي "en".
onComplete(result: CheckoutCompleteResult) => voidبيتنادى لما الدفعة تكتمل بنجاح.
onClose() => voidبيتنادى لما النافذة المنبثقة تتقفل.
onReady(session: CheckoutSession) => voidبيتنادى لما الجلسة تتحمّل والواجهة تجهز.
onConfirmed() => voidبيتنادى لما العميل يأكّد الدفع، قبل النتيجة النهائية.
onError(error: CheckoutError) => voidبيتنادى لما يحصل خطأ.

CheckoutInstance

بيرجعه xpay.checkout(). مقبض أمري.

interface CheckoutInstance {
  open(): void; // modal mode
  close(): void;
  destroy(): void;
  on(event: "complete" | "close" | "ready" | "confirmed" | "error", handler): void;
  off(event: string, handler): void;
}

CheckoutCompleteResult (الحمولة لـ onComplete):

الحقلالنوعالوصف
status"succeeded"دايمًا "succeeded" للـ callback ده.
paymentIntentIdstringمعرّف الـ Payment Intent للتحقق من ناحية السيرفر.
chargeIdstringاختياري. معرّف الـ Charge، لما يكون متاح.
redirectUrlstringاختياري. URL التحويل بعد الاكتمال بتاع الجلسة.

InitCheckoutOptions

الـ API العصري باستدعاء واحد. بيدمج elements() مع تحميل الجلسة، وبيكشف بيانات الجلسة زائد دوال الإجراءات على كائن واحد.

const checkout = await xpay.initCheckout({ clientSecret: "cs_test_..." });
console.log(checkout.amountTotal); // session field
const result = await checkout.confirm({ customerDetails: { email } });
الحقلالنوعالوصف
clientSecretstring | Promise<string>مطلوب. الـ client secret بتاع الجلسة.
appearanceAppearanceاختياري. تجاوزات الواجهة.
locale"en" | "ar"اختياري. الافتراضي "en".

InitCheckoutResult هو CheckoutSession & CheckoutActions. دوال الإجراءات على CheckoutActions:

الدالةبتعمل إيه
confirm(options?)بتأكّد الدفعة. بترجّع ActionResult.
applyPromotionCode(code)بتطبّق كود. بترجّع ActionResult.
removePromotionCode()بتشيل الكود المطبَّق. بترجّع ActionResult.
updateLineItemQuantity({ lineItem, quantity })بتحدّث كمية بند. بترجّع ActionResult.
submit()بتتحقّق من الحقول. بترجّع { error?, selectedPaymentMethod? }.
fetchUpdates()بتعيد جلب الجلسة من السيرفر. بترجّع ActionResult.
changeAppearance(appearance)بتحدّث العلامة التجارية في وقت التشغيل.
on(event, handler)تستنى "change"، أو "error"، أو حدث مخصّص.
getElements()بترجّع الـ Elements الأساسي لإنشاء الـ elements.

CheckoutSession (نوع بيانات)

بيانات الجلسة المكشوفة للتاجر. مشتقّة من رد السيرفر، مقصوصة على الحقول الموجّهة للتاجر.

الحقلالنوعالوصف
idstringمعرّف الجلسة cs_*.
amountSubtotalnumberالمجموع الفرعي بالوحدات الصغرى (مثلًا 50000 لـ 500.00 EGP).
amountTotalnumberالإجمالي بالوحدات الصغرى بعد الرسوم والضرايب والخصومات.
currencystringكود العملة ISO (مثلًا "EGP").
merchantNamestringالاسم المعروض لنشاطك التجاري.
livemodebooleantrue للمفاتيح الفعلية؛ وfalse لوضع الاختبار.
expiresAtstringطابع زمني ISO لوقت انتهاء الجلسة.
statusSessionStatustagged union: open، وexpired، وcomplete.
canConfirmbooleanإذا كانت الجلسة ممكن تتأكّد حاليًا.
paymentMethodsPaymentMethodInfo[]وسائل الدفع المتاحة على الجلسة دي.
lineItemsCheckoutLineItem[]البنود.
totalDetailsCheckoutTotalDetailsتفصيل المجموع الفرعي، والضريبة، والشحن، والخصم.
feesCheckoutFeesتفصيل الرسوم لما يكون feesPassThrough مفعّل.
discountsCheckoutDiscount[]أكواد الخصم المطبَّقة.

SessionStatus:

type SessionStatus =
  | { type: "open" }
  | { type: "expired" }
  | { type: "complete"; paymentStatus: "paid" | "unpaid" | "no_payment_required" };

PaymentMethodInfo:

الحقلالنوعالوصف
typestringنوع الوسيلة ("card"، "valu"، "fawry").
displayNamestringلافتة مترجمة ("Card"، "ValU"، "Fawry").
category"card" | "bnpl" | "kiosk" | "wallet"تصنيف لتجميع الواجهة.
iconstringURL أيقونة اختياري.
nextActionTextstringاختياري. وصف الخطوة الجاية اللي بتظهر للعميل.

ActionResult وXPayError

كل إجراء بيعدّل الجلسة بيرجّع ActionResult. ده tagged union، فضيّق حسب result.type قبل ما تقرا الحمولة.

type ActionResult<E = XPayError> =
  | { type: "success"; session: CheckoutSession }
  | { type: "error"; error: E };

XPayError هو شكل الخطأ الموحَّد. الحقول الخاصة بالدفع بتبقى null للأخطاء اللي مش دفع.

الحقلالنوعالوصف
typestringفئة الخطأ: "card_error"، "invalid_request_error"، "api_error".
codestring | nullكود قابل للقراءة آليًا ("card_declined"، "promotion_code_not_found").
messagestringرسالة مقروءة للبني آدم.
paramstring | nullالبارامتر اللي سبّب الخطأ (مثلًا "promotionCode").
docUrlstring | nullURL التوثيق لكود الخطأ ده.
declineCodestring | nullتفصيل الرفض زي "insufficient_funds". Null للأخطاء اللي مش دفع.
adviceCodestring | nullنصيحة إعادة المحاولة: "try_again_later"، "do_not_try_again"، "confirm_card_data".
chargeIdstring | nullمعرّف الـ charge الفاشل.
paymentMethodIdstring | nullمعرّف وسيلة الدفع الفاشلة.
paymentMethodTypestring | nullنوع وسيلة الدفع ("card"، "valu").
paymentMethodRecord<string, unknown> | nullلقطة وسيلة الدفع وقت الفشل.

لدليل التعامل مع أخطاء الـ API وفضاءات أكواد الخطأ التلاتة، شوف الأخطاء، وأكواد أخطاء الـ API، وأكواد أخطاء الدفع، وأكواد الرفض.

Appearance

تجاوزات العلامة التجارية للواجهة المضمّنة. بتعكس مجموعة فرعية من حقول التاجر الافتراضية اللي بتظبطها في إعدادات العلامة التجارية.

الحقلالقيم
colorMode"system" | "light" | "dark"
borderStyle"rounded" | "sharp" | "pill"
spacing"condensed" | "normal" | "spacious"
inputSize"small" | "medium" | "large"
inputStyle"outlined" | "flat" | "filled"
formLayout"compact" | "spacious"
colorsكائن بـ اتناشر رمز دلالي (primary، وforeground، وbackground، وmuted، وaccent، وborder، وinput، وring، وdestructive، زائد أزواج الـ foreground).
fontFamilyنص CSS لـ font-family.

مرّر Appearance لـ xpay.elements()، أو xpay.checkout()، أو xpay.initCheckout(). أو استدعي elements.changeAppearance() / checkout.changeAppearance() علشان تحدّث في وقت التشغيل.

CustomerDetails وAddress

الأشكال لحقول العميل اللي بتجمّعها على فورمك وبتمرّرها وقت التأكيد.

interface CustomerDetails {
  email?: string;
  name?: string;
  phone?: string;
  billingDetails?: { name?: string; email?: string; phone?: string; address?: Address };
  shipping?: { name?: string; phone?: string; address?: Address };
}

interface Address {
  line1?: string;
  line2?: string;
  city?: string;
  state?: string;
  postalCode?: string;
  country?: string;
}

للمرجع المتبادل من ناحية المطوّر عن كل حقل في جلسة الدفع بيتحكم في إيه (مفاتيح التحصيل، والحقول المخصّصة، وأولوية الملء المسبق)، شوف دورة حياة العميل.

رايح فين بعد كده

في الصفحة دي