Search code examples
paypalpaypal-sandboxpaypal-subscriptions

PayPal Api: How to test subscription payment


I have a MERN stack application which provides subscriptions for pro versions.

A user can click a paypal button and approve a subscription. This subscription is stored in my database by calling my backend with the subscriptionId. My backend calls paypal to get the subscriptions's data and stores the subscription in my database with the start_date, status and next_billing_date.

So now to my Problem.

How can I simulate, when an automatically payment for a subscription was made? Or is it still the shortest period of 1 day?

I implemented webhooks, reacting on following events:

  • BILLING.SUBSCRIPTION.ACTIVATED - store subscription in our database if not existing (should already exist with status=ACTIVE by onApprove function of paypal button)
  • PAYMENT.SALE.COMPLETED - how can I simulate this? I guess I receive a payment with date, amount and currency and have to get subscription again to find out my new next_billing_date
  • PAYMENT.SALE.REVERSED - I manually cancel the subscription in paypal and my database
  • BILLING.SUBSCRIPTION.PAYMENT.SUSPEND: I manually cancel the subscription in paypal and my database
  • BILLING.SUBSCRIPTION.CANCELLED - I manually cancel the subscription in my database How can I simulate those webhooks in sandbox mode (especially the auto payment) ? I know the webhook simulator, but this simulator has no real data. E.g. I can not see, if the subscription's next billing_date is the new one, since no real data were processed. So I have no clue how to update my subscriptions next_billing_date.

Is there maybe even a better practice to sync the paypal subscriptions and my database? I need to have the start_date, the next_billing_date and the status in my database to show them my users.

Thanks for any hints :)


Solution

  • If someone has a similar problem, here what I did.

    After testing different things, the only way is really to create a plan with a billing cycle of one day. After about 28h the next payment fired the PAYMENT.SALE.COMPLETED webhook event. Unfortunately it did't come with the next_billing_date of the subscription, so I needed to load the subscription from paypal afterwords.

    So I got following webhhok data at the next payment:

    {
      "id": "WH-33S38016N0419011P-7AL95866D0492814K",
      "create_time": "2023-10-19T09:47:30.276Z",
      "resource_type": "sale",
      "event_type": "PAYMENT.SALE.COMPLETED",
      "summary": "Payment completed for EUR 0.99 EUR",
      "resource": {
        "amount": {
          "total": "0.99",
          "currency": "EUR",
          "details": {
            "subtotal": "0.99"
          }
        },
        "payment_mode": "INSTANT_TRANSFER",
        "create_time": "2023-10-19T09:47:20Z",
        "custom": "27",
        "transaction_fee": {
          "currency": "EUR",
          "value": "0.37"
        },
        "billing_agreement_id": "I-TEL8DYVLFG7U",
        "update_time": "2023-10-19T09:47:20Z",
        "protection_eligibility_type": "ITEM_NOT_RECEIVED_ELIGIBLE,UNAUTHORIZED_PAYMENT_ELIGIBLE",
        "protection_eligibility": "ELIGIBLE",
        "links": [
          {
            "method": "GET",
            "rel": "self",
            "href": "https://api.sandbox.paypal.com/v1/payments/sale/65999752KJ722264U"
          },
          {
            "method": "POST",
            "rel": "refund",
            "href": "https://api.sandbox.paypal.com/v1/payments/sale/65999752KJ722264U/refund"
          }
        ],
        "id": "65999752KJ722264U",
        "state": "completed",
        "invoice_number": ""
      },
      "status": "SUCCESS",
      "transmissions": [
        {
          "webhook_url": "https://9b3f-2406-2d40-4190-3700-595d-5bd4-e11c-bb27.ngrok-free.app/api/webhooks/paypal",
          "http_status": 200,
          "reason_phrase": "HTTP/1.1 200 Connection established",
          "response_headers": {
            "Ngrok-Trace-Id": "1a9ba30dffa07ebde35fbd27456bc5a1",
            "Etag": "W/\"20-zDv+P2uwtTiLMaxSw7ZiOQQFwcY\"",
            "Connection": "keep-alive",
            "Vary": "Origin",
            "Content-Length": "32",
            "Date": "Thu, 19 Oct 2023 09:47:58 GMT",
            "Access-Control-Allow-Headers": "x-access-token, Origin, Content-Type, Accept",
            "X-Powered-By": "Express",
            "Content-Type": "text/html; charset=utf-8"
          },
          "transmission_id": "8cbf8250-6e64-11ee-8714-7b3d516c33ea",
          "status": "SUCCESS",
          "timestamp": "2023-10-19T09:47:43Z"
        }
      ],
      "links": [
        {
          "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-33S38016N0419011P-7AL95866D0492814K",
          "rel": "self",
          "method": "GET",
          "encType": "application/json"
        },
        {
          "href": "https://api.sandbox.paypal.com/v1/notifications/webhooks-events/WH-33S38016N0419011P-7AL95866D0492814K/resend",
          "rel": "resend",
          "method": "POST",
          "encType": "application/json"
        }
      ],
      "event_version": "1.0"
    }
    

    So I got my subscriptionId in resource.billing_agreement_id and loaded my subscription from paypal by calling subscription_get to get further informations.