1Pay

API OTP Charging


Các bước thực hiện

1 End User gửi yêu cầu giao dịch đến Merchant.

2 Merchant thực hiện redirect thông tin cần thanh toán đến 1Pay.

3 1Pay xử lý và trả về thông tin giao dịch tương ứng cho Merchant, đồng thời trả otp về số điện thoại cho End User.

4 End User nhập OTP vừa nhận được trên website/app của Merchant.

5 Merchant thực hiện request sang 1pay để xác nhận giao dịch.

6 1Pay trả kết quả giao dịch cho merchant, merchant trả kết quả cuối và xử lý trong web/app cho End User.

1. Gửi thông tin và thực hiện giao dịch

Địa chỉ nhận Request Charging:

POST  http://api.1pay.vn/direct-charging/charge/request

Giao thức truyền dữ liệu: HTTP/HTTPS POST
Max request time out: 30 seconds

Tham số Mô tả
access_key Đại diện cho sản phẩm của merchant khai báo trong hệ thống 1pay.
amount Mệnh giá thực hiện thanh toán từ 1000 đ - > 100.000 đ (phải là bội số của 1000 đ).
content Mô tả giao dịch.
msisdn Số điện thoại thực hiện việc thanh toán qua direct changing.
requestId Tham số mà merchant tự sinh ra để gửi lên server.
signature Chữ ký, merchant có thể sử dụng signature để kiểm soát an ninh.
Signature là một chuỗi string: access_key=$access_key&amount=$amount&content=$content&msisdn=$msisdn&requestId=$requestId được hmac bằng thuật toán SHA256

Response

Trong trường hợp kiểm tra chữ ký không hợp lệ, hệ thống sẽ trả về trạng thái http 403 Forbidden. Nếu tham số không hợp lệ(thiếu tham số hoặc độ dài tham số không phù hợp), hệ thống sẽ trả về trạng thái http 400 Bad request.

Sau khi xử lý, số điện thoại đã đăng ký giao dịch (msisdn) sẽ nhận được OTP, đồng thời 1pay trả về kết quả cho merchant dưới dạng sau:

{"errorMessage":"[Thông báo]","requestId":"[requestId thực hiện giao dịch]", "transId":"[Mã giao dịch]","errorCode":"[Mã lỗi]"}

Chú ý: Riêng đối với mạng vina thì 1pay trả về kết quả cho merchant dưới dạng sau:

{"errorMessage":"[Thông báo]","requestId":"[requestId thực hiện giao dịch]", "transId":"[Mã giao dịch]","errorCode":"[Mã lỗi]","redirectUrl":"[url]"}

Merchant cần thực hiện redirect đến địa chỉ redirectUrl nhận được từ bước 1. Hệ thống 1Pay sẽ hiển thị ô nhập mã otp với user.

2. Xác nhận lại giao dịch

2.1: Đối với mạng VinaPhone.

User sau khi nhập đúng otp 1pay sẽ thực hiện request đến webservice của merchant ở dạng HTTP GET với các tham số như sau:

Tham số Mô tả
access_key Đại diện cho sản phẩm của merchant khai báo trong hệ thống 1pay.
amount Số tiền trừ vào tài khoản khách hàng.
errorCode Là mã lỗi 1pay trả về cho khách hàng.
errorMessage Thông báo lỗi 1Pay gửi về cho merchant.
msisdn Số điện thoại nhắn tin của khách hàng, theo chuẩn international, bắt đầu bằng 84.
requestId Tham số mà merchant đã sinh ra trước đó để gửi request lên server để lấy otp.
request_time Thời gian user thực hiện giao dịch, ở dạng iso, ví dụ: 2015-10-02T15:43:50Z.
transId Tham số được server gửi về khi thực hiện charging request.
signature Chữ ký, merchant có thể sử dụng signature để kiểm soát an ninh.
Signature là một chuỗi string: access_key=$access_key&amount=$amount&errorCode=$errorCode&errorMessage=$errorMessage&msisdn=$msisdn&requestId=$requestId&request_time=$request_time&transId=$transId được hmac bằng thuật toán SHA256

Response.

Sau khi xử lý, webservice cần trả về nội dung ở dạng json với cấu trúc như sau:

{"status":status,"sms":"nội dung tin nhắn cần trả về cho khách hàng" ,"type" :"loại tin nhắn"}

Trong đó

Tham số Mô tả
status Trạng thái xử lý, nhận giá trị: 1 - Tính phí, 0 - Không tính phí
sms Nội dung tin nhắn cần trả về cho khách hàng
type Loại tin nhắn, nhận giá trị: text, hoặc wap_push

2.2: Đối với mạng Viettel và Mobifone.

Địa chỉ nhận Request Charging:

POST  http://api.1pay.vn/direct-charging/charge/confirm

Tham số Mô tả
access_key Đại diện cho sản phẩm của merchant khai báo trong hệ thống 1pay.vn.
otp Mã otp được gửi về tin nhắn của số điện thoại thực hiện việc thanh toán( gửi về số msisdn đã khai báo ở charging request).
requestId Tham số mà merchant đã sinh ra trước đó để gửi request lên server để lấy otp.
transId Tham số được server gửi về khi thực hiện charging request.
signature Chữ ký
Signature là một chuỗi string:
access_key=$access_key&otp=$otp&requestId=$requestId&transId=$transId được hmac bằng thuật toán SHA256.

Response.

Sau khi xử lý, hệ thống 1pay sẽ trả về nội dung ở dạng json:

{"errorMessage":"[Thông báo]","requestId":"[request Id thực hiện giao dịch]", "transId":"[Mã giao dịch]","errorCode":"[Mã lỗi]"}

3.Truy vấn lại kiểm tra kết quả giao dịch (Query Api)

Địa chỉ nhận Request Charging:

GET  http://merchant.1pay.vn/charging/service/logs

Giao thức truyền dữ liệu: HTTP
Max request time out: 20 giây

Tham số Mô tả
access_key Đại diện cho sản phẩm của merchant khai báo trong hệ thống 1pay.vn
request_id requestId của giao dịch muốn kiểm tra nhận được ở bước 1
charging_type Loại hình dịch vụ (Ở đây là “direct”)
signature Chữ ký, là một chuỗi string:
access_key=$access_key&charging_type=$charging_type&request_id=$request_id
được hmac bằng thuật toán SHA256

Response trả về có dạng json

{"direct":{"amount":[Mệnh giá tin nhắn],"request_id":"requestId của giao dịch","status":"Trạng thái giao dịch","trans_id":"transId của giao dịch","msisdn":"Số điện thoại","error_message":"Mã lỗi và miêu tả mã lỗi","request_time":"thời gian thực hiện giao dịch","info":"nội dung giao dịch"},"message":"You have one transaction detail","status":1,"type":"text"}

Trong đó

Tham số Mô tả
status Trạng thái xử lý, nhận giá trị: 1 - Giao dịch thất bại, 0 - Giao dịch thành công

Bảng mã lỗi.

Mã trạng thái Mô tả
00 Giao dịch thành công
01 Lỗi, địa chỉ IP truy cập API bị từ chối.
02 Lỗi, tham số gửi từ merchant tới chưa chính xác (thường sai tên tham số hoặc thiếu tham số)
03 Lỗi, merchant không tồn tại hoặc merchant đang bị khóa kết nối.
04 Mật khẩu hoặc chữ ký xác thực không chính xác.
05 Trùng mã giao dịch (transRef).
06 Mã giao dịch không tồn tại hoặc sai định dạng.
07 Thuê bao không hợp lệ.
08 Không gửi được mã OTP cho khách hàng.
09 Không kết nối được đến Charging Proxy.
10 Tài khoản không đủ để thực hiện trừ tiền.
11 Nhập sai mã OTP.
12 Lỗi gửi tin nhắn báo trừ tiền.
13 Chưa khai báo CPCODE.
14 Số tiền thanh toán quá lớn.
15 Lỗi hệ thống WebCharging.
16 Số tiền nạp trong ngày lớn hơn 500.000 vnd.
17 Hệ thống đơn vị phát hành (Telco) bị lỗi hoặc quá tải, thẻ chưa bị trừ.
18 Đã gửi OTP cho khách hàng.
19 Số lần thực hiện giao dịch trong một đơn vị thời gian của thuê bao vượt quá giới hạn cho phép.
20 Số lần thử (nhập sai liên tiếp) của giao dịch vượt quá giới hạn cho phép.
21 Hệ thống đơn vị phát hành (Telco) bị lỗi hoặc quá tải, thuê bao chưa bị trừ.
22 Đơn vị phát hành không hỗ trợ nghiệp vụ này.
23 Kết nối tới hệ thống đơn vị phát hành (Telco) bị lỗi, thuê bao chưa bị trừ (thường do lỗi kết nối với Telco, ví dụ sai tham số kết nối, mà không liên quan đến merchant).
24 Kết nối 1Pay tới hệ thống đơn vị cung cấp bị lỗi, thẻ chưa bị trừ.
99 Lỗi, tuy nhiên lỗi chưa được định nghĩa hoặc chưa xác định được nguyên nhân.

   public static String getCarrierCode(Context context) {
	TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    String mccmnc = telephonyManager.getSimOperator();
    if (mccmnc == null) {
        return null;
    }
    String code = null;
    if (mccmnc.equals("45204")) {
        code = "viettel";
    } else if (mccmnc.equals("45201")) {
        code = "mobifone";
    } else if (mccmnc.equals("45202")) {
        code = "vinaphone";
    } else if (mccmnc.equals("45205")) {
        code = "vietnamobile";
    } else if (mccmnc.equals("45203")) {
        code = "sfone";
    }
    return code;
}

  File ChargeReqestResult.java


package server;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Random;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.JSONObject;

@WebServlet("/ChargeReqestResult")
public class ChargeReqestResult extends HttpServlet {

	private static final long serialVersionUID = 1L;
	private String json;

	public ChargeReqestResult() {
		super();
	}

	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

	}

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
        String errorMessage;
		String requests;
		String transId;
		String errorCode;	 
		String redirectUrl;    
        
		String amount = request.getParameter("amount"); // thap nhat la 1000vnd
		String phone = request.getParameter("msisdn");
		String content = request.getParameter("content");
		String requestId = randomString();
		final String access_key = ""; // access key do 1pay cung cap
		try {
			sendPost(access_key, amount, content, phone, requestId);
			// decode json
			JSONObject jObj = new JSONObject(json);
			errorMessage = jObj.getString("errorMessage");
			requests = jObj.getString("requestId");
			transId = jObj.getString("transId");
			errorCode = jObj.getString("errorCode");
			if (jObj.has("redirectUrl")) {
				redirectUrl = jObj.getString("redirectUrl");
				response.sendRedirect(redirectUrl);
			}else {
				request.setAttribute("accKey", access_key);
				request.setAttribute("errorMessage", errorMessage);
				request.setAttribute("requestId", requests);
				request.setAttribute("transId", transId);
				request.setAttribute("errorCode", errorCode);
				response.setContentType("application/json;charset=UTF-8");
				request.getRequestDispatcher("WEB-INF/jsp/Confirm.jsp").forward(
						request, response);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private String randomString() {
		final String RAND = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
		Random random = new Random();
		StringBuilder builder = new StringBuilder();
		for (int i = 0; i < 10; i++) {
			builder.append(RAND.charAt(random.nextInt(RAND.length())));
		}
		return builder.toString();
	}

	private static String hmacDigest(String msg, String keyString, String algo) {
		String digest = "";
		try {
			if (keyString != null && keyString.length() > 0) {
				SecretKeySpec key = new SecretKeySpec(
						(keyString).getBytes("UTF-8"), algo);
				Mac mac = Mac.getInstance(algo);
				mac.init(key);
				byte[] bytes = mac.doFinal(msg.getBytes("ASCII"));
				StringBuffer hash = new StringBuffer();
				for (int i = 0; i < bytes.length; i++) {
					String hex = Integer.toHexString(0xFF & bytes[i]);
					if (hex.length() == 1) {
						hash.append('0');
					}
					hash.append(hex);
				}
				digest = hash.toString();
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		}
		return digest;
	}

	private String generateSignature(String access_key, String amount,
			String content, String msisdn, String requestId, String secret) {
		String urlParameters = "";
		String signature = "";
		if ((access_key != null) && (amount != null) && (content != null)
				&& (msisdn != null) && (requestId != null)) {
			urlParameters = "access_key="+access_key+"&amount="+amount+"&content="+content+"&msisdn="+msisdn+"&requestId="+requestId;
			signature = hmacDigest(urlParameters, secret, "HmacSHA256");
			System.out.println("Signature:" + signature);
		}
		return signature;
	}

	private void sendPost(String access_key, String amount, String content,
			String msisdn, String requestId) throws Exception {
		String url = "http://api.1pay.vn/direct-charging/charge/request";
		String secretKey = "";  //secret key do 1pay cung cap
		String signature = generateSignature(access_key, amount, content,
				msisdn, requestId, secretKey);
		URL obj = new URL(url);
		HttpURLConnection con = (HttpURLConnection) obj.openConnection();
		con.setRequestMethod("POST");
		con.setRequestProperty("User-Agent", "Mozilla/5.0");
		con.setRequestProperty("Accept-Language", "en-US,en;q0.5");
		String urlParameters = "access_key="+access_key+"&amount="+amount+"&content="+content+"&msisdn="+msisdn+"&requestId="+requestId+"&signature="+signature;

		con.setDoOutput(true);
		DataOutputStream wr = new DataOutputStream(con.getOutputStream());
		wr.writeBytes(urlParameters);
		wr.flush();
		wr.close();

		int responseCode = con.getResponseCode();
		System.out.println("URL : " + url);
		System.out.println("Parameters : " + urlParameters);
		System.out.println("Response Code : " + responseCode);
		BufferedReader in = new BufferedReader(new InputStreamReader(
				con.getInputStream(), "UTF-8"));
		String inputLine;
		StringBuffer response = new StringBuffer();
		while ((inputLine = in.readLine()) != null) {
			response.append(inputLine);
		}
		in.close();
		json = response.toString();
		System.out.println(json);
	}
}

  File ConfirmResult.java


package server;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@WebServlet("/ConfirmResult")
public class ConfirmResult extends HttpServlet {
	private static final long serialVersionUID = 1L;

    public ConfirmResult() {
        super();
    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String accKey = request.getParameter("access_key");
		String otp = request.getParameter("otp");
		String requestId = request.getParameter("requestId");
		String transId = request.getParameter("transId");
		try {
			sendPost(accKey, otp, requestId, transId);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private static String hmacDigest(String msg, String keyString, String algo) {
		String digest = "";
		try {
			if (keyString != null && keyString.length() > 0) {
				SecretKeySpec key = new SecretKeySpec(
						(keyString).getBytes("UTF-8"), algo);
				Mac mac = Mac.getInstance(algo);
				mac.init(key);
				byte[] bytes = mac.doFinal(msg.getBytes("ASCII"));
				StringBuffer hash = new StringBuffer();
				for (int i = 0; i < bytes.length; i++) {
					String hex = Integer.toHexString(0xFF & bytes[i]);
					if (hex.length() == 1) {
						hash.append('0');
					}
					hash.append(hex);
				}
				digest = hash.toString();
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		}
		return digest;
	}
	
	private String generateSignature(String access_key, String otp,
			String requestId, String transId, String secret) {
		String urlParameters = "";
		String signature = "";
		if ((access_key != null) && (otp != null) && (requestId != null)
				&& (transId != null)) {
			urlParameters = "access_key="+access_key+"&otp="+otp+"&requestId="+requestId+"&transId="+transId;
			signature = hmacDigest(urlParameters, secret, "HmacSHA256");
			System.out.println("Signature:"+signature);
		}
		return signature;
	}
	
	private void sendPost(String access_key, String otp, String requestId, String transId) throws Exception {
		String url = "http://api.1pay.vn/direct-charging/charge/confirm";
		String secretKey =""; // secret key do 1pay cung cap
		String signature = generateSignature(access_key, otp, requestId, transId, secretKey);
		URL obj = new URL(url);
		HttpURLConnection con = (HttpURLConnection) obj.openConnection();
		con.setRequestMethod("POST");
		con.setRequestProperty("User-Agent", "Mozilla/5.0");
		con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
		String urlParameters = "access_key="+access_key+"&otp="+otp+"&requestId="+requestId+"&transId="+transId+"&signature="+signature;
		
		con.setDoOutput(true);
		DataOutputStream wr = new DataOutputStream(con.getOutputStream());
		wr.writeBytes(urlParameters);
		wr.flush();
		wr.close();
		
		int responseCode = con.getResponseCode();
		System.out.println("URL : " + url);
		System.out.println("Parameters : " + urlParameters);
		System.out.println("Response Code : " + responseCode);
		BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream(),"UTF-8"));
		String inputLine;
		StringBuffer response  = new StringBuffer();
		while ((inputLine = in.readLine())!=null) {
			response.append(inputLine);
		}
		in.close();	
		String json = response.toString();
		System.out.println(json);
	}
}

  File SmsWebService.java


package service;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.json.JSONException;
import org.json.JSONObject;

@Path("/")
public class SmsWebService {
	
	@GET
	@Path("/ServiceOtp")
	@Produces({MediaType.APPLICATION_JSON})
	public Response charging(
			@DefaultValue("0") @QueryParam("access_key") String accKey,
			@DefaultValue("0") @QueryParam("amount") String amount,
			@QueryParam("errorCode") String errorCode,
			@QueryParam("errorMessage") String errorMessage,
			@QueryParam("msisdn") String msisdn,
			@QueryParam("requestId") String requestId,
			@QueryParam("request_time") String request_time,
			@QueryParam("transId") String transId,
			@QueryParam("signature") String signature) {
		JSONObject json = new JSONObject();
		try {
			String secret = ""; // Secret Key do 1pay cung cap. Thay bang Secret Key cua ban.
			String signatureGen = generateSignature(accKey, amount, errorCode, errorMessage, msisdn, requestId, request_time, transId, secret);
			if (signature.equalsIgnoreCase(signatureGen)) {				
				json.put("status", 1);
				json.put("sms", "Thanh toan thanh cong");
			}else {
				json.put("status", 0);
				json.put("sms", "Thanh toan that bai");
			}
			json.put("text", "text");
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return Response.status(200).entity(json.toString()).build();
	}
	
	public static String hmacDigest(String msg, String keyString, String algo) {
		String digest = "";
		try {
			if (keyString != null && keyString.length() > 0) {
				SecretKeySpec key = new SecretKeySpec(
						(keyString).getBytes("UTF-8"), algo);
				Mac mac = Mac.getInstance(algo);
				mac.init(key);
				byte[] bytes = mac.doFinal(msg.getBytes("UTF-8"));
				StringBuffer hash = new StringBuffer();
				for (int i = 0; i < bytes.length; i++) {
					String hex = Integer.toHexString(0xFF & bytes[i]);
					if (hex.length() == 1) {
						hash.append('0');
					}
					hash.append(hex);
				}
				digest = hash.toString();
			}
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return digest;
	}

	public String generateSignature(String access_key, String amount,
			String errorCode, String errorMessage, String msisdn,
			String requestId, String request_time,String transId, String secret) {
		String urlParameters = "";
		String signature = "";
		if (access_key != null && amount != null && errorCode != null
				&& errorMessage != null && msisdn != null && requestId != null
				&& request_time != null && transId != null && secret != null) {
			urlParameters = "access_key="+access_key+"&amount="+amount+"&errorCode="+errorCode
					+ "&errorMessage="+errorMessage+"&msisdn="+msisdn+"&requestId="+requestId+"&request_time="+request_time+"&transId="+transId;			

			signature = hmacDigest(urlParameters, secret, "HmacSHA256");
			System.out.println("Signature:" + signature);
		}
		return signature;
	}

}

  File form_otp.php


<?php
require_once('function.php');
?>

<form method="post" action="1pay/process_otp.php" id="form">
<input type="hidden" name="requestId" value="<?php echo $transRef;?>"/>



<table width="100%" border="0" cellpadding="3" cellspacing="3">
	<tr>
    	<td colspan="2" align="center">
        	<h2>OTP CHARGING</h2>
        </td>
        
    </tr>
    <tr>
        <td align="right" width="40%">
            Chọn nhà mạng:
        </td>
        <td>
            <select id="telcos" name="telcos">
                    <option value="vtm">Viettel</option>
                    <option value="vms">MobiFone</option>
                    <option value="vnp">VinaPhone</option>
        
                    
                </select>
        </td>
    </tr>
    <tr>
    	<td align="right" width="40%">
        	Chọn giá :
        </td>
        <td>
        	<select id="amount" name="amount">
                    <option value="1000">1000</option>
                    <option value="5000">5000</option>
                    <option value="10000">10000</option>
                    <option value="20000">20000</option>
                    <option value="30000">30000</option>
                    <option value="50000">50000</option>
                    <option value="100000">100000</option>
                    
                </select>
        </td>
    </tr>
    <tr>
    	
    	<td align="right">
        	Số điện thoại :
        </td>
        <td>
        	<input type="text" id="msisdn" name="msisdn" />
        </td>
    </tr>
    <tr><td align="right">
        	Nội dung :
        </td>
        <td>
        	<input type="text" id="content" name="content" />
        </td>
    </tr>
     <tr>
    	<td align="right">
        	
        </td>
        <td>
        	<input type="submit" value="Nạp" />
        </td>
    </tr>
</table>
</form>
   

  File function.php


 <?php
function random_string( $length ) {
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
$size = strlen( $chars );
for( $i = 0; $i < $length; $i++ ) {
$str .= $chars[ rand( 0, $size - 1 ) ];
 }
return $str;
}
$transRef = random_string(10);
?>

  File process_otp.php


<?php
	function execPostRequest($url, $data)
	{
		$ch = curl_init();
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
		curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		$result = curl_exec($ch);
		curl_close($ch);
		return $result;
	}
	$access_key = "";           // product's access key (get value from 1Pay product detail)
	$secret = "";   // product's secret key (get value from 1Pay product detail)
	$msisdn = $_POST['msisdn'];
	$amount = $_POST['amount'];				// >1000
	$content = $_POST['content'];			
	$requestId = $_POST['requestId'];
	$telcos = $_POST['telcos'];                     
	if($telcos == 'vnp'){
		$data = "access_key=" .$access_key. "&amount=" .$amount. "&content=" .$content. "&msisdn=" .$msisdn. "&requestId=" .$requestId;
		$signature = hash_hmac("sha256", $data, $secret);
		$data.= "&signature=" . $signature; //"&backUrl=".$back_url.
		$json_Charging = execPostRequest('http://api.1pay.vn/direct-charging/charge/request', $data);
		$decode_Charging=json_decode($json_Charging,true);  // decode json
		$errorMessage = $decode_Charging["errorMessage"];
		$requestId_back = $decode_Charging["requestId"];
		$transId = $decode_Charging["transId"];
		$errorCode = $decode_Charging["errorCode"];
		$redirect_url = $decode_Charging["redirectUrl"]; 
 header("Location: $redirect_url");  //URL address implement submit request (redirect)
   
	}else{
		$data = "access_key=".$access_key."&amount=".$amount."&content=".$content."&msisdn=".$msisdn."&requestId=".$requestId;
		$signature = hash_hmac("sha256", $data, $secret);
		$data.= "&signature=" . $signature;
	    $json_bankCharging = execPostRequest('http://api.1pay.vn/direct-charging/charge/request', $data);
		$decode_bankCharging=json_decode($json_bankCharging,true);		// decode json
		$errorMessage = $decode_bankCharging["errorMessage"];
	    $requestId_back = $decode_bankCharging["requestId"];
	    $transId = $decode_bankCharging["transId"];
	    $errorCode = $decode_bankCharging["errorCode"];
		$url = "&access_key=".$access_key."&amount=".$amount."&requestId=".$requestId."&transId=".$transId."&telcos=".$telcos;
		$pay_url= "./confirm.php?".$url;
		//echo $pay_url;
		header("Location: $pay_url");
	}
?>

  File otp_vnp_ws.php


  $access_key = $_GET["access_key"];
$msisdn = $_GET['msisdn'];   
$amount = $_GET['amount'];    // >1000 vnd.
$errorCode = $_GET['errorCode'];
$errorMessage = $_GET['errorMessage'];   
$requestId = $_GET['requestId'];
$requestTime = $_GET["request_time"];
$transId = $_GET["transId"];
$sign = $_GET["signature"];
$secret = ""; //product's secret key (get value from 1Pay product detail)
$data = "access_key=$access_key&amount=$amount&errorCode=$errorCode&errorMessage=$errorMessage&msisdn=$msisdn&requestId=$requestId&request_time=$requestTime&transId=$transId";
$signature = hash_hmac("sha256", $data, $secret); 
if($sign == $signature){
	$arResponse['status'] = 1;
	$arResponse['sms'] = "Thanh toan thanh cong";
	$arResponse['type'] = "text";
}else{
	$arResponse['status'] = 0;
	$arResponse['sms'] = "Thanh toan that bai";
	$arResponse['type'] = "text";
}
//Merchant handle SQL
echo json_encode($arResponse);

  File confirm.php


<form action="result_otp.php" method="GET">
<table width="100%" border="0" cellpadding="3" cellspacing="3">
	<tr>
    	<td colspan="2" align="center">
        	<h2>OTP CONFIRM</h2>
        </td>
        
    </tr>
    
    <tr><td width="35%" align="right">
        	OTP :
        </td>
        <td width="65%">
        	<input type="text" id="otp" name="otp" value=""/>
        </td>
    </tr>
     <tr>
    	<td align="right">
        	
        </td>
        <td>
        	<input type="submit" value="Submit" />
        </td>
    </tr>
</table>
<input type="hidden" name="requestId" value="<?php $requestId = isset($_GET["requestId"]) ? $_REQUEST["requestId"] : NULL; echo $requestId; ?>"/>

<input type="hidden" name="transId" value="<?php $transId = isset($_GET["transId"]) ? $_REQUEST["transId"] : NULL;echo $transId;?>"/>

<input type="hidden" name="access_key" value="<?php $access_key = isset($_GET["access_key"]) ? $_REQUEST["access_key"] : NULL;echo $access_key;?>"/>

<input type="hidden" name="amount" value="<?php $amount = isset($_GET["amount"]) ? $_REQUEST["amount"] : NULL;echo $amount;?>"/>
<input type="hidden" name="telcos" value="<?php $amount = isset($_GET["telcos"]) ? $_REQUEST["telcos"] : NULL;echo $telcos;?>"/>

</form>

  File result_otp.php


<?php
		function execPostRequest($url, $data)
		{
			$ch = curl_init();
			curl_setopt($ch, CURLOPT_URL, $url);
			curl_setopt($ch, CURLOPT_POST, 1);
			curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
			curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
			curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			$result = curl_exec($ch);
			curl_close($ch);
			return $result;
		}	
		
		$requestId = isset($_GET["requestId"]) ? $_REQUEST["requestId"] : NULL;
		$transId = isset($_GET["transId"]) ? $_REQUEST["transId"] : NULL;
		$otp = isset($_GET["otp"]) ? $_GET["otp"] : NULL;
		$access_key = isset($_GET["access_key"]) ? $_REQUEST["access_key"] : NULL;
	    $amount = isset($_GET["amount"]) ? $_REQUEST["amount"] : NULL;
	    $telcos = isset($_GET["telcos"]) ? $_REQUEST["telcos"] : NULL;
        $secret = "";               // product's secret key (get value from 1Pay product detail)
		$data = "access_key=".$access_key."&otp=".$otp."&requestId=".$requestId."&transId=".$transId;
	
	$signature = hash_hmac("sha256", $data, $secret);
	$data.= "&signature=" . $signature;
    $json_bankCharging = execPostRequest('http://api.1pay.vn/direct-charging/charge/confirm', $data);
//decode json
	$decode_bankCharging=json_decode($json_bankCharging,true);
	$errorMessage = $decode_bankCharging["errorMessage"];
    $requestId_back = $decode_bankCharging["requestId"];
    $transId = $decode_bankCharging["transId"];
    $errorCode = $decode_bankCharging["errorCode"];
//Merchant handle SQL
?>
  Download 1pay.dll

using System;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using _1Pay;
namespace OTPCharging
{
    public partial class _Default : System.Web.UI.Page
    {
		//request new OTP transaction
        public static string OTPChargeRequest(String amount, String content, String msisdn, String requestId)
        {
            //create signature true with parameters
            String result = "";
			String amount=""; // transaction's amount
			String content=""; // transaction's description
			String msisdn=""; //transaction's phone number, start with "09", "01" or "849", "841"
			String requestId=""; //transaction's id, create by merchant system
            String access_key = "";//fill 1pay accessKey
            string secretKey = ""; //fill 1pay secretKey
            string signature = generateSignature_ApiOtp_RequestCharging(access_key, amount, content, msisdn, requestId, secretKey);
            string url = "http://api.1pay.vn/direct-charging/charge/request";
            String urlParameter = String.Format("access_key={0}&amount={1}&content={2}&msisdn={3}&requestId={4}&signature={5}", access_key, amount, content, msisdn, requestId, signature);
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.KeepAlive = false; request.ProtocolVersion = HttpVersion.Version10; request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded"; request.UserAgent = "Mozilla/5.0";
                WebHeaderCollection headerReader = request.Headers; headerReader.Add("Accept-Language", "en-US,en;q=0.5");
                var data = Encoding.ASCII.GetBytes(urlParameter);
                request.ContentLength = data.Length;
                Stream requestStream = request.GetRequestStream();
                // send url param
                requestStream.Write(data, 0, data.Length);
                requestStream.Close();
                //recive response
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                result = new StreamReader(response.GetResponseStream()).ReadToEnd();
                response.Close();
            }
            catch (Exception ex){//write message log }
            return result;
        }
		
		//get transaction's otp from end user and send to 1pay
        public static string OTPChargeConfirm(String otp, String requestId, String transId)
        {
            //create signature true with parameters
            string result = "";
            String access_key = "";//fill 1pay accessKey
            string secretKey = ""; //fill 1pay secretKey
			string otp =""; //transaction's otp
			string requestId=""; //transaction's id, create by merchant system
			string transId=""; //transaction's id, create by 1pay system
            string signature = generateSignature_ApiOtp_ConfirmCharging(access_key, otp, requestId, transId, secretKey);
            string url = "http://api.1pay.vn/direct-charging/charge/confirm";
            String urlParameter = string.Format("access_key={0}&otp={1}&requestId={2}&transId={3}&signature={4}", access_key, otp, requestId, transId, signature);
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.KeepAlive = false; request.ProtocolVersion = HttpVersion.Version10; request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded"; request.UserAgent = "Mozilla/5.0";
                WebHeaderCollection headerReader = request.Headers; headerReader.Add("Accept-Language", "en-US,en;q=0.5");
                var data = Encoding.ASCII.GetBytes(urlParameter);
                request.ContentLength = data.Length;
                Stream requestStream = request.GetRequestStream();
                // send url param
                requestStream.Write(data, 0, data.Length);
                requestStream.Close();
                //recive response
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                result = new StreamReader(response.GetResponseStream()).ReadToEnd();
                response.Close();
            }
            catch (Exception ex){//write message log }
            return result;
        }
	}
}