Skip to content

Commit

Permalink
feat: add pay.ir to providers
Browse files Browse the repository at this point in the history
  • Loading branch information
Ja7ad committed Jan 6, 2023
1 parent a9e3892 commit 3132d55
Show file tree
Hide file tree
Showing 9 changed files with 218 additions and 23 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ go get -u github.com/GoFarsi/paygap

## Usage

example for zarinpal provider ([Other examples](_example))
example for zarinpal provider ([Other examples](_examples))

```go
package main
Expand Down Expand Up @@ -50,7 +50,7 @@ func main() {

- [x] zarinpal
- [x] idpay
- [ ] pay.ir
- [x] pay.ir
- [ ] yekpay
- [ ] payping
- [ ] rayanpay
Expand Down
39 changes: 39 additions & 0 deletions _example/pay/pay.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package main

import (
"context"
"fmt"
"github.com/GoFarsi/paygap/client"
"github.com/GoFarsi/paygap/providers/pay"
"log"
)

func main() {
ctx := context.Background()

p, err := pay.New(client.New(), "YOUR_API_KEY", true)
if err != nil {
log.Fatal(err)
}

resp, err := p.CreateTransaction(ctx, &pay.PaymentRequest{
Amount: 11000,
Redirect: "http://example.com/callback",
Mobile: "09151234567",
FactorNumber: "xxxxx",
Description: "desc test",
ValidCardNumber: "1234123412341234",
})

if err != nil {
log.Fatal(err)
}

fmt.Println(resp)

verifyResp, err := p.VerifyTransaction(ctx, &pay.VerifyRequest{
Token: resp.Token,
})

fmt.Println(verifyResp)
}
2 changes: 1 addition & 1 deletion client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func (c *Client) Post(ctx context.Context, apiConfig *APIConfig, headers map[str

if len(headers) != 0 {
for k, v := range headers {
req.Header.Set(k, v)
req.Header.Add(k, v)
}
}

Expand Down
12 changes: 10 additions & 2 deletions providers/idpay/idpay.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package idpay

import (
"context"
"errors"
"github.com/GoFarsi/paygap/client"
"github.com/GoFarsi/paygap/status"
"google.golang.org/grpc/codes"
"net/http"
"reflect"
)

const (
Expand Down Expand Up @@ -77,8 +79,14 @@ func (i *IdPay) TransactionList(ctx context.Context, req *TransactionListRequest
}

func request[RQ any, RS any](ctx context.Context, i *IdPay, req RQ, baseUrl string, endpoint string) (response RS, err error) {
r, ok := reflect.New(reflect.TypeOf(response).Elem()).Interface().(RS)
if !ok {
return response, errors.New("response type is invalid")
}

headers := make(map[string]string)
headers["X-API-KEY"] = i.apiKey
headers["Content-Type"] = "application/json"

if i.sandbox {
headers["X-SANDBOX"] = "1"
Expand All @@ -97,9 +105,9 @@ func request[RQ any, RS any](ctx context.Context, i *IdPay, req RQ, baseUrl stri
return response, status.New(errResp.ErrorCode, http.StatusFailedDependency, codes.OK, errResp.ErrorMessage)
}

if err := resp.GetJSON(response); err != nil {
if err := resp.GetJSON(r); err != nil {
return response, status.New(0, http.StatusInternalServerError, codes.Internal, err.Error())
}

return response, nil
return r, nil
}
14 changes: 7 additions & 7 deletions providers/idpay/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ type ErrorResponse struct {
type PaymentRequest struct {
OrderId string `validate:"required,max=50" json:"order_id"`
Amount uint `validate:"required,min=1000,max=5000000000" json:"amount"`
Name string `validate:"max=255" json:"name"`
Phone string `validate:"max=11" json:"phone"`
Name string `validate:"omitempty,max=255" json:"name"`
Phone string `validate:"omitempty,max=11" json:"phone"`
Mail string `validate:"email,max=255" json:"mail"`
Desc string `validate:"max=255" json:"desc"`
Callback string `validate:"required,max=2048" json:"callback"`
Desc string `validate:"omitempty,max=255" json:"desc"`
Callback string `validate:"required,max=2048,url" json:"callback"`
}

type PaymentResponse struct {
Expand Down Expand Up @@ -102,11 +102,11 @@ type TransactionListRequest struct {
Page uint `json:"page"`
PageSize uint `json:"page_size"`
Id string `json:"id"`
OrderId string `validate:"max=50" json:"order_id"`
Amount uint `validate:"max=5000000000,min=1000" json:"amount"`
OrderId string `validate:"omitempty,max=50" json:"order_id"`
Amount uint `validate:"omitempty,max=5000000000,min=1000" json:"amount"`
Status []string `json:"status"`
TrackId string `json:"track_id"`
PaymentCardNo string `validate:"max=16" json:"payment_card_no"`
PaymentCardNo string `validate:"omitempty,max=16" json:"payment_card_no"`
PaymentHashedCardNo string `json:"payment_hashed_card_no"`
PaymentDate struct {
Min uint `json:"min"`
Expand Down
53 changes: 53 additions & 0 deletions providers/pay/models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package pay

import "github.com/GoFarsi/paygap/client"

type Pay struct {
client client.Transporter
apiKey string

host string
paymentEndpoint string
verifyEndpoint string
}

type ErrorResponse struct {
Status int `json:"status"`
ErrorCode int `json:"errorCode"`
ErrorMessage string `json:"errorMessage"`
}

type Request struct {
API string `json:"api"`
*PaymentRequest
*VerifyRequest
}

type PaymentRequest struct {
Amount uint `json:"amount" validate:"required,min=10000"`
Redirect string `json:"redirect" validate:"required,url"`
Mobile string `json:"mobile,omitempty" validate:"omitempty,min=11"`
FactorNumber string `json:"factorNumber,omitempty"`
Description string `json:"description,omitempty" validate:"omitempty,max=255"`
ValidCardNumber string `json:"validCardNumber,omitempty" validate:"omitempty,max=16"`
}

type PaymentResponse struct {
Status int `json:"status"`
Token string `json:"token"`
}

type VerifyRequest struct {
Token string `json:"token" validate:"required"`
}

type VerifyResponse struct {
Status int `json:"status"`
Amount string `json:"amount"`
TransId string `json:"transId"`
FactorNumber string `json:"factorNumber"`
Mobile string `json:"mobile"`
Description string `json:"description"`
CardNumber string `json:"cardNumber"`
Message string `json:"message"`
}
95 changes: 95 additions & 0 deletions providers/pay/pay.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package pay

import (
"context"
"errors"
"github.com/GoFarsi/paygap/client"
"github.com/GoFarsi/paygap/status"
"google.golang.org/grpc/codes"
"net/http"
"reflect"
)

const (
PAY_HOST = "https://pay.ir"

PAYMENT_ENDPOINT = "/pg/send"
VERIFY_ENDPOINT = "/pg/verify"
)

func New(client client.Transporter, apiKey string, sandbox bool) (*Pay, error) {
if client == nil {
return nil, status.ERR_CLIENT_IS_NIL
}

pay := new(Pay)

pay.client = client
pay.host = PAY_HOST
pay.apiKey = apiKey
pay.paymentEndpoint = PAYMENT_ENDPOINT
pay.verifyEndpoint = VERIFY_ENDPOINT

if sandbox {
pay.apiKey = "test"
}

if err := client.GetValidator().Struct(pay); err != nil {
return nil, status.New(0, http.StatusBadRequest, codes.InvalidArgument, err.Error())
}

return pay, nil
}

func (p *Pay) CreateTransaction(ctx context.Context, req *PaymentRequest) (*PaymentResponse, error) {
if err := p.client.GetValidator().Struct(req); err != nil {
return nil, status.New(0, http.StatusBadRequest, codes.InvalidArgument, err.Error())
}

gatewayReq := new(Request)
gatewayReq.API = p.apiKey
gatewayReq.PaymentRequest = req

return request[*Request, *PaymentResponse](ctx, p, gatewayReq, p.paymentEndpoint)
}

func (p *Pay) VerifyTransaction(ctx context.Context, req *VerifyRequest) (*VerifyResponse, error) {
if err := p.client.GetValidator().Struct(req); err != nil {
return nil, status.New(0, http.StatusBadRequest, codes.InvalidArgument, err.Error())
}

gatewayReq := new(Request)
gatewayReq.API = p.apiKey
gatewayReq.VerifyRequest = req

return request[*Request, *VerifyResponse](ctx, p, gatewayReq, p.verifyEndpoint)
}

func request[RQ any, RS any](ctx context.Context, p *Pay, req RQ, endpoint string) (response RS, err error) {
r, ok := reflect.New(reflect.TypeOf(response).Elem()).Interface().(RS)
if !ok {
return response, errors.New("response type is invalid")
}

errResp := new(ErrorResponse)
headers := make(map[string]string)
headers["Content-Type"] = "application/json"

resp, err := p.client.Post(ctx, &client.APIConfig{Host: p.host, Path: endpoint}, headers, req)
if err != nil {
return response, status.New(0, http.StatusInternalServerError, codes.Internal, err.Error())
}

if resp.GetHttpResponse().StatusCode != http.StatusOK {
if err := resp.GetJSON(errResp); err != nil {
return response, status.New(0, http.StatusInternalServerError, codes.Internal, err.Error())
}
return response, status.New(errResp.ErrorCode, http.StatusFailedDependency, codes.OK, errResp.ErrorMessage)
}

if err := resp.GetJSON(r); err != nil {
return response, status.New(0, http.StatusInternalServerError, codes.Internal, err.Error())
}

return r, nil
}
12 changes: 6 additions & 6 deletions providers/zarinpal/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,26 @@ type Zarinpal struct {
}

type paymentRequest struct {
MerchantID string `json:"merchant_id" validate:"required"`
Amount uint `json:"amount" validate:"min=5000"`
merchantID string `json:"merchant_id" validate:"required"`
Amount uint `json:"amount" validate:"required,min=5000"`
Currency string `json:"currency"`
CallBackURL string `json:"callback_url" validate:"url"`
CallBackURL string `json:"callback_url" validate:"required,url"`
Description string `json:"description"`
MetaData map[string]interface{} `json:"metadata"`
}

type verifyRequest struct {
MerchantID string `json:"merchant_id" validate:"required"`
merchantID string `json:"merchant_id" validate:"required"`
Amount uint `json:"amount" validate:"min=0"`
Authority string `json:"authority"`
}

type unverifiedTransactionsRequest struct {
MerchantID string `json:"merchant_id" validate:"required"`
merchantID string `json:"merchant_id" validate:"required"`
}

type floatingShareSettlementRequest struct {
MerchantID string `json:"merchant_id" validate:"required"`
merchantID string `json:"merchant_id" validate:"required"`
Amount uint `json:"amount" validate:"min=5000"`
CallBackURL string `json:"callback_url" validate:"url"`
Description string `json:"description"`
Expand Down
10 changes: 5 additions & 5 deletions providers/zarinpal/zarinpal.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func New(client client.Transporter, merchantID string, sandbox bool) (*Zarinpal,
// RequestPayment create payment request and return status code and authority
func (z *Zarinpal) RequestPayment(ctx context.Context, amount uint, callBackUrl, currency, description string, metaData map[string]interface{}) (*PaymentResponse, error) {
req := &paymentRequest{
MerchantID: z.merchantID,
merchantID: z.merchantID,
Amount: amount,
Currency: currency,
CallBackURL: callBackUrl,
Expand Down Expand Up @@ -76,7 +76,7 @@ func (z *Zarinpal) RequestPayment(ctx context.Context, amount uint, callBackUrl,
// VerifyPayment transaction by merchant id, amount and authority to payment provider
func (z *Zarinpal) VerifyPayment(ctx context.Context, amount uint, authority string) (*VerifyResponse, error) {
req := &verifyRequest{
MerchantID: z.merchantID,
merchantID: z.merchantID,
Amount: amount,
Authority: authority,
}
Expand All @@ -101,7 +101,7 @@ func (z *Zarinpal) VerifyPayment(ctx context.Context, amount uint, authority str
// UnverifiedTransactions get unverified transactions from provider
func (z *Zarinpal) UnverifiedTransactions(ctx context.Context) (*UnverifiedTransactionsResponse, error) {
req := &unverifiedTransactionsRequest{
MerchantID: z.merchantID,
merchantID: z.merchantID,
}

if err := z.client.GetValidator().Struct(req); err != nil {
Expand All @@ -125,7 +125,7 @@ func (z *Zarinpal) UnverifiedTransactions(ctx context.Context) (*UnverifiedTrans
// more information in https://docs.zarinpal.com/paymentGateway/setshare.html#%D8%AA%D8%B3%D9%88%DB%8C%D9%87-%D8%A7%D8%B4%D8%AA%D8%B1%D8%A7%DA%A9%DB%8C-%D8%B4%D9%86%D8%A7%D9%88%D8%B1
func (z *Zarinpal) FloatingShareSettlement(ctx context.Context, amount uint, description, callbackUrl string, wages []*Wages, metaData map[string]interface{}) (*FloatingShareSettlementResponse, error) {
req := &floatingShareSettlementRequest{
MerchantID: z.merchantID,
merchantID: z.merchantID,
Amount: amount,
CallBackURL: callbackUrl,
Description: description,
Expand Down Expand Up @@ -153,7 +153,7 @@ func (z *Zarinpal) FloatingShareSettlement(ctx context.Context, amount uint, des
// VerifyFloatingShareSettlement verify floating share settlement
func (z *Zarinpal) VerifyFloatingShareSettlement(ctx context.Context, amount uint, authority string) (*VerifyFloatingShareSettlementResponse, error) {
req := &verifyRequest{
MerchantID: z.merchantID,
merchantID: z.merchantID,
Amount: amount,
Authority: authority,
}
Expand Down

0 comments on commit 3132d55

Please sign in to comment.