No
I print the json.dumps(payload)
Get this
JSON payload ============
{"termsOfServiceAgreed": true, "contact": ["mailto:test_mail_new@sina.com"]}
No
I print the json.dumps(payload)
Get this
JSON payload ============
{"termsOfServiceAgreed": true, "contact": ["mailto:test_mail_new@sina.com"]}
That looks much better. 
You even got the email array correct.
but it is still get the same error response
Let's see... 
You only use PHP ?
Or you also use python ?
Only PHP. Nothing else.
This function is not producing correct base64url encoding.
Try using url64.encode instead (as with the signature).
Is this:
base64.urlsafe_b64encode(json.dumps(protected_header))
converting (+ -> -) and (/ -> _) ?
So I was on target! 
It doesn't work.....
What's the current state?
I've moved the thread to the Client dev, which is more appropriate IMO.
Absolutely right. 
What doesn't work? I tried changing your program with that exact change, and the parse error is gone:
{'Strict-Transport-Security': 'max-age=604800', 'Server': 'nginx', 'Connection': 'keep-alive', 'Link': '<https://acme-staging-v02.api.letsencrypt.org/directory>;rel="index"', 'Cache-Control': 'public, max-age=0, no-cache', 'Date': 'Fri, 11 Dec 2020 09:05:36 GMT', 'X-Frame-Options': 'DENY', 'Replay-Nonce': '0003HnIFgBGglxRQ5-8oTG2jR30zha5IlAPhs0aBvQL-urA'}
Nonce is: 0003HnIFgBGglxRQ5-8oTG2jR30zha5IlAPhs0aBvQL-urA
{'protected': u'eyJub25jZSI6ICJNREF3TTBodVNVWm5Ra2RuYkhoU1VUVXRPRzlVUnpKcVVqTXdlbWhoTlVsc1FWQm9jekJoUW5aUlRDMTFja0UiLCAiYWxnIjogIkVTMjU2IiwgInVybCI6ICJodHRwczovL2FjbWUtc3RhZ2luZy12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL25ldy1hY2N0In0', 'payload': u'eyJ0ZXJtc09mU2VydmljZUFncmVlZCI6IHRydWUsICJjb250YWN0IjogWyJtYWlsdG86dGVzdF9tYWlsX25ld0BzaW5hLmNvbSJdfQ'}
{"payload":"eyJ0ZXJtc09mU2VydmljZUFncmVlZCI6IHRydWUsICJjb250YWN0IjogWyJtYWlsdG86dGVzdF9tYWlsX25ld0BzaW5hLmNvbSJdfQ","protected":"eyJ0ZXJtc09mU2VydmljZUFncmVlZCI6IHRydWUsICJjb250YWN0IjogWyJtYWlsdG86dGVzdF9tYWlsX25ld0BzaW5hLmNvbSJdfQ","signature":"kDvWyaUmvNkaE6O6RBfDzMf1kThGYmUx4eP_dxd33zrNudhlA6f6ejTV9zQ-cjz5Eb4OwSPj2ybvKjrDBMR_6A"}
=======req=======
{'payload': u'eyJ0ZXJtc09mU2VydmljZUFncmVlZCI6IHRydWUsICJjb250YWN0IjogWyJtYWlsdG86dGVzdF9tYWlsX25ld0BzaW5hLmNvbSJdfQ',
'protected': u'eyJub25jZSI6ICJNREF3TTBodVNVWm5Ra2RuYkhoU1VUVXRPRzlVUnpKcVVqTXdlbWhoTlVsc1FWQm9jekJoUW5aUlRDMTFja0UiLCAiYWxnIjogIkVTMjU2IiwgInVybCI6ICJodHRwczovL2FjbWUtc3RhZ2luZy12MDIuYXBpLmxldHNlbmNyeXB0Lm9yZy9hY21lL25ldy1hY2N0In0',
'signature': u'eyJwYXlsb2FkIjoiZXlKMFpYSnRjMDltVTJWeWRtbGpaVUZuY21WbFpDSTZJSFJ5ZFdVc0lDSmpiMjUwWVdOMElqb2dXeUp0WVdsc2RHODZkR1Z6ZEY5dFlXbHNYMjVsZDBCemFXNWhMbU52YlNKZGZRIiwicHJvdGVjdGVkIjoiZXlKMFpYSnRjMDltVTJWeWRtbGpaVUZuY21WbFpDSTZJSFJ5ZFdVc0lDSmpiMjUwWVdOMElqb2dXeUp0WVdsc2RHODZkR1Z6ZEY5dFlXbHNYMjVsZDBCemFXNWhMbU52YlNKZGZRIiwic2lnbmF0dXJlIjoia0R2V3lhVW12TmthRTZPNlJCZkR6TWYxa1RoR1ltVXg0ZVBfZHhkMzN6ck51ZGhsQTZmNmVqVFY5elEtY2p6NUViNE93U1BqMnlidktqckRCTVJfNkEifQ'}
========response========
{'Content-Length': '114', 'Server': 'nginx', 'Connection': 'keep-alive', 'Link': '<https://acme-staging-v02.api.letsencrypt.org/directory>;rel="index"', 'Cache-Control': 'public, max-age=0, no-cache', 'Date': 'Fri, 11 Dec 2020 09:05:37 GMT', 'Content-Type': 'application/problem+json', 'Replay-Nonce': '0004QvKnZI77i7CzD24uKbbEfz9hERhkz5AI8aXLMC-mbC8'}
{u'status': 400, u'type': u'urn:ietf:params:acme:error:malformed', u'detail': u'No embedded JWK in JWS header'}
You have other errors now that you need to deal with, but that's not surprising.
Now is this one:
Get the same error
import requests
import url64
import json
import base64
from jwcrypto import jwk, jws
from jwcrypto.common import json_encode
from pprint import pprint as pp
#
# HEAD newNonce
#
resp = requests.head('https://acme-staging-v02.api.letsencrypt.org/acme/new-nonce')
pp(resp.headers)
replay_nonce = resp.headers['Replay-Nonce']
print 'Nonce is:'
pp(replay_nonce)
session = requests.Session()
session.headers.update({'Content-Type': 'application/jose+json'})
key = jwk.JWK.generate(kty='EC')
jwk_param = key.export()
protected_header = {
"alg": "ES256",
"nonce": replay_nonce,
"url": "https://acme-staging-v02.api.letsencrypt.org/acme/new-acct",
"jwk": jwk_param
}
payload = {
"termsOfServiceAgreed": True,
"contact": [
"mailto:test_mail_new@sina.com"
]
}
req = {
"protected": url64.encode(json.dumps(protected_header)),
"payload": url64.encode(json.dumps(payload)),
}
print req
jwstoken = jws.JWS(json.dumps(payload))
jwstoken.add_signature(
key,
'ES256',
json.dumps(payload),
# header=header,
# json_encode({"kid": key.thumbprint()})
)
sig = jwstoken.serialize()
print sig
req.update({"signature": url64.encode(sig)})
print '=======req======='
pp(req)
resp = session.post(
url='https://acme-staging-v02.api.letsencrypt.org/acme/new-acct',
json=req,
)
print '========response========'
print resp.headers
print resp.json()
Oh, it is so sad....
I said this earlier and it got fixed lower down. You're using the older code, I think. Do you get the same result from the tip code two posts above?
How about the signature method ?
Is it correct ?
I do this:
openssl_sign("$protected.$payload", $signature, $this->accountPrivateKeyPEM, "sha256WithRSAEncryption")
have you got the correct response?