thephpleague / omnipay-authorizenet Goto Github PK
View Code? Open in Web Editor NEWAuthorize.Net driver for the Omnipay payment processing library
License: MIT License
Authorize.Net driver for the Omnipay payment processing library
License: MIT License
The function getTransactionId
is defined in the class AbstractResponse
to return null
. It is never overwritten by by the class AIMResponse
. I propose it be overwritten to return the correct value.
Like other payment gateway libraries this library doesn't support createCard
method. Is there support coming, or is it that AuthorizeNet
doesn't support creating a card?
Is there a way (within Omnipay directives) to have Message\AIMResponse
give meaningful error messages based on the return codes?
The reason this is coming us is that for some reason all of their error messages (errorText
) just says The transaction has been declined
but there's an additional errorCode
that gives a clue as to why. The challenge is that all the customer sees when code uses $response->getMessage()
is the decline, not the why. For example, here is their list of most common codes and what it means
https://support.authorize.net/authkb/index?page=content&id=A50
My thought would be to modify and replace/extend the getMessage function such that if a known error code is returned, display a readable message, otherwise, just show the errorText
(and possibly the errorCode
.
Or does this just have to be custom-coded to get the reasonCode
and map it locally outside of Omnipay? (which would mean we'd have to add an additional response translation layer between all omnipay gateways and our code, instead of being able to hot swap em).
Not sure what the design directives would state here.
Is there a way to use any of the additional request properties, such as order line items and shipping address? Those defined here: https://developer.authorize.net/api/reference/#payment-transactions
If not, is this going to be added? Without it, it is very limited functionality.
It would be a good idea to have a method to add generic properties into the request, so we are not limited to what is specifically defined in AIMAbstractRequest
.
EDIT: Nevermind! I see there are CreditCard
and ItemBag
from the main OmniPay package that deal with this.
Installation request for omnipay/authorizenet ~2.5.1 -> satisfiable by omnipay/authorizenet[2.5.1].
- Can only install one of: symfony/http-foundation[v3.4.4, 4.0.x-dev].
- Can only install one of: symfony/http-foundation[v3.4.5, 4.0.x-dev].
- Can only install one of: symfony/http-foundation[v3.4.6, 4.0.x-dev].
- Can only install one of: symfony/http-foundation[v3.4.7, 4.0.x-dev].
- Can only install one of: symfony/http-foundation[v3.4.8, 4.0.x-dev].
- laravel/framework 5.6.x-dev requires symfony/http-foundation ~4.0 -> satisfiable by symfony/http-foundation[v4.0.9, 4.0.x-dev, 4.1.x-dev, 4.2.x-dev, v4.0.0, v4.0.0-BETA1, v4.0.0-BETA2, v4.0.0-BETA3, v4.0.0-BETA4, v4.0.0-RC1, v4.0.0-RC2, v4.0.1, v4.0.2, v4.0.3, v4.0.4, v4.0.5, v4.0.6, v4.0.7, v4.0.8, v4.1.0-BETA1].
The problem is laravel 5.6 require Symfony 4 package . any solution?
It looks like the code is expecting the value to be returned as messages[0]->message[0]->description or errors[0]->error[0]->errorText. When testing it appears as messages[0]->message[0]->text.
Here's a sample response:
SimpleXMLElement {#1025 ▼
+"refId": "0001"
+"messages": SimpleXMLElement {#848 ▼
+"resultCode": "Error"
+"message": SimpleXMLElement {#851 ▼
+"code": "E00007"
+"text": "User authentication failed due to invalid authentication values."
}
}
+"transactionResponse": SimpleXMLElement {#849}
}
I noticed Authorize has a PHP-SDK up on github/packagist. Would it be worth wrapping here?
This new API makes use of JavaScript on the front end to build forms and (presumably) to avoid the need to send credit card numbers to your own server. It is an extension to the DPM API.
An example application is available here:
https://github.com/AuthorizeNet/accept-sample-app
I'm not sure what documentation is available apart from that. Authorize.Net are keen to help us incorporate this API into the gateway, so I'm opening this issue to log any discussions on what that may involve or any ideas or issues that anyone may have.
OmniPay has traditionally not got involved with the front end part of the UI, but most gateways are moving towards a very front-end centric approach (e.g. with "drop-in" forms generated through JavaScript, and card tokenisation APIs that can be used by the front end to avoid card numbers going anywhere near your server). How this fits into OmniPay 2.x or whether it should be something to expand OmniPay 3.0 with, is up for question. I personally don't have an answer for that at this time.
From @WebVida on March 19, 2015 15:18
composer require omnipay/authorizenet:~2.0
Does not pull the latest version? It does not contain the AIMRefundRequest.php file...
Thanks!
Copied from original issue: thephpleague/omnipay#247
This is as a result of issue #30 where the transaction to Authorize.Net was being sent through another device and library, but the notify/callback was being handled by OmniPay. It turns out there are alternative transaction response formats that can be sent in this instance, but which OmniPay does not realise and ends up declaring the transaction as authorised.
To be valid, the first field of the response MUST be "1", "2", "3" or "4". Any other value should raise an immediate exception. A value of "1.0" is the normal response when the transaction was sent via a card reader.
This isn't urgent or something that will affect many people, but when it does, the results can be very misleading, resulting in expired cards being declared as authorised.
Why is there a check to see if the transaction is successful in order to return the transaction reference object.
https://github.com/thephpleague/omnipay-authorizenet/blob/master/src/Message/AIMResponse.php#L120
Whether it's successful or not we should be able to still get that object since it provides valuable information. Right now it returns null which i can't even pull the response code, authcode etc when it fails. i have to to getData()->transactionResponse[0]->...
Thoughts?
Hi, I have this, but when I run it it does not work for me
<?
require_once '../../common/vendor/autoload.php';
use \Omnipay\Omnipay;
$amount = floatval(10);
$currency = 'USD';
$gateway = Omnipay::create('AuthorizeNet_AIM');
$gateway->setApiLoginId('LOGINID');
$gateway->setTransactionKey('TRANSACTIONKEY');
$gateway->setDeveloperMode(true);
try {
$response = $gateway->purchase(
array(
'card' => array(
'number' => 5424000000000015,
'expiryMonth' => 12,
'expiryYear' => 2020,
'code' => 999,
'cardCode' => 999
),
'amount' => $amount,
'currency' => 'USD',
'description' => 'Example',
'transactionId' => '01AD'
)
)->send();
echo $response->getMessage();
} catch (Exception $e) {
print_r($e);
}
The server response is:
The 'AnetApi/xml/v1/schema/AnetApiSchema.xsd:cardCode' element is invalid - The value XX is invalid according to its datatype 'AnetApi/xml/v1/schema/AnetApiSchema.xsd:cardCode' - The Pattern constraint failed.
I appreciate your help!
Edited: judgej code formatting characters.
Hello, I found a bug while implementing this module. All my test cards were passing, even the bad ones.
I found that the isSucessful() method is compared to the getCode() method, which takes the first item in the array--the first item in the array is not a status code, but appears to be a version code.
public function isSuccessful()
{
return '1' === $this->getCode();
}
Here's my array.
AIMResponse {#469 ▼
#request: AIMPurchaseRequestCustom {#465 ▶}
#data: array:22 [▼
0 => "1.0"
1 => "3"
2 => "8"
3 => "The credit card has expired."
4 => ""
5 => "P"
6 => ""
7 => "0"
8 => "116CD77DEE0CE79285A5A6A93E6357CE"
9 => ""
10 => ""
11 => ""
12 => ""
13 => ""
14 => ""
15 => ""
16 => ""
17 => ""
18 => ""
19 => ""
20 => "XXXX1001"
21 => "American Express"
]
}
As you can see, the real status code is in key 1, not in key 0.
I've fixed it locally, but thought you'd like to know.
Thanks.
Are there any plans to support eChecks or bank account transfer processing?
The function getResultCode in the CIMAbstractResponse class (line 59) is doing an array to string conversion which now throws a fatal error in PHP 7.2.
$result should be evaluated before being casted to a string
This is a simple one: the callback URL is set with SIM/DPMAuthorizeRequest::setReturnUrl()
That is historic, AFAIK, and is more appropriately served with setNotifyUrl() now.
This is assuming the URLs are what I think they are:
We can keep the return URL support for legacy users (maybe deprecate it), but support the notify URL as an alternative.
Authorize.Net are in the process of moving their servers. This will involve some downtime on the current live endpoint URLs leading up to October 2015. This one, for example:
https://github.com/thephpleague/omnipay-authorizenet/blob/master/src/AIMGateway.php#L24
'liveEndpoint' => 'https://secure.authorize.net/gateway/transact.dll',
To avoid the downtime, the URL can be changed to this now (from start of July), as this endpoint has already gone through the server migration process:
https://secure2.authorize.net/gateway/transact.dll
Should we change this? Note that the endpoint URL can be set by hand when creating the gateway, so the merchant site can override it to use the secure2
version. However, that would need a merchant site change, while doing so here would be a packageist "hotfix" change.
Obviously needs to be tested on a live site first - I'm happy to do that.
Here's the message from them.
Does this affect the omnipay driver? Will it need updating, or is this something that won't affect functionality and security?
Thanks
I'm currently working on a SilverStripe Omnipay implementation (https://github.com/silverstripe/silverstripe-omnipay) and I'm running into an error with the Authorize.net Omnipay module.
To start, upon testing submissions, I got the following error:
Warning] simplexml_load_string(): namespace warning : xmlns: URI AnetApi/xml/v1/schema/AnetApiSchema.xsd is not absolute
After digging a little, I updated AIMResponse.php
on line 27 with the following:
$xml = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOWARNING);
This got rid of the error but revealed another problem. Here's the value of the $xml variable, which is a SimpleXMLElement Object response from the call to Authorize.net:
SimpleXMLElement Object (
[messages] => SimpleXMLElement Object (
[resultCode] => Error
[message] => SimpleXMLElement Object (
[code] => E00003
[text] => The element 'transactionRequest' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd' has invalid child element 'billTo' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd'. List of possible elements expected: 'cardholderAuthentication, retail, employeeId, transactionSettings, userFields' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd'.
)
)
)
And here is the SimpleXMLElement Object value from the getData() method in AIMAuthorizeRequest.php
:
SimpleXMLElement Object (
[@attributes] => Array (
[xmlns] => AnetApi/xml/v1/schema/AnetApiSchema.xsd
)
[merchantAuthentication] => SimpleXMLElement Object (
[name] => SimpleXMLElement Object ( )
[transactionKey] => SimpleXMLElement Object ( )
)
[refId] => 14-14
[transactionRequest] => SimpleXMLElement Object (
[transactionType] => authCaptureTransaction
[amount] => 125.00
[payment] => SimpleXMLElement Object (
[creditCard] => SimpleXMLElement Object (
[cardNumber] => 4111111111111111
[expirationDate] => 0120
[cardCode] => 123
)
)
[customerIP] => 192.168.0.1
[billTo] => SimpleXMLElement Object (
[firstName] => John
[lastName] => Doe
[company] => SimpleXMLElement Object ( )
[address] => 5555 Main Street
[city] => New York
[state] => New York
[zip] => 10001
[country] => US
)
[shipTo] => SimpleXMLElement Object (
[firstName] => John
[lastName] => Doe
[company] => SimpleXMLElement Object ( )
[address] => 5555 Main Street
[city] => New York
[state] => New York
[zip] => 10001
[country] => US
)
[transactionSettings] => SimpleXMLElement Object (
[setting] => SimpleXMLElement Object (
[settingName] => testRequest
[settingValue] => false
)
)
)
)
Don't see anything out of the ordinary so...I'm confused. Any idea on what could be causing these errors? Thx in advance! :)
PR will follow
The getResultCode is returning a "Trying to get property of non-object" exception because the "responseCode" doesn't exist in the data.
This is happening when entering an incorrect CVV length. So entering in 6 characters for the CVV would cause this to happen.
The description transaction option was not being set in AIMGateway. Created pull request #44
Add support for retail data (deviceType and marketType) to AIMAuthorizeRequest (and subsequently AIMPurchaseRequest). Authorize.Net allows retail data for both authOnlyTransactions and authCaptureTransactions.
Further to #16 where the code change was made to set the x_relay_url from the notifyUrl instead of the returnUrl, a method needs to be in place to set the x_receipt_link_URL which is in effect the returnUrl for the SIM gateway.
This is a non-BC change for anyone who's currently using the returnUrl to set the x_relay_url.
References:
https://support.authorize.net/authkb/index?page=content&id=A587&actp=LIST
x_receipt_link_URL -- set to the URL where the customer should be sent after submitting payment. Parameterized URLs are not permitted.
https://support.authorize.net/authkb/index?page=content&id=A558
What are the plans for supporting omnipay 3.0?
Hi,
I am trying to setup a payment processor using omnipay-authorizenet AuthorizeNet_CIM.
I create the gateway object successfully and can make requests to the sandbox server.
Step 2 is to "create a card" for future use with Token Billing: $gateway->createCard() . This is successful.
From the general Omnipay Token Billing documentation:
createCard($options) - returns a response object which includes a cardReference, which can be used for future transactions.
I don't see a specific 'cardReference' in the above createCard() response object.
So I create a $cardRef array and grab the returned response CustomerProfileId and CustomerPaymentProfileId .
$profileResult['customerProfileId']=$response->getCustomerProfileId();
$profileResult['paymentProfileId']=$response->getCustomerPaymentProfileId();
Step 3 is a function to generate the purchase which fails:
`
function create_transaction($cardRef,$amount,$description,$invoice_number){
global $status, $gateway;
try {
// Send purchase request
$response = $gateway->purchase(
array(
'cardReference' => $cardRef ,
'amount' => $amount,
'currency' => 'USD',
'description' => $_POST['description'],
'transactionId' => $invoice_number
)
)->send();
if ($response->isSuccessful()) {
// Payment was successful
//echo 'Success: '.$response->getMessage();
$status.='Success: '.$response->getMessage();
} elseif ($response->isRedirect()) {
// Redirect to offsite payment gateway
$response->redirect();
} else {
// Payment failed
$status.='Transaction Failure: '.$response->getMessage();
}
} catch (Exception $e) {
$status.='<strong>Error:</strong> '.$e->getMessage(). "<br/>";
}
}
`
The purchase fails and when I look at the Response object it seems the Request is not populating [cardReference] => Omnipay\AuthorizeNet\Model\CardReference Object
(
[customerProfileId:Omnipay\AuthorizeNet\Model\CardReference:private] =>
[paymentProfileId:Omnipay\AuthorizeNet\Model\CardReference:private] =>
[shippingProfileId:Omnipay\AuthorizeNet\Model\CardReference:private] =>
)
I am obviously not passing the correct data to the purchase method.
Any help would be greatly appreciated.
Thanks
Skip
deleting cards does not work when your provide a cardReference string.
In order to fix this, please add these three lines at the top of the getData() method in CIMDeletePaymentProfileRequest.
$cardRef = $this->getCardReference(false);
$this->setCustomerProfileId($cardRef->getCustomerProfileId());
$this->setCustomerPaymentProfileId($cardRef->getPaymentProfileId());
Place these before the call to validate(). This will parse the string and get the customerProfileId and customerPaymentProfileId from the card reference json string.
Can submit a pull request if needed, let me know.
I am trying to make a purchase and creating customer profile using the transaction ID.
https://developer.authorize.net/api/reference/index.html#customer-profiles-create-a-customer-profile-from-a-transaction
I am able to purchase but I have no idea how to create customer profile using the transactionID. It seems possible only when I have a card.
purchase is made using AIM, but I am guessing I have to use CIM at same time for customer profile and transactionID seems the only thing that can bridge both.
Does the authorize.net aspect of Omnipay support Authorize.net's auto-billing / recurring billing features?
This has niggled me for a while, but I could not put my finger on the problem. Just realised today, while writing a test harness, that the SIM/DPM "complete" respons messages just provide the transaction data and the result, but leave the merchant site entirely to decide what to do about that.
In fact, there is just one thing to do: a redirect. For Authorize.Net this redirect is not like the GET/POST methods offered by OmniPay Common. This is a HTML page that needs to be returned, containing a GET URL redirect. The redirect cannot use an auto-submitted POST, as that will generate browser security warnings if the final return page is not SSL (HTTPS).
Keep getting the above error using AIM. Any indicators?
Add support for track data (track1 and track2) to AIMAuthorizeRequest (and subsequently AIMPurchaseRequest). Authorize.Net allows retail data for both authOnlyTransactions and authCaptureTransactions.
The Direct Post Method has been around for a while. It is similar to SIM in functionality and operation, but the credit card form exists on the merchant site and POSTs direct to Authorize.Net.
I have forked and written a driver for this, which we are using in production. It needs some tests before I create a pull request for it, but hopefully it will be useful.
TL;DR:
Charge token,
'cardReference' => json_decode($token),
Got error from omnipay/auth.net code (php didn't throw exception):
"json_decode() expects parameter 1 to be string, array given"
It would be nice if the returned error was a little more appropriate for the cause of the error.
"Card Reference must be this, this or this. You submitted this."
The details:
I am writing code to charge a token through authorize.net. I am storing a previously generated card reference in my database as a json string.
This looks something like this:
{"customerProfileId":"#######","customerPaymentProfileId":"#######"}
When it came time to actually charge it, I decoded it:
$purchaseDetails = [
'amount' => $amount,
'currency' => 'USD',
'cardReference' => json_decode($token),
];
Than actually sending the charge:
try {
$responseFromGateway = $gateway->purchase($purchaseDetails)->send();
} catch (Exception $e) {
return $this->handleErrorReturn($e->getMessage(),$submitData);
}
Ignore submit data, it is a master array I build, handleErrorReturn is just a method I can format errors in a more use friendly output, and log advanced details.
The problem is that I would land in the catch, and the message would be:
"json_decode() expects parameter 1 to be string, array given"
It isn't php blowing up, it's code inside omnipay or the auth.net plug in and because I was just recently decoding something it took me a second to realize my code was ok, that I didn't need to decode the token.
It would be nice if the returned error was a little more appropriate for the cause of the error.
"Card Reference must be this, this or this. You submitted this."
It looks like Authorize.net has support for token billing with a feature called Customer Information Manager (CIM) that allows you to save customer information on their server, and later access it via a token.
Is there plans for Omnipay's token billing methods to support CIM for this gateway?
A helper function similar to getAVSCode
for the cvvResultCode.
Using AuthorizeNet_AIM
and getting this error when trying to process an order via Omnipay
:
Fatal error: Method Guzzle\Http\QueryString::__toString() must not throw an exception in /var/www/mysite/lib/guzzle/guzzle/src/Guzzle/Http/Curl/CurlHandle.php on line 0
Anyone experienced this at all? SIM works no problem..
Authorize.net has been sending us emails saying that they strongly recommend that we update to use their new Akamai SureRoute service. Initially they were saying that after June 30th the old URL's would route automatically to the new service but now they are saying that they aren't going to do that anymore so if you want to use that service, you need to change the URL's that you are sending your messages to. The page they directed us to in order to make the necessary changes is http://www.authorize.net/support/akamaifaqs/.
They are saying that there could be firewall issues that each merchant will need to consider if they are whitelisting IP addresses on outbound connections so if this change is made, you'll probably want to make it an option instead of just changing the URL's.
I'm going out of my mind I guess. The main page for this module says to see the Omnipay documentation on how to use it.
However the documentation for Omnipay is about 1000% useless because it doesn't discuss how to create customer accounts and store the customer credit cards on Authorize.net and then finally to submit the payment using the credit card token. Is any of this possible? If so, where is the documentation or examples?
Please help.
I can not set the following fields using the library in current state:
Billing/Shipping e-mails
invoice number
description.
phone number.
A helper function go get the accountType from the transactionResponse.
Which method should I use to get the transaction ID? I am already getting the authorization code, but don't I need both to settle? Thank you.
So here is a scenario:
a customer submits his credit card info on our form, we authorize and create a profile. at the end of the process he submits the form and we attempt to charge the card. We charge using the 'purchase' method under CIMGateway. The problem is we have the fraud suite enabled for CVV but we have no way of passing in the cardCode when we pass in the cardReference.
Example
$request = $this->getGateway()->purchase(['cardReference' => $cardReference, 'amount' => $amount, 'description' => $this->reservation->description]);
$data = $request->getData();
$data looks like this:
SimpleXMLElement Object
(
[@attributes] => Array
(
[xmlns] => AnetApi/xml/v1/schema/AnetApiSchema.xsd
)
[merchantAuthentication] => SimpleXMLElement Object
(
[name] => xxxx
[transactionKey] => xxxx
)
[transactionRequest] => SimpleXMLElement Object
(
[transactionType] => authCaptureTransaction
[amount] => 327.00
[profile] => SimpleXMLElement Object
(
[customerProfileId] => xxxx
[paymentProfile] => SimpleXMLElement Object
(
[paymentProfileId] => xxxx
)
)
[order] => SimpleXMLElement Object
(
[description] => AVN Reservation: Hard Rock Hotel & Casino Las Vegas for 3 nights (Oct 27, 2016 - Oct 30, 2016)
)
[transactionSettings] => SimpleXMLElement Object
(
[setting] => SimpleXMLElement Object
(
[settingName] => testRequest
[settingValue] => false
)
)
)
)
Based on the documentation we can pass in cardCode as part of the profile->paymentProfile object but i am not sure if this is possible with the way it's currently setup.
This is an issue since it prevents from being able to validate the CVV and requires to turn it off to make the purchase pass.
Any thoughts on this? i can also submit a PR for this.
I am thinking of forking this repository and maintaining it myself if i can't get these changes merged quickly.
Thanks for the help.
SIM and DPM use Complete*
messages for handling the back-channel notifications. There is now a notification handler abstract in OmniPay Common that should be used for this purpose.
Backwards compatibility should be preserved for OmniPay 2.x, but the old messages can be deprecated and removed for 3.0, so it would be good to get it implemented before any 3.0 migration.
Looks like the new "invoiceNumber" parameter gets set in "addBillingData" which is overridden in CIMAuthorizeRequest to do nothing.
Hello,
I am trying to integrate Omnipay into CodeIgniter - I'm a seasoned PHP developer, but I am having some difficulty getting a transaction id from a Purchase or Authorization using the Authorize.net module. If I run the ->getData() method on the response, I get a large array of values, which can be a little overwhelming. Could you tell me which index is the TransactionID or if there is a method defined to get the transaction id from the response?
Thanks,
Kyle
The 'captureOnlyTransaction' is not implemented.
The invoice_num field is used to put the transactionId
into. This stops it being used to hold the invoice number. We should stop using this field in this way.
This would be a BC break for sites that are expecting to see the transaction ID in this field, so this change should be reserved for v3.0
A custom field omnipay_transaction_id
currently takes on this function for the notify handler, though custom fields are not stored in the transaction log on the Authorize.Net account as x_invoice_num
would be. The application can decide how to use that field though, so they can carry on using it this way if they want.
Hello. Thanks for developing this library, I'm using it with great success. However, I would like to be able to pass the customer's email along with the purchase transaction API call (which triggers an automated payment receipt email from Authorize.net to each customer).
I forked the repo and modified AIMAbstractRequest to set $req->customer->email
in the appropriate place. Is this something you're interested in integrating into your library?
I've been calling this a "callback". It's not. It's the notify or notification call. Title changed to show this
SIM uses a callback (they call it a "relay response" to notify the site of the authorisation result. Within this callback is a hash to confirm the callback has legitimately come from Authorize.Net
The hash is coded by the remote gateway using:
1, 2 and 4 are known by both ends in advance. 3 is in the notify POST data (x_trans_id) and is known for the first time by the marchant site in this notify POST. 1, 3 and 4 are sent in the POST data, so those three can be confirmed as not tampered using the shared secret, which is never sent in any POST request.
SIMCompleteAuthorizeRequest() checks the hash using getHash(). Instead of looking at the POST data, it looks entirely at the values supplied by the merchant account. 1 and 2 are fine, but 3 and 4 are not.
The hash check reads $request->getTransactionId() to get the transaction reference. So the merchant site must presumably get x_trans_id from the post data (the reference) and push it into $request->setTransactionId().
This is essentially a mixup between transaction IDs and references.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.