إجراء معاملات فعلية باستخدام Google Pay

يرشدك هذا الدليل خلال عملية تطوير مشروع Actions يتضمن معاملات للسلع المادية ويستخدم Google Pay للدفع.

مسار المعاملة

عندما يعالج مشروع Actions معاملات مادية باستخدام دفعات يديرها التاجر، يستخدم العملية التالية:

  1. جمع المعلومات (اختياري) - بناءً على طبيعة معاملتك، قد تحتاج إلى جمع المعلومات التالية من المستخدم في بداية المحادثة:
    1. التحقق من متطلبات المعاملة - في بداية المحادثة، تحقق من استيفاء المستخدم لمتطلبات إجراء المعاملة، مثل تهيئة معلومات الدفع وإتاحتها بشكل صحيح قبل إنشاء سلة التسوق.
    2. طلب عنوان تسليم - إذا كانت المعاملة تتطلب عنوان تسليم، اجمع عنوان التسليم من المستخدم.
  2. إنشاء الطلب - قدِّم للمستخدم إرشادات حول "تجميع سلة التسوّق" حيث يختار العناصر التي يريد شراءها.
  3. اقتراح الطلب - بمجرد اكتمال عربة التسوق، اقترح الطلب على المستخدم حتى يتمكن من تأكيد صحته. إذا تم تأكيد الطلب، فستتلقى ردًا يحتوي على تفاصيل الطلب ورمز مميز للدفع.
  4. إنهاء الطلب وإرسال إيصال: بعد تأكيد الطلب، يمكنك تعديل تتبُّع المستودع أو خدمات التوصيل الأخرى، ثم إرسال إيصال إلى المستخدم.
  5. إرسال إشعارات الطلب: على مدار فترة تنفيذ الطلب، أرسِل إشعارات إلى المستخدمين بشأن الطلب من خلال إرسال طلبات الرموز المقترَحة إلى واجهة برمجة تطبيقات الطلبات.

القيود وإرشادات المراجعة

ملاحظة: تنطبق سياسات إضافية على الإجراءات التي تتضمّن معاملات. قد تستغرق مراجعة الإجراءات ذات المعاملات ما يصل إلى ستة أسابيع، لذا يُرجى أخذ هذا الوقت في الاعتبار عند التخطيط لجدولك الزمني للإصدار. لتيسير عملية المراجعة، احرص على الالتزام بسياسات وإرشادات المعاملات قبل إرسال الإجراء الخاص بك للمراجعة.

يمكنك نشر "المهام" التي تبيع سلعًا مادية في البلدان التالية فقط:

أستراليا
البرازيل
كندا
إندونيسيا
اليابان
المكسيك
روسيا
سنغافورة
تايلاند
تركيا
المملكة المتحدة
الولايات المتحدة

إنشاء مشروعك

للحصول على أمثلة شاملة لمحادثات المعاملات، يمكنك الاطّلاع على نموذج معاملات Node.js.

الإعداد

عند إنشاء الإجراء الخاص بك، يجب تحديد أنّك تريد تنفيذ معاملات في وحدة تحكّم الإجراءات.

لإعداد مشروعك وتنفيذه، قم بما يلي:

  1. أنشئ مشروعًا جديدًا أو استورِد مشروعًا حاليًا.
  2. انتقِل إلى نشر > معلومات الدليل.
  3. ضمن معلومات إضافية > المعاملات > ضَع علامة في المربّع "هل تستخدم إجراءاتك واجهة برمجة تطبيقات المعاملات لتنفيذ معاملات سلع مادية؟".

1- جمع المعلومات (اختياري)

1a. التحقّق من متطلبات المعاملة (اختياري)

حالما يذكر المستخدم أنه يريد إجراء عملية شراء، يجب عليك التحقق للتأكد من أنه سيتمكن من إجراء المعاملة. على سبيل المثال، عند استدعاء الإجراء الخاص بك، قد يسألك: "هل تريد طلب أحذية أم تريد التحقق من رصيد حسابك؟" إذا قال المستخدم "طلب أحذية"، يجب عليك التأكد من أنه يمكنه المتابعة وإعطائه الفرصة لإصلاح أي إعدادات تمنعه من مواصلة المعاملة. للقيام بذلك، يجب عليك الانتقال إلى مشهد يجري فحصًا لمتطلبات المعاملة.

إنشاء مشهد التحقق من متطلبات المعاملات
  1. من علامة التبويب "مشاهد"، أضِف مشهدًا جديدًا باسم TransactionRequirementsCheck.
  2. ضمن ملء الفتحة، انقر على + لإضافة خانة جديدة.
  3. ضمن اختيار النوع، اختَر actions.type.TransactionRequirementsCheckResult كنوع الخانة.
  4. في حقل اسم الخانة، أدخِل الاسم TransactionRequirementsCheck.
  5. فعِّل مربّع الاختيار تخصيص قيمة الخانة لاحقًا (مفعّلة تلقائيًا).
  6. انقر على حفظ.

يؤدّي التحقّق من متطلبات المعاملة إلى تحقيق إحدى النتائج التالية:

  • في حال استيفاء المتطلبات، يتم ضبط مَعلمة الجلسة مع ذكر شرط نجاح ويمكنك مواصلة إنشاء ترتيب المستخدِم.
  • في حال تعذّر استيفاء متطلب واحد أو أكثر من هذه المتطلبات، يتم ضبط مَعلمة الجلسة بحالة تعذُّر. في هذه الحالة، يجب عليك تركيز المحادثة بعيدًا عن تجربة المعاملات، أو إنهاء المحادثة.
    • إذا كان بإمكان المستخدم إصلاح أي أخطاء نتج عنها حالة الفشل، سيُطلب منه حل هذه المشاكل على جهازه. إذا كانت المحادثة تُجرى على منصة صوتية فقط، سيبدأ التسليم إلى هاتف المستخدم.

التعامل مع نتيجة التحقّق من متطلبات المعاملات

  1. من علامة التبويب مشاهد، اختَر المشهد TransactionRequirementsCheck الذي تم إنشاؤه حديثًا.
  2. ضمن الشرط، انقر على + لإضافة شرط جديد.
  3. في حقل النص، أدخل بناء جملة الشرط التالي للتحقق من شرط النجاح:

    scene.slots.status == "FINAL" && session.params.TransactionRequirementsCheck.resultType == "CAN_TRANSACT"
    
  4. مرِّر مؤشر الماوس فوق الشرط الذي أضفته للتو وانقر على السهم المتّجه للأعلى لوضعه قبل if scene.slots.status == "FINAL".

  5. تفعيل إرسال المطالبات وتقديم رسالة مطالبة بسيطة تتيح للمستخدم معرفة أنّه مستعد لإجراء معاملة:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                You are ready to purchase physical goods.
    
  6. ضمن النقل، حدِّد مشهدًا آخر، مما يسمح للمستخدم بمتابعة المحادثة ومتابعة إجراء المعاملة.

  7. اختَر الشرط else if scene.slots.status == "FINAL".

  8. فعِّل إرسال الطلبات وقدِّم رسالة مطالبة بسيطة تخبر المستخدم بأنّه غير قادر على إجراء معاملة:

    candidates:
      - first_simple:
          variants:
            - speech: Transaction requirements check failed.
    
  9. ضمن النقل، اختَر إنهاء المحادثة لإنهاء المحادثة في حال تعذّر على المستخدم إجراء المعاملات.

طلب عنوان تسليم

إذا كانت المعاملة تتطلب عنوان التسليم الخاص بالمستخدم، عليك طلبه. قد يكون هذا مفيدًا لتحديد السعر الإجمالي أو موقع التسليم/الاستلام أو لضمان أن المستخدم داخل منطقة خدمتك. للقيام بذلك، يجب عليك الانتقال إلى مشهد يطالب المستخدم بعنوان التسليم الخاص به.

إنشاء مشهد لعنوان التسليم

  1. من علامة التبويب مشاهد، أضِف مشهدًا جديدًا باسم DeliveryAddress.
  2. ضمن ملء الفتحة، انقر على + لإضافة خانة جديدة.
  3. ضمن اختيار النوع، اختَر actions.type.DeliveryAddressValue كنوع الخانة.
  4. في حقل اسم الخانة، أدخِل الاسم TransactionDeliveryAddress.
  5. فعِّل مربّع الاختيار تخصيص خانة كتابة قيمة الخانة (مفعّل تلقائيًا).
  6. انقر على حفظ.

عند ضبط الخانة، يمكنك توفير reason يسمح لك بمقدمة طلب "مساعد Google" للحصول على عنوان يتضمن سلسلة.وسلسلة السبب التلقائية هي "معرفة مكان إرسال الطلب". وبالتالي، قد يسأل "مساعد Google" المستخدم: "لمعرفة مكان إرسال الطلب، سأحتاج إلى الحصول على عنوان التسليم".

  • على الأسطح التي تحتوي على شاشة، سيختار المستخدم العنوان الذي يريد استخدامه لإجراء المعاملة. إذا لم يسبق لهم تقديم عنوان، فسيمكنهم إدخال عنوان جديد.
  • على مساحات العرض الصوتية فقط، سيطلب "مساعد Google" من المستخدم إذنًا لمشاركة عنوانه التلقائي للمعاملة. إذا لم يكن قد أعطوا عنوانًا من قبل، فسيتم تسليم المحادثة إلى هاتف للدخول.

لمعالجة نتيجة عنوان التسليم، اتبع الخطوات التالية:

  1. من علامة التبويب مشاهد، اختَر مشهد DeliveryAddress الذي تم إنشاؤه حديثًا.
  2. ضمن الشرط، انقر على + لإضافة شرط جديد.
  3. في حقل النص، أدخل بناء جملة الشرط التالي للتحقق من شرط النجاح:

    scene.slots.status == "FINAL" && session.params.TransactionDeliveryAddress.userDecision == "ACCEPTED"
    
  4. مرِّر مؤشر الماوس فوق الشرط الذي أضفته للتو وانقر على السهم المتّجه للأعلى لوضعه قبل if scene.slots.status == "FINAL".

  5. عليك تفعيل إرسال المطالبات وتقديم رسالة مطالبة بسيطة تتيح للمستخدم معرفة أنك استلمت عنوانه:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Great! Your order will be delivered to
                $session.params.TransactionDeliveryAddress.location.postalAddress.locality
                $session.params.TransactionDeliveryAddress.location.postalAddress.administrativeArea
                $session.params.TransactionDeliveryAddress.location.postalAddress.regionCode
                $session.params.TransactionDeliveryAddress.location.postalAddress.postalCode
    
  6. ضمن النقل، اختَر مشهدًا آخر يسمح للمستخدم بمواصلة المحادثة.

  7. اختَر الشرط else if scene.slots.status == "FINAL".

  8. فعِّل إرسال الطلبات وقدِّم رسالة مطالبة بسيطة تخبر المستخدم بأنّه غير قادر على إجراء معاملة:

    candidates:
      - first_simple:
          variants:
            - speech: I failed to get your delivery address.
    
  9. ضمن النقل، اختَر إنهاء المحادثة لإنهاء المحادثة إذا تعذّر على المستخدم إجراء المعاملات.

بناء الطلب

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

تتضمن التجربة الأساسية لتجميع عربة التسوق قيام المستخدم باختيار عناصر من قائمة لإضافتها إلى طلبها، على الرغم من أنه يمكنك تصميم المحادثة لتبسيط تجربة المستخدم. يمكنك إنشاء تجربة تجميع عربة التسوق التي تمكّن المستخدم من إعادة طلب آخر عملية شراء عبر سؤال بسيط بنعم أو لا. ويمكنك أيضًا أن تعرض للمستخدم لوحة عرض دوّارة أو بطاقة قائمة بأهم العناصر "المميزة" أو "المقترحة".

ننصح باستخدام الردود التفاعلية لتقديم خيارات المستخدم بشكل مرئي، وكذلك تصميم المحادثة بحيث يتمكن المستخدم من إنشاء سلة التسوّق باستخدام الصوت فقط. للاطّلاع على بعض أفضل الممارسات والأمثلة على تجارب تجميع سلال التسوّق العالية الجودة، يمكنك مراجعة إرشادات التصميم.

إنشاء طلب

خلال محادثتك، سيكون عليك جمع العناصر التي يريد المستخدم شراءها، ثم إنشاء عنصر Order.

على الأقل، يجب أن يحتوي Order على ما يلي:

  • buyerInfo: معلومات عن المستخدِم الذي يُجري عملية الشراء
  • transactionMerchant - معلومات عن التاجر الذي سهّل الطلب
  • contents - المحتوى الفعلي للطلب المدرَج باسم lineItems.
  • priceAttributes - تفاصيل سعر الطلب، بما في ذلك التكلفة الإجمالية للطلب مع الخصومات والضرائب

يمكنك الرجوع إلى مستندات الرد Order لإنشاء سلة التسوّق. لاحظ أنك قد تحتاج إلى تضمين حقول مختلفة حسب الترتيب.

يوضح الرمز النموذجي أدناه طلبًا كاملاً، بما في ذلك الحقول الاختيارية:

const order = {
  createTime: '2019-09-24T18:00:00.877Z',
  lastUpdateTime: '2019-09-24T18:00:00.877Z',
  merchantOrderId: orderId, // A unique ID String for the order
  userVisibleOrderId: orderId,
  transactionMerchant: {
    id: 'http://www.example.com',
    name: 'Example Merchant',
  },
  contents: {
    lineItems: [
      {
        id: 'LINE_ITEM_ID',
        name: 'Pizza',
        description: 'A four cheese pizza.',
        priceAttributes: [
          {
            type: 'REGULAR',
            name: 'Item Price',
            state: 'ACTUAL',
            amount: {
              currencyCode: 'USD',
              amountInMicros: 8990000,
            },
            taxIncluded: true,
          },
          {
            type: 'TOTAL',
            name: 'Total Price',
            state: 'ACTUAL',
            amount: {
              currencyCode: 'USD',
              amountInMicros: 9990000,
            },
            taxIncluded: true,
          },
        ],
        notes: [
          'Extra cheese.',
        ],
        purchase: {
          quantity: 1,
          unitMeasure: {
            measure: 1,
            unit: 'POUND',
          },
          itemOptions: [
            {
              id: 'ITEM_OPTION_ID',
              name: 'Pepperoni',
              prices: [
                {
                  type: 'REGULAR',
                  state: 'ACTUAL',
                  name: 'Item Price',
                  amount: {
                    currencyCode: 'USD',
                    amountInMicros: 1000000,
                  },
                  taxIncluded: true,
                },
                {
                  type: 'TOTAL',
                  name: 'Total Price',
                  state: 'ACTUAL',
                  amount: {
                    currencyCode: 'USD',
                    amountInMicros: 1000000,
                  },
                  taxIncluded: true,
                },
              ],
              note: 'Extra pepperoni',
              quantity: 1,
              subOptions: [],
            },
          ],
        },
      },
    ],
  },
  buyerInfo: {
    email: 'janedoe@gmail.com',
    firstName: 'Jane',
    lastName: 'Doe',
    displayName: 'Jane Doe',
  },
  priceAttributes: [
    {
      type: 'SUBTOTAL',
      name: 'Subtotal',
      state: 'ESTIMATE',
      amount: {
        currencyCode: 'USD',
        amountInMicros: 9990000,
      },
      taxIncluded: true,
    },
    {
      type: 'DELIVERY',
      name: 'Delivery',
      state: 'ACTUAL',
      amount: {
        currencyCode: 'USD',
        amountInMicros: 2000000,
      },
      taxIncluded: true,
    },
    {
      type: 'TAX',
      name: 'Tax',
      state: 'ESTIMATE',
      amount: {
        currencyCode: 'USD',
        amountInMicros: 3780000,
      },
      taxIncluded: true,
    },
    {
      type: 'TOTAL',
      name: 'Total Price',
      state: 'ESTIMATE',
      amount: {
        currencyCode: 'USD',
        amountInMicros: 15770000,
      },
      taxIncluded: true,
    },
  ],
  followUpActions: [
    {
      type: 'VIEW_DETAILS',
      title: 'View details',
      openUrlAction: {
        url: 'http://example.com',
      },
    },
    {
      type: 'CALL',
      title: 'Call us',
      openUrlAction: {
        url: 'tel:+16501112222',
      },
    },
    {
      type: 'EMAIL',
      title: 'Email us',
      openUrlAction: {
        url: 'mailto:person@example.com',
      },
    },
  ],
  termsOfServiceUrl: 'http://www.example.com',
  note: 'Sale event',
  promotions: [
    {
      coupon: 'COUPON_CODE',
    },
  ],
  purchase: {
    status: 'CREATED',
    userVisibleStatusLabel: 'CREATED',
    type: 'FOOD',
    returnsInfo: {
      isReturnable: false,
      daysToReturn: 1,
      policyUrl: 'http://www.example.com',
    },
    fulfillmentInfo: {
      id: 'FULFILLMENT_SERVICE_ID',
      fulfillmentType: 'DELIVERY',
      expectedFulfillmentTime: {
        timeIso8601: '2019-09-25T18:00:00.877Z',
      },
      location: location,
      price: {
        type: 'REGULAR',
        name: 'Delivery Price',
        state: 'ACTUAL',
        amount: {
          currencyCode: 'USD',
          amountInMicros: 2000000,
        },
        taxIncluded: true,
      },
      fulfillmentContact: {
        email: 'johnjohnson@gmail.com',
        firstName: 'John',
        lastName: 'Johnson',
        displayName: 'John Johnson',
      },
    },
    purchaseLocationType: 'ONLINE_PURCHASE',
  },
};

إنشاء خيارات الطلب والعرض

قبل أن يؤكد المستخدم طلبه، ستظهر له بطاقة طلب مقترحة. يمكنك تخصيص الطريقة التي يتم بها عرض هذه البطاقة للمستخدم عن طريق تعيين خيارات مختلفة للطلب والعرض.

في ما يلي خيارات الطلب والعرض لتقديم طلب يتطلب عنوان تسليم، بما في ذلك البريد الإلكتروني للمستخدم في بطاقة تأكيد الطلب:

const orderOptions = {
      'requestDeliveryAddress': true,
      'userInfoOptions': {
        'userInfoProperties': ['EMAIL']
      }
    };

const presentationOptions = {
      'actionDisplayName': 'PLACE_ORDER'
    };

إنشاء مَعلمات الدفع

سيتضمّن العنصر paymentParameters معلَمات الرموز المميّزة التي تتغيّر استنادًا إلى معالج Google Pay الذي تنوي استخدامه (مثل Stripe وBrintree وACI وغير ذلك).

const paymentParamenters = {
      'googlePaymentOption': {
        // facilitationSpec is expected to be a serialized JSON string
        'facilitationSpec': JSON.stringify({
          'apiVersion': 2,
          'apiVersionMinor': 0,
          'merchantInfo': {
            'merchantName': 'Example Merchant',
          },
          'allowedPaymentMethods': [
            {
              'type': 'CARD',
              'parameters': {
                'allowedAuthMethods': ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
                'allowedCardNetworks': [
                  'AMEX', 'DISCOVER', 'JCB', 'MASTERCARD', 'VISA'],
              },
              'tokenizationSpecification': {
                'type': 'PAYMENT_GATEWAY',
                'parameters': {
                  'gateway': 'example',
                  'gatewayMerchantId': 'exampleGatewayMerchantId',
                },
              },
            },
          ],
          'transactionInfo': {
            'totalPriceStatus': 'FINAL',
            'totalPrice': '15.77',
            'currencyCode': 'USD',
          },
        }),
      },
    };

سيختلف محتوى عنصر tokenizationSpecification لكل بوابة دفع. يعرض الجدول التالي المعلَمات المستخدمة من خلال كل بوابة:

مثال
"parameters": {
  "gateway": "example",
  "gatewayMerchantId": "exampleGatewayMerchantId"
}
ACI
"parameters": {
  "gateway": "aciworldwide",
  "gatewayMerchantId": "YOUR_ENTITY_ID"
}
ADYEN
"parameters": {
  "gateway": "adyen",
  "gatewayMerchantId": "YOUR_MERCHANT_ACCOUNT_NAME"
}
ALFA-BANK
"parameters": {
  "gateway": "alfabank",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
BLUE_MEDIA
"parameters": {
  "gateway": "bluemedia",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
BLUESNAP
"parameters": {
  "gateway": "bluesnap",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
البرازيل
"parameters": {
  "gateway": "braintree",
  "braintree:apiVersion": "v1",
  "braintree:sdkVersion": braintree.client.VERSION,
  "braintree:merchantId": "YOUR_BRAINTREE_MERCHANT_ID",
  "braintree:clientKey": "YOUR_BRAINTREE_TOKENIZATION_KEY"
}
CHASE_PAYMENTECH
"parameters": {
  "gateway": "chase",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ACCOUNT_NUMBER"
}
الدفع
"parameters": {
  "gateway": "checkoutltd",
  "gatewayMerchantId": "YOUR_PUBLIC_KEY"
}
Cloudpayments
"parameters": {
  "gateway": "cloudpayments",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
CYBERSOURCE
"parameters": {
  "gateway": "cybersource",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
DATATRANS
"parameters": {
  "gateway": "datatrans",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
EBANX
"parameters": {
  "gateway": "ebanx",
  "gatewayMerchantId": "YOUR_PUBLIC_INTEGRATION_KEY"
}
FIRST_DATA
"parameters": {
  "gateway": "firstdata",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
GLOBAL_payments
"parameters": {
  "gateway": "globalpayments",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
GOPAY
"parameters": {
  "gateway": "gopay",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
دالة HITRUST
"parameters": {
  "gateway": "hitrustpay",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
النتائج
"parameters": {
  "gateway": "imsolutions",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
LYRA
"parameters": {
  "gateway": "lyra",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
الكيلومترات في كل مكان
"parameters": {
  "gateway": "mpgs",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
مال_Mail_RU
"parameters": {
  "gateway": "moneymailru",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
NEWEBPAY
"parameters": {
  "gateway": "newebpay",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
NEXI
"parameters": {
  "gateway": "nexi",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
NMI
"parameters": {
  "gateway": "creditcall",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
PAYSAFE
"parameters": {
  "gateway": "paysafe",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
الراتب
"parameters": {
  "gateway": "payture",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
PAYU
"parameters": {
  "gateway": "payu",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
PRZELEWY24
"parameters": {
  "gateway": "przelewy24",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
الروبية الهندية (RBK)
"parameters": {
  "gateway": "rbkmoney",
  "gatewayMerchantId": "YOUR_MERCHANT_ID"
}
SBERBANK
"parameters": {
  "gateway": "sberbank",
  "gatewayMerchantId": "YOUR_ORGANIZATION_NAME"
}
الميدان
"parameters": {
  "gateway": "square",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
شريط
"parameters": {
  "gateway": "stripe",
  "stripe:version": "2018-10-31",
  "stripe:publishableKey": "YOUR_PUBLIC_STRIPE_KEY"
}
TAPPAY
"parameters": {
  "gateway": "tappay",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
TINKOFF
"parameters": {
  "gateway": "tinkoff",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
الوحدة
"parameters": {
  "gateway": "uniteller",
  "gatewayMerchantId": "YOUR_GATEWAY_MERCHANT_ID"
}
VANTIV
"parameters": {
  "gateway": "vantiv",
  "vantiv:merchantPayPageId": "YOUR_PAY_PAGE_ID",
  "vantiv:merchantOrderId": "YOUR_ORDER_ID",
  "vantiv:merchantTransactionId": "YOUR_TRANSACTION_ID",
  "vantiv:merchantReportGroup": "*web"
}
WORLDPAY
"parameters": {
  "gateway": "worldpay",
  "gatewayMerchantId": "YOUR_WORLDPAY_MERCHANT_ID"
}
YANDEX
"parameters": {
  "gateway": "yandexcheckout",
  "gatewayMerchantId": "YOUR_SHOP_ID"
}

حفظ بيانات الطلبات في مَعلمة الجلسة

من عملية التنفيذ، احفظ بيانات الطلب في مَعلمة جلسة. سيتم استخدام كائن الترتيب عبر المشاهد لنفس الجلسة.

conv.session.params.order = {
    '@type': 'type.googleapis.com/google.actions.transactions.v3.TransactionDecisionValueSpec',
    order: order,
    orderOptions: orderOptions,
    presentationOptions: presentationOptions,
    paymentParameters: paymentParameters
};

اقتراح الأمر

بعد إنشاء الطلب، يجب تقديمه إلى المستخدم لتأكيده أو رفضه. للقيام بذلك، يجب عليك الانتقال إلى مشهد يقوم بقرار المعاملة.

إنشاء مشهد قرار المعاملة

  1. من علامة التبويب مشاهد، أضِف مشهدًا جديدًا باسم TransactionDecision.
  2. ضمن ملء الفتحة، انقر على + لإضافة خانة جديدة.
  3. ضمن اختيار نوع، اختَر actions.type.TransactionDecisionValue كنوع الخانة.
  4. في حقل اسم الخانة، أدخِل الاسم TransactionDecision.
  5. فعِّل مربّع الاختيار تخصيص خانة كتابة قيمة الخانة (مفعّل تلقائيًا).
  6. ضمن ضبط الخانة، اختر استخدام مَعلمة الجلسة من القائمة المنسدلة.
  7. ضمن ضبط الخانة، أدخِل اسم معلمة الجلسة المستخدَمة لتخزين الترتيب في حقل النص (أي $session.params.order).
  8. انقر على حفظ.

في محاولة لملء فجوة TransactionDecisionValue، يبدأ "مساعد Google" تجربة مضمّنة يتم فيها عرض رمز Order الذي مررت به مباشرةً على "بطاقة معاينة سلة التسوّق". يمكن للمستخدم قول "تقديم طلب" أو رفض المعاملة أو تغيير خيار الدفع مثل بطاقة الائتمان أو العنوان أو طلب تغيير محتويات الطلب.

ويمكن للمستخدم أيضًا طلب إجراء تغييرات على الطلب في هذه المرحلة. في هذه الحالة، يجب عليك التأكد من أن عملية توصيل الطلبات يمكنها التعامل مع طلبات تغيير الطلبات بعد إنهاء تجربة تجميع عربة التسوق.

معالجة نتيجة قرار المعاملة

عندما يتم ملء خانة TransactionDecisionValue، سيتم تخزين إجابة المستخدم على قرار المعاملة في مَعلمة جلسة. تحتوي هذه القيمة على ما يلي:

  • ORDER_ACCEPTED,
  • ORDER_REJECTED,
  • DELIVERY_ADDRESS_UPDATED,
  • CART_CHANGE_REQUESTED
  • USER_CANNOT_TRANSACT.

لمعالجة نتيجة قرار المعاملة:

  1. من علامة التبويب مشاهد، اختَر مشهد TransactionDecision الذي تم إنشاؤه حديثًا.
  2. ضمن الشرط، انقر على + لإضافة شرط جديد.
  3. في حقل النص، أدخل بناء جملة الشرط التالي للتحقق من شرط النجاح:

    scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_ACCEPTED"
    
  4. مرِّر مؤشر الماوس فوق الشرط الذي أضفته للتو وانقر على السهم المتّجه للأعلى لوضعه قبل if scene.slots.status == "FINAL".

  5. يمكنك تفعيل إرسال المطالبات وتقديم رسالة مطالبة بسيطة تتيح للمستخدم معرفة اكتمال طلبه:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Transaction completed! Your order
                $session.params.TransactionDecision.order.merchantOrderId is all
                set!
    
  6. ضمن النقل، اختَر إنهاء المحادثة لإنهاء المحادثة.

  7. ضمن الشرط، انقر على + لإضافة شرط جديد.

  8. في حقل النص، أدخل بناء جملة الشرط التالي للتحقق من شروط الفشل:

      scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_REJECTED"
    
  9. مرِّر مؤشر الماوس فوق الشرط الذي أضفته للتو وانقر على السهم المتّجه للأعلى لوضعه قبل if scene.slots.status == "FINAL".

  10. فعِّل إرسال المطالبات وقدِّم رسالة مطالبة بسيطة تخبر المستخدم أنه قد تم رفض الطلب:

    candidates:
      - first_simple:
          variants:
            - speech: Look like you don't want to order anything. Goodbye.
    
  11. ضمن النقل، اختَر إنهاء المحادثة لإنهاء المحادثة.

  12. اختَر الشرط else if scene.slots.status == "FINAL".

  13. يمكنك تفعيل إرسال المطالبات وتقديم رسالة مطالبة بسيطة تتيح للمستخدم معرفة أنّه لا يمكنه إجراء معاملة:

    candidates:
      - first_simple:
          variants:
            - speech: >-
                Transaction failed with status
                $session.params.TransactionDecision.transactionDecision
    
  14. ضمن النقل، انقر على إنهاء المحادثة لإنهاء المحادثة إذا تعذّر على المستخدم إجراء المعاملات.

إنهاء الطلب وإرسال إيصال

عندما تعرض خانة TransactionDecisionValue نتيجة ORDER_ACCEPTED، يجب إجراء أي معالجة مطلوبة على الفور "لتأكيد" الطلب (مثل الاحتفاظ به في قاعدة بياناتك وتحصيل الرسوم من المستخدم).

يمكنك إنهاء المحادثة بهذا الرد، ولكن يجب عليك تضمين رد بسيط لإبقاء المحادثة قائمة. عند تقديم رسالة orderUpdate الأولى هذه، ستظهر للمستخدم "بطاقة إيصال مصغَّرة" مع بقية ردّك. ستعكس هذه البطاقة الإيصال الذي عثر عليه المستخدم في سجل الطلبات الخاصة به.

أثناء تأكيد الطلب، يمكن أن يتضمّن كائن الطلب userVisibleOrderId، وهو المعرّف الذي يظهر للمستخدم للطلب. يمكنك إعادة استخدام merchantOrderId لهذا الحقل.

يجب أن يتضمّن جزء من عنصر OrderUpdate عنصر إجراء متابعة، ويظهر في شكل أزرار عناوين URL في أسفل تفاصيل الطلب التي يمكن للمستخدم العثور عليها في سجلّ طلبات "مساعد Google".

  • عليك تقديم إجراء متابعة على الأقل VIEW_DETAILS مع كل طلب. يجب أن يحتوي هذا على رابط لموضع معيّن لتمثيل الطلب على تطبيق الهاتف المحمول أو موقع الويب.
  • عليك أيضًا إرسال إيصال رسمي عبر البريد الإلكتروني يفي بجميع المتطلبات القانونية لإجراء المعاملة، بالإضافة إلى بطاقة الإيصال في محادثة الإجراء الخاص بك.

لإرسال تعديل أولي للطلب:

  1. من علامة التبويب مشاهد، اختَر المشهد TransactionDecision.
  2. ضمن الشرط، اختَر الشرط الذي يتحقّق من نتيجة النجاح، ORDER_ACCEPTED:

      scene.slots.status == "FINAL" && session.params.TransactionDecision.transactionDecision == "ORDER_ACCEPTED"
    
  3. بالنسبة إلى هذا الشرط، فعِّل الاتصال للردّ التلقائي على الويب وأدخِل اسم معالج الغرض، مثل update_order.

  4. في رمز الرد التلقائي على الويب، أضِف معالج أهداف لإرسال تحديث الطلب الأولي:

    app.handle('update_order', conv => {
      const currentTime = new Date().toISOString();
      let order = conv.session.params.TransactionDecision.order;
      conv.add(new OrderUpdate({
        'updateMask': {
          'paths': [
            'purchase.status',
            'purchase.user_visible_status_label'
          ]
        },
        'order': {
          'merchantOrderId': order.merchantOrderId,
          'lastUpdateTime': currentTime,
          'purchase': {
            'status': 'CONFIRMED',
            'userVisibleStatusLabel': 'Order confirmed'
          },
        },
        'reason': 'Reason string
      }));
    });
    

إرسال آخر أخبار الطلب

ستحتاج إلى إبقاء المستخدم على اطلاع بحالة الطلب على مدار منذ إنشائه. أرسِل تحديثات طلب المستخدم من خلال إرسال طلبات HTTP PATCH إلى Orders API، بالإضافة إلى حالة الطلب وتفاصيله.

إعداد طلبات غير متزامنة لـ Orders API

يتم السماح بطلبات تعديل الطلبات إلى واجهة برمجة التطبيقات Orders API من خلال رمز دخول. للحصول على موافقة لتحديث طلب بخصوص واجهة برمجة التطبيقات Orders API، عليك تنزيل مفتاح حساب خدمة بتنسيق JSON مرتبط بمشروعك على "وحدة تحكّم المهام"، ثم استبدال مفتاح حساب الخدمة برمز حامل مميّز يمكن تمريره إلى رأس Authorization لطلب HTTP.

لاسترداد مفتاح حساب الخدمة، عليك اتّباع الخطوات التالية:

  1. في Google Cloud Console، انتقِل إلى القائمة أعضاء > واجهات برمجة التطبيقات والخدمات > بيانات الاعتماد > إنشاء بيانات اعتماد > مفتاح حساب الخدمة.
  2. ضمن حساب الخدمة، اختَر حساب خدمة جديد.
  3. اضبط حساب الخدمة على service-account.
  4. اضبط الدور على المشروع > المالك.
  5. اضبط نوع المفتاح على JSON.
  6. اختَر إنشاء.
  7. سيتم تنزيل مفتاح حساب خدمة JSON خاص على جهازك المحلي.

في رمز تعديلات الطلب، يمكنك استبدال مفتاح الخدمة برمز حامل مميز باستخدام مكتبة عملاء Google APIs ونطاق "https://www.googleapis.com/auth/actions.order.developer". يمكنك العثور على خطوات التثبيت وأمثلة عليه في مكتبة عميل واجهة برمجة التطبيقات على صفحة GitHub.

يمكنك أيضًا الرجوع إلى order-update.js في نموذج Node.js للحصول على مثال لتبادل المفاتيح.

إرسال آخر أخبار الطلب

بعد استبدال مفتاح حساب الخدمة برمز مميز لحامل OAuth، يمكنك إرسال آخر أخبار الطلبات إلى واجهة برمجة التطبيقات Orders API باعتبارها طلبات موافقة معتمَدة.

عنوان URL لواجهة برمجة تطبيقات الطلبات: PATCH https://actions.googleapis.com/v3/orders/${orderId}

قدِّم العناوين التالية في طلبك:

  • "Authorization: Bearer token" باستخدام رمز حامل OAuth المميز الذي استبدلت مفتاح حساب الخدمة به.
  • "Content-Type: application/json".

يجب أن يتخذ طلب PATCH نص JSON بالتنسيق التالي:

{ "orderUpdate": OrderUpdate }

يتألف الكائن OrderUpdate من حقول المستوى الأعلى التالية:

  • updateMask: حقول الترتيب الذي تُعدِّله لتحديث حالة الطلب، اضبط القيمة على purchase.status, purchase.userVisibleStatusLabel.
  • order - محتوى التحديث في حال تعديل محتوى الترتيب، اضبط القيمة على عنصر Order المعدّل. إذا كنت تعدّل حالة الطلب (على سبيل المثال، من "CONFIRMED" إلى "SHIPPED")، يحتوي العنصر على الحقول التالية:

    • merchantOrderId - رقم التعريف نفسه الذي حدّدته في عنصر Order
    • lastUpdateTime - الطابع الزمني لهذا التعديل
    • purchase - كائن يحتوي على ما يلي:
      • status - حالة الطلب على أنّه PurchaseStatus، مثل "SHIPPED" أو "DELIVERED".
      • userVisibleStatusLabel - تصنيف يظهر للمستخدم يوفّر تفاصيل عن حالة الطلب، مثل "تم شحن طلبك وهو في طريقه إليك".
  • userNotification يمكن عرضه على جهاز المستخدم عند إرسال هذا التحديث. ويُرجى العِلم بأنّ تضمين هذا الكائن لا يضمن ظهور إشعار على جهاز المستخدم.

يعرض الرمز النموذجي التالي مثالاً OrderUpdate الذي يعدّل حالة الطلب إلى DELIVERED:

// Import the 'googleapis' module for authorizing the request.
const {google} = require('googleapis');
// Import the 'request-promise' module for sending an HTTP POST request.
const request = require('request-promise');
// Import the OrderUpdate class from the client library.
const {OrderUpdate} = require('@assistant/conversation');

// Import the service account key used to authorize the request.
// Replacing the string path with a path to your service account key.
// i.e. const serviceAccountKey = require('./service-account.json')

// Create a new JWT client for the Actions API using credentials
// from the service account key.
let jwtClient = new google.auth.JWT(
    serviceAccountKey.client_email,
    null,
    serviceAccountKey.private_key,
    ['https://www.googleapis.com/auth/actions.order.developer'],
    null,
);

// Authorize the client
let tokens = await jwtClient.authorize();

// Declare order update
const orderUpdate = new OrderUpdate({
    updateMask: {
      paths: [
        'purchase.status',
        'purchase.user_visible_status_label'
      ]
    },
    order: {
      merchantOrderId: orderId, // Specify the ID of the order to update
      lastUpdateTime: new Date().toISOString(),
      purchase: {
        status: 'DELIVERED',
        userVisibleStatusLabel: 'Order delivered',
      },
    },
    reason: 'Order status updated to delivered.',
});

// Set up the PATCH request header and body,
// including the authorized token and order update.
let options = {
  method: 'PATCH',
  uri: `https://actions.googleapis.com/v3/orders/${orderId}`,
  auth: {
    bearer: tokens.access_token,
  },
  body: {
    header: {
      isInSandbox: true,
    },
    orderUpdate,
  },
  json: true,
};

// Send the PATCH request to the Orders API.
try {
  await request(options);
} catch (e) {
  console.log(`Error: ${e}`);
}
ضبط حالة الشراء

يجب أن يكون رمز status لتعديل الطلب موضّحًا للحالة الراهنة للطلب. في حقل order.purchase.status الخاص بالتحديث، استخدِم إحدى القيم التالية:

  • CREATED - تم قبول الطلب من قِبل المستخدم و "تم إنشاؤه" من منظور الإجراء الخاص بك، إلا أنّه يجب معالجة هذا الطلب يدويًا من الخلفية.
  • CONFIRMED - الطلب نشط وتتم معالجته.
  • IN_PREPARATION - يتم تجهيز الطلب للشحن/التسليم، مثل الطعام الذي يتم طهيه أو صنف يتم تعبئته.
  • READY_FOR_PICKUP - الطلب متاح لاستلامه من قِبل المستلِم.
  • DELIVERED - تم تسليم الطلب إلى المستلم.
  • OUT_OF_STOCK - غير متوفّر سلعة واحدة أو أكثر في الطلب
  • CHANGE_REQUESTED - طلب المستخدم إجراء تغيير على الطلب، وتتم معالجة التغيير.
  • RETURNED - تم إرجاع الطلب من قِبل المستخدم بعد التسليم.
  • REJECTED - إذا تعذّرت عليك معالجة الطلب أو تحصيل الرسوم منه أو "تفعيله" بأي طريقة أخرى.
  • CANCELLED - تم إلغاء الطلب بواسطة المستخدم.

يجب إرسال تحديثات الطلب لكل حالة ذات صلة بمعاملتك. على سبيل المثال، إذا كانت المعاملة تتطلّب معالجة يدوية لتسجيل الطلب بعد تقديمه، أرسِل تعديلاً على طلب CREATED إلى أن تنتهي المعالجة الإضافية. لا يتطلب كل طلب قيمة كل حالة.

اختبار مشروعك

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

  1. في وحدة تحكّم الإجراءات، انقر على اختبار في شريط التنقّل.
  2. انقر على الإعدادات.
  3. فعِّل خيار وضع الحماية للتطوير.

وبالنسبة إلى المعاملات المادية، يمكنك أيضًا ضبط الحقل isInSandbox على true في النموذج. يعادل هذا الإجراء تفعيل إعداد وضع الحماية في وحدة تحكُّم المهام. للاطّلاع على مقتطف رمز يستخدم isInSandbox، راجِع القسم إرسال تعديلات الطلب.

تحديد المشاكل وحلّها

في حال مواجهة أي مشاكل أثناء الاختبار، يُرجى الاطّلاع على خطوات تحديد المشاكل وحلّها للمعاملات.