WyWallet WyWallet sms payment api version


Appendix A 5.1Hash description



Download 405.9 Kb.
Page6/6
Date05.01.2017
Size405.9 Kb.
#7131
1   2   3   4   5   6

5Appendix A




5.1Hash description


Returns only the first half of the generated Hash. This is to make brute force attack harder.

It’s easier to guess the MAC key for a single request, but harder to know if this is the correct key since many keys can generate the first half of the output.


5.1.1SHA1 Hash .Net


public static String GetMAC(String generatedString)

{

Encoding enc = Encoding.UTF8;



Byte[] rawMessage = enc.GetBytes(generatedString);
SHA1 sha1 = new SHA1CryptoServiceProvider();
Byte[] result = sha1.ComputeHash(rawMessage);

string mac = Convert.ToBase64String(result);


//split the string in 2 and return the first half

mac = mac.Substring(0, mac.Length / 2);


return mac;

}


5.1.2SHA1 Hash – JAVA



public class Sha1Hash {

/** Creates a new instance of Sha1Hash */



public Sha1Hash() {

}
/**

     * @param inputData

     * @return

     */

public String getHashedValue(String inputData) {

String sResp = null;

try {

byte byteHash[];



MessageDigest sha1 = MessageDigest.getInstance("SHA-1");

sha1.update(inputData.getBytes("utf-8"));

byteHash = sha1.digest();

sha1.reset();


// see code snippet below..



String hash = Base64Util.encode(byteHash);

return hash.substring(0, (hash.length()/2));

} catch (Exception e) {



System.err.println("getHashedValue failed: " + e.getMessage());

return null;

}

}



private String toHexString(byte[] array) {

StringBuilder sb = new StringBuilder ();



for (int i=0; i< array.length; i++) {

String hex = "0"+Integer.toHexString(array[i]);

String end = hex.substring(hex.length()-2);

sb.append(end.toUpperCase());

}

System.err.println("HASH:"+sb.toString());

return sb.toString();

}


}

/**


 * Freeware from:

 * Roedy Green

 * Canadian Mind Products

 * #208 - 525 Ninth Street

 * New Westminster, BC Canada V3M 5T9

 * tel: (604) 777-1804

 * mailto:roedy@mindprod.com

 */
/**

 * Encode arbitrary binary into printable ASCII using BASE64 encoding.

 * very loosely based on the Base64 Reader by

 * Dr. Mark Thornton

 * Optrak Distribution Software Ltd.

 * http://www.optrak.co.uk

 * and Kevin Kelley's

 *http://www.ruralnet.net/~kelley/java/Base64.java

 */
public class Base64Util

{
/**

     * how we separate lines, e.g. \n, \r\n, \r etc.

     **/

static String lineSeparator = System.getProperty( "line.separator");
/**

     * max chars per line. A multiple of 4.

     **/

private static int lineLength = 72;

/**


     * determines how long the lines are that are generated by encode.

     * Ignored by decode.

     * @param length 0 means no newlines inserted.

     */


public static void setLineLength(int length)

{

lineLength = length;



}
/**

     * letter of the alphabet used to encode binary values 0..63

     **/

static final char[] valueToChar = new char[64];

/**


     * binary value encoded by a given letter of the alphabet 0..63

     **/



static final int[] charToValue = new int[256];

/**


     * Marker value for chars we just ignore, e.g. \n \r high ascii

     */


static final int IGNORE = -1;
/**

     * Marker for = trailing pad

     */

static final int PAD = -2;

static

{

// build translate valueToChar table only once.



// 0..25 -> 'A'..'Z'

for ( int i=0; i<=25; i++ )

valueToChar[i] = (char)('A'+i);

// 26..51 -> 'a'..'z'

for ( int i=0; i<=25; i++ )

valueToChar[i+26] = (char)('a'+i);

// 52..61 -> '0'..'9'

for ( int i=0; i<=9; i++ )

valueToChar[i+52] = (char)('0'+i);

valueToChar[62] = '+';

valueToChar[63] = '/';


// build translate charToValue table only once.

for ( int i=0; i<256; i++ )

{

charToValue[i] = IGNORE; // default is to ignore



}
for ( int i=0; i<64; i++ )

{

charToValue[valueToChar[i]] = i;



}
charToValue['='] = PAD;

}
/**

     * Encode an arbitrary array of bytes as Base64 printable ASCII.

     * It will be broken into lines of 72 chars each. The last line

     * is not

     * terminated with a line separator.

     */

public static String encode(byte[] b)

{

// Each group or partial group of 3 bytes becomes four chars



int outputLength = ((b.length + 2) / 3) * 4;
// account for embedded newlines

outputLength += (outputLength / lineLength) *

lineSeparator.length();
// must be local for recursion to work.

StringBuffer sb = new StringBuffer( outputLength );
// must be local for recursion to work.

int linePos = 0;


// first deal with even multiples of 3 bytes.

int len = (b.length / 3) * 3;

int leftover = b.length - len;

for ( int i=0; i

{

// Start a new line if next 4 chars won't fit on the current line



// We don't encapsulate so that linePos and sb will work recursively

{
linePos += 4;



if ( linePos > lineLength )

{

linePos = 0;



if ( lineLength != 0) {sb.append(lineSeparator);}

}

}


// get next three bytes in unsigned form lined up,

// in big-endian order

int combined = b[i+0] & 0xff;

combined <<= 8;

combined |= b[i+1] & 0xff;

combined <<= 8;

combined |= b[i+2] & 0xff;
// break those 24 bits into a 4 groups of 6 bits,

// working LSB to MSB.

int c3 = combined & 0x3f;

combined >>>= 6;

int c2 = combined & 0x3f;

combined >>>= 6;

int c1 = combined & 0x3f;

combined >>>= 6;

int c0 = combined & 0x3f;
// Translate into the equivalent alpha character

// emitting them in big-endian order.

sb.append( valueToChar[c0]);

sb.append( valueToChar[c1]);

sb.append( valueToChar[c2]);

sb.append( valueToChar[c3]);

}
// deal with leftover bytes

switch ( leftover )

{

case 0:



default:

// nothing to do



break;
case 1:

// One leftover byte generates xx==

// Start a new line if next 4 chars won't fit on the current line

// We don't encapsulate so that linePos and sb will work recursively

{
linePos += 4;

if ( linePos > lineLength )

{

linePos = 0;



if ( lineLength != 0) {sb.append(lineSeparator);}

}

}



// Handle this recursively with a faked complete triple.

// Throw away last two chars and replace with ==

sb.append(encode(new byte[] {b[len], 0, 0}

).substring(0,2));

sb.append("==");

break;
case 2:

// Two leftover bytes generates xxx=

// Start a new line if next 4 chars won't fit on the current line

// We don't encapsulate so that linePos and sb will work recursively

{

linePos += 4;



if ( linePos > lineLength )

{

linePos = 0;



if ( lineLength != 0) {sb.append(lineSeparator);}

}

}



// Handle this recursively with a faked complete triple.

// Throw away last char and replace with =

sb.append(encode(new byte[] {b[len], b[len+1], 0}

).substring(0,3));

sb.append("=");

break;
} // end switch;
if ( outputLength != sb.length() ) System.out.println("oops");
return sb.toString();

}// end encode

}

5.2Postback service examples

5.2.1Java JSP postback


<%@page import="org.w3c.dom.*,javax.xml.xpath.*,javax.xml.parsers.*,java.io.IOException,org.xml.sax.SAXException" %>

<%@page import="javax.servlet.ServletInputStream,javax.servlet.http.HttpServletRequest"%>

<%@page import="java.io.BufferedReader,java.io.InputStreamReader"%>

<%@page import="java.io.*" %>

<%@page import="org.xml.sax.InputSource" %>

<%

try


{

DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();

domFactory.setNamespaceAware(true);

DocumentBuilder builder = domFactory.newDocumentBuilder();

//Load the XML document in the parser

Document doc = builder.parse(new InputSource(newStringReader(request.getParameter("PostbackRequestWrapper"))));

XPath xpath = XPathFactory.newInstance().newXPath();

// XPath Query for showing all nodes value

XPathExpression expr;

//Set the filter to find the elements

//Header parameters

expr = xpath.compile("//PostbackRequestWrapper/Header/AcquirerID/text()");



String AcquirerID = (String) expr.evaluate(doc, XPathConstants.STRING);

expr = xpath.compile("//PostbackRequestWrapper/Header/AgreementID/text()");



String AgreementID = (String) expr.evaluate(doc, XPathConstants.STRING);

expr = xpath.compile("//PostbackRequestWrapper/Header/MerchantID/text()");



String MerchantID = (String) expr.evaluate(doc, XPathConstants.STRING);

expr = xpath.compile("//PostbackRequestWrapper/Header/TransmissionTime/text()");



String TransmissionTime = (String) expr.evaluate(doc, XPathConstants.STRING);

expr = xpath.compile("//PostbackRequestWrapper/Header/ClientIP/text()");



String ClientIP = (String) expr.evaluate(doc, XPathConstants.STRING);

expr = xpath.compile("//PostbackRequestWrapper/Header/PostbackURL/text()");



String PostbackURL = (String) expr.evaluate(doc, XPathConstants.STRING);

//PostbackRequest parameters

expr = xpath.compile("//PostbackRequestWrapper/PostbackRequest/Operation/text()");

String Operation = (String) expr.evaluate(doc, XPathConstants.STRING);

expr = xpath.compile("//PostbackRequestWrapper/PostbackRequest/Amount/text()");



String Amount = (String) expr.evaluate(doc, XPathConstants.STRING);

expr = xpath.compile("//PostbackRequestWrapper/PostbackRequest/BatchID/text()");



String BatchID = (String) expr.evaluate(doc, XPathConstants.STRING);

expr = xpath.compile("//PostbackRequestWrapper/PostbackRequest/OrderID/text()");



String OrderID = (String) expr.evaluate(doc, XPathConstants.STRING);

expr = xpath.compile("//PostbackRequestWrapper/PostbackRequest/TransactionID/text()");



String TransactionID = (String) expr.evaluate(doc, XPathConstants.STRING);

//Status parameters

expr = xpath.compile("//PostbackRequestWrapper/Status/TransactionStatus/text()");

String TransactionStatus = (String) expr.evaluate(doc, XPathConstants.STRING);

expr = xpath.compile("//PostbackRequestWrapper/Status/TransactionStatusDesc/text()");



String TransactionStatusDesc = (String) expr.evaluate(doc, XPathConstants.STRING);

expr = xpath.compile("//PostbackRequestWrapper/Status/OperationStatus/text()");



String OperationStatus = (String) expr.evaluate(doc, XPathConstants.STRING);

expr = xpath.compile("//PostbackRequestWrapper/Status/OperationStatusDesc/text()");



String OperationStatusDesc = (String) expr.evaluate(doc, XPathConstants.STRING);
expr = xpath.compile("//PostbackRequestWrapper/Footer/MAC/text()");

String MAC = (String) expr.evaluate(doc, XPathConstants.STRING);

}

catch (Exception e) {



throw e;

}

%>


5.2.2ASP.net postback service

// Read the incoming HTTPS stream

StreamReader reader = new StreamReader(Request.InputStream, Encoding.Default);

if (!reader.EndOfStream)

{

string xmlString = reader.ReadToEnd();



xmlString = HttpUtility.UrlDecode(xmlString.Replace("PostbackRequestWrapper=", ""));

XmlDocument xmlDoc = new XmlDocument();

xmlDoc.LoadXml(xmlString);
// Create a Hashtable to store values

Hashtable values = new Hashtable();

values.Add("AcquirerID", xmlDoc.GetElementsByTagName("AcquirerID").Item(0).FirstChild.InnerText);

values.Add("AgreementID", xmlDoc.GetElementsByTagName("AgreementID").Item(0).FirstChild.InnerText);

values.Add("MerchantID", xmlDoc.GetElementsByTagName("MerchantID").Item(0).FirstChild.InnerText);

values.Add("TransmissionTime",xmlDoc.GetElementsByTagName("TransmissionTime").Item(0).FirstChild.InnerText);

values.Add("ClientIP", xmlDoc.GetElementsByTagName("ClientIP").Item(0).FirstChild.InnerText);

values.Add("PostbackURL", xmlDoc.GetElementsByTagName("PostbackURL").Item(0).FirstChild.InnerText);

values.Add("PostbackRequest",xmlDoc.GetElementsByTagName("PostbackRequest").Item(0).FirstChild.InnerText);

values.Add("Operation", xmlDoc.GetElementsByTagName("Operation").Item(0).FirstChild.InnerText);

values.Add("Amount", xmlDoc.GetElementsByTagName("Amount").Item(0).FirstChild.InnerText);

values.Add("BatchID", xmlDoc.GetElementsByTagName("BatchID").Item(0).FirstChild.InnerText);

values.Add("OrderID", xmlDoc.GetElementsByTagName("OrderID").Item(0).FirstChild.InnerText);

values.Add("TransactionID", xmlDoc.GetElementsByTagName("TransactionID").Item(0).FirstChild.InnerText);

values.Add("TransactionStatus", xmlDoc.GetElementsByTagName("TransactionStatus").Item(0).FirstChild.InnerText);

values.Add("TransactionStatusDesc",xmlDoc.GetElementsByTagName("TransactionStatusDesc").Item(0).FirstChild.InnerText);

values.Add("OperationStatus", xmlDoc.GetElementsByTagName("OperationStatus").Item(0).FirstChild.InnerText);

values.Add("OperationStatusDesc", xmlDoc.GetElementsByTagName("OperationStatusDesc").Item(0).FirstChild.InnerText);

values.Add("MAC", xmlDoc.GetElementsByTagName("MAC").Item(0).FirstChild.InnerText);

}

6Appendix C: Simulator for API development

The API provides a simulator returning predefined transaction status codes depending on input parameters in the request. Developers using the API can use this simulator to force errors and test error handling in their application. The WSDL (service description) is identical to the actual API to be used in production. The simulator tries to emulate the behavior of the real service by maintaining a transaction history of the last 200 transactions and return an appropriate response code, but does not guarantee 100% compatibility.

6.1URL

URL for MAP PaymentService simulator:

https://mpaymenttest.payex.com/MAP/PaymentServiceTest?wsdl


6.2Valid request parameters




Parameter

Value

Remarks

AquirerID

WyWallet




AgreementID

One of 99990095, 99990096 or 99990097




ClientType

MSISDN




ClientID

004699999nnn

nnn is a number in the range 000…999.

Other values will return transaction status 6 (Account not found)



MAC




Shared secret = map123

6.3Response codes


The API will return a non-zero transaction status or timeout for the following combinations of Operation and ClientID:


Operation

ClientID

/MSISDN

Transaction status

Remarks

CheckOrder

0046999994nn

nn

nn = 01..20

CheckOrder

004699999499

Timeout

Takes 1 minute to complete

Purchase

0046999995nn

nn

nn = 01..20

ClientID is fetched from original Purchase transaction



Purchase

004699999599

Timeout

Takes 1 minute to complete

nn = 01..20

ClientID is fetched from original Purchase


Reversal

0046999996nn

nn

nn = 01..20

Reversal

004699999699

Timeout

Takes 1 minute to complete

nn = 01..20



Credit

0046999997nn

nn

nn = 01..20

Credit

004699999799

Timeout

Takes 1 minute to complete




6.4Frequently asked questions


Question

Answer

I have problems calculating the MAC Key for my request.

The most common problem is that there are missing parameters in the concatenated string.
Please see our source code examples for examples on how to generate the MAC. If you are using another programming language or still have problems you can try and use our Online MAC generator to get help and compare your calculations with a verified source.
https://shop.wywallet.se/mac-generator.aspx

Why do I get the error code 3 “Agreement not found”?

Most probably this is due to the fact that the payment request is sent to the wrong payment system / URL. Please see section for relevant systems and URL:s
If you still get the same error code after confirming that the correct system is used it could be a misconfiguration in our system. Please contact merchant support for further assistance.


I’ve submitted my PostbackURL in the payment request but I’ve waited and there is no HTTP POST to my URL.

Most merchant accounts are configured to be synchronous where you receive the payment status immediately and postbacks aren’t used. If you have a synchronous account you can ignore to set the PostbackURL parameter in your request.
If you have service with high performance requirements (e.g. TV & event votings) you should ask WyWallet merchant support (re)configure your account to asynchronous.
If you have an asynchronous account and you don’t receive and callbacks please check that you have entered a HTTPS url (we only allow postbacks via SSL port 443 due to security restrictions) and that your firewall accepts incoming traffic on this IP & port.

Is there a time limit for requesting a reversal on a transaction?

There are no technical time limit implemented and reversals are always accepted as long as the end user still has a WyWallet account.

Do you provide mobile short codes or SMS services?

No, WyWallet is a dedicated payment service and only handle the actual payment. Short codes and SMS services can either be ordered via each MNO/Operator or by using a SMS aggregator. If you don’t have



6.5Merchant support


For questions regarding the integration please contact our helpdesk merchant-support@wywallet.se



2017-01-05 WyWallet SMS Payment API v0.4 Page ()




Download 405.9 Kb.

Share with your friends:
1   2   3   4   5   6




The database is protected by copyright ©ininet.org 2024
send message

    Main page