ping++ 支付


一.最近要開發支付,考慮到以后接入的支付類型比較多,如常用的,微信,支付寶,銀聯,以及后期需要接入qq,京東,易寶支付等。為了以后統一管理支付,就考慮使用ping++ 支付,提供了統一的支付接口。

    下面我介紹下,利用ping++ 接入支付寶的支付功能。

二.請求服務器 支付接口 orderpay.

    1.配置:ping++ api key ,appId,webhooksParse

    2.在ping++ 官網 找到 rsa private key ,官網提供的是rsc pacs#1 ,這里需要轉成 pkcs8,我是利用在線的一個網站轉換 : http://tool.chacuo.net/cryptrsapkcs1pkcs8

    3.創建charge對象,這里着重要說明的是 獲取客戶端ip,這也是官網demo 未強調的點,對於不了解代理請求轉發的小伙伴來說,這里又會遇到大坑,項目不上線 不知道,一上線支付就調用不起來,根源就在

    x-forwarded-for  獲取客戶端IP這里。給一個地址介紹下x-forwarded-for :http://www.360doc.com/content/12/0409/15/1073512_202198496.shtml,他最終結果是將所有的代理過的ip地址全拼接在一起,而我        們需要的是最開始發起支付請求的客戶端IP。下面是代碼部分:

    

 1 public String orderpay(){
 2           //live   LIVE_API_BASE = "https://api.pingxx.com";
 3            //Pingpp.overrideApiBase(PingppTestData.getApiBase());
 4          Pingpp.apiKey = Cont.API_KEY_LIVE;
 5          // 建議使用 PKCS8 編碼的私鑰,可以用 openssl 將 PKCS1 轉成 PKCS8
 6          //Pingpp.privateKey = PingppTestData.getPKCS8PrivateKey();
 7          
 8         // Pingpp.DEBUG = true; 
 9          //PKCS8,建議使用 PKCS8 編碼的私鑰,可以用 openssl 將 PKCS1 轉成 PKCS8 
10          Pingpp.privateKey = "-----BEGIN PRIVATE KEY-----\n"+
12                     "此處填入pkcs8 私鑰\n"+
13                     "-----END PRIVATE KEY-----\n";
14          
15          //私鑰
16          //Pingpp.privateKeyPath = ApiCommonAction.class.getClassLoader().getResource("res").getPath()+"/pingpp_private_key.pem";18          String paramObj = getRequest().getParameter("paramObj");
19          if(!StringUtil.isEmpty(paramObj)){
20              if(new JsonParser().parse(paramObj).isJsonObject()){
21                  JsonObject jsonobj = new JsonParser().parse(paramObj).getAsJsonObject();23                  String amount = jsonobj.get("price").getAsString();
24                  //此處支付時,需將價格 轉成 以分為單位
25                    //int price = (int) (Double.valueOf(amount) * 100);// 支付時  100 代表 1塊。
26                    int price = (int) (Double.valueOf(amount) * 100);// 支付時  100 代表 1塊。
27                    String order_no = jsonobj.get("orderNo").getAsString();
28                    String orderId = jsonobj.get("orderId").getAsString();
29                    String payType = jsonobj.get("paytype").getAsString();
30                    
31                    String channel = "";
32                    //支付寶
33                    if(!StringUtil.isEmpty(payType) && "1".equals(payType)){
34                        channel = "alipay";
35                        
36                    }else if(!StringUtil.isEmpty(payType) && "2".equals(payType)){//微信
37                        channel = "wx";
38                    }else{
39                        setJsonString(AppJSON.errReq("支付類型不能為空!"));
40                        return "ajax";
41                    }
42                    
43                    String remoteAddr = getRequest().getRemoteAddr();45                    
46                    String ip = getRequest().getHeader("x-forwarded-for");
47                  if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
48                      ip = getRequest().getHeader("Proxy-Client-IP");
49                  }
50                  if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
51                      ip = getRequest().getHeader("WL-Proxy-Client-IP");
52                  }
53                  if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
54                      ip = getRequest().getRemoteAddr();
55                  }
56                  
57                  if(!StringUtil.isEmpty(ip)){
58                       String[] iparr = ip.trim().split(",");
59                       ip = iparr[0];
60                  }
61                  
62                    System.out.println("客戶端++  ip="+ip);
63                    
64                    //String client_ip = "127.0.0.1";//host.substring(0,host.indexOf(":"));
65                    String client_ip = ip;
66                    
67                    //subject 和 body 參數用來在用戶付款、以及在第三方支付軟件的賬單顯示。從訂單表中獲取
68                    String subject = "預定服務";
69                    String body = "支付訂單費用";
70                    
71                    Charge charge = this.createCharge(orderId,price,order_no,channel,client_ip, subject, body);
72                    if(charge!=null){
73                        System.out.println("========ping++ chargeId=  "+charge.getId());
74                        // 傳到客戶端請先轉成字符串 .toString(), 調該方法,會自動轉成正確的 JSON 字符串
75                        
76                        //以"X"結尾,則標識需求訂單,
77                        if(order_no.endsWith("X")){
78                          //業務處理82                        
}else{ 83 //業務處理87
}
88 String chargeString = charge.toString(); 89 90 setJsonString(AppJSON.succReq("請求成功", chargeString)); 91 } 92 } 93 94 }else{ 95 setJsonString(AppJSON.errParas("支付 paramObj不能為空"));return "ajax"; 96 } 97 98 return "ajax"; 99 }

三.創建支付對象 charge

   1.指定 支付使用的appid

   2.調用 charge對象的create 方法,創建支付對象。

 1 public Charge createCharge(String orderId,int price,String orderNo,String channel,String clent_ip,String subject,String body){
 2         //String appId = PingppTestData.getAppID();
 3         String appId = Cont.API_ID;
 5         Charge charge = null;
 6         Map<String, Object> chargeMap = new HashMap<String, Object>();
 7         chargeMap.put("amount", price);//訂單總金額, 人民幣單位:分(如訂單總金額為 1 元,此處請填 100)
 8         chargeMap.put("currency", "cny");
 9         chargeMap.put("subject", subject);
10         chargeMap.put("body", body);
11         chargeMap.put("order_no", orderNo);// 推薦使用 8-20 位,要求數字或字母,不允許其他字符
12         chargeMap.put("channel", channel);// 支付使用的第三方支付渠道取值,請參考:https://www.pingxx.com/api#api-c-new
13         
14         Calendar cal = Calendar.getInstance();  
15         cal.add(Calendar.MINUTE, 5);//5分鍾失效  
16         long timestamp = cal.getTimeInMillis()/ 1000L;  
17         chargeMap.put("time_expire", timestamp);
18         Timer timer = new Timer();
19         //發起一個定時任務,半小時后自動觸發,取消訂單流程
20        //以"X"結尾,則標識需求訂單,
21         if(orderNo.endsWith("X")){
22             //需求訂單
23             timer.schedule(new DemandlobbyNoPayCancel(Long.valueOf(orderId)), 1000 * 60 * 5);
24         }else{
25             //普通訂單
26             timer.schedule(new OrderNoPayCancel(Long.valueOf(orderId)), 1000 * 60 * 5);
27         }
28         
29         chargeMap.put("client_ip", clent_ip); // 發起支付請求客戶端的 IP 地址,格式為 IPV4,如: 127.0.0.1
30         Map<String, String> app = new HashMap<String, String>();
31         app.put("id", appId);
32         chargeMap.put("app", app);
33 
34         Map<String, Object> extra = new HashMap<String, Object>();
35 //            extra.put("success_url", "http://127.0.0.1/succeeded");
36         chargeMap.put("extra", extra);
37         try {
38             // 發起 charge 創建請求
39             charge = Charge.create(chargeMap);
40 
41         } catch (APIConnectionException e) {
42             e.printStackTrace();
43         } catch (ChannelException e) {
44             e.printStackTrace();
45         } catch (RateLimitException e) {
46             e.printStackTrace();
47         } catch (AuthenticationException e) {
48             e.printStackTrace();
49         } catch (APIException e) {
50             e.printStackTrace();
51         } catch (InvalidRequestException e) {
52             e.printStackTrace();
53         }
54 
55         return charge;
56     }

四.支付回調方法

   1.回調地址,是在ping++ 官網配置,官網提供 test 和 live 兩版本,開發過程先用test 做回調地址配置,測通后,項目正式上線改成live模式.

   2.回調地址進行業務處理,回調方法獲取event type類型,是支付成功,還是退款成功或者紅包發送成功..... 具體可參考 ping++ 開發api: https://www.pingxx.com/api#events-事件

   3.貼出我的回調處理方法代碼,這里主要會發生的簽名驗簽的錯誤,那么遇到這種情況,你還是要核對下,是否直接使用了ping++的私鑰 並沒有轉成 pkcs8 加密方式,或者直接拷入了ping++的公鑰....

 1 public String webhooksParseCharge(){
 2           HttpServletRequest request  = getRequest();
 3           HttpServletResponse response = getResponse();
 4         try {
 5             request.setCharacterEncoding("UTF8");
 6         } catch (UnsupportedEncodingException e1) {
 7             e1.printStackTrace();
 8         }  
 9         //獲取頭部所有信息  
10         Enumeration<String> headerNames = request.getHeaderNames();  
11         String signature=null;  
12         while (headerNames.hasMoreElements()) {  
13             String key = (String) headerNames.nextElement();  
14             String value = request.getHeader(key);  
15             if("x-pingplusplus-signature".equals(key)){  
16                 signature=value;  
17             }  
18         }  
19  
20         // 獲得 http body 內容  
21        StringBuffer eventJson=new StringBuffer();  
22        BufferedReader reader= null;  
23         try {  
24             reader = request.getReader();  
25             do{  
26                 eventJson.append(reader.readLine());  
27             }while(reader.read()!=-1);  
28             reader.close();  
29         } catch (IOException e) {  
30             e.printStackTrace();  
31         }  
32         
33         JSONObject event=JSONObject.fromObject(eventJson.toString()); 
34         System.out.println("=========event=========== "+event);
35         boolean verifyRS=false;  
36         try {  
37             PublicKey publicKey = WebhooksVerifyService.getPubKey();  
38             System.out.println("============公鑰============"+publicKey);  
39             verifyRS = WebhooksVerifyService.verifyData(eventJson.toString(),signature,publicKey);  
40             System.out.println("============== 是否簽名驗證成功! "+ verifyRS);
41             //verifyRS = true;
42         } catch (Exception e) {  
43             e.printStackTrace();  
44         }  
45    
46         if(verifyRS) {  
47             // charge.succeeded    支付對象,支付成功時觸發。
48             // refund.succeeded    退款對象,退款成功時觸發。
49             if ("charge.succeeded".equals(event.get("type"))) {  
50                 JSONObject data = JSONObject.fromObject(event.get("data").toString());  
51                 JSONObject object = JSONObject.fromObject(data.get("object").toString()); 
52                 
53                 String channel = (String) object.get("channel");  
54                 String payType = null;  
55                 int amountFen = (int) object.get("amount");  
56                 //交易流水號
57                 String transaction_no = object.get("transaction_no")+"";
58                         
59                 Double amountYuan = amountFen * 1.0 / 100;//ping++扣款,精確到分,而數據庫精確到元  
60                 Double weiXinInput = null;  
61                 Double aliPayInput = null;  
62                 Double bankCardInput = null;  
63                 
64                 if ("wx".equals(channel)) {  
65                     payType = "2";//支付類型(1:支付寶2微信)  
66                     weiXinInput = amountYuan;  
67                 } else if ("alipay".equals(channel)) {  
68                     payType = "1";  
69                     aliPayInput = amountYuan;  
70                 } 
71                 
72                 String orderNo = (String) object.get("order_no");                  
73                 // 支付成功業務處理
74             }else if("refund.succeeded".equals(event.get("type"))){//退款事件
75                 // 退款業務處理
76                 
77             }  
78             
79         }else{  
80             System.out.println("簽名驗證失敗");
81             setJsonString(AppJSON.errReq("簽名驗證失敗!"));
82         }  
83           
84           return "ajax";
85       }

五. 關於ping++ 支付先介紹到這里,后期有先關支付類技術 我會逐步跟進,如此文大家有什么問題,請留言聯系我,很樂意解決大家的問題。

     另外鄭重說明 本篇文章是個人原創,如需轉載請標注原文地址。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM