ping_pay.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. (function(){
  2. var
  3. version = "2.0.6",
  4. hasOwn = {}.hasOwnProperty,
  5. PingppSDK = function(){},
  6. cfg = {
  7. PINGPP_NOTIFY_URL: 'https://api.pingxx.com/notify/charges/',
  8. UPACP_WAP_URL: 'https://gateway.95516.com/gateway/api/frontTransReq.do',
  9. ALIPAY_WAP_URL: 'http://wappaygw.alipay.com/service/rest.htm',
  10. UPMP_WAP_URL: 'uppay://uppayservice/?style=token&paydata=',
  11. JDPAY_WAP_URL: 'https://m.jdpay.com/wepay/web/pay',
  12. BFB_SUCCESS: '<html><head><meta name="VIP_BFB_PAYMENT" content="BAIFUBAO"></head><body></body></html>',
  13. YEEPAY_WAP_URL: 'https://ok.yeepay.com/paymobile/api/pay/request',
  14. YEEPAY_WAP_TEST_URL: 'http://mobiletest.yeepay.com/paymobile/api/pay/request',
  15. PINGPP_MOCK_URL: 'http://sissi.pingxx.com/mock.php'
  16. },
  17. channels = {
  18. alipay_wap: 'alipay_wap',
  19. upmp_wap: 'upmp_wap',
  20. upacp_wap: 'upacp_wap',
  21. bfb_wap: 'bfb_wap',
  22. wx_pub: 'wx_pub',
  23. yeepay_wap: 'yeepay_wap',
  24. jdpay_wap: 'jdpay_wap'
  25. };
  26. PingppSDK.prototype = {
  27. version: version,
  28. _resultCallback: undefined,
  29. _jsApiParameters: {},
  30. _debug: false,
  31. _signature: undefined,
  32. createPayment: function(charge_json, callback, signature, debug) {
  33. if (typeof callback == "function") {
  34. this._resultCallback = callback;
  35. }
  36. if (typeof signature != "undefined") {
  37. this._signature = signature;
  38. }
  39. if (typeof debug == "boolean") {
  40. this._debug = debug;
  41. }
  42. var charge;
  43. if(typeof charge_json == "string"){
  44. try{
  45. charge = JSON.parse(charge_json);
  46. }catch(err){
  47. this._innerCallback("fail", this._error("json_decode_fail"));
  48. return;
  49. }
  50. }else{
  51. charge = charge_json;
  52. }
  53. if(typeof charge == "undefined"){
  54. this._innerCallback("fail", this._error("json_decode_fail"));
  55. return;
  56. }
  57. if(!hasOwn.call(charge, 'id')){
  58. this._innerCallback("fail", this._error("invalid_charge", "no_charge_id"));
  59. return;
  60. }
  61. if(!hasOwn.call(charge, 'channel')){
  62. this._innerCallback("fail", this._error("invalid_charge", "no_channel"));
  63. return;
  64. }
  65. var channel = charge['channel'];
  66. if(!hasOwn.call(charge, 'credential')){
  67. this._innerCallback("fail", this._error("invalid_charge", "no_credential"));
  68. return;
  69. }
  70. if (!charge['credential']) {
  71. this._innerCallback("fail", this._error("invalid_credential", "credential_is_undefined"));
  72. return;
  73. }
  74. if (!hasOwn.call(channels, channel)) {
  75. this._innerCallback("fail", this._error("invalid_charge", "no_such_channel:" + channel));
  76. return;
  77. }
  78. if (!hasOwn.call(charge['credential'], channel)) {
  79. this._innerCallback("fail", this._error("invalid_credential", "no_valid_channel_credential"));
  80. return;
  81. }
  82. if(!hasOwn.call(charge, 'livemode')){
  83. this._innerCallback("fail", this._error("invalid_charge", "no_livemode"));
  84. return;
  85. }
  86. if (charge['livemode'] == false) {
  87. this._testModeNotify(charge);
  88. return;
  89. }
  90. var credential = charge['credential'][channel];
  91. if (channel == channels.upmp_wap) { // 调起银联支付控件,客户端需要安装银联支付控件才能调起
  92. location.href = cfg.UPMP_WAP_URL + credential['paydata'];
  93. } else if (channel == channels.upacp_wap) {
  94. form_submit(cfg.UPACP_WAP_URL, 'post', credential);
  95. } else if (channel == channels.alipay_wap) { // 调起支付宝手机网页支付
  96. credential['_input_charset'] = 'utf-8';
  97. if (typeof _AP != "undefined") {
  98. var query = stringify_data(credential, channel, true);
  99. _AP.pay(cfg.ALIPAY_WAP_URL + "?" + query);
  100. } else {
  101. form_submit(cfg.ALIPAY_WAP_URL, 'get', credential);
  102. }
  103. } else if (channel == channels.bfb_wap) {
  104. if (!hasOwn.call(credential, 'url')) {
  105. this._innerCallback("fail", this._error("invalid_credential", "missing_field:url"));
  106. return;
  107. }
  108. location.href = credential['url'] + '?' + stringify_data(credential, channel);
  109. } else if (channel == channels.yeepay_wap) {
  110. var fields = ["merchantaccount", "encryptkey", "data"];
  111. for(var k in fields){
  112. if(typeof fields[k] !== "function" && !hasOwn.call(credential, fields[k])){
  113. this._innerCallback("fail", this._error("invalid_credential", "missing_field_"+fields[k]));
  114. return;
  115. }
  116. }
  117. if (hasOwn.call(credential, "mode") && credential["mode"] == "test") {
  118. location.href = cfg.YEEPAY_WAP_TEST_URL + '?' + stringify_data(credential, channel, true);
  119. } else {
  120. location.href = cfg.YEEPAY_WAP_URL + '?' + stringify_data(credential, channel, true);
  121. }
  122. } else if (channel == channels.wx_pub) {
  123. var fields = ["appId", "timeStamp", "nonceStr", "package", "signType", "paySign"];
  124. for (var k in fields) {
  125. if (typeof fields[k] !== "function" && !hasOwn.call(credential, fields[k])) {
  126. this._innerCallback("fail", this._error("invalid_credential", "missing_field_"+fields[k]));
  127. return;
  128. }
  129. }
  130. this._jsApiParameters = credential;
  131. this._callpay();
  132. } else if (channel == channels.jdpay_wap) {
  133. form_submit(cfg.JDPAY_WAP_URL, 'post', credential);
  134. }
  135. },
  136. _jsApiCall: function(){
  137. var self = this;
  138. if(self._jsApiParameters != {}){
  139. WeixinJSBridge.invoke(
  140. 'getBrandWCPayRequest',
  141. self._jsApiParameters,
  142. function(res){
  143. if(res.err_msg == 'get_brand_wcpay_request:ok'){
  144. self._innerCallback("success");
  145. }else if(res.err_msg == 'get_brand_wcpay_request:cancel'){
  146. self._innerCallback("cancel");
  147. }else{
  148. self._innerCallback("fail", self._error("wx_result_fail", res.err_msg));
  149. }
  150. }
  151. );
  152. }
  153. },
  154. _callpay: function(){
  155. var self = this;
  156. if (typeof wx != "undefined" && typeof self._signature != "undefined") {
  157. var wxConfigFailed = false;
  158. wx.config({
  159. debug: self._debug,
  160. appId: self._jsApiParameters["appId"],
  161. timestamp: self._jsApiParameters["timeStamp"],
  162. nonceStr: self._jsApiParameters["nonceStr"],
  163. signature: self._signature,
  164. jsApiList: ['chooseWXPay']
  165. });
  166. wx.ready(function(){
  167. if (wxConfigFailed) {
  168. return;
  169. }
  170. wx.chooseWXPay({
  171. timestamp: self._jsApiParameters["timeStamp"],
  172. nonceStr: self._jsApiParameters["nonceStr"],
  173. "package": self._jsApiParameters["package"],
  174. signType: self._jsApiParameters["signType"],
  175. paySign: self._jsApiParameters["paySign"],
  176. success: function(res) {
  177. if (res.errMsg == "chooseWXPay:ok") {
  178. self._innerCallback("success");
  179. } else {
  180. self._innerCallback("fail", self._error("wx_result_fail", res.errMsg));
  181. }
  182. },
  183. cancel: function(res) {
  184. self._innerCallback("cancel");
  185. },
  186. fail: function(res) {
  187. self._innerCallback("fail", self._error("wx_result_fail", res.errMsg));
  188. }
  189. });
  190. });
  191. wx.error(function(res){
  192. wxConfigFailed = true;
  193. self._innerCallback("fail", self._error("wx_config_error", res.errMsg));
  194. });
  195. } else if (typeof WeixinJSBridge == "undefined") {
  196. function eventCallback(){
  197. self._jsApiCall();
  198. }
  199. if (document.addEventListener) {
  200. document.addEventListener('WeixinJSBridgeReady', eventCallback, false);
  201. } else if(document.attachEvent) {
  202. document.attachEvent('WeixinJSBridgeReady', eventCallback);
  203. document.attachEvent('onWeixinJSBridgeReady', eventCallback);
  204. }
  205. }else{
  206. this._jsApiCall();
  207. }
  208. },
  209. _error: function(msg, extra) {
  210. msg = (typeof msg == "undefined") ? "" : msg;
  211. extra = (typeof extra == "undefined") ? "" : extra;
  212. return {
  213. msg:msg,
  214. extra:extra
  215. };
  216. },
  217. _innerCallback: function(result, err) {
  218. if (typeof this._resultCallback == "function") {
  219. if (typeof err == "undefined") {
  220. err = this._error();
  221. }
  222. this._resultCallback(result, err);
  223. }
  224. },
  225. _testModeNotify: function(charge) {
  226. var self = this;
  227. if (charge['channel'] == channels.wx_pub) {
  228. var dopay = confirm("模拟付款?");
  229. if (dopay) {
  230. var request = new XMLHttpRequest();
  231. request.open('GET', cfg.PINGPP_NOTIFY_URL+charge['id']+'?livemode=false', true);
  232. request.onload = function() {
  233. if (request.status >= 200 && request.status < 400 && request.responseText == "success"){
  234. self._innerCallback("success");
  235. } else {
  236. var extra = 'http_code:'+request.status+';response:'+request.responseText;
  237. self._innerCallback("fail", self._error("testmode_notify_fail", extra));
  238. }
  239. };
  240. request.onerror = function() {
  241. self._innerCallback("fail", self._error("network_err"));
  242. };
  243. request.send();
  244. } else {
  245. self._innerCallback("cancel");
  246. }
  247. } else {
  248. var params = {
  249. 'ch_id': charge['id'],
  250. 'scheme': 'http',
  251. 'channel': charge['channel']
  252. };
  253. if (hasOwn.call(charge, 'order_no')) {
  254. params['order_no'] = charge['order_no'];
  255. }
  256. if (hasOwn.call(charge, 'extra')) {
  257. params['extra'] = encodeURIComponent(JSON.stringify(charge['extra']));
  258. }
  259. location.href = cfg.PINGPP_MOCK_URL+'?'+stringify_data(params);
  260. }
  261. }
  262. };
  263. function form_submit(url, method, params) {
  264. var form = document.createElement("form");
  265. form.setAttribute("method", method);
  266. form.setAttribute("action", url);
  267. for (var key in params) {
  268. if (hasOwn.call(params, key)) {
  269. var hiddenField = document.createElement("input");
  270. hiddenField.setAttribute("type", "hidden");
  271. hiddenField.setAttribute("name", key);
  272. hiddenField.setAttribute("value", params[key]);
  273. form.appendChild(hiddenField);
  274. }
  275. }
  276. document.body.appendChild(form);
  277. form.submit();
  278. }
  279. function stringify_data(data, channel, urlencode) {
  280. if (typeof urlencode == "undefined") {
  281. urlencode = false;
  282. }
  283. var output = [];
  284. for (var i in data) {
  285. if (channel == "bfb_wap" && i == "url") {
  286. continue;
  287. }
  288. if (channel == "yeepay_wap" && i == "mode") {
  289. continue;
  290. }
  291. output.push(i + '=' + (urlencode ? encodeURIComponent(data[i]) : data[i]));
  292. }
  293. return output.join('&');
  294. }
  295. PingppSDK.prototype.payment = PingppSDK.prototype.createPayment;
  296. window.pingpp = new PingppSDK();
  297. // aliases
  298. window.PINGPP_PAY_SDK = window.PINGPP_WX_PUB = window.pingpp;
  299. })();