由于第一次接微信SDK。沿路踩过一个又一个大大小小的坑,以此做一下记录。
对于安卓版来说。前期一些基本jar导入。xml配置什么的都基本不会有什么问题,按照微信文档来就可以了。
第一个坑在出在签名上,第三方应用要拉起微信必须保证2点:
1.应用中的包名(Mainfext.xml中的package)必须与后台配置的一致。
2.应用生成不能是debug包,必须是正式的签名包。这个签名必须与后台配置的一致。
在第一点上,会出错的概率还是比较小的。
主要出错会在第2点上,微信官方有微信签名检测工具。用检测工具检测到的签名是一串小写并且中间没有冒号的字符串。
而在后台配置的却是直接从在eclipse打签名包时直接复制出来的MD5签名。(大写,并且中间夹杂:)
所以后台配置的签名必须与打包时的签名一致。必须是小写无冒号的字符串。
第二个坑出现在接登录的时候,在拉起微信授权登录之后无法自动返回第三方应用。
问题出在判断微信是否安装上。用了api.openWXApp(),导致打开微信后无法返回,修改为 api.isWXAppInstalled()就完美解决问题了。
- public static void sendMsgtoWX()
- {
- System.out.println("hwt c-----------------sendMsgtoWX");
- if(api.isWXAppInstalled())
- {
- // send oauth request
- SendAuth.Req req = new SendAuth.Req();
- req.scope = "snsapi_userinfo";
- req.state = "login_state";
- api.sendReq(req);
- }
- else
- {
- ShowMsg(1);
- }
第三个坑出现在分享图片的时候。微信对于图片分享中,对图片的大小做了限定。图片分享中主要是两部分,一个分享出去就直接能看到的一张比较小的图。还有一张就是点击之后出现的图片。两张图片的具体大小没有做测试。但是知道第一个图片必须比较小。太大就会出现无法拉起分享的情况。第二张图片比较大。基本1M左右应该都没什么问题。
- //分享图片到微信
- public void shareImgToWeixin(String path,int type)//type = 1 好友。type = 2 朋友圈
- {
- System.out.println("----------shareToWeixin--path:"+path);
- File file = new File(path);
- if (!file.exists()) {
- ShowMsg(2);
- return;
- }
- if(api.isWXAppInstalled())
- {
- if(type == 1)
- {
- Bitmap bmp = BitmapFactory.decodeFile(path);
- WXImageObject imgObj = new WXImageObject(bmp);
- imgObj.setImagePath(path+"screenshot.png");
- int num1 =bmp.getByteCount();
- int w =bmp.getWidth();
- int h =bmp.getHeight();
- float scal = 100/(float)w;
- w = (int)(w*scal);
- h = (int)(h*scal);
- System.out.println("----------thumbBmp w:"+w+"h:"+h);
- Bitmap thumbBmp = Bitmap.createScaledBitmap(bmp, w,h, true);
- int num =thumbBmp.getByteCount();
- System.out.println("----------thumbBmp num1:"+num1+"------num:"+num);
- bmp.recycle();
- WXMediaMessage msg = new WXMediaMessage();
- msg.mediaObject = imgObj;
- msg.thumbData = Util.bmpToByteArray(thumbBmp, true);
- SendMessageToWX.Req req = new SendMessageToWX.Req();
- req.scene = (type == 1)?SendMessageToWX.Req.WXSceneSession:SendMessageToWX.Req.WXSceneTimeline;
- req.transaction = buildTransaction("img");
- req.message = msg;
- api.sendReq(req);
- }
- }
- }
在微信支付中遇到的问题还是挺多的,因为微信的流程中数据的接收和发送都是xml格式的。由于之前没有对xml格式做过处理,走了不少弯路。
其实流程很简单,就是将数据拼成xml格式post发过去,再解析xml格式的数据获得参数。微信第一部分统一下单,由于各种原因我们放在了客户端中处理。服务端只是生成了一个商户订单号。
由于我们的项目ios和安卓是同一套代码。所以我们将第一部分统一下单放在了cocos中实现。
其中需要注意的几点是:在生成签名的时候,必须把需要发送过去的参数,除了sign本身之外都需要打进去,少一个都不行。签名就按照微信官方文档来就可以了。
需要签名的参数大写与小写所生成的签名是不一样的。所以,我把需要签名的参数都是小写,再在最后转化为大写。还有签名中的key并非AppID或AppSectet,而是在商户平台设置的,官方描述为“key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置”。
- void WXMessage::SendFirstDate(std::string out_trade_no,std::string price,std::string body)
- {
- //网络异步连接方法
- HttpRequest* request = new HttpRequest();
- request->setUrl("https://api.mch.weixin.qq.com/pay/unifiedorder");
- request->setRequestType(HttpRequest::Type::POST);
- request->setResponseCallback(this, httpresponse_selector(WXMessage::onHttpRequestCompleted));
- std::string postData = "";
- postData += "<xml>";
- postData += "\n";
- postData += "<appid><![CDATA["+(std::string)wx_appid+"]]></appid>";
- postData += "\n";
- postData += "<mch_id><![CDATA["+(std::string)wx_mchid+"]]></mch_id>";
- postData += "\n";
- postData += "<nonce_str><![CDATA["+rand_str()+"]]></nonce_str>";
- postData += "\n";
- postData += "<sign><![CDATA["+Getsign(out_trade_no,price,body)+"]]></sign>";
- postData += "\n";
- postData += "<body><![CDATA["+body+"]]></body>";
- postData += "\n";
- postData += "<out_trade_no><![CDATA["+out_trade_no+"]]></out_trade_no>";
- postData += "\n";
- postData += "<total_fee>"+price+"</total_fee>";
- postData += "\n";
- postData += "<spbill_create_ip><![CDATA["+GetIP()+"]]></spbill_create_ip>";
- postData += "\n";
- postData += "<notify_url><![CDATA["+(std::string)wx_notify_url+"]]></notify_url>";
- postData += "\n";
- postData += "<trade_type><![CDATA["+(std::string)wx_trade_type+"]]></trade_type>";
- postData += "\n";
- postData += "</xml>; <pre name="code" class="cpp">
HttpClient::getInstance()->send(request);
request->release();
}
- void WXMessage::onHttpRequestCompleted(HttpClient *sender, HttpResponse *response)
- {
- if (!response) {
- return;
- }
- if (0 != strlen(response->getHttpRequest()->getTag())) {
- log("%s completed",response->getHttpRequest()->getTag());
- }
- long statusCode = response->getResponseCode();
- char statusString[64] = {};
- sprintf(statusString, "HTTP Status Code: %ld, tag = %s",statusCode,response->getHttpRequest()->getTag());
- log("response code: %ld",statusCode);
- if (!response->isSucceed()) {
- log("response failed");
- log("error buffer: %s",response->getErrorBuffer());
- return;
- }
- if(statusCode == 200)
- {
- std::vector<char>* buffer = response->getResponseData();
- std::string str = &(*buffer)[0];
- int a = (int)str.find("<return_code><![CDATA[");
- int e = (int)str.find("]]></return_code>");
- std::string code = &(*buffer)[a];
- code = code.substr(22,e-a-22);
- if(code.compare("SUCCESS") == 0)
- {
- int start =(int)str.find("<prepay_id><![CDATA[");
- int end =(int)str.find("]]></prepay_id>");
- std::string prepay_id =&(*buffer)[start];
- prepay_id = prepay_id.substr(20,end-start-20);
- CCLOG("prepay_id:%s",prepay_id.c_str());
- SocialUtils::WXPay(prepay_id,nonce_str);
- }else{
- //printf("Http Test, dump data: ");
- for (unsigned int i = 0 ; i < buffer->size();i++) {
- printf("%c",(*buffer)[i]);
- }
- printf("\n");
- }
- }
- }
- //随机值
- std::string WXMessage::rand_str()
- {
- char str[33] = "";
- int i;
- srand((unsigned int)time(0));
- for(i=0;i<32;++i)
- {
- if(rand()%2)
- {
- str[i]='0'+rand()%10;
- }else
- {
- str[i]='a'+rand()%26;
- }
- }
- str[++i]='\0';
- std::string nond = str;
- return nond;
- }
- //签名
- std::string WXMessage::Getsign(std::string out_trade_no,std::string price,std::string body)
- {
- char str[1024] = "";
- std::string sign = "";
- std::string str1= "";
- str1 +="appid="+(std::string)wx_appid;
- str1 +="&body="+body;
- str1 +="&mch_id="+(std::string)wx_mchid;
- str1 +="&nonce_str="+(std::string)nonce_str;
- str1 +="¬ify_url="+(std::string)wx_notify_url;
- str1 +="&out_trade_no="+out_trade_no;
- str1 +="&spbill_create_ip="+GetIP();
- str1 +="&total_fee="+price;
- str1 +="&trade_type="+(std::string)wx_trade_type;
- str1 +="&key="+(std::string)wx_key;
- sprintf(str, "%s",str1.c_str());
- char md5p[33];
- md5_passwd(str, md5p);
- for(int i=0;i<strlen(md5p);i++)
- {
- if(islower(md5p[i]))
- {
- md5p[i] = toupper(md5p[i]);
- }
- }
- sign = md5p;
- m_sign = sign;
- return sign;
- }
安卓:
- public void ToWX_Pay(String m_prepayid,String m_nonce_str)
- {
- // nonce_str = m_nonce_str;
- // prepayid = m_prepayid;
- timeStamp = Long.toString(System.currentTimeMillis()/ 1000);
- if(api.isWXAppInstalled())
- {
- PayReq req = new PayReq();
- req.appId = AppConfig.WX_APPID;
- req.partnerId = AppConfig.mch_id;
- req.prepayId = m_prepayid;
- req.nonceStr = m_nonce_str;
- req.timeStamp = timeStamp;
- req.packageValue = "Sign=WXPay";
- req.sign = WX_sign(m_prepayid,m_nonce_str);
- // req.extData = "";
- System.out.println("-----------------WX_pay-- \n appId:"+req.appId+"\n"+"--partnerId:"+req.partnerId+"\n"+"--prepayId:"+req.prepayId+"\n"+
- "--nonceStr:"+ req.nonceStr+"\n"+"--timeStamp:"+req.timeStamp+"\n"+"--sign:"+req.sign);
- api.sendReq(req);
- }else
- {
- ShowMsg(1);
- }
- }
- /**
- * 微信支付签名算法sign
- * @param m_prepayid
- * @param m_nonce_str
- * @return
- */
- public String WX_sign(String m_prepayid,String m_nonce_str)
- {
- //微信api提供的参数
- SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
- parameters.put("appid", AppConfig.WX_APPID);
- parameters.put("partnerid", AppConfig.mch_id);
- parameters.put("prepayid", m_prepayid);
- parameters.put("package", "Sign=WXPay");
- parameters.put("noncestr", m_nonce_str);
- parameters.put("timestamp", timeStamp);
- StringBuffer sb = new StringBuffer();
- Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)
- Iterator it = es.iterator();
- while(it.hasNext()) {
- Map.Entry entry = (Map.Entry)it.next();
- String k = (String)entry.getKey();
- Object v = entry.getValue();
- if(null != v && !"".equals(v)
- && !"sign".equals(k) && !"key".equals(k)) {
- sb.append(k + "=" + v + "&");
- }
- }
- sb.append("key=" + AppConfig.Key);
- <span style="white-space:pre"> </span>String sign = Tools.MD5Encode(sb.toString(), "UTF-8").toUpperCase();
- <span style="white-space:pre"> </span>return sign;
- }
IOS:
- NSString* _time_stamp;
- +(void)ToWX_Pay:(NSString*)payid toNoncestr:(NSString*)nonce_str
- {
- NSLog(@"微信支付--------------》》");
- if([WXApi isWXAppInstalled])
- {
- time_t now;
- time(&now);
- _time_stamp = [NSString stringWithFormat:@"%ld", now];
- NSMutableString *stamp = (NSMutableString*)_time_stamp;
- //调起微信支付
- PayReq* req = [[PayReq alloc] init];
- req.openID = [NSString stringWithUTF8String:wx_appid];
- req.partnerId = [NSString stringWithUTF8String:wx_mchid];
- req.prepayId = payid;//
- req.nonceStr = nonce_str;
- req.timeStamp = stamp.intValue;
- req.package = @"Sign=WXPay";
- req.sign = [self GetSign:payid toNoncestr:nonce_str];
- [WXApi sendReq:req];
- //日志输出
- NSLog(@"appid=%@\npartid=%@\nprepayid=%@\nnoncestr=%@\ntimestamp=%ld\npackage=%@\nsign=%@",req.openID,req.partnerId,req.prepayId,req.nonceStr,(long)req.timeStamp,req.package,req.sign );
- }else
- {
- [AppWXController ShowMsg];
- }
- }
- +(NSString*)GetSign:(NSString*)payid toNoncestr:(NSString*)m_nonce_str
- {
- NSString *appid,*prePayid,*mchid,*package, *time_stamp, *nonce_str;
- appid = [NSString stringWithUTF8String:wx_appid];
- mchid = [NSString stringWithUTF8String:wx_mchid];
- nonce_str = m_nonce_str;
- package = @"Sign=WXPay";
- time_stamp = _time_stamp;
- prePayid = payid;
- NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
- [signParams setObject: appid forKey:@"appid"];
- [signParams setObject: nonce_str forKey:@"noncestr"];
- [signParams setObject: package forKey:@"package"];
- [signParams setObject: mchid forKey:@"partnerid"];
- [signParams setObject: time_stamp forKey:@"timestamp"];
- [signParams setObject: prePayid forKey:@"prepayid"];
- //[signParams setObject: @"MD5" forKey:@"signType"];
- //生成签名
- NSString *sign = [self createMd5Sign:signParams];
- return sign;
- }
- //创建package签名
- +(NSString*) createMd5Sign:(NSMutableDictionary*)dict
- {
- NSMutableString *contentString =[NSMutableString string];
- NSArray *keys = [dict allKeys];
- //按字母顺序排序
- NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
- return [obj1 compare:obj2 options:NSNumericSearch];
- }];
- //拼接字符串
- for (NSString *categoryId in sortedArray) {
- if ( ![[dict objectForKey:categoryId] isEqualToString:@""]
- && ![categoryId isEqualToString:@"sign"]
- && ![categoryId isEqualToString:@"key"]
- )
- {
- [contentString appendFormat:@"%@=%@&", categoryId, [dict objectForKey:categoryId]];
- }
- }
- //添加key字段
- [contentString appendFormat:@"key=%@", [NSString stringWithUTF8String:wx_key]];//
- //得到MD5 sign签名
- NSString *md5Sign =[WXUtil md5:contentString];
- return md5Sign;
- }
就此,微信拉起支付流程基本完成了。
如果拉起微信支付,errCode返回-1,有人说清除微信缓存或切换账户就好了,这种解决方案治标不治本啊,根本不能算解决方案。虽然我没遇到能用这方法解决的问题,但目测是签名的问题,建议还得找到真正的问题所在。
以此记录踩过的一些坑,希望各位能顺利接完微信SDK!
由于第一次接微信SDK。沿路踩过一个又一个大大小小的坑,以此做一下记录。
对于安卓版来说。前期一些基本jar导入。xml配置什么的都基本不会有什么问题,按照微信文档来就可以了。
第一个坑在出在签名上,第三方应用要拉起微信必须保证2点:
1.应用中的包名(Mainfext.xml中的package)必须与后台配置的一致。
2.应用生成不能是debug包,必须是正式的签名包。这个签名必须与后台配置的一致。
在第一点上,会出错的概率还是比较小的。
主要出错会在第2点上,微信官方有微信签名检测工具。用检测工具检测到的签名是一串小写并且中间没有冒号的字符串。
而在后台配置的却是直接从在eclipse打签名包时直接复制出来的MD5签名。(大写,并且中间夹杂:)
所以后台配置的签名必须与打包时的签名一致。必须是小写无冒号的字符串。
第二个坑出现在接登录的时候,在拉起微信授权登录之后无法自动返回第三方应用。
问题出在判断微信是否安装上。用了api.openWXApp(),导致打开微信后无法返回,修改为 api.isWXAppInstalled()就完美解决问题了。
- public static void sendMsgtoWX()
- {
- System.out.println("hwt c-----------------sendMsgtoWX");
- if(api.isWXAppInstalled())
- {
- // send oauth request
- SendAuth.Req req = new SendAuth.Req();
- req.scope = "snsapi_userinfo";
- req.state = "login_state";
- api.sendReq(req);
- }
- else
- {
- ShowMsg(1);
- }
第三个坑出现在分享图片的时候。微信对于图片分享中,对图片的大小做了限定。图片分享中主要是两部分,一个分享出去就直接能看到的一张比较小的图。还有一张就是点击之后出现的图片。两张图片的具体大小没有做测试。但是知道第一个图片必须比较小。太大就会出现无法拉起分享的情况。第二张图片比较大。基本1M左右应该都没什么问题。
- //分享图片到微信
- public void shareImgToWeixin(String path,int type)//type = 1 好友。type = 2 朋友圈
- {
- System.out.println("----------shareToWeixin--path:"+path);
- File file = new File(path);
- if (!file.exists()) {
- ShowMsg(2);
- return;
- }
- if(api.isWXAppInstalled())
- {
- if(type == 1)
- {
- Bitmap bmp = BitmapFactory.decodeFile(path);
- WXImageObject imgObj = new WXImageObject(bmp);
- imgObj.setImagePath(path+"screenshot.png");
- int num1 =bmp.getByteCount();
- int w =bmp.getWidth();
- int h =bmp.getHeight();
- float scal = 100/(float)w;
- w = (int)(w*scal);
- h = (int)(h*scal);
- System.out.println("----------thumbBmp w:"+w+"h:"+h);
- Bitmap thumbBmp = Bitmap.createScaledBitmap(bmp, w,h, true);
- int num =thumbBmp.getByteCount();
- System.out.println("----------thumbBmp num1:"+num1+"------num:"+num);
- bmp.recycle();
- WXMediaMessage msg = new WXMediaMessage();
- msg.mediaObject = imgObj;
- msg.thumbData = Util.bmpToByteArray(thumbBmp, true);
- SendMessageToWX.Req req = new SendMessageToWX.Req();
- req.scene = (type == 1)?SendMessageToWX.Req.WXSceneSession:SendMessageToWX.Req.WXSceneTimeline;
- req.transaction = buildTransaction("img");
- req.message = msg;
- api.sendReq(req);
- }
- }
- }
在微信支付中遇到的问题还是挺多的,因为微信的流程中数据的接收和发送都是xml格式的。由于之前没有对xml格式做过处理,走了不少弯路。
其实流程很简单,就是将数据拼成xml格式post发过去,再解析xml格式的数据获得参数。微信第一部分统一下单,由于各种原因我们放在了客户端中处理。服务端只是生成了一个商户订单号。
由于我们的项目ios和安卓是同一套代码。所以我们将第一部分统一下单放在了cocos中实现。
其中需要注意的几点是:在生成签名的时候,必须把需要发送过去的参数,除了sign本身之外都需要打进去,少一个都不行。签名就按照微信官方文档来就可以了。
需要签名的参数大写与小写所生成的签名是不一样的。所以,我把需要签名的参数都是小写,再在最后转化为大写。还有签名中的key并非AppID或AppSectet,而是在商户平台设置的,官方描述为“key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置”。
- void WXMessage::SendFirstDate(std::string out_trade_no,std::string price,std::string body)
- {
- //网络异步连接方法
- HttpRequest* request = new HttpRequest();
- request->setUrl("https://api.mch.weixin.qq.com/pay/unifiedorder");
- request->setRequestType(HttpRequest::Type::POST);
- request->setResponseCallback(this, httpresponse_selector(WXMessage::onHttpRequestCompleted));
- std::string postData = "";
- postData += "<xml>";
- postData += "\n";
- postData += "<appid><![CDATA["+(std::string)wx_appid+"]]></appid>";
- postData += "\n";
- postData += "<mch_id><![CDATA["+(std::string)wx_mchid+"]]></mch_id>";
- postData += "\n";
- postData += "<nonce_str><![CDATA["+rand_str()+"]]></nonce_str>";
- postData += "\n";
- postData += "<sign><![CDATA["+Getsign(out_trade_no,price,body)+"]]></sign>";
- postData += "\n";
- postData += "<body><![CDATA["+body+"]]></body>";
- postData += "\n";
- postData += "<out_trade_no><![CDATA["+out_trade_no+"]]></out_trade_no>";
- postData += "\n";
- postData += "<total_fee>"+price+"</total_fee>";
- postData += "\n";
- postData += "<spbill_create_ip><![CDATA["+GetIP()+"]]></spbill_create_ip>";
- postData += "\n";
- postData += "<notify_url><![CDATA["+(std::string)wx_notify_url+"]]></notify_url>";
- postData += "\n";
- postData += "<trade_type><![CDATA["+(std::string)wx_trade_type+"]]></trade_type>";
- postData += "\n";
- postData += "</xml>; <pre name="code" class="cpp">
HttpClient::getInstance()->send(request);
request->release();
}
- void WXMessage::onHttpRequestCompleted(HttpClient *sender, HttpResponse *response)
- {
- if (!response) {
- return;
- }
- if (0 != strlen(response->getHttpRequest()->getTag())) {
- log("%s completed",response->getHttpRequest()->getTag());
- }
- long statusCode = response->getResponseCode();
- char statusString[64] = {};
- sprintf(statusString, "HTTP Status Code: %ld, tag = %s",statusCode,response->getHttpRequest()->getTag());
- log("response code: %ld",statusCode);
- if (!response->isSucceed()) {
- log("response failed");
- log("error buffer: %s",response->getErrorBuffer());
- return;
- }
- if(statusCode == 200)
- {
- std::vector<char>* buffer = response->getResponseData();
- std::string str = &(*buffer)[0];
- int a = (int)str.find("<return_code><![CDATA[");
- int e = (int)str.find("]]></return_code>");
- std::string code = &(*buffer)[a];
- code = code.substr(22,e-a-22);
- if(code.compare("SUCCESS") == 0)
- {
- int start =(int)str.find("<prepay_id><![CDATA[");
- int end =(int)str.find("]]></prepay_id>");
- std::string prepay_id =&(*buffer)[start];
- prepay_id = prepay_id.substr(20,end-start-20);
- CCLOG("prepay_id:%s",prepay_id.c_str());
- SocialUtils::WXPay(prepay_id,nonce_str);
- }else{
- //printf("Http Test, dump data: ");
- for (unsigned int i = 0 ; i < buffer->size();i++) {
- printf("%c",(*buffer)[i]);
- }
- printf("\n");
- }
- }
- }
- //随机值
- std::string WXMessage::rand_str()
- {
- char str[33] = "";
- int i;
- srand((unsigned int)time(0));
- for(i=0;i<32;++i)
- {
- if(rand()%2)
- {
- str[i]='0'+rand()%10;
- }else
- {
- str[i]='a'+rand()%26;
- }
- }
- str[++i]='\0';
- std::string nond = str;
- return nond;
- }
- //签名
- std::string WXMessage::Getsign(std::string out_trade_no,std::string price,std::string body)
- {
- char str[1024] = "";
- std::string sign = "";
- std::string str1= "";
- str1 +="appid="+(std::string)wx_appid;
- str1 +="&body="+body;
- str1 +="&mch_id="+(std::string)wx_mchid;
- str1 +="&nonce_str="+(std::string)nonce_str;
- str1 +="¬ify_url="+(std::string)wx_notify_url;
- str1 +="&out_trade_no="+out_trade_no;
- str1 +="&spbill_create_ip="+GetIP();
- str1 +="&total_fee="+price;
- str1 +="&trade_type="+(std::string)wx_trade_type;
- str1 +="&key="+(std::string)wx_key;
- sprintf(str, "%s",str1.c_str());
- char md5p[33];
- md5_passwd(str, md5p);
- for(int i=0;i<strlen(md5p);i++)
- {
- if(islower(md5p[i]))
- {
- md5p[i] = toupper(md5p[i]);
- }
- }
- sign = md5p;
- m_sign = sign;
- return sign;
- }
安卓:
- public void ToWX_Pay(String m_prepayid,String m_nonce_str)
- {
- // nonce_str = m_nonce_str;
- // prepayid = m_prepayid;
- timeStamp = Long.toString(System.currentTimeMillis()/ 1000);
- if(api.isWXAppInstalled())
- {
- PayReq req = new PayReq();
- req.appId = AppConfig.WX_APPID;
- req.partnerId = AppConfig.mch_id;
- req.prepayId = m_prepayid;
- req.nonceStr = m_nonce_str;
- req.timeStamp = timeStamp;
- req.packageValue = "Sign=WXPay";
- req.sign = WX_sign(m_prepayid,m_nonce_str);
- // req.extData = "";
- System.out.println("-----------------WX_pay-- \n appId:"+req.appId+"\n"+"--partnerId:"+req.partnerId+"\n"+"--prepayId:"+req.prepayId+"\n"+
- "--nonceStr:"+ req.nonceStr+"\n"+"--timeStamp:"+req.timeStamp+"\n"+"--sign:"+req.sign);
- api.sendReq(req);
- }else
- {
- ShowMsg(1);
- }
- }
- /**
- * 微信支付签名算法sign
- * @param m_prepayid
- * @param m_nonce_str
- * @return
- */
- public String WX_sign(String m_prepayid,String m_nonce_str)
- {
- //微信api提供的参数
- SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
- parameters.put("appid", AppConfig.WX_APPID);
- parameters.put("partnerid", AppConfig.mch_id);
- parameters.put("prepayid", m_prepayid);
- parameters.put("package", "Sign=WXPay");
- parameters.put("noncestr", m_nonce_str);
- parameters.put("timestamp", timeStamp);
- StringBuffer sb = new StringBuffer();
- Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)
- Iterator it = es.iterator();
- while(it.hasNext()) {
- Map.Entry entry = (Map.Entry)it.next();
- String k = (String)entry.getKey();
- Object v = entry.getValue();
- if(null != v && !"".equals(v)
- && !"sign".equals(k) && !"key".equals(k)) {
- sb.append(k + "=" + v + "&");
- }
- }
- sb.append("key=" + AppConfig.Key);
- <span style="white-space:pre"> </span>String sign = Tools.MD5Encode(sb.toString(), "UTF-8").toUpperCase();
- <span style="white-space:pre"> </span>return sign;
- }
IOS:
- NSString* _time_stamp;
- +(void)ToWX_Pay:(NSString*)payid toNoncestr:(NSString*)nonce_str
- {
- NSLog(@"微信支付--------------》》");
- if([WXApi isWXAppInstalled])
- {
- time_t now;
- time(&now);
- _time_stamp = [NSString stringWithFormat:@"%ld", now];
- NSMutableString *stamp = (NSMutableString*)_time_stamp;
- //调起微信支付
- PayReq* req = [[PayReq alloc] init];
- req.openID = [NSString stringWithUTF8String:wx_appid];
- req.partnerId = [NSString stringWithUTF8String:wx_mchid];
- req.prepayId = payid;//
- req.nonceStr = nonce_str;
- req.timeStamp = stamp.intValue;
- req.package = @"Sign=WXPay";
- req.sign = [self GetSign:payid toNoncestr:nonce_str];
- [WXApi sendReq:req];
- //日志输出
- NSLog(@"appid=%@\npartid=%@\nprepayid=%@\nnoncestr=%@\ntimestamp=%ld\npackage=%@\nsign=%@",req.openID,req.partnerId,req.prepayId,req.nonceStr,(long)req.timeStamp,req.package,req.sign );
- }else
- {
- [AppWXController ShowMsg];
- }
- }
- +(NSString*)GetSign:(NSString*)payid toNoncestr:(NSString*)m_nonce_str
- {
- NSString *appid,*prePayid,*mchid,*package, *time_stamp, *nonce_str;
- appid = [NSString stringWithUTF8String:wx_appid];
- mchid = [NSString stringWithUTF8String:wx_mchid];
- nonce_str = m_nonce_str;
- package = @"Sign=WXPay";
- time_stamp = _time_stamp;
- prePayid = payid;
- NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
- [signParams setObject: appid forKey:@"appid"];
- [signParams setObject: nonce_str forKey:@"noncestr"];
- [signParams setObject: package forKey:@"package"];
- [signParams setObject: mchid forKey:@"partnerid"];
- [signParams setObject: time_stamp forKey:@"timestamp"];
- [signParams setObject: prePayid forKey:@"prepayid"];
- //[signParams setObject: @"MD5" forKey:@"signType"];
- //生成签名
- NSString *sign = [self createMd5Sign:signParams];
- return sign;
- }
- //创建package签名
- +(NSString*) createMd5Sign:(NSMutableDictionary*)dict
- {
- NSMutableString *contentString =[NSMutableString string];
- NSArray *keys = [dict allKeys];
- //按字母顺序排序
- NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
- return [obj1 compare:obj2 options:NSNumericSearch];
- }];
- //拼接字符串
- for (NSString *categoryId in sortedArray) {
- if ( ![[dict objectForKey:categoryId] isEqualToString:@""]
- && ![categoryId isEqualToString:@"sign"]
- && ![categoryId isEqualToString:@"key"]
- )
- {
- [contentString appendFormat:@"%@=%@&", categoryId, [dict objectForKey:categoryId]];
- }
- }
- //添加key字段
- [contentString appendFormat:@"key=%@", [NSString stringWithUTF8String:wx_key]];//
- //得到MD5 sign签名
- NSString *md5Sign =[WXUtil md5:contentString];
- return md5Sign;
- }
就此,微信拉起支付流程基本完成了。
如果拉起微信支付,errCode返回-1,有人说清除微信缓存或切换账户就好了,这种解决方案治标不治本啊,根本不能算解决方案。虽然我没遇到能用这方法解决的问题,但目测是签名的问题,建议还得找到真正的问题所在。
以此记录踩过的一些坑,希望各位能顺利接完微信SDK!