细谈软件支付功能的实现----菜鸟日记

   

互联网的时代,毕竟是金钱money时代,很多网站都与支付宝,微信支付,捆绑银联支付接口,当然银联,支付宝公司也会收服务费,存钱到银行,或者办信用卡都收年费,服务费。

  除了开发网站之外,还要开发软件,免费软件没有生意,只有做共享软件,哪些编程语言如何绑定支付接口呢。

Java程序绑定微信支付

Java通过JsApi方式实现微信支付

 

要使用JsApi进行微信支付,首先要从微信获得一个prepay_id,然后通过调用微信的jsapi完成支付,JS API的返回结果get_brand_wcpay_request:ok仅在用户成功完成支付时返回。由于前端交互复杂,get_brand_wcpay_request:cancel或者get_brand_wcpay_request:fail可以统一处理为用户遇到错误或者主动放弃,不必细化区分。
示例代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
function onBridgeReady(){
  WeixinJSBridge.invoke(
    'getBrandWCPayRequest', {
      "appId":"wx2421b1c4370ec43b",  //公众号名称,由商户传入  
      "timeStamp":" 1395712654",    //时间戳,自1970年以来的秒数  
      "nonceStr":"e61463f8efa94090b1f366cccfbbb444",//随机串  
      "package":"u802345jgfjsdfgsdg888",  
      "signType":"MD5",    //微信签名方式:  
      "paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89"//微信签名
    },
    function(res){  
      if(res.err_msg =="get_brand_wcpay_request:ok") {}  // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回  ok,但并不保证它绝对可靠。
    }
  );
}
if(typeof WeixinJSBridge =="undefined"){
  if( document.addEventListener ){
    document.addEventListener('WeixinJSBridgeReady', onBridgeReady,false);
  }elseif(document.attachEvent){
    document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
    document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
  }
}else{
  onBridgeReady();
}

以上传入的参数package,即为prepay_id

下面讲的是获得参数来调用jsapi
我们调用JSAPI时,必须获得用户的openid,(trade_type=JSAPI,openid为必填参数。)
首先定义一个请求的对象:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
packagecom.unstoppedable.protocol;
 
 
 
importcom.unstoppedable.common.Configure;
importcom.unstoppedable.common.HttpService;
importcom.unstoppedable.common.RandomStringGenerator;
importcom.unstoppedable.common.Signature;
 
importjava.lang.reflect.Field;
importjava.util.HashMap;
importjava.util.Map;
 
 
publicclassUnifiedOrderReqData {
 
  privateString appid;
  privateString mch_id;
  privateString device_info;
  privateString nonce_str;
  privateString sign;
  privateString body;
  privateString detail;
  privateString attach;
  privateString out_trade_no;
  privateString fee_type;
  privateinttotal_fee;
  privateString spbill_create_ip;
  privateString time_start;
  privateString time_expire;
  privateString goods_tag;
  privateString notify_url;
  privateString trade_type;
  privateString product_id;
  privateString limit_pay;
  privateString openid;
 
  privateUnifiedOrderReqData(UnifiedOrderReqDataBuilder builder) {
    this.appid = builder.appid;
    this.mch_id = builder.mch_id;
    this.device_info = builder.device_info;
    this.nonce_str = RandomStringGenerator.getRandomStringByLength(32);
    this.body = builder.body;
    this.detail = builder.detail;
    this.attach = builder.attach;
    this.out_trade_no = builder.out_trade_no;
    this.fee_type = builder.fee_type;
    this.total_fee = builder.total_fee;
    this.spbill_create_ip = builder.spbill_create_ip;
    this.time_start = builder.time_start;
    this.time_expire = builder.time_expire;
    this.goods_tag = builder.goods_tag;
    this.notify_url = builder.notify_url;
    this.trade_type = builder.trade_type;
    this.product_id = builder.product_id;
    this.limit_pay = builder.limit_pay;
    this.openid = builder.openid;
    this.sign = Signature.getSign(toMap());
  }
 
 
  publicvoidsetAppid(String appid) {
    this.appid = appid;
  }
 
  publicvoidsetMch_id(String mch_id) {
    this.mch_id = mch_id;
  }
 
  publicvoidsetDevice_info(String device_info) {
    this.device_info = device_info;
  }
 
  publicvoidsetNonce_str(String nonce_str) {
    this.nonce_str = nonce_str;
  }
 
  publicvoidsetSign(String sign) {
    this.sign = sign;
  }
 
  publicvoidsetBody(String body) {
    this.body = body;
  }
 
  publicvoidsetDetail(String detail) {
    this.detail = detail;
  }
 
  publicvoidsetAttach(String attach) {
    this.attach = attach;
  }
 
  publicvoidsetOut_trade_no(String out_trade_no) {
    this.out_trade_no = out_trade_no;
  }
 
  publicvoidsetFee_type(String fee_type) {
    this.fee_type = fee_type;
  }
 
  publicvoidsetTotal_fee(inttotal_fee) {
    this.total_fee = total_fee;
  }
 
  publicvoidsetSpbill_create_ip(String spbill_create_ip) {
    this.spbill_create_ip = spbill_create_ip;
  }
 
  publicvoidsetTime_start(String time_start) {
    this.time_start = time_start;
  }
 
  publicvoidsetTime_expire(String time_expire) {
    this.time_expire = time_expire;
  }
 
  publicvoidsetGoods_tag(String goods_tag) {
    this.goods_tag = goods_tag;
  }
 
  publicvoidsetNotify_url(String notify_url) {
    this.notify_url = notify_url;
  }
 
  publicvoidsetTrade_type(String trade_type) {
    this.trade_type = trade_type;
  }
 
  publicvoidsetProduct_id(String product_id) {
    this.product_id = product_id;
  }
 
  publicvoidsetLimit_pay(String limit_pay) {
    this.limit_pay = limit_pay;
  }
 
  publicvoidsetOpenid(String openid) {
    this.openid = openid;
  }
 
  publicMap<String, Object> toMap() {
    Map<String, Object> map =newHashMap<String, Object>();
    Field[] fields =this.getClass().getDeclaredFields();
    for(Field field : fields) {
      Object obj;
      try{
        obj = field.get(this);
        if(obj !=null) {
          map.put(field.getName(), obj);
        }
      }catch(IllegalArgumentException e) {
        e.printStackTrace();
      }catch(IllegalAccessException e) {
        e.printStackTrace();
      }
    }
    returnmap;
  }
 
 
  publicstaticclassUnifiedOrderReqDataBuilder {
    privateString appid;
    privateString mch_id;
    privateString device_info;
    privateString body;
    privateString detail;
    privateString attach;
    privateString out_trade_no;
    privateString fee_type;
    privateinttotal_fee;
    privateString spbill_create_ip;
    privateString time_start;
    privateString time_expire;
    privateString goods_tag;
    privateString notify_url;
    privateString trade_type;
    privateString product_id;
    privateString limit_pay;
    privateString openid;
 
    publicUnifiedOrderReqDataBuilder(String appid, String mch_id, String body, String out_trade_no, Integer total_fee,
                     String spbill_create_ip, String notify_url, String trade_type) {
      if(appid ==null) {
        thrownewIllegalArgumentException("传入参数appid不能为null");
      }
      if(mch_id ==null) {
        thrownewIllegalArgumentException("传入参数mch_id不能为null");
      }
      if(body ==null) {
        thrownewIllegalArgumentException("传入参数body不能为null");
      }
      if(out_trade_no ==null) {
        thrownewIllegalArgumentException("传入参数out_trade_no不能为null");
      }
      if(total_fee ==null) {
        thrownewIllegalArgumentException("传入参数total_fee不能为null");
      }
      if(spbill_create_ip ==null) {
        thrownewIllegalArgumentException("传入参数spbill_create_ip不能为null");
      }
      if(notify_url ==null) {
        thrownewIllegalArgumentException("传入参数notify_url不能为null");
      }
      if(trade_type ==null) {
        thrownewIllegalArgumentException("传入参数trade_type不能为null");
      }
      this.appid = appid;
      this.mch_id = mch_id;
      this.body = body;
      this.out_trade_no = out_trade_no;
      this.total_fee = total_fee;
      this.spbill_create_ip = spbill_create_ip;
      this.notify_url = notify_url;
      this.trade_type = trade_type;
    }
 
    publicUnifiedOrderReqDataBuilder setDevice_info(String device_info) {
      this.device_info = device_info;
      returnthis;
    }
 
    publicUnifiedOrderReqDataBuilder setDetail(String detail) {
      this.detail = detail;
      returnthis;
    }
 
    publicUnifiedOrderReqDataBuilder setAttach(String attach) {
      this.attach = attach;
      returnthis;
    }
 
    publicUnifiedOrderReqDataBuilder setFee_type(String fee_type) {
      this.fee_type = fee_type;
      returnthis;
    }
 
    publicUnifiedOrderReqDataBuilder setTime_start(String time_start) {
      this.time_start = time_start;
      returnthis;
    }
 
    publicUnifiedOrderReqDataBuilder setTime_expire(String time_expire) {
      this.time_expire = time_expire;
      returnthis;
    }
 
    publicUnifiedOrderReqDataBuilder setGoods_tag(String goods_tag) {
      this.goods_tag = goods_tag;
      returnthis;
    }
 
    publicUnifiedOrderReqDataBuilder setProduct_id(String product_id) {
      this.product_id = product_id;
      returnthis;
    }
 
    publicUnifiedOrderReqDataBuilder setLimit_pay(String limit_pay) {
      this.limit_pay = limit_pay;
      returnthis;
    }
 
    publicUnifiedOrderReqDataBuilder setOpenid(String openid) {
      this.openid = openid;
      returnthis;
    }
 
 
    publicUnifiedOrderReqData build() {
 
      if("JSAPI".equals(this.trade_type) &&this.openid ==null) {
        thrownewIllegalArgumentException("当传入trade_type为JSAPI时,openid为必填参数");
      }
      if("NATIVE".equals(this.trade_type) &&this.product_id ==null) {
        thrownewIllegalArgumentException("当传入trade_type为NATIVE时,product_id为必填参数");
      }
      returnnewUnifiedOrderReqData(this);
    }
  }
 
 
 
}

因为有些参数为必填,有些参数为选填。而且sign要等所有参数传入之后才能计算的出,所以这里用了builder模式。关于builder模式。

我们选用httpclient进行网络传输。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
packagecom.unstoppedable.common;
 
importcom.thoughtworks.xstream.XStream;
importcom.thoughtworks.xstream.io.xml.DomDriver;
importcom.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
importorg.apache.commons.logging.Log;
importorg.apache.commons.logging.LogFactory;
importorg.apache.http.HttpEntity;
importorg.apache.http.HttpResponse;
importorg.apache.http.client.ClientProtocolException;
importorg.apache.http.client.ResponseHandler;
importorg.apache.http.client.config.RequestConfig;
importorg.apache.http.client.methods.HttpGet;
importorg.apache.http.client.methods.HttpPost;
importorg.apache.http.conn.ConnectTimeoutException;
importorg.apache.http.conn.ConnectionPoolTimeoutException;
importorg.apache.http.conn.ssl.SSLConnectionSocketFactory;
importorg.apache.http.conn.ssl.SSLContexts;
importorg.apache.http.entity.StringEntity;
importorg.apache.http.impl.client.CloseableHttpClient;
importorg.apache.http.impl.client.HttpClients;
importorg.apache.http.util.EntityUtils;
 
importjavax.net.ssl.SSLContext;
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.IOException;
importjava.net.SocketTimeoutException;
importjava.security.KeyStore;
 
/**
 * Created by hupeng on 2015/7/28.
 */
publicclassHttpService {
  privatestaticLog logger = LogFactory.getLog(HttpService.class);
 
  privatestaticCloseableHttpClient httpClient = buildHttpClient();
 
  //连接超时时间,默认10秒
  privatestaticintsocketTimeout =5000;
 
  //传输超时时间,默认30秒
  privatestaticintconnectTimeout =5000;
 
  privatestaticintrequestTimeout =5000;
 
  publicstaticCloseableHttpClient buildHttpClient() {
 
    try{
      KeyStore keyStore = KeyStore.getInstance("PKCS12");
      FileInputStream instream =newFileInputStream(newFile(Configure.getCertLocalPath()));//加载本地的证书进行https加密传输
      try{
        keyStore.load(instream, Configure.getCertPassword().toCharArray());//设置证书密码
      }finally{
        instream.close();
      }
 
 
      // Trust own CA and all self-signed certs
      SSLContext sslcontext = SSLContexts.custom()
          .loadKeyMaterial(keyStore, Configure.getCertPassword().toCharArray())
          .build();
      // Allow TLSv1 protocol only
      SSLConnectionSocketFactory sslsf =newSSLConnectionSocketFactory(
          sslcontext,
          newString[]{"TLSv1"},
          null,
          SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
 
      RequestConfig requestConfig = RequestConfig.custom()
          .setConnectTimeout(connectTimeout)
          .setConnectionRequestTimeout(requestTimeout)
          .setSocketTimeout(socketTimeout).build();
 
      httpClient = HttpClients.custom()
          .setDefaultRequestConfig(requestConfig)
          .setSSLSocketFactory(sslsf)
          .build();
 
      returnhttpClient;
    }catch(Exception e) {
      thrownewRuntimeException("error create httpclient......", e);
    }
  }
 
 
 
  publicstaticString doGet(String requestUrl)throwsException {
    HttpGet httpget =newHttpGet(requestUrl);
    try{
 
 
      logger.debug("Executing request "+ httpget.getRequestLine());
      // Create a custom response handler
      ResponseHandler<String> responseHandler =newResponseHandler<String>() {
 
        @Override
        publicString handleResponse(
            finalHttpResponse response)throwsClientProtocolException, IOException {
          intstatus = response.getStatusLine().getStatusCode();
          if(status >=200&& status <300) {
            HttpEntity entity = response.getEntity();
            returnentity !=null? EntityUtils.toString(entity) :null;
          }else{
            thrownewClientProtocolException("Unexpected response status: "+ status);
          }
        }
 
      };
 
      returnhttpClient.execute(httpget, responseHandler);
    }finally{
      httpget.releaseConnection();
    }
  }
 
  publicstaticString doPost(String url, Object object2Xml) {
 
    String result =null;
 
    HttpPost httpPost =newHttpPost(url);
 
    //解决XStream对出现双下划线的bug
    XStream xStreamForRequestPostData =newXStream(newDomDriver("UTF-8",newXmlFriendlyNameCoder("-_","_")));
 
    //将要提交给API的数据对象转换成XML格式数据Post给API
    String postDataXML = xStreamForRequestPostData.toXML(object2Xml);
 
    logger.info("API,POST过去的数据是:");
    logger.info(postDataXML);
 
    //得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别
    StringEntity postEntity =newStringEntity(postDataXML,"UTF-8");
    httpPost.addHeader("Content-Type","text/xml");
    httpPost.setEntity(postEntity);
 
    //设置请求器的配置
 
    logger.info("executing request"+ httpPost.getRequestLine());
 
    try{
      HttpResponse response = httpClient.execute(httpPost);
 
      HttpEntity entity = response.getEntity();
 
      result = EntityUtils.toString(entity,"UTF-8");
 
    }catch(ConnectionPoolTimeoutException e) {
      logger.error("http get throw ConnectionPoolTimeoutException(wait time out)", e);
 
    }catch(ConnectTimeoutException e) {
      logger.error("http get throw ConnectTimeoutException", e);
 
    }catch(SocketTimeoutException e) {
      logger.error("http get throw SocketTimeoutException", e);
 
    }catch(Exception e) {
      logger.error("http get throw Exception", e);
 
    }finally{
      httpPost.abort();
    }
 
    returnresult;
  }
}

然后是我们的总入口:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
packagecom.unstoppedable.service;
 
importcom.unstoppedable.common.Configure;
importcom.unstoppedable.common.HttpService;
importcom.unstoppedable.common.XMLParser;
importcom.unstoppedable.protocol.UnifiedOrderReqData;
importorg.xml.sax.SAXException;
 
importjavax.xml.parsers.ParserConfigurationException;
importjava.io.IOException;
importjava.util.Map;
 
/**
 * Created by hupeng on 2015/7/28.
 */
publicclassWxPayApi {
 
  publicstaticMap<String,Object> UnifiedOrder(UnifiedOrderReqData reqData)throwsIOException, SAXException, ParserConfigurationException {
    String res = HttpService.doPost(Configure.UNIFIED_ORDER_API, reqData);
    returnXMLParser.getMapFromXML(res);
  }
 
  publicstaticvoidmain(String[] args)throwsException {
    UnifiedOrderReqData reqData =newUnifiedOrderReqData.UnifiedOrderReqDataBuilder("appid","mch_id","body","out_trade_no",1,"spbill_create_ip","notify_url","JSAPI").setOpenid("openid").build();
    System.out.println(UnifiedOrder(reqData));
 
 
  }
}

返回的xml为:

?
1
2
3
4
5
6
7
8
9
10
11
<xml>
  <return_code><![CDATA[SUCCESS]]></return_code>
  <return_msg><![CDATA[OK]]></return_msg>
  <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
  <mch_id><![CDATA[10000100]]></mch_id>
  <nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
  <sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
  <result_code><![CDATA[SUCCESS]]></result_code>
  <prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
  <trade_type><![CDATA[JSAPI]]></trade_type>
</xml>

return_code 和result_code都为SUCCESS的时候会返回我们需要的prepay_id。。。,然后在jsapi中使用他就可以了。。

 最后测试一下。

Android捆绑银联支付接口

导入银联支付的依赖包:

2.在res目录下增加资源包:

3.配置AndroidManifest.xml文件配置打开的activity:

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <activity  
  2.             android:name="com.unionpay.uppay.PayActivity"  
  3.             android:configChanges="orientation|keyboardHidden"  
  4.             android:excludeFromRecents="true"  
  5.             android:label="@string/app_name"  
  6.             android:screenOrientation="portrait"  
  7.             android:windowSoftInputMode="adjustResize" />  

至此,我们的项目环境就搭好了.(以上资料文件,请查看银联测试文档目录的androiddemo);


银联支付代码3步骤:

1.获取TN号  2.请求控件界面(PayActivity)   

3.ActivityResult处理支付结果(但该结果并不一定正确 ,因为银联系统通过异步返回给服务器和我们的app是同时异步的)

以下 我以测试接口为例

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  *      UnionPay Test 
  3.  * 
  4.  *  @author Lean  @date:2014-8-8   
  5.  */  
  6. public class MainActivity extends Activity implements Runnable {  
  7.   
  8.     private String mMode = "01";//设置测试模式:01为测试 00为正式环境  
  9.     private static final String TN_URL_01 = "http://202.101.25.178:8080/sim/gettn";//自己后台需要实现的给予我们app的tn号接口  
  10.   
  11.     private Handler mHandler=new Handler(){  
  12.           
  13.         public void handleMessage(android.os.Message msg) {  
  14.   
  15.             String tn = "";  
  16.             if (msg.obj == null || ((String) msg.obj).length() == 0) {  
  17.                 AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);  
  18.                 builder.setTitle("错误提示");  
  19.                 builder.setMessage("网络连接失败,请重试!");  
  20.                 builder.setNegativeButton("确定",  
  21.                         new DialogInterface.OnClickListener() {  
  22.                             @Override  
  23.                             public void onClick(DialogInterface dialog, int which) {  
  24.                                 dialog.dismiss();  
  25.                             }  
  26.                         });  
  27.                 builder.create().show();  
  28.             } else {  
  29.                 tn = (String) msg.obj;  
  30.                 doStartUnionPayPlugin(MainActivity.this, tn, mMode);  
  31.             }  
  32.         }  
  33.     };  
  34.       
  35.     /** 
  36.      *  启动支付界面 
  37.      */  
  38.     public void doStartUnionPayPlugin(Activity activity, String tn, String mode) {  
  39.         UPPayAssistEx.startPayByJAR(activity, PayActivity.classnullnull,  
  40.                 tn, mode);  
  41.     }  
  42.       
  43.       
  44.     @Override  
  45.     protected void onCreate(Bundle savedInstanceState) {  
  46.         super.onCreate(savedInstanceState);  
  47.         setContentView(R.layout.activity_main);  
  48.   
  49.         new Thread(MainActivity.this).start();  
  50.   
  51.     }  
  52.   
  53.       
  54.     @Override  
  55.     public void run() {  
  56.         String tn = null;  
  57.         InputStream is;  
  58.         try {  
  59.   
  60.             String url = TN_URL_01;  
  61.   
  62.             URL myURL = new URL(url);  
  63.             URLConnection ucon = myURL.openConnection();  
  64.             ucon.setConnectTimeout(120000);  
  65.             is = ucon.getInputStream();  
  66.             int i = -1;  
  67.             ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  68.             while ((i = is.read()) != -1) {  
  69.                 baos.write(i);  
  70.             }  
  71.   
  72.             tn = baos.toString();  
  73.             is.close();  
  74.             baos.close();  
  75.         } catch (Exception e) {  
  76.             e.printStackTrace();  
  77.         }  
  78.           
  79.         Message msg = mHandler.obtainMessage();  
  80.         msg.obj = tn;  
  81.         mHandler.sendMessage(msg);  
  82.     }  
  83.   
  84.     @Override  
  85.     protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
  86.         if (data == null) {  
  87.             return;  
  88.         }  
  89.         String msg = "";  
  90.         /* 
  91.          * 支付控件返回字符串:success、fail、cancel 分别代表支付成功,支付失败,支付取消 
  92.          */  
  93.         String str = data.getExtras().getString("pay_result");  
  94.         Log.v("zftphone""2 "+data.getExtras().getString("merchantOrderId"));  
  95.         if (str.equalsIgnoreCase("success")) {  
  96.             msg = "支付成功!";  
  97.               
  98.         } else if (str.equalsIgnoreCase("fail")) {  
  99.             msg = "支付失败!";  
  100.               
  101.         } else if (str.equalsIgnoreCase("cancel")) {  
  102.               
  103.             msg = "用户取消了支付";  
  104.         }  
  105.         //支付完成,处理自己的业务逻辑!  
  106.     }  
  107.   
  108. }  


 

 

 

 

Android工程与支付宝绑定实现支付功能

Android SDK下载如下:

创建工程及引用SDK源码文件

以下以eclipse为开发的IDE进行范例说明:
使用Eclipse ADT 17 以上版本开发者
请在工程目录下新建一个文件夹libs,将open-sdk.jar文件和mta_sdk_x.x.x.jar文件拷贝到这个文件下(mta包请自主选择,非必须,mta详细说明见sdk开发包mta文档),然后在Eclipse里面刷新工程即可完成SDK文件的引入。
使用Eclipse ADT 17 以下版本开发者
请参考下面的步骤引入SDK文件:
(1)创建一个工程,并把open-sdk.jar文件和mta_sdk_x.x.x.jar文件拷贝到libs(或lib)目录下,如下图所示:
android_sdk_1.png
(2)将open-sdk.jar加入编译路径中。
选中open-sdk.jar,右键菜单中选择Build Path, 选择Add to Build Path,如下图所示:
android_sdk_2.png
(3)将mta_sdk_x.x.x.jar加入编译路径中。
按照上面的方法,将mta_sdk_x.x.x.jar加入编译路径中。
在工程的Referenced Libraries目录下看到导入的jar包,说明已经成功将jar包加入build path,如下图所示:
android_sdk_3.png

next,下载支付宝Android sdk,完整的sdk应该包含如下图示:

24122729_O941.jpg

其中使用openssl生成RSA公钥,和RSA私钥。

2.客户端里面

24122729_iwQg.jpg

Alipay_lib工具包,将它导入到eclipse里面,里面内容可以不用了解,只需在工程上引用就好。

Alipay_sdk_demo,是一个Android支付宝支付demo,当我们导入运行后,会报“参数错误”。

Android_SDK,里面是支付宝jar包。

3.查看alipay_sdk_demo src,包含如下java文件:

24122729_w2eI.jpg

其中Base64.java、Result.java、Rsa.java这三个java文件,我们不需要改写。

Key.java文件内容如下:

package com.alipay.Android.msp.demo;

//
// 请参考 Android平台安全支付服务(msp)应用开发接口(4.2 RSA算法签名)部分,并使用压缩包中的openssl RSA密钥生成工具,生成一套RSA公私钥。
// 这里签名时,只需要使用生成的RSA私钥。
// Note: 为安全起见,使用RSA私钥进行签名的操作过程,应该尽量放到商家服务器端去进行。
public final class Keys {

    // 合作身份者id,以2088开头的16位纯数字,商户账号申请成功后就会有PID和key
    public static final String DEFAULT_PARTNER = "";

    // 收款支付宝账号
    public static final String DEFAULT_SELLER = "";

// 商户私钥,自助生成,私钥通过openssl生成,详细可以查看移动支付接口智能SDK版接入与使用规则.pdf文档。
    public static final String PRIVATE = "";
// 商户公钥,自助生成,这个公钥使用demo上的便可。
    public static final String PUBLIC = "";

}

ExternalPartner.java文件,仔细看下来发现也就是使用了listview加载了很多商品,实现点击调用支付宝支付,具体需要熟悉如下代码:

24122729_QiaT.jpg

24122729_h1Ey.jpg

4.实现过程以及出现问题:

a)导入alipay_lib工具包;

b)在项目中,将alipay_sdk_demo src里面Base64.java、Result.java、Rsa.java,keys.java拷贝;

c)将res,lib里面内容拷贝,以及配置AndroidManifest.xml;

d)在activity里面简单写一个按钮点击触发支付宝支付接口,点击出现参数错误,可能原因,是配置公钥、私钥,或者合作ID写的不正确;

e)当一切配置正确后,点击发现报“商户没有开通快捷支付,请使用其他方式”,因为这个原因,花费了不少时间开通审核(这个在支付宝申请成功后,就应该立刻开通);

f)当审核通过,OK。

当然还有c#,Delphi,PHP如何调用支付宝接口,

代码略。

未完再续。

 

转载于:https://my.oschina.net/bigfool007139/blog/646614

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值