APNs push provider

Important: On March 31 2021 Apple has discontinued the APNs legacy binary protocol. Therefore, the com.APNS class is now desupported. The documentation pages related to the APNS binary protocol are still provided for information. Contact your support center, if you need to implement APNS with the new HTTP/2-based provider API.

The com.APNS class can be used to implement an APNs push provider.

The following code example implements a push program using the com.APNS API to send a notification message to devices by using the TCP request API. See also com.APNS methods for more details about the APNs API.

Note: An SSL/TLS certificate needs to be defined in FGLPROFILE, as described in APNs SSL/TLS certificate.
Note: The size of the resulting BYTE variable containing the APNS payload cannot exceed 2 Kilobytes.
Important: In order to check that the push message was properly handled by the APNs server, you need to define a TCP request timeout (2 seconds in this example). In case of error, the APNs server will return a response immediately. In case of success, there is no response from the APNs server. For more details about this protocol, see Apple's APNs documentation.
IMPORT com
IMPORT security
IMPORT util

MAIN
  DEFINE json STRING
  DEFINE deviceTokenHexa STRING
  DEFINE req com.TCPRequest
  DEFINE resp com.TCPResponse
  DEFINE uuid STRING
  DEFINE ecode INTEGER
  DEFINE dt DATETIME YEAR TO SECOND
  DEFINE exp INTEGER
  DEFINE data, err BYTE

  LOCATE data IN MEMORY
  LOCATE err IN MEMORY

  LET deviceTokenHexa = "84e3................."
  LET dt = CURRENT + INTERVAL(10) MINUTE TO MINUTE
  LET exp = util.Datetime.toSecondsSinceEpoch(dt)
  TRY  
    LET req = com.TCPRequest.create( "tcps://gateway.push.apple.com:2195" )
    CALL req.setKeepConnection(true)
    CALL req.setTimeout(2) # Wait 2 seconds for APNs to return an error code
    LET uuid = security.RandomGenerator.createRandomString(4)
    LET json = '{"aps":{"alert":"Hello, world","sound":"default","badge":1,"content-available":1}}'    
    CALL com.APNS.EncodeMessage(
                  data,
                  security.HexBinary.ToBase64(deviceTokenHexa),
                  json,
                  uuid,
                  exp,
                  10
             )
    IF LENGTH(data) > 2000 THEN
       DISPLAY "APNS payload cannot exceed 2 kilobytes"
       EXIT PROGRAM 1
    END IF
    DISPLAY "Sending notif with ID:",uuid," and expiring at ",dt
    CALL req.doDataRequest(data)
    LET resp = req.getResponse()
    TRY
        CALL resp.getDataResponse(err)        
        CALL com.APNS.DecodeError(err) RETURNING uuid, ecode
        DISPLAY "ERROR code :",ecode
        DISPLAY "ERROR uuid :",uuid
    CATCH
        CASE STATUS
          WHEN -15553 DISPLAY "Timeout Push sent without error"
          WHEN -15566 DISPLAY "Operation failed :", SQLCA.SQLERRM
          WHEN -15564 DISPLAY "Server has shutdown"
          OTHERWISE   DISPLAY "ERROR :",STATUS
        END CASE
    END TRY
  CATCH
    DISPLAY "ERROR :",STATUS||" ("||SQLCA.SQLERRM||")"
  END TRY

END MAIN