Ücretsiz
DeneyinUygulama → otpmock → Test
- Ayda 300 mesaj
- 1 kullanıcı, 1 API anahtarı
- 15 SMS sağlayıcı API'sinin hepsi
- Canlı gelen kutusu
SMS Uçtan uca testler için sahte gelen kutusu
Kayıt, giriş ya da işlem onayı testiniz bir SMS kodunda mı takılıyor? otpmock, kullandığınız SMS sağlayıcısının API'sini birebir taklit eden, barındırılan bir gelen kutusudur. Uygulamanız SMS'i her zamanki gibi gönderir; mesaj hiçbir operatöre gitmez, testiniz kodu HTTPS ile alır. Netgsm, İleti Merkezi, Verimor, Mutlucell ve 11 sağlayıcı daha desteklenir; kodu sağlayıcının ürettiği Verify API'leri dahil.
Ücretsiz plan: ayda 300 mesaj, kart gerekmez.
Bu pano bir demo. Üzerindeki hiçbir şey bir telefona ulaşmadı, testlerinizin gönderdiği hiçbir şey de ulaşmayacak.
Şunlarla çalışır Playwright / Cypress / Selenium / WebdriverIO / Puppeteer / TestCafe / Appium / Maestro / Detox / Postman / Robot Framework / k6 / herhangi bir HTTP istemcisi
1 Sorun
Akışın kendisi çalışıyor, ama test takımı dördüncü adımda bir SMS'in gelmesini bekliyor. Bilinen çözümlerin her birinin bir bedeli var.
Her CI koşusu SMS kredinizden yer. Teslim süresini operatör belirlediği için testler rastgele zaman aşımına düşer. Üstelik kodu geri okumak için yine bir telefon ya da ücretli bir gelen kutusu gerekir.
if (telefon === TEST_NO) kod = "000000" satırı bir yanlış ayara kadar zararsızdır. O ayar canlıya sızarsa, o numaraya bağlı hesapların kapısı herkese açık demektir.
Düz SMS için makul bir tercih. Ama kodu sağlayıcının ürettiği Verify tipi API'lerde sahte servisiniz kodu hiç görmez. Her yeni projede de aynı işi baştan yaparsınız.
Tek bir sağlayıcı için mock dakikalar içinde çıkar. Zaman alan kısım onu doğru tutmaktır: her sağlayıcının hata biçimleri, Verify deneme sınırları ve süre aşımı, başka dillerde ortaya çıkan SDK ayrıntıları ve staging ile CI'nin gerçekten ulaşabildiği bir adres. Bizimkini her değişiklikte yedi dilde, resmi SDK'larla sınıyoruz.
2 Nasıl çalışır
otpmock, SMS sağlayıcınızın kendi API biçimiyle yanıt verir; uygulama kodunuz farkı anlamaz. Değişen tek şey test ortamının yapılandırmasıdır.
Uygulamanız
Sağlayıcının SDK'sını çağırır: messages.create, sendRestSms ya da bir Verify isteği. Canlıdakiyle aynı SDK, aynı kod yolu.
otpmock
Sağlayıcınızın tam yanıt biçimiyle cevap verir, mesajı 10 dakika saklar ve kodu metnin içinden ayıklar.
Operatör ağı hiç çağrılmaz
Testiniz
HTTPS ile gelen kutusuna sorar, kodu ekrana yazar. Verify doğrulaması doğru kodla geçer; gerçek sağlayıcıda olduğu gibi.
Entegrasyonun tamamı bu kadar: zaten oluşturduğunuz istemciye tek bir seçenek. Canlı ortam sağlayıcınızla konuşmaya devam eder; OTPMOCK_URL tanımlı olan her ortam bizimle konuşur. Aşağıdan dilinizi ve sağlayıcınızı seçin ya da tüm sağlayıcılara bakın.
import twilio from "twilio";
import { OtpMockHttpClient } from "./twilio-node-client.mjs";
export const sms = twilio(process.env.TWILIO_ACCOUNT_SID, process.env.TWILIO_AUTH_TOKEN, {
httpClient: process.env.OTPMOCK_URL ? new OtpMockHttpClient(process.env.OTPMOCK_URL) : undefined,
}); import os
from urllib.parse import urlparse
from twilio.http.http_client import TwilioHttpClient
from twilio.rest import Client
class OtpMockHttpClient(TwilioHttpClient):
"""Sends Twilio SDK requests to otpmock, keeping path, params and auth."""
def __init__(self, base):
super().__init__()
self.base = base.rstrip("/")
def request(self, method, url, *args, **kwargs):
u = urlparse(url)
return super().request(method, self.base + u.path + ("?" + u.query if u.query else ""), *args, **kwargs)
otpmock = os.environ.get("OTPMOCK_URL")
client = Client(
os.environ["TWILIO_ACCOUNT_SID"],
os.environ["TWILIO_AUTH_TOKEN"], # testte: otpmock API anahtarı
http_client=OtpMockHttpClient(otpmock) if otpmock else None,
) import com.twilio.http.*;
import java.net.URI;
// Sends Twilio SDK requests to otpmock, keeping path, params and auth.
public class OtpMockTwilioHttpClient extends NetworkHttpClient {
private final String base;
public OtpMockTwilioHttpClient(String base) { this.base = base.replaceAll("/+$", ""); }
@Override
public Response makeRequest(Request request) {
Request routed = new Request(request.getMethod(), base + URI.create(request.getUrl()).getRawPath());
request.getQueryParams().forEach((k, vs) -> vs.forEach(v -> routed.addQueryParam(k, v)));
request.getPostParams().forEach((k, vs) -> vs.forEach(v -> routed.addPostParam(k, v)));
request.getHeaderParams().forEach((k, vs) -> vs.forEach(v -> routed.addHeaderParam(k, v)));
routed.setAuth(request.getUsername(), request.getPassword());
return super.makeRequest(routed);
}
}
// Where you build the client:
String otpmock = System.getenv("OTPMOCK_URL");
TwilioRestClient.Builder builder = new TwilioRestClient.Builder(accountSid, authToken); // testte: otpmock API anahtarı
if (otpmock != null) builder.httpClient(new OtpMockTwilioHttpClient(otpmock));
TwilioRestClient client = builder.build();
// Message.creator(...).create(client); using Twilio.Clients;
using Twilio.Http;
// Sends requests to otpmock, keeping path, query and auth headers.
class OtpMockHandler : DelegatingHandler
{
private readonly Uri _base;
public OtpMockHandler(string baseUrl) : base(new HttpClientHandler()) => _base = new Uri(baseUrl);
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken ct)
{
request.RequestUri = new Uri(_base, request.RequestUri!.PathAndQuery);
return base.SendAsync(request, ct);
}
}
var otpmock = Environment.GetEnvironmentVariable("OTPMOCK_URL");
var client = new TwilioRestClient(
accountSid,
authToken, // testte: otpmock API anahtarı
httpClient: otpmock is null ? null : new SystemNetHttpClient(new HttpClient(new OtpMockHandler(otpmock))));
// await MessageResource.CreateAsync(..., client: client); use Twilio\Http\CurlClient;
use Twilio\Rest\Client;
// Sends Twilio SDK requests to otpmock, keeping path, params and auth.
class OtpMockTwilioClient extends CurlClient {
public function __construct(private string $base) { parent::__construct(); }
public function request(string $method, string $url, array $params = [], array $data = [], array $headers = [],
?string $user = null, ?string $password = null, ?int $timeout = null, ?\Twilio\AuthStrategy\AuthStrategy $authStrategy = null): \Twilio\Http\Response {
return parent::request($method, rtrim($this->base, '/') . parse_url($url, PHP_URL_PATH), $params, $data, $headers, $user, $password, $timeout, $authStrategy);
}
}
$otpmock = getenv('OTPMOCK_URL');
$client = new Client(
getenv('TWILIO_ACCOUNT_SID'),
getenv('TWILIO_AUTH_TOKEN'), // testte: otpmock API anahtarı
null, null,
$otpmock ? new OtpMockTwilioClient($otpmock) : null,
); require "twilio-ruby"
require "uri"
# Sends Twilio SDK requests to otpmock, keeping path, params and auth.
class OtpMockHttpClient < Twilio::HTTP::Client
def initialize(base)
super()
@base = URI(base)
end
def request(_host, _port, method, url, *rest)
u = URI(url)
path = u.path + (u.query ? "?#{u.query}" : "")
super("#{@base.scheme}://#{@base.host}", @base.port, method, "#{@base.scheme}://#{@base.host}:#{@base.port}#{path}", *rest)
end
end
otpmock = ENV["OTPMOCK_URL"]
client = Twilio::REST::Client.new(
ENV["TWILIO_ACCOUNT_SID"],
ENV["TWILIO_AUTH_TOKEN"], # testte: otpmock API anahtarı
nil, nil,
otpmock ? OtpMockHttpClient.new(otpmock) : nil
) // otpmockTransport sends SDK requests to otpmock, keeping path, query and auth.
type otpmockTransport struct{ base *url.URL }
func (t otpmockTransport) RoundTrip(r *http.Request) (*http.Response, error) {
r = r.Clone(r.Context())
r.URL.Scheme, r.URL.Host, r.Host = t.base.Scheme, t.base.Host, t.base.Host
return http.DefaultTransport.RoundTrip(r)
}
func newTwilio() *twilio.RestClient {
// token = testte: otpmock API anahtarı. twilio-go only accepts letters and digits here,
// so use the key without underscores (om_live_abc… -> omliveabc…); otpmock accepts both forms.
sid, token := os.Getenv("TWILIO_ACCOUNT_SID"), os.Getenv("TWILIO_AUTH_TOKEN")
params := twilio.ClientParams{Username: sid, Password: token}
if base, err := url.Parse(os.Getenv("OTPMOCK_URL")); err == nil && base.Host != "" {
c := &client.Client{Credentials: client.NewCredentials(sid, token), HTTPClient: &http.Client{Transport: otpmockTransport{base}}}
c.SetAccountSid(sid)
params.Client = c
}
return twilio.NewRestClientWithParams(params)
} import { Vonage } from "@vonage/server-sdk";
export const vonage = new Vonage(
{
apiKey: process.env.VONAGE_API_KEY,
apiSecret: process.env.VONAGE_API_SECRET, // testte: otpmock API anahtarı
applicationId: process.env.VONAGE_APPLICATION_ID, // testte: otpmock API anahtarı (Verify v2)
privateKey: process.env.VONAGE_PRIVATE_KEY,
},
process.env.OTPMOCK_URL ? { restHost: process.env.OTPMOCK_URL, apiHost: process.env.OTPMOCK_URL } : {},
); import os
from urllib.parse import urlparse
from vonage import Auth, HttpClientOptions, Vonage
otpmock = os.environ.get("OTPMOCK_URL") # e.g. https://api.otpmock.com
host = urlparse(otpmock).netloc if otpmock else None
vonage = Vonage(
Auth(api_key=os.environ["VONAGE_API_KEY"], api_secret=os.environ["VONAGE_API_SECRET"]), # secret = otpmock key in tests
HttpClientOptions(api_host=host, rest_host=host) if host else None,
)
# Verify v2 uses an application JWT (otpmock reads application_id, ignores the signature)
verify = Vonage(
Auth(application_id=os.environ["VONAGE_APPLICATION_ID"], # testte: otpmock API anahtarı
private_key=os.environ["VONAGE_PRIVATE_KEY"]),
HttpClientOptions(api_host=host) if host else None,
).verify import com.vonage.client.HttpConfig;
import com.vonage.client.VonageClient;
String otpmock = System.getenv("OTPMOCK_URL");
VonageClient.Builder builder = VonageClient.builder()
.apiKey(System.getenv("VONAGE_API_KEY"))
.apiSecret(System.getenv("VONAGE_API_SECRET")); // testte: otpmock API anahtarı
if (otpmock != null) builder.httpConfig(HttpConfig.builder().baseUri(otpmock).build());
VonageClient vonage = builder.build(); // The Vonage .NET SDK reads its hosts from configuration (appsettings.json).
// In the test environment:
{
"vonage": {
"Url.Rest": "https://api.otpmock.com",
"Url.Api": "https://api.otpmock.com"
}
}
// Code stays the same:
var vonage = new VonageClient(Credentials.FromApiKeyAndSecret(apiKey, apiSecret)); // secret = otpmock key in tests
// Verify v2 over HTTPS (Basic auth with key and secret):
var vonageUrl = Environment.GetEnvironmentVariable("OTPMOCK_URL") ?? "https://api.nexmo.com";
var http = new HttpClient { BaseAddress = new Uri(vonageUrl) };
http.DefaultRequestHeaders.Authorization = new("Basic",
Convert.ToBase64String(Encoding.UTF8.GetBytes($"{apiKey}:{apiSecret}")));
// POST /v2/verify { brand, workflow = [{ channel = "sms", to }] } -> request_id
// POST /v2/verify/{request_id} { code } -> { status = "completed" } use Vonage\Client;
use Vonage\Client\Credentials\Basic;
$otpmock = getenv('OTPMOCK_URL');
$vonage = new Client(
new Basic(getenv('VONAGE_API_KEY'), getenv('VONAGE_API_SECRET')), // secret = otpmock key in tests
$otpmock ? ['base_rest_url' => $otpmock, 'base_api_url' => $otpmock] : [],
);
// Verify v2: application JWT (application_id = otpmock key in tests; signature not checked).
// verify2() hard-codes api.nexmo.com, so tests pass a host-rewriting Guzzle client.
$stack = \GuzzleHttp\HandlerStack::create();
if ($otpmock) {
$u = parse_url($otpmock);
$stack->push(\GuzzleHttp\Middleware::mapRequest(fn ($r) => $r->withUri(
$r->getUri()->withScheme($u['scheme'])->withHost($u['host'])->withPort($u['port'] ?? null))));
}
$verify = new Client(
new \Vonage\Client\Credentials\Keypair(file_get_contents(getenv('VONAGE_PRIVATE_KEY_PATH')), getenv('VONAGE_APPLICATION_ID')),
[], new \GuzzleHttp\Client(['handler' => $stack]),
); require "vonage"
require "uri"
otpmock = ENV["OTPMOCK_URL"] && URI(ENV["OTPMOCK_URL"])
host = otpmock && "#{otpmock.host}:#{otpmock.port}"
vonage = Vonage::Client.new(
api_key: ENV["VONAGE_API_KEY"],
api_secret: ENV["VONAGE_API_SECRET"], # testte: otpmock API anahtarı
**(host ? { api_host: host, rest_host: host } : {})
)
# Verify v2 (JWT): otpmock reads application_id as the key; signature not checked
verify = Vonage::Client.new(
application_id: ENV["VONAGE_APPLICATION_ID"], # testte: otpmock API anahtarı
private_key: File.read(ENV["VONAGE_PRIVATE_KEY_PATH"]),
**(host ? { api_host: host } : {})
).verify2 auth := vonage.CreateAuthFromKeySecret(os.Getenv("VONAGE_API_KEY"), os.Getenv("VONAGE_API_SECRET")) // secret = otpmock key in tests
smsClient := vonage.NewSMSClient(auth)
if base := os.Getenv("OTPMOCK_URL"); base != "" {
smsClient.Config.BasePath = base + "/sms"
}
// Verify v2 (net/http): POST {base}/v2/verify, then POST {base}/v2/verify/{request_id} {"code": ...}
verifyBase := "https://api.nexmo.com"
if base := os.Getenv("OTPMOCK_URL"); base != "" {
verifyBase = base
}
req, _ := http.NewRequest("POST", verifyBase+"/v2/verify", bytes.NewReader(body))
req.SetBasicAuth(os.Getenv("VONAGE_API_KEY"), os.Getenv("VONAGE_API_SECRET")) // secret = otpmock key in tests import { SNSClient } from "@aws-sdk/client-sns";
export const sns = new SNSClient({
region: process.env.AWS_REGION ?? "us-east-1",
...(process.env.OTPMOCK_URL && {
endpoint: process.env.OTPMOCK_URL,
credentials: { accessKeyId: process.env.OTPMOCK_API_KEY, secretAccessKey: "unused" },
}),
}); import os
import boto3
sns = boto3.client(
"sns",
region_name=os.environ.get("AWS_REGION", "us-east-1"),
endpoint_url=os.environ.get("OTPMOCK_URL"), # None in production
)
# In tests, set AWS_ACCESS_KEY_ID to your otpmock API key (any secret works). import java.net.URI;
import software.amazon.awssdk.services.sns.SnsClient;
String otpmock = System.getenv("OTPMOCK_URL");
var builder = SnsClient.builder();
if (otpmock != null) builder.endpointOverride(URI.create(otpmock));
SnsClient sns = builder.build();
// In tests, set AWS_ACCESS_KEY_ID to your otpmock API key (any secret works). using Amazon.SimpleNotificationService;
var otpmock = Environment.GetEnvironmentVariable("OTPMOCK_URL");
var config = new AmazonSimpleNotificationServiceConfig();
if (otpmock is not null) { config.ServiceURL = otpmock; config.AuthenticationRegion = "us-east-1"; }
var sns = new AmazonSimpleNotificationServiceClient(config);
// In tests, set AWS_ACCESS_KEY_ID to your otpmock API key (any secret works). use Aws\Sns\SnsClient;
$otpmock = getenv('OTPMOCK_URL');
$sns = new SnsClient(array_filter([
'region' => getenv('AWS_REGION') ?: 'us-east-1',
'version' => 'latest',
'endpoint' => $otpmock ?: null,
]));
// In tests, set AWS_ACCESS_KEY_ID to your otpmock API key (any secret works). require "aws-sdk-sns"
sns = Aws::SNS::Client.new(
region: ENV.fetch("AWS_REGION", "us-east-1"),
**(ENV["OTPMOCK_URL"] ? { endpoint: ENV["OTPMOCK_URL"] } : {})
)
# In tests, set AWS_ACCESS_KEY_ID to your otpmock API key (any secret works). cfg, err := config.LoadDefaultConfig(ctx) // in tests, AWS_ACCESS_KEY_ID = otpmock API key (any secret works)
if err != nil {
return err
}
client := sns.NewFromConfig(cfg, func(o *sns.Options) {
if base := os.Getenv("OTPMOCK_URL"); base != "" {
o.BaseEndpoint = aws.String(base)
}
}) import Telnyx from "telnyx";
export const telnyx = new Telnyx({
apiKey: process.env.TELNYX_API_KEY, // testte: otpmock API anahtarı
...(process.env.OTPMOCK_URL && { baseURL: `${process.env.OTPMOCK_URL}/v2` }),
}); import os
from telnyx import Telnyx
otpmock = os.environ.get("OTPMOCK_URL")
telnyx = Telnyx(
api_key=os.environ["TELNYX_API_KEY"], # testte: otpmock API anahtarı
base_url=f"{otpmock}/v2" if otpmock else None,
) import com.telnyx.sdk.client.TelnyxClient;
import com.telnyx.sdk.client.okhttp.TelnyxOkHttpClient;
String otpmock = System.getenv("OTPMOCK_URL");
TelnyxOkHttpClient.Builder builder = TelnyxOkHttpClient.builder()
.apiKey(System.getenv("TELNYX_API_KEY")); // testte: otpmock API anahtarı
if (otpmock != null) builder.baseUrl(otpmock + "/v2"); // keep the /v2 suffix
TelnyxClient telnyx = builder.build();
// Messaging: telnyx.messages().send(...); Verify: telnyx.verifications().triggerSms(...) using Telnyx;
TelnyxConfiguration.SetApiKey(Environment.GetEnvironmentVariable("TELNYX_API_KEY")); // testte: otpmock API anahtarı
var otpmock = Environment.GetEnvironmentVariable("OTPMOCK_URL");
if (otpmock is not null) TelnyxConfiguration.SetApiBase(otpmock + "/v2");
var messages = new MessageService(); use Telnyx\Client;
$otpmock = getenv('OTPMOCK_URL');
$telnyx = new Client(
apiKey: getenv('TELNYX_API_KEY'), // testte: otpmock API anahtarı
baseUrl: $otpmock ? rtrim($otpmock, '/') . '/v2' : null,
); require "telnyx"
telnyx = Telnyx::Client.new(
api_key: ENV["TELNYX_API_KEY"], # testte: otpmock API anahtarı
**(ENV["OTPMOCK_URL"] ? { base_url: "#{ENV["OTPMOCK_URL"]}/v2" } : {})
) opts := []option.RequestOption{option.WithAPIKey(os.Getenv("TELNYX_API_KEY"))} // testte: otpmock API anahtarı
if base := os.Getenv("OTPMOCK_URL"); base != "" {
opts = append(opts, option.WithBaseURL(base+"/v2/"))
}
client := telnyx.NewClient(opts...) import { PinpointSMSVoiceV2Client } from "@aws-sdk/client-pinpoint-sms-voice-v2";
export const sms = new PinpointSMSVoiceV2Client({
region: process.env.AWS_REGION ?? "us-east-1",
...(process.env.OTPMOCK_URL && {
endpoint: process.env.OTPMOCK_URL,
credentials: { accessKeyId: process.env.OTPMOCK_API_KEY, secretAccessKey: "unused" },
}),
}); import os
import boto3
sms = boto3.client(
"pinpoint-sms-voice-v2",
region_name=os.environ.get("AWS_REGION", "us-east-1"),
endpoint_url=os.environ.get("OTPMOCK_URL"), # None in production
)
# In tests, set AWS_ACCESS_KEY_ID to your otpmock API key (any secret works). import java.net.URI;
import software.amazon.awssdk.services.pinpointsmsvoicev2.PinpointSmsVoiceV2Client;
String otpmock = System.getenv("OTPMOCK_URL");
var builder = PinpointSmsVoiceV2Client.builder();
if (otpmock != null) builder.endpointOverride(URI.create(otpmock));
PinpointSmsVoiceV2Client sms = builder.build();
// In tests, set AWS_ACCESS_KEY_ID to your otpmock API key (any secret works). using Amazon.PinpointSMSVoiceV2;
var otpmock = Environment.GetEnvironmentVariable("OTPMOCK_URL");
var config = new AmazonPinpointSMSVoiceV2Config();
if (otpmock is not null) { config.ServiceURL = otpmock; config.AuthenticationRegion = "us-east-1"; }
var sms = new AmazonPinpointSMSVoiceV2Client(config);
// In tests, set AWS_ACCESS_KEY_ID to your otpmock API key (any secret works). use Aws\PinpointSMSVoiceV2\PinpointSMSVoiceV2Client;
$otpmock = getenv('OTPMOCK_URL');
$sms = new PinpointSMSVoiceV2Client(array_filter([
'region' => getenv('AWS_REGION') ?: 'us-east-1',
'version' => 'latest',
'endpoint' => $otpmock ?: null,
]));
// In tests, set AWS_ACCESS_KEY_ID to your otpmock API key (any secret works). require "aws-sdk-pinpointsmsvoicev2"
sms = Aws::PinpointSMSVoiceV2::Client.new(
region: ENV.fetch("AWS_REGION", "us-east-1"),
**(ENV["OTPMOCK_URL"] ? { endpoint: ENV["OTPMOCK_URL"] } : {})
)
# In tests, set AWS_ACCESS_KEY_ID to your otpmock API key (any secret works). cfg, err := config.LoadDefaultConfig(ctx) // in tests, AWS_ACCESS_KEY_ID = otpmock API key (any secret works)
if err != nil {
return err
}
client := pinpointsmsvoicev2.NewFromConfig(cfg, func(o *pinpointsmsvoicev2.Options) {
if base := os.Getenv("OTPMOCK_URL"); base != "" {
o.BaseEndpoint = aws.String(base)
}
}) import TeleSignSDK from "telesignsdk";
export const telesign = new TeleSignSDK(
process.env.TELESIGN_CUSTOMER_ID, // testte: otpmock API anahtarı
process.env.TELESIGN_API_KEY,
process.env.OTPMOCK_URL ?? "https://rest-api.telesign.com",
); import os
from telesign.messaging import MessagingClient
telesign = MessagingClient(
os.environ["TELESIGN_CUSTOMER_ID"], # testte: otpmock API anahtarı
os.environ["TELESIGN_API_KEY"],
rest_endpoint=os.environ.get("OTPMOCK_URL", "https://rest-api.telesign.com"),
) import com.telesign.MessagingClient;
MessagingClient telesign = new MessagingClient(
System.getenv("TELESIGN_CUSTOMER_ID"), // testte: otpmock API anahtarı
System.getenv("TELESIGN_API_KEY"),
System.getenv().getOrDefault("OTPMOCK_URL", "https://rest-api.telesign.com")); using Telesign;
var messaging = new MessagingClient(
Environment.GetEnvironmentVariable("TELESIGN_CUSTOMER_ID"), // testte: otpmock API anahtarı
Environment.GetEnvironmentVariable("TELESIGN_API_KEY"),
Environment.GetEnvironmentVariable("OTPMOCK_URL") ?? "https://rest-api.telesign.com",
"csharp_telesign", null, null); use telesign\sdk\messaging\MessagingClient;
$telesign = new MessagingClient(
getenv('TELESIGN_CUSTOMER_ID'), // testte: otpmock API anahtarı
getenv('TELESIGN_API_KEY'),
getenv('OTPMOCK_URL') ?: 'https://rest-api.telesign.com',
);
// SMS Verify (HTTP; the SDK has no verify client): Basic customer ID : API key.
$verifyUrl = getenv('OTPMOCK_URL') ?: 'https://rest-ww.telesign.com';
$auth = [getenv('TELESIGN_CUSTOMER_ID'), getenv('TELESIGN_API_KEY')];
$ref = json_decode((string) (new \GuzzleHttp\Client())->post("$verifyUrl/v1/verify/sms", [
'auth' => $auth, 'form_params' => ['phone_number' => '15550142'],
])->getBody(), true)['reference_id'];
// then GET "$verifyUrl/v1/verify/$ref?verify_code=..." -> verify.code_state "VALID" require "telesign"
messaging = Telesign::MessagingClient.new(
ENV["TELESIGN_CUSTOMER_ID"], # testte: otpmock API anahtarı
ENV["TELESIGN_API_KEY"],
rest_endpoint: ENV.fetch("OTPMOCK_URL", "https://rest-api.telesign.com")
) // Telesign has no official Go SDK; call its HTTP API with net/http, only the host changes.
base := os.Getenv("OTPMOCK_URL")
if base == "" {
base = "https://rest-api.telesign.com"
}
form := url.Values{"phone_number": {"15550142"}, "message": {msg}, "message_type": {"OTP"}}
req, _ := http.NewRequest("POST", base+"/v1/messaging", strings.NewReader(form.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.SetBasicAuth(os.Getenv("TELESIGN_CUSTOMER_ID"), os.Getenv("TELESIGN_API_KEY")) // customer ID = otpmock key in tests
res, err := http.DefaultClient.Do(req) // body status.code 290 = in progress import { Configuration, MessagesApi } from "bandwidth-sdk";
import { operationServerMap } from "bandwidth-sdk/dist/base";
if (process.env.OTPMOCK_URL) {
operationServerMap["MessagesApi.createMessage"][0].url = `${process.env.OTPMOCK_URL}/api/v2`;
}
export const bandwidth = new MessagesApi(
new Configuration({
username: process.env.BANDWIDTH_USERNAME,
password: process.env.BANDWIDTH_PASSWORD, // testte: otpmock API anahtarı
}),
); import os
from urllib.parse import urlparse
import bandwidth
class OtpMockApiClient(bandwidth.ApiClient):
"""Each Bandwidth operation has its own host; send them all to otpmock."""
def call_api(self, method, url, *args, **kwargs):
u = urlparse(url)
url = os.environ["OTPMOCK_URL"].rstrip("/") + u.path + ("?" + u.query if u.query else "")
return super().call_api(method, url, *args, **kwargs)
config = bandwidth.Configuration(
username=os.environ["BANDWIDTH_USERNAME"],
password=os.environ["BANDWIDTH_PASSWORD"], # testte: otpmock API anahtarı
)
client = OtpMockApiClient(config) if os.environ.get("OTPMOCK_URL") else bandwidth.ApiClient(config)
messages = bandwidth.MessagesApi(client)String base = System.getenv().getOrDefault("OTPMOCK_URL", "https://messaging.bandwidth.com");
String auth = Base64.getEncoder().encodeToString(
(System.getenv("BANDWIDTH_USERNAME") + ":" + System.getenv("BANDWIDTH_PASSWORD")).getBytes()); // password = testte: otpmock API anahtarı
HttpRequest req = HttpRequest.newBuilder(URI.create(base + "/api/v2/users/" + accountId + "/messages"))
.header("Authorization", "Basic " + auth)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json)) // {"applicationId":"...","to":["+1..."],"from":"+1...","text":"..."}
.build(); // The Bandwidth .NET package has no host option, so call the Messaging API directly.
var baseUrl = Environment.GetEnvironmentVariable("OTPMOCK_URL") ?? "https://messaging.bandwidth.com";
var accountId = Environment.GetEnvironmentVariable("BANDWIDTH_ACCOUNT_ID");
var auth = Convert.ToBase64String(Encoding.UTF8.GetBytes(
$"{Environment.GetEnvironmentVariable("BANDWIDTH_USERNAME")}:{Environment.GetEnvironmentVariable("BANDWIDTH_PASSWORD")}")); // password = otpmock key in tests
using var http = new HttpClient();
var req = new HttpRequestMessage(HttpMethod.Post, $"{baseUrl}/api/v2/users/{accountId}/messages")
{
Content = JsonContent.Create(new { applicationId, to = new[] { phone }, from, text }),
};
req.Headers.Authorization = new AuthenticationHeaderValue("Basic", auth);
(await http.SendAsync(req)).EnsureSuccessStatusCode(); use Bandwidth\Api\MessagesApi;
use Bandwidth\Configuration;
use GuzzleHttp\{Client, HandlerStack, Middleware};
use Psr\Http\Message\RequestInterface;
// createMessage has its own server URL, so tests swap the host on the Guzzle client.
$stack = HandlerStack::create();
if ($otpmock = getenv('OTPMOCK_URL')) {
$u = parse_url($otpmock);
$stack->push(Middleware::mapRequest(fn (RequestInterface $r) => $r->withUri(
$r->getUri()->withScheme($u['scheme'])->withHost($u['host'])->withPort($u['port'] ?? null))));
}
$config = (new Configuration())
->setUsername(getenv('BANDWIDTH_USERNAME'))
->setPassword(getenv('BANDWIDTH_PASSWORD')); // testte: otpmock API anahtarı
$bandwidth = new MessagesApi(new Client(['handler' => $stack]), $config); require "net/http"
require "json"
BANDWIDTH_URL = ENV.fetch("OTPMOCK_URL", "https://messaging.bandwidth.com")
uri = URI("#{BANDWIDTH_URL}/api/v2/users/#{ENV["BANDWIDTH_ACCOUNT_ID"]}/messages")
req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json")
req.basic_auth(ENV["BANDWIDTH_USERNAME"], ENV["BANDWIDTH_PASSWORD"]) # password = testte: otpmock API anahtarı
req.body = { applicationId: ENV["BANDWIDTH_APP_ID"], to: ["+15550142"], from: "+15550000001", text: "Your code is #{code}" }.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) } // Bandwidth has no official Go SDK; call its HTTP API with net/http, only the host changes.
base := os.Getenv("OTPMOCK_URL")
if base == "" {
base = "https://messaging.bandwidth.com"
}
body, _ := json.Marshal(map[string]any{
"applicationId": os.Getenv("BANDWIDTH_APPLICATION_ID"), "to": []string{"+15550142"},
"from": os.Getenv("BANDWIDTH_NUMBER"), "text": msg,
})
req, _ := http.NewRequest("POST", base+"/api/v2/users/"+os.Getenv("BANDWIDTH_ACCOUNT_ID")+"/messages", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
req.SetBasicAuth(os.Getenv("BANDWIDTH_USERNAME"), os.Getenv("BANDWIDTH_PASSWORD")) // password = otpmock key in tests
res, err := http.DefaultClient.Do(req) // 202 Accepted import { Infobip, AuthType } from "@infobip-api/sdk";
export const infobip = new Infobip({
baseUrl: process.env.OTPMOCK_URL ?? process.env.INFOBIP_BASE_URL,
apiKey: process.env.INFOBIP_API_KEY, // testte: otpmock API anahtarı
authType: AuthType.ApiKey,
}); import os
from infobip_api_client.api.sms_api import SmsApi
from infobip_api_client.api_client import ApiClient, Configuration
config = Configuration(
host=os.environ.get("OTPMOCK_URL") or os.environ["INFOBIP_BASE_URL"],
api_key=os.environ["INFOBIP_API_KEY"], # testte: otpmock API anahtarı
)
sms = SmsApi(ApiClient(config)) import com.infobip.*;
import com.infobip.api.SmsApi;
String base = System.getenv().getOrDefault("OTPMOCK_URL", System.getenv("INFOBIP_BASE_URL"));
ApiClient client = ApiClient.forApiKey(ApiKey.from(System.getenv("INFOBIP_API_KEY"))) // testte: otpmock API anahtarı
.withBaseUrl(BaseUrl.from(base))
.build();
SmsApi sms = new SmsApi(client); using Infobip.Api.Client.Api;
using Infobip.Api.Client.Client;
var baseUrl = Environment.GetEnvironmentVariable("OTPMOCK_URL")
?? Environment.GetEnvironmentVariable("INFOBIP_BASE_URL");
var config = new Configuration(
Environment.GetEnvironmentVariable("INFOBIP_API_KEY"), // testte: otpmock API anahtarı
new Uri(baseUrl));
var sms = new SmsApi(config); use Infobip\Api\SmsApi;
use Infobip\Configuration;
$config = new Configuration(
host: getenv('OTPMOCK_URL') ?: getenv('INFOBIP_BASE_URL'),
apiKey: getenv('INFOBIP_API_KEY'), // testte: otpmock API anahtarı
);
$sms = new SmsApi(config: $config); require "net/http"
require "json"
# Infobip has no official Ruby SDK; apps call the REST API, so only the host changes.
INFOBIP_URL = ENV["OTPMOCK_URL"] || ENV["INFOBIP_BASE_URL"]
res = Net::HTTP.post(
URI("#{INFOBIP_URL}/sms/2/text/advanced"),
{ messages: [{ from: "InfoSMS", destinations: [{ to: "15550142" }], text: "Your PIN is #{code}" }] }.to_json,
"Content-Type" => "application/json",
"Authorization" => "App #{ENV["INFOBIP_API_KEY"]}" # testte: otpmock API anahtarı
) cfg := infobip.NewConfiguration()
cfg.Host = os.Getenv("INFOBIP_BASE_URL")
if base := os.Getenv("OTPMOCK_URL"); base != "" {
cfg.Host = base
}
client := api.NewAPIClient(cfg)
auth := context.WithValue(ctx, infobip.ContextAPIKeys, map[string]infobip.APIKey{
"APIKeyHeader": {Key: os.Getenv("INFOBIP_API_KEY")}, // testte: otpmock API anahtarı
}) import { SinchClient } from "@sinch/sdk-core";
export const sinch = new SinchClient({
servicePlanId: process.env.SINCH_SERVICE_PLAN_ID,
apiToken: process.env.SINCH_API_TOKEN, // testte: otpmock API anahtarı
applicationKey: process.env.SINCH_APPLICATION_KEY, // testte: otpmock API anahtarı (Verification)
applicationSecret: process.env.SINCH_APPLICATION_SECRET,
...(process.env.OTPMOCK_URL && { smsHostname: process.env.OTPMOCK_URL, verificationHostname: process.env.OTPMOCK_URL }),
}); import os
from sinch import SinchClient
sinch = SinchClient(
service_plan_id=os.environ["SINCH_SERVICE_PLAN_ID"],
sms_api_token=os.environ["SINCH_API_TOKEN"], # testte: otpmock API anahtarı
sms_region="us",
)
if os.environ.get("OTPMOCK_URL"):
sinch.configuration.sms_domain_with_service_plan_id = os.environ["OTPMOCK_URL"]
# Verification API (HTTP): Application auth, key = testte: otpmock API anahtarı
VERIFY_URL = os.environ.get("OTPMOCK_URL", "https://verification.api.sinch.com")
VERIFY_AUTH = {"Authorization": f"Application {os.environ['SINCH_APP_KEY']}:{os.environ['SINCH_APP_SECRET']}"}
# POST {VERIFY_URL}/verification/v1/verifications, PUT ./id/{id} {"method": "sms", "sms": {"code": ...}} import com.sinch.sdk.SinchClient;
import com.sinch.sdk.models.*;
String otpmock = System.getenv("OTPMOCK_URL");
Configuration.Builder config = Configuration.builder()
.setSmsServicePlanId(System.getenv("SINCH_SERVICE_PLAN_ID"))
.setSmsApiToken(System.getenv("SINCH_API_TOKEN")) // testte: otpmock API anahtarı
.setApplicationKey(System.getenv("SINCH_APPLICATION_KEY")) // Verification: testte: otpmock API anahtarı
.setApplicationSecret(System.getenv("SINCH_APPLICATION_SECRET"));
if (otpmock != null) {
config.setSmsContext(SmsContext.builder().setSmsUrl(otpmock).setSmsRegion(SMSRegion.US).build());
config.setVerificationContext(VerificationContext.builder().setVerificationUrl(otpmock).build());
}
SinchClient sinch = new SinchClient(config.build()); using Sinch;
using Sinch.SMS;
var otpmock = Environment.GetEnvironmentVariable("OTPMOCK_URL");
var sinch = new SinchClient(default, default, default, options =>
{
options.UseServicePlanIdWithSms(
Environment.GetEnvironmentVariable("SINCH_SERVICE_PLAN_ID"),
Environment.GetEnvironmentVariable("SINCH_API_TOKEN"), // testte: otpmock API anahtarı
SmsServicePlanIdRegion.Us);
if (otpmock is not null) options.ApiUrlOverrides = new ApiUrlOverrides { SmsUrl = otpmock };
});
// Verification over HTTPS (application key = testte: otpmock API anahtarı; signature isn't checked):
var verifyHttp = new HttpClient { BaseAddress = new Uri(otpmock ?? "https://verification.api.sinch.com") };
verifyHttp.DefaultRequestHeaders.Authorization = new("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes(
$"{Environment.GetEnvironmentVariable("SINCH_APPLICATION_KEY")}:{Environment.GetEnvironmentVariable("SINCH_APPLICATION_SECRET")}")));
// POST /verification/v1/verifications { identity = { type = "number", endpoint }, method = "sms" } -> id
// PUT /verification/v1/verifications/id/{id} { method = "sms", sms = { code } } -> status "SUCCESSFUL" use GuzzleHttp\Client;
$sinchUrl = getenv('OTPMOCK_URL') ?: 'https://us.sms.api.sinch.com';
$planId = getenv('SINCH_SERVICE_PLAN_ID');
(new Client())->post("$sinchUrl/xms/v1/$planId/batches", [
'headers' => ['Authorization' => 'Bearer ' . getenv('SINCH_API_TOKEN')], // testte: otpmock API anahtarı
'json' => ['from' => '12345', 'to' => ['+15550142'], 'body' => "Your code is $code"],
]);
// Verification API: application key/secret auth.
$verifyUrl = getenv('OTPMOCK_URL') ?: 'https://verification.api.sinch.com';
$appAuth = ['Authorization' => 'Application ' . getenv('SINCH_APPLICATION_KEY') . ':' . $signature]; // key = testte: otpmock API anahtarı
(new Client())->post("$verifyUrl/verification/v1/verifications", [
'headers' => $appAuth,
'json' => ['identity' => ['type' => 'number', 'endpoint' => '+15550142'], 'method' => 'sms'],
]); require "net/http"
require "json"
# Sinch has no official Ruby SDK; apps call the REST API, so only the host changes.
SINCH_URL = ENV.fetch("OTPMOCK_URL", "https://us.sms.api.sinch.com")
res = Net::HTTP.post(
URI("#{SINCH_URL}/xms/v1/#{ENV["SINCH_SERVICE_PLAN_ID"]}/batches"),
{ to: ["+15550142"], from: "12345", body: "Your code: #{code}" }.to_json,
"Content-Type" => "application/json",
"Authorization" => "Bearer #{ENV["SINCH_API_TOKEN"]}" # testte: otpmock API anahtarı
) // Sinch has no official Go SDK; call its HTTP API with net/http, only the host changes.
base := os.Getenv("OTPMOCK_URL")
if base == "" {
base = "https://us.sms.api.sinch.com"
}
body, _ := json.Marshal(map[string]any{"to": []string{"+15550142"}, "from": os.Getenv("SINCH_NUMBER"), "body": msg})
req, _ := http.NewRequest("POST", base+"/xms/v1/"+os.Getenv("SINCH_SERVICE_PLAN_ID")+"/batches", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+os.Getenv("SINCH_API_TOKEN")) // testte: otpmock API anahtarı
res, err := http.DefaultClient.Do(req)
// Verification: POST {base}/verification/v1/verifications, then PUT .../verifications/id/{id}.
// Production host is https://verification.api.sinch.com. Basic auth with the application key and secret:
req.SetBasicAuth(os.Getenv("SINCH_APPLICATION_KEY"), os.Getenv("SINCH_APPLICATION_SECRET")) // key = otpmock key in tests import { BirdClient } from "@messagebird/sdk";
export const bird = new BirdClient({
apiKey: process.env.BIRD_API_KEY, // testte: otpmock API anahtarı
...(process.env.OTPMOCK_URL && { baseUrl: process.env.OTPMOCK_URL }),
}); import os
import requests
BIRD_URL = os.environ.get("OTPMOCK_URL", "https://us-west-1.platform.bird.com")
requests.post(
f"{BIRD_URL}/v1/sms/messages",
headers={"Authorization": f"Bearer {os.environ['BIRD_API_KEY']}"}, # testte: otpmock API anahtarı
json={"from": "+15557654321", "to": "+15550142", "text": f"Your code is {code}", "category": "authentication"},
).raise_for_status() // Bird has no Java SDK; call the REST API and swap the host.
String base = System.getenv().getOrDefault("OTPMOCK_URL", "https://eu.platform.bird.com");
HttpRequest req = HttpRequest.newBuilder(URI.create(base + "/v1/sms/messages"))
.header("Authorization", "Bearer " + System.getenv("BIRD_API_KEY")) // testte: otpmock API anahtarı
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json)) // {"from":"+1...","to":"+1...","text":"...","category":"authentication"}
.build(); // Bird has no official .NET SDK; call the REST API with HttpClient.
var birdUrl = Environment.GetEnvironmentVariable("OTPMOCK_URL") ?? "https://eu-west-1.platform.bird.com";
var http = new HttpClient { BaseAddress = new Uri(birdUrl) };
http.DefaultRequestHeaders.Add("Authorization",
"Bearer " + Environment.GetEnvironmentVariable("BIRD_API_KEY")); // testte: otpmock API anahtarı
await http.PostAsJsonAsync("/v1/sms/messages",
new { from = "+15557654321", to = phone, text = $"Your code is {code}", category = "authentication" }); use GuzzleHttp\Client;
$birdUrl = getenv('OTPMOCK_URL') ?: 'https://us-west-1.platform.bird.com';
(new Client())->post("$birdUrl/v1/sms/messages", [
'headers' => ['Authorization' => 'Bearer ' . getenv('BIRD_API_KEY')], // testte: otpmock API anahtarı
'json' => ['from' => '+15557654321', 'to' => '+15550142', 'text' => "Your code is $code", 'category' => 'authentication'],
]); require "net/http"
require "json"
# Bird has no official Ruby SDK; apps call the REST API, so only the host changes.
BIRD_URL = ENV.fetch("OTPMOCK_URL", "https://api.bird.com")
res = Net::HTTP.post(
URI("#{BIRD_URL}/v1/sms/messages"),
{ from: "+15557654321", to: "+15550142", text: "Your code is #{code}", category: "authentication" }.to_json,
"Content-Type" => "application/json",
"Authorization" => "Bearer #{ENV["BIRD_API_KEY"]}" # testte: otpmock API anahtarı
) // Bird has no official Go SDK; call its HTTP API with net/http, only the host changes.
base := os.Getenv("OTPMOCK_URL")
if base == "" {
base = "https://eu.platform.bird.com"
}
body, _ := json.Marshal(map[string]any{"from": os.Getenv("BIRD_NUMBER"), "to": "+15550142", "text": msg, "category": "authentication"})
req, _ := http.NewRequest("POST", base+"/v1/sms/messages", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+os.Getenv("BIRD_API_KEY")) // testte: otpmock API anahtarı
res, err := http.DefaultClient.Do(req) // 202, status "accepted" import plivo from "plivo";
const authId = process.env.PLIVO_AUTH_ID;
export const plivoClient = new plivo.Client(
authId,
process.env.PLIVO_AUTH_TOKEN, // testte: otpmock API anahtarı
process.env.OTPMOCK_URL ? { url: `${process.env.OTPMOCK_URL}/v1/Account/${authId}` } : {},
); import os
from urllib.parse import urlparse
import plivo
plivo_client = plivo.RestClient(
os.environ["PLIVO_AUTH_ID"],
os.environ["PLIVO_AUTH_TOKEN"], # testte: otpmock API anahtarı
)
otpmock = os.environ.get("OTPMOCK_URL")
if otpmock: # the SDK has no host option: rewrite the host of each request
_send = plivo_client.session.send
def _send_to_otpmock(request, *args, **kwargs):
u = urlparse(request.url)
request.url = otpmock.rstrip("/") + u.path + ("?" + u.query if u.query else "")
return _send(request, *args, **kwargs)
plivo_client.session.send = _send_to_otpmock import com.fasterxml.jackson.databind.module.SimpleModule;
import com.plivo.api.PlivoClient;
import com.plivo.api.models.base.LogLevel;
import okhttp3.OkHttpClient;
String otpmock = System.getenv("OTPMOCK_URL");
String authToken = System.getenv("PLIVO_AUTH_TOKEN"); // testte: otpmock API anahtarı
PlivoClient plivo = otpmock == null
? new PlivoClient(authId, authToken)
: new PlivoClient(authId, authToken, new OkHttpClient.Builder(), otpmock + "/v1/", new SimpleModule(), LogLevel.NONE);
// Message.creator(src, dst, text).client(plivo).create();
// VerifySession.creator(...).client(plivo).create(); // The Plivo .NET SDK has no base URL option; in apps that must be testable, call the REST API.
var plivoUrl = Environment.GetEnvironmentVariable("OTPMOCK_URL") ?? "https://api.plivo.com";
var authId = Environment.GetEnvironmentVariable("PLIVO_AUTH_ID");
var authToken = Environment.GetEnvironmentVariable("PLIVO_AUTH_TOKEN"); // testte: otpmock API anahtarı
var http = new HttpClient { BaseAddress = new Uri(plivoUrl) };
http.DefaultRequestHeaders.Authorization = new("Basic",
Convert.ToBase64String(Encoding.UTF8.GetBytes($"{authId}:{authToken}")));
await http.PostAsJsonAsync($"/v1/Account/{authId}/Message/",
new { src = "+15550000001", dst = phone, text = $"Your code is {code}" }); use GuzzleHttp\Client;
// plivo/plivo-php hard-codes api.plivo.com, so call the REST path directly.
$plivoUrl = getenv('OTPMOCK_URL') ?: 'https://api.plivo.com';
$authId = getenv('PLIVO_AUTH_ID');
(new Client())->post("$plivoUrl/v1/Account/$authId/Message/", [
'auth' => [$authId, getenv('PLIVO_AUTH_TOKEN')], // auth token = testte: otpmock API anahtarı
'json' => ['src' => '+15550000001', 'dst' => '+15550142', 'text' => "Your code is $code"],
]); require "net/http"
require "json"
PLIVO_URL = ENV.fetch("OTPMOCK_URL", "https://api.plivo.com")
auth_id = ENV["PLIVO_AUTH_ID"]
uri = URI("#{PLIVO_URL}/v1/Account/#{auth_id}/Message/")
req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json")
req.basic_auth(auth_id, ENV["PLIVO_AUTH_TOKEN"]) # testte: otpmock API anahtarı
req.body = { src: "+15550000001", dst: "+15550142", text: "Your code is #{code}" }.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) } // otpmockTransport sends SDK requests to otpmock, keeping path, query and auth.
type otpmockTransport struct{ base *url.URL }
func (t otpmockTransport) RoundTrip(r *http.Request) (*http.Response, error) {
r = r.Clone(r.Context())
r.URL.Scheme, r.URL.Host, r.Host = t.base.Scheme, t.base.Host, t.base.Host
return http.DefaultTransport.RoundTrip(r)
}
func newPlivo() (*plivo.Client, error) {
opts := &plivo.ClientOptions{}
if base, err := url.Parse(os.Getenv("OTPMOCK_URL")); err == nil && base.Host != "" {
opts.HttpClient = &http.Client{Transport: otpmockTransport{base}}
}
return plivo.NewClient(os.Getenv("PLIVO_AUTH_ID"), os.Getenv("PLIVO_AUTH_TOKEN"), opts) // token = testte: otpmock API anahtarı
} import { Netgsm } from "@netgsm/sms";
export const netgsm = new Netgsm({
username: process.env.NETGSM_USERNAME, // testte: otpmock API anahtarı
password: process.env.NETGSM_PASSWORD,
});
if (process.env.OTPMOCK_URL) (netgsm as any).baseURL = process.env.OTPMOCK_URL; import os
import requests
NETGSM_URL = os.environ.get("OTPMOCK_URL", "https://api.netgsm.com.tr")
requests.post(
f"{NETGSM_URL}/sms/rest/v2/send",
auth=(os.environ["NETGSM_USERNAME"], os.environ["NETGSM_PASSWORD"]), # username = testte: otpmock API anahtarı
json={"msgheader": "BASLIGIM", "encoding": "TR", "messages": [{"msg": f"Doğrulama kodunuz: {code}", "no": "5321234567"}]},
).raise_for_status()String base = System.getenv().getOrDefault("OTPMOCK_URL", "https://api.netgsm.com.tr");
String auth = Base64.getEncoder().encodeToString(
(System.getenv("NETGSM_USERNAME") + ":" + System.getenv("NETGSM_PASSWORD")).getBytes()); // username = testte: otpmock API anahtarı
HttpRequest req = HttpRequest.newBuilder(URI.create(base + "/sms/rest/v2/send"))
.header("Authorization", "Basic " + auth)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json)) // {"msgheader":"...","encoding":"TR","messages":[{"msg":"...","no":"5321234567"}]}
.build(); // Netgsm has no official .NET SDK; call REST v2 with HttpClient.
var netgsmUrl = Environment.GetEnvironmentVariable("OTPMOCK_URL") ?? "https://api.netgsm.com.tr";
var user = Environment.GetEnvironmentVariable("NETGSM_USERNAME"); // testte: otpmock API anahtarı
var pass = Environment.GetEnvironmentVariable("NETGSM_PASSWORD");
var http = new HttpClient { BaseAddress = new Uri(netgsmUrl) };
http.DefaultRequestHeaders.Authorization = new("Basic",
Convert.ToBase64String(Encoding.UTF8.GetBytes($"{user}:{pass}")));
await http.PostAsJsonAsync("/sms/rest/v2/send", new
{
msgheader = "BASLIGIM", encoding = "TR",
messages = new[] { new { msg = $"Doğrulama kodunuz: {code}", no = "5321234567" } },
}); use GuzzleHttp\Client;
$netgsmUrl = getenv('OTPMOCK_URL') ?: 'https://api.netgsm.com.tr';
(new Client())->post("$netgsmUrl/sms/rest/v2/send", [
'auth' => [getenv('NETGSM_USERNAME'), getenv('NETGSM_PASSWORD')], // username = testte: otpmock API anahtarı
'json' => ['msgheader' => 'BASLIGIM', 'encoding' => 'TR', 'messages' => [['msg' => "Doğrulama kodunuz: $code", 'no' => '5321234567']]],
]); require "net/http"
require "json"
# Netgsm has no official Ruby SDK; apps call REST v2, so only the host changes.
NETGSM_URL = ENV.fetch("OTPMOCK_URL", "https://api.netgsm.com.tr")
uri = URI("#{NETGSM_URL}/sms/rest/v2/send")
req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json")
req.basic_auth(ENV["NETGSM_USERNAME"], ENV["NETGSM_PASSWORD"]) # username = testte: otpmock API anahtarı
req.body = { msgheader: "BASLIGIM", encoding: "TR", messages: [{ msg: "Doğrulama kodunuz: #{code}", no: "5321234567" }] }.to_json
res = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) } // Netgsm has no official Go SDK; call its HTTP API with net/http, only the host changes.
base := os.Getenv("OTPMOCK_URL")
if base == "" {
base = "https://api.netgsm.com.tr"
}
body, _ := json.Marshal(map[string]any{
"msgheader": os.Getenv("NETGSM_HEADER"), "encoding": "TR",
"messages": []map[string]string{{"msg": msg, "no": "5321234567"}},
})
req, _ := http.NewRequest("POST", base+"/sms/rest/v2/send", bytes.NewReader(body))
req.Header.Set("Content-Type", "application/json")
req.SetBasicAuth(os.Getenv("NETGSM_USERNAME"), os.Getenv("NETGSM_PASSWORD")) // username = otpmock key in tests
res, err := http.DefaultClient.Do(req) // body code "00" = queuedconst VERIMOR_URL = process.env.OTPMOCK_URL ?? "https://sms.verimor.com.tr";
const res = await fetch(`${VERIMOR_URL}/v2/send.json`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
username: process.env.VERIMOR_USERNAME,
password: process.env.VERIMOR_PASSWORD, // testte: otpmock API anahtarı
source_addr: "BASLIGIM",
messages: [{ msg: `Doğrulama kodunuz: ${code}`, dest: "905321234567" }],
}),
});
const campaignId = await res.text(); import os
import requests
VERIMOR_URL = os.environ.get("OTPMOCK_URL", "https://sms.verimor.com.tr")
res = requests.post(f"{VERIMOR_URL}/v2/send.json", json={
"username": os.environ["VERIMOR_USERNAME"],
"password": os.environ["VERIMOR_PASSWORD"], # testte: otpmock API anahtarı
"source_addr": "BASLIGIM",
"messages": [{"msg": f"Doğrulama kodunuz: {code}", "dest": "905321234567"}],
})
campaign_id = res.textString base = System.getenv().getOrDefault("OTPMOCK_URL", "https://sms.verimor.com.tr");
// json: {"username":"...","password":"<VERIMOR_PASSWORD, testte: otpmock API anahtarı>","source_addr":"BASLIGIM",
// "messages":[{"msg":"...","dest":"905321234567"}]}
HttpRequest req = HttpRequest.newBuilder(URI.create(base + "/v2/send.json"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
// Response body is the campaign ID as plain text.var verimorUrl = Environment.GetEnvironmentVariable("OTPMOCK_URL") ?? "https://sms.verimor.com.tr";
var http = new HttpClient { BaseAddress = new Uri(verimorUrl) };
var res = await http.PostAsJsonAsync("/v2/send.json", new
{
username = Environment.GetEnvironmentVariable("VERIMOR_USERNAME"),
password = Environment.GetEnvironmentVariable("VERIMOR_PASSWORD"), // testte: otpmock API anahtarı
source_addr = "BASLIGIM",
messages = new[] { new { msg = $"Doğrulama kodunuz: {code}", dest = "905321234567" } },
});
var campaignId = await res.Content.ReadAsStringAsync(); use GuzzleHttp\Client;
$verimorUrl = getenv('OTPMOCK_URL') ?: 'https://sms.verimor.com.tr';
$campaignId = (string) (new Client())->post("$verimorUrl/v2/send.json", [
'json' => [
'username' => getenv('VERIMOR_USERNAME'),
'password' => getenv('VERIMOR_PASSWORD'), // testte: otpmock API anahtarı
'source_addr' => 'BASLIGIM',
'messages' => [['msg' => "Doğrulama kodunuz: $code", 'dest' => '905321234567']],
],
])->getBody(); require "net/http"
require "json"
# Verimor has no official Ruby SDK; apps call the REST API, so only the host changes.
VERIMOR_URL = ENV.fetch("OTPMOCK_URL", "https://sms.verimor.com.tr")
res = Net::HTTP.post(
URI("#{VERIMOR_URL}/v2/send.json"),
{
username: ENV["VERIMOR_USERNAME"],
password: ENV["VERIMOR_PASSWORD"], # testte: otpmock API anahtarı
source_addr: "BASLIGIM",
messages: [{ msg: "Doğrulama kodunuz: #{code}", dest: "905321234567" }],
}.to_json,
"Content-Type" => "application/json"
)
campaign_id = res.body // Verimor has no official Go SDK; call its HTTP API with net/http, only the host changes.
base := os.Getenv("OTPMOCK_URL")
if base == "" {
base = "https://sms.verimor.com.tr"
}
body, _ := json.Marshal(map[string]any{
"username": os.Getenv("VERIMOR_USERNAME"),
"password": os.Getenv("VERIMOR_PASSWORD"), // testte: otpmock API anahtarı
"source_addr": "BASLIGIM",
"messages": []map[string]string{{"msg": msg, "dest": "905321234567"}},
})
res, err := http.Post(base+"/v2/send.json", "application/json", bytes.NewReader(body)) // plain-text campaign IDconst MUTLUCELL_URL = process.env.OTPMOCK_URL ?? "https://smsgw.mutlucell.com";
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<smspack ka="${process.env.MUTLUCELL_USER}" pwd="${process.env.MUTLUCELL_PASSWORD}" org="MUTLUCELL">
<mesaj><metin>Doğrulama kodunuz: ${code}</metin><nums>5321234567</nums></mesaj>
</smspack>`;
const res = await fetch(`${MUTLUCELL_URL}/smsgw-ws/sndblkex`, {
method: "POST",
headers: { "content-type": "text/xml; charset=UTF-8" },
body: xml,
});
const result = await res.text(); // "$12345678#1.0" or an error code import os
import requests
MUTLUCELL_URL = os.environ.get("OTPMOCK_URL", "https://smsgw.mutlucell.com")
xml = f"""<?xml version="1.0" encoding="UTF-8"?>
<smspack ka="{os.environ['MUTLUCELL_USER']}" pwd="{os.environ['MUTLUCELL_PASSWORD']}" org="MUTLUCELL">
<mesaj><metin>Doğrulama kodunuz: {code}</metin><nums>5321234567</nums></mesaj>
</smspack>""" # pwd = testte: otpmock API anahtarı
res = requests.post(f"{MUTLUCELL_URL}/smsgw-ws/sndblkex", data=xml.encode("utf-8"),
headers={"Content-Type": "text/xml; charset=UTF-8"})
result = res.text # "$12345678#1.0" or an error codeString base = System.getenv().getOrDefault("OTPMOCK_URL", "https://smsgw.mutlucell.com");
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><smspack ka=\"" + user + "\" pwd=\"" + pwd // pwd = testte: otpmock API anahtarı
+ "\" org=\"MUTLUCELL\"><mesaj><metin>" + text + "</metin><nums>05321234567</nums></mesaj></smspack>";
HttpRequest req = HttpRequest.newBuilder(URI.create(base + "/smsgw-ws/sndblkex"))
.header("Content-Type", "text/xml; charset=UTF-8")
.POST(HttpRequest.BodyPublishers.ofString(xml))
.build();
// Response: "$12345678#1.0" or an error code such as "23". using System.Security;
var mutlucellUrl = Environment.GetEnvironmentVariable("OTPMOCK_URL") ?? "https://smsgw.mutlucell.com";
var user = Environment.GetEnvironmentVariable("MUTLUCELL_USER");
var pwd = Environment.GetEnvironmentVariable("MUTLUCELL_PASSWORD"); // testte: otpmock API anahtarı
var xml = $"<?xml version=\"1.0\" encoding=\"UTF-8\"?><smspack ka=\"{SecurityElement.Escape(user)}\" pwd=\"{SecurityElement.Escape(pwd)}\" org=\"MUTLUCELL\">"
+ $"<mesaj><metin>Doğrulama kodunuz: {code}</metin><nums>5321234567</nums></mesaj></smspack>";
var res = await new HttpClient().PostAsync(mutlucellUrl + "/smsgw-ws/sndblkex",
new StringContent(xml, Encoding.UTF8, "text/xml"));
var result = await res.Content.ReadAsStringAsync(); // "$12345678#1.0" or an error code use GuzzleHttp\Client;
$mutlucellUrl = getenv('OTPMOCK_URL') ?: 'https://smsgw.mutlucell.com';
$user = htmlspecialchars(getenv('MUTLUCELL_USER'));
$pwd = htmlspecialchars(getenv('MUTLUCELL_PASSWORD')); // testte: otpmock API anahtarı
$xml = '<?xml version="1.0" encoding="UTF-8"?>'
. "<smspack ka=\"$user\" pwd=\"$pwd\" org=\"MUTLUCELL\">"
. "<mesaj><metin>Doğrulama kodunuz: $code</metin><nums>5321234567</nums></mesaj></smspack>";
$result = (string) (new Client())->post("$mutlucellUrl/smsgw-ws/sndblkex", [
'headers' => ['Content-Type' => 'text/xml; charset=UTF-8'],
'body' => $xml,
])->getBody(); // "$12345678#1.0" or an error code require "net/http"
# Apps post the XML directly, so only the host changes.
MUTLUCELL_URL = ENV.fetch("OTPMOCK_URL", "https://smsgw.mutlucell.com")
xml = <<~XML
<?xml version="1.0" encoding="UTF-8"?>
<smspack ka="#{ENV["MUTLUCELL_USER"]}" pwd="#{ENV["MUTLUCELL_PASSWORD"]}" org="MUTLUCELL">
<mesaj><metin>Doğrulama kodunuz: #{code}</metin><nums>5321234567</nums></mesaj>
</smspack>
XML
# pwd = testte: otpmock API anahtarı
res = Net::HTTP.post(URI("#{MUTLUCELL_URL}/smsgw-ws/sndblkex"), xml, "Content-Type" => "text/xml; charset=UTF-8")
result = res.body # "$12345678#1.0" or an error code // Mutlucell has no official Go SDK; call its HTTP API with net/http, only the host changes.
base := os.Getenv("OTPMOCK_URL")
if base == "" {
base = "https://smsgw.mutlucell.com"
}
xml := fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?>
<smspack ka="%s" pwd="%s" org="MUTLUCELL"><mesaj><metin>%s</metin><nums>5321234567</nums></mesaj></smspack>`,
os.Getenv("MUTLUCELL_USER"), os.Getenv("MUTLUCELL_PASSWORD"), msg) // pwd = testte: otpmock API anahtarı
res, err := http.Post(base+"/smsgw-ws/sndblkex", "text/xml; charset=UTF-8", strings.NewReader(xml)) // "$12345678#1.0" or an error code import { IletiMerkeziClient } from "@iletimerkezi/iletimerkezi-node";
export const ileti = new IletiMerkeziClient(
process.env.ILETIMERKEZI_API_KEY, // testte: otpmock API anahtarı
process.env.ILETIMERKEZI_API_HASH,
process.env.ILETIMERKEZI_SENDER,
);
if (process.env.OTPMOCK_URL) (ileti as any).httpClient.baseUrl = `${process.env.OTPMOCK_URL}/v1/`; import os
import requests
ILETI_URL = os.environ.get("OTPMOCK_URL", "https://api.iletimerkezi.com")
res = requests.post(f"{ILETI_URL}/v1/send-sms/json", json={"request": {
"authentication": {
"key": os.environ["ILETIMERKEZI_API_KEY"], # testte: otpmock API anahtarı
"hash": os.environ["ILETIMERKEZI_API_HASH"],
},
"order": {"sender": "BASLIGIM", "sendDateTime": [], "iys": "0",
"message": {"text": f"Doğrulama kodunuz: {code}", "receipents": {"number": ["5321234567"]}}},
}})String base = System.getenv().getOrDefault("OTPMOCK_URL", "https://api.iletimerkezi.com");
// json: {"request":{"authentication":{"key":"<ILETIMERKEZI_API_KEY, testte: otpmock API anahtarı>","hash":"..."},
// "order":{"sender":"...","iys":"0","message":{"text":"...","receipents":{"number":["5051234567"]}}}}}
HttpRequest req = HttpRequest.newBuilder(URI.create(base + "/v1/send-sms/json"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build(); // İleti Merkezi has no official .NET SDK; call the JSON API with HttpClient.
var iletiUrl = Environment.GetEnvironmentVariable("OTPMOCK_URL") ?? "https://api.iletimerkezi.com";
await new HttpClient().PostAsJsonAsync(iletiUrl + "/v1/send-sms/json", new
{
request = new
{
authentication = new
{
key = Environment.GetEnvironmentVariable("ILETIMERKEZI_API_KEY"), // testte: otpmock API anahtarı
hash = Environment.GetEnvironmentVariable("ILETIMERKEZI_API_HASH"),
},
order = new
{
sender = "BASLIGIM", sendDateTime = Array.Empty<string>(), iys = "0",
message = new { text = $"Doğrulama kodunuz: {code}", receipents = new { number = new[] { "5051234567" } } },
},
},
}); use IletiMerkezi\IletiMerkeziClient;
$ileti = new IletiMerkeziClient(
getenv('ILETIMERKEZI_API_KEY'), // testte: otpmock API anahtarı
getenv('ILETIMERKEZI_API_HASH'),
getenv('ILETIMERKEZI_SENDER'),
);
if ($otpmock = getenv('OTPMOCK_URL')) {
// The SDK has no base URL option; its HTTP client keeps the URL in a private property.
$http = (fn () => $this->httpClient)->call($ileti);
(fn () => $this->baseUrl = rtrim($otpmock, '/') . '/v1/')->call($http);
} require "net/http"
require "json"
# İleti Merkezi has no official Ruby SDK; apps call the REST API, so only the host changes.
ILETI_URL = ENV.fetch("OTPMOCK_URL", "https://api.iletimerkezi.com")
res = Net::HTTP.post(
URI("#{ILETI_URL}/v1/send-sms/json"),
{ request: {
authentication: { key: ENV["ILETIMERKEZI_API_KEY"], hash: ENV["ILETIMERKEZI_API_HASH"] }, # key = testte: otpmock API anahtarı
order: { sender: ENV["ILETIMERKEZI_SENDER"], sendDateTime: [], iys: "0",
message: { text: "Doğrulama kodunuz: #{code}", receipents: { number: ["5051234567"] } } },
} }.to_json,
"Content-Type" => "application/json"
) // İleti Merkezi has no official Go SDK; call its HTTP API with net/http, only the host changes.
base := os.Getenv("OTPMOCK_URL")
if base == "" {
base = "https://api.iletimerkezi.com"
}
body, _ := json.Marshal(map[string]any{"request": map[string]any{
"authentication": map[string]string{
"key": os.Getenv("ILETIMERKEZI_API_KEY"), // testte: otpmock API anahtarı
"hash": os.Getenv("ILETIMERKEZI_API_HASH"),
},
"order": map[string]any{
"sender": os.Getenv("ILETIMERKEZI_SENDER"), "iys": "0",
"message": map[string]any{"text": msg, "receipents": map[string]any{"number": []string{"5051234567"}}},
},
}})
res, err := http.Post(base+"/v1/send-sms/json", "application/json", bytes.NewReader(body)) // HTTP 200 = success3 Sağlayıcılar
Her taklit, sağlayıcının gerçek yollarını, istek gövdelerini, yanıtlarını ve hata biçimlerini izler. Node.js, Python, Java, C#, PHP, Ruby ve Go'da, sağlayıcının resmi SDK'larıyla uçtan uca sınanır. Dilinizi aşağıdan seçin.
twilio@vonage/server-sdk@aws-sdk/client-snstelnyx@aws-sdk/client-pinpoint-sms-voice-v2telesignsdkbandwidth-sdk@infobip-api/sdk@sinch/sdk-core@messagebird/sdkplivo@netgsm/smsHTTP APIHTTP API@iletimerkezi/iletimerkezi-nodeListede olmayan bir servis mi kullanıyorsunuz? Sağlayıcıdan bağımsız HTTP API'sine test ortamına özel bir dalda gönderin; bize yazın, gelen talepler, sıradaki işimizi belirliyor. Tüm sağlayıcılar
Sadakat kartı, iade ve puan işlemlerinde SMS ile doğrulama mı yapıyorsunuz? Bu akışları nasıl test edeceğinizi ayrıca yazdık.
4 Testlerinizde
Her teste kendi numarasını verin; paralel çalışan testler birbirinin kodunu okumasın. Sonra kodu bekleyin ve forma yazın.
test("telefonla kayıt", async ({ page }) => {
const telefon = otp.randomPhone("+905"); // her test için ayrı numara
await page.getByLabel("Telefon").fill(telefon);
const since = Date.now() - 5000; // önceki koşudan kalan kodları yok say
await page.getByRole("button", { name: "Kod gönder" }).click();
const { code } = await otp.waitForCode(telefon, { since });
await page.getByLabel("Doğrulama kodu").fill(code);
await expect(page.getByText("Hoş geldiniz")).toBeVisible();
});
// cypress.config.js: on("task", { waitForCode: (telefon) => otp.waitForCode(telefon).then((r) => r.code) })
it("telefonla kayıt olur", () => {
const telefon = "+90555" + Cypress._.random(1e7, 9e7);
cy.get("[name=telefon]").type(telefon);
cy.contains("Kod gönder").click();
cy.task("waitForCode", telefon).then((kod) => cy.get("[name=kod]").type(kod));
cy.contains("Hoş geldiniz").should("be.visible");
});
def test_kayit(driver):
telefon = "+90555" + "".join(random.choices("0123456789", k=7)) # her test için ayrı numara
driver.find_element(By.NAME, "telefon").send_keys(telefon)
since = int(time.time() * 1000) - 5000
driver.find_element(By.CSS_SELECTOR, "button[type=submit]").click()
kod = wait_for_code(telefon, since) # GET /v1/inbox/{telefon}/code adresini yoklar
driver.find_element(By.NAME, "kod").send_keys(kod)
it("SMS koduyla kayıt olur", async () => {
const telefon = otp.randomPhone("+905"); // her test için ayrı numara
await $("~phone-input").setValue(telefon);
const since = Date.now() - 5_000;
await $("~send-code-button").click();
const { code } = await otp.waitForCode(telefon, { since });
await $("~code-input").setValue(code);
await expect($("~welcome-screen")).toBeDisplayed();
});
- runScript: ../scripts/new-phone.js # output.phone değerini üretir
- tapOn: { id: "phone-input" }
- inputText: ${output.phone}
- evalScript: ${output.since = Date.now() - 5000}
- tapOn: { id: "send-code-button" }
- repeat: # kod gelene kadar yokla
times: 30
while: { true: ${output.code == ''} }
commands:
- runScript: { file: ../scripts/fetch-code.js, env: { PHONE: ${output.phone} } }
- inputText: ${output.code}
// "Kodu bekle" isteği: GET {{OTPMOCK_URL}}/v1/inbox/{{phone}}/code?since={{since}}
const attempts = Number(pm.collectionVariables.get("attempts")) + 1;
pm.collectionVariables.set("attempts", String(attempts));
if (pm.response.code === 404 && attempts < 50) {
pm.execution.setNextRequest("Kodu bekle"); // yeniden yokla
return;
}
pm.test("kod geldi", () => pm.response.to.have.status(200));
pm.collectionVariables.set("otp", pm.response.json().code);
# Bir numaraya gelen son kod (kod gelene kadar 404)
curl https://api.otpmock.com/v1/inbox/%2B905321234567/code \
-H "Authorization: Bearer $OTPMOCK_API_KEY"
{ "code": "482913", "messageSid": "SM6926…", "receivedAt": 1791406301420 }
otp yardımcısı bağımlılığı olmayan tek bir dosya: dokümandan alın (İngilizce). Yapay zeka kodlama asistanı mı kullanıyorsunuz? otpmock.com/llms-full.txt adresini verin, entegrasyonu baştan sona o yapabilir.
5 Panel
Elle test yapanlar kodların tarayıcıda düşmesini izler, tıklayıp kopyalar. Mühendisler her ortam için anahtarları yönetir. Ayın ne kadarının kaldığını herkes görür.
Acme doğrulama kodunuz: 482913
Acme: giriş kodunuz 7731. Kimseyle paylaşmayın.
Acme kodunuz: 905126
Telefon numaranızı onaylamak için 3388 kodunu girin.
Örnek verilerle çizilmiş bir görsel.
6 Ayrıntılar
since zaman damgası, önceki koşudan kalan her şeyi yok sayar.sleep yok.7 Fiyat
Bir mesaj, uygulamanızın gönderdiği tek bir SMS ya da başlattığı tek bir Verify doğrulamasıdır. Kodları okumak her zaman ücretsiz.
Uygulama → otpmock → Test
Uygulama → otpmock → Test
Uygulama → otpmock → Test
Uygulama → otpmock → Test
Fiyatlar USD cinsindendir ve aylık faturalanır. Ödeme sırasında ülkenizin gerektirdiği KDV ya da satış vergisi eklenebilir. Ödemeleri satıcı kuruluşumuz (merchant of record) Creem işler. İstediğiniz zaman iptal edebilirsiniz. Ayrıntılar için iade politikasına (İngilizce) bakın.
8 Sorular
Hayır, amaç da bu. Mesajlar API'mizden dışarı çıkmaz: operatör ücreti, teslim gecikmesi ve telefon yok. otpmock'u yalnızca test ve staging ortamlarında kullanın.
Neredeyse hiç. Bir ortam değişkeni tanımlıyken sağlayıcının SDK'sını otpmock'a yönlendirirsiniz; çoğu zaman tek bir seçenek yeter (Twilio'da httpClient, Vonage'da restHost, AWS SDK'da endpoint, Netgsm'de baseURL gibi). Canlı yapılandırmanız olduğu gibi kalır.
Evet: Twilio Verify v2, Vonage Verify v2, Telnyx Verify, Infobip 2FA, Sinch Verification, Plivo Verify, Telesign Verify ve Bird Verify. Kodu otpmock üretir, testiniz gelen kutusundan okur ve doğrulama isteği, gerçek sağlayıcının yapacağı gibi kodu onaylar. Yanlış kod ve çok fazla deneme hataları da dahil. Netgsm, İleti Merkezi, Verimor ve Mutlucell düz SMS servisleridir; kodu uygulamanız üretir, otpmock mesajı yakalar.
Netgsm (REST v2 SMS ve OTP), İleti Merkezi (JSON API), Verimor (SMS API v2) ve Mutlucell (XML API). Türk numaraları yerel biçimde (5321234567, 05321234567) ya da uluslararası biçimde (905321234567) gönderilebilir; otpmock hepsini +905321234567 olarak saklar, testte kodu bu biçimle sorgularsınız.
Olur; tek bir sağlayıcı ve düz SMS için bu gayet makul bir seçim. Sonradan zaman yiyen kısımlar şunlar: her sağlayıcının tam yanıtları ve hataları, kodu sağlayıcının ürettiği Verify akışları (yanlış kod, deneme sınırı, süre aşımı), staging ve CI'nin ulaşabildiği bir adres, elle test yapanlar için ortak bir gelen kutusu ve SDK'lar değiştikçe hepsini doğru tutmak. otpmock bunları yapar; taklitleri her değişiklikte Node.js, Python, Java, C#, PHP, Ruby ve Go'daki resmi SDK'larla sınanır. Kurulumu yapay zekaya yaptırmak isterseniz ona otpmock.com/llms-full.txt adresini verin.
Yalnızca test ve staging ortamlarınız etkilenir, canlı ortam etkilenmez; çünkü canlı ortam gerçek SMS sağlayıcınızla konuşmaya devam eder. Sağlık kontrolü 5 dakikada bir koşar, anlık durum durum sayfasındadır.
Kullanabilirsiniz ama kullanmayın. Test ortamında randomPhone() gibi uydurma numaralar tercih edin, gerçek müşteri verisi test sistemine girmesin. Hangisini kullanırsanız kullanın, her mesaj 10 dakika sonra silinir.
Hakkınız ayın 1'inde (UTC) yenilenene ya da planınızı yükseltene kadar gönderme isteği HTTP 429 döner. Kod okumak çalışmaya devam eder.
İstediğiniz zaman, hesabınızdan. Ödediğiniz dönemin sonuna kadar erişiminiz sürer. Yeni abonelikler 7 gün içinde iade edilebilir; ayrıntılar iade politikasında (İngilizce).
Anahtarınız bir dakikadan kısa sürede hazır. Ücretsiz plan, küçük bir test takımına sürekli yeter.
Ücretsiz API anahtarı al