Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PayPal REST API - State doesn't change after purchase

Tags:

paypal

So I have noticed that when checking on the status of a payment

GET /v1/payments/payment/<Payment-Id>

the "state" of a PayPal response does not change from "created" even after the PayPal user has purchased the item. It isn't until I execute the payment that the state changes to "approved".

This makes it difficult to tell the difference between a payment that has actually been approved by a client and one that is still in process as they are both in the "created" state. The only difference in the json response is that it seems to include shipping_address once the payment has actually been approved. I'm not sure that is a standard way to denote the difference though.

What is the standard way to tell if a client has actually approved a PayPal transaction when using the above call to the REST API?

Note: I already have the PHP callback scripts setup and working. I am working on a fail safe system that constantly checks database entries to make sure an approved payment was executed (in case of some system failure).

I thought I could use the IPN callback script I have setup from CLASSIC API but it seems that the REST API and CLASSIC API are not compatible since the IPN callback will not contain a transaction id or any necessary information to be useful.

It seems like when using the REST API, if you miss the redirect call to your webserver then that transaction is lost forever.

like image 963
Josh Brittain Avatar asked Oct 19 '22 16:10

Josh Brittain


1 Answers

It is correct that you won't tell an approved payment from the state field in the lookup API response, instead, you would look for the payer object in the JSON body, and that piece of info will indicate an approved payment resource for you.

Here're the JSON responses of the same PAY-ID before/after the customer redirection (user approval)

  1. Lookup payment /v1/payments/payment/PAY-9J02491382988403BK3BMC6I (before user approval):

    {
       "id": "PAY-9J02491382988403BK3BMC6I",
       "intent": "sale",
       "state": "created",
       "cart": "07U14103P0008801U",
       "transactions": [   {
          "amount":       {
             "total": "80.00",
             "currency": "USD"
          },
          "payee": {"email": "[email protected]"},
          "invoice_number": "55a460ff696br",
          "item_list":       {
             "items":          [
                            {
                   "name": "Test Ticket 1",
                   "sku": "55a460ff65f13",
                   "price": "10.00",
                   "currency": "USD",
                   "quantity": 1
                },
                            {
                   "name": "Test Ticket 2",
                   "sku": "55a460ff66c7a",
                   "price": "20.00",
                   "currency": "USD",
                   "quantity": 2
                },
                            {
                   "name": "Test Ticket 3",
                   "sku": "55a460ff66ce2",
                   "price": "10.00",
                   "currency": "USD",
                   "quantity": 3
                }
             ],
             "shipping_address":          {
                "recipient_name": "Test Name",
                "line1": "Main St 1",
                "city": "San Jose",
                "state": "CA",
                "postal_code": "95131",
                "country_code": "US"
             }
          },
          "related_resources": [],
          "notify_url": "https://bt-pduan-1.c9.io/ipn.php"
       }],
       "redirect_urls":    {
          "return_url": "http://localhost:80/getpaypal?paymentId=PAY-9J02491382988403BK3BMC6I",
          "cancel_url": "http://localhost:80/cancel"
       },
       "create_time": "2016-02-16T06:28:08Z",
       "update_time": "2016-02-16T06:28:08Z",
       "links":    [
                {
             "href": "https://api.sandbox.paypal.com/v1/payments/payment/PAY-9J02491382988403BK3BMC6I",
             "rel": "self",
             "method": "GET"
          },
                {
             "href": "https://api.sandbox.paypal.com/v1/payments/payment/PAY-9J02491382988403BK3BMC6I/execute",
             "rel": "execute",
             "method": "POST"
          },
                {
             "href": "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-07U14103P0008801U",
             "rel": "approval_url",
             "method": "REDIRECT"
          }
       ]
    }
    
  2. Lookup the payment after user approval (I'm removing some JSON contents e.g. transaction/url arrays for readablity):

    {
       "id": "PAY-9J02491382988403BK3BMC6I",
       "intent": "sale",
       "state": "created",
       "cart": "07U14103P0008801U",
       "payer":    {
          "payment_method": "paypal",
          "status": "VERIFIED",
          "payer_info":       {
             "email": "[email protected]",
             "first_name": "Payer",
             "last_name": "US",
             "payer_id": "8FMFQ2KVYYHTY",
             "shipping_address":          {
                "recipient_name": "Test Name",
                "line1": "Main St 1",
                "city": "San Jose",
                "state": "CA",
                "postal_code": "95131",
                "country_code": "US"
             },
             "phone": "408-743-9795",
             "country_code": "US",
             "billing_address":          {
                "line1": "1 Main St",
                "line2": "",
                "city": "San Jose",
                "state": "CA",
                "postal_code": "95131",
                "country_code": "US"
             }
          }
       },
       "transactions": [],
       "redirect_urls": {},
       "create_time": "2016-02-16T06:28:08Z",
       "update_time": "2016-02-16T06:28:08Z",
       "links": []
    }
    

By checking the recorded PAY-ID looking for payer object in the API response, your will be able to save the orders and proceed the execute call in case it was missed in the customer return redirection.

Additionaly, neither IPN or webhooks would help in this case as they are async meesages triggered by transactional level events, which means there will be no notification until a payment is executed.

like image 175
pp_pduan Avatar answered Jan 04 '23 06:01

pp_pduan