UNPKG

@liuliang520500/pdd-sdk

Version:

拼多多开放平台SDK,支持多多进宝API

255 lines (225 loc) 7.57 kB
var util = require('../pddUtil.js'); var RestClient = require('./network.js'); /** * 拼多多开放平台客户端 * @param {Object} options 配置选项 * @param {String} options.clientId 应用ID(client_id) * @param {String} options.clientSecret 应用密钥(client_secret) * @param {String} [options.accessToken] 访问令牌 * @param {String} [options.apiVersion] API版本号 * @constructor */ function PddClient(options) { if (!(this instanceof PddClient)) { return new PddClient(options); } options = options || {}; if (!options.clientId || !options.clientSecret) { throw new Error('clientId和clientSecret是必须的'); } // 拼多多开放平台网关地址 this.gatewayUrl = 'https://gw-api.pinduoduo.com/api/router'; this.clientId = options.clientId; this.clientSecret = options.clientSecret; this.accessToken = options.accessToken; this.apiVersion = options.apiVersion || 'V1'; this.dataType = 'JSON'; } /** * 执行API调用 * @param {String} type 请求类型,'get'或'post' * @param {String} method 接口方法名,例如:'pdd.goods.list.get' * @param {Object} params 业务参数 * @param {Object} [options] 可选配置参数 * @param {Function} callback 回调函数,接收(err, response) */ PddClient.prototype.invoke = function(type, method, params, options, callback) { if (typeof options === 'function') { callback = options; options = {}; } params.type = method; this.request(type, params, options, function(err, result) { if (err) { return callback(err); } // 获取API响应名称 var responseName = util.getApiResponseName(method); // 解析响应数据 var response = result[responseName]; if (!response) { // 检查是否有错误响应 if (result.error_response) { return callback(result.error_response, result); } // 如果既没有正常响应也没有错误响应,返回原始结果 return callback(null, result); } callback(null, response); }); }; /** * 构建请求参数并执行请求 * @param {String} type 请求类型,'get'或'post' * @param {Object} params 业务参数 * @param {Object} options 请求选项 * @param {Function} callback 回调函数 */ PddClient.prototype.request = function(type, params, options, callback) { var err = util.checkRequired(params, 'type'); if (err) { return callback(err); } // 构建系统参数 var sysParams = { client_id: this.clientId, timestamp: Math.floor(util.getTimeMillis() / 1000).toString(), // 秒级时间戳 data_type: this.dataType, version: this.apiVersion }; // 添加access_token(如果有) if (this.accessToken) { sysParams.access_token = this.accessToken; } // 合并业务参数和系统参数 var allParams = {}; for (var key in params) { // 如果参数是对象或数组,转为JSON字符串 if (typeof params[key] === 'object') { allParams[key] = JSON.stringify(params[key]); } else { allParams[key] = params[key]; } } // 添加系统参数 for (var key in sysParams) { allParams[key] = sysParams[key]; } // 生成签名 allParams.sign = this.sign(allParams); // 创建HTTP请求 var request = null; if (type.toLowerCase() === 'get') { request = RestClient.get(this.gatewayUrl); } else { request = RestClient.post(this.gatewayUrl); } // 设置请求头 request.header('Content-Type', 'application/x-www-form-urlencoded'); // 设置请求参数 for (var key in allParams) { request.field(key, allParams[key]); } // 发送请求 request.end(function(response) { if (response.statusCode === 200) { var data = response.body; callback(null, data); } else { var error = new Error('网络错误'); error.code = response.statusCode; error.data = response.body; callback(error); } }); }; /** * 生成API签名 * @param {Object} params 请求参数 * @return {String} 签名字符串 */ PddClient.prototype.sign = function(params) { // 按键名升序排序 var keys = Object.keys(params).sort(); // 拼接参数字符串 var stringToSign = this.clientSecret; for (var i = 0; i < keys.length; i++) { var key = keys[i]; // 签名不包含sign字段本身 if (key !== 'sign' && params[key] !== undefined && params[key] !== null) { stringToSign += key + params[key]; } } stringToSign += this.clientSecret; // 计算MD5并转为大写 return util.md5(stringToSign).toUpperCase(); }; /** * 执行GET请求 * @param {String} method 接口方法名 * @param {Object} params 业务参数 * @param {Function} callback 回调函数 */ PddClient.prototype.get = function(method, params, callback) { this.invoke('get', method, params, callback); }; /** * 执行POST请求 * @param {String} method 接口方法名 * @param {Object} params 业务参数 * @param {Function} callback 回调函数 */ PddClient.prototype.post = function(method, params, callback) { this.invoke('post', method, params, callback); }; /** * 使用Promise方式执行API调用 * @param {String} method 接口方法名 * @param {Object} params 业务参数 * @param {Object} [options] 可选配置参数 * @return {Promise} Promise对象 */ PddClient.prototype.execute = function(method, params, options) { var self = this; return new Promise(function(resolve, reject) { self.invoke('post', method, params, options, function(err, response) { if (err) { reject(err); } else { resolve(response); } }); }); }; /** * 商品相关API */ PddClient.prototype.goods = { /** * 获取商品列表 * @param {Object} params 请求参数 * @param {Function} callback 回调函数 */ list: function(params, callback) { this.parent.invoke('post', 'pdd.goods.list.get', params, callback); }, /** * 获取商品详情 * @param {Object} params 请求参数 * @param {Function} callback 回调函数 */ detail: function(params, callback) { this.parent.invoke('post', 'pdd.goods.detail.get', params, callback); } }; /** * 推广相关API */ PddClient.prototype.promotion = { /** * 生成商品推广链接 * @param {Object} params 请求参数 * @param {Function} callback 回调函数 */ generateUrl: function(params, callback) { this.parent.invoke('post', 'pdd.ddk.goods.promotion.url.generate', params, callback); } }; // 为子对象设置父引用 Object.defineProperty(PddClient.prototype.goods, 'parent', { value: PddClient.prototype }); Object.defineProperty(PddClient.prototype.promotion, 'parent', { value: PddClient.prototype }); exports.PddClient = PddClient;