phone-number-service

command module
v0.4.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 27, 2019 License: Apache-2.0 Imports: 20 Imported by: 0

README

Phone number microservice

It's a gRPC based microservice. It uses Aliyun service to send sms to a phone and the codes sent are stored in MySQL compatiable databases. It has two interfaces:

  • SendSMS, send a random 6 digits code to the specified phone number.
  • Valid, check if the code is right.

Get the package:

go get github.com/liulinhuai/phone-number-service/phonenumberservice

Implementation

  • No sending policy is implemented, such as limiting the number of codes sent to a phone number per day or total, as Aliyun already implements that and it's configable.

  • After a successful call of SendSMS, all the previous codes of the same phone number will be invalidated.

  • After Valid is called more than attemptLimit(default is 3) against the same phone number p, all the codes sent to p will be invalidated to prevent guessing the codes.

  • After a call to Valid returned true, the following requests with the same phone number and code will return false even the code is correct. This means a code can only be used one time.

The full proto definition

syntax = "proto3";

package phonenumberservice;

service PhoneNumberService {
    rpc SendSMS(SendSMSRequest) returns (Empty) {}
    rpc Valid(ValidRequest) returns (ValidResponse) {}
}

message Empty {}

message SendSMSRequest {
    string phone_number = 1;
    string signature = 2;
    string template_code = 3;
}

message ValidRequest {
    string phone_number = 1;
    string code = 2;
}

message ValidResponse {
    bool valid = 1;
}

Example usage

func Example() {
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
	defer cancel()

	conn, err := grpc.DialContext(ctx, ":50511", grpc.WithInsecure(), grpc.WithBlock())
	if err != nil {
		fmt.Printf("Dial returned an error: %v\n", err)
		return
	}
	c := pb.NewPhoneNumberServiceClient(conn)
	p := "186xxxxxxxx"

	req := &pb.SendSMSRequest{PhoneNumber: p, Signature: "xxx", TemplateCode: "xxx"}
	if _, err := c.SendSMS(ctx, req); err != nil {
		fmt.Printf("SendSMS returned error: %v\n", err)
		return
	}

	resp, err := c.Valid(ctx, &pb.ValidRequest{PhoneNumber: p, Code: "123456"})
	if err != nil {
		fmt.Printf("Valid returned error: %v\n", err)
		return
	}
	if !resp.Valid {
		fmt.Printf("Valid returned false, want true\n")
	}
}

Set up the service

  • Set up the database first. Create the database:

    CREATE DATABASE `PhoneNumberService` DEFAULT CHARACTER SET ascii COLLATE ascii_bin;
    

    Create the tables by using phonenumberservice.sql, note it uses ascii character set.

  • Set the environment variables needed by this service:

    Data_SOURCE_NAME for connecting to a database, example:

    root:password@tcp([192.168.1.100]:3306)/PhoneNumberService
    

    ALIYUN_ACCESS_KEY_ID and ALIYUN_ACCESS_KEY_SECRET for sending sms.

Use this service

  • Clone this repository, and run the tests to make sure it works:

    git clone git@github.com:liulinhuai/phone-number-service.git
    cd phone-number-service
    go test
    

    Tests that send real sms are skipped, to test them, comment the skip statement:

    // t.Skip("send real sms is skipped")
    
  • Clone this repository and modify it as needed or use it as a docker image:

    docker pull liulinhuai/phone-number-service:v0.1.0
    
  • Run the image (replace the password, ip and 'xxx'):

    docker run \
      -e DATA_SOURCE_NAME='root:password@tcp([192.168.1.100]:3306)/PhoneNumberService' \
      -e ALIYUN_ACCESS_KEY_ID=xxx \
      -e ALIYUN_ACCESS_KEY_SECRET=xxx \
      -p 50511:50511 phone-number-service
    

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL