Parcourir la source

alipay 第一版

kangna il y a 8 ans
commit
e359cd60b5
5 fichiers modifiés avec 369 ajouts et 0 suppressions
  1. 139 0
      README.md
  2. 129 0
      index.js
  3. 22 0
      package.json
  4. 48 0
      test/app.js
  5. 31 0
      test/index.html

+ 139 - 0
README.md

@@ -0,0 +1,139 @@
+# 支付宝开发文档
+
+## 范围
+本指南用于指导开发者为开发”支付宝接口”项目的过程,通过开发文档达到提高项目的质量,降低维护成本的目的
+
+## 总体要求
+### 总体功能要求
+- 开发者通过支付宝接口文档完成手机版与电脑版的“即时到账”功能
+- 用户可通过访问制定的页面扫描支付宝二维码或登录账号来对商品进行支付并且支付成功
+
+
+### 项目开发要求
+
+- 开发语言
+    -  node
+- 开发工具
+    -  自定
+
+## 项目开发
+
+开发支付宝接口(老版)需要获取几个重要信息才能进行开发
+
+- 待接入应用的
+    -  partner (合作者身份ID)
+    -  sign (交易安全检验码)
+    -  卖家账号或ID
+- 开发工具
+    -  自定
+
+###接口实例
+
+请求参数是商户在与支付宝进行数据交互时,提供给支付宝的请求数据,以便支付宝根据这些数据进一步处理。
+
+####基本参数(不可空参数)
+
+查看蚂蚁金服文档[ https://docs.open.alipay.com/62/104743 ]
+
+在你的项目中引入先把开发参数定义完成
+
+```Javascript
+// app.js
+alipay.config({
+    seller_email: '121889866@qq.com',
+    partner: '2088102565988752',
+    key: 'vrabpv2qbyrz3o6uhby9xtepp12b80xa'
+});
+
+// index.js
+var basicConfig = {
+    alipay_gateway: 'https://mapi.alipay.com/gateway.do?',
+    _input_charset: 'UTF-8',
+    sign_type: 'MD5',
+    service: 'alipay.wap.create.direct.pay.by.user'
+};
+```
+
+参数说明:
+
+- `seller_email` - 签约支付宝账号或卖家收款支付宝帐户
+- `partner` - 合作身份者ID,以2088开头由16位纯数字组成的字符串
+- `key` - 交易安全检验码,由数字和字母组成的32位字符串
+- `alipay_gateway` - 支付宝默认网关
+- `_input_charset` - 字符编码格式
+- `sign_type` - 签名加密方式
+
+## 创建订单
+
+讲订单参数单独分开定义
+
+```Javascript
+var json = {
+    service: 'create_direct_pay_by_user',
+    payment_type: '1',
+    _input_charset: basicConfig._input_charset,
+    notify_url: basicConfig.notify_url,
+    partner: basicConfig.partner,
+    return_url: basicConfig.return_url,
+    seller_email: basicConfig.seller_email
+};
+```
+
+参数说明:
+
+- `body` - 订单描述、订单详细、订单备注,显示在支付宝收银台里的“商品描述”里
+- `out_trade_no` - 你的网站订单系统中的唯一订单号匹配
+- `subject` - 订单名称显示在支付宝收银台里的“商品名称”里,显示在支付宝的交易管理的“商品名称”的列表里。
+- `total_fee` - 订单总金额,显示在支付宝收银台里的“应付总额”里
+- `service` - 支付方式(电脑支付create_direct_pay_by_user 手机支付alipay.wap.create.direct.pay.by.user)
+
+## 参数拼接
+
+### 签名计算
+
+将排序后的参数与其对应值,组合成“参数=参数值”的格式,并且把这些参数用&字符连接起来,此时生成的字符串为待签名字符串。MD5签名的商户需要将key的值拼接在字符串后面,调用MD5算法生成sign;RSA签名的商户将待签名字符串和商户私钥带入SHA1算法中得出sign。以下为示例
+
+项目中引入加密方法
+
+```Javascript
+var crypto = require('crypto');
+var querystring = require('querystring');
+```
+
+先将订单的参数进行拼接之后再进行加密
+
+```Javascript
+var keys = Object.keys(json);
+keys = keys.sort();
+var map = {};
+for (var i = 0; i < keys.length; i++) {
+    var key = keys[i];
+    if (key !== 'sign' && key !== 'sign_type' && json[key]) {
+        map[key] = json[key];
+    }
+}
+var str = querystring.unescape(querystring.stringify(map)) + basicConfig.key;
+console.log(crypto.createHash(basicConfig.sign_type).update(str, basicConfig._input_charset).digest('hex'))
+return crypto.createHash(basicConfig.sign_type).update(str, basicConfig._input_charset).digest('hex');
+```
+
+return 出来的就是进行了MD5加密后的订单字符
+
+##请求URL
+
+签名计算好后就可以进行url拼接
+
+```Javascript
+basicConfig.alipay_gateway + querystring.stringify(json);
+```
+
+返回的值就是可以访问的url
+
+## 结语
+
+至此,我们已经完成了支付宝支付的接入.
+
+本文若有未涵盖到的部分,可参见 `支付宝支付接入` 文档自行查阅所需信息.
+
+作者 [ kangna ]
+2017 年 3月 31日

+ 129 - 0
index.js

@@ -0,0 +1,129 @@
+var https = require('https');
+var crypto = require('crypto');
+var querystring = require('querystring');
+
+/**
+ * alipay_gateway 支付宝默认网关
+ * _input_charset 字符编码格式
+ * sign_type 签名加密方式
+*/
+
+var basicConfig = {
+    alipay_gateway: 'https://mapi.alipay.com/gateway.do?',
+    _input_charset: 'UTF-8',
+    sign_type: 'MD5',
+    service: 'alipay.wap.create.direct.pay.by.user'
+};
+
+/**
+ * https GET 对应的url
+ * @param url  @param url 要请求的url
+ * @returns {Promise}
+ */
+// function httpsGET(url) {
+//     return new Promise(function (resolve, reject) {
+//         var req = https.get(url, function (res) {
+//             res.on('data', function (data) {
+//                 resolve(data);
+//             });
+//         });
+//         req.on('error', function (err) {
+//             reject(err);
+//         });
+//         req.end();
+//     });
+// }
+
+/**
+ * 计算签名
+ * @param json
+ * @returns {string}
+ */
+function buildSign(json) {
+    var keys = Object.keys(json);
+    keys = keys.sort();
+    var map = {};
+    for (var i = 0; i < keys.length; i++) {
+        var key = keys[i];
+        if (key !== 'sign' && key !== 'sign_type' && json[key]) {
+            map[key] = json[key];
+        }
+    }
+    var str = querystring.unescape(querystring.stringify(map)) + basicConfig.key;
+    return crypto.createHash(basicConfig.sign_type).update(str, basicConfig._input_charset).digest('hex');
+}
+
+/**
+ * 配置
+ * @param params
+ * {
+ *  seller_email:签约支付宝账号或卖家收款支付宝帐户
+ *  partner:合作身份者ID,以2088开头由16位纯数字组成的字符串
+ *  key:交易安全检验码,由数字和字母组成的32位字符串
+ *  notify_url:支付宝服务器通知的页面
+ *  return_url:支付后跳转后的页面
+ * }
+ */
+exports.config = function (params) {
+    Object.assign(basicConfig, params);
+};
+
+/**
+ * 使用订单参数构造一个支付请求
+ * @param orderParams 订单参数
+ * {
+ *  body:订单描述、订单详细、订单备注,显示在支付宝收银台里的“商品描述”里
+ *  out_trade_no:你的网站订单系统中的唯一订单号匹配
+ *  subject:订单名称显示在支付宝收银台里的“商品名称”里,显示在支付宝的交易管理的“商品名称”的列表里。
+ *  total_fee:订单总金额,显示在支付宝收银台里的“应付总额”里
+ *  service: 电脑支付create_direct_pay_by_user 手机支付alipay.wap.create.direct.pay.by.user
+ * }
+ * @returns {string} 支付宝支付请求URL 浏览器跳转到该url支付
+ */
+exports.buildDirectPayURL = function (orderParams) {
+    var json = {
+        service: 'create_direct_pay_by_user',
+        payment_type: '1',
+        _input_charset: basicConfig._input_charset,
+        notify_url: basicConfig.notify_url,
+        partner: basicConfig.partner,
+        return_url: basicConfig.return_url,
+        seller_email: basicConfig.seller_email
+    };
+    Object.assign(json, orderParams);
+    //加入签名结果与签名方式
+    json.sign = buildSign(json);
+    json.sign_type = basicConfig.sign_type;
+    return basicConfig.alipay_gateway + querystring.stringify(json);
+};
+
+/**
+ * 验证来自支付宝的通知是否合法
+ * @param params 来自支付宝的通知参数
+ * @returns {Promise} 验证通过时resolve,失败时reject
+ */
+// exports.verify = function (params) {
+//     return new Promise(function (resolve, reject) {
+//         var paramsSign = params.sign;
+//         var realSign = buildSign(params);
+//         if (paramsSign === realSign) {
+//             var url = basicConfig.alipay_gateway +
+//                 querystring.stringify({
+//                     service: 'notify_verify',
+//                     partner: basicConfig.partner,
+//                     notify_id: params['notify_id']
+//                 });
+//             httpsGET(url).then(function (data) {
+//                 if (data.toString() === 'true') {
+//                     resolve(true);
+//                 } else {
+//                     reject('来自alipay接口的结果为:验证结果不合法');
+//                 }
+//             }).catch(function (err) {
+//                 reject('请求alipay接口发生网络错误:' + JSON.stringify(err))
+//             });
+//         } else {
+//             reject('sign验证不相等: ' + paramsSign + ' !== ' + realSign);
+//         }
+//     });
+// };

+ 22 - 0
package.json

@@ -0,0 +1,22 @@
+{
+  "name": "cloudsql-alipay",
+  "version": "1.0.0",
+  "description": "alipay",
+  "main": "index.js",
+  "directories": {
+    "test": "test"
+  },
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "repository": {
+    "type": "git",
+    "url": "http://git.1473.cn/kangna/cloudsql-alipay.git"
+  },
+  "author": "kangna",
+  "license": "ISC",
+  "dependencies": {
+    "body-parser": "^1.18.2",
+    "express": "^4.16.3"
+  }
+}

+ 48 - 0
test/app.js

@@ -0,0 +1,48 @@
+var express = require('express');
+var bodyParser = require('body-parser');
+var alipay = require('../index');
+var app = express();
+
+/**
+ * seller_email 支付宝账号
+ * partner 合作者id
+ * key 支付安全签名
+ * return_url 支付成功返回页面
+ */
+alipay.config({
+    seller_email: '121889866@qq.com',
+    partner: '2088102565988752',
+    key: 'vrabpv2qbyrz3o6uhby9xtepp12b80xa',
+    // return_url: 'http://127.0.0.1:3000/return'
+});
+
+// index.html
+app.get('/', function (req, res) {
+    res.sendFile(__dirname + '/index.html');
+});
+
+app.use(bodyParser.urlencoded({ extended: false }));
+app.post('/', function (req, res) {
+    var params = req.body;
+    // 业务侧需要为每个订单生成一个唯一订单号
+    params.out_trade_no = Date.now().toString() + Math.random();
+    var url = alipay.buildDirectPayURL(params);
+    res.redirect(url);
+});
+
+// app.get('/return', function (req, res) {
+//     var params = req.query;
+//     alipay.verify(params, function (err, result) {
+//         if (err) {
+//             console.error(err);
+//         } else {
+//             if (result === true) {
+//                 res.reply('支付成功');
+//                 //该通知是来自支付宝的合法通知
+//             }
+//         }
+//     });
+//     res.end('');
+// });
+
+app.listen(3000);

+ 31 - 0
test/index.html

@@ -0,0 +1,31 @@
+<html>
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+    <title>支付宝即时到帐接口</title>
+</head>
+<style type="text/css">
+	.paybtn {
+		width: 100px;
+		border: 1px solid #000000;
+		text-align: center;
+		padding: 10px;
+		float: left;
+		margin: 10px;
+		cursor: pointer;
+	}
+	.paybtn:active {
+		border: 2px solid #000000;
+	}
+</style>
+<body>
+<form action="/" method="post">
+    <input type="text" name="subject" placeholder="标题"/>
+    <input type="text" name="body" placeholder="备注">
+    <input type="text" name="total_fee" placeholder="付款金额"/>
+    <input type="submit" value="确认付款">
+</form>
+<h2>选择支付方式</h2>
+<div class="paybtn">支付宝</div>
+<div class="paybtn">微信</div>
+</body>
+</html>