Trouble receiving notifications from iTunes Connect about IAP status change events - ios

I've set up a URL on my server to receive auto-renewable IAP status change notifications per this article:
https://help.apple.com/itunes-connect/developer/#/dev0067a330b
And of course I've provided my URL to iTunes Connect via my app's main settings page.
However, I'm receiving neither update notifications nor any kind of message indicating that there's a problem.
Help troubleshooting? I don't even know where to start.
Thanks!

Have you checked secure network connection with your server? I mean that you have to check ATS on your server. I'm using nginx such as proxy server. First of all, you have to check your nginx system pair past with ATS to connect with apple server.
This method to check ATS pass on nginx server
nscurl --ats-diagnostics <your status receive url>
See more on apple documentation Using the nscurl Tool to Diagnose ATS Connection Issues
If your server passed. You are ready to receive response from apple.
My subscription status URL setup simple such as a simple http service created on nodejs ( express framwork )
const express = require('express')
const app = express()
const bodyParser = require('body-parser');
const path = require('path');
process.on('uncaughtException', function (err) {
console.log(err.stack);
});
process.on('exit', function (code) {
console.log('About to exit with code: ' + code);
});
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
app.post('/', function (req, res) {
console.log(req.body); < response from apple is here >
res.send({ ok: 1 });
})
const port = 12092;
app.listen(port, function () {
console.log('Subscription status url ping on port ' + port);
});
By the way, you should update your question. you can reference from a other relation question on your question. This's more helpful!.

Related

Socket-io iOS client says it's connected to server, despite "connection" event not firing on the server

I am having trouble wrapping my mind around this problem with my very basic Socket-IO setup. In short, the iOS client (running Socket.IO-Client-Swift), seems convinced that it has successfully connected to the socket on the server: The SocketIOClient has a status of connected. However, on the server the connection event is never fired.
When running the code below the iOS client prints Socket status: connected to the console once every 15 seconds or so, indicating that it has successfully connected to the server, and that the connection is maintained.
However, on the server, it appears that the "connection" event is never fired. NEW CONNECTION is never printed to the console on the server. The only console output is Server is running on port 4400..., indicating that the server is ready to accept connections.
When attempting to connect to the server via a web browser, NEW CONNECTION is printed to the console of the server, as expected. It appears that the problem is with the iOS code.
The complete code for the client and server is below.
Client:
class GMSockets {
private var manager: SocketManager = SocketManager(socketURL: URL(string: "ws://localhost:4400")!, config: [.log(false), .compress])
private var socket: SocketIOClient
init() {
self.socket = self.manager.defaultSocket
self.socket.on(clientEvent: .connect) { (data, ack) in
print("Socket status: \(self.socket.status)")
self.socket.emit("testEvent", "Hello")
}
self.socket.connect()
}
}
Server:
let port = 4400;
var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
server.listen(port);
console.log(`Server is running on port ${port}...`);
io.sockets.on("connection", function(socket) {
console.log("NEW CONNECTION")
socket.on("testEvent", function(data) {
console.log("Test event recieved")
})
})
I am using Socket.IO-Client-Swift version 15.2.0 on the iOS client, and Socket.io version 3.0.4 on the server.
The documentation for Socket.IO-Client-Swift erroneously suggests that it supports Socket-io 3.0, however it only supports versions 2.x.x. Downgrading socket.io to 2.3.0 (the last 2.x.x release) will fix this issue.

SocketIOClient- Swift : Unable to authenticate socket server

I am passing authentication token parameter like below...
socket = SocketIOClient(socketURL: URL(string:"http://localhost:3001")!, config: [.log(true), .forcePolling(true),.connectParams(["Authorisation": kToken])])
But it always gives an error....
LOG SocketParser: Decoded packet as: SocketPacket {type: 2; data: [login_ack, {
message = "InValid Token";
result = "";
status = error;
}]; id: -1; placeholders: -1; nsp: /}
As I think that I am missing some thing to establish authenticated socket connection. So, please guide me where I am lacking.
I have resolved it by my self!
It was the issue from back end team. They were put some dependencies with the socket call back sender device information details which they are taking from the socket call backs. And the actual problem was ,all the devices and computers were providing their device details but iOS was not giving it from their end with their security protection.So,their validity condition were not satisfying for iOS socket call backs.
Backend team handled this situation by putting "Other" device type checking at their end.

Sandbox apple pay testing handshake failure

I am having trouble validating the merchant in my apple pay sandbox environment. Taken from https://developer.apple.com/reference/applepayjs/applepaysession#2166532, once my server then calls the Start Session endpoint at the provided URL, I get a 500 error.
I've dug around and this 500 error is happening somewhere in the network layer. As listed on the apple page (https://developer.apple.com/reference/applepayjs/), I need the following requirements met:
All pages that include Apple Pay must be served over HTTPS. done, server has ssl/https sitewide
To enable merchant validation, your server must allow access over HTTPS (TCP over port 443) to the Apple Pay IP addresses provided in Listing 1 below. done, server is open to all ips on port 443
Your server must support the Transport Layer Security (TLS) 1.2 protocol and one of the cipher suites listed in Table 1. server does support tls 1.2, since I send requests on tls 1.2 to apple pay's development server (below)
I've been using Wireshark to check what's going on, and I seem to be failing once the server is in the ChangeCipherSpec phase, after the server sends back the cipher spec to the client. (Reference for ssl procedure: https://support.f5.com/csp/article/K15292). As you can see from my image, I'm communicating to the apple pay sandbox server, passing in the same supported tls protocol and cipher suite that the error would suggest -> Handshake Failure (40), so something else is going on and I don't know where to look
If you look at the ServerHello message, you can see the server found and accepted the cipher suite that matches the client, which also matches one of the required ciphers that apple pay supports
I can add other details as necessary
The issue was that our server did not have TLS 1.2 enabled by default. Enabling TLS 1.2 and disabling TLS 1.0 fixed the issue - Win 2008
edit
There are a few things that needed to happen. Our server was on .net 4.5, which does not use tls 1.2 by default (apple requires tls 1.2 to be used). So, we upgraded our solution to .net 4.6, and also forced tls 1.2 for our request. Additionally, we have to include the merchant id certificate in our request to apple (which isn't mentioned in the docs very well).
You can find the github repo of the source I used here (https://github.com/justeat/ApplePayJSSample), but here is my code that I needed to put in my solution to make things work (I also had to export my merchant certificate from my mac's keychain that gave me a .p12 file. I imported this .p12 file into my server's computer certificate store)
[System.Web.Http.HttpPost]
public async Task<ContentResult> GetApplePaySession([FromBody] string url)
{
// http://stackoverflow.com/a/36912392/1837080
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
// Load the merchant certificate for two-way TLS authentication with the Apple Pay server.
var certificate = LoadMerchantCertificate();
// Get the merchant identifier from the certificate to send in the validation payload.
var merchantIdentifier = GetMerchantIdentifier(certificate);
// Create the JSON payload to POST to the Apple Pay merchant validation URL.
var payload = new ApplePayRequest()
{
merchantIdentifier = merchantIdentifier,
domainName = System.Web.HttpContext.Current.Request.Url.Host,
displayName = "[display name from apple developer portal]"
};
JObject merchantSession;
// Create an HTTP client with the merchant certificate
// for two-way TLS authentication over HTTPS.
using (var httpClient = CreateHttpClient(certificate))
{
var jsonPayload = JsonConvert.SerializeObject(payload);
using (var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json"))
{
// POST the data to create a valid Apple Pay merchant session.
using (var response = await httpClient.PostAsync(url, content))
{
response.EnsureSuccessStatusCode();
// Read the opaque merchant session JSON from the response body.
var merchantSessionJson = await response.Content.ReadAsStringAsync();
merchantSession = JObject.Parse(merchantSessionJson);
}
}
}
// Return the merchant session as JSON.
return Content(merchantSession.ToString(), "application/json");
}
#region Apple Pay helper methods
private X509Certificate2 LoadMerchantCertificate()
{
X509Certificate2 certificate;
// Load the certificate from the current user's certificate store. This
// is useful if you do not want to publish the merchant certificate with
// your application, but it is also required to be able to use an X.509
// certificate with a private key if the user profile is not available,
// such as when using IIS hosting in an environment such as Microsoft Azure.
using (var store = new X509Store(StoreName.My, StoreLocation.LocalMachine))
{
store.Open(OpenFlags.ReadOnly);
// when using thumbprint from mmc, look at:
// http://stackoverflow.com/a/14852713
// there is a hidden character that you must delete
var certificates = store.Certificates.Find(
X509FindType.FindByThumbprint,
"[thumbprint]",
validOnly: false);
if (certificates.Count < 1)
{
throw new InvalidOperationException(
// ReSharper disable once UseStringInterpolation
string.Format(
"Could not find Apple Pay merchant certificate with thumbprint '{0}' from store '{1}' in location '{2}'.",
"‎[thumpprint]", store.Name, store.Location));
}
certificate = certificates[0];
}
return certificate;
}
private string GetMerchantIdentifier(X509Certificate2 certificate)
{
// This OID returns the ASN.1 encoded merchant identifier
var extension = certificate.Extensions["1.2.840.113635.100.6.32"];
// Convert the raw ASN.1 data to a string containing the ID
return extension == null ? string.Empty : Encoding.ASCII.GetString(extension.RawData).Substring(2);
}
private HttpClient CreateHttpClient(X509Certificate2 certificate)
{
var handler = new WebRequestHandler();
handler.ClientCertificates.Add(certificate);
return new HttpClient(handler, disposeHandler: true);
}
#endregion
I just recently went through this. For me I had to merge the PEM and KEY files into a PFX. Then I was able to run the start session call from ubuntu 16.04 using .net core 2.1
private HttpClient CreateHttpClient()
{
var handler = new HttpClientHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.SslProtocols = SslProtocols.Tls12;
handler.ClientCertificates.Add(new X509Certificate2(#"/path/yourcombinedpfx.pfx"));
return new HttpClient(handler); ;
}

SignalR, Messages are to be pushed by the Server without any event triggered by the client

There are running examples of SignalR, but in those, i have seen that the process is started by the client i.e. every piece of code contains following similar lines
$.connection.hub.start().done(function () {
$('#mybutton').click(function () {
notifier.server.doLongOperation();
});
});
The process on server starts on $('#mybutton').click and then responds.
Is my understanding correct? If yes then is it possible to start the process by Server? I mean Server will push messages to all clients without any triggering from the client side.
This didn't work
var context = GlobalHost.ConnectionManager.GetHubContext<Broadcast>();
context.Clients.All.Send(message);
My bad, method name on client side was incorrect. Problem solved
Yes it is possible to send server initiated "messages" from the server to clients. Note that you have to call a method on the client. Note that it's a RPC/Remoting type of communication.
On the server you'd have a code like this:
Clients.All.Say("Hello World!");
where the client needs to define a function:
myHub.client.say = function (message) {
console.log(message);
});
see the SignalR documentation

Pusher auto reconnect when detecting errors / disconnect

Is there some way to reconnect to Pusher if any error or non-connected state is found?
Here's our connection code:
var pusher = new Pusher('<apikey>', {encrypted: true});
var state = pusher.connection.state;
pusher.connection.bind( 'error', function( err ) {
console.log(err);
});
pusher.connection.bind('state_change', function(states) {
// states = {previous: 'oldState', current: 'newState'}
console.log(states);
});
The Pusher JavaScript library automatically attempts reconnection. You don't need to add any code to support this.
I can't find this anywhere in the Pusher docs, but I know this for a fact as I worked for Pusher for 2 years.
You can test by going to http://test.pusher.com/ and disconnecting from the Internet and then reconnecting again. The logging will show it is auto-reconnecting.

Resources