[RUBY] [Offre d'abonnement Apple] Comment créer une signature d'offre promotionnelle

tl;dr

Il n'y avait aucune information sur les offres promotionnelles pour les offres d'abonnement d'Apple. ** Ceci est le premier document du Japon. ** **

Qu'est-ce qu'une offre promotionnelle?

Vidéo WWDC 2019

https://developer.apple.com/videos/play/wwdc2019/305

Documentation officielle Apple

https://developer.apple.com/jp/app-store/subscriptions/#subscription-offers

7ec9cdbd-1f10-4e9a-a5a5-c76e2c99f9ee.png

Cela s'applique aux clients qui utilisent actuellement ou ont utilisé l'abonnement dans le passé. Avec ces offres, pour augmenter et maintenir le nombre d'utilisateurs Vous aurez la possibilité de réaliser vos propres promotions. Grâce à la campagne, les utilisateurs qui ont annulé leur abonnement peuvent être encouragés à se réinscrire, Vous pouvez proposer une mise à niveau vers un autre abonnement à un prix spécial.

Préparation

Documentation officielle Apple

Mettre en place une offre d'abonnement

https://developer.apple.com/jp/documentation/storekit/in-app_purchase/setting_up_subscription_offers/

la mise en oeuvre

** * Cette fois, nous ne décrirons que la création de signature côté serveur **

Documentation officielle Apple

Générer des signatures pour des offres promotionnelles https://developer.apple.com/jp/documentation/storekit/in-app_purchase/generating_a_signature_for_subscription_offers/

Ce dont vous avez besoin pour générer une signature

スクリーンショット 2020-09-10 12.16.24.png

■appBundleID Avoir des variables d'environnement ■keyIdentifier Avoir des variables d'environnement ■productIdentifier Obtenir des paramètres du côté de l'application ■offerIdentifier Obtenir des paramètres du côté de l'application ■applicationUsername Obtenir des paramètres du côté de l'application ■nonce Générer côté serveur ■timestamp Générer côté serveur

Signature

スクリーンショット 2020-09-10 12.45.19.png

Génération de signature

Exemple de code À l'origine, il est divisé par méthode, mais l'accent est mis sur la clarté

require 'openssl'
require 'base64'
require 'securerandom'
require 'json'

#Lire comme une variable d'environnement, mais osez la décrire
private_key = '-----BEGIN PRIVATE KEY-----xxxxxxxxxxxxxxxxxxx-----END PRIVATE KEY-----'

#Empêche le code de saut de ligne de la clé privée lue à partir de la variable d'environnement d'être échappé
private_key = OpenSSL::PKey::EC.new(private_key.gsub(/\\n/, "\n")))

app_bundle_id = 'xxxx'
key_identifier = 'xxxx'
product_identifier = 'xxxx'
offer_identifier = 'xxxx'
application_username = 'xxxx'
nonce = SecureRandom.uuid
timestamp = (Time.current.to_f * 1000).to_i.to_s

#Séparateur invisible ('\u2063') Entre les paramètres et combiner

payload = app_bundle_id + "\u{2063}" +
          key_identifier + "\u{2063}" +
          product_identifier + "\u{2063}" +
          offer_identifier + "\u{2063}" +
          application_username + "\u{2063}" +
          nonce + "\u{2063}" +
          timestamp

#Signature

# Ruby2.4.Si c'est 0 ou plus tard
# signature = private_key.sign(digest, data)

# SHA-Signé avec 256 hachages
signature = private_key.dsa_sign_asn1(OpenSSL::Digest::SHA256.digest(payload))

#Encoder en base64
# strict_Utilisez encode64 pour effacer le code de saut de ligne
signature_base64 = Base64.strict_encode64(signature)


#Vérification

# OpenSSL::PKey::Générer un objet EC
ec = OpenSSL::PKey::EC.new(private_key.group)
ec.public_key = private_key.public_key

# SHA-Valider avec 256 hachages
digest = OpenSSL::Digest::SHA256.new

#Vérifiez que la chaîne de signature qui a signé la charge utile avec la clé privée est une signature à l'aide de la clé publique
ec.verify(digest, signature, payload)

result = { key_identifier: key_identifier, nonce: nonce, timestamp: timestamp, signature: signature_base64 }.to_json

À propos de l'algorithme de signature numérique à courbe elliptique (ECDSA)

Au début, je pensais utiliser une gemme appelée ruby_ecdsa https://github.com/DavidEGrayson/ruby_ecdsa

require 'ecdsa'
require 'securerandom'
require 'digest/sha2'

group = ECDSA::Group::Secp256k1

private_key = 1 + SecureRandom.random_number(group.order - 1)
public_key = group.generator.multiply_by_scalar(private_key)

message = 'ECDSA is cool.'
digest = Digest::SHA2.digest(message)

temp_key = 1 + SecureRandom.random_number(group.order - 1)
signature = ECDSA.sign(group, private_key, digest, temp_key)

valid = ECDSA.valid_signature?(public_key, digest, signature)
puts "valid: #{valid}"

Cependant, comme la clé privée a été conçue en supposant une valeur numérique, j'ai oublié de l'utiliser.

Exemple de création de signature officielle Apple

Exemple utilisant JavaScript et Node.js

https://developer.apple.com/documentation/storekit/in-app_purchase/subscriptions_and_offers/generating_a_subscription_offer_signature_on_the_server

Démarrez le serveur et obtenez une réponse lorsque vous y accédez

Recommended Posts

[Offre d'abonnement Apple] Comment créer une signature d'offre promotionnelle
Comment créer une méthode
[Swift5] Comment créer un écran de démarrage
[rails] Comment créer un modèle partiel
Comment créer une base de données H2 n'importe où
[Rails] Comment créer un graphique à l'aide de lazy_high_charts
Comment créer des pages pour le tableau "kaminari"
Comment créer une classe qui hérite des informations de classe
Comment créer un thème dans Liferay 7 / DXP
[1st] Comment créer un projet de framework Spring-MVC
Comment créer facilement un pull-down avec des rails
[Rails] Comment créer un bouton de partage Twitter
Comment créer docker-compose
Comment créer un environnement Java en seulement 3 secondes
Comment créer une URL JDBC (Oracle Database, Thin)
Comment créer un projet Spring Boot dans IntelliJ
[Spring Boot] Comment créer un projet (pour les débutants)
Comment créer un URI de données (base64) en Java
Comment laisser un commentaire
Comment insérer une vidéo
Comment créer une image de conteneur légère pour les applications Java
Comment créer un formulaire pour sélectionner une date dans le calendrier
Comment créer une partie d'espace réservé à utiliser dans la clause IN
Comment créer et lancer un Dockerfile pour Payara Micro
Comment créer un fichier jar et un fichier war à l'aide de la commande jar
Préparation à la création de l'application Rails
Comment créer un conteneur Java
[Rails 6] Comment créer un écran de saisie de formulaire dynamique à l'aide de cocoon
Comment signer Minecraft MOD
Comment créer un pilote JDBC
Comment créer un nouveau projet Gradle + Java + Jar dans Intellij 2016.03
[Swift] Comment envoyer une notification
Comment créer un écran de démarrage
Comment créer un plug-in Jenkins
Comment faire un projet Maven
Essayez de créer une application client serveur
Comment créer un serveur Web sur une instance EC2 d'AWS
Comment créer un tableau Java
Comment créer une requête à l'aide de variables dans GraphQL [Utilisation de Ruby on Rails]
[Docker] Comment créer un environnement virtuel pour les applications Rails et Nuxt.js
Comment créer un validateur qui n'autorise la saisie que dans un seul champ
Exécutable serveur avec Spring gradle Comment créer JAR et WAR
[Rails] Comment créer une table, ajouter une colonne et changer le type de colonne
Comment créer une méthode pratique qui utilise des génériques et une interface fonctionnelle
Comment exécuter un contrat avec web3j
Comment trier une liste à l'aide du comparateur
Comment créer un résumé de calendrier Java
Un mémorandum sur l'utilisation d'Eclipse
[Basique] Comment écrire un auto-apprentissage Dockerfile ②
Comment insérer une vidéo dans Rails
Comment ajouter un nouveau hachage / tableau
[Introduction à Java] Comment écrire un programme Java
Comment créer un robot Discord (Java)